agent-Specialization/server/work_timer.py

96 lines
3.6 KiB
Python

"""对话工作计时器持久化与空闲判定辅助函数。
把「对话真正停止运行(没有其它前台任务、也没有后台子智能体/后台命令/压缩)」
这一时刻的 work_timer 同步到磁盘,并刷新当前 ContextManager 内存中的副本,
避免刷新页面后计时器又恢复成「工作中」。
"""
from __future__ import annotations
from datetime import datetime
from typing import Any, Optional, Set
from modules.sub_agent import TERMINAL_STATUSES as SUB_AGENT_TERMINAL_STATUSES
def has_running_background_work(terminal: Any, conversation_id: Optional[str]) -> bool:
"""检测指定对话是否还有未完成的后台工作(子智能体、后台命令、待通知完成项)。"""
if not terminal or not conversation_id:
return False
sub_agent_manager = getattr(terminal, "sub_agent_manager", None)
if sub_agent_manager:
try:
sub_agent_manager.reconcile_task_states(conversation_id=conversation_id)
for task_info in sub_agent_manager.tasks.values():
if task_info.get("conversation_id") != conversation_id:
continue
status = task_info.get("status")
if status not in SUB_AGENT_TERMINAL_STATUSES.union({"terminated"}):
return True
# 已完成但尚未发出通知,对话仍应视为运行中
if status in SUB_AGENT_TERMINAL_STATUSES and not task_info.get("notified"):
return True
except Exception:
pass
bg_manager = getattr(terminal, "background_command_manager", None)
if bg_manager:
try:
bg_manager.reconcile_stale_records(conversation_id=conversation_id)
if bg_manager.has_pending_for_conversation(conversation_id):
return True
except Exception:
pass
return False
def finalize_conversation_work_timer(
terminal: Any,
conversation_id: Optional[str],
*,
finished_at: Optional[str] = None,
exclude_task_id: Optional[str] = None,
active_task_ids: Optional[Set[str]] = None,
) -> bool:
"""当对话真正停止运行时,把 work_timer 持久化到后端并同步内存。
参数:
terminal: 当前终端实例,需携带 context_manager。
conversation_id: 要处理的对话 ID。
finished_at: 完成时间 ISO 字符串,默认当前时间。
exclude_task_id: 在判断「是否还有其它前台任务」时要排除的任务 ID。
active_task_ids: 当前仍活跃的前台任务 ID 集合。若提供且除 exclude_task_id
外仍有其它任务,则视为对话仍在运行,不做持久化。
"""
if not terminal or not conversation_id:
return False
# 1. 空闲判定:还有其它前台任务在跑?
if active_task_ids:
others = {tid for tid in active_task_ids if tid and tid != exclude_task_id}
if others:
return False
# 2. 空闲判定:还有后台工作?
if has_running_background_work(terminal, conversation_id):
return False
context_manager = getattr(terminal, "context_manager", None)
if not context_manager:
return False
cm = getattr(context_manager, "conversation_manager", None)
if not cm:
return False
now_iso = finished_at or datetime.now().isoformat()
# 3. 持久化到磁盘并同步内存副本
try:
return cm.mark_latest_user_work_completed(
conversation_id, now_iso, context_manager=context_manager
)
except Exception:
return False