diff --git a/web/__init__.py b/web/__init__.py index 81696b9..617ddcb 100644 --- a/web/__init__.py +++ b/web/__init__.py @@ -23,7 +23,9 @@ def register_blueprints(app): from .devices_api import bp as devices_bp from .apks_api import bp as apks_bp from .tailscale_api import bp as tailscale_bp + from . import agent_api as _agent_mod from .agent_api import bp as agent_bp + _agent_mod.set_app(app) for bp in (auth_bp, monitor_bp, tasks_bp, admin_bp, tools_bp, devices_bp, apks_bp, tailscale_bp, agent_bp): app.register_blueprint(bp) diff --git a/web/agent_api.py b/web/agent_api.py index ede6239..2dcb2a1 100644 --- a/web/agent_api.py +++ b/web/agent_api.py @@ -43,6 +43,12 @@ _run = {"id": None, "state": "idle", "prompt": "", "serial": "", _queues = {} # run_id -> queue.Queue(SSE 消费者读取) _stop_events = {} # run_id -> threading.Event(用户中断) _lock = threading.Lock() +_flask_app = None # web_server 注册时注入(后台线程 db 操作需 app context) + + +def set_app(app): + global _flask_app + _flask_app = app def _meta_get(key): @@ -90,10 +96,13 @@ def _bigrams(text): def _find_experiences(prompt, limit=2, threshold=0.10): """按 bigram 重叠检索相似历史经验(prompt 与任务描述的字符相似度)。""" try: - _ensure_exp_table() - rows = db.session.execute(db.text( - "SELECT task_prompt, recipe, hits FROM agent_experience " - "WHERE recipe != '' ORDER BY hits DESC, id DESC LIMIT 50")).fetchall() + if _flask_app is None: + return "" + with _flask_app.app_context(): + _ensure_exp_table() + rows = db.session.execute(db.text( + "SELECT task_prompt, recipe, hits FROM agent_experience " + "WHERE recipe != '' ORDER BY hits DESC, id DESC LIMIT 50")).fetchall() except Exception: return "" if not rows: @@ -141,16 +150,20 @@ def _distill_experience(cfg, prompt, tool_seq): def _save_experience(prompt, recipe, tool_seq): + """保存经验(后台线程调用,包 app context)。""" try: - _ensure_exp_table() - from datetime import datetime - db.session.execute(db.text( - "INSERT INTO agent_experience(task_prompt, recipe, tool_seq, hits, created_at) " - "VALUES(:p, :r, :t, 0, :c)"), - {"p": prompt[:500], "r": recipe, "t": tool_seq[:1000], - "c": datetime.now().strftime("%Y-%m-%d %H:%M")}) - db.session.commit() - _log.info("经验已保存(配方 %d 字符)", len(recipe)) + if _flask_app is None: + return + with _flask_app.app_context(): + _ensure_exp_table() + from datetime import datetime + db.session.execute(db.text( + "INSERT INTO agent_experience(task_prompt, recipe, tool_seq, hits, created_at) " + "VALUES(:p, :r, :t, 0, :c)"), + {"p": prompt[:500], "r": recipe, "t": tool_seq[:1000], + "c": datetime.now().strftime("%Y-%m-%d %H:%M")}) + db.session.commit() + _log.info("经验已保存(配方 %d 字符)", len(recipe)) except Exception as e: _log.warning(f"经验保存失败: {e}")