Skip to main content

ForgetOptions

Struct ForgetOptions 

Source
pub struct ForgetOptions {
    pub run_id: Option<String>,
    pub lesson_id: Option<String>,
}

Fields§

§run_id: Option<String>§lesson_id: Option<String>

Implementations§

Source§

impl ForgetOptions

Source

pub fn for_run(run_id: impl Into<String>) -> Self

Examples found in repository?
examples/helper_all_helpers.rs (line 171)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "helper_all_helpers";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("helper_all_helpers");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        let remember_response = client.remember(remember).await?;
36
37        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
38        lesson.run_id = Some(run_id.clone());
39        lesson.agent_id = Some("planner".to_string());
40        lesson.intent = Some("lesson".to_string());
41        lesson.lesson_type = Some("success".to_string());
42        lesson.lesson_scope = Some("session".to_string());
43        lesson.lesson_importance = Some("high".to_string());
44        let lesson_response = client.remember(lesson).await?;
45
46        let mut recall = RecallOptions::new("What is the policy limit?");
47        recall.run_id = Some(run_id.clone());
48        recall.agent_id = Some("planner".to_string());
49        recall.limit = 5;
50        let recall_response = client.recall(recall).await?;
51
52        let mut context = GetContextOptions::default();
53        context.run_id = Some(run_id.clone());
54        context.query = Some("Prepare a short adjuster summary".to_string());
55        context.agent_id = Some("planner".to_string());
56        context.limit = Some(6);
57        context.max_token_budget = Some(700);
58        let context_response = client.get_context(context).await?;
59
60        let mut health = MemoryHealthOptions::default();
61        health.run_id = Some(run_id.clone());
62        health.limit = 50;
63        let health_response = client.memory_health(health).await?;
64
65        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
66        diagnose.run_id = Some(run_id.clone());
67        diagnose.error_type = Some("retrieval".to_string());
68        diagnose.limit = 5;
69        let diagnose_response = client.diagnose(diagnose).await?;
70
71        let mut reflect = ReflectOptions::default();
72        reflect.run_id = Some(run_id.clone());
73        let reflect_response = client.reflect(reflect).await?;
74
75        let mut register = RegisterAgentOptions::new("planner");
76        register.run_id = Some(run_id.clone());
77        register.role = "planner".to_string();
78        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
79        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
80        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
81        let register_response = client.register_agent(register).await?;
82
83        let mut list_agents = ListAgentsOptions::default();
84        list_agents.run_id = Some(run_id.clone());
85        let agents_response = client.list_agents(list_agents).await?;
86
87        let mut archive = ArchiveOptions::new(
88            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
89            "adjuster_note",
90        );
91        archive.run_id = Some(run_id.clone());
92        archive.agent_id = Some("planner".to_string());
93        archive.origin_agent_id = Some("planner".to_string());
94        archive.source_attempt_id = Some("attempt-1".to_string());
95        archive.source_tool = Some("phone_call".to_string());
96        archive.labels = vec!["claims".to_string(), "triage".to_string()];
97        archive.family = Some("claims-adjustment".to_string());
98        archive.metadata = Some(json!({"case": "all-helpers"}));
99        let archive_response = client.archive(archive).await?;
100        let reference_id = archive_response
101            .get("reference_id")
102            .and_then(Value::as_str)
103            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
104            .to_string();
105
106        let mut dereference = DereferenceOptions::new(reference_id.clone());
107        dereference.run_id = Some(run_id.clone());
108        dereference.agent_id = Some("planner".to_string());
109        let dereference_response = client.dereference(dereference).await?;
110
111        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
112        checkpoint.run_id = Some(run_id.clone());
113        checkpoint.label = Some("pre-compaction".to_string());
114        checkpoint.metadata = Some(json!({"stage": "analysis"}));
115        checkpoint.agent_id = Some("planner".to_string());
116        let checkpoint_response = client.checkpoint(checkpoint).await?;
117
118        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
119        let lesson_id = lessons_response
120            .get("lessons")
121            .and_then(Value::as_array)
122            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
123            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
124            .to_string();
125
126        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
127        outcome.run_id = Some(run_id.clone());
128        outcome.signal = 0.75;
129        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
130        outcome.agent_id = Some("planner".to_string());
131        let outcome_response = client.record_outcome(outcome).await?;
132
133        let mut strategies = SurfaceStrategiesOptions::default();
134        strategies.run_id = Some(run_id.clone());
135        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
136        strategies.max_strategies = 5;
137        let strategies_response = client.surface_strategies(strategies).await?;
138
139        let mut handoff = HandoffOptions::new(
140            "claim-1",
141            "planner",
142            "reviewer",
143            "Review whether the stored claimant city is sufficient for routing.",
144        );
145        handoff.run_id = Some(run_id.clone());
146        handoff.requested_action = "review".to_string();
147        handoff.metadata = Some(json!({"team": "claims"}));
148        let handoff_response = client.handoff(handoff).await?;
149        let handoff_id = handoff_response
150            .get("handoff_id")
151            .and_then(Value::as_str)
152            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
153            .to_string();
154
155        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
156        feedback.run_id = Some(run_id.clone());
157        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
158        feedback.from_agent_id = Some("reviewer".to_string());
159        feedback.metadata = Some(json!({"team": "claims"}));
160        let feedback_response = client.feedback(feedback).await?;
161
162        let scratch_run = format!("{run_id}_forget");
163        let mut scratch = RememberOptions::new("Scratch run for forget helper coverage.");
164        scratch.run_id = Some(scratch_run.clone());
165        scratch.agent_id = Some("planner".to_string());
166        scratch.intent = Some("fact".to_string());
167        scratch.metadata = Some(json!({"suite": "all-helpers", "temporary": true}));
168        let scratch_response = client.remember(scratch).await?;
169
170        let forget_response = client
171            .forget(ForgetOptions::for_run(scratch_run.clone()))
172            .await?;
173
174        let mut forgotten = RecallOptions::new("What temporary scratch fact exists?");
175        forgotten.run_id = Some(scratch_run.clone());
176        forgotten.limit = 3;
177        let forgotten_response = client.recall(forgotten).await?;
178
179        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
180        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
181        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
182        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
183        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
184        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
185        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
186        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
187        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
188        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
189        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
190        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
191        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
192        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
193        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
194        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
195        require(scratch_response.get("job_id").is_some() || scratch_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("scratch remember failed: {scratch_response}"))?;
196        require(forget_response.get("success").and_then(Value::as_bool).unwrap_or(true), format!("forget failed: {forget_response}"))?;
197        let scratch_fact_visible = forgotten_response
198            .get("evidence")
199            .and_then(Value::as_array)
200            .map(|items| {
201                items.iter().any(|item| {
202                    item.get("run_id").and_then(Value::as_str) == Some(scratch_run.as_str())
203                        || item
204                            .get("content")
205                            .and_then(Value::as_str)
206                            .map(|content| {
207                                content
208                                    .to_ascii_lowercase()
209                                    .contains("scratch run for forget helper coverage")
210                            })
211                            .unwrap_or(false)
212                })
213            })
214            .unwrap_or(false);
215        require(!scratch_fact_visible, format!("scratch fact should be forgotten even if same-user lessons still surface: {forgotten_response}"))?;
216
217        let strategy_count = strategies_response
218            .get("strategies")
219            .and_then(Value::as_array)
220            .map(|items| items.len())
221            .unwrap_or(0);
222        let agent_count = agents_response
223            .get("agents")
224            .and_then(Value::as_array)
225            .map(|items| items.len())
226            .unwrap_or(0);
227        let lesson_count = lessons_response
228            .get("lessons")
229            .and_then(Value::as_array)
230            .map(|items| items.len())
231            .unwrap_or(0);
232
233        metrics = json!({
234            "run_id": run_id,
235            "agent_count": agent_count,
236            "strategy_count": strategy_count,
237            "reference_id": reference_id,
238            "lesson_count": lesson_count,
239            "forgotten_run": scratch_run,
240        });
241
242        Ok::<(), Box<dyn Error>>(())
243    }
244    .await;
245
246    if let Err(err) = scenario {
247        passed = false;
248        detail = err.to_string();
249    }
250
251    let cleanup_ok = cleanup_run(&client, &run_id).await;
252    if !cleanup_ok {
253        passed = false;
254        detail = format!("{detail} | cleanup failures");
255    }
256
257    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
258
259    if passed { Ok(()) } else { Err(boxed_error(detail)) }
260}
Source

pub fn for_lesson(lesson_id: impl Into<String>) -> Self

Trait Implementations§

Source§

impl Clone for ForgetOptions

Source§

fn clone(&self) -> ForgetOptions

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ForgetOptions

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ForgetOptions

Source§

fn default() -> ForgetOptions

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more