summaryrefslogtreecommitdiffhomepage
path: root/.dispatch/wire.reference.md
diff options
context:
space:
mode:
Diffstat (limited to '.dispatch/wire.reference.md')
-rw-r--r--.dispatch/wire.reference.md131
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;
+}
+```