fix: 执行器失败直接发核心群,不走API
- 执行器修不了→hermes send到核心群,知微在群里收到就处理 - Dad也在核心群,能看到 - 不发gateway API(上下文隔离,Dad看不到) - 无fix_action也走同一路径
This commit is contained in:
@@ -673,7 +673,7 @@ def main():
|
||||
if entry["level"] in ("critical", "error"):
|
||||
print(f" [{entry['level'].upper()}] {entry['category']}: {entry['msg']}")
|
||||
|
||||
# 检查是否有 needs_llm 的 TODO(执行器尝试失败,需知微介入)
|
||||
# 检查是否有执行器升级来的TODO(通知失败挂起的)
|
||||
try:
|
||||
conn2 = sqlite3.connect(str(DB_PATH))
|
||||
needs_llm = conn2.execute(
|
||||
|
||||
@@ -1,53 +1,30 @@
|
||||
#!/usr/bin/env python3
|
||||
"""self_todo_executor.py — TODO自动执行器 (no_agent模式)
|
||||
|
||||
每10分钟轮询mofin.db中todos表的pending任务,执行fix_action命令。
|
||||
没有"blocked"状态。能修就修,修不了留着等明天体检再说。
|
||||
纯代码逻辑,不调LLM。
|
||||
每10分钟轮询pending TODOs,执行fix_action。
|
||||
成功→completed。失败→直接调Hermes Gateway让知微处理。
|
||||
"""
|
||||
|
||||
import json, os, sqlite3, subprocess, sys, time
|
||||
import json, sqlite3, subprocess, time, urllib.request
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
BASE = Path("/home/hmo/MoFin")
|
||||
DB_PATH = BASE / "data" / "mofin.db"
|
||||
|
||||
|
||||
def get_conn():
|
||||
conn = sqlite3.connect(str(DB_PATH))
|
||||
conn.row_factory = sqlite3.Row
|
||||
return conn
|
||||
|
||||
|
||||
def execute_fix(fix_action):
|
||||
"""执行修复命令,返回 (ok, output)"""
|
||||
if not fix_action:
|
||||
return False, "无修复命令"
|
||||
try:
|
||||
r = subprocess.run(
|
||||
fix_action,
|
||||
shell=True, capture_output=True, text=True, timeout=60
|
||||
)
|
||||
if r.returncode == 0:
|
||||
return True, r.stdout.strip()[:300] or "ok"
|
||||
else:
|
||||
return False, f"exit={r.returncode}: {r.stderr.strip()[:300]}"
|
||||
except subprocess.TimeoutExpired:
|
||||
return False, "执行超时(60s)"
|
||||
except Exception as e:
|
||||
return False, str(e)[:200]
|
||||
GATEWAY_URL = "http://localhost:8643/v1/chat/completions"
|
||||
GATEWAY_KEY = "hermes123"
|
||||
COREGROUP = "coregroup@conference.yoin.fun"
|
||||
|
||||
|
||||
def main():
|
||||
start = time.time()
|
||||
conn = get_conn()
|
||||
conn = sqlite3.connect(str(DB_PATH))
|
||||
conn.row_factory = sqlite3.Row
|
||||
|
||||
rows = conn.execute(
|
||||
"SELECT id, title, fix_action, retry_count, max_retries FROM todos "
|
||||
"WHERE status='pending' ORDER BY "
|
||||
"CASE priority WHEN 'high' THEN 0 WHEN 'medium' THEN 1 ELSE 2 END, "
|
||||
"created_at ASC LIMIT 5"
|
||||
"SELECT id, title, fix_action FROM todos WHERE status='pending' "
|
||||
"ORDER BY CASE priority WHEN 'high' THEN 0 WHEN 'medium' THEN 1 ELSE 2 END, "
|
||||
"created_at ASC LIMIT 3"
|
||||
).fetchall()
|
||||
|
||||
if not rows:
|
||||
@@ -55,49 +32,59 @@ def main():
|
||||
print("[SILENT] 无待处理TODO")
|
||||
return
|
||||
|
||||
results = []
|
||||
for row in rows:
|
||||
todo_id = row["id"]
|
||||
tid = row["id"]
|
||||
title = row["title"]
|
||||
fix_action = row["fix_action"]
|
||||
fix = row["fix_action"]
|
||||
|
||||
if not fix_action:
|
||||
conn.execute(
|
||||
"UPDATE todos SET status='needs_llm', note='无fix_action需人工分析', "
|
||||
"updated_at=CURRENT_TIMESTAMP WHERE id=?", (todo_id,))
|
||||
results.append(("🔶", f"{title}: 需知微分析(无修复方案)"))
|
||||
conn.commit()
|
||||
continue
|
||||
|
||||
# 执行(只试一次,失败立即升级)
|
||||
conn.execute(
|
||||
"UPDATE todos SET status='in_progress', updated_at=CURRENT_TIMESTAMP WHERE id=?",
|
||||
(todo_id,))
|
||||
conn.execute("UPDATE todos SET status='in_progress' WHERE id=?", (tid,))
|
||||
conn.commit()
|
||||
|
||||
ok, output = execute_fix(fix_action)
|
||||
if ok:
|
||||
conn.execute(
|
||||
"UPDATE todos SET status='completed', note=?, "
|
||||
"updated_at=CURRENT_TIMESTAMP WHERE id=?",
|
||||
(f"已修复: {output[:200]}", todo_id))
|
||||
results.append(("✅", f"{title}: 已修复"))
|
||||
if not fix:
|
||||
msg = f"[自愈执行器] 需处理: {title} (无自动修复方案)"
|
||||
else:
|
||||
conn.execute(
|
||||
"UPDATE todos SET status='needs_llm', note=?, "
|
||||
"updated_at=CURRENT_TIMESTAMP WHERE id=?",
|
||||
(f"执行失败: {output[:200]}", todo_id))
|
||||
results.append(("🔶", f"{title}: 需知微介入({output[:60]})"))
|
||||
# 执行修复命令
|
||||
try:
|
||||
r = subprocess.run(fix, shell=True, capture_output=True, text=True, timeout=30)
|
||||
if r.returncode == 0:
|
||||
conn.execute("UPDATE todos SET status='completed', note=? WHERE id=?",
|
||||
(f"已修复: {r.stdout.strip()[:200]}", tid))
|
||||
conn.commit()
|
||||
print(f" ✅ {title}: 已修复")
|
||||
continue
|
||||
output = r.stderr.strip()[:200] or r.stdout.strip()[:200]
|
||||
except subprocess.TimeoutExpired:
|
||||
output = "执行超时"
|
||||
except Exception as e:
|
||||
output = str(e)[:200]
|
||||
msg = f"需处理: {title} (尝试失败: {output})"
|
||||
|
||||
# 修复失败→发到核心群让知微处理(知微在群里,我收到了就处理)
|
||||
try:
|
||||
# 用hermes send发到核心群
|
||||
send_cmd = ["hermes", "send", "--to", f"xmpp:{COREGROUP}", msg]
|
||||
r = subprocess.run(send_cmd, capture_output=True, text=True, timeout=30)
|
||||
if r.returncode == 0:
|
||||
conn.execute("UPDATE todos SET status='completed', note='已发到核心群通知知微' WHERE id=?",
|
||||
(tid,))
|
||||
print(f" 🔶 {title}: 已发到核心群")
|
||||
else:
|
||||
conn.execute("UPDATE todos SET status='pending', note=? WHERE id=?",
|
||||
(f"发核心群失败: {r.stderr[:100]}", tid))
|
||||
print(f" ⚠️ {title}: 发核心群失败({r.stderr[:60]})")
|
||||
except Exception as e:
|
||||
conn.execute("UPDATE todos SET status='pending', note=? WHERE id=?",
|
||||
(f"发核心群异常: {str(e)[:100]}", tid))
|
||||
print(f" ⚠️ {title}: 发核心群异常({str(e)[:60]})")
|
||||
|
||||
conn.commit()
|
||||
|
||||
conn.close()
|
||||
|
||||
elapsed = time.time() - start
|
||||
if results:
|
||||
print(f"自愈执行器 | {datetime.now().strftime('%H:%M')} | {len(results)}条 ({elapsed:.0f}s)")
|
||||
for icon, msg in results:
|
||||
print(f" {icon} {msg}")
|
||||
if rows:
|
||||
print(f"自愈执行器 | {datetime.now().strftime('%H:%M')} | {len(rows)}条 ({time.time()-start:.0f}s)")
|
||||
else:
|
||||
print("[SILENT] 无待处理TODO")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user