Files
dev/codex-rs/agents-client/src/api.rs
T
zeekay ccbf9c3829 feat(cli): run Hanzo Cloud agents from the terminal (dev agent)
Add `dev agent {list,run,show}` over the canonical `/v1/agents` registry
(cloud/clients/agents), reusing the signed-in hanzo.id session for auth.

- New crate `agents-client` mirrors `cloud-tasks-client`: wire types
  (Agent/AgentDetail/Run matching the server contract), an `AgentsBackend`
  trait, and a reqwest `HttpClient` that targets `{base}/v1/agents…`,
  injects the bearer JWT via `codex_api::SharedAuthProvider`, and quotes
  server errors honestly. A recorded error run (HTTP 502 with a Run body)
  is surfaced as the Run, not swallowed as a bare status.
- New `cli/src/agent_cmd.rs` module wires the subcommand like the existing
  `cloud` command: resolves base URL (default https://api.hanzo.ai,
  override CODEX_AGENTS_BASE_URL) + AuthManager from the loaded Config,
  fails secure when not signed in. `list`/`run`/`show`, each with `--json`;
  `run` reads the prompt from an arg or stdin.
- Cloud-agent invocation is additive and orthogonal to the local
  config-defined subprocess agents; no shared state.

Tests: 8 wiremock unit tests (list/get/run happy + recorded-error 502 +
503 server error + bearer header + path encoding). `cargo build`, `cargo
clippy -D warnings`, and `cargo test` are clean for the touched crates.

Bumps @hanzo/dev 0.6.91 -> 0.6.92 (patch) so a release can publish.
2026-07-01 23:59:20 -07:00

25 lines
898 B
Rust

use std::future::Future;
use std::pin::Pin;
use crate::Agent;
use crate::AgentDetail;
use crate::Result;
use crate::Run;
type BackendFuture<'a, T> = Pin<Box<dyn Future<Output = Result<T>> + Send + 'a>>;
/// The org-scoped cloud agents registry. Object-safe (boxed futures) so it can
/// be held as `Arc<dyn AgentsBackend>`, matching the sibling cloud-tasks crate.
pub trait AgentsBackend: Send + Sync {
/// List the calling org's agents (`GET /v1/agents`).
fn list_agents(&self) -> BackendFuture<'_, Vec<Agent>>;
/// Fetch one agent with its instructions and recent runs
/// (`GET /v1/agents/:name`).
fn get_agent<'a>(&'a self, name: &'a str) -> BackendFuture<'a, AgentDetail>;
/// Run an agent against `input` and return the recorded run
/// (`POST /v1/agents/:name/run`).
fn run_agent<'a>(&'a self, name: &'a str, input: &'a str) -> BackendFuture<'a, Run>;
}