use crate::models::field_names;
use anyhow::Result;
use clap::Args;
use serde_json::{Value, json};
use crate::cli::CliOutput;
use crate::storage as db;
#[derive(Args, Debug, Clone)]
pub struct ReflectionOriginArgs {
#[arg(long = "memory-id", value_name = "ID")]
pub memory_id: String,
#[arg(long)]
pub json: bool,
}
pub fn cmd_reflection_origin(
db_path: &std::path::Path,
args: &ReflectionOriginArgs,
out: &mut CliOutput<'_>,
) -> Result<()> {
let conn = db::open(db_path)?;
let params = json!({"memory_id": args.memory_id});
let envelope = crate::mcp::handle_reflection_origin(&conn, ¶ms)
.map_err(|e| anyhow::anyhow!("reflection-origin: {e}"))?;
if args.json {
writeln!(out.stdout, "{}", serde_json::to_string(&envelope)?)?;
return Ok(());
}
let is_refl = envelope
.get(field_names::IS_REFLECTION)
.and_then(Value::as_bool)
.unwrap_or(false);
let peer = envelope
.get(field_names::PEER_ORIGIN)
.and_then(Value::as_str)
.unwrap_or("");
let depth = envelope
.get(field_names::ORIGINAL_DEPTH)
.and_then(Value::as_i64)
.unwrap_or(0);
writeln!(
out.stdout,
"reflection-origin: is_reflection={is_refl} peer_origin={peer} original_depth={depth}"
)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cli::test_utils::{TestEnv, seed_memory};
#[test]
fn reflection_origin_cli_known_id_returns_envelope() {
let mut env = TestEnv::fresh();
let db = env.db_path.clone();
let mid = seed_memory(&db, "ns", "plain", "body");
let args = ReflectionOriginArgs {
memory_id: mid,
json: true,
};
{
let mut out = env.output();
cmd_reflection_origin(&db, &args, &mut out).expect("ok");
}
let stdout = env.stdout_str();
let envelope: Value = serde_json::from_str(stdout.trim()).expect("parse envelope");
assert_eq!(envelope["is_reflection"].as_bool(), Some(false));
}
#[test]
fn reflection_origin_cli_empty_id_returns_err() {
let mut env = TestEnv::fresh();
let db = env.db_path.clone();
let args = ReflectionOriginArgs {
memory_id: String::new(),
json: true,
};
let mut out = env.output();
let err = cmd_reflection_origin(&db, &args, &mut out).expect_err("must fail");
assert!(err.to_string().contains("reflection-origin"), "got: {err}");
}
#[test]
fn reflection_origin_cli_text_output() {
let mut env = TestEnv::fresh();
let db = env.db_path.clone();
let mid = seed_memory(&db, "ns", "plain-text", "body");
let args = ReflectionOriginArgs {
memory_id: mid,
json: false,
};
{
let mut out = env.output();
cmd_reflection_origin(&db, &args, &mut out).expect("ok");
}
let stdout = env.stdout_str();
assert!(
stdout.contains("reflection-origin: is_reflection=false"),
"got: {stdout}"
);
assert!(stdout.contains("peer_origin="), "got: {stdout}");
assert!(stdout.contains("original_depth="), "got: {stdout}");
}
}