PicoBot/src/command/handlers/memory_crud.rs

119 lines
3.9 KiB
Rust

use crate::command::context::CommandContext;
use crate::command::handler::{CommandHandler, CommandMetadata};
use crate::command::response::{CommandError, CommandResponse};
use crate::command::Command;
use crate::storage::{MemoryUpsert, SessionStore, GLOBAL_SCOPE_KEY};
use async_trait::async_trait;
use std::sync::Arc;
pub struct MemoryCrudCommandHandler {
store: Arc<SessionStore>,
}
impl MemoryCrudCommandHandler {
pub fn new(store: Arc<SessionStore>) -> Self {
Self { store }
}
}
/// 通过 ID 查找记忆的 namespace 和 memory_key
fn find_by_id(
store: &SessionStore,
id: &str,
) -> Result<Option<(String, String)>, CommandError> {
let records = store
.list_memories_for_scope("user", GLOBAL_SCOPE_KEY)
.map_err(|e| CommandError::new("LIST_ERROR", e.to_string()))?;
Ok(records
.iter()
.find(|r| r.id == id)
.map(|r| (r.namespace.clone(), r.memory_key.clone())))
}
#[async_trait]
impl CommandHandler for MemoryCrudCommandHandler {
fn can_handle(&self, cmd: &Command) -> bool {
matches!(
cmd,
Command::CreateMemory { .. } | Command::UpdateMemory { .. } | Command::DeleteMemory { .. }
)
}
fn metadata(&self) -> Option<CommandMetadata> {
Some(CommandMetadata {
name: "memory_crud",
description: "创建、更新、删除记忆",
usage: "/memory_crud",
})
}
async fn handle(
&self,
cmd: Command,
ctx: CommandContext,
) -> Result<CommandResponse, CommandError> {
let scope_key = GLOBAL_SCOPE_KEY.to_string();
match cmd {
Command::CreateMemory {
namespace,
key,
content,
} => {
let input = MemoryUpsert {
scope_kind: "user".to_string(),
scope_key,
namespace,
memory_key: key,
content,
source_type: "manual".to_string(),
source_session_id: None,
source_message_id: None,
source_message_seq: None,
source_channel_name: None,
source_chat_id: None,
};
self.store
.put_memory(&input)
.map_err(|e| CommandError::new("CREATE_ERROR", e.to_string()))?;
}
Command::UpdateMemory { id, content } => {
let Some((namespace, memory_key)) = find_by_id(&self.store, &id)? else {
return Err(CommandError::new("NOT_FOUND", "记忆不存在"));
};
let input = MemoryUpsert {
scope_kind: "user".to_string(),
scope_key,
namespace,
memory_key,
content,
source_type: "manual".to_string(),
source_session_id: None,
source_message_id: None,
source_message_seq: None,
source_channel_name: None,
source_chat_id: None,
};
self.store
.update_memory(&input)
.map_err(|e| CommandError::new("UPDATE_ERROR", e.to_string()))?;
}
Command::DeleteMemory { id } => {
let Some((namespace, memory_key)) = find_by_id(&self.store, &id)? else {
return Err(CommandError::new("NOT_FOUND", "记忆不存在"));
};
self.store
.delete_memory("user", &scope_key, &namespace, &memory_key)
.map_err(|e| CommandError::new("DELETE_ERROR", e.to_string()))?;
}
_ => unreachable!(),
}
Ok(CommandResponse::success(ctx.request_id)
.with_metadata("memory_updated", "true"))
}
}