ai_memory/cli/commands/
entity_get_by_alias.rs1use crate::models::field_names;
14use anyhow::Result;
15use clap::Args;
16use serde_json::{Value, json};
17
18use crate::cli::CliOutput;
19use crate::storage as db;
20
21#[derive(Args, Debug, Clone)]
23pub struct EntityGetByAliasArgs {
24 #[arg(long, value_name = "ALIAS")]
26 pub alias: String,
27
28 #[arg(long, value_name = "NS")]
31 pub namespace: Option<String>,
32
33 #[arg(long)]
35 pub json: bool,
36}
37
38pub fn cmd_entity_get_by_alias(
46 db_path: &std::path::Path,
47 args: &EntityGetByAliasArgs,
48 out: &mut CliOutput<'_>,
49) -> Result<()> {
50 let conn = db::open(db_path)?;
51
52 let mut params = json!({"alias": args.alias});
53 if let Some(ns) = &args.namespace {
54 params["namespace"] = json!(ns);
55 }
56
57 let envelope = crate::mcp::handle_entity_get_by_alias(&conn, ¶ms)
58 .map_err(|e| anyhow::anyhow!("entity-get-by-alias: {e}"))?;
59
60 if args.json {
61 writeln!(out.stdout, "{}", serde_json::to_string(&envelope)?)?;
62 return Ok(());
63 }
64
65 let found = envelope
66 .get("found")
67 .and_then(Value::as_bool)
68 .unwrap_or(false);
69 if found {
70 let id = envelope
71 .get("entity_id")
72 .and_then(Value::as_str)
73 .unwrap_or("?");
74 let name = envelope
75 .get(field_names::CANONICAL_NAME)
76 .and_then(Value::as_str)
77 .unwrap_or("?");
78 writeln!(
79 out.stdout,
80 "entity-get-by-alias: entity_id={id} canonical_name={name}"
81 )?;
82 } else {
83 writeln!(out.stdout, "entity-get-by-alias: no match")?;
84 }
85 Ok(())
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91 use crate::cli::test_utils::TestEnv;
92
93 #[test]
94 fn entity_get_by_alias_cli_unknown_alias_returns_not_found() {
95 let mut env = TestEnv::fresh();
96 let db = env.db_path.clone();
97 let args = EntityGetByAliasArgs {
98 alias: "nonexistent-alias".into(),
99 namespace: None,
100 json: true,
101 };
102 {
103 let mut out = env.output();
104 cmd_entity_get_by_alias(&db, &args, &mut out).expect("ok");
105 }
106 let stdout = env.stdout_str();
107 let envelope: Value = serde_json::from_str(stdout.trim()).expect("parse envelope");
108 assert_eq!(envelope["found"].as_bool(), Some(false));
109 }
110
111 #[test]
112 fn entity_get_by_alias_cli_round_trip_finds_entity() {
113 let mut env = TestEnv::fresh();
114 let db = env.db_path.clone();
115 let reg = crate::mcp::handle_entity_register(
117 &crate::storage::open(&db).unwrap(),
118 &json!({
119 "canonical_name": "Bob",
120 "namespace": "people",
121 "aliases": ["bobby"],
122 "agent_id": "ai:tester",
123 }),
124 None,
125 )
126 .expect("register");
127 let expected_id = reg["entity_id"].as_str().unwrap().to_string();
128 let args = EntityGetByAliasArgs {
129 alias: "bobby".into(),
130 namespace: Some("people".into()),
131 json: true,
132 };
133 {
134 let mut out = env.output();
135 cmd_entity_get_by_alias(&db, &args, &mut out).expect("ok");
136 }
137 let stdout = env.stdout_str();
138 let envelope: Value = serde_json::from_str(stdout.trim()).expect("parse envelope");
139 assert_eq!(envelope["found"].as_bool(), Some(true));
140 assert_eq!(envelope["entity_id"].as_str(), Some(expected_id.as_str()));
141 }
142
143 #[test]
144 fn entity_get_by_alias_cli_text_output_not_found() {
145 let mut env = TestEnv::fresh();
146 let db = env.db_path.clone();
147 let args = EntityGetByAliasArgs {
148 alias: "nope".into(),
149 namespace: None,
150 json: false,
151 };
152 {
153 let mut out = env.output();
154 cmd_entity_get_by_alias(&db, &args, &mut out).expect("ok");
155 }
156 assert!(env.stdout_str().contains("entity-get-by-alias: no match"));
157 }
158
159 #[test]
160 fn entity_get_by_alias_cli_text_output_found() {
161 let mut env = TestEnv::fresh();
162 let db = env.db_path.clone();
163 crate::mcp::handle_entity_register(
164 &crate::storage::open(&db).unwrap(),
165 &json!({
166 "canonical_name": "Carol",
167 "namespace": "people",
168 "aliases": ["caz"],
169 "agent_id": "ai:tester",
170 }),
171 None,
172 )
173 .expect("register");
174 let args = EntityGetByAliasArgs {
175 alias: "caz".into(),
176 namespace: Some("people".into()),
177 json: false,
178 };
179 {
180 let mut out = env.output();
181 cmd_entity_get_by_alias(&db, &args, &mut out).expect("ok");
182 }
183 let stdout = env.stdout_str();
184 assert!(stdout.contains("entity_id="), "got: {stdout}");
185 assert!(stdout.contains("canonical_name=Carol"), "got: {stdout}");
186 }
187}