#!/usr/bin/env python3 """self_todo_executor.py — TODO自动执行器 (no_agent模式) 每10分钟轮询mofin.db中todos表的pending任务,执行fix_action命令。 没有"blocked"状态。能修就修,修不了留着等明天体检再说。 纯代码逻辑,不调LLM。 """ import json, os, sqlite3, subprocess, sys, time 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] def main(): start = time.time() conn = get_conn() 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" ).fetchall() if not rows: conn.close() print("[SILENT] 无待处理TODO") return results = [] for row in rows: todo_id = row["id"] title = row["title"] fix_action = row["fix_action"] retry_count = row["retry_count"] max_retries = row["max_retries"] if not fix_action: # 没有fix_action就不应该创建这个TODO,跳过 conn.execute( "UPDATE todos SET status='completed', note='无修复命令,跳过', " "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.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}: 已修复")) else: retry_count += 1 if retry_count >= max_retries: # 重试用完,留到下次体检再重新发现 conn.execute( "UPDATE todos SET status='pending', retry_count=0, " "note=?, updated_at=CURRENT_TIMESTAMP WHERE id=?", (f"已达最大重试({max_retries}次),留待下次", todo_id)) results.append(("🔄", f"{title}: 重试耗尽,等下次体检")) else: conn.execute( "UPDATE todos SET status='pending', retry_count=?, " "note=?, updated_at=CURRENT_TIMESTAMP WHERE id=?", (retry_count, f"第{retry_count}次失败: {output[:100]}", todo_id)) results.append(("🔄", f"{title}: 重试{retry_count}/{max_retries}")) 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 __name__ == "__main__": main()