use crate::hook::{cut_to, open_for_hook};
use core_api::digest::{MAX_OUTPUT_BYTES, UNTRUSTED_FRAMING};
use core_api::memory::recall::{recall_digest, RecallOutcome};
use std::path::Path;
fn prompt_from_payload(raw: &str) -> Option<String> {
let v: serde_json::Value = serde_json::from_str(raw).ok()?;
for k in ["prompt", "user_prompt", "user_input"] {
if let Some(s) = v.get(k).and_then(|x| x.as_str()) {
let s = s.trim();
if !s.is_empty() {
return Some(s.to_string());
}
}
}
None
}
#[must_use]
pub fn run_recall(db_dir: &Path, hook_stdin: &str) -> String {
let Some(prompt) = prompt_from_payload(hook_stdin) else {
return String::new();
};
let Some(db) = open_for_hook(db_dir) else {
return String::new();
};
let budget = MAX_OUTPUT_BYTES.saturating_sub(UNTRUSTED_FRAMING.len());
match recall_digest(&db, &prompt, &db_dir.display().to_string(), budget) {
RecallOutcome::Hits(digest) => {
cut_to(format!("{UNTRUSTED_FRAMING}{digest}"), MAX_OUTPUT_BYTES)
}
RecallOutcome::NoIndex | RecallOutcome::NoMatch => String::new(),
}
}
#[cfg(test)]
mod tests {
use super::prompt_from_payload;
#[test]
fn prompt_is_read_from_any_of_the_three_documented_fields() {
for field in ["prompt", "user_prompt", "user_input"] {
let payload = format!(r#"{{"{field}":" hello "}}"#);
assert_eq!(prompt_from_payload(&payload).as_deref(), Some("hello"));
}
assert_eq!(prompt_from_payload(r#"{"prompt":" "}"#), None);
assert_eq!(prompt_from_payload(r#"{"other":"hi"}"#), None);
assert_eq!(prompt_from_payload("not json"), None);
}
}