summaryrefslogtreecommitdiffhomepage
path: root/.dispatch/wire.reference.md
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-22 00:36:31 +0900
committerAdam Malczewski <[email protected]>2026-06-22 00:36:31 +0900
commit54e88b71efd9a6fd9d880b6e90d844a875808662 (patch)
tree7d8292486f845225f4f03801531db2dc6ba8b7b1 /.dispatch/wire.reference.md
parenta8de5b2b9bec07a5ed5df54b859fa6ff5f98406f (diff)
downloaddispatch-web-54e88b71efd9a6fd9d880b6e90d844a875808662.tar.gz
dispatch-web-54e88b71efd9a6fd9d880b6e90d844a875808662.zip
feat(tabs): cross-device tab sync via conversation lifecycle
Consume the conversation lifecycle handoff ([email protected], [email protected]). Re-pinned file: deps + re-mirrored .dispatch/*.reference.md. - fetchOpenConversations() on connect: GET /conversations?status=active,idle restores the tab bar across devices (merges with localStorage — opens new tabs, removes closed ones, updates titles from backend) - conversation.statusChanged WS handler: closed → removeTabLocally (no re-POST); active → open tab + spinner; idle → update status map - conversation.compacted WS handler: dispose stale store + cache, reload history from server - TabBar shows a spinner on active conversations (statusFor prop) - closeTab refactored to use removeTabLocally (extracted cleanup) - conformance guards + WS adapter tests cover all 3 new WsServerMessage types 686 tests green.
Diffstat (limited to '.dispatch/wire.reference.md')
-rw-r--r--.dispatch/wire.reference.md19
1 files changed, 18 insertions, 1 deletions
diff --git a/.dispatch/wire.reference.md b/.dispatch/wire.reference.md
index e96c353..ead4d9c 100644
--- a/.dispatch/wire.reference.md
+++ b/.dispatch/wire.reference.md
@@ -4,9 +4,17 @@
> 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]` (conversation metadata). Regenerate
+> **Orchestrator:** SNAPSHOT of `[email protected]` (conversation lifecycle status). Regenerate
> whenever `@dispatch/wire` changes.
>
+> **2026-06-22 delta (conversation lifecycle handoff — package bumped `0.9.0` → `0.10.0`, ADDITIVE):**
+> adds `ConversationStatus` (`"active" | "idle" | "closed"`) — the per-conversation lifecycle
+> status. `ConversationMeta` gains a `status` field. `active` = a turn is generating; `idle` =
+> exists, not generating; `closed` = dismissed (hidden from the tab bar). Transitions are
+> backend-owned: `idle → active` on turn start, `active → idle` on turn settle, `→ closed` on
+> `POST /conversations/:id/close`. Pushed to all WS clients via `conversation.statusChanged`
+> (see `[email protected]`).
+>
> **2026-06-21 delta (conversation.open handoff — package bumped `0.8.0` → `0.9.0`, ADDITIVE):**
> adds `ConversationMeta` — metadata for a conversation (id, title, createdAt, lastActivityAt),
> returned by `GET /conversations` (the list endpoint, see `[email protected]`).
@@ -585,6 +593,14 @@ export interface TurnSteeringEvent {
// ─── Conversation metadata ───────────────────────────────────────────────────
/**
+ * The per-conversation lifecycle status. `active` = a turn is generating;
+ * `idle` = exists, not generating; `closed` = dismissed (hidden from the tab
+ * bar, not deleted). Transitions are backend-owned and pushed via the
+ * `conversation.statusChanged` WS message (see `transport-contract`).
+ */
+export type ConversationStatus = "active" | "idle" | "closed";
+
+/**
* Metadata for a conversation, returned by `GET /conversations` (the list
* endpoint). The title defaults to the first user message (truncated) and can
* be set via `PUT /conversations/:id/title`. `createdAt` is set on first write;
@@ -595,5 +611,6 @@ export interface ConversationMeta {
readonly createdAt: number;
readonly lastActivityAt: number;
readonly title: string;
+ readonly status: ConversationStatus;
}
```