收到用户提供的微信公众号文章链接(mp.weixin.qq.com)后,按以下步骤执行:
如果用户尚未配置过 IMA 和 Playwright,按以下顺序指导他完成设置。
IMA 是腾讯出品的 AI 知识库工具,本 skill 用它来存储和管理文章。
> 下载地址: https://ima.qq.com/
>
> 支持 Windows / macOS,下载对应版本安装即可。
安装后登录你的微信/QQ 账号。
本 skill 依赖「腾讯 ima」skill 来调用 IMA API。在 WorkBuddy 中运行:
/skills
在技能市场搜索 IMA 或 腾讯ima,安装以下两个 skill:
腾讯ima:knowledge-base腾讯ima:notesIMA 知识库 API 需要 Client ID 和 API Key。获取方式:
mkdir -p ~/.config/ima
echo "你的ClientID" > ~/.config/ima/client_id
echo "你的APIKey" > ~/.config/ima/api_key
> 凭证只用于向 ima.qq.com 发请求,不会泄露到其他地方。
本 skill 用浏览器内核将 HTML 渲染为 PDF。只需在终端执行一次:
cd /tmp && npm install playwright && npx playwright install chromium
> 这条命令会下载约 90MB 的 Chromium 浏览器引擎,只需执行一次即可。
# 检查 Playwright 是否安装成功
test -f /tmp/node_modules/playwright/index.js && echo "✅ Playwright OK"
# 检查 Chromium
ls ~/Library/Caches/ms-playwright/chromium_headless_shell-*/chrome-headless-shell-* 2>/dev/null && echo "✅ Chromium OK"
# 检查 IMA 凭证
test -f ~/.config/ima/client_id && test -f ~/.config/ima/api_key && echo "✅ IMA 凭证 OK"
三行都显示 ✅ 即配置完成,可以开始使用了。
以下指令供执行工作流时使用。WorkBuddy 每次调用 Bash 时 shell 状态不会持久,因此所有路径变量需由 WorkBuddy 在上下文中追踪,或在每个 Bash 调用中重新计算。
先定位本 skill 和 IMA skill 的路径。WorkBuddy 将以下两个路径记在上下文中:
# ── 本 skill 目录 ──
SKILL_DIR="$HOME/.workbuddy/skills/wechat-article-pipeline"
if [ ! -f "$SKILL_DIR/SKILL.md" ]; then
# 兜底搜索
SKILL_DIR=$(find "$HOME/.workbuddy/skills" -maxdepth 2 -name "SKILL.md" -path "*wechat*article*" 2>/dev/null | head -1 | xargs dirname)
fi
echo "SKILL_DIR=$SKILL_DIR"
# ── IMA skill 目录(查找 ima_api.cjs) ──
IMA_SKILL_DIR=""
for d in "$HOME/.workbuddy/skills/"*ima* "$HOME/.workbuddy/skills/"*IM* "$HOME/.workbuddy/skills/"*腾讯* "$HOME/.workbuddy/skills/"*tencent*; do
if [ -f "$d/ima_api.cjs" ]; then
IMA_SKILL_DIR="$d"
break
fi
done
# 兜底:全局搜索 ima_api.cjs
if [ -z "$IMA_SKILL_DIR" ]; then
IMA_SKILL_DIR=$(find "$HOME/.workbuddy/skills" -maxdepth 3 -name "ima_api.cjs" -type f 2>/dev/null | head -1 | xargs dirname 2>/dev/null)
fi
if [ -z "$IMA_SKILL_DIR" ]; then
echo 'MISSING_IMA_SKILL'
exit 1
fi
echo "IMA_SKILL_DIR=$IMA_SKILL_DIR"
# ── IMA 凭证 ──
if [ ! -f "$HOME/.config/ima/client_id" ] || [ ! -f "$HOME/.config/ima/api_key" ]; then
echo 'MISSING_IMA_CREDENTIALS'
exit 1
fi
输出 MISSING_IMA_SKILL 时,提示用户安装 IMA skill(参见「新手上手指南」第2步)。
输出 MISSING_IMA_CREDENTIALS 时,提示用户配置凭证(参见「新手上手指南」第3步)。
正常输出后,WorkBuddy 记下 SKILL_DIR 和 IMA_SKILL_DIR 的值,后续步骤直接引用。
node -e "try{require('/tmp/node_modules/playwright');console.log('PW_OK')}catch(e){console.log('PW_MISSING')}"
输出 PW_MISSING 时提示用户安装(参见新手指南第4步)。
> ⚠️ 重要提示:WorkBuddy 每次调用 Bash 时 shell 状态不会持久。因此每个 Bash 调用中所需的变量(如 IMA_SKILL_DIR、OPTS 等)都需要在调用内重新计算或由 WorkBuddy 以实际值替换。
>
> 以下步骤中,、、、、、<文章URL> 等占位符由 WorkBuddy 在执行时代入实际值。
>
> OPTS 每次使用时都需要重新生成,格式固定为:
> ```bash
> OPTS=$(printf '{"clientId":"%s","apiKey":"%s"}' "$(cat ~/.config/ima/client_id)" "$(cat ~/.config/ima/api_key)")
> ```
调用 Skill("ima-skills") 加载 IMA 操作指令,获取 import_urls、get_media_info 等接口的调用方式。
OPTS=$(printf '{"clientId":"%s","apiKey":"%s"}' "$(cat ~/.config/ima/client_id)" "$(cat ~/.config/ima/api_key)")
node "<IMA_SKILL_DIR>/ima_api.cjs" "openapi/wiki/v1/search_knowledge_base" \
'{"query":"","cursor":"","limit":20}' "$OPTS"
从返回结果中选择一个知识库(如果用户没指定,选 content_count 最大的那个)。WorkBuddy 记下 kb_id。
OPTS=$(printf '{"clientId":"%s","apiKey":"%s"}' "$(cat ~/.config/ima/client_id)" "$(cat ~/.config/ima/api_key)")
node "<IMA_SKILL_DIR>/ima_api.cjs" "openapi/wiki/v1/import_urls" '{
"knowledge_base_id": "<kb_id>",
"urls": ["<文章URL>"]
}' "$OPTS"
记录返回的 media_id。
OPTS=$(printf '{"clientId":"%s","apiKey":"%s"}' "$(cat ~/.config/ima/client_id)" "$(cat ~/.config/ima/api_key)")
node "<IMA_SKILL_DIR>/ima_api.cjs" "openapi/wiki/v1/get_media_info" \
'{"media_id": "<media_id>"}' "$OPTS"
从 url_info.url 提取文章的最终访问地址。
用 WebFetch 工具请求文章 URL,prompt 写明以下要求:
> 请完整提取这篇文章的全部内容,包括:
> 1. 文章标题
> 2. 所有正文文字内容,保持完整段落
> 3. 所有图片的 URL(img 标签的 src 属性值)
> 4. 列表、表格、代码块等格式信息
>
> 不要遗漏任何段落,给我最完整的内容。
WORK_DIR=$(mktemp -d)
echo "WORK_DIR=$WORK_DIR"
WorkBuddy 记下 WORK_DIR。然后用 curl 逐一下载 WebFetch 返回的所有图片:
for url in "<图片URL1>" "<图片URL2>"; do
ext="jpeg"
[[ "$url" == *.png* ]] && ext="png"
[[ "$url" == *.jpg* ]] && ext="jpg"
[[ "$url" == *.gif* ]] && ext="gif"
curl -sL -o "<WORK_DIR>/img${count}.${ext}" "$url"
echo "img${count}.${ext}: $(wc -c < "<WORK_DIR>/img${count}.${ext}") bytes"
count=$((count + 1))
done
如果图片下载后文件大小为 0 或极小(< 1KB),尝试带 Referer 重试:
curl -sL -e "https://mp.weixin.qq.com/" -o "<WORK_DIR>/img${count}.${ext}" "<图片URL>"
WorkBuddy 执行以下检测,记下 CN_FONT_URL(URL 编码后的字体文件路径):
/System/Library/Fonts/STHeiti Light.ttc → file:///System/Library/Fonts/STHeiti%20Light.ttc/System/Library/Fonts/PingFang.ttc/mnt/c/Windows/Fonts/msyh.ttc/c/Windows/Fonts/msyh.ttc/usr/share/fonts/truetype/wqy/wqy-microhei.ttc 或 /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc@font-face,使用 sans-serif 降级WorkBuddy 根据文章内容和图片列表,生成一份完整的 HTML 文件。CSS 模板如下:
CN_FONT_RULE
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'CJKFont', 'PingFang SC', 'Microsoft YaHei', 'Noto Sans CJK SC', sans-serif;
font-size: 12pt; line-height: 1.8; color: #333; padding: 40px 50px;
}
h1 { text-align: center; font-size: 22pt; color: #1a1a2e; margin-bottom: 6pt; }
h2 { font-size: 16pt; color: #16213e; margin-top: 24pt; margin-bottom: 12pt; border-left: 4px solid #0f3460; padding-left: 10pt; }
p { margin-bottom: 8pt; }
.bold { font-weight: bold; }
.note { background: #f0f4f8; padding: 10pt 14pt; margin: 10pt 0; border-radius: 4pt; font-size: 11pt; }
.bullet { padding-left: 20pt; margin-bottom: 4pt; }
img { display: block; max-width: 90%; margin: 12pt auto; border: 1px solid #ddd; border-radius: 4pt; }
.caption { text-align: center; font-size: 9pt; color: #888; margin-bottom: 16pt; }
table { width: 80%; margin: 10pt auto; border-collapse: collapse; font-size: 10pt; }
th { background: #0f3460; color: white; padding: 6pt 10pt; border: 1px solid #0f3460; }
td { padding: 5pt 10pt; border: 1px solid #ccc; text-align: center; }
.divider { text-align: center; color: #ccc; margin: 20pt 0 12pt; }
.center { text-align: center; font-weight: bold; font-size: 12pt; margin-bottom: 4pt; }
.star { padding-left: 12pt; font-size: 11pt; color: #444; margin-bottom: 4pt; }
其中 CN_FONT_RULE:
@font-face { font-family: 'CJKFont'; src: url('CN_FONT_URL'); }文章内容到 HTML 的映射规则:
| 文章元素 | HTML 输出 | ||||||
|---|---|---|---|---|---|---|---|
| --------- | ---------- | ||||||
| 文章标题 | | ||||||
| 二级标题(##) | | ||||||
| 正文段落 | | ||||||
| 粗体强调 | | ||||||
| 注意事项/提示框 | | ||||||
| 列表项 | | ||||||
| 图片 | 使用绝对路径 | ||||||
| 图片说明 | | ||||||
| 表格 | |