summaryrefslogtreecommitdiffhomepage
path: root/src/features/tabs
diff options
context:
space:
mode:
Diffstat (limited to 'src/features/tabs')
-rw-r--r--src/features/tabs/tabs-store.svelte.ts10
-rw-r--r--src/features/tabs/tabs.ts40
2 files changed, 49 insertions, 1 deletions
diff --git a/src/features/tabs/tabs-store.svelte.ts b/src/features/tabs/tabs-store.svelte.ts
index acf56fe..5ed08d4 100644
--- a/src/features/tabs/tabs-store.svelte.ts
+++ b/src/features/tabs/tabs-store.svelte.ts
@@ -1,3 +1,4 @@
+import type { NamedAgentSelectionSnapshot } from "../named-agents";
import type { Tab, TabsState } from "./tabs";
import {
initialState,
@@ -7,6 +8,7 @@ import {
openTab as reduceOpenTab,
selectTab as reduceSelectTab,
setModel as reduceSetModel,
+ setSnapshot as reduceSetSnapshot,
setTitle as reduceSetTitle,
setWorkspaceId as reduceSetWorkspaceId,
activeTab as selectActiveTab,
@@ -28,6 +30,11 @@ export interface TabsStore {
selectTab(conversationId: string): void;
closeTab(conversationId: string): void;
setModel(conversationId: string, model: string): void;
+ /**
+ * Set (or clear, with null) a tab's Named Agent snapshot (plan §7). The caller
+ * keeps the snapshot's captured `model` in sync with the tab's `model`.
+ */
+ setSnapshot(conversationId: string, snapshot: NamedAgentSelectionSnapshot | null): void;
setTitle(conversationId: string, title: string): void;
setWorkspaceId(conversationId: string, workspaceId: string): void;
}
@@ -68,6 +75,9 @@ export function createTabsStore(storage: TabsStorage): TabsStore {
setModel(conversationId: string, model: string): void {
apply(reduceSetModel(state, conversationId, model));
},
+ setSnapshot(conversationId: string, snapshot: NamedAgentSelectionSnapshot | null): void {
+ apply(reduceSetSnapshot(state, conversationId, snapshot));
+ },
setTitle(conversationId: string, title: string): void {
apply(reduceSetTitle(state, conversationId, title));
},
diff --git a/src/features/tabs/tabs.ts b/src/features/tabs/tabs.ts
index 9fc9306..ff7bb4f 100644
--- a/src/features/tabs/tabs.ts
+++ b/src/features/tabs/tabs.ts
@@ -1,9 +1,18 @@
+import type { NamedAgentSelectionSnapshot } from "../named-agents";
+
export interface Tab {
readonly conversationId: string;
readonly model: string;
readonly title: string;
/** The workspace this tab belongs to (the workspace's URL slug). */
readonly workspaceId: string;
+ /**
+ * The Named Agent selection snapshot, when this conversation was selected via
+ * a Named Agent (plan §7). Retained so the conversation keeps showing the
+ * friendly label (and its captured raw model) even after the Named Agent is
+ * renamed/removed. Absent for a raw model selection.
+ */
+ readonly snapshot?: NamedAgentSelectionSnapshot;
}
export interface TabsState {
@@ -73,7 +82,36 @@ export function closeTab(state: TabsState, conversationId: string): TabsState {
}
export function setModel(state: TabsState, conversationId: string, model: string): TabsState {
- const tabs = state.tabs.map((t) => (t.conversationId === conversationId ? { ...t, model } : t));
+ // A raw-model selection clears any Named Agent snapshot (a raw selection is
+ // not "via a Named Agent"). Omit the key entirely (`exactOptionalPropertyTypes`).
+ const tabs = state.tabs.map((t) =>
+ t.conversationId !== conversationId ? t : omitSnapshot({ ...t, model }),
+ );
+ return { tabs, activeConversationId: state.activeConversationId };
+}
+
+/** Drop the optional `snapshot` key (used to clear a Named Agent selection). */
+function omitSnapshot(tab: Tab): Tab {
+ if (!("snapshot" in tab)) return tab;
+ const { snapshot: _omit, ...rest } = tab;
+ void _omit;
+ return rest;
+}
+
+/**
+ * Set (or clear) a tab's Named Agent selection snapshot (plan §7). The snapshot's
+ * captured `model` should equal the tab's `model` (the resolved raw model); this
+ * reducer does not rewrite `model` — the caller keeps them in sync. Pass `null`
+ * to clear (a raw model selection).
+ */
+export function setSnapshot(
+ state: TabsState,
+ conversationId: string,
+ snapshot: NamedAgentSelectionSnapshot | null,
+): TabsState {
+ const tabs = state.tabs.map((t) =>
+ t.conversationId === conversationId ? { ...t, ...(snapshot === null ? {} : { snapshot }) } : t,
+ );
return { tabs, activeConversationId: state.activeConversationId };
}