feat: 添加 session_id 支持到 OutboundMessage,优化会话管理
This commit is contained in:
parent
0095ace411
commit
025c0b5d7f
@ -251,7 +251,12 @@ impl InboundMessage {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OutboundMessage {
|
||||
pub channel: String,
|
||||
/// 消息发送目标 ID(如飞书 open_id、微信 chat_id)
|
||||
/// 注意:这始终是原始入站消息的 chat_id,不会被修改为会话 ID
|
||||
pub chat_id: String,
|
||||
/// 内部会话 ID(对应 sessions.id)
|
||||
/// 用于会话管理和消息持久化,与消息发送目标无关
|
||||
pub session_id: Option<String>,
|
||||
pub content: String,
|
||||
pub reply_to: Option<String>,
|
||||
pub media: Vec<MediaItem>,
|
||||
@ -281,6 +286,7 @@ impl OutboundMessage {
|
||||
pub fn assistant(
|
||||
channel: impl Into<String>,
|
||||
chat_id: impl Into<String>,
|
||||
session_id: Option<String>,
|
||||
content: impl Into<String>,
|
||||
reply_to: Option<String>,
|
||||
metadata: HashMap<String, String>,
|
||||
@ -288,6 +294,7 @@ impl OutboundMessage {
|
||||
Self {
|
||||
channel: channel.into(),
|
||||
chat_id: chat_id.into(),
|
||||
session_id,
|
||||
content: content.into(),
|
||||
reply_to,
|
||||
media: Vec::new(),
|
||||
@ -303,11 +310,12 @@ impl OutboundMessage {
|
||||
pub fn scheduler_notification(
|
||||
channel: impl Into<String>,
|
||||
chat_id: impl Into<String>,
|
||||
session_id: Option<String>,
|
||||
content: impl Into<String>,
|
||||
reply_to: Option<String>,
|
||||
metadata: HashMap<String, String>,
|
||||
) -> Self {
|
||||
let mut message = Self::assistant(channel, chat_id, content, reply_to, metadata);
|
||||
let mut message = Self::assistant(channel, chat_id, session_id, content, reply_to, metadata);
|
||||
message.event_kind = OutboundEventKind::SchedulerNotification;
|
||||
message
|
||||
}
|
||||
@ -315,11 +323,12 @@ impl OutboundMessage {
|
||||
pub fn error_notification(
|
||||
channel: impl Into<String>,
|
||||
chat_id: impl Into<String>,
|
||||
session_id: Option<String>,
|
||||
content: impl Into<String>,
|
||||
reply_to: Option<String>,
|
||||
metadata: HashMap<String, String>,
|
||||
) -> Self {
|
||||
let mut message = Self::assistant(channel, chat_id, content, reply_to, metadata);
|
||||
let mut message = Self::assistant(channel, chat_id, session_id, content, reply_to, metadata);
|
||||
message.event_kind = OutboundEventKind::ErrorNotification;
|
||||
message
|
||||
}
|
||||
@ -327,6 +336,7 @@ impl OutboundMessage {
|
||||
pub fn tool_call(
|
||||
channel: impl Into<String>,
|
||||
chat_id: impl Into<String>,
|
||||
session_id: Option<String>,
|
||||
message_id: impl Into<String>,
|
||||
tool_name: impl Into<String>,
|
||||
tool_arguments: serde_json::Value,
|
||||
@ -338,6 +348,7 @@ impl OutboundMessage {
|
||||
Self {
|
||||
channel: channel.into(),
|
||||
chat_id: chat_id.into(),
|
||||
session_id,
|
||||
content,
|
||||
reply_to,
|
||||
media: Vec::new(),
|
||||
@ -353,6 +364,7 @@ impl OutboundMessage {
|
||||
pub fn tool_result(
|
||||
channel: impl Into<String>,
|
||||
chat_id: impl Into<String>,
|
||||
session_id: Option<String>,
|
||||
tool_call_id: impl Into<String>,
|
||||
tool_name: impl Into<String>,
|
||||
content: impl Into<String>,
|
||||
@ -365,6 +377,7 @@ impl OutboundMessage {
|
||||
Self {
|
||||
channel: channel.into(),
|
||||
chat_id: chat_id.into(),
|
||||
session_id,
|
||||
content,
|
||||
reply_to,
|
||||
media: Vec::new(),
|
||||
@ -380,6 +393,7 @@ impl OutboundMessage {
|
||||
pub fn tool_pending(
|
||||
channel: impl Into<String>,
|
||||
chat_id: impl Into<String>,
|
||||
session_id: Option<String>,
|
||||
tool_call_id: impl Into<String>,
|
||||
tool_name: impl Into<String>,
|
||||
content: impl Into<String>,
|
||||
@ -392,6 +406,7 @@ impl OutboundMessage {
|
||||
Self {
|
||||
channel: channel.into(),
|
||||
chat_id: chat_id.into(),
|
||||
session_id,
|
||||
content,
|
||||
reply_to,
|
||||
media: Vec::new(),
|
||||
@ -407,6 +422,7 @@ impl OutboundMessage {
|
||||
pub fn from_chat_message(
|
||||
channel: &str,
|
||||
chat_id: &str,
|
||||
session_id: Option<String>,
|
||||
reply_to: Option<String>,
|
||||
metadata: &HashMap<String, String>,
|
||||
message: &ChatMessage,
|
||||
@ -419,6 +435,7 @@ impl OutboundMessage {
|
||||
outbound.push(Self::assistant(
|
||||
channel.to_string(),
|
||||
chat_id.to_string(),
|
||||
session_id.clone(),
|
||||
message.content.clone(),
|
||||
reply_to.clone(),
|
||||
metadata.clone(),
|
||||
@ -429,6 +446,7 @@ impl OutboundMessage {
|
||||
Self::tool_call(
|
||||
channel.to_string(),
|
||||
chat_id.to_string(),
|
||||
session_id.clone(),
|
||||
tool_call.id.clone(),
|
||||
tool_call.name.clone(),
|
||||
tool_call.arguments.clone(),
|
||||
@ -441,6 +459,7 @@ impl OutboundMessage {
|
||||
vec![Self::assistant(
|
||||
channel.to_string(),
|
||||
chat_id.to_string(),
|
||||
session_id,
|
||||
message.content.clone(),
|
||||
reply_to,
|
||||
metadata.clone(),
|
||||
@ -455,6 +474,7 @@ impl OutboundMessage {
|
||||
ToolMessageState::Completed => vec![Self::tool_result(
|
||||
channel.to_string(),
|
||||
chat_id.to_string(),
|
||||
session_id,
|
||||
message.tool_call_id.clone().unwrap_or_default(),
|
||||
message.tool_name.clone().unwrap_or_default(),
|
||||
message.content.clone(),
|
||||
@ -464,6 +484,7 @@ impl OutboundMessage {
|
||||
ToolMessageState::PendingUserAction => vec![Self::tool_pending(
|
||||
channel.to_string(),
|
||||
chat_id.to_string(),
|
||||
session_id,
|
||||
message.tool_call_id.clone().unwrap_or_default(),
|
||||
message.tool_name.clone().unwrap_or_default(),
|
||||
message.content.clone(),
|
||||
@ -562,6 +583,7 @@ mod tests {
|
||||
TEST_CHANNEL,
|
||||
"chat-1",
|
||||
None,
|
||||
None,
|
||||
&HashMap::new(),
|
||||
&message,
|
||||
);
|
||||
@ -599,6 +621,7 @@ mod tests {
|
||||
TEST_CHANNEL,
|
||||
"chat-1",
|
||||
None,
|
||||
None,
|
||||
&HashMap::new(),
|
||||
&message,
|
||||
);
|
||||
@ -618,6 +641,7 @@ mod tests {
|
||||
TEST_CHANNEL,
|
||||
"chat-1",
|
||||
None,
|
||||
None,
|
||||
&HashMap::new(),
|
||||
&message,
|
||||
);
|
||||
@ -639,6 +663,7 @@ mod tests {
|
||||
TEST_CHANNEL,
|
||||
"chat-1",
|
||||
None,
|
||||
None,
|
||||
&HashMap::new(),
|
||||
&message,
|
||||
);
|
||||
|
||||
@ -119,6 +119,7 @@ mod tests {
|
||||
.send(OutboundMessage::assistant(
|
||||
"cli",
|
||||
"session-1",
|
||||
None, // session_id
|
||||
"hello",
|
||||
None,
|
||||
HashMap::new(),
|
||||
@ -143,6 +144,7 @@ mod tests {
|
||||
.send(OutboundMessage::assistant(
|
||||
"cli",
|
||||
"session-1",
|
||||
None, // session_id
|
||||
"hello",
|
||||
None,
|
||||
HashMap::new(),
|
||||
|
||||
@ -114,6 +114,7 @@ impl AgentExecutionService {
|
||||
OutboundMessage::from_chat_message(
|
||||
request.channel_name,
|
||||
request.chat_id,
|
||||
None, // session_id
|
||||
None,
|
||||
request.metadata,
|
||||
message,
|
||||
|
||||
@ -125,32 +125,23 @@ impl InboundProcessor {
|
||||
let cmd_ctx = crate::command::context::CommandContext::new(&inbound.channel, &inbound.channel)
|
||||
.with_session_id(&inbound.chat_id);
|
||||
|
||||
// 记录是否是创建会话命令(用于后续自动切换)
|
||||
let is_create_session = matches!(cmd, Command::CreateSession { .. });
|
||||
// 记录是否是创建会话命令(用于后续处理)
|
||||
let _is_create_session = matches!(cmd, Command::CreateSession { .. });
|
||||
|
||||
let response = self.command_router.dispatch_with_response(cmd, cmd_ctx).await;
|
||||
|
||||
// 发送响应给用户
|
||||
if response.success {
|
||||
// 如果是创建会话,更新 chat_id 到新会话
|
||||
let target_chat_id = if let Some(session_id) = response.metadata.get("session_id") {
|
||||
if is_create_session {
|
||||
// 自动切换到新会话
|
||||
session_id.clone()
|
||||
} else {
|
||||
inbound.chat_id.clone()
|
||||
}
|
||||
} else {
|
||||
inbound.chat_id.clone()
|
||||
};
|
||||
|
||||
// 提取响应消息
|
||||
// chat_id 保持为 inbound.chat_id(飞书 open_id)
|
||||
// session_id 放入 metadata 用于会话管理
|
||||
for msg in &response.messages {
|
||||
if let Err(error) = self
|
||||
.bus
|
||||
.publish_outbound(OutboundMessage::assistant(
|
||||
inbound.channel.clone(),
|
||||
target_chat_id.clone(),
|
||||
inbound.chat_id.clone(),
|
||||
response.metadata.get("session_id").cloned(),
|
||||
msg.content.clone(),
|
||||
None,
|
||||
inbound.forwarded_metadata.clone(),
|
||||
@ -166,6 +157,7 @@ impl InboundProcessor {
|
||||
.publish_outbound(OutboundMessage::assistant(
|
||||
inbound.channel.clone(),
|
||||
inbound.chat_id.clone(),
|
||||
response.metadata.get("session_id").cloned(),
|
||||
format!("Error [{}]: {}", error.code, error.message),
|
||||
None,
|
||||
inbound.forwarded_metadata.clone(),
|
||||
@ -216,6 +208,7 @@ impl InboundProcessor {
|
||||
.publish_outbound(OutboundMessage::error_notification(
|
||||
inbound.channel,
|
||||
inbound.chat_id,
|
||||
None, // session_id
|
||||
error.to_string(),
|
||||
None,
|
||||
metadata,
|
||||
|
||||
@ -79,6 +79,7 @@ impl EmittedMessageHandler for BusToolCallEmitter {
|
||||
for outbound in OutboundMessage::from_chat_message(
|
||||
&self.channel_name,
|
||||
&self.chat_id,
|
||||
None, // session_id
|
||||
None,
|
||||
&self.metadata,
|
||||
&message,
|
||||
|
||||
@ -47,6 +47,7 @@ impl SessionMessageSender for BusSessionMessageSender {
|
||||
.publish_outbound(OutboundMessage::assistant(
|
||||
channel_name.to_string(),
|
||||
chat_id.to_string(),
|
||||
None, // session_id
|
||||
text,
|
||||
None,
|
||||
metadata.clone(),
|
||||
@ -68,6 +69,7 @@ impl SessionMessageSender for BusSessionMessageSender {
|
||||
let mut outbound = OutboundMessage::assistant(
|
||||
channel_name.to_string(),
|
||||
chat_id.to_string(),
|
||||
None, // session_id
|
||||
String::new(),
|
||||
None,
|
||||
metadata.clone(),
|
||||
|
||||
@ -201,6 +201,7 @@ mod tests {
|
||||
let message = OutboundMessage::tool_call(
|
||||
"cli",
|
||||
"session-1",
|
||||
None, // session_id
|
||||
"call-1",
|
||||
"calculator",
|
||||
json!({"expression": "1 + 1"}),
|
||||
|
||||
@ -409,6 +409,7 @@ impl Scheduler {
|
||||
.publish_outbound(OutboundMessage::error_notification(
|
||||
channel,
|
||||
chat_id,
|
||||
None, // session_id
|
||||
format!(
|
||||
"定时任务执行失败:{}\n{}",
|
||||
job.id,
|
||||
@ -904,6 +905,7 @@ fn build_outbound_message(job: &RuntimeJob) -> anyhow::Result<OutboundMessage> {
|
||||
Ok(OutboundMessage::scheduler_notification(
|
||||
channel,
|
||||
chat_id,
|
||||
None, // session_id
|
||||
content.to_string(),
|
||||
job.target.reply_to.clone(),
|
||||
metadata,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user