Commit 9cd93521 authored by 郭阔's avatar 郭阔

perf(harvest): attempt2 resumes the failed session instead of full re-run

A fresh attempt2 re-fetched every article (minutes + dollars) just to
re-deliver a result whose data was already archived and pushed. attempt2
now extracts session_id from the failed envelope and runs
claude --resume with a short re-deliver prompt (no re-collection, no
browser); heartbeat is not reset in resume mode. attempt3 (fallback
provider) stays a fresh full run — cross-provider resume not trusted.
parent f33c4a50
......@@ -103,17 +103,12 @@ echo "采集中" > "$LOG_DIR/${SOURCE}.phase"
# 走正常失败路径 → trap 回收浏览器实例,不阻塞次日 launchd 触发。
# 可在栏目 conf 覆盖(如 MAX_RUNTIME_MIN=90),默认 60。
MAX_RUNTIME_MIN="${MAX_RUNTIME_MIN:-60}"
RESUME_SESSION=""
run_claude_once() { # 用当前 CLAUDE_SETTINGS_ARGS 执行一次采集会话(带看门狗)
run_claude_once() { # 执行一次采集会话(带看门狗);RESUME_SESSION 非空时为续会话补交结果模式
set +e
claude -p \
"${CLAUDE_SETTINGS_ARGS[@]}" \
--permission-mode bypassPermissions \
--allowed-tools Bash Write \
--output-format json \
--json-schema "$RESULT_SCHEMA" \
--max-budget-usd "$RESOLVED_MAX_BUDGET_USD" \
"使用news-harvester获取${SOURCE}的最新${COUNT}条数据,并保存到obsidian中。
local resume_args=()
local prompt="使用news-harvester获取${SOURCE}的最新${COUNT}条数据,并保存到obsidian中。
执行要求:
- 必须在前台同步完成所有抓取和归档,不要把浏览器自动化或任何步骤放到后台任务中运行。
......@@ -124,7 +119,20 @@ run_claude_once() { # 用当前 CLAUDE_SETTINGS_ARGS 执行一次采集会话(
echo '<阶段>' > ~/NewsHarvester/logs/${SOURCE}.phase
阶段只允许三个值:采集中(列表页浏览与逐篇抓取)、摘要生成(写中文摘要)、推送/收尾(finalize 与推送)。
- 列表页候选与 registry(近7天)对照后,若所有候选均已在库(无任何新文章):立即收尾返回结果——articles 留空、succeeded_count=0、source_exhausted=true、exhaustion_reason="all_seen",不要再做单篇核验、摘要或重复确认,这是正常且成功的结果。
${RESULT_REQUIREMENTS}" \
${RESULT_REQUIREMENTS}"
if [ -n "$RESUME_SESSION" ]; then
resume_args=(--resume "$RESUME_SESSION")
prompt="上一轮采集工作已全部完成(文章已归档、摘要已写、已推送 News Hub),但你的最终结果未能通过 StructuredOutput 结构化通道交付。请勿重新采集、不要打开浏览器、不要重复核验;基于你上一轮已完成的工作,立即通过结构化输出按原 JSON Schema 重新提交最终结果(articles 列表/各计数/status,数据以上一轮实际完成者为准)。"
fi
claude -p \
"${CLAUDE_SETTINGS_ARGS[@]}" \
"${resume_args[@]}" \
--permission-mode bypassPermissions \
--allowed-tools Bash Write \
--output-format json \
--json-schema "$RESULT_SCHEMA" \
--max-budget-usd "$RESOLVED_MAX_BUDGET_USD" \
"$prompt" \
> "$JSON_OUT" 2> "$RAW_OUT" &
_claude_pid=$!
(
......@@ -169,12 +177,19 @@ for ATTEMPT in 1 2 3; do
if [ "$ATTEMPT" = "2" ]; then
cp -f "$JSON_OUT" "${JSON_OUT}.attempt1" 2>/dev/null || true
cp -f "$RAW_OUT" "${RAW_OUT}.attempt1" 2>/dev/null || true
echo "[attempt 2/3] 同 provider 重试(${USED_PROVIDER:-default})…"
# 优先续接上一会话补交结果(秒级、零重采);拿不到 session_id 才整场重跑
RESUME_SESSION="$(jq -r '.session_id // empty' "$JSON_OUT" 2>/dev/null || true)"
if [ -n "$RESUME_SESSION" ]; then
echo "[attempt 2/3] 续接会话 ${RESUME_SESSION} 补交结构化结果(${USED_PROVIDER:-default})…"
else
echo "[attempt 2/3] 同 provider 重试(${USED_PROVIDER:-default})…"
fi
fi
if [ "$ATTEMPT" = "3" ]; then
if [ -n "${FALLBACK_PROVIDER:-}" ] && [ "${FALLBACK_PROVIDER}" != "${PROVIDER:-}" ]; then
cp -f "$JSON_OUT" "${JSON_OUT}.attempt2" 2>/dev/null || true
cp -f "$RAW_OUT" "${RAW_OUT}.attempt2" 2>/dev/null || true
RESUME_SESSION="" # 跨 provider 不续接旧会话,全新完整跑
resolve_continue_provider # PROVIDER → FALLBACK_PROVIDER,重建 CLAUDE_SETTINGS_ARGS
resolve_max_budget_usd # 按备用 provider 的预算覆盖(如 ccswitch-gpt=30)
echo "[attempt 3/3] 切换备用 provider:${USED_PROVIDER}…"
......@@ -182,7 +197,10 @@ for ATTEMPT in 1 2 3; do
break # 无可用备用通道,不再空转
fi
fi
echo "采集中" > "$LOG_DIR/${SOURCE}.phase"
# 续会话补交模式不重采,心跳保持上一轮状态;全新尝试才重置为采集中
if [ -z "$RESUME_SESSION" ]; then
echo "采集中" > "$LOG_DIR/${SOURCE}.phase"
fi
run_claude_once
if ! attempt_needs_retry; then break; fi
if [ "$ATTEMPT" = "3" ]; then break; fi
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment