diff options
| author | Adam Malczewski <[email protected]> | 2026-08-20 19:36:12 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-08-20 19:36:12 +0900 |
| commit | fb7eb3105e1fbbdefdad9348f9132815b5bbe52d (patch) | |
| tree | deb95e97a917424ea67470b168b91349a41d1c08 /src/features/chat/store.svelte.ts | |
| parent | 63588c3c69b32d180dc78a2cc187cc8aa22ad7e0 (diff) | |
| download | dispatch-web-fb7eb3105e1fbbdefdad9348f9132815b5bbe52d.tar.gz dispatch-web-fb7eb3105e1fbbdefdad9348f9132815b5bbe52d.zip | |
feat(named-agents): sidebar view, synthetic provider, auto-save, snapshot semantics
Implement the frontend of the Named Agents feature (plan §5-§9):
- New features/named-agents module: pure logic (types re-exported from
@dispatch/wire + transport-contract, validation, provider/model options,
snapshot helpers, network normalizers, auto-save status model) + an injected
auto-save controller (name debounce, immediate provider/model save, monotonic
stale-response guard) + the collapsible sidebar card view.
- Store: /named-agents CRUD + boot seed; selectModel(model, snapshot?) persists
the raw model WITH the namedAgent snapshot; draft promotion carries it;
refreshModel restores ModelResponse.namedAgent.
- Chat store setNamedAgent (sends namedAgent on chat.send); Tab.snapshot +
setSnapshot (retained across rename/remove, persisted with tabs).
- Model selector: synthetic Named Agents provider ALWAYS first; selecting one
resolves to the raw model + records a snapshot; a retained snapshot of a
renamed/removed agent still displays as unavailable (plan §7).
- Composition root wires the view (viewKinds + loaded-modules manifest) + feeds
the selector.
Tests: logic + controller + selector + app-store CRUD (1246 pass), typecheck 0,
biome clean (only pre-existing config infos pending a future migrate), build OK.
Diffstat (limited to 'src/features/chat/store.svelte.ts')
| -rw-r--r-- | src/features/chat/store.svelte.ts | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/src/features/chat/store.svelte.ts b/src/features/chat/store.svelte.ts index 24a1d06..c83c5fd 100644 --- a/src/features/chat/store.svelte.ts +++ b/src/features/chat/store.svelte.ts @@ -34,6 +34,7 @@ import { selectOrderedTurnMetrics, } from "../../core/metrics"; import type { ConversationCache } from "../conversation-cache"; +import type { NamedAgentSelectionSnapshot } from "../named-agents"; import type { ChatTransport, HistorySync, MetricsSync } from "./ports"; export interface ChatStoreDependencies { @@ -145,6 +146,15 @@ export interface ChatStore { cancelQueuedMessage(messageId: string): void; setModel(model: string): void; /** + * Set (or clear, with null) the Named Agent selection snapshot this chat sends + * with `chat.send` (plan §7). The backend persists it on the conversation at + * creation so it freezes the friendly id/name + resolved model — later edits to + * the Named Agent do not change this conversation's selection. The raw model + * (already set via `setModel`) is sent alongside; the snapshot is display/identity + * metadata that preserves HOW it was selected. + */ + setNamedAgent(snapshot: NamedAgentSelectionSnapshot | null): void; + /** * Update the chat limit LIVE: re-normalizes, then adjusts the loaded window. * Lowering it unloads older committed chunks (deferred via the gate while the * reader is scrolled up, catching up on the next mutation). Raising it @@ -180,6 +190,7 @@ export function createChatStore(deps: ChatStoreDependencies): ChatStore { let _pendingSync = $state(false); let _error = $state<string | null>(null); let _model = $state<string | undefined>(deps.model); + let _namedAgent = $state<NamedAgentSelectionSnapshot | null>(null); let disposed = false; let chatLimit = normalizeChatLimit(deps.chatLimit); @@ -342,6 +353,7 @@ export function createChatStore(deps: ChatStoreDependencies): ChatStore { conversationId: deps.conversationId, message: text, ...(_model !== undefined ? { model: _model } : {}), + ...(_namedAgent !== null ? { namedAgent: _namedAgent } : {}), ...(deps.workspaceId !== undefined ? { workspaceId: deps.workspaceId } : {}), ...(images !== undefined && images.length > 0 ? { images: [...images] } : {}), }; @@ -379,6 +391,10 @@ export function createChatStore(deps: ChatStoreDependencies): ChatStore { _model = model; }, + setNamedAgent(snapshot: NamedAgentSelectionSnapshot | null): void { + _namedAgent = snapshot; + }, + async setChatLimit(limit: number): Promise<void> { const prev = chatLimit; chatLimit = normalizeChatLimit(limit); |
