feat: 添加父话题 ID 支持,优化子智能体任务管理和会话关联

This commit is contained in:
oudecheng 2026-05-20 18:11:16 +08:00
parent 49475783a2
commit 1c6ee160e5
8 changed files with 55 additions and 9 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ PicoBot.code-workspace
output output
.python-version .python-version
pyproject.toml pyproject.toml
uv.lock

View File

@ -53,7 +53,7 @@ pub async fn save_session_to_file(
// 加载子智能体消息(如果启用) // 加载子智能体消息(如果启用)
let subagent_data = if include_subagents { 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 { } else {
Vec::new() 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( pub async fn load_subagent_data(
parent_session_id: &str, parent_session_id: &str,
parent_topic_id: Option<&str>,
store: &SessionStore, store: &SessionStore,
task_repository: Option<&dyn TaskRepository>, task_repository: Option<&dyn TaskRepository>,
) -> Vec<SubagentTaskData> { ) -> Vec<SubagentTaskData> {
@ -247,13 +254,22 @@ pub async fn load_subagent_data(
return Vec::new(); return Vec::new();
}; };
// 获取所有子任务 // 获取子任务:如果提供了 topic_id则按 topic 查询;否则按 session 查询
let tasks = match repo.list_tasks_for_session(parent_session_id).await { 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, Ok(tasks) => tasks,
Err(e) => { Err(e) => {
tracing::warn!(error = %e, "Failed to list tasks for session"); tracing::warn!(error = %e, "Failed to list tasks for session");
return Vec::new(); return Vec::new();
} }
},
}; };
let mut result = Vec::new(); let mut result = Vec::new();

View File

@ -44,7 +44,7 @@ pub async fn save_topic_to_file(
// 加载子智能体消息(如果启用) // 加载子智能体消息(如果启用)
let subagent_data = if include_subagents { 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 { } else {
Vec::new() Vec::new()
}; };

View File

@ -69,6 +69,7 @@ impl AgentFactory {
sender_id: request.sender_id.map(str::to_string), sender_id: request.sender_id.map(str::to_string),
chat_id: Some(tool_chat_id.to_string()), chat_id: Some(tool_chat_id.to_string()),
session_id: Some(session_id), session_id: Some(session_id),
topic_id: None,
message_id: request.message_id.map(str::to_string), message_id: request.message_id.map(str::to_string),
message_seq: None, message_seq: None,
subagent_description: None, subagent_description: None,

View File

@ -25,6 +25,12 @@ pub trait TaskRepository: Send + Sync + 'static {
parent_session_id: &str, parent_session_id: &str,
) -> Result<Vec<TaskSession>, StorageError>; ) -> Result<Vec<TaskSession>, StorageError>;
/// 列出父话题的所有任务
async fn list_tasks_for_topic(
&self,
parent_topic_id: &str,
) -> Result<Vec<TaskSession>, StorageError>;
/// 清理过期任务(超过指定小时) /// 清理过期任务(超过指定小时)
async fn cleanup_expired_tasks(&self, ttl_hours: u64) -> Result<usize, StorageError>; async fn cleanup_expired_tasks(&self, ttl_hours: u64) -> Result<usize, StorageError>;
} }
@ -80,6 +86,20 @@ impl TaskRepository for InMemoryTaskRepository {
.collect()) .collect())
} }
async fn list_tasks_for_topic(
&self,
parent_topic_id: &str,
) -> Result<Vec<TaskSession>, 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<usize, StorageError> { async fn cleanup_expired_tasks(&self, ttl_hours: u64) -> Result<usize, StorageError> {
let now = current_timestamp(); let now = current_timestamp();
let ttl_millis = ttl_hours * 3600 * 1000; let ttl_millis = ttl_hours * 3600 * 1000;

View File

@ -149,6 +149,7 @@ impl DefaultSubAgentRuntime {
sender_id: None, sender_id: None,
chat_id: Some(session.parent_chat_id.clone()), // 使用父会话 chat_id chat_id: Some(session.parent_chat_id.clone()), // 使用父会话 chat_id
session_id: Some(session.session_id.clone()), // 子代理自己的 session_id session_id: Some(session.session_id.clone()), // 子代理自己的 session_id
topic_id: session.parent_topic_id.clone(), // 继承父话题 ID
message_id: None, message_id: None,
message_seq: None, message_seq: None,
subagent_description: Some(session.description.clone()), subagent_description: Some(session.description.clone()),
@ -282,8 +283,10 @@ impl SubAgentRuntime for DefaultSubAgentRuntime {
.ok_or_else(|| TaskError::MissingContext("channel_name".to_string()))?; .ok_or_else(|| TaskError::MissingContext("channel_name".to_string()))?;
// 2. 创建任务会话 // 2. 创建任务会话
let topic_id = parent_context.topic_id.clone();
let session = TaskSession::new( let session = TaskSession::new(
session_id, session_id,
topic_id,
chat_id, chat_id,
channel_name, channel_name,
task.description.clone(), task.description.clone(),

View File

@ -57,6 +57,8 @@ pub struct TaskSession {
pub session_id: String, pub session_id: String,
/// 父会话 ID (用于关联) /// 父会话 ID (用于关联)
pub parent_session_id: String, pub parent_session_id: String,
/// 父话题 ID (可选,用于关联)
pub parent_topic_id: Option<String>,
/// 父 chat_id /// 父 chat_id
pub parent_chat_id: String, pub parent_chat_id: String,
/// 父 channel_name /// 父 channel_name
@ -80,6 +82,7 @@ pub struct TaskSession {
impl TaskSession { impl TaskSession {
pub fn new( pub fn new(
parent_session_id: String, parent_session_id: String,
parent_topic_id: Option<String>,
parent_chat_id: String, parent_chat_id: String,
parent_channel_name: String, parent_channel_name: String,
description: String, description: String,
@ -92,6 +95,7 @@ impl TaskSession {
id, id,
session_id, session_id,
parent_session_id, parent_session_id,
parent_topic_id,
parent_chat_id, parent_chat_id,
parent_channel_name, parent_channel_name,
description, description,

View File

@ -13,6 +13,7 @@ pub struct ToolContext {
pub sender_id: Option<String>, pub sender_id: Option<String>,
pub chat_id: Option<String>, pub chat_id: Option<String>,
pub session_id: Option<String>, pub session_id: Option<String>,
pub topic_id: Option<String>,
pub message_id: Option<String>, pub message_id: Option<String>,
pub message_seq: Option<i64>, pub message_seq: Option<i64>,
/// 子代理标识,用于标注消息来源 /// 子代理标识,用于标注消息来源