use yoagent::gasp::{GaspRecorder, GoalRef};
use yoagent::provider::mock::*;
use yoagent::provider::{MockProvider, ModelConfig};
use yoagent::*;
struct TouchTool;
#[async_trait::async_trait]
impl AgentTool for TouchTool {
fn name(&self) -> &str {
"touch"
}
fn label(&self) -> &str {
"Touch"
}
fn description(&self) -> &str {
"pretends to touch a file"
}
fn parameters_schema(&self) -> serde_json::Value {
serde_json::json!({"type": "object", "properties": {"path": {"type": "string"}}})
}
async fn execute(
&self,
params: serde_json::Value,
_ctx: ToolContext,
) -> Result<ToolResult, ToolError> {
Ok(ToolResult {
content: vec![Content::Text {
text: format!("touched {}", params["path"]),
}],
details: serde_json::Value::Null,
})
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let repo = std::env::args()
.nth(1)
.unwrap_or_else(|| "/tmp/yoagent-gasp-demo".into());
let recorder = GaspRecorder::init(
&repo,
"demo-agent",
"worker-1",
GoalRef::New {
title: "demonstrate GASP emission".into(),
},
)
.await?;
let provider = MockProvider::new(vec![
MockResponse::ToolCalls(vec![MockToolCall {
provider_metadata: None,
name: "touch".into(),
arguments: serde_json::json!({"path": "hello.txt"}),
}]),
MockResponse::Text("Done: touched hello.txt".into()),
]);
let mut agent =
Agent::from_provider(provider, ModelConfig::mock()).with_tools(vec![Box::new(TouchTool)]);
let (tx, record_handle) = recorder.recording_sender("touch hello.txt", None);
agent.prompt_with_sender("touch hello.txt", tx).await;
let run_id = record_handle.await??.expect("run recorded");
println!("recorded run {run_id} into {repo}");
println!("inspect: cat {repo}/state/events.jsonl");
println!("verify: git clone https://github.com/yologdev/gasp");
println!(" cd gasp/conformance-check && cargo run -q -- {repo}");
Ok(())
}