From 1c6ee160e5ad336ece99a0ba396dd1ff4df28460 Mon Sep 17 00:00:00 2001 From: oudecheng <13802883547@139.com> Date: Wed, 20 May 2026 18:11:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=88=B6=E8=AF=9D?= =?UTF-8?q?=E9=A2=98=20ID=20=E6=94=AF=E6=8C=81=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=AD=90=E6=99=BA=E8=83=BD=E4=BD=93=E4=BB=BB=E5=8A=A1=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=92=8C=E4=BC=9A=E8=AF=9D=E5=85=B3=E8=81=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + src/command/handlers/save_session.rs | 32 +++++++++++++++++++++------- src/command/handlers/save_topic.rs | 2 +- src/gateway/agent_factory.rs | 1 + src/tools/task/repository.rs | 20 +++++++++++++++++ src/tools/task/runtime.rs | 3 +++ src/tools/task/types.rs | 4 ++++ src/tools/traits.rs | 1 + 8 files changed, 55 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 37c4580..889a2be 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ PicoBot.code-workspace output .python-version pyproject.toml +uv.lock diff --git a/src/command/handlers/save_session.rs b/src/command/handlers/save_session.rs index 4ceb4e5..2334e76 100644 --- a/src/command/handlers/save_session.rs +++ b/src/command/handlers/save_session.rs @@ -53,7 +53,7 @@ pub async fn save_session_to_file( // 加载子智能体消息(如果启用) let subagent_data = if include_subagents { - load_subagent_data(session_id, store, task_repository).await + load_subagent_data(session_id, None, store, task_repository).await } else { Vec::new() }; @@ -238,8 +238,15 @@ pub struct SubagentTaskData { } /// 加载子智能体数据 +/// +/// # Arguments +/// * `parent_session_id` - 父会话 ID +/// * `parent_topic_id` - 可选的父话题 ID,如果提供则只加载该话题下的子智能体 +/// * `store` - 会话存储 +/// * `task_repository` - 任务存储(可选) pub async fn load_subagent_data( parent_session_id: &str, + parent_topic_id: Option<&str>, store: &SessionStore, task_repository: Option<&dyn TaskRepository>, ) -> Vec { @@ -247,13 +254,22 @@ pub async fn load_subagent_data( return Vec::new(); }; - // 获取所有子任务 - let tasks = match repo.list_tasks_for_session(parent_session_id).await { - Ok(tasks) => tasks, - Err(e) => { - tracing::warn!(error = %e, "Failed to list tasks for session"); - return Vec::new(); - } + // 获取子任务:如果提供了 topic_id,则按 topic 查询;否则按 session 查询 + let tasks = match parent_topic_id { + Some(topic_id) => match repo.list_tasks_for_topic(topic_id).await { + Ok(tasks) => tasks, + Err(e) => { + tracing::warn!(error = %e, "Failed to list tasks for topic"); + return Vec::new(); + } + }, + None => match repo.list_tasks_for_session(parent_session_id).await { + Ok(tasks) => tasks, + Err(e) => { + tracing::warn!(error = %e, "Failed to list tasks for session"); + return Vec::new(); + } + }, }; let mut result = Vec::new(); diff --git a/src/command/handlers/save_topic.rs b/src/command/handlers/save_topic.rs index 9981eaf..9b28f85 100644 --- a/src/command/handlers/save_topic.rs +++ b/src/command/handlers/save_topic.rs @@ -44,7 +44,7 @@ pub async fn save_topic_to_file( // 加载子智能体消息(如果启用) let subagent_data = if include_subagents { - load_subagent_data(&topic.session_id, store, task_repository).await + load_subagent_data(&topic.session_id, Some(topic_id), store, task_repository).await } else { Vec::new() }; diff --git a/src/gateway/agent_factory.rs b/src/gateway/agent_factory.rs index 4f2e6aa..7d7c0ba 100644 --- a/src/gateway/agent_factory.rs +++ b/src/gateway/agent_factory.rs @@ -69,6 +69,7 @@ impl AgentFactory { sender_id: request.sender_id.map(str::to_string), chat_id: Some(tool_chat_id.to_string()), session_id: Some(session_id), + topic_id: None, message_id: request.message_id.map(str::to_string), message_seq: None, subagent_description: None, diff --git a/src/tools/task/repository.rs b/src/tools/task/repository.rs index e59a5a5..d3a9117 100644 --- a/src/tools/task/repository.rs +++ b/src/tools/task/repository.rs @@ -25,6 +25,12 @@ pub trait TaskRepository: Send + Sync + 'static { parent_session_id: &str, ) -> Result, StorageError>; + /// 列出父话题的所有任务 + async fn list_tasks_for_topic( + &self, + parent_topic_id: &str, + ) -> Result, StorageError>; + /// 清理过期任务(超过指定小时) async fn cleanup_expired_tasks(&self, ttl_hours: u64) -> Result; } @@ -80,6 +86,20 @@ impl TaskRepository for InMemoryTaskRepository { .collect()) } + async fn list_tasks_for_topic( + &self, + parent_topic_id: &str, + ) -> Result, StorageError> { + Ok(self + .sessions + .read() + .unwrap() + .values() + .filter(|s| s.parent_topic_id.as_ref() == Some(&parent_topic_id.to_string())) + .cloned() + .collect()) + } + async fn cleanup_expired_tasks(&self, ttl_hours: u64) -> Result { let now = current_timestamp(); let ttl_millis = ttl_hours * 3600 * 1000; diff --git a/src/tools/task/runtime.rs b/src/tools/task/runtime.rs index 4e87395..9fda713 100644 --- a/src/tools/task/runtime.rs +++ b/src/tools/task/runtime.rs @@ -149,6 +149,7 @@ impl DefaultSubAgentRuntime { sender_id: None, chat_id: Some(session.parent_chat_id.clone()), // 使用父会话 chat_id session_id: Some(session.session_id.clone()), // 子代理自己的 session_id + topic_id: session.parent_topic_id.clone(), // 继承父话题 ID message_id: None, message_seq: None, subagent_description: Some(session.description.clone()), @@ -282,8 +283,10 @@ impl SubAgentRuntime for DefaultSubAgentRuntime { .ok_or_else(|| TaskError::MissingContext("channel_name".to_string()))?; // 2. 创建任务会话 + let topic_id = parent_context.topic_id.clone(); let session = TaskSession::new( session_id, + topic_id, chat_id, channel_name, task.description.clone(), diff --git a/src/tools/task/types.rs b/src/tools/task/types.rs index 349ff79..838e13c 100644 --- a/src/tools/task/types.rs +++ b/src/tools/task/types.rs @@ -57,6 +57,8 @@ pub struct TaskSession { pub session_id: String, /// 父会话 ID (用于关联) pub parent_session_id: String, + /// 父话题 ID (可选,用于关联) + pub parent_topic_id: Option, /// 父 chat_id pub parent_chat_id: String, /// 父 channel_name @@ -80,6 +82,7 @@ pub struct TaskSession { impl TaskSession { pub fn new( parent_session_id: String, + parent_topic_id: Option, parent_chat_id: String, parent_channel_name: String, description: String, @@ -92,6 +95,7 @@ impl TaskSession { id, session_id, parent_session_id, + parent_topic_id, parent_chat_id, parent_channel_name, description, diff --git a/src/tools/traits.rs b/src/tools/traits.rs index ce36f27..5b7f589 100644 --- a/src/tools/traits.rs +++ b/src/tools/traits.rs @@ -13,6 +13,7 @@ pub struct ToolContext { pub sender_id: Option, pub chat_id: Option, pub session_id: Option, + pub topic_id: Option, pub message_id: Option, pub message_seq: Option, /// 子代理标识,用于标注消息来源