119 lines
3.9 KiB
Rust
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"))
|
|
}
|
|
}
|