Skip to main content

control_legacy_state_compat/
control_legacy_state_compat.rs

1#[path = "support/utils.rs"]
2mod _utils;
3
4use _utils::{boxed_error, cleanup_run, create_client, new_run_id, print_summary, require};
5use mubit_sdk::TransportMode;
6use serde_json::{json, Value};
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 = "control_legacy_state_compat";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("control_legacy_state_compat");
16    let linked_run_id = new_run_id("control_legacy_state_linked");
17    client.set_run_id(Some(run_id.clone()));
18    client.set_transport(TransportMode::Http);
19
20    let mut passed = true;
21    let mut detail = "validated legacy state compatibility APIs".to_string();
22    let mut metrics = json!({});
23
24    let scenario = async {
25        let set_var = client.control.set_variable(json!({"run_id": run_id, "name": "claim_status", "value_json": json!({"value": "triage"}).to_string(), "source": "explicit"})).await?;
26        let get_var = client.control.get_variable(json!({"run_id": run_id, "name": "claim_status"})).await?;
27        let list_vars = client.control.list_variables(json!({"run_id": run_id})).await?;
28        let delete_var = client.control.delete_variable(json!({"run_id": run_id, "name": "claim_status"})).await?;
29
30        let define_concept = client.control.define_concept(json!({"run_id": run_id, "name": "claim", "schema_json": json!({"type": "object", "properties": {"status": {"type": "string"}}}).to_string()})).await?;
31        let list_concepts = client.control.list_concepts(json!({"run_id": run_id})).await?;
32
33        let add_goal = client.control.add_goal(json!({"run_id": run_id, "description": "Resolve claim", "priority": "high"})).await?;
34        let goal_id = add_goal.get("id").and_then(Value::as_str).ok_or_else(|| boxed_error(format!("add_goal failed: {add_goal}")))?.to_string();
35        let child_goal = client.control.add_goal(json!({
36            "run_id": run_id,
37            "description": "Verify receipts",
38            "priority": "medium",
39            "parent_goal_id": goal_id,
40        })).await?;
41        let update_goal = client.control.update_goal(json!({"run_id": run_id, "goal_id": goal_id, "status": "suspended"})).await?;
42        let list_goals = client.control.list_goals(json!({"run_id": run_id})).await?;
43        let goal_tree = client.control.get_goal_tree(json!({"run_id": run_id, "root_goal_id": goal_id})).await?;
44
45        let submit_action = client.control.submit_action(json!({"run_id": run_id, "agent_id": "planner", "action_type": "note", "action_json": json!({"step": "inspect facts"}).to_string()})).await?;
46        let action_log = client.control.get_action_log(json!({"run_id": run_id, "limit": 10})).await?;
47        let run_cycle = client.control.run_cycle(json!({"run_id": run_id, "agent_id": "planner", "candidates": [{"action_type": "inspect", "action_json": json!({"target": "claim facts"}).to_string(), "score": 0.9, "rationale": "highest confidence"}]})).await?;
48        let cycle_history = client.control.get_cycle_history(json!({"run_id": run_id, "limit": 10})).await?;
49        let link_run = client.control.link_run(json!({"run_id": run_id, "linked_run_id": linked_run_id})).await?;
50        let unlink_run = client.control.unlink_run(json!({"run_id": run_id, "linked_run_id": linked_run_id})).await?;
51
52        require(set_var.get("success").and_then(Value::as_bool).unwrap_or(false), format!("set_variable failed: {set_var}"))?;
53        require(get_var.get("name").and_then(Value::as_str) == Some("claim_status"), format!("get_variable failed: {get_var}"))?;
54        require(list_vars.get("variables").and_then(Value::as_array).map(|items| items.iter().any(|item| item.get("name").and_then(Value::as_str) == Some("claim_status"))).unwrap_or(false), format!("list_variables failed: {list_vars}"))?;
55        require(delete_var.get("success").and_then(Value::as_bool).unwrap_or(false), format!("delete_variable failed: {delete_var}"))?;
56        require(define_concept.get("success").and_then(Value::as_bool).unwrap_or(false), format!("define_concept failed: {define_concept}"))?;
57        require(list_concepts.get("concepts").and_then(Value::as_array).map(|items| items.iter().any(|item| item.get("name").and_then(Value::as_str) == Some("claim"))).unwrap_or(false), format!("list_concepts failed: {list_concepts}"))?;
58        require(child_goal.get("id").and_then(Value::as_str).is_some(), format!("child add_goal failed: {child_goal}"))?;
59        require(update_goal.get("success").and_then(Value::as_bool).unwrap_or(false), format!("update_goal failed: {update_goal}"))?;
60        require(list_goals.get("goals").and_then(Value::as_array).map(|items| items.iter().any(|item| item.get("id").and_then(Value::as_str) == Some(goal_id.as_str()))).unwrap_or(false), format!("list_goals failed: {list_goals}"))?;
61        require(
62            goal_tree.get("root").is_some()
63                || goal_tree.get("nodes").is_some()
64                || goal_tree.get("goals").and_then(Value::as_array).is_some(),
65            format!("goal_tree failed: {goal_tree}"),
66        )?;
67        require(submit_action.get("success").and_then(Value::as_bool).unwrap_or(false), format!("submit_action failed: {submit_action}"))?;
68        require(action_log.get("entries").and_then(Value::as_array).is_some(), format!("action_log failed: {action_log}"))?;
69        let cycle_number_valid = run_cycle.get("cycle_number").and_then(Value::as_u64).is_some()
70            || run_cycle
71                .get("cycle_number")
72                .and_then(Value::as_str)
73                .map(|value| value.chars().all(|ch| ch.is_ascii_digit()))
74                .unwrap_or(false);
75        require(cycle_number_valid, format!("run_cycle failed: {run_cycle}"))?;
76        require(cycle_history.get("cycles").and_then(Value::as_array).is_some(), format!("cycle_history failed: {cycle_history}"))?;
77        require(link_run.get("success").and_then(Value::as_bool).unwrap_or(false), format!("link_run failed: {link_run}"))?;
78        require(unlink_run.get("success").and_then(Value::as_bool).unwrap_or(false), format!("unlink_run failed: {unlink_run}"))?;
79
80        metrics = json!({
81            "run_id": run_id,
82            "goal_id": goal_id,
83            "action_id": submit_action.get("action_id").cloned().unwrap_or(Value::Null),
84            "cycle_number": run_cycle.get("cycle_number").cloned().unwrap_or(Value::Null),
85        });
86        Ok::<(), Box<dyn Error>>(())
87    }
88    .await;
89
90    if let Err(err) = scenario {
91        passed = false;
92        detail = err.to_string();
93    }
94
95    let cleanup_ok = cleanup_run(&client, &run_id).await;
96    if !cleanup_ok {
97        passed = false;
98        detail = format!("{detail} | cleanup failures");
99    }
100
101    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
102
103    if passed { Ok(()) } else { Err(boxed_error(detail)) }
104}