feat: 添加会话查询命令处理器,支持列出和加载会话功能
This commit is contained in:
parent
b77fc93d71
commit
5eb9a26843
@ -69,119 +69,3 @@ impl InputAdapter for ChannelInputAdapter {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_channel_adapter_new_without_title() {
|
|
||||||
let adapter = ChannelInputAdapter::new();
|
|
||||||
let ctx = AdapterContext::new("channel");
|
|
||||||
|
|
||||||
let result = adapter.try_parse("/new", ctx).unwrap();
|
|
||||||
|
|
||||||
assert!(result.is_some());
|
|
||||||
let cmd = result.unwrap();
|
|
||||||
assert!(matches!(cmd, Command::CreateSession { title: None }));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_channel_adapter_new_with_title() {
|
|
||||||
let adapter = ChannelInputAdapter::new();
|
|
||||||
let ctx = AdapterContext::new("channel");
|
|
||||||
|
|
||||||
let result = adapter.try_parse("/new planning session", ctx).unwrap();
|
|
||||||
|
|
||||||
assert!(result.is_some());
|
|
||||||
let cmd = result.unwrap();
|
|
||||||
assert!(matches!(
|
|
||||||
cmd,
|
|
||||||
Command::CreateSession {
|
|
||||||
title: Some(ref t)
|
|
||||||
} if t == "planning session"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_channel_adapter_save_without_path() {
|
|
||||||
let adapter = ChannelInputAdapter::new();
|
|
||||||
let ctx = AdapterContext::new("channel");
|
|
||||||
|
|
||||||
let result = adapter.try_parse("/save", ctx).unwrap();
|
|
||||||
|
|
||||||
assert!(result.is_some());
|
|
||||||
let cmd = result.unwrap();
|
|
||||||
assert!(matches!(
|
|
||||||
cmd,
|
|
||||||
Command::SaveSession {
|
|
||||||
filepath: None,
|
|
||||||
include_all: false,
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_channel_adapter_save_with_path() {
|
|
||||||
let adapter = ChannelInputAdapter::new();
|
|
||||||
let ctx = AdapterContext::new("channel");
|
|
||||||
|
|
||||||
let result = adapter.try_parse("/save ./session.md", ctx).unwrap();
|
|
||||||
|
|
||||||
assert!(result.is_some());
|
|
||||||
let cmd = result.unwrap();
|
|
||||||
assert!(matches!(
|
|
||||||
cmd,
|
|
||||||
Command::SaveSession {
|
|
||||||
filepath: Some(ref p),
|
|
||||||
include_all: false,
|
|
||||||
} if p == "./session.md"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_channel_adapter_save_all() {
|
|
||||||
let adapter = ChannelInputAdapter::new();
|
|
||||||
let ctx = AdapterContext::new("channel");
|
|
||||||
|
|
||||||
let result = adapter.try_parse("/save all", ctx).unwrap();
|
|
||||||
|
|
||||||
assert!(result.is_some());
|
|
||||||
let cmd = result.unwrap();
|
|
||||||
assert!(matches!(
|
|
||||||
cmd,
|
|
||||||
Command::SaveSession {
|
|
||||||
filepath: None,
|
|
||||||
include_all: true,
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_channel_adapter_save_all_with_path() {
|
|
||||||
let adapter = ChannelInputAdapter::new();
|
|
||||||
let ctx = AdapterContext::new("channel");
|
|
||||||
|
|
||||||
let result = adapter.try_parse("/save all ./session.md", ctx).unwrap();
|
|
||||||
|
|
||||||
assert!(result.is_some());
|
|
||||||
let cmd = result.unwrap();
|
|
||||||
assert!(matches!(
|
|
||||||
cmd,
|
|
||||||
Command::SaveSession {
|
|
||||||
filepath: Some(ref p),
|
|
||||||
include_all: true,
|
|
||||||
} if p == "./session.md"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_channel_adapter_not_command() {
|
|
||||||
let adapter = ChannelInputAdapter::new();
|
|
||||||
let ctx = AdapterContext::new("channel");
|
|
||||||
|
|
||||||
let result = adapter.try_parse("hello world", ctx).unwrap();
|
|
||||||
|
|
||||||
assert!(result.is_none());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -12,18 +12,21 @@ pub struct CommandContext {
|
|||||||
pub chat_id: Option<String>,
|
pub chat_id: Option<String>,
|
||||||
/// 发送者ID
|
/// 发送者ID
|
||||||
pub sender_id: String,
|
pub sender_id: String,
|
||||||
|
/// 通道名称(如 "cli", "feishu", "wechat")
|
||||||
|
pub channel_name: String,
|
||||||
/// 额外元数据
|
/// 额外元数据
|
||||||
pub metadata: HashMap<String, String>,
|
pub metadata: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandContext {
|
impl CommandContext {
|
||||||
/// 创建新的命令上下文
|
/// 创建新的命令上下文
|
||||||
pub fn new(sender_id: impl Into<String>) -> Self {
|
pub fn new(sender_id: impl Into<String>, channel_name: impl Into<String>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
request_id: Uuid::new_v4(),
|
request_id: Uuid::new_v4(),
|
||||||
session_id: None,
|
session_id: None,
|
||||||
chat_id: None,
|
chat_id: None,
|
||||||
sender_id: sender_id.into(),
|
sender_id: sender_id.into(),
|
||||||
|
channel_name: channel_name.into(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -238,7 +238,7 @@ mod tests {
|
|||||||
router.register(Box::new(TestHandler));
|
router.register(Box::new(TestHandler));
|
||||||
router.register(Box::new(NoOpHandler));
|
router.register(Box::new(NoOpHandler));
|
||||||
|
|
||||||
let ctx = CommandContext::new("test");
|
let ctx = CommandContext::new("test", "test");
|
||||||
let cmd = Command::CreateSession { title: None };
|
let cmd = Command::CreateSession { title: None };
|
||||||
|
|
||||||
let result = router.dispatch(cmd, ctx).await;
|
let result = router.dispatch(cmd, ctx).await;
|
||||||
@ -252,7 +252,7 @@ mod tests {
|
|||||||
async fn test_router_no_handler() {
|
async fn test_router_no_handler() {
|
||||||
let router = CommandRouter::new();
|
let router = CommandRouter::new();
|
||||||
|
|
||||||
let ctx = CommandContext::new("test");
|
let ctx = CommandContext::new("test", "test");
|
||||||
let cmd = Command::CreateSession { title: None };
|
let cmd = Command::CreateSession { title: None };
|
||||||
|
|
||||||
let result = router.dispatch(cmd, ctx).await;
|
let result = router.dispatch(cmd, ctx).await;
|
||||||
|
|||||||
@ -48,7 +48,7 @@ async fn handle_create_session(
|
|||||||
) -> Result<CommandResponse, CommandError> {
|
) -> Result<CommandResponse, CommandError> {
|
||||||
let record = handler
|
let record = handler
|
||||||
.cli_sessions
|
.cli_sessions
|
||||||
.create(title.as_deref())
|
.create_with_channel(&ctx.channel_name, title.as_deref())
|
||||||
.map_err(|e| CommandError::new("CREATE_SESSION_ERROR", e.to_string()))?;
|
.map_err(|e| CommandError::new("CREATE_SESSION_ERROR", e.to_string()))?;
|
||||||
|
|
||||||
Ok(CommandResponse::success(ctx.request_id)
|
Ok(CommandResponse::success(ctx.request_id)
|
||||||
@ -74,7 +74,7 @@ mod tests {
|
|||||||
async fn test_create_session_with_title() {
|
async fn test_create_session_with_title() {
|
||||||
let service = create_test_service();
|
let service = create_test_service();
|
||||||
let handler = SessionCommandHandler::new(service);
|
let handler = SessionCommandHandler::new(service);
|
||||||
let ctx = CommandContext::new("test");
|
let ctx = CommandContext::new("test", "test");
|
||||||
let cmd = Command::CreateSession {
|
let cmd = Command::CreateSession {
|
||||||
title: Some("my session".to_string()),
|
title: Some("my session".to_string()),
|
||||||
};
|
};
|
||||||
@ -93,7 +93,7 @@ mod tests {
|
|||||||
async fn test_create_session_without_title() {
|
async fn test_create_session_without_title() {
|
||||||
let service = create_test_service();
|
let service = create_test_service();
|
||||||
let handler = SessionCommandHandler::new(service);
|
let handler = SessionCommandHandler::new(service);
|
||||||
let ctx = CommandContext::new("test");
|
let ctx = CommandContext::new("test", "test");
|
||||||
let cmd = Command::CreateSession { title: None };
|
let cmd = Command::CreateSession { title: None };
|
||||||
|
|
||||||
let result = handler.handle(cmd, ctx).await;
|
let result = handler.handle(cmd, ctx).await;
|
||||||
|
|||||||
188
src/command/handlers/session_query.rs
Normal file
188
src/command/handlers/session_query.rs
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
use crate::command::context::CommandContext;
|
||||||
|
use crate::command::handler::CommandHandler;
|
||||||
|
use crate::command::response::{CommandError, CommandResponse, MessageKind};
|
||||||
|
use crate::command::Command;
|
||||||
|
use crate::gateway::cli_session::CliSessionService;
|
||||||
|
use crate::protocol::SessionSummary;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
/// 会话查询命令处理器
|
||||||
|
///
|
||||||
|
/// 处理 ListSessions 和 LoadSession 命令
|
||||||
|
pub struct SessionQueryCommandHandler {
|
||||||
|
cli_sessions: CliSessionService,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SessionQueryCommandHandler {
|
||||||
|
/// 创建新的会话查询命令处理器
|
||||||
|
pub fn new(cli_sessions: CliSessionService) -> Self {
|
||||||
|
Self { cli_sessions }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl CommandHandler for SessionQueryCommandHandler {
|
||||||
|
fn can_handle(&self, cmd: &Command) -> bool {
|
||||||
|
matches!(cmd, Command::ListSessions { .. } | Command::LoadSession { .. })
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle(
|
||||||
|
&self,
|
||||||
|
cmd: Command,
|
||||||
|
ctx: CommandContext,
|
||||||
|
) -> Result<CommandResponse, CommandError> {
|
||||||
|
match cmd {
|
||||||
|
Command::ListSessions { include_archived } => {
|
||||||
|
handle_list_sessions(self, include_archived, ctx).await
|
||||||
|
}
|
||||||
|
Command::LoadSession { session_id } => {
|
||||||
|
handle_load_session(self, session_id, ctx).await
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 处理列出会话命令
|
||||||
|
async fn handle_list_sessions(
|
||||||
|
handler: &SessionQueryCommandHandler,
|
||||||
|
include_archived: bool,
|
||||||
|
ctx: CommandContext,
|
||||||
|
) -> Result<CommandResponse, CommandError> {
|
||||||
|
let records = handler
|
||||||
|
.cli_sessions
|
||||||
|
.list(include_archived)
|
||||||
|
.map_err(|e| CommandError::new("LIST_SESSIONS_ERROR", e.to_string()))?;
|
||||||
|
|
||||||
|
let summaries: Vec<SessionSummary> = records
|
||||||
|
.into_iter()
|
||||||
|
.map(|r| SessionSummary {
|
||||||
|
session_id: r.id,
|
||||||
|
title: r.title,
|
||||||
|
channel_name: r.channel_name,
|
||||||
|
chat_id: r.chat_id,
|
||||||
|
message_count: r.message_count,
|
||||||
|
last_active_at: r.last_active_at,
|
||||||
|
archived_at: r.archived_at,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// 将会话列表序列化为 JSON 存储在 metadata 中
|
||||||
|
let sessions_json =
|
||||||
|
serde_json::to_string(&summaries).map_err(|e| CommandError::new("SERIALIZE_ERROR", e.to_string()))?;
|
||||||
|
|
||||||
|
let message = if summaries.is_empty() {
|
||||||
|
"No sessions found.".to_string()
|
||||||
|
} else {
|
||||||
|
format!("Found {} session(s)", summaries.len())
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(CommandResponse::success(ctx.request_id)
|
||||||
|
.with_message(MessageKind::Notification, &message)
|
||||||
|
.with_metadata("sessions", &sessions_json)
|
||||||
|
.with_metadata("count", &summaries.len().to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 处理加载会话命令
|
||||||
|
async fn handle_load_session(
|
||||||
|
handler: &SessionQueryCommandHandler,
|
||||||
|
session_id: String,
|
||||||
|
ctx: CommandContext,
|
||||||
|
) -> Result<CommandResponse, CommandError> {
|
||||||
|
let record = handler
|
||||||
|
.cli_sessions
|
||||||
|
.get(&session_id)
|
||||||
|
.map_err(|e| CommandError::new("LOAD_SESSION_ERROR", e.to_string()))?
|
||||||
|
.ok_or_else(|| CommandError::new("SESSION_NOT_FOUND", format!("Session not found: {}", session_id)))?;
|
||||||
|
|
||||||
|
Ok(CommandResponse::success(ctx.request_id)
|
||||||
|
.with_message(MessageKind::Notification, &record.title)
|
||||||
|
.with_metadata("session_id", &record.id)
|
||||||
|
.with_metadata("title", &record.title)
|
||||||
|
.with_metadata("message_count", &record.message_count.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::storage::SessionStore;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
fn create_test_service() -> CliSessionService {
|
||||||
|
let store = Arc::new(SessionStore::in_memory().unwrap());
|
||||||
|
CliSessionService::new(store)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_list_sessions_empty() {
|
||||||
|
let service = create_test_service();
|
||||||
|
let handler = SessionQueryCommandHandler::new(service);
|
||||||
|
let ctx = CommandContext::new("test");
|
||||||
|
let cmd = Command::ListSessions {
|
||||||
|
include_archived: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = handler.handle(cmd, ctx).await;
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
let resp = result.unwrap();
|
||||||
|
assert!(resp.success);
|
||||||
|
assert!(resp.messages[0].content.contains("No sessions"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_list_sessions_with_items() {
|
||||||
|
let service = create_test_service();
|
||||||
|
let handler = SessionQueryCommandHandler::new(service.clone());
|
||||||
|
|
||||||
|
// 创建一些会话
|
||||||
|
service.create(Some("test session")).unwrap();
|
||||||
|
|
||||||
|
let ctx = CommandContext::new("test");
|
||||||
|
let cmd = Command::ListSessions {
|
||||||
|
include_archived: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = handler.handle(cmd, ctx).await;
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
let resp = result.unwrap();
|
||||||
|
assert!(resp.success);
|
||||||
|
assert!(resp.metadata.contains_key("sessions"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_load_session_not_found() {
|
||||||
|
let service = create_test_service();
|
||||||
|
let handler = SessionQueryCommandHandler::new(service);
|
||||||
|
let ctx = CommandContext::new("test");
|
||||||
|
let cmd = Command::LoadSession {
|
||||||
|
session_id: "nonexistent".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = handler.handle(cmd, ctx).await;
|
||||||
|
|
||||||
|
assert!(result.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_load_session_success() {
|
||||||
|
let service = create_test_service();
|
||||||
|
let handler = SessionQueryCommandHandler::new(service.clone());
|
||||||
|
|
||||||
|
// 创建会话
|
||||||
|
let record = service.create(Some("test session")).unwrap();
|
||||||
|
|
||||||
|
let ctx = CommandContext::new("test");
|
||||||
|
let cmd = Command::LoadSession {
|
||||||
|
session_id: record.id.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = handler.handle(cmd, ctx).await;
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
let resp = result.unwrap();
|
||||||
|
assert!(resp.success);
|
||||||
|
assert_eq!(resp.metadata.get("session_id").unwrap(), &record.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,6 +19,17 @@ impl CliSessionService {
|
|||||||
.map_err(|err| AgentError::Other(format!("create session error: {}", err)))
|
.map_err(|err| AgentError::Other(format!("create session error: {}", err)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 创建指定通道的会话
|
||||||
|
pub(crate) fn create_with_channel(
|
||||||
|
&self,
|
||||||
|
channel_name: &str,
|
||||||
|
title: Option<&str>,
|
||||||
|
) -> Result<SessionRecord, AgentError> {
|
||||||
|
self.store
|
||||||
|
.create_session(channel_name, title)
|
||||||
|
.map_err(|err| AgentError::Other(format!("create session error: {}", err)))
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn get(&self, session_id: &str) -> Result<Option<SessionRecord>, AgentError> {
|
pub(crate) fn get(&self, session_id: &str) -> Result<Option<SessionRecord>, AgentError> {
|
||||||
self.store
|
self.store
|
||||||
.get_session(session_id)
|
.get_session(session_id)
|
||||||
|
|||||||
@ -117,7 +117,7 @@ impl InboundProcessor {
|
|||||||
|
|
||||||
if let Ok(Some(cmd)) = adapter.try_parse(&inbound.content, ctx) {
|
if let Ok(Some(cmd)) = adapter.try_parse(&inbound.content, ctx) {
|
||||||
// 使用命令路由器处理
|
// 使用命令路由器处理
|
||||||
let cmd_ctx = crate::command::context::CommandContext::new(&inbound.channel)
|
let cmd_ctx = crate::command::context::CommandContext::new(&inbound.channel, &inbound.channel)
|
||||||
.with_session_id(&inbound.chat_id);
|
.with_session_id(&inbound.chat_id);
|
||||||
|
|
||||||
let response = self.command_router.dispatch_with_response(cmd, cmd_ctx).await;
|
let response = self.command_router.dispatch_with_response(cmd, cmd_ctx).await;
|
||||||
|
|||||||
@ -227,7 +227,7 @@ async fn handle_inbound(
|
|||||||
)));
|
)));
|
||||||
|
|
||||||
// 构建命令上下文
|
// 构建命令上下文
|
||||||
let cmd_ctx = CommandContext::new("websocket")
|
let cmd_ctx = CommandContext::new("websocket", "cli")
|
||||||
.with_session_id(current_session_id.as_str());
|
.with_session_id(current_session_id.as_str());
|
||||||
|
|
||||||
// 执行命令
|
// 执行命令
|
||||||
|
|||||||
@ -76,6 +76,18 @@ pub enum WsOutbound {
|
|||||||
SessionEstablished { session_id: String },
|
SessionEstablished { session_id: String },
|
||||||
#[serde(rename = "session_created")]
|
#[serde(rename = "session_created")]
|
||||||
SessionCreated { session_id: String, title: String },
|
SessionCreated { session_id: String, title: String },
|
||||||
|
#[serde(rename = "session_list")]
|
||||||
|
SessionList {
|
||||||
|
sessions: Vec<SessionSummary>,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
current_session_id: Option<String>,
|
||||||
|
},
|
||||||
|
#[serde(rename = "session_loaded")]
|
||||||
|
SessionLoaded {
|
||||||
|
session_id: String,
|
||||||
|
title: String,
|
||||||
|
message_count: i64,
|
||||||
|
},
|
||||||
#[serde(rename = "session_saved")]
|
#[serde(rename = "session_saved")]
|
||||||
SessionSaved { session_id: String, filepath: String },
|
SessionSaved { session_id: String, filepath: String },
|
||||||
#[serde(rename = "pong")]
|
#[serde(rename = "pong")]
|
||||||
|
|||||||
@ -204,14 +204,24 @@ impl SessionStore {
|
|||||||
Self::from_connection(Connection::open_in_memory()?)
|
Self::from_connection(Connection::open_in_memory()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_cli_session(&self, title: Option<&str>) -> Result<SessionRecord, StorageError> {
|
pub fn create_session(
|
||||||
|
&self,
|
||||||
|
channel_name: &str,
|
||||||
|
title: Option<&str>,
|
||||||
|
) -> Result<SessionRecord, StorageError> {
|
||||||
let now = current_timestamp();
|
let now = current_timestamp();
|
||||||
let id = uuid::Uuid::new_v4().to_string();
|
let id = uuid::Uuid::new_v4().to_string();
|
||||||
let title = title
|
let title = title
|
||||||
.map(str::trim)
|
.map(str::trim)
|
||||||
.filter(|value| !value.is_empty())
|
.filter(|value| !value.is_empty())
|
||||||
.map(ToOwned::to_owned)
|
.map(ToOwned::to_owned)
|
||||||
.unwrap_or_else(|| format!("CLI Session {}", &id[..8]));
|
.unwrap_or_else(|| {
|
||||||
|
if channel_name == "cli" {
|
||||||
|
format!("CLI Session {}", &id[..8])
|
||||||
|
} else {
|
||||||
|
format!("Session {}", &id[..8])
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let conn = self.conn.lock().expect("session db mutex poisoned");
|
let conn = self.conn.lock().expect("session db mutex poisoned");
|
||||||
conn.execute(
|
conn.execute(
|
||||||
@ -220,9 +230,9 @@ impl SessionStore {
|
|||||||
id, title, channel_name, chat_id, summary,
|
id, title, channel_name, chat_id, summary,
|
||||||
created_at, updated_at, last_active_at, archived_at, deleted_at, message_count,
|
created_at, updated_at, last_active_at, archived_at, deleted_at, message_count,
|
||||||
reset_cutoff_seq, user_turn_count, agent_prompt_reinjection_count
|
reset_cutoff_seq, user_turn_count, agent_prompt_reinjection_count
|
||||||
) VALUES (?1, ?2, 'cli', ?3, NULL, ?4, ?4, ?4, NULL, NULL, 0, 0, 0, 0)
|
) VALUES (?1, ?2, ?3, ?4, NULL, ?5, ?5, ?5, NULL, NULL, 0, 0, 0, 0)
|
||||||
",
|
",
|
||||||
params![id, title, id, now],
|
params![id, title, channel_name, id, now],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
drop(conn);
|
drop(conn);
|
||||||
@ -230,6 +240,10 @@ impl SessionStore {
|
|||||||
.ok_or_else(|| rusqlite::Error::QueryReturnedNoRows.into())
|
.ok_or_else(|| rusqlite::Error::QueryReturnedNoRows.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_cli_session(&self, title: Option<&str>) -> Result<SessionRecord, StorageError> {
|
||||||
|
self.create_session("cli", title)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ensure_channel_session(
|
pub fn ensure_channel_session(
|
||||||
&self,
|
&self,
|
||||||
channel_name: &str,
|
channel_name: &str,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user