summaryrefslogtreecommitdiffhomepage
AgeCommit message (Collapse)Author
2026-06-27feat(concurrency): 'Saved.' confirmation on the limit row + handoff updateAdam Malczewski
Backend now persists concurrency limits across reboots (no API contract change — same endpoints/shapes, so no re-pin/re-mirror needed). Taking the suggested optional UX hint: after a successful Save the limit row shows a brief green 'Saved.' that clears on the next edit (mirrors the ChatLimitField pattern). backend-handoff.md §2j: notes the persistence change + the two earlier backend-only changes (200ms release cooldown; 'queued' status — already shipped as CR-13). typecheck 0/0, 926 tests green, biome clean, build OK.
2026-06-27style(concurrency): drop the verbose section descriptionsAdam Malczewski
The 'Concurrency limits' and 'Live status' section headings are clear on their own; the explanatory paragraphs under each were overbearing. Removed both.
2026-06-27style(concurrency): use DaisyUI loading-ring for the queued indicatorAdam Malczewski
The 'queued' (waiting-for-a-concurrency-slot) indicator on the tab + composer corner used loading-spinner; switch to DaisyUI's loading-ring. The 'active' (generating) indicator stays loading-dots. typecheck 0/0, 926 tests green, biome clean, build OK.
2026-06-27fix(concurrency): silent background refresh — no loading flickerAdam Malczewski
The 2s status poll (and post-mutation limit reloads) toggled a visible loading state, but since the refresh is near-instant the spinner flashed for <1 frame — a visible flicker/jerk every poll. The polling is now SILENT (mirrors the heartbeat runs list): - refreshLimits/refreshStatus: re-entrancy guard (limitsInFlight/statusInFlight, no UI), no loading-state toggle. Error cleared only on success so it stays visible + stable during an in-flight retry (no vanish-mid-poll). - Removed limitsLoading/statusLoading: the Refresh buttons are plain-text (no spinner, not disabled); the empty-state guards use hasLoaded* only (no && !loading), so the list area never reflows mid-refresh. +1 regression-guard test (Refresh buttons never surface a spinner). typecheck 0/0, 926 tests green (x2), biome clean, build OK.
2026-06-27feat(concurrency): loading-ring for queued chats (CR-13 consumed)Adam Malczewski
Backend shipped "queued" ConversationStatus (additive to [email protected]): when a request blocks on a concurrency slot, conversation.statusChanged broadcasts "queued" (broadcast-only, never persisted); "active" on slot grant. FE consumes it: - WS parser (adapters/ws/logic.ts): accepts "queued" in the status set. - Store handler: "queued" updates the status map + opens a tab for a new cross-device queued conversation (like "active"). - TabList: status === "queued" -> loading-ring (spinner, aria-label "Queued"); "active" -> loading-dots (unchanged). - Composer: status type widened to ComposerStatus (idle|running|queued|error), exported from features/chat. "queued" -> a loading-ring status icon + placeholder "Queued for a slot…"; behaves like "running" for the send button (steer/stop — the turn is in flight, just waiting for a slot). - App.svelte: composerStatus derived (error > queued > running > idle) — conversationStatus === "queued" wins over generating so the corner shows a ring during the wait (turn-start fires before the slot is granted, so generating is already true while status === "queued"). - Re-mirrored .dispatch/wire.reference.md (ConversationStatus widened + header). Tests: WS parser accepts queued; store handler sets status + opens a cross-device tab + transitions queued->active->idle; TabList renders a ring for queued + dots for active. typecheck 0/0, 925 tests green (x2), biome clean, build OK. backend-handoff.md CR-13 marked RESOLVED.
2026-06-27docs(handoff): CR-13 — per-conversation 'queued' status for the ↵Adam Malczewski
concurrency queue A small UX ask (queued chat -> loading ring, generating -> loading dots, in the tab + composer corner) needs a backend change: there is no FE-derivable per- conversation 'queued' signal (turn-start sets generating before the queue wait; concurrency status is per-provider aggregate; background tabs only get the conversation.statusChanged broadcast). Add 'queued' to ConversationStatus (@dispatch/wire) + emit it from the concurrency extension when acquire() blocks. Sent to backend agent e1d7; FE side fully designed, blocked on the wire bump. Header notes the dev merge (e81df4c, 921 tests green).
2026-06-27Merge branch 'dev' into feature/provider-concurrencyAdam Malczewski
2026-06-27feat(concurrency): provider dropdown instead of free-text inputAdam Malczewski
Replace the Add-form provider text input with a <select> dropdown populated from the available models' provider prefixes (<provider>/<model>), unioned with providers already carrying a configured limit (so a limit set out-of-band but whose model list is empty still appears). The selection auto-defaults to the first option and falls back when an option disappears. - logic/view-model.ts: pure providerFromModel + providerOptions(models, limits) (distinct provider ids, first-seen order) + 7 tests. - ConcurrencyView.svelte: models prop + <select> bound to newProviderId; disabled + 'No providers available' when there are no models. - App.svelte: pass models={store.models}; component test updated to the dropdown (selectOptions) + a no-models case (6 component tests). Verified: typecheck 0/0, 922 tests green, biome clean, build OK.
2026-06-27feat(sidebar-tabs): add dashboard home button + same-tab workspace openAdam Malczewski
2026-06-27feat(sidebar-tabs): prefix build hash with "build: "Adam Malczewski
2026-06-27fix(sidebar-tabs): align chat scrollbar with composer instead of flush ↵Adam Malczewski
against sidebar
2026-06-27feat(sidebar-tabs): use daisyui loading-dots for chat generating spinnersAdam Malczewski
2026-06-27fix(sidebar-tabs): use text-selection highlight as copy indicator instead of ↵Adam Malczewski
swapping text
2026-06-27feat(sidebar-tabs): click tab ID badge to copy conversation idAdam Malczewski
2026-06-27fix(sidebar-tabs): drop sidebar left padding so it shares the chat gutterAdam Malczewski
2026-06-27feat(sidebar-tabs): remove sidebar left borderAdam Malczewski
2026-06-27feat(sidebar-tabs): replace hamburger with directional double-chevron toggleAdam Malczewski
2026-06-27fix(sidebar-tabs): inset top-bar title 8px left to match parent px-2 spacingAdam Malczewski
2026-06-27feat(sidebar-tabs): add 2px horizontal spacing to top-bar titleAdam Malczewski
2026-06-27feat(sidebar-tabs): add active tab title to top bar (New Tab for unstarted ↵Adam Malczewski
chats)
2026-06-27docs(concurrency): expand backend handoff §2j + drop unused importAdam Malczewski
- backend-handoff.md: full §2j slice (API surface, contract note, FE summary, verification, the single-provider GET note, worktree symlink note) + bump the pinned transport-contract version 0.22.0 → 0.23.0 in the header/packages/ mirror/endpoints sections. - ConcurrencyView.svelte: remove an unused ConcurrencyLimitView type import (the type flows via viewConcurrencyLimits' return type; svelte-check clean).
2026-06-27feat(concurrency): add provider concurrency limits UI — settings + live statusAdam Malczewski
2026-06-27feat(sidebar-tabs): move tab bar from top into sidebar as vertical listAdam Malczewski
2026-06-27Merge branch 'dev' into feature/heartbeatAdam Malczewski
# Conflicts: # src/app/App.svelte # src/app/store.svelte.ts # src/app/store.test.ts # src/features/workspaces/ui/WorkspaceCard.test.ts
2026-06-27Merge branch 'feature/indent-change' into devAdam Malczewski
2026-06-27chore: update path references for directory rename (dispatch-backend → ↵Adam Malczewski
backend, dispatch-web → frontend)
2026-06-27feat(heartbeat): show next heartbeat timer + backend handoff for timestamp ↵Adam Malczewski
endpoint
2026-06-26fix(heartbeat): hide runs loading state to prevent sidebar flickerAdam Malczewski
2026-06-26fix(heartbeat): PromptEditor save not persisting — flickers and revertsAdam Malczewski
2026-06-26style: switch from tabs to 2-space indentation (incl. svelte)Adam Malczewski
2026-06-26feat(heartbeat): default system prompt to workspace default + reset buttonAdam Malczewski
2026-06-26fix(heartbeat): make PromptEditor modal truly fullscreenAdam Malczewski
2026-06-26feat(heartbeat): prompt editor modal + hours/minutes timer + backend handoffAdam Malczewski
2026-06-26feat(heartbeat): heartbeat view with config, run list, live chat modal, and ↵Adam Malczewski
sidebar wiring
2026-06-25Merge branch 'feature/ssh-support' into devAdam Malczewski
# Conflicts: # src/features/workspaces/ui/WorkspaceCard.svelte # src/features/workspaces/ui/WorkspaceCard.test.ts # src/features/workspaces/ui/WorkspacesHome.svelte
2026-06-25fix(computer): show ✓ check after a successful Test (not a stuck spinner)Adam Malczewski
When the user clicks Test, the button now transitions spinner → ✓ (green) on success / ✗ (red) on failure (persisting until the next test or computer change), instead of reverting to plain 'Test' text with no success indicator. Also refresh the connection-status badge immediately after a test completes, so a stale 'connecting' spinner caught by the 4s poll mid-test is cleared and the badge reflects the real post-test state. Clear the test result when the selected computer changes so a stale ✓ from alias A doesn't persist for alias B.
2026-06-25docs(handoff): mark §2d provider-retry divergence RESOLVED (backend merge ↵Adam Malczewski
de022ce) Backend merged dev into feature/ssh-support (de022ce): TurnProviderRetryEvent is now present alongside the SSH types. FE re-synced both file: deps; typecheck is GREEN (0/0) with ZERO FE code changes (the consumer was already complete). Full suite: 795/795 tests, biome clean, build OK. §2e verified post-merge.
2026-06-25feat(computer): SSH computer selection + status + workspace default (handoff #2)Adam Malczewski
Mirrors the cwd/workspace UI for the SSH-computer feature: - New feature library src/features/computer/: - logic/view-model.ts (pure): viewComputer/viewComputerStatus/viewTestResult/ summarizeComputers/formatHost/knownHostLabel + state->badge for the 4 ComputerStatusResponse states + SaveComputer/LoadComputerStatus/ TestComputer/LoadComputers ports. 20 view-model tests. - ui/ComputerField.svelte: per-conversation selector (dropdown + connection-status badge + Test-connection, polling the selected alias). - ui/ComputerSelect.svelte: reusable Local/computers dropdown, shared with the workspace default-computer control. - AppStore: computerId state + refreshComputer (at every focus site, parallel to refreshCwd) + setComputer (PUT /conversations/:id/computer, null=clear) + global computers catalog (GET /computers on boot, like models) + computerStatus(alias) + testComputer(alias). chat.send UNCHANGED (resolved server-side like cwd). - App.svelte: ComputerField in the Model sidebar view next to CwdField; adapted ports wrap the store. - workspaces: setDefaultComputer on WorkspaceHttp+WorkspaceStore (PUT /workspaces/:id/default-computer); default-computer selector in WorkspaceCard (reuses ComputerSelect); router passes store.computers through. - Re-mirrored .dispatch/transport-contract.reference.md (Computers section + ChatRequest.computerId); updated .dispatch/wire.reference.md (Computer/ ComputerEntry/defaultComputerId + the provider-retry divergence note from handoff #1); GLOSSARY + backend-handoff.md (handoff #2, §2e). Transparency invariant: the computer is USER-facing only (a tool-execution target, never part of the model prompt); the agent never sees it. Verify: 795/795 tests green; biome clean; vite build succeeds; 0 typecheck errors from the computer feature. (11 pre-existing svelte-check errors remain from the open §2d provider-retry divergence — backend feature/ssh-support still lacks TurnProviderRetryEvent; not from this feature.)
2026-06-25feat(workspaces): open workspace in a new browser tabAdam Malczewski
The 'Open' button on a workspace card did client-side navigation (onNavigate -> pushState), opening the workspace in the SAME tab. Replace the JS click handler with a native anchor using target="_blank" (+ rel=noopener noreferrer) so clicking Open opens the workspace in a NEW browser tab. The new tab does a full load and routes to /<id> via the existing parsePath -> App wiring. The card no longer needs the onNavigate prop (its only navigation was the Open button), so drop it from WorkspaceCard + WorkspacesHome and update the card tests to assert the new-tab link attributes instead of the onNavigate call.
2026-06-25feat(tabs): show full title in tab hover tooltipAdam Malczewski
The conversation tab's title span was truncated with a static 'Double-click to rename' tooltip. Replace the static title with the full tab.title so hovering reveals the complete conversation title (the truncate class still clips the visible label).
2026-06-25feat: workspaces shell + cwd-lsp rename + mcp/settings/system-prompt ↵Adam Malczewski
features + app wiring - workspaces: URL-driven conversation grouping (home listing at /, routing, store, http adapter, WorkspaceCard) wired into the App.svelte shell - rename features/workspace -> features/cwd-lsp (the cwd/lsp status feature) - new features: mcp (status view), settings (chat-limit field), system-prompt (prompt builder), all rendered via the generic surface host - chat: store + ChatView updates - tabs: tabs-store updates - app wiring: ErrorModal (full-screen error surface), app/App.svelte + store.svelte This commit makes HEAD typecheck clean for the first time: the prior HEAD (c95cc77) imported features/settings from app/App.svelte but never committed the feature, so only the full working tree was green.
2026-06-25feat(core): chunks retry-banner, wire conformance, ws logic, history adapterAdam Malczewski
- core/chunks: add retry-banner view-model (+test), update reducer/selectors/types - core/wire: update conformance checks (+test) - adapters/ws: update reconnect logic (+tests) - adapters/history: new client-side routing adapter (history + popstate wrapper)
2026-06-25chore: regenerate contract mirrors, bump deps, update docs/notes/scriptsAdam Malczewski
- Regenerate .dispatch/{wire,transport-contract}.reference.md mirrors - Bump deps (package.json, bun.lock) - Update AGENTS.md, GLOSSARY.md, README.md, ROADMAP.md - Add workspaces backend-handoff exchange + notes/assumptions-log.md - Add scripts/fix-dist-perms.sh (root-owned dist/ from Docker build) - Add scripts/live-probe-provider-retry.ts
2026-06-22fix: duplicate user message on first send in a new tabAdam Malczewski
When a draft is promoted to a real conversation, send() appends the user message as a provisional chunk (optimistic echo). But load() also fires syncTail, which fetches the CR-6 persisted user message as a committed chunk — showing the message twice until turn seal. Fix: applyHistory now removes provisional chunks that duplicate the last committed chunk (matching role + text content) when new committed chunks arrive during generation. The optimistic echo is dropped once the authoritative committed version arrives. 684 tests green.
2026-06-22feat: double-click tab to rename (PUT /conversations/:id/title)Adam Malczewski
Double-click a tab's title to enter inline edit mode. Enter or click away (blur) saves; Escape cancels. The rename is optimistic — the local tab updates immediately and PUT /title fires in the background. 683 tests green.
2026-06-22feat: switch theme from dracula to monokai (custom)Adam Malczewski
Replace dracula with a custom monokai theme (from dachinat/daisyui-themes, with modifications: all -content colors set to black, base-300 changed to #3b3a3a). Dracula is unloaded; monokai is the sole bundled theme and default. Also adds .env.development (dev ports 24203/24205) and .env.production (arch ports 24991/24990) so Vite uses the correct backend per mode. Excludes src/themes/ from biome (third-party CSS). 683 tests green.
2026-06-22feat: consume context window + percentage-based compact handoffAdam Malczewski
1. Real context window: GET /models now returns modelInfo[model].contextWindow. The Composer uses this instead of the hardcoded MAX_CONTEXT = 1,000,000. Falls back to 1M when modelInfo is absent or the model has no contextWindow. 2. Percentage-based auto-compact: the compact-threshold endpoint is renamed to compact-percent. The CompactionView now shows a percent input (0-100, default 85, 0 = manual) instead of a token count input. Types renamed: CompactThresholdResponse → CompactPercentResponse, SetCompactThresholdRequest → SetCompactPercentRequest. Note: the field name in the backend types is still 'threshold' (not 'percent') — the FE maps between them. Re-mirrored .dispatch/transport-contract.reference.md. 686 tests green. 0 svelte-check errors + warnings.
2026-06-22feat: persist sidebar layout + open/closed state between refreshesAdam Malczewski
Sidebar panel layout (which views are open and their order) and the sidebar open/closed toggle are now persisted to localStorage. Default layout is just the Model view at the top. - ViewSidebar accepts an onChange callback that reports panel kinds - App.svelte creates two createLocalStore instances (dispatch.sidebar.views + dispatch.sidebar.open) using the store's storage adapter - AppStore exposes its storage instance so the shell persists via the same adapter (test-injectable, not globalThis.localStorage) - Tests pre-populate fake storage with ["extensions"] for the 4 tests that need the Extensions view visible 686 tests green. 0 svelte-check warnings (2 pre-existing errors from missing transport-contract exports, unchanged).
2026-06-22feat: collapsible tool output (collapsed by default like thinking)Adam Malczewski
Tool calls and results now use the same DaisyUI collapse pattern as thinking blocks — collapsed by default, click to expand. Each card shows the tool name + a wrench icon in the title; expanding reveals the input/output with overflow-x-auto for long lines and max-h-96 overflow-y-auto for very long output. Batched tool calls: each entry is its own collapse card (was a DaisyUI list). Pending results show a spinner in the title. Errors show a red badge. 686 tests green.
2026-06-22fix: tool output scrolls within its container instead of bleeding outAdam Malczewski
Add overflow-hidden to tool card containers and overflow-x-auto to <pre> elements so long tool output (file contents, JSON, etc.) gets its own scrollbar instead of expanding the chat width and creating a horizontal scrollbar on the entire transcript. 686 tests green.