From 8d530dcd6b63b71349ecbdfe2181bcb8a4cf3dcf Mon Sep 17 00:00:00 2001 From: oudecheng <13802883547@139.com> Date: Wed, 20 May 2026 17:21:14 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=A1=AE=E4=BF=9D?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E5=AD=98=E5=9C=A8=E7=9A=84=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=E5=AD=90=E6=99=BA=E8=83=BD=E4=BD=93?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/storage/mod.rs | 16 +++++++++++++--- src/storage/ports.rs | 19 +++++++++++++++++++ src/tools/task/runtime.rs | 32 +++++++++++++++++++++++++++----- 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/src/storage/mod.rs b/src/storage/mod.rs index f1831ae..2474a17 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -269,12 +269,22 @@ impl SessionStore { chat_id: &str, ) -> Result { let session_id = persistent_session_id(channel_name, chat_id); - if let Some(record) = self.get_session(&session_id)? { + self.ensure_session(&session_id, channel_name, chat_id, &format!("{}:{}", channel_name, chat_id)) + } + + /// 确保指定 session_id 的会话存在(如果不存在则创建) + pub fn ensure_session( + &self, + session_id: &str, + channel_name: &str, + chat_id: &str, + title: &str, + ) -> Result { + if let Some(record) = self.get_session(session_id)? { return Ok(record); } let now = current_timestamp(); - let title = format!("{}:{}", channel_name, chat_id); let conn = self.conn.lock().expect("session db mutex poisoned"); conn.execute( " @@ -288,7 +298,7 @@ impl SessionStore { )?; drop(conn); - self.get_session(&session_id)? + self.get_session(session_id)? .ok_or_else(|| rusqlite::Error::QueryReturnedNoRows.into()) } diff --git a/src/storage/ports.rs b/src/storage/ports.rs index 21a02e5..76a2c68 100644 --- a/src/storage/ports.rs +++ b/src/storage/ports.rs @@ -11,6 +11,15 @@ pub trait ConversationRepository: Send + Sync + 'static { chat_id: &str, ) -> Result; + /// 确保指定 session_id 的会话存在(如果不存在则创建) + fn ensure_session( + &self, + session_id: &str, + channel_name: &str, + chat_id: &str, + title: &str, + ) -> Result; + fn load_messages(&self, session_id: &str) -> Result, StorageError>; fn append_message(&self, session_id: &str, message: &ChatMessage) -> Result<(), StorageError>; @@ -139,6 +148,16 @@ impl ConversationRepository for super::SessionStore { super::SessionStore::ensure_channel_session(self, channel_name, chat_id) } + fn ensure_session( + &self, + session_id: &str, + channel_name: &str, + chat_id: &str, + title: &str, + ) -> Result { + super::SessionStore::ensure_session(self, session_id, channel_name, chat_id, title) + } + fn load_messages(&self, session_id: &str) -> Result, StorageError> { super::SessionStore::load_messages(self, session_id) } diff --git a/src/tools/task/runtime.rs b/src/tools/task/runtime.rs index 505f2e0..4e87395 100644 --- a/src/tools/task/runtime.rs +++ b/src/tools/task/runtime.rs @@ -290,7 +290,18 @@ impl SubAgentRuntime for DefaultSubAgentRuntime { task.subagent_type, ); - // 3. 保存会话 + // 3. 在 sessions 表中创建子智能体会话(确保外键约束满足) + let session_title = format!("Subagent: {}", task.description); + if let Err(e) = self.conversation_repository.ensure_session( + &session.session_id, + &session.parent_channel_name, + &session.parent_chat_id, + &session_title, + ) { + tracing::warn!(error = %e, session_id = %session.session_id, "Failed to ensure subagent session"); + } + + // 4. 保存任务会话 self.task_repository.save_task_session(&session).await?; // 4. 构建子代理系统提示词 @@ -354,21 +365,32 @@ impl SubAgentRuntime for DefaultSubAgentRuntime { return Err(TaskError::InvalidParentSession); } - // 3. 构建恢复提示词 + // 3. 确保 sessions 表中存在子智能体会话记录 + let session_title = format!("Subagent: {}", session.description); + if let Err(e) = self.conversation_repository.ensure_session( + &session.session_id, + &session.parent_channel_name, + &session.parent_chat_id, + &session_title, + ) { + tracing::warn!(error = %e, session_id = %session.session_id, "Failed to ensure subagent session on resume"); + } + + // 4. 构建恢复提示词 let system_prompt = SubagentPromptBuilder::build_resume_prompt( &session.description, &additional_prompt, ); - // 4. 创建子代理 + // 5. 创建子代理 let agent = self.create_subagent(&session, system_prompt)?; - // 5. 使用历史继续执行 + // 6. 使用历史继续执行 let result = self .execute_task_with_history(agent, &session, additional_prompt) .await; - // 6. 更新会话状态 + // 7. 更新会话状态 match result { Ok(tool_result) => { let mut session = session;