Compare commits
No commits in common. "fe4088cd1f3a9c498d6bb36daa94994ac2a9a093" and "e2fd8367946aa513c83bb1187034e4e48e2c0142" have entirely different histories.
fe4088cd1f
...
e2fd836794
@ -28,10 +28,6 @@ mod tests {
|
|||||||
assert_eq!(parse_slash_command("/reset"), Some(("reset", "")));
|
assert_eq!(parse_slash_command("/reset"), Some(("reset", "")));
|
||||||
assert_eq!(parse_slash_command("/reset arg"), Some(("reset", "arg")));
|
assert_eq!(parse_slash_command("/reset arg"), Some(("reset", "arg")));
|
||||||
assert_eq!(parse_slash_command("/new hello world"), Some(("new", "hello world")));
|
assert_eq!(parse_slash_command("/new hello world"), Some(("new", "hello world")));
|
||||||
assert_eq!(parse_slash_command("/??"), Some(("??", "")));
|
|
||||||
assert_eq!(parse_slash_command("/? arg"), Some(("?", "arg")));
|
|
||||||
assert_eq!(parse_slash_command("/?"), Some(("?", "")));
|
|
||||||
assert_eq!(parse_slash_command("/help"), Some(("help", "")));
|
|
||||||
assert_eq!(parse_slash_command("hello"), None);
|
assert_eq!(parse_slash_command("hello"), None);
|
||||||
assert_eq!(parse_slash_command("/"), Some(("", "")));
|
assert_eq!(parse_slash_command("/"), Some(("", "")));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -204,14 +204,6 @@ impl Session {
|
|||||||
}
|
}
|
||||||
self.last_active_at = now;
|
self.last_active_at = now;
|
||||||
|
|
||||||
// Sync message_count to Storage
|
|
||||||
if persist {
|
|
||||||
tracing::debug!(session_id = %self.id, last_active_at = %now, message_count = %self.message_count, "Persisting session meta after add_message");
|
|
||||||
if let Err(e) = self.persist_session_meta().await {
|
|
||||||
tracing::warn!("failed to persist session meta: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,9 +278,9 @@ impl Session {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 检查是否需要自动生成 title(5 条用户消息后)
|
/// 检查是否需要自动生成 title(10 条用户消息后)
|
||||||
pub fn should_generate_title(&self) -> bool {
|
pub fn should_generate_title(&self) -> bool {
|
||||||
self.title == "新对话" && self.message_count >= 5
|
self.title == "新对话" && self.message_count >= 10
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 生成标题(调用 LLM)
|
/// 生成标题(调用 LLM)
|
||||||
@ -637,11 +629,6 @@ pub static SLASH_COMMANDS: &[SlashCommand] = &[
|
|||||||
description: "保存当前对话为 markdown 文档",
|
description: "保存当前对话为 markdown 文档",
|
||||||
aliases: &["/dump"],
|
aliases: &["/dump"],
|
||||||
},
|
},
|
||||||
SlashCommand {
|
|
||||||
name: "?",
|
|
||||||
description: "显示帮助",
|
|
||||||
aliases: &["/?", "/help"],
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
impl SessionManager {
|
impl SessionManager {
|
||||||
@ -771,17 +758,9 @@ impl SessionManager {
|
|||||||
let session_guard = session.lock().await;
|
let session_guard = session.lock().await;
|
||||||
let message_count = session_guard.get_history().len();
|
let message_count = session_guard.get_history().len();
|
||||||
let session_id_str = session_guard.session_id();
|
let session_id_str = session_guard.session_id();
|
||||||
let title = &session_guard.title;
|
|
||||||
let model_name = &session_guard.provider_config.name;
|
|
||||||
let created_at = chrono::DateTime::from_timestamp_millis(session_guard.created_at)
|
|
||||||
.map(|dt| dt.format("%Y-%m-%d %H:%M:%S").to_string())
|
|
||||||
.unwrap_or_default();
|
|
||||||
let last_active_at = chrono::DateTime::from_timestamp_millis(session_guard.last_active_at)
|
|
||||||
.map(|dt| dt.format("%Y-%m-%d %H:%M:%S").to_string())
|
|
||||||
.unwrap_or_default();
|
|
||||||
Ok((None, format!(
|
Ok((None, format!(
|
||||||
"对话标题: {}\nSession ID: {}\n模型: {}\n用户消息: {} / 总消息: {}\n创建时间: {}\n最后活跃: {}",
|
"Session ID: {}\nMessage count: {}",
|
||||||
title, session_id_str, model_name, session_guard.message_count, message_count, created_at, last_active_at
|
session_id_str, message_count
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
Ok((None, "No active session.".to_string()))
|
Ok((None, "No active session.".to_string()))
|
||||||
@ -833,13 +812,7 @@ impl SessionManager {
|
|||||||
Ok((None, "No active session.".to_string()))
|
Ok((None, "No active session.".to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"?" | "help" => {
|
_ => Err(AgentError::Other(format!("Command not implemented: {}", cmd.name))),
|
||||||
let lines: Vec<String> = SLASH_COMMANDS.iter().map(|c| {
|
|
||||||
format!(" {} - {}", c.aliases.join(", "), c.description)
|
|
||||||
}).collect();
|
|
||||||
Ok((None, format!("可用命令:\n{}", lines.join("\n"))))
|
|
||||||
}
|
|
||||||
_ => Err(AgentError::Other(format!("未知命令:/{}。输入 /? 获取帮助。", cmd.name))),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -911,7 +884,6 @@ impl SessionManager {
|
|||||||
// Try to restore from Storage
|
// Try to restore from Storage
|
||||||
match self.storage.get_session(&session_id_str).await {
|
match self.storage.get_session(&session_id_str).await {
|
||||||
Ok(meta) => {
|
Ok(meta) => {
|
||||||
tracing::debug!(session_id = %session_id_str, last_active_at = %meta.last_active_at, message_count = %meta.message_count, "Restoring session from Storage");
|
|
||||||
let (user_tx, _rx) = mpsc::channel::<WsOutbound>(100);
|
let (user_tx, _rx) = mpsc::channel::<WsOutbound>(100);
|
||||||
let session = Session::from_storage(
|
let session = Session::from_storage(
|
||||||
unified_id.clone(),
|
unified_id.clone(),
|
||||||
@ -1091,14 +1063,11 @@ impl SessionManager {
|
|||||||
} else {
|
} else {
|
||||||
// No current session tracked, find active or create new
|
// No current session tracked, find active or create new
|
||||||
let ttl_millis = self.inner.lock().await.session_ttl.as_millis() as i64;
|
let ttl_millis = self.inner.lock().await.session_ttl.as_millis() as i64;
|
||||||
tracing::debug!(channel, chat_id, ttl_millis, "No current_sessions entry, searching Storage for active session");
|
|
||||||
match self.storage.find_active_session(channel, chat_id, ttl_millis).await {
|
match self.storage.find_active_session(channel, chat_id, ttl_millis).await {
|
||||||
Ok(Some(meta)) => {
|
Ok(Some(meta)) => {
|
||||||
tracing::debug!(session_id = %meta.id, dialog_id = %meta.dialog_id, last_active_at = %meta.last_active_at, "Found active session in Storage");
|
|
||||||
UnifiedSessionId::new(channel, chat_id, &meta.dialog_id)
|
UnifiedSessionId::new(channel, chat_id, &meta.dialog_id)
|
||||||
}
|
}
|
||||||
Ok(None) | Err(_) => {
|
Ok(None) | Err(_) => {
|
||||||
tracing::debug!("No active session found in Storage, creating new session");
|
|
||||||
// Create new session
|
// Create new session
|
||||||
let (new_id, _) = self.create_session(channel, chat_id, None, String::new()).await?;
|
let (new_id, _) = self.create_session(channel, chat_id, None, String::new()).await?;
|
||||||
new_id
|
new_id
|
||||||
@ -1106,28 +1075,29 @@ impl SessionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
tracing::debug!(unified_id = %unified_id, "handle_message resolved unified_id");
|
|
||||||
let session = self.get_or_create_session(&unified_id).await?;
|
let session = self.get_or_create_session(&unified_id).await?;
|
||||||
|
|
||||||
// Check for slash command
|
// Check for slash command
|
||||||
if let Some((cmd_name, cmd_args)) = parse_slash_command(content) {
|
if let Some((cmd_name, cmd_args)) = parse_slash_command(content) {
|
||||||
let result = self.execute_slash_command(
|
let (new_session_id, response) = self.execute_slash_command(
|
||||||
cmd_name,
|
cmd_name,
|
||||||
if cmd_args.is_empty() { None } else { Some(cmd_args) },
|
if cmd_args.is_empty() { None } else { Some(cmd_args) },
|
||||||
channel,
|
channel,
|
||||||
chat_id,
|
chat_id,
|
||||||
Some(&unified_id),
|
Some(&unified_id),
|
||||||
).await;
|
).await?;
|
||||||
|
|
||||||
|
// If a new session was created (e.g., /new, /delete), update the session binding
|
||||||
|
if let Some(new_id) = new_session_id {
|
||||||
|
// Update the session in the map with the new ID
|
||||||
|
let mut inner = self.inner.lock().await;
|
||||||
|
if let Some(old_session) = inner.sessions.remove(&unified_id.to_string()) {
|
||||||
|
inner.sessions.insert(new_id.to_string(), old_session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match result {
|
|
||||||
Ok((_new_session_id, response)) => {
|
|
||||||
return Ok(HandleResult::CommandOutput(response));
|
return Ok(HandleResult::CommandOutput(response));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
|
||||||
return Ok(HandleResult::CommandOutput(e.to_string()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normal message handling through LLM
|
// Normal message handling through LLM
|
||||||
let response: String = {
|
let response: String = {
|
||||||
@ -1165,13 +1135,6 @@ impl SessionManager {
|
|||||||
.map_err(|e| AgentError::Other(format!("persist error: {}", e)))?;
|
.map_err(|e| AgentError::Other(format!("persist error: {}", e)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we need to generate a title (after 10 user messages)
|
|
||||||
if session_guard.should_generate_title() {
|
|
||||||
if let Err(e) = session_guard.generate_title().await {
|
|
||||||
tracing::warn!("failed to generate title: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.final_response.content
|
result.final_response.content
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user