AkurAI Build
Menu

Public repository / master

AkurAI-Notes / crates/notes-cli/src/cmd_tool.rs

Latest change 7f7b543549487ff8ff6802fb420feff1a197c507 - Checkpoint WIP + add AkurAI Build CI/CD pipeline by Ólafur Búi Ólafsson

use akurai_json::Value;
use akurai_storage::BTree;
use notes_mcp::tools::ToolRegistry;
use std::io::Read;
use std::sync::{Arc, Mutex};

pub fn run(name: &str, confirmed: bool) -> Result<(), String> {
    if matches!(name, "delete_note" | "delete_notebook" | "delete_tag") && !confirmed {
        return Err(format!("{name} requires --confirm"));
    }

    let registry = registry()?;
    let mut input = String::new();
    std::io::stdin()
        .read_to_string(&mut input)
        .map_err(|error| format!("read stdin: {error}"))?;
    let arguments = if input.trim().is_empty() {
        Vec::new()
    } else {
        match akurai_json::parse(&input).map_err(|error| format!("invalid JSON input: {error}"))? {
            Value::Object(arguments) => arguments,
            _ => return Err("stdin must contain one JSON object".into()),
        }
    };
    println!("{}", registry.execute(name, &arguments)?.to_json());
    Ok(())
}

pub fn list() -> Result<(), String> {
    println!("{}", Value::Array(registry()?.list_tools()).to_json());
    Ok(())
}

fn registry() -> Result<ToolRegistry, String> {
    let db_path = std::env::var("AKURAI_NOTES_DB")
        .unwrap_or_else(|_| "/var/lib/akurai-notes/notes.db".into());
    let db = BTree::open(&db_path).map_err(|error| format!("open {db_path}: {error}"))?;
    Ok(ToolRegistry::new(
        Arc::new(Mutex::new(db)),
        nonempty_env("AKURAI_NOTES_EMBED_URL"),
        nonempty_env("AKURAI_NOTES_EMBED_MODEL"),
        nonempty_env("AKURAI_NOTES_EMBED_API_KEY"),
        std::env::var("AKURAI_NOTES_MCP_OWNER_SUB").unwrap_or_default(),
    ))
}

fn nonempty_env(name: &str) -> Option<String> {
    std::env::var(name).ok().filter(|value| !value.is_empty())
}