Skip to main content

batuta/serve/banco/
handlers_tools.rs

1//! Tool calling endpoint handlers — list, configure, execute tools.
2
3use axum::{extract::State, http::StatusCode, response::Json};
4use serde::Deserialize;
5
6use super::state::BancoState;
7use super::tools::{ToolCall, ToolDefinition, ToolResult};
8use super::types::ErrorResponse;
9
10/// GET /api/v1/tools — list available tools for current privacy tier.
11pub async fn list_tools_handler(State(state): State<BancoState>) -> Json<ToolsListResponse> {
12    let tier = format!("{:?}", state.privacy_tier);
13    let tools = state.tools.list_for_tier(&tier);
14    Json(ToolsListResponse { tools })
15}
16
17/// POST /api/v1/tools/execute — execute a tool call directly.
18pub async fn execute_tool_handler(
19    State(state): State<BancoState>,
20    Json(call): Json<ToolCall>,
21) -> Result<Json<ToolResult>, (StatusCode, Json<ErrorResponse>)> {
22    // Check tool exists
23    if state.tools.get(&call.name).is_none() {
24        return Err((
25            StatusCode::NOT_FOUND,
26            Json(ErrorResponse::new(
27                format!("Tool '{}' not found", call.name),
28                "tool_not_found",
29                404,
30            )),
31        ));
32    }
33
34    let result = state.tools.execute(&call);
35    Ok(Json(result))
36}
37
38/// PUT /api/v1/tools/:name/config — enable/disable a tool.
39pub async fn configure_tool_handler(
40    State(state): State<BancoState>,
41    axum::extract::Path(name): axum::extract::Path<String>,
42    Json(config): Json<ToolConfigRequest>,
43) -> Result<StatusCode, (StatusCode, Json<ErrorResponse>)> {
44    if !state.tools.set_enabled(&name, config.enabled) {
45        return Err((
46            StatusCode::NOT_FOUND,
47            Json(ErrorResponse::new(format!("Tool '{name}' not found"), "tool_not_found", 404)),
48        ));
49    }
50    Ok(StatusCode::OK)
51}
52
53/// POST /api/v1/tools — register a custom tool.
54pub async fn register_tool_handler(
55    State(state): State<BancoState>,
56    Json(tool): Json<ToolDefinition>,
57) -> Json<ToolDefinition> {
58    state.tools.register(tool.clone());
59    Json(tool)
60}
61
62// ============================================================================
63// Types
64// ============================================================================
65
66#[derive(Debug, serde::Serialize)]
67pub struct ToolsListResponse {
68    pub tools: Vec<ToolDefinition>,
69}
70
71#[derive(Debug, Deserialize)]
72pub struct ToolConfigRequest {
73    pub enabled: bool,
74}