fix: 取消blocked,改为needs_llm升级机制
- executor重试耗尽→needs_llm(需知微介入),非blocked - health check报告尾段展示needs_llm项+失败原因 - derive_fix_action覆盖全部已知场景(cron errors/delivery等) - TODO创建时注明"无法当场修复原因" - 每个TODO必有fix_action,没有的不创建TODOs直接在报告列出
This commit is contained in:
@@ -48,6 +48,9 @@ def derive_fix_action(detail, msg):
|
||||
# system-audit error → 验证拷贝
|
||||
if "system_audit" in msg or "系统审计" in msg:
|
||||
return f"ls -la /home/hmo/.hermes/profiles/position-analyst/scripts/system_audit.py 2>&1"
|
||||
# cron errors(last_status=error)→ 验证文件存在,等下次cron运行自动恢复
|
||||
if "cron" in msg.lower() and "error" in msg.lower() and ("小果" in msg or "系统审计" in msg):
|
||||
return f"ls -la /home/hmo/.hermes/profiles/position-analyst/scripts/xiaoguo_scanner.py /home/hmo/.hermes/profiles/position-analyst/scripts/system_audit.py 2>&1"
|
||||
# 港股汇率 → 刷新
|
||||
if "港股汇率" in msg:
|
||||
return f"cd {BASE} && python3 hk_rate.py 2>&1"
|
||||
@@ -160,13 +163,14 @@ def write_todos_for_issues():
|
||||
fix_action = derive_fix_action(issue.get("detail", ""), issue.get("msg", ""))
|
||||
if not fix_action:
|
||||
# 没有fix_action就不创建TODO,直接输出到报告里
|
||||
print(f" ⚠️ 无自动修复方案: [{pri}] {title[:60]}")
|
||||
print(f" ⚠️ 无法自动修复: [{pri}] {title[:60]}")
|
||||
print(f" 原因: 未知修复方案,需人工分析")
|
||||
continue
|
||||
conn.execute(
|
||||
"INSERT INTO todos (title, description, priority, source, status, fix_action) "
|
||||
"VALUES (?, ?, ?, 'health_check', 'pending', ?)",
|
||||
(title,
|
||||
f"体检发现于 {ctx['started_at'].strftime('%Y-%m-%d %H:%M')}\n分类: {issue['category']}\n详情: {issue.get('detail', '')}",
|
||||
f"体检发现于 {ctx['started_at'].strftime('%Y-%m-%d %H:%M')}\n分类: {issue['category']}\n详情: {issue.get('detail', '')}\n无法当场修复原因: 需验证/需等待",
|
||||
pri, fix_action)
|
||||
)
|
||||
new_count += 1
|
||||
@@ -669,19 +673,20 @@ def main():
|
||||
if entry["level"] in ("critical", "error"):
|
||||
print(f" [{entry['level'].upper()}] {entry['category']}: {entry['msg']}")
|
||||
|
||||
# 检查是否有待处理的 TODO 需要知微关注
|
||||
# 检查是否有 needs_llm 的 TODO(执行器尝试失败,需知微介入)
|
||||
try:
|
||||
conn2 = sqlite3.connect(str(DB_PATH))
|
||||
pending_llm = conn2.execute(
|
||||
"SELECT id, title, priority, created_at FROM todos "
|
||||
"WHERE status='pending' AND fix_action IS NULL "
|
||||
"ORDER BY created_at ASC LIMIT 5"
|
||||
needs_llm = conn2.execute(
|
||||
"SELECT id, title, priority, created_at, note FROM todos "
|
||||
"WHERE status='needs_llm' "
|
||||
"ORDER BY CASE priority WHEN 'high' THEN 0 WHEN 'medium' THEN 1 ELSE 2 END, created_at ASC LIMIT 10"
|
||||
).fetchall()
|
||||
if pending_llm:
|
||||
if needs_llm:
|
||||
print()
|
||||
print("⚠️ 待处理(需知微介入):")
|
||||
for p in pending_llm:
|
||||
print(f" [{p[2]}] #{p[0]} {p[1][:70]} ({p[3][:10]})")
|
||||
print("🔶 需知微介入(执行器无法自动修复):")
|
||||
for n in needs_llm:
|
||||
note = (n[4] or "")[:60]
|
||||
print(f" [{n[2]}] #{n[0]} {n[1][:60]} → {note}")
|
||||
conn2.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -88,12 +88,12 @@ def main():
|
||||
else:
|
||||
retry_count += 1
|
||||
if retry_count >= max_retries:
|
||||
# 重试用完,留到下次体检再重新发现
|
||||
# 重试用完,超出能力范围→标记需LLM处理
|
||||
conn.execute(
|
||||
"UPDATE todos SET status='pending', retry_count=0, "
|
||||
"UPDATE todos SET status='needs_llm', retry_count=?, "
|
||||
"note=?, updated_at=CURRENT_TIMESTAMP WHERE id=?",
|
||||
(f"已达最大重试({max_retries}次),留待下次", todo_id))
|
||||
results.append(("🔄", f"{title}: 重试耗尽,等下次体检"))
|
||||
(retry_count, f"尝试{retry_count}次仍失败: {output[:150]}", todo_id))
|
||||
results.append(("🔶", f"{title}: 需知微介入(重试{retry_count}次失败)"))
|
||||
else:
|
||||
conn.execute(
|
||||
"UPDATE todos SET status='pending', retry_count=?, "
|
||||
|
||||
Reference in New Issue
Block a user