# Public API
## Inference contracts
- `LlmFuture<'a>` is the pinned, boxed, sendable future returned by an inference call. It resolves to `Result<Inference, LlmError>` and may borrow the thread and delta for `'a`.
- `ToolFuture` is a pinned, boxed, sendable `'static` future resolving to a tool output `String`.
- `CompactFuture` is a pinned, boxed, sendable `'static` future resolving to `Result<String, String>`.
- `Llm` is a `Send + Sync` factory. `start` creates one boxed `LlmThread`.
- `LlmThread` is `Send`. `infer` mutably borrows the thread and accepts a borrowed delta for the lifetime of its returned `LlmFuture`.
- `LlmError` is cloneable, debuggable, and equality-comparable. `Transient(String)` permits retry and `Permanent(String)` does not.
- `Inference` is cloneable, debuggable, and equality-comparable. `text` is primary model text, `calls` is the requested work, and `continue_inference` requests another inference step.
- `Call` is cloneable, debuggable, and equality-comparable. Its variants contain `ToolRequest`, `WorkerRequest`, or `CompactRequest`.
- `ToolRequest` is cloneable, debuggable, and equality-comparable. Its public `name` and `input` fields select a tool and provide its input.
- `WorkerRequest` is cloneable, debuggable, and equality-comparable. Its public `llm` and `prompt` fields select a worker model and provide its prompt.
- `CompactRequest` is cloneable, debuggable, and equality-comparable. Its public `instruction` field provides the compaction instruction.
- `ToolMode` is copyable, cloneable, debuggable, and equality-comparable. `Fast` identifies immediately executed work and `Queued` identifies queued work.
- `ToolStart` exposes public `mode`, `queued`, and `future` fields for a started tool.
- `WorkerStart` exposes a public `llm` factory and public `queued` text for a started worker.
- `Runtime` is `Send + Sync`. `start_tool` starts a `ToolRequest` with an `Updates` handle, `start_worker` resolves a borrowed `WorkerRequest`, and `compact` starts compaction with a request and primary text.
## Update delivery
- `SubmittedUpdate` is cloneable, debuggable, and equality-comparable. `Activity(String)` replaces activity information and `Append(String)` contributes appended text.
- `UpdateSink` is `Send + Sync + 'static`. `submit` synchronously receives a job identity, update identity, and owned `SubmittedUpdate`, returning `ChatError` unchanged on failure.
- `Updates` is an opaque cloneable preparation handle. `bind` creates a handle for a job and sink. `activity` and `append` each consume an owned string and return one `PreparedUpdate`.
- `PreparedUpdate` is opaque and cloneable. `send` synchronously submits its prepared update and returns the sink result unchanged.
Each `bind` starts identity allocation at 1. The resulting `Updates` clones share one `AtomicU64`; each preparation performs one relaxed atomic increment. Preparations therefore receive distinct identities in atomic allocation order. Cloning a `PreparedUpdate` does not allocate: every clone retains the same job, identity, payload, and sink. Every `send` invokes the sink, including repeated sends, so deduplication by job and identity is downstream. A send clones its stored payload to satisfy the sink's owned argument.
The update wrapper adds no channel operation, task creation, callback phase, timeout, or waiting around the direct sink call. Sink calls can run concurrently when callers invoke `send` concurrently, and the sink is responsible for its own synchronization and execution time. Relaxed identity allocation establishes no memory-ordering relationship for other data. Identity allocation is constant time and shared state is constant size; prepared payload strings and handles remain allocated while their owners or clones remain alive.
## Chat state
- `ChatView` is cloneable, debuggable, and equality-comparable. Its public fields are `primary`, `pending`, `history`, and `actions`.
- `PendingAction` is cloneable, debuggable, and equality-comparable. Its variants are `Inference { attempt }`, `Tool { name }`, `Worker { llm }`, and `Compaction`.
- `ChatEvent` is cloneable, debuggable, and equality-comparable. Its variants are `Text(String)`, `Activity(String)`, and `Stalled(String)`.
- `ChatError` is cloneable, debuggable, and equality-comparable. Its variants are `Empty`, `NotStalled`, `Busy`, and `Closed`.
## Retry leaf
`infer_with_retry` owns one boxed `LlmThread`, one delta `String`, and a shared `AtomicU8`, then returns the same boxed thread with either an `Inference` or error text. Calls are serial and always target the same object with the same `&delta`. Immediately before calls one through five, it stores the respective attempt number with relaxed ordering. Relaxed stores make the current value observable without using it as a synchronization barrier.
A successful call returns immediately. A permanent failure returns its text immediately. Transient failures after attempts one through four wait exactly 10, 20, 40, and 80 seconds through Tokio timers; the attempt value remains at the failed attempt during each wait. The fifth transient returns its text without another wait. Scheduling can make wall-clock resumption later than a timer deadline.
An individual inference call has no timeout and can remain pending indefinitely. Calls never overlap, retries do not replace the thread, and prior failures are not retained. Dropping the returned future drops the in-progress inference or timer and yields no returned thread. Apart from boxed trait futures and retained owned inputs, retry state is constant size. Waiting is timer-driven and does not busy-loop.