helper_remember_recall/
helper_remember_recall.rs1#[path = "support/utils.rs"]
2mod _utils;
3
4use _utils::{boxed_error, cleanup_run, create_client, new_run_id, print_summary, require};
5use mubit_sdk::{RecallOptions, RememberOptions, TransportMode};
6use serde_json::json;
7use std::error::Error;
8use std::time::Instant;
9
10#[tokio::main(flavor = "current_thread")]
11async fn main() -> Result<(), Box<dyn Error>> {
12 let name = "helper_remember_recall";
13 let started = Instant::now();
14 let client = create_client().await?;
15 let run_id = new_run_id("helper_remember_recall");
16 client.set_run_id(Some(run_id.clone()));
17 client.set_transport(TransportMode::Http);
18
19 let mut passed = true;
20 let mut detail = "validated helper remember -> recall flow".to_string();
21 let mut metrics = json!({});
22
23 let scenario = async {
24 let mut remember = RememberOptions::new(
25 "Before retrying cache rebuilds, verify the token signer has rotated cleanly.",
26 );
27 remember.run_id = Some(run_id.clone());
28 remember.agent_id = Some("helper-example".to_string());
29 remember.intent = Some("lesson".to_string());
30 remember.lesson_type = Some("success".to_string());
31 remember.lesson_scope = Some("session".to_string());
32 remember.metadata = Some(json!({ "source": "rust-helper-example" }));
33 remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
34
35 let remembered = client.remember(remember).await?;
36 require(
37 remembered
38 .get("done")
39 .and_then(|value| value.as_bool())
40 .unwrap_or(false),
41 format!("remember should wait for ingest completion: {remembered}"),
42 )?;
43
44 let mut recall = RecallOptions::new("What should I verify before retrying cache rebuilds?");
45 recall.run_id = Some(run_id.clone());
46 recall.entry_types = vec!["lesson".to_string(), "fact".to_string()];
47 let answer = client.recall(recall).await?;
48 let evidence = answer
49 .get("evidence")
50 .and_then(|value| value.as_array())
51 .ok_or_else(|| boxed_error(format!("evidence missing: {answer}")))?;
52 require(!evidence.is_empty(), format!("evidence missing: {answer}"))?;
53 require(
54 answer
55 .get("final_answer")
56 .and_then(|value| value.as_str())
57 .is_some(),
58 format!("final answer missing: {answer}"),
59 )?;
60
61 metrics = json!({
62 "run_id": run_id,
63 "evidence_count": evidence.len(),
64 "confidence": answer.get("confidence").cloned().unwrap_or(serde_json::Value::Null),
65 });
66
67 Ok::<(), Box<dyn Error>>(())
68 }
69 .await;
70
71 if let Err(err) = scenario {
72 passed = false;
73 detail = err.to_string();
74 }
75
76 let cleanup_ok = cleanup_run(&client, &run_id).await;
77 if !cleanup_ok {
78 passed = false;
79 detail = format!("{detail} | cleanup failures");
80 }
81
82 print_summary(
83 name,
84 passed,
85 &detail,
86 &metrics,
87 started.elapsed().as_secs_f64(),
88 cleanup_ok,
89 );
90
91 if passed {
92 Ok(())
93 } else {
94 Err(boxed_error(detail))
95 }
96}