From fd81987fcec0178ae2c466800b428e1b1dfc4ab0 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Sun, 21 Jun 2026 21:47:24 +0900 Subject: feat(ws): handle conversation.open broadcast — open/focus tab from CLI --open MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consume the conversation.open handoff (wire@0.9.0, transport-contract@0.13.0). Re-pinned file: deps + re-mirrored .dispatch/*.reference.md. - WS adapter (logic.ts + index.ts): parse + route the new top-level "conversation.open" WsServerMessage to an onConversationOpen handler - app store: openConversation(id) opens (or focuses) a tab — creates a chat store, loads history, subscribes to live turns, creates+selects the tab - conformance guard + WS adapter tests cover the new type - backend also shipped conversation metadata endpoints (GET /conversations, GET /conversations/:id/last, GET/PUT /conversations/:id/title) — mirrored but not yet consumed by the FE 682 tests green. --- src/app/store.svelte.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'src/app') diff --git a/src/app/store.svelte.ts b/src/app/store.svelte.ts index dc06ea1..5159353 100644 --- a/src/app/store.svelte.ts +++ b/src/app/store.svelte.ts @@ -3,6 +3,7 @@ import type { ChatErrorMessage, ConversationHistoryResponse, ConversationMetricsResponse, + ConversationOpenMessage, CwdResponse, LspStatusResponse, ModelsResponse, @@ -432,10 +433,39 @@ export function createAppStore(opts?: CreateAppStoreOptions): AppStore { let socket: ReturnType | null = null; + /** + * Open (or focus) a conversation tab — used by the `conversation.open` WS + * broadcast (CLI `--open` flag). If the conversation is already open, just + * focus it; otherwise create a chat store, load its history, subscribe to its + * live turns, and create+select the tab. + */ + function openConversation(conversationId: string): void { + const alreadyOpen = chatStores.has(conversationId); + if (!alreadyOpen) { + const store = createChatFor(conversationId, activeModel); + chatStores.set(conversationId, store); + void store.load(); + subscribeChat(conversationId); + tabsStore.createTab({ + conversationId, + model: activeModel, + title: "Conversation", + }); + } + tabsStore.selectTab(conversationId); + refreshActiveChat(); + syncSubscriptions(); + void refreshCwd(); + void refreshReasoningEffort(); + } + const socketOpts: SurfaceSocketOptions = { url: wsUrl, onMessage: handleServerMessage, onChat: handleChatMessage, + onConversationOpen(msg: ConversationOpenMessage): void { + openConversation(msg.conversationId); + }, onReopen() { // The server forgot our subscriptions on reconnect; re-send each with the // conversation it was subscribed under (protocolSubscribe would no-op since -- cgit v1.2.3