kiromi-ai-cli 0.2.0

Operator and developer CLI for the kiromi-ai-memory store: append, search, snapshot, regenerate, migrate-scheme, gc, audit-tail.
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! `kiromi-ai-memory get` — fetch one memory.

use std::str::FromStr;

use kiromi_ai_memory::{MemoryId, MemoryRef, PartitionPath};

use crate::cli::{GetArgs, GlobalArgs};
use crate::error::{CliError, ExitCode};
use crate::output;
use crate::runtime::Runtime;

pub(crate) async fn run(args: GetArgs, globals: &GlobalArgs) -> Result<(), CliError> {
    let rt = Runtime::open(globals).await?;
    let id = MemoryId::from_str(&args.id).map_err(|e| CliError {
        kind: ExitCode::Config,
        source: anyhow::anyhow!("bad memory id: {e}"),
    })?;
    let probe = MemoryRef {
        id,
        partition: probe_partition()?,
    };
    let record = rt.mem.get(&probe).await?;

    if globals.json {
        let wire = record.wire();
        println!("{}", output::to_json(&wire));
    } else {
        // Body to stdout, metadata to stderr — friendly for piping.
        eprintln!("{}", output::record_kv(&record));
        println!("{}", record.content.as_str());
    }
    rt.mem.close().await?;
    Ok(())
}

/// `Memory::get` keys off id alone; partition is informational. Use a sentinel
/// path so we don't have to round-trip metadata first.
pub(crate) fn probe_partition() -> Result<PartitionPath, CliError> {
    PartitionPath::from_str("_=_").map_err(|e| CliError {
        kind: ExitCode::Config,
        source: anyhow::anyhow!("internal: probe partition: {e}"),
    })
}