use axllm::runtime::quickjs::QuickJsCodeRuntime;
use axllm::{agent, AxCodeRuntime, AxError, AxResult};
use serde_json::json;
fn main() -> AxResult<()> {
let mut runtime = QuickJsCodeRuntime::new()
.with_runtime_policy(json!({"timeoutMs": 100, "maxSnapshotBytes": 64}));
runtime.register_callable("search", |params| {
Ok(json!({"answer": format!("result for {}", params["query"].as_str().unwrap_or(""))}))
})?;
runtime.register_callable("badTool", |_params| {
Err(AxError::runtime("bad tool failed"))
})?;
let mut runner = agent("question:string -> answer:string")?;
let step = runner.test(
&mut runtime,
"answer = inputs.question; final({ answer })",
json!({"question": "quickjs"}),
json!({}),
)?;
assert_eq!(step.payload["kind"], "final");
assert_eq!(step.payload["result"]["args"][0]["answer"], "quickjs");
let actor_step = runner.execute_actor_step(
&mut runtime,
"answer = inputs.question; final({ answer })",
json!({"question": "quickjs"}),
json!({}),
)?;
assert_eq!(actor_step.payload["kind"], "final");
assert_eq!(runner.inspect_runtime()?["answer"], "quickjs");
let snapshot = runner.export_session_state()?;
assert_eq!(snapshot["bindings"]["answer"], "quickjs");
runner.restore_session_state(json!({"bindings": {"answer": "patched"}}))?;
assert_eq!(runner.inspect_runtime()?["answer"], "patched");
let mut session = runtime.create_session(
json!({
"inputs": {"question": "host"},
"marker": {"__ax_host_callable": true, "result": {"ok": true}}
}),
json!({"reservedNames": ["inputs", "final"]}),
)?;
assert_eq!(
session
.execute("askClarification('more?')", json!({}))?
.payload["type"],
"askClarification"
);
assert_eq!(
session
.execute("discover({topic: 'docs'})", json!({}))?
.payload["kind"],
"discover"
);
assert_eq!(
session
.execute("recall({query: 'state'})", json!({}))?
.payload["kind"],
"recall"
);
assert_eq!(
session
.execute("used('doc-1', 'needed')", json!({}))?
.payload["kind"],
"used"
);
assert_eq!(
session.execute("reportSuccess('ok')", json!({}))?.payload["kind"],
"status"
);
assert_eq!(
session.execute("reportFailure('no')", json!({}))?.payload["kind"],
"status"
);
assert_eq!(
session
.execute("guideAgent('try this')", json!({}))?
.payload["type"],
"guide_agent"
);
assert_eq!(
session
.execute("final(search({query: inputs.question}))", json!({}))?
.payload["args"][0]["answer"],
"result for host"
);
assert_eq!(
session.execute("final(marker())", json!({}))?.payload["args"][0]["ok"],
true
);
let caught = session.execute("let caught = ''; let category = ''; try { badTool({}); } catch (error) { caught = String(error); category = String(error.error_category || ''); } final({caught, category})", json!({}))?;
assert!(caught.payload["args"][0]["caught"]
.as_str()
.unwrap_or("")
.contains("bad tool failed"));
assert_eq!(caught.payload["args"][0]["category"], "runtime");
let failed = session.execute("badTool({}); final({unreachable: true})", json!({}))?;
assert_eq!(failed.payload["is_error"], true);
assert_eq!(failed.payload["error_category"], "runtime");
assert!(failed.payload["error"]
.as_str()
.unwrap_or("")
.contains("bad tool failed"));
assert_eq!(
session
.execute("throw new Error('boom')", json!({}))?
.payload["error_category"],
"runtime"
);
assert_eq!(
session
.execute("while (true) {}", json!({"timeoutMs": 1}))?
.payload["error_category"],
"timeout"
);
session.patch_globals(
json!({"bindings": {"final": "blocked", "answer": "patched"}}),
json!({}),
)?;
assert_ne!(session.inspect_globals(json!({}))?["final"], "blocked");
assert_eq!(session.inspect_globals(json!({}))?["answer"], "patched");
session.close()?;
assert_eq!(
session.execute("final({})", json!({}))?.payload["error_category"],
"session_closed"
);
println!("rust-javascript-quickjs-profile-ok runtime-behavior-parity-ok");
Ok(())
}