feat: 添加父话题 ID 支持,优化子智能体任务管理和会话关联
This commit is contained in:
parent
49475783a2
commit
1c6ee160e5
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,3 +13,4 @@ PicoBot.code-workspace
|
|||||||
output
|
output
|
||||||
.python-version
|
.python-version
|
||||||
pyproject.toml
|
pyproject.toml
|
||||||
|
uv.lock
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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()
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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(),
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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>,
|
||||||
/// 子代理标识,用于标注消息来源
|
/// 子代理标识,用于标注消息来源
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user