diff options
| author | Adam Malczewski <[email protected]> | 2026-06-27 20:20:02 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-27 20:20:02 +0900 |
| commit | f5dc22f7c14d6c0dd4bcedee5a85b21ecd294aed (patch) | |
| tree | 8ba78efaefc25148dfb550b4332204822f5acf5d /src/app | |
| parent | fa0bd9c0e433b1abddc814b48a358c94954c7d36 (diff) | |
| download | dispatch-web-f5dc22f7c14d6c0dd4bcedee5a85b21ecd294aed.tar.gz dispatch-web-f5dc22f7c14d6c0dd4bcedee5a85b21ecd294aed.zip | |
feat(vision): resolve persisted image URLs against the API base
Images are now stored on disk under tmp (not SQLite) and served via
GET /images/:conversationId/:imageId. Persisted ImageChunk.url is a compact
relative HTTP path (/images/<conv>/<uuid>.png) instead of a base64 data URL.
No wire/transport-contract type change (behavior only) — re-mirrored the
delta notes.
- New pure resolveImageUrl(url, apiBase) helper (core/chunks/image-url.ts,
+8 tests): data/absolute URLs pass through; relative paths are prepended
with the API base (no double slash; empty base -> root-relative). Exported
from core/chunks + re-exported from features/chat.
- ChatView: new apiBaseUrl prop; <img src> uses resolveImageUrl. The
optimistic echo's data URL passes through; persisted relative paths
resolve against the base. +3 tests.
- AppStore exposes httpBase (getter); App.svelte passes apiBaseUrl into
ChatView and the heartbeat RunModal (also renders image chunks).
Verification: svelte-check 0/0; vitest 959/959 (run twice, +11); biome
clean; vite build OK. See backend-handoff.md §2j-update-2.
Not merged or pushed.
Diffstat (limited to 'src/app')
| -rw-r--r-- | src/app/App.svelte | 2 | ||||
| -rw-r--r-- | src/app/store.svelte.ts | 9 |
2 files changed, 11 insertions, 0 deletions
diff --git a/src/app/App.svelte b/src/app/App.svelte index f41d7ba..7d70f67 100644 --- a/src/app/App.svelte +++ b/src/app/App.svelte @@ -516,6 +516,7 @@ onShowEarlier={handleShowEarlier} thinkingKeyBase={store.activeChat.thinkingKeyBase} providerRetry={store.activeChat.providerRetry} + apiBaseUrl={store.httpBase} /> {/key} </div> @@ -610,6 +611,7 @@ closeChat={closeRunChat} stopRun={stopHeartbeatRun} onClose={() => (heartbeatRun = null)} + apiBaseUrl={store.httpBase} /> {/key} {/if} diff --git a/src/app/store.svelte.ts b/src/app/store.svelte.ts index 554d5e0..8353820 100644 --- a/src/app/store.svelte.ts +++ b/src/app/store.svelte.ts @@ -157,6 +157,12 @@ export interface AppStore { readonly activeConversationId: string | null; /** The workspace currently in view (URL slug); tabs are filtered to it. */ readonly activeWorkspaceId: string; + /** + * The resolved HTTP API base URL (e.g. `http://localhost:24203`). Used to + * resolve relative image URLs served by the backend (`/images/…`) into + * absolute URLs for `<img src>`. + */ + readonly httpBase: string; readonly activeChat: ChatStore; readonly models: readonly string[]; /** Per-model metadata (contextWindow, etc.) from `GET /models`. */ @@ -1127,6 +1133,9 @@ export function createAppStore(opts?: CreateAppStoreOptions): AppStore { get activeWorkspaceId(): string { return activeWorkspaceId; }, + get httpBase(): string { + return httpBase; + }, setActiveWorkspace(workspaceId: string): void { activeWorkspaceId = workspaceId; // Reset to a fresh draft scoped to the new workspace so a new chat is |
