Skip to main content

opencode_codes/
lib.rs

1//! A typed Rust interface for the [opencode](https://opencode.ai) agent server.
2//!
3//! <div class="warning">
4//!
5//! **Maturity warning**: this crate is new and should be considered **highly
6//! untested** — it is under active development. The types are generated from
7//! opencode's published OpenAPI spec and the suite passes against a live
8//! server, but real-world mileage is minimal and the API may change between
9//! releases while the surface settles. Bug reports and wire captures that
10//! break the types are very welcome at
11//! <https://github.com/meawoppl/rust-code-agent-sdks/issues>.
12//!
13//! </div>
14//!
15//! Unlike its sibling crates ([`claude-codes`](https://docs.rs/claude-codes) and
16//! [`codex-codes`](https://docs.rs/codex-codes)), which wrap CLIs that speak a
17//! JSON-Lines protocol over stdio, opencode runs a **local HTTP server** with a
18//! **Server-Sent Events** (SSE) stream. This crate models that server's OpenAPI
19//! 3.1 wire contract with serde types, and offers an async (Tokio) client plus a
20//! managed launcher for the `opencode serve` process.
21//!
22//! # Architecture
23//!
24//! opencode exposes a REST + SSE surface:
25//!
26//! - **REST** — session lifecycle and prompt submission are ordinary JSON
27//!   request/response calls (`POST /session`, `POST /session/{sessionID}/prompt_async`,
28//!   `GET /session/{sessionID}/message`, `POST /session/{sessionID}/abort`,
29//!   `POST /session/{sessionID}/permissions/{permissionID}`).
30//! - **SSE** — `GET /event` is a long-lived event stream carrying incremental
31//!   message parts, tool activity, and permission requests.
32//!
33//! The conversation lifecycle is:
34//!
35//! 1. **Create a session** — `POST /session`.
36//! 2. **Subscribe** — open the `GET /event` SSE stream.
37//! 3. **Prompt** — `POST /session/{sessionID}/prompt_async` returns immediately;
38//!    the agent's work is observed on the SSE stream.
39//! 4. **Handle permissions** — a permission request arrives on the stream; the
40//!    reply is a *separate* REST call
41//!    (`POST /session/{sessionID}/permissions/{permissionID}`). Correlating a
42//!    request to its reply is the consumer's responsibility — the pending
43//!    permission surface is kept explicit rather than hidden behind a callback.
44//! 5. **Reconcile** — SSE is best-effort and must not be trusted alone. Poll
45//!    `GET /session/{sessionID}/message` to reconcile the authoritative message
46//!    state against what the stream delivered. This crate documents and exposes
47//!    that poll path deliberately.
48//! 6. **Abort** — `POST /session/{sessionID}/abort` cancels in-flight work.
49//!
50//! Authentication is HTTP Basic when `OPENCODE_SERVER_PASSWORD` is set; the
51//! username defaults to `"opencode"`.
52//!
53//! # Feature Flags
54//!
55//! | Feature | Description | WASM-compatible |
56//! |---------|-------------|-----------------|
57//! | `types` | Core protocol types only (serde) | Yes |
58//! | `async-client` | Async HTTP/SSE client using reqwest + tokio | No |
59//! | `server` | Managed `opencode serve` launcher (picks a free port) | No |
60//! | `integration-tests` | Enables tests that require a live opencode server | No |
61//!
62//! `default = ["types", "async-client"]`. For WASM or type-sharing use cases:
63//!
64//! ```toml
65//! [dependencies]
66//! opencode-codes = { version = "1.18", default-features = false, features = ["types"] }
67//! ```
68//!
69//! # Provenance
70//!
71//! Module layout, SSE handling, and server-lifecycle lessons were informed by the
72//! Apache-2.0 licensed `opencode_rs` reference SDK. No code is copied verbatim;
73//! it is credited here as a design reference in keeping with its license.
74//!
75//! **Tested against:** opencode 1.18.5.
76
77pub mod error;
78pub mod protocol_generated;
79
80pub use error::{Error, Result};
81
82#[cfg(feature = "async-client")]
83pub mod http;
84
85#[cfg(feature = "async-client")]
86pub mod sse;
87
88#[cfg(feature = "async-client")]
89pub use sse::{EventStream, RetryConfig, StreamEvent};
90
91#[cfg(feature = "async-client")]
92pub mod client_async;
93
94#[cfg(feature = "async-client")]
95pub use client_async::{OpencodeClient, OpencodeClientBuilder};
96
97#[cfg(feature = "server")]
98pub mod server;
99
100#[cfg(feature = "server")]
101pub use server::{ManagedServer, ManagedServerBuilder};