Compare commits

...

2 Commits

Author SHA1 Message Date
oudecheng
18ad891a51 feat(gateway): 补发运行中子智能体任务的TaskStarted事件
- 在加载话题历史消息时增加调用task_repository参数
- 查询该话题下所有运行中的子智能体任务
- 对每个运行中的任务补发TaskStarted事件
- 解决页面刷新后navigateToTaskId丢失的问题
- 增加错误处理及日志警告与信息输出
- 优化消息发送流程,避免子智能体消息混入
2026-06-18 19:07:26 +08:00
oudecheng
82eab7ad8d fix(useChat): 修复 task_started 事件过滤及日志输出
- 增加 task_started 消息的调试日志,输出 task_id、topic_id、parent_task_id 和当前选中的话题
- 对 topic_id 不匹配的 task_started 消息进行过滤,并打印日志提示
- 对带有 parent_task_id 的孙智能体 TaskStarted 消息进行过滤,避免回填主视图,并打印日志
- 在更新消息状态时添加日志,记录查找 task tool_call 消息的数量及索引
- 处理未找到匹配 task tool_call 的情况并打印对应日志
2026-06-18 17:50:44 +08:00
2 changed files with 46 additions and 4 deletions

View File

@ -27,6 +27,8 @@ use crate::command::handlers::switch_topic::SwitchTopicCommandHandler;
use crate::gateway::agent_prompt_provider::AgentPromptProvider;
use crate::protocol::{WsInbound, WsOutbound, MediaSummary, parse_inbound, serialize_outbound};
use crate::skills::SkillPromptProvider;
use crate::tools::task::repository::TaskRepository;
use crate::tools::task::types::TaskSessionState;
use axum::extract::State;
use axum::extract::ws::{Message as WsMessage, WebSocket, WebSocketUpgrade};
use axum::response::Response;
@ -482,7 +484,7 @@ async fn handle_inbound(
*current_topic_id = Some(topic_id.clone());
// 加载并发送该话题的历史消息
if let Err(e) = send_topic_history(&store, current_session_id, topic_id, sender).await {
if let Err(e) = send_topic_history(&store, current_session_id, topic_id, sender, &state.task_repository).await {
tracing::warn!(error = %e, topic_id = %topic_id, "Failed to send topic history");
}
}
@ -586,7 +588,7 @@ async fn handle_inbound(
if let Some(first_topic) = topics.first() {
let topic_id = first_topic.topic_id.clone();
*current_topic_id = Some(topic_id.clone());
if let Err(e) = send_topic_history(&store, current_session_id, &topic_id, sender).await {
if let Err(e) = send_topic_history(&store, current_session_id, &topic_id, sender, &state.task_repository).await {
tracing::warn!(error = %e, topic_id = %topic_id, "Failed to send initial topic history");
}
}
@ -641,6 +643,7 @@ async fn send_topic_history(
session_id: &str,
topic_id: &str,
sender: &mpsc::Sender<WsOutbound>,
task_repository: &Arc<dyn TaskRepository>,
) -> Result<(), Box<dyn std::error::Error>> {
// 加载话题消息,按 session_id 过滤,避免混入子智能体消息
let messages = store.load_messages_for_topic(topic_id, Some(session_id))?;
@ -654,6 +657,35 @@ async fn send_topic_history(
}
}
// 查询该话题下所有运行中的子智能体任务,补发 TaskStarted 事件
// 解决页面刷新后 navigateToTaskId 丢失的问题
let running_tasks = match task_repository.list_tasks_for_topic(topic_id).await {
Ok(tasks) => tasks,
Err(e) => {
tracing::warn!(error = %e, topic_id = %topic_id, "Failed to list tasks for topic");
return Ok(());
}
};
for task in running_tasks {
if task.state == TaskSessionState::Running {
tracing::info!(
task_id = %task.id,
description = %task.description,
"Re-sending TaskStarted for running task after topic history load"
);
let _ = sender
.send(WsOutbound::TaskStarted {
task_id: task.id.clone(),
description: task.description.clone(),
subagent_type: task.subagent_type.clone(),
topic_id: Some(topic_id.to_string()),
parent_task_id: None,
})
.await;
}
}
Ok(())
}

View File

@ -445,20 +445,30 @@ export function useChat(): UseChatReturn {
case 'task_started': {
const msg = message as TaskStarted
console.log('[useChat] task_started received:', { task_id: msg.task_id, topic_id: msg.topic_id, parent_task_id: msg.parent_task_id, selectedTopic: selectedTopicRef.current })
// 只 backfill 当前话题的 task tool_call避免跨话题串扰
if (msg.topic_id && msg.topic_id !== selectedTopicRef.current) break
if (msg.topic_id && msg.topic_id !== selectedTopicRef.current) {
console.log('[useChat] task_started filtered by topic_id')
break
}
// 孙智能体的 TaskStarted 不应 backfill 到主视图
if (msg.parent_task_id) break
if (msg.parent_task_id) {
console.log('[useChat] task_started filtered by parent_task_id')
break
}
// 设置 navigateToTaskId让用户可以点击查看实时进度
setMessages((prev) => {
console.log('[useChat] task_started searching messages for task tool_call, total messages:', prev.length)
for (let i = prev.length - 1; i >= 0; i--) {
if (prev[i].type === 'tool_call' && prev[i].toolName === 'task' && !prev[i].navigateToTaskId) {
console.log('[useChat] task_started SET navigateToTaskId at index', i, 'task_id:', msg.task_id)
const updated = [...prev]
updated[i] = { ...updated[i], navigateToTaskId: msg.task_id }
return updated
}
}
console.log('[useChat] task_started NO matching task tool_call found in messages')
return prev
})
break