anda_brain 0.13.5

🧠 Anda Brain (大脑) — Autonomous Graph Memory for AI Agents
use super::*;
use crate::runtime_api::{AttentionQuery, AttentionResponse, RuntimeError, RuntimeStatus};

pub(crate) fn runtime_error(error: RuntimeError) -> AppError {
    use http::StatusCode;
    let status = match &error {
        RuntimeError::Invalid(_) => StatusCode::BAD_REQUEST,
        RuntimeError::Unauthorized => StatusCode::UNAUTHORIZED,
        RuntimeError::Forbidden => StatusCode::FORBIDDEN,
        RuntimeError::NotFound => StatusCode::NOT_FOUND,
        RuntimeError::Conflict(_) => StatusCode::CONFLICT,
        RuntimeError::Unavailable(_) => StatusCode::SERVICE_UNAVAILABLE,
        RuntimeError::Storage(_) => StatusCode::INTERNAL_SERVER_ERROR,
    };
    AppError::with_status(status, error.to_string())
}

pub async fn get_attention(
    State(app): State<AppState>,
    AppPath(space_id): AppPath<String>,
    Accept(ct, _): Accept,
    HeaderVals(token, sharding): HeaderVals,
    AppQuery(input): AppQuery<AttentionQuery>,
) -> Result<impl IntoResponse, AppError> {
    let (space, credential) = crate::authz::runtime_credentials(
        &app,
        &space_id,
        &token,
        Some(sharding),
        TokenScope::Read,
    )
    .await
    .map_err(runtime_error)?;
    let runtime = space.memory_runtime().ok_or_else(|| {
        runtime_error(RuntimeError::Unavailable(
            "runtime bindings are not installed".into(),
        ))
    })?;
    let caller = runtime.map_credential(&credential).map_err(runtime_error)?;
    let page = runtime.inbox(&caller, input).await.map_err(runtime_error)?;
    Ok(ct.response(RpcResponse::success(page)))
}

pub async fn post_attention_response(
    State(app): State<AppState>,
    AppPath((space_id, id)): AppPath<(String, String)>,
    Accept(ct, _): Accept,
    HeaderVals(token, sharding): HeaderVals,
    AppBytes(body): AppBytes,
) -> Result<impl IntoResponse, AppError> {
    let (space, credential) = crate::authz::runtime_credentials(
        &app,
        &space_id,
        &token,
        Some(sharding),
        TokenScope::Write,
    )
    .await
    .map_err(runtime_error)?;
    let runtime = space.memory_runtime().ok_or_else(|| {
        runtime_error(RuntimeError::Unavailable(
            "runtime bindings are not installed".into(),
        ))
    })?;
    let caller = runtime.map_credential(&credential).map_err(runtime_error)?;
    let input = ct
        .parse_body::<AttentionResponse>(&body)
        .map_err(AppError::bad_request)?
        .value()
        .map_err(|_| AppError::bad_request("structured JSON/CBOR response required"))?;
    let result = runtime
        .respond(caller, id, input)
        .await
        .map_err(runtime_error)?;
    Ok(ct.response(RpcResponse::success(result)))
}

pub async fn post_outcome(
    State(app): State<AppState>,
    AppPath(space_id): AppPath<String>,
    Accept(ct, _): Accept,
    HeaderVals(token, sharding): HeaderVals,
    AppBytes(body): AppBytes,
) -> Result<impl IntoResponse, AppError> {
    let (space, credential) = crate::authz::runtime_credentials(
        &app,
        &space_id,
        &token,
        Some(sharding),
        TokenScope::Write,
    )
    .await
    .map_err(runtime_error)?;
    let runtime = space.memory_runtime().ok_or_else(|| {
        runtime_error(RuntimeError::Unavailable(
            "observer bindings are not installed".into(),
        ))
    })?;
    let caller = runtime.map_credential(&credential).map_err(runtime_error)?;
    if !caller.observer {
        return Err(runtime_error(RuntimeError::Forbidden));
    }
    let input = ct
        .parse_body::<crate::consequence::OutcomeInput>(&body)
        .map_err(AppError::bad_request)?
        .value()
        .map_err(|_| AppError::bad_request("structured JSON/CBOR observation required"))?;
    let receipt = runtime
        .submit_outcome(caller, input)
        .await
        .map_err(runtime_error)?;
    Ok(ct.response(RpcResponse::success(receipt)))
}

pub async fn get_runtime_status(
    State(app): State<AppState>,
    AppPath(space_id): AppPath<String>,
    Accept(ct, _): Accept,
    HeaderVals(token, sharding): HeaderVals,
) -> Result<impl IntoResponse, AppError> {
    let (space, credential) = crate::authz::runtime_credentials(
        &app,
        &space_id,
        &token,
        Some(sharding),
        TokenScope::Read,
    )
    .await
    .map_err(runtime_error)?;
    let status = if let Some(runtime) = space.memory_runtime() {
        let caller = runtime.map_credential(&credential).map_err(runtime_error)?;
        runtime
            .status(&caller, app.runtime_cwt_verifier_enabled())
            .await
            .map_err(runtime_error)?
    } else {
        RuntimeStatus::unconfigured()
    };
    Ok(ct.response(RpcResponse::success(status)))
}