diff options
| -rw-r--r-- | src/app/store.svelte.ts | 20 | ||||
| -rw-r--r-- | src/features/tabs/tabs-store.svelte.ts | 5 | ||||
| -rw-r--r-- | src/features/tabs/tabs.ts | 11 |
3 files changed, 35 insertions, 1 deletions
diff --git a/src/app/store.svelte.ts b/src/app/store.svelte.ts index 629e6c6..8997ce0 100644 --- a/src/app/store.svelte.ts +++ b/src/app/store.svelte.ts @@ -1106,8 +1106,15 @@ export function createAppStore(opts?: CreateAppStoreOptions): AppStore { workspaceId: conv.workspaceId, }); } else { - // Already open — update the title from the backend if it differs. + // Already open — reconcile title + workspace from the authoritative + // backend list. A raced `conversation.open` (summon) may have stamped + // the tab with the wrong workspace ("default"); the backend's + // authoritative conversation record is the source of truth, so a + // differing tab workspace is corrected here. tabsStore.setTitle(conv.id, conv.title); + if (tabsStore.tabs.find((t) => t.conversationId === conv.id)?.workspaceId !== conv.workspaceId) { + tabsStore.setWorkspaceId(conv.id, conv.workspaceId); + } } } @@ -1146,6 +1153,17 @@ export function createAppStore(opts?: CreateAppStoreOptions): AppStore { // `queued` = the turn is in flight but waiting for a concurrency slot // (broadcast-only, never persisted — CR-13); the tab shows a ring. conversationStatuses = new Map(conversationStatuses).set(conversationId, status); + // Reconcile the already-open tab's workspace from this authoritative + // lifecycle event (the payload workspace is the conversation's actual + // persisted workspace). A raced `conversation.open` may have stamped the + // wrong workspace ("default") — correct it here. + if ( + chatStores.has(conversationId) && + (tabsStore.tabs.find((t) => t.conversationId === conversationId)?.workspaceId ?? + workspaceId) !== workspaceId + ) { + tabsStore.setWorkspaceId(conversationId, workspaceId); + } // If this is a new active OR queued conversation we don't have a tab for, // open one — so a cross-device turn (incl. one waiting in the concurrency // queue) is visible. `idle` never opens a tab. diff --git a/src/features/tabs/tabs-store.svelte.ts b/src/features/tabs/tabs-store.svelte.ts index d044b1f..acf56fe 100644 --- a/src/features/tabs/tabs-store.svelte.ts +++ b/src/features/tabs/tabs-store.svelte.ts @@ -8,6 +8,7 @@ import { selectTab as reduceSelectTab, setModel as reduceSetModel, setTitle as reduceSetTitle, + setWorkspaceId as reduceSetWorkspaceId, activeTab as selectActiveTab, } from "./tabs"; @@ -28,6 +29,7 @@ export interface TabsStore { closeTab(conversationId: string): void; setModel(conversationId: string, model: string): void; setTitle(conversationId: string, title: string): void; + setWorkspaceId(conversationId: string, workspaceId: string): void; } export function createTabsStore(storage: TabsStorage): TabsStore { @@ -69,5 +71,8 @@ export function createTabsStore(storage: TabsStorage): TabsStore { setTitle(conversationId: string, title: string): void { apply(reduceSetTitle(state, conversationId, title)); }, + setWorkspaceId(conversationId: string, workspaceId: string): void { + apply(reduceSetWorkspaceId(state, conversationId, workspaceId)); + }, }; } diff --git a/src/features/tabs/tabs.ts b/src/features/tabs/tabs.ts index 63cda35..9fc9306 100644 --- a/src/features/tabs/tabs.ts +++ b/src/features/tabs/tabs.ts @@ -82,6 +82,17 @@ export function setTitle(state: TabsState, conversationId: string, title: string return { tabs, activeConversationId: state.activeConversationId }; } +export function setWorkspaceId( + state: TabsState, + conversationId: string, + workspaceId: string, +): TabsState { + const tabs = state.tabs.map((t) => + t.conversationId === conversationId ? { ...t, workspaceId } : t, + ); + return { tabs, activeConversationId: state.activeConversationId }; +} + export function activeTab(state: TabsState): Tab | null { if (state.activeConversationId === null) return null; return state.tabs.find((t) => t.conversationId === state.activeConversationId) ?? null; |
