feat: AI 控制台增强——①de_read_clipboard 剪贴板回读工具;②任务可中断(stop_event 循环检查点 + API stop + 前端■停止按钮);③智能滚动(回看历史不被打断,贴底才跟随);④右侧实时画面(MJPEG 流自动跟随操作设备,可手动选择)
This commit is contained in:
+21
-1
@@ -41,6 +41,7 @@ _run = {"id": None, "state": "idle", "prompt": "", "serial": "",
|
||||
"answer": "", "error": "",
|
||||
"history": []} # 多轮对话历史 [{role: user|assistant, content}]
|
||||
_queues = {} # run_id -> queue.Queue(SSE 消费者读取)
|
||||
_stop_events = {} # run_id -> threading.Event(用户中断)
|
||||
_lock = threading.Lock()
|
||||
|
||||
|
||||
@@ -107,6 +108,7 @@ def agent_run():
|
||||
answer="", error="")
|
||||
# history 保留(同会话多轮对话),由前端「清空对话」调用 clear 重置
|
||||
_queues[run_id] = queue.Queue()
|
||||
_stop_events[run_id] = threading.Event()
|
||||
_log.info(f"Agent 启动: {prompt[:60]}")
|
||||
threading.Thread(target=_agent_thread,
|
||||
args=(run_id, prompt, serial, cfg),
|
||||
@@ -143,6 +145,20 @@ def agent_stream():
|
||||
"X-Accel-Buffering": "no"})
|
||||
|
||||
|
||||
@bp.route("/api/agent/stop", methods=["POST"])
|
||||
@admin_required
|
||||
def agent_stop():
|
||||
"""中断当前运行的 Agent(下一个检查点生效,通常在数秒内)。"""
|
||||
with _lock:
|
||||
if _run["state"] != "running":
|
||||
return jsonify({"ok": False, "error": "当前没有运行中的任务"}), 400
|
||||
evt = _stop_events.get(_run["id"])
|
||||
if evt:
|
||||
evt.set()
|
||||
_log.info("用户请求中断 Agent")
|
||||
return jsonify({"ok": True, "msg": "已请求停止"})
|
||||
|
||||
|
||||
@bp.route("/api/agent/clear", methods=["POST"])
|
||||
@admin_required
|
||||
def agent_clear():
|
||||
@@ -193,12 +209,15 @@ def _agent_thread(run_id, prompt, serial, cfg):
|
||||
with _lock:
|
||||
history = list(_run.get("history") or [])
|
||||
target = serial or cfg.get("default_serial") or ""
|
||||
stop_evt = _stop_events.get(run_id)
|
||||
|
||||
async def _execute():
|
||||
await agent._load_tools()
|
||||
return await agent.run_stream(prompt, target,
|
||||
history=history,
|
||||
on_delta=on_delta, on_tool=on_tool)
|
||||
on_delta=on_delta, on_tool=on_tool,
|
||||
should_stop=lambda: bool(
|
||||
stop_evt and stop_evt.is_set()))
|
||||
|
||||
# 整体超时保护:卡死时结束,释放单实例
|
||||
answer = asyncio.run(asyncio.wait_for(_execute(), timeout=900))
|
||||
@@ -220,3 +239,4 @@ def _agent_thread(run_id, prompt, serial, cfg):
|
||||
finally:
|
||||
q.put(None) # 关闭 SSE
|
||||
_queues.pop(run_id, None)
|
||||
_stop_events.pop(run_id, None)
|
||||
|
||||
Reference in New Issue
Block a user