diff options
Diffstat (limited to '.dispatch/wire.reference.md')
| -rw-r--r-- | .dispatch/wire.reference.md | 131 |
1 files changed, 122 insertions, 9 deletions
diff --git a/.dispatch/wire.reference.md b/.dispatch/wire.reference.md index b430a45..777a2ba 100644 --- a/.dispatch/wire.reference.md +++ b/.dispatch/wire.reference.md @@ -1,11 +1,50 @@ # `@dispatch/wire` — in-repo reference (read THIS, not node_modules) +> **2026-10-22 delta (reasoning block boundaries — ADDITIVE, no version bump):** `AgentEvent` +> gains `TurnReasoningEndEvent` `{ type: "reasoning-end", conversationId, turnId }`. The kernel emits +> one per provider reasoning block (Anthropic signs each thinking block separately), carrying NO +> opaque payload (signature/redacted data never leave the server). A live consumer splits thinking +> exactly as HTTP history persists it: the open thinking chunk closes; with none open (a redacted +> empty block) an empty thinking chunk is implied. Providers without block structure never emit it. +> The FE reducer mirrors the kernel's chunk builder; the old merged-run alignment stays as a fallback +> for older servers/replays. See `backend-handoff.md` and the backend's +> `notes/reasoning-end-live-event-plan.md`. +> +> **2026-10-20 review 3.5:** history replacements preserve monotonic seqs (retained history need not start at 1). HTTP history and WS compaction carry required `historyEpoch`; unknown cached epochs must be reloaded. Consumed by review 3.6. +> > MIRRORS the backend's `@dispatch/wire` package source so headless FE agents can read the wire > types WITHOUT following the `file:` dep symlink out of this repo (which hangs on a permission > prompt). Your CODE still imports `@dispatch/wire` normally — this file is for READING only. > > **Orchestrator:** SNAPSHOT of `[email protected]` (workspaces + computers + provider-retry + concurrency-`queued` status). Regenerate whenever `@dispatch/wire` changes. > +> **2026-09-20 delta (workspace archiving — ADDITIVE to `[email protected]`, NO version bump):** `Workspace` gains a +> required `archived: boolean` (defaults to `false` on creation; legacy rows normalize to `false`). An archived +> workspace is HIDDEN from the home grid WITHOUT deleting its data (conversations/settings untouched) and can be +> unarchived at any time. Toggled via dedicated `PUT`/`DELETE /workspaces/:id/archive` endpoints (no body; both +> create-on-miss and return the updated `Workspace`; both reject `"default"` with 409). `GET /workspaces` takes an +> optional `?archived=` query: `true` → archived only, `all` → every workspace, absent/other → non-archived only +> (the home grid's default). `PUT /workspaces/:id` does NOT accept an `archived` field. Implemented in BOTH repos +> of the `feature/archive-workspaces` worktree (see `backend-handoff.md`). +> +> **2026-08-25 delta (per-conversation model on ConversationMeta — ADDITIVE, no version bump):** +> `ConversationMeta` gains an optional `model?: string` (`<credential>/<model>`, absENT = default +> provider model). Surfaced on `GET /conversations` and the `conversation.open` WS broadcast so the +> FE can stamp a tab with the conversation's ACTUAL model instead of the globally-selected one +> (fix-toolcall-duplicate-keys plan Part 4 — prevents the stored model being overwritten by +> `activeModel`). See `transport-contract.reference.md` for the `ConversationOpenMessage.model` +> addition. +> +> **2026-08-20 delta (Named Agents — ADDITIVE, no version bump):** `@dispatch/wire` now exports two +> named-agent shapes the FE consumes (`named-agents-plan.md`): `NamedAgent` +> `{ id, name, model }` (a user-curated model preset; `model` = canonical `<provider>/<model>`) and +> `NamedAgentSelectionSnapshot` `{ namedAgentId, namedAgentName, model }` (the snapshot a conversation +> retains when selected via a Named Agent — plan §7). These mirror the backend's `packages/named-agents`. +> The FE re-exports them from this package (`features/named-agents/logic/types.ts`) rather than +> duplicating. Transport-contract also carries the `/named-agents` HTTP request/response types + +> `ChatRequest.namedAgent` / `ModelResponse.namedAgent` / `SetModelRequest.namedAgent` (see +> `transport-contract.reference.md`). +> > **2026-06-27 delta (workspace starring — ADDITIVE to `[email protected]`, NO version bump):** `Workspace` gains a > required `starred: boolean` (defaults to `false` on creation). A starred workspace's agents receive > PRIORITY in the concurrency limiter queue — they jump ahead of agents from non-starred workspaces @@ -231,26 +270,37 @@ export interface ChatMessage { /** * A persisted chunk plus its sync metadata. The append-only conversation log - * stamps every chunk with a **1-based**, monotonic, gap-free, per-conversation + * stamps every chunk with a positive, monotonic, per-conversation * `seq` (the sync cursor, assigned in append order) and records the `role` of * the message it belongs to. This makes a flat seq-ordered stream both * incrementally syncable ("give me chunks after seq N") and regroupable into * messages by the client. * - * The 1-based start is a CONTRACTUAL GUARANTEE (not an implementation detail): - * a conversation's first chunk is always `seq === 1` and numbering never skips, - * so a client holding only a windowed suffix of the log can derive "older - * chunks exist server-side" purely from `oldestLoaded.seq > 1` — no separate - * has-older flag is needed (or provided). `chunk` is the content unit — `Chunk` carries no storage/sync cursor + * Seq is never reused within a conversation, including after compaction replaces + * its history. The retained log need not start at 1 or be gap-free; a client + * cannot infer that older chunks exist solely from `oldestLoaded.seq > 1`. + * `chunk` is the content unit — `Chunk` carries no storage/sync cursor * (`seq` lives here on the envelope, not on the chunk, since it is assigned by * the store and the provider has no use for it). A chunk MAY still carry * generation provenance assigned at production time (e.g. a tool chunk's * `stepId`), which is intrinsic to the content and so travels with it. */ export interface StoredChunk { - readonly seq: number; - readonly role: Role; - readonly chunk: Chunk; + readonly seq: number; + readonly role: Role; + readonly chunk: Chunk; + /** + * The turn that produced this chunk — the same `turnId` carried on every + * live `AgentEvent` of that turn (the turn's opening user message, any + * mid-turn steering message, and every assistant/tool chunk the turn + * generated). The join key between transcript content and the turn's + * `TurnMetrics`, so a client places per-turn metrics EXACTLY (no positional + * guessing) — including while a turn is in flight and when older history has + * been unloaded. Optional: absent on rows persisted before this field + * existed and on chunks written outside any turn (e.g. a compaction summary). + * A consumer must tolerate its absence. + */ + readonly turnId?: string; } // ─── Reasoning effort ─────────────────────────────────────────────────────── @@ -374,6 +424,7 @@ export type AgentEvent = | TurnInputEvent | TurnTextDeltaEvent | TurnReasoningDeltaEvent + | TurnReasoningEndEvent | TurnToolCallEvent | TurnToolResultEvent | TurnToolOutputEvent @@ -434,6 +485,21 @@ export interface TurnReasoningDeltaEvent { readonly delta: string; } +/** + * End of one reasoning / thinking block. Emitted once per block by providers with + * block-structured reasoning (e.g. Anthropic, whose consecutive thinking blocks — each + * separately signed — persist as separate thinking chunks). Lets a live consumer split + * thinking exactly as history does: the open thinking chunk closes; if none is open (a + * redacted/empty block with no deltas) an EMPTY thinking chunk is implied. Carries no + * content: the opaque replay payloads (signature / redacted data) never leave the + * server. Providers without block structure never emit it (deltas merge as before). + */ +export interface TurnReasoningEndEvent { + readonly type: "reasoning-end"; + readonly conversationId: string; + readonly turnId: string; +} + /** The model has requested a tool to be run. */ export interface TurnToolCallEvent { readonly type: "tool-call"; @@ -670,6 +736,15 @@ export interface ConversationMeta { * that have never been compacted. */ readonly compactedFrom?: string; + /** + * The persisted per-conversation model name (`<credential>/<model>`), when + * one has been set. Absent/null means the conversation uses the default + * provider model. Surfaced on the open-conversation list + `conversation.open` + * broadcast so a client can stamp a tab with the conversation's ACTUAL model + * instead of the currently-selected global model (fix-toolcall-duplicate-keys + * plan Part 4). + */ + readonly model?: string; } // ─── Compaction ────────────────────────────────────────────────────────────── @@ -722,6 +797,14 @@ export interface Workspace { * Defaults to `false` on creation. */ readonly starred: boolean; + /** + * Whether the workspace is archived by the user. Archived workspaces are + * HIDDEN from the home grid (`GET /workspaces` excludes them by default; + * `?archived=` opts back in) without deleting their data — the workspace, + * its conversations, and its settings are untouched, and it can be + * unarchived at any time. Defaults to `false` on creation. + */ + readonly archived: boolean; /** Epoch-ms when the workspace was first created. */ readonly createdAt: number; /** Epoch-ms of the most recent conversation activity in this workspace. */ @@ -778,3 +861,33 @@ export interface ComputerEntry extends Computer { readonly usageCount: number; } ``` + +--- + +## 2026-09-24 delta (search-backend-selection — ADDITIVE) + +The global search-backend selection wire types (`GET/PUT /search/config`, GLOBAL — not +workspace-scoped) shipped in `@dispatch/wire` (transport-contract re-exports them): + +```ts +/** The selected backend id. `"none"` = search off (scrape/crawl keep working). */ +export type SearchBackendId = "firecrawl" | "umans" | "none"; + +/** One dropdown entry; `configured` is the availability gate (umans: UMANS_API_KEY resolves; firecrawl: always). */ +export interface SearchBackendAvailability { + readonly id: string; + readonly label: string; + readonly configured: boolean; +} + +/** Response of `GET /search/config` — the selection + every registered backend's availability. */ +export interface SearchBackendConfigResponse { + readonly backend: string; + readonly available: readonly SearchBackendAvailability[]; +} + +/** Body of `PUT /search/config` — select a backend by id (or `"none"`). */ +export interface UpdateSearchConfigRequest { + readonly backend: string; +} +``` |
