| name | wewrite-republish |
| description | 手动重试推送已生成内容到微信公众号草稿箱。从「今日写作计划」中读取 `写作状态==发布失败` 的记录,
跳过 LLM(不重新写文章),直接调用 wewrite 的 publish 命令重推送。适用于 IP 白名单更新、
token 刷新、网络故障等场景下的批量补救。
触发关键词:重试推送、补推送、重发草稿、wewrite-republish、republish、补发、IP 白名单后重试。
|
| allowed-tools | ["Bash","Read","Grep"] |
WeWrite-Republish — 手动重试推送
把已经写好但推送失败的文章重新推到公众号草稿箱。不重新跑 LLM,节约 5-10 分钟和 ¥1-2/篇成本。
适用场景
- 早上
/wewrite-execute 自动跑时撞上微信 API 报错(IP 白名单、token 过期、5xx 抖动)
- 修复根因后(更新公众号后台 IP 白名单 / 重新拉 token / 调整文章规避审核)
- 想批量把今天失败的几篇重新推一次
不适用:
- 文章本身没生成(Step 4 LLM 阶段失败)→ 走
/wewrite-execute 从头跑
- 想换主题 / 换封面 / 改标题 → 直接编辑本地 markdown 后用 wewrite 的
cli.py publish 手动重推
- 历史日期的文章(本 skill 只处理今天的「今日写作计划」记录)
⚠️ 前置:必须执行(不可跳过)
执行本 skill 任何步骤前,第一步必须加载飞书配置:
source ~/.claude/skills/wewrite-base/scripts/feishu_config.sh
加载失败时按 wrapper 错误指引处理。所有 lark-cli 命令依赖环境变量,跳过 source 会因为变量为空而失败。
source 成功后环境变量(与 wewrite-base 共用):
$WEWRITE_BASE_TOKEN / $WEWRITE_TBL_PLAN / $WEWRITE_TBL_OVERVIEW / $WEWRITE_USER_OPEN_ID
常量(非敏感)
CLIENT_MAP:
AI文森说: winson
赵姐说事儿: zhaojie
WEWRITE_DIR: ~/.claude/skills/wewrite
WEWRITE_PUBLISH_CMD: python3 ~/.claude/skills/wewrite/toolkit/cli.py publish
其他前置
- 加载 skill:
lark-base(用于读写多维表格)
- 加载 skill:
lark-im(用于 Bot 通知)
- 确认
~/.claude/skills/wewrite/toolkit/cli.py 可用(不需要加载 wewrite skill 整体——只调它的 publish 命令)
步骤
Step 1 — 读取失败记录
读「今日写作计划」中 计划日期=今天 且 写作状态=="发布失败" 的所有记录:
TODAY_MS=$(date +%s%3N)
TODAY_START_MS=$(date -j -v0H -v0M -v0S +%s%3N 2>/dev/null || date -d "today 00:00" +%s%3N)
lark-cli base +record-list \
--base-token ${WEWRITE_BASE_TOKEN} \
--table-id ${WEWRITE_TBL_PLAN} \
--filter "AND(CurrentValue.[计划日期] >= ${TODAY_START_MS}, CurrentValue.[写作状态] = \"发布失败\")" \
--limit 200
含**已熔断(重试次数 ≥ 3)**的记录——本 skill 是熔断后的"人工接管"通道。
Step 2 — 分类候选
对每条返回记录:
| 条件 | 分类 |
|---|
markdown路径 为空 / 文件不存在 | 不可重试:跳过,提示用户从头跑 /wewrite-execute |
markdown路径 文件存在 + 其他必填字段(主题/标题/摘要)齐全 | 可重试:进入候选列表 |
markdown路径 文件存在但其他字段缺失 | 可重试(带警告:缺失字段会用默认值,比如缺封面用微信默认) |
校验文件存在:
[ -f "${MARKDOWN_PATH}" ] && echo "✓ exists" || echo "✗ missing"
Step 3 — 显示候选列表 + 用户确认
打印一张清晰的表格让用户决定推哪些:
今日发布失败的文章({N} 条):
┌────┬──────────┬──────────────────┬──────────┬──────────┬──────────────────┐
│ # │ 账号 │ 标题 │ 重试次数 │ 失败原因 │ 产物状态 │
├────┼──────────┼──────────────────┼──────────┼──────────┼──────────────────┤
│ 1 │ AI文森说 │ 《XXXX》 │ 2/3 │ {error} │ ✓ markdown+cover │
│ 2 │ 赵姐说事儿│ 《YYYY》 │ 3/3 🔥 │ {error} │ ✓ markdown only │
│ 3 │ AI文森说 │ 《ZZZZ》 │ 1/3 │ {error} │ ✗ 无产物 │
└────┴──────────┴──────────────────┴──────────┴──────────┴──────────────────┘
🔥 = 已熔断(≥3 次失败) ✗ = 不可重试
请选择要重推的编号(如 "1,2" 或 "all" 推全部可重试项,"q" 取消):
等用户输入。✗ 标记的不进入选择列表。
Step 4 — 逐条重推
对用户选中的每条记录,按以下顺序操作:
4.1 调用 publish 命令
COVER_ARG=""
if [ -n "${COVER_PATH}" ] && [ -f "${COVER_PATH}" ]; then
COVER_ARG="--cover \"${COVER_PATH}\""
fi
python3 ~/.claude/skills/wewrite/toolkit/cli.py publish \
"${MARKDOWN_PATH}" \
${COVER_ARG} \
--theme "${THEME}" \
--title "${TITLE}" \
--digest "${DIGEST}" 2>&1 | tee /tmp/wewrite-republish-{record_id}.log
PUBLISH_EXIT=$?
解析输出拿到 media_id(cli.py publish 成功时会输出,格式参考 wewrite skill 的 Step 7)。
4.2 推送成功 → 回写各表
a. 更新「今日写作计划」为终态:
lark-cli base +record-upsert \
--base-token ${WEWRITE_BASE_TOKEN} \
--table-id ${WEWRITE_TBL_PLAN} \
--record-id {plan_record_id} \
--json '{
"写作状态": "已推送草稿",
"media_id": "{media_id}",
"发布结果": "成功",
"备注": "通过 /wewrite-republish 手动重推成功"
}'
b. 候选区状态改为「已写稿」:
lark-cli base +record-upsert \
--base-token ${WEWRITE_BASE_TOKEN} \
--table-id ${WEWRITE_TBL_TOPICS} \
--record-id {topic_record_id} \
--json '{"状态": "已写稿"}'
c. 创建「文章总览」记录(同 wewrite-base B.4.c 逻辑):
lark-cli base +record-upsert \
--base-token ${WEWRITE_BASE_TOKEN} \
--table-id ${WEWRITE_TBL_OVERVIEW} \
--json '{
"标题": "{title}",
"对应账号": "{对应账号}",
"推送日期": {今天的毫秒时间戳},
"框架类型": "{框架类型}",
"media_id": "{media_id}",
"选题来源": "热点抓取",
"字数": {从 markdown 解析},
"备注": "通过 /wewrite-republish 手动重推"
}'
注意:要先查「文章总览」是否已有同 media_id 的记录,避免重复创建。
4.3 推送仍失败 → 重试次数 +1
CURRENT_RETRY=$(从 step 1 的查询结果中取)
NEW_RETRY=$((CURRENT_RETRY + 1))
lark-cli base +record-upsert \
--base-token ${WEWRITE_BASE_TOKEN} \
--table-id ${WEWRITE_TBL_PLAN} \
--record-id {plan_record_id} \
--json "{
\"重试次数\": ${NEW_RETRY},
\"备注\": \"/wewrite-republish 第 ${NEW_RETRY} 次手动重推仍失败:{新错误}\"
}"
Step 5 — 汇总通知
全部处理完发一条 Bot 汇总:
lark-cli im +messages-send --as bot \
--user-id ${WEWRITE_USER_OPEN_ID} \
--markdown "**📤 手动重推完成**\n\n- 成功:{n_success} 篇\n- 仍失败:{n_failed} 篇\n- 跳过(无产物):{n_skipped} 篇\n\n{逐条列出标题 + 结果}\n\n[查看写作计划](${WEWRITE_BASE_URL}?table=${WEWRITE_TBL_PLAN})"
边界情况
Q: publish 命令成功但回写 Base 失败怎么办?
症状:cli.py publish 返回了 media_id(说明草稿已推到公众号),但 lark-cli 回写「今日写作计划」时网络断/API 报错。
结果:公众号草稿箱已有这篇,但 Base 仍显示"发布失败"。
修法:再跑一次 /wewrite-republish。Step 4.2 会再调一次 publish——这会在公众号草稿箱产生重复草稿。需要手动删除其中一份。
当前接受这个成本(与 wewrite-base 的 B.7 中断恢复 race 同源)。如果需要严格防重复,要在 Step 4.1 之前先查「文章总览」表是否已有同 markdown 路径的记录——但当前不做。
Q: 文章总览已经有记录了(之前推送成功过的某次)
症状:第一次推送时其实已经成功创建了草稿和文章总览记录,但回写「今日写作计划」失败留下"发布失败"假象,导致这次又来重推。
避免:Step 4.2.c 创建文章总览前先按 media_id 或"账号+标题+日期"查重,命中就只 update 不 insert。
Q: 用户选了 "all" 但其中一条文件被手动删了
症状:Step 2 校验时文件还在,Step 4 执行时已被删(极少)。
结果:cli.py publish 报"file not found",进入 4.3 失败分支。
预期:可接受,重试次数 +1,下次跑会被 Step 2 标记为 ✗ 跳过。
与 wewrite-base 的关系
/wewrite-execute(自动)
↓
推送失败 → 重试次数 +1 → 状态:发布失败
↓
下次自动重试(重试次数 < 3)
↓
仍失败 → 重试次数 ≥ 3 → 熔断 + Bot 通知人工
↓
人工排查根因(IP 白名单 / token / 内容审核)
↓
/wewrite-republish(手动)← 你在这里
↓
跳过 LLM 直接调 publish 命令
↓
成功 → 回写状态终态
失败 → 重试次数 +1(等下次再处理)
注意事项
- 本 skill 只读今日的「今日写作计划」记录,不处理跨日。跨日重推请直接手动
cd ~/.claude/skills/wewrite && python3 toolkit/cli.py publish ...
- 校验 markdown 文件存在性时用绝对路径,避免 cwd 误差
cli.py publish 输出 media_id 的格式跟 wewrite skill 主管道 Step 7 一致——按那里的解析方式取
- 推送成功后清零
重试次数 是可选项,当前设计不清零(保留历史),但「写作状态」从"发布失败"变为"已推送草稿"已经把记录从 wewrite-base 的重试循环里摘出来了