Skip to main content

everruns_builtins/
native_async_tools.rs

1//! Explicit native async opt-in. The host owns persistence and execution policy.
2use async_trait::async_trait;
3use everruns_core::Capability;
4use serde_json::{Value, json};
5use std::collections::BTreeMap;
6
7pub struct NativeAsyncToolsCapability;
8fn selected(config: &Value) -> Result<BTreeMap<String, Option<Value>>, String> {
9    if config.is_null() || config == &json!({}) {
10        return Ok(BTreeMap::from([("web_fetch".into(), None)]));
11    }
12    let tools = config
13        .get("tools")
14        .ok_or("native async requires a tools map")?;
15    let tools: BTreeMap<String, Option<Value>> = serde_json::from_value(tools.clone())
16        .map_err(|_| "native async tools must map names to null or a custom format")?;
17    if tools.is_empty() || tools.keys().any(|name| name.is_empty()) {
18        return Err("native async tools cannot be empty".into());
19    }
20    if tools.values().flatten().any(|format| !format.is_object()) {
21        return Err("custom tool formats must be objects".into());
22    }
23    Ok(tools)
24}
25#[async_trait]
26impl Capability for NativeAsyncToolsCapability {
27    fn id(&self) -> &str {
28        "native_async_tools"
29    }
30    fn name(&self) -> &str {
31        "Native Async Tools"
32    }
33    fn description(&self) -> &str {
34        "Run selected read-only lookups while a supported model continues reasoning. Requires durable worker storage."
35    }
36    fn category(&self) -> Option<&str> {
37        Some("Optimization")
38    }
39    fn native_async_tools(&self, config: &Value) -> Option<BTreeMap<String, Option<Value>>> {
40        selected(config).ok()
41    }
42    fn validate_config(&self, config: &Value) -> Result<(), String> {
43        selected(config).map(|_| ())
44    }
45    fn config_schema(&self) -> Option<Value> {
46        Some(
47            json!({"type":"object","properties":{"tools":{"type":"object","description":"Tool names mapped to null for functions, or a custom tool format object.","default":{"web_fetch":null},"additionalProperties":{"type":["object","null"]}}}}),
48        )
49    }
50}