summaryrefslogtreecommitdiffhomepage
path: root/src/app/App.svelte
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-12 20:38:57 +0900
committerAdam Malczewski <[email protected]>2026-06-12 20:38:57 +0900
commitb74357495e443ff6011531d296560caff9398a14 (patch)
tree63aafc3ef6ced7cc2ec59ad66c788ecae74db295 /src/app/App.svelte
parentaa8b086cd2ec47038e5b35d2295260114651bf8f (diff)
downloaddispatch-web-b74357495e443ff6011531d296560caff9398a14.tar.gz
dispatch-web-b74357495e443ff6011531d296560caff9398a14.zip
feat(chat): reasoning-effort selector — sticky per-conversation thinking-depth knob
Consume the backend's reasoning-effort handoff ([email protected] ReasoningEffort + [email protected] GET/PUT /conversations/:id/reasoning-effort, ChatRequest.reasoningEffort): a 5-level selector in the sidebar Model view, under the provider + model dropdowns. null renders as 'high (default)' per the server-owned resolution chain; PUT on change (effective next turn); error + revert on 400; per-conversation re-mount incl. drafts (the draft id survives promotion, so an effort set on a draft applies from turn 1). Re-mirrored .dispatch references; GLOSSARY 'reasoning effort'; handoff updated. 616 tests green; live curl probe passed.
Diffstat (limited to 'src/app/App.svelte')
-rw-r--r--src/app/App.svelte21
1 files changed, 18 insertions, 3 deletions
diff --git a/src/app/App.svelte b/src/app/App.svelte
index 4c5a82b..dffa937 100644
--- a/src/app/App.svelte
+++ b/src/app/App.svelte
@@ -1,4 +1,5 @@
<script lang="ts">
+ import type { ReasoningEffort } from "@dispatch/transport-contract";
import type { InvokeMessage } from "@dispatch/ui-contract";
import { tick } from "svelte";
import Table from "../components/Table.svelte";
@@ -12,6 +13,8 @@
Composer,
manifest as chatManifest,
ModelSelector,
+ ReasoningEffortSelector,
+ type ReasoningEffortSaveResult,
} from "../features/chat";
import { manifest as conversationCacheManifest } from "../features/conversation-cache";
import { manifest as markdownManifest } from "../features/markdown";
@@ -154,6 +157,17 @@
: { ok: false, error: result.error };
}
+ // Adapt the store's reasoning-effort result to the chat feature's port.
+ async function saveReasoningEffort(
+ level: ReasoningEffort,
+ ): Promise<ReasoningEffortSaveResult | null> {
+ const result = await store.setReasoningEffort(level);
+ if (result === null) return null;
+ return result.ok
+ ? { ok: true, reasoningEffort: result.reasoningEffort }
+ : { ok: false, error: result.error };
+ }
+
// Adapt the store's cwd/LSP results to the workspace feature's ports.
async function saveCwd(cwd: string): Promise<CwdSaveResult | null> {
const result = await store.setCwd(cwd);
@@ -295,10 +309,11 @@
{#if kind === "model"}
<div class="flex flex-col gap-3">
<ModelSelector models={store.models} selected={store.activeModel} onSelect={handleSelectModel} />
- <!-- Keyed on the workspace conversation (active tab OR draft) so the input
- re-mounts per conversation — incl. switching between drafts — and can't
- bleed across tabs. Editable for a draft too (cwd applies from turn 1). -->
+ <!-- Keyed on the workspace conversation (active tab OR draft) so the inputs
+ re-mount per conversation — incl. switching between drafts — and can't
+ bleed across tabs. Editable for a draft too (cwd + effort apply from turn 1). -->
{#key store.currentConversationId}
+ <ReasoningEffortSelector persisted={store.reasoningEffort} save={saveReasoningEffort} />
<CwdField cwd={store.cwd} canEdit={true} save={saveCwd} />
{/key}
</div>