fix: 子智能体执行路径发布带 subagent_task_id 的完成/错误事件

在 runtime.rs 新增 build_subagent_event_metadata/publish_subagent_completion/publish_subagent_error 函数,在 spawn/resume 的 Ok/Err 分支发布带 subagent_task_id=session.id 的 ExecutionCompleted/ErrorNotification 事件。

load_task_messages.rs 的 reconstruct_task_from_db 硬编码 Completed 加 TODO 注释,记录 DB 重建无法可靠推断 task 状态的已知缺陷。

Spec: fix-subagent-message-refresh-on-exit (Task 1.4, 9)
This commit is contained in:
oudecheng 2026-07-06 18:11:12 +08:00
parent 61c2fca2a7
commit b4b7c5a208
2 changed files with 67 additions and 0 deletions

View File

@ -158,6 +158,8 @@ fn reconstruct_task_from_db(
parent_channel_name: record.channel_name.clone(),
description,
subagent_type,
// TODO: DB 重建时无法可靠推断 task 状态,暂硬编码为 Completed。
// 实际 failed/timeout 的子智能体会被错误显示为 completed需独立跟进。
state: TaskSessionState::Completed,
created_at: record.created_at,
updated_at: now,

View File

@ -279,6 +279,63 @@ impl SubAgentEmitter {
}
}
/// 构建子智能体事件的基础 metadata与 SubAgentEmitter 注入的字段保持一致。
fn build_subagent_event_metadata(session: &TaskSession) -> HashMap<String, String> {
let mut metadata = HashMap::new();
metadata.insert("subagent_task_id".to_string(), session.id.clone());
metadata.insert("is_subagent_event".to_string(), "true".to_string());
metadata.insert(
"topic_id".to_string(),
session.parent_topic_id.clone().unwrap_or_default(),
);
metadata
}
/// 发布子智能体执行完成事件ExecutionCompletedmetadata 含 subagent_task_id。
async fn publish_subagent_completion(
bus: &Option<Arc<MessageBus>>,
session: &TaskSession,
) {
if let Some(bus) = bus {
let metadata = build_subagent_event_metadata(session);
if let Err(e) = bus
.publish_outbound(OutboundMessage::execution_completed(
session.parent_channel_name.clone(),
session.parent_chat_id.clone(),
Some(session.parent_session_id.clone()),
metadata,
))
.await
{
tracing::warn!(error = %e, task_id = %session.id, "Failed to publish subagent execution_completed");
}
}
}
/// 发布子智能体执行错误事件ErrorNotificationmetadata 含 subagent_task_id。
async fn publish_subagent_error(
bus: &Option<Arc<MessageBus>>,
session: &TaskSession,
error_msg: &str,
) {
if let Some(bus) = bus {
let metadata = build_subagent_event_metadata(session);
if let Err(e) = bus
.publish_outbound(OutboundMessage::error_notification(
session.parent_channel_name.clone(),
session.parent_chat_id.clone(),
Some(session.parent_session_id.clone()),
error_msg.to_string(),
None,
metadata,
))
.await
{
tracing::warn!(error = %e, task_id = %session.id, "Failed to publish subagent error notification");
}
}
}
impl SystemPromptProvider for StaticSystemPromptProvider {
fn build(&self, _context: &SystemPromptContext) -> Option<SystemPrompt> {
Some(SystemPrompt {
@ -633,6 +690,8 @@ impl SubAgentRuntime for DefaultSubAgentRuntime {
"Task completed, updating session"
);
self.task_repository.save_task_session(&session).await?;
// 发布子智能体 ExecutionCompletedmetadata 注入 subagent_task_id 供前端路由到对应子智能体层
publish_subagent_completion(&self.bus, &session).await;
Ok(tool_result)
}
Err(e) => {
@ -651,6 +710,8 @@ impl SubAgentRuntime for DefaultSubAgentRuntime {
session.mark_failed(e.to_string());
}
self.task_repository.save_task_session(&session).await?;
// 发布子智能体 ErrorNotificationmetadata 注入 subagent_task_id 供前端路由到对应子智能体层
publish_subagent_error(&self.bus, &session, &e.to_string()).await;
Err(e)
}
}
@ -709,12 +770,16 @@ impl SubAgentRuntime for DefaultSubAgentRuntime {
let mut session = session;
session.mark_completed(tool_result.summary.clone());
self.task_repository.save_task_session(&session).await?;
// 发布子智能体 ExecutionCompletedmetadata 注入 subagent_task_id 供前端路由到对应子智能体层
publish_subagent_completion(&self.bus, &session).await;
Ok(tool_result)
}
Err(e) => {
let mut session = session;
session.mark_failed(e.to_string());
self.task_repository.save_task_session(&session).await?;
// 发布子智能体 ErrorNotificationmetadata 注入 subagent_task_id 供前端路由到对应子智能体层
publish_subagent_error(&self.bus, &session, &e.to_string()).await;
Err(e)
}
}