//! End-to-end usage example. //! //! Run against a live clawdforge: //! //! ```sh //! CLAWDFORGE_URL=http://localhost:8800 \ //! CLAWDFORGE_TOKEN=cf_xxxxxxxxxxxxxxxx \ //! cargo run --example basic //! ``` use clawdforge::{Client, RunRequest}; use serde::Deserialize; #[derive(Debug, Deserialize)] struct Hello { hello: String, } #[tokio::main] async fn main() -> Result<(), Box> { let url = std::env::var("CLAWDFORGE_URL").unwrap_or_else(|_| "http://localhost:8800".to_string()); let token = std::env::var("CLAWDFORGE_TOKEN") .map_err(|_| "set CLAWDFORGE_TOKEN to a cf_... bearer minted via /admin/tokens")?; let client = Client::builder().base_url(url).token(token).build()?; // 1) liveness let h = client.healthz().await?; println!( "healthz: ok={} claude_present={} version={:?}", h.ok, h.claude_present, h.claude_version ); // 2) JSON-shaped run let r = client .run(RunRequest { prompt: r#"Reply with JSON: {"hello": "world"}"#.into(), model: Some("sonnet".into()), timeout_secs: Some(30), ..Default::default() }) .await?; println!( "duration_ms={} stop_reason={:?}", r.duration_ms, r.stop_reason ); match r.as_json::() { Ok(v) => println!("parsed: hello = {}", v.hello), Err(_) => match r.as_text() { Some(t) => println!("text reply: {t}"), None => println!("unparseable reply: {:?}", r.result), }, } // 3) optional file upload — only if a path is given. if let Ok(path) = std::env::var("CLAWDFORGE_DEMO_FILE") { let ft = client.upload_file(&path, Some(3600)).await?; println!( "uploaded {} bytes -> {} (ttl {}s)", ft.size, ft.file_token, ft.ttl_secs ); let r2 = client .run(RunRequest { prompt: "Describe the attached file in one sentence.".into(), files: Some(vec![ft.file_token]), ..Default::default() }) .await?; println!("file-run reply: {:?}", r2.result); } Ok(()) }