fix: enrich sub-agent results
This commit is contained in:
parent
ed82fc966e
commit
cd3f07bcc8
@ -328,6 +328,10 @@ class SubAgentManager:
|
||||
|
||||
task["status"] = status
|
||||
task["updated_at"] = time.time()
|
||||
elapsed_seconds = self._compute_elapsed_seconds(task)
|
||||
if status == "completed" and elapsed_seconds is not None:
|
||||
task["elapsed_seconds"] = elapsed_seconds
|
||||
task["runtime_seconds"] = elapsed_seconds
|
||||
|
||||
# 构建系统消息
|
||||
agent_id = task.get("agent_id")
|
||||
@ -340,6 +344,7 @@ class SubAgentManager:
|
||||
stats_summary=stats_summary,
|
||||
summary=summary,
|
||||
deliverables_dir=deliverables_dir,
|
||||
duration_seconds=elapsed_seconds,
|
||||
)
|
||||
elif status == "timeout":
|
||||
system_message = self._compose_sub_agent_message(
|
||||
@ -365,6 +370,9 @@ class SubAgentManager:
|
||||
"stats_summary": stats_summary,
|
||||
"system_message": system_message,
|
||||
}
|
||||
if status == "completed" and elapsed_seconds is not None:
|
||||
result["elapsed_seconds"] = elapsed_seconds
|
||||
result["runtime_seconds"] = elapsed_seconds
|
||||
task["final_result"] = result
|
||||
return result
|
||||
|
||||
@ -827,6 +835,11 @@ class SubAgentManager:
|
||||
copied_path = self._copy_deliverables_to_project(task, deliverables_dir)
|
||||
task["copied_path"] = str(copied_path)
|
||||
|
||||
elapsed_seconds = self._compute_elapsed_seconds(task)
|
||||
if elapsed_seconds is not None:
|
||||
task["elapsed_seconds"] = elapsed_seconds
|
||||
task["runtime_seconds"] = elapsed_seconds
|
||||
|
||||
system_message = self._build_system_message(task, status, copied_path, message)
|
||||
result = {
|
||||
"success": True,
|
||||
@ -840,6 +853,9 @@ class SubAgentManager:
|
||||
"system_message": system_message,
|
||||
"details": service_payload,
|
||||
}
|
||||
if elapsed_seconds is not None:
|
||||
result["elapsed_seconds"] = elapsed_seconds
|
||||
result["runtime_seconds"] = elapsed_seconds
|
||||
task["final_result"] = result
|
||||
return result
|
||||
|
||||
@ -896,7 +912,10 @@ class SubAgentManager:
|
||||
extra = (extra_message or "").strip()
|
||||
|
||||
if status == "completed" and copied_path:
|
||||
elapsed_seconds = self._compute_elapsed_seconds(task)
|
||||
msg = f"{prefix} 已完成,成果已复制到 {copied_path}。"
|
||||
if elapsed_seconds is not None:
|
||||
msg += f" 运行了{elapsed_seconds}秒。"
|
||||
if extra:
|
||||
msg += f" ({extra})"
|
||||
return msg
|
||||
@ -916,6 +935,18 @@ class SubAgentManager:
|
||||
except (TypeError, ValueError):
|
||||
return 0
|
||||
|
||||
@staticmethod
|
||||
def _compute_elapsed_seconds(task: Dict) -> Optional[int]:
|
||||
try:
|
||||
created_at = float(task.get("created_at") or 0)
|
||||
updated_at = float(task.get("updated_at") or time.time())
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
if created_at <= 0:
|
||||
return None
|
||||
elapsed = max(0.0, updated_at - created_at)
|
||||
return int(round(elapsed))
|
||||
|
||||
def _build_stats_summary(self, stats: Optional[Dict[str, Any]]) -> str:
|
||||
if not isinstance(stats, dict):
|
||||
stats = {}
|
||||
@ -946,10 +977,13 @@ class SubAgentManager:
|
||||
stats_summary: str,
|
||||
summary: str,
|
||||
deliverables_dir: Optional[str] = None,
|
||||
duration_seconds: Optional[int] = None,
|
||||
) -> str:
|
||||
parts = [prefix]
|
||||
if stats_summary:
|
||||
parts.append(stats_summary)
|
||||
if duration_seconds is not None:
|
||||
parts.append(f"运行了{duration_seconds}秒")
|
||||
if summary:
|
||||
parts.append(summary)
|
||||
if deliverables_dir:
|
||||
|
||||
@ -197,11 +197,18 @@ async def poll_sub_agent_completion(*, web_terminal, workspace, conversation_id,
|
||||
|
||||
# 构建 user 消息(后台完成时才发送)
|
||||
prefix = "这是一句系统自动发送的user消息,用于通知你子智能体已经运行完成"
|
||||
runtime_line = ""
|
||||
elapsed_seconds = update.get("runtime_seconds")
|
||||
if elapsed_seconds is None:
|
||||
elapsed_seconds = update.get("elapsed_seconds")
|
||||
if status == "completed" and isinstance(elapsed_seconds, (int, float)):
|
||||
runtime_line = f"\n\n运行了{int(round(elapsed_seconds))}秒"
|
||||
user_message = f"""{prefix}
|
||||
|
||||
子智能体{agent_id} ({summary}) 已完成任务。
|
||||
|
||||
{result_summary}
|
||||
{runtime_line}
|
||||
|
||||
交付目录:{deliverables_dir}"""
|
||||
|
||||
|
||||
@ -56,6 +56,9 @@ async def process_sub_agent_updates(*, messages: List[Dict], inline: bool = Fals
|
||||
updates = synthesized
|
||||
debug_log(f"[SubAgent] synthesized updates count={len(updates)}")
|
||||
|
||||
if inline and not hasattr(web_terminal, "_inline_sub_agent_notified"):
|
||||
web_terminal._inline_sub_agent_notified = set()
|
||||
|
||||
for update in updates:
|
||||
task_id = update.get("task_id")
|
||||
task_info = manager.tasks.get(task_id) if task_id else None
|
||||
@ -78,6 +81,12 @@ async def process_sub_agent_updates(*, messages: List[Dict], inline: bool = Fals
|
||||
debug_log(f"[SubAgent] update missing system_message: task={task_id} keys={list(update.keys())}")
|
||||
continue
|
||||
|
||||
if inline:
|
||||
inline_key = ("task", task_id) if task_id else ("msg", message)
|
||||
if inline_key in web_terminal._inline_sub_agent_notified:
|
||||
debug_log(f"[SubAgent] inline 通知已发送,跳过: key={inline_key}")
|
||||
continue
|
||||
|
||||
debug_log(f"[SubAgent] update task={task_id} inline={inline} msg={message}")
|
||||
|
||||
# 记录到对话历史(用于后续 build_messages 转换为 user 消息)
|
||||
@ -118,6 +127,8 @@ async def process_sub_agent_updates(*, messages: List[Dict], inline: bool = Fals
|
||||
"content": message,
|
||||
"metadata": {"sub_agent_notice": True, "inline": inline, "task_id": task_id}
|
||||
})
|
||||
if inline:
|
||||
web_terminal._inline_sub_agent_notified.add(inline_key)
|
||||
debug_log(f"[SubAgent] 插入子智能体通知位置: {insert_index} role={insert_role} after_tool_call_id={after_tool_call_id}")
|
||||
sender('system_message', {
|
||||
'content': message,
|
||||
|
||||
@ -56,38 +56,38 @@ const normalizeStatus = (status?: string) => {
|
||||
return status || 'running';
|
||||
};
|
||||
|
||||
const buildText = (entry: ActivityEntry, stateLabel: string) => {
|
||||
const buildText = (entry: ActivityEntry) => {
|
||||
const tool = entry.tool || '';
|
||||
const args = entry.args || {};
|
||||
if (tool === 'read_file') {
|
||||
const path = args.path || args.file_path || '';
|
||||
return `阅读 ${path} ${stateLabel}`;
|
||||
return `阅读 ${path}`;
|
||||
}
|
||||
if (tool === 'search_workspace') {
|
||||
const query = args.query || args.keyword || '';
|
||||
return `在工作区搜索 ${query} ${stateLabel}`;
|
||||
return `在工作区搜索 ${query}`;
|
||||
}
|
||||
if (tool === 'web_search') {
|
||||
const query = args.query || args.q || '';
|
||||
return `在互联网中搜索 ${query} ${stateLabel}`;
|
||||
return `在互联网中搜索 ${query}`;
|
||||
}
|
||||
if (tool === 'extract_webpage') {
|
||||
const url = args.url || '';
|
||||
return `在互联网中提取 ${url} ${stateLabel}`;
|
||||
return `在互联网中提取 ${url}`;
|
||||
}
|
||||
if (tool === 'run_command') {
|
||||
const command = args.command || '';
|
||||
return `运行命令 ${command} ${stateLabel}`;
|
||||
return `运行命令 ${command}`;
|
||||
}
|
||||
if (tool === 'edit_file') {
|
||||
const path = args.path || args.file_path || '';
|
||||
return `编辑 ${path} ${stateLabel}`;
|
||||
return `编辑 ${path}`;
|
||||
}
|
||||
if (tool === 'read_mediafile') {
|
||||
const path = args.path || args.file_path || '';
|
||||
return `读取媒体文件 ${path} ${stateLabel}`;
|
||||
return `读取媒体文件 ${path}`;
|
||||
}
|
||||
return `${tool || '工具'} ${stateLabel}`;
|
||||
return `${tool || '工具'}`;
|
||||
};
|
||||
|
||||
const displayItems = computed(() => {
|
||||
@ -112,7 +112,7 @@ const displayItems = computed(() => {
|
||||
key,
|
||||
state,
|
||||
stateLabel,
|
||||
text: buildText(item, stateLabel)
|
||||
text: buildText(item)
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@ -529,9 +529,14 @@ def _format_create_sub_agent(result_data: Dict[str, Any]) -> str:
|
||||
result_data.get("stats") or (result_data.get("final_result") or {}).get("stats")
|
||||
)
|
||||
summary = result_data.get("message") or result_data.get("summary")
|
||||
elapsed_seconds = result_data.get("runtime_seconds")
|
||||
if elapsed_seconds is None:
|
||||
elapsed_seconds = result_data.get("elapsed_seconds")
|
||||
lines = [header]
|
||||
if stats_text:
|
||||
lines.append(stats_text)
|
||||
if status == "completed" and isinstance(elapsed_seconds, (int, float)):
|
||||
lines.append(f"运行了{int(round(elapsed_seconds))}秒")
|
||||
if summary and status in {"completed", "failed", "timeout", "terminated"}:
|
||||
lines.append(str(summary))
|
||||
return "\n".join(lines)
|
||||
@ -541,7 +546,13 @@ def _format_wait_sub_agent(result_data: Dict[str, Any]) -> str:
|
||||
task_id = result_data.get("task_id")
|
||||
agent_id = result_data.get("agent_id")
|
||||
status = result_data.get("status")
|
||||
stats_text = _format_sub_agent_stats(result_data.get("stats"))
|
||||
stats_value = result_data.get("stats")
|
||||
if not isinstance(stats_value, dict) and status == "timeout":
|
||||
stats_value = {}
|
||||
stats_text = _format_sub_agent_stats(stats_value)
|
||||
elapsed_seconds = result_data.get("runtime_seconds")
|
||||
if elapsed_seconds is None:
|
||||
elapsed_seconds = result_data.get("elapsed_seconds")
|
||||
if result_data.get("success"):
|
||||
copied_path = result_data.get("copied_path") or result_data.get("deliverables_path")
|
||||
message = result_data.get("message") or "子智能体任务已完成。"
|
||||
@ -549,6 +560,8 @@ def _format_wait_sub_agent(result_data: Dict[str, Any]) -> str:
|
||||
lines = [f"子智能体 #{agent_id}/{task_id} 完成"]
|
||||
if stats_text:
|
||||
lines.append(stats_text)
|
||||
if isinstance(elapsed_seconds, (int, float)):
|
||||
lines.append(f"运行了{int(round(elapsed_seconds))}秒")
|
||||
lines.append(message)
|
||||
lines.append(deliver_note)
|
||||
return "\n".join(lines)
|
||||
@ -575,14 +588,20 @@ def _format_get_sub_agent_status(result_data: Dict[str, Any]) -> str:
|
||||
status = item.get("status")
|
||||
summary = None
|
||||
final_result = item.get("final_result") or {}
|
||||
elapsed_seconds = None
|
||||
if isinstance(final_result, dict):
|
||||
summary = final_result.get("message") or final_result.get("summary")
|
||||
elapsed_seconds = final_result.get("runtime_seconds")
|
||||
if elapsed_seconds is None:
|
||||
elapsed_seconds = final_result.get("elapsed_seconds")
|
||||
if not summary:
|
||||
summary = item.get("summary") or ""
|
||||
stats_text = _format_sub_agent_stats(item.get("stats"))
|
||||
lines = [f"子智能体 #{agent_id} 状态: {status}"]
|
||||
if stats_text:
|
||||
lines.append(stats_text)
|
||||
if status == "completed" and isinstance(elapsed_seconds, (int, float)):
|
||||
lines.append(f"运行了{int(round(elapsed_seconds))}秒")
|
||||
if summary:
|
||||
lines.append(str(summary))
|
||||
blocks.append("\n".join(lines))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user