diff options
| author | Adam Malczewski <[email protected]> | 2026-08-02 13:49:14 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-08-02 13:49:14 +0900 |
| commit | 42cada78db1e58947074f12dcf7c8e41fc501b40 (patch) | |
| tree | b3a2c70c9cf8ea2046ed93999cecd65edc840e2c | |
| parent | 65ebbef310b619251cccf55b6c13a94d7b9538da (diff) | |
| download | dispatch-web-42cada78db1e58947074f12dcf7c8e41fc501b40.tar.gz dispatch-web-42cada78db1e58947074f12dcf7c8e41fc501b40.zip | |
feat(vision): add dedicated Vision settings view, move vision model setting out of Compaction
| -rw-r--r-- | src/app/App.svelte | 8 | ||||
| -rw-r--r-- | src/app/App.test.ts | 23 |
2 files changed, 28 insertions, 3 deletions
diff --git a/src/app/App.svelte b/src/app/App.svelte index f0cd7ec..e50648a 100644 --- a/src/app/App.svelte +++ b/src/app/App.svelte @@ -125,6 +125,7 @@ { id: "cache-warming", label: "Cache Warming" }, { id: "tasks", label: "Tasks" }, { id: "compaction", label: "Compaction" }, + { id: "vision", label: "Vision" }, { id: "heartbeat", label: "Heartbeat" }, { id: "concurrency", label: "Concurrency" }, { id: "system-prompt", label: "System Prompt" }, @@ -814,8 +815,7 @@ {/key} {:else if kind === "compaction"} <!-- Message compaction is per-conversation (keyed so the percent + feedback - can't bleed across tabs). Vision (image-compaction) settings are GLOBAL, - so they stay mounted across conversation switches (no {#key}). --> + can't bleed across tabs). --> {#key store.currentConversationId} <CompactionView percent={store.compactPercent} @@ -824,7 +824,9 @@ savePercent={saveCompactPercent} /> {/key} - <div class="divider my-1 text-xs text-base-content/40">Image compaction</div> + {:else if kind === "vision"} + <!-- Global vision settings (image-compaction limit + model). Not + conversation-scoped (no {#key}), so they stay mounted across tab switches. --> <VisionSettingsView models={store.models} modelInfo={store.modelInfo} diff --git a/src/app/App.test.ts b/src/app/App.test.ts index dcdcb9b..f43a6b8 100644 --- a/src/app/App.test.ts +++ b/src/app/App.test.ts @@ -73,6 +73,11 @@ function fakeFetchImpl(): typeof fetch { status: 200, }); } + if (url.endsWith("/settings/vision")) { + return new Response(JSON.stringify({ imageLimit: 10, compactionModel: null }), { + status: 200, + }); + } return new Response(JSON.stringify({ chunks: [], latestSeq: 0 }), { status: 200 }); }; } @@ -583,4 +588,22 @@ describe("App component interaction tests", () => { store.dispose(); }); + + it("the Vision view renders the vision settings UI (image limit + compaction model)", async () => { + const ws = fakeSocket(); + const store = createAppStore({ + socketFactory: () => ws, + fetchImpl: fakeFetchImpl(), + localStorage: createFakeStorageWithViews(["vision"]), + }); + ws.resolveOpen(); + + render(App, { props: { store, onNavigate: vi.fn() } }); + + // The vision settings load (`GET /settings/vision`) seeds the inputs. + expect(await screen.findByLabelText(/Image limit/)).toBeInTheDocument(); + expect(await screen.findByLabelText(/Compaction model/)).toBeInTheDocument(); + + store.dispose(); + }); }); |
