use std::io::Write;
use anyhow::Result;
use clap::Subcommand;
use crate::mcp::BasemindServer;
use crate::mcp::mode::MemoryMode;
use crate::mcp::params::{Lenient, Parameters};
use crate::mcp::types_memory::{MemoryParams, Visibility};
use super::render::{Emit, emit};
use super::run_tool;
fn visibility(individual: bool) -> Option<Visibility> {
individual.then_some(Visibility::Individual)
}
#[derive(Subcommand, Debug)]
pub enum MemoryCmd {
Put {
key: String,
value: String,
#[arg(long)]
tag: Vec<String>,
#[arg(long)]
no_embed: bool,
#[arg(long)]
individual: bool,
},
Get {
key: String,
#[arg(long)]
individual: bool,
},
List {
#[arg(long)]
prefix: Option<String>,
#[arg(long)]
tag: Option<String>,
#[arg(long)]
limit: Option<u32>,
#[arg(long)]
individual: bool,
},
Search {
query: String,
#[arg(long)]
limit: Option<u32>,
#[arg(long)]
tag: Option<String>,
#[arg(long)]
individual: bool,
},
Delete {
key: String,
#[arg(long)]
individual: bool,
},
Audit {
#[arg(long)]
key: Option<String>,
#[arg(long)]
individual: bool,
#[arg(long)]
dry_run: bool,
#[arg(long)]
limit: Option<u32>,
#[arg(long)]
include_archived: bool,
},
Documents {
query: String,
#[arg(long)]
limit: Option<u32>,
#[arg(long)]
mime_type: Option<String>,
#[arg(long)]
scope: Option<String>,
},
Mine {
#[arg(long)]
window: Option<u32>,
#[arg(long)]
min_support: Option<u32>,
#[arg(long)]
min_confidence: Option<f32>,
#[arg(long)]
max_files_per_commit: Option<u32>,
},
Proposals {
#[arg(long)]
kind: Option<String>,
#[arg(long)]
limit: Option<u32>,
},
Accept {
id: String,
#[arg(long)]
key: Option<String>,
},
Reject {
id: String,
#[arg(long)]
reason: Option<String>,
},
}
fn params(mode: MemoryMode) -> MemoryParams {
MemoryParams {
mode,
key: None,
value: None,
tags: None,
embed: None,
visibility: None,
prefix: None,
tag: None,
limit: None,
cursor: None,
query: None,
dry_run: None,
include_archived: None,
max_tokens: None,
format: None,
mime_type: None,
scope: None,
entity_category: None,
keywords_contains: None,
window: None,
min_support: None,
min_confidence: None,
max_files_per_commit: None,
kind: None,
id: None,
reason: None,
overrides: Default::default(),
}
}
pub async fn run(server: &BasemindServer, cmd: MemoryCmd, opts: &Emit, out: &mut impl Write) -> Result<()> {
let p = match cmd {
MemoryCmd::Put {
key,
value,
tag,
no_embed,
individual,
} => MemoryParams {
key: Some(key),
value: Some(value),
tags: (!tag.is_empty()).then_some(tag),
embed: no_embed.then_some(false),
visibility: visibility(individual),
..params(MemoryMode::Put)
},
MemoryCmd::Get { key, individual } => MemoryParams {
key: Some(key),
visibility: visibility(individual),
..params(MemoryMode::Get)
},
MemoryCmd::List {
prefix,
tag,
limit,
individual,
} => MemoryParams {
prefix,
tag,
limit,
visibility: visibility(individual),
..params(MemoryMode::List)
},
MemoryCmd::Search {
query,
limit,
tag,
individual,
} => MemoryParams {
query: Some(query),
limit,
tag,
visibility: visibility(individual),
..params(MemoryMode::Search)
},
MemoryCmd::Delete { key, individual } => MemoryParams {
key: Some(key),
visibility: visibility(individual),
..params(MemoryMode::Delete)
},
MemoryCmd::Audit {
key,
individual,
dry_run,
limit,
include_archived,
} => MemoryParams {
key,
visibility: visibility(individual),
dry_run: dry_run.then_some(true),
limit,
include_archived: include_archived.then_some(true),
..params(MemoryMode::Audit)
},
MemoryCmd::Documents {
query,
limit,
mime_type,
scope,
} => MemoryParams {
query: Some(query),
limit,
mime_type,
scope,
..params(MemoryMode::Documents)
},
MemoryCmd::Mine {
window,
min_support,
min_confidence,
max_files_per_commit,
} => MemoryParams {
window,
min_support,
min_confidence,
max_files_per_commit,
..params(MemoryMode::Mine)
},
MemoryCmd::Proposals { kind, limit } => MemoryParams {
kind,
limit,
..params(MemoryMode::Proposals)
},
MemoryCmd::Accept { id, key } => MemoryParams {
id: Some(id),
key,
..params(MemoryMode::Accept)
},
MemoryCmd::Reject { id, reason } => MemoryParams {
id: Some(id),
reason,
..params(MemoryMode::Reject)
},
};
let key = p.mode.telemetry_key();
let r = run_tool(key, server.memory(Parameters(Lenient(p))).await)?;
emit(key, &r, opts, out)
}