feat(gateway): PUT/DELETE /api/memories/{key} write endpoints

This commit is contained in:
xiaoxixi 2026-07-26 21:58:01 +08:00
parent 3f09793864
commit b49f0ec8a5
3 changed files with 58 additions and 0 deletions

View File

@ -947,6 +947,49 @@ pub async fn get_memories(
Ok(Json(json!({ "memories": memories })))
}
#[derive(Deserialize)]
pub struct PutMemoryBody {
content: String,
importance: Option<f64>,
}
pub async fn put_memory(
State(state): State<Arc<GatewayState>>,
Path(key): Path<String>,
Json(body): Json<PutMemoryBody>,
) -> Result<Json<Value>, ApiError> {
let existing = state
.storage
.get_memory_by_key(&key)
.await
.map_err(ApiError::internal)?
.ok_or_else(|| ApiError::not_found("memory not found"))?;
let mut updated = existing;
updated.content = body.content;
if let Some(importance) = body.importance {
updated.importance = importance.clamp(0.0, 1.0);
}
updated.updated_at = chrono::Utc::now().to_rfc3339();
state
.storage
.upsert_memory(&updated)
.await
.map_err(ApiError::internal)?;
Ok(Json(json!({ "updated": true, "key": key })))
}
pub async fn delete_memory(
State(state): State<Arc<GatewayState>>,
Path(key): Path<String>,
) -> Result<Json<Value>, ApiError> {
state
.storage
.delete_memory(&key)
.await
.map_err(ApiError::internal)?;
Ok(Json(json!({ "deleted": true })))
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -599,6 +599,10 @@ fn build_router(state: Arc<GatewayState>) -> Router {
.route("/api/jobs", routing::get(http::get_jobs))
.route("/api/jobs/{id}/runs", routing::get(http::get_job_runs))
.route("/api/memories", routing::get(http::get_memories))
.route(
"/api/memories/{key}",
routing::put(http::put_memory).delete(http::delete_memory),
)
.route(
"/api/chat/{client_id}/uploads",
routing::post(http::upload_file).layer(axum::extract::DefaultBodyLimit::disable()),

View File

@ -42,6 +42,17 @@ impl super::Storage {
parse_memory_rows(&rows)
}
pub async fn get_memory_by_key(&self, key: &str) -> Result<Option<MemoryEntry>, StorageError> {
let rows = sqlx::query(
"SELECT id, key, content, category, importance, session_id, created_at, updated_at FROM memories WHERE key = ?",
)
.bind(key)
.fetch_all(self.pool())
.await?;
let mut entries = parse_memory_rows(&rows)?;
Ok(entries.pop())
}
/// Store or update a memory entry (upsert by key).
pub async fn upsert_memory(&self, entry: &MemoryEntry) -> Result<(), StorageError> {
let category_str = entry.category.as_str();