# herocoordinator Supervisor JSON-RPC client This crate now includes a typed client to communicate with an external "supervisor" component via JSON-RPC 2.0 over HTTP and WebSocket, generated from the OpenAPI spec in `specs/supervisor.yaml`. Highlights - Transports: HTTP and WebSocket (jsonrpsee). - Session: optional bearer token support (Authorization header). - Methods implemented: fetch_nonce, authenticate, whoami, play, create_job, start_job, run_job, get_job_status, get_job_output, get_job_logs, list_jobs, stop_job, delete_job, clear_all_jobs. - Types mirror the spec exactly (enum casing etc.). Enable features jsonrpsee client features are enabled in Cargo.toml: - server, macros, client, http-client, ws-client. Usage Add to your crate imports: ```rust use herocoordinator::supervisor::{ SupervisorClient, ScriptType, JobParams, }; ``` Create an HTTP client (default http://127.0.0.1:9944/) ```rust # #[tokio::main] # async fn main() -> Result<(), Box> { let mut client = SupervisorClient::new_http("http://127.0.0.1:9944/").await?; // Optional: obtain a token (out-of-band) and set it // client.set_bearer_token("your-token").await?; let pk = "abcdef1234deadbeef"; let nonce = client.fetch_nonce(pk).await?; let ok = client.authenticate(pk, "signature-here", &nonce).await?; assert!(ok, "authentication should succeed"); // whoami let who = client.whoami().await?; println!("whoami: {who}"); // play let res = client.play(r#"echo "hello""#).await?; println!("play.output: {}", res.output); // create a job let job_id = client .create_job(JobParams { script: r#"print("hi")"#.into(), script_type: ScriptType::Python, caller_id: "cli".into(), context_id: "demo".into(), timeout: Some(30), prerequisites: Some(vec![]), }) .await?; println!("created job: {job_id}"); // start a job let started = client.start_job(&job_id).await?; println!("job started: {}", started.success); // get status / output / logs let status = client.get_job_status(&job_id).await?; println!("job status: {:?}", status); let output = client.get_job_output(&job_id).await?; println!("job output: {output}"); let logs = client.get_job_logs(&job_id).await?; println!("job logs: {:?}", logs.logs); // list / stop / delete / clear let jobs = client.list_jobs().await?; println!("jobs: {:?}", jobs); // stop and delete are noop if job is already finished (server-defined behavior) let _ = client.stop_job(&job_id).await?; let _ = client.delete_job(&job_id).await?; // clear all jobs (use with care) let _ = client.clear_all_jobs().await?; # Ok(()) # } ``` Create a WebSocket client (default ws://127.0.0.1:9944/) ```rust # #[tokio::main] # async fn main() -> Result<(), Box> { let client = SupervisorClient::new_ws("ws://127.0.0.1:9944/").await?; // Use the same methods as the HTTP client let who = client.whoami().await?; println!("whoami: {who}"); # Ok(()) # } ``` Notes on authenticate and tokens - The OpenAPI spec defines authenticate returning a boolean. If your deployment provides a token via a header or another method, capture it externally and set it on the client using: - `client.set_bearer_token("...").await?` - To remove: `client.clear_bearer_token().await?` Types - Enums and DTOs mirror the OpenAPI casing: - ScriptType: "OSIS" | "SAL" | "V" | "Python" - JobStatus: "Dispatched" | "WaitingForPrerequisites" | "Started" | "Error" | "Finished" - JobParams include: script, script_type, caller_id, context_id, timeout?, prerequisites?. Testing - Unit tests verify enum casing and request param shapes. No live server needed. Run: `cargo test`. Files - src/supervisor/mod.rs - src/supervisor/types.rs - src/supervisor/error.rs - src/supervisor/client.rs