refactor(agent): extract claude driver into hive-claude crate
This commit is contained in:
parent
e35acca814
commit
a3b66241d1
13 changed files with 907 additions and 442 deletions
61
hive-claude/src/lib.rs
Normal file
61
hive-claude/src/lib.rs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
//! `hive-claude` — a small, reusable async driver for headless
|
||||
//! `claude --print` (Claude Code CLI) sessions.
|
||||
//!
|
||||
//! It spawns the CLI, streams and classifies its `stream-json` output, and
|
||||
//! reports the result as a `Result<(), Error>`: a clean turn is `Ok(())`, and
|
||||
//! every non-completion state — both recognized sentinels (rate-limit,
|
||||
//! prompt-too-long, …) and hard failures (spawn, non-zero exit) — is a variant
|
||||
//! of the single [`Error`] enum, so callers branch with one `match`. The crate
|
||||
//! also locates and archives on-disk sessions by title ([`SessionStore`]). It
|
||||
//! knows only about the Claude Code CLI — no application types, policy,
|
||||
//! watermarks, or logging. Callers wire streaming output through a [`Sink`] and
|
||||
//! layer their own compaction / retry / reset policy on top.
|
||||
//!
|
||||
//! # `thiserror` here, `anyhow` in the apps
|
||||
//!
|
||||
//! This is a **library**, so it exposes a concrete, matchable error enum built
|
||||
//! with [`thiserror`](https://docs.rs/thiserror): a caller can distinguish
|
||||
//! `Error::Exit { status, .. }` from `Error::Spawn { .. }` and branch on it.
|
||||
//! A library should never force its callers to reach into `anyhow`'s
|
||||
//! type-erased error to find out what went wrong.
|
||||
//!
|
||||
//! The **applications** in this workspace (the `hive-*` binaries) use
|
||||
//! [`anyhow`](https://docs.rs/anyhow) instead. At the top level you usually
|
||||
//! only want to attach context and log or bubble a failure up — not match on
|
||||
//! it — and `anyhow::Result` + `?` + `.context()` is the ergonomic fit.
|
||||
//! `anyhow::Error` implements `From<E>` for any `std::error::Error`, so a
|
||||
//! `hive_claude::Error` converts into an `anyhow::Error` for free at the `?`
|
||||
//! boundary. Rule of thumb: **libraries return `thiserror` enums, binaries
|
||||
//! consume them with `anyhow`.**
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! # async fn ex() {
|
||||
//! use hive_claude::{Claude, Config, Error, NoopSink, Session};
|
||||
//!
|
||||
//! let config = Config {
|
||||
//! model: "haiku".into(),
|
||||
//! ..Default::default()
|
||||
//! };
|
||||
//! match Claude::run(&config, &Session::Resume("my-session".into()), "hello", &NoopSink).await {
|
||||
//! Ok(()) => {}
|
||||
//! Err(Error::PromptTooLong) => { /* caller compacts + retries */ }
|
||||
//! Err(Error::RateLimited) => { /* caller parks + retries */ }
|
||||
//! Err(other) => eprintln!("claude: {other}"),
|
||||
//! }
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
mod classify;
|
||||
mod config;
|
||||
mod driver;
|
||||
mod error;
|
||||
mod sink;
|
||||
mod store;
|
||||
|
||||
pub use config::{Config, Session};
|
||||
pub use driver::Claude;
|
||||
pub use error::{Error, Result};
|
||||
pub use sink::{NoopSink, Sink};
|
||||
pub use store::SessionStore;
|
||||
Loading…
Reference in a new issue