remem-ai 0.6.61

Local-first coding agent memory for Claude Code and OpenAI Codex
Documentation
use axum::{extract::State, http::StatusCode, response::IntoResponse, Json};

use super::super::helpers::{error_response, open_request_db};
use super::super::types::{DbState, UserRecallRequest};

pub(in crate::api) async fn handle_user_recall(
    State(_state): State<DbState>,
    Json(params): Json<UserRecallRequest>,
) -> impl IntoResponse {
    if params.query.trim().is_empty() {
        return error_response(
            StatusCode::BAD_REQUEST,
            "invalid_user_recall_request",
            "query is required",
        )
        .into_response();
    }

    let project = match resolve_recall_project(params.project.as_deref(), params.cwd.as_deref()) {
        Ok(project) => project,
        Err(message) => {
            return error_response(
                StatusCode::BAD_REQUEST,
                "invalid_user_recall_request",
                &message,
            )
            .into_response()
        }
    };
    let conn = match open_request_db() {
        Ok(conn) => conn,
        Err(response) => return response,
    };

    match crate::user_context::recall::recall_user_context(
        &conn,
        &crate::user_context::recall::UserRecallRequest {
            query: params.query,
            project,
            task_intent: params.task_intent,
            current_files: params.current_files,
            host: params.host,
            owner_scope: params.owner_scope,
            owner_key: params.owner_key,
            state_keys: params.state_keys,
            include_sensitive: params.include_sensitive,
            include_suppressed: params.include_suppressed,
            limit: params.limit,
            budget_chars: params.budget_chars,
        },
    ) {
        Ok(result) => Json(result).into_response(),
        Err(err) => error_response(
            StatusCode::INTERNAL_SERVER_ERROR,
            "user_recall_failed",
            &err.to_string(),
        )
        .into_response(),
    }
}

fn resolve_recall_project(project: Option<&str>, cwd: Option<&str>) -> Result<String, String> {
    if let Some(project) = project.map(str::trim).filter(|value| !value.is_empty()) {
        return Ok(project.to_string());
    }
    if let Some(cwd) = cwd.map(str::trim).filter(|value| !value.is_empty()) {
        return Ok(crate::db::project_from_cwd(cwd));
    }
    Err("project or cwd is required".to_string())
}