summaryrefslogtreecommitdiffhomepage
AgeCommit message (Collapse)Author
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-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.
2026-06-22fix: trim provisional chunks during long turns (browser stays responsive)Adam Malczewski
trimTranscript now drops oldest provisional chunks (the in-flight turn) when committed chunks are exhausted. Previously it bailed with drop=0 when committed was empty, allowing unbounded provisional growth during long generating turns (300+ chunks → browser crawls). Root cause of the syncTail approach failing: the kernel emits step-complete (line 360) BEFORE calling onStepComplete (line 542) — chunks are persisted only after tool results come back, not when step-complete fires. So syncTail on step-complete found nothing. Reverted the applyHistory + syncTail-on-step-complete changes from 4e1d041. The new approach is simpler: trim provisional directly in trimTranscript. Dropped chunks are lost temporarily (no Show Earlier) but come back as committed when the turn seals and syncTail fetches everything from the server. 686 tests green.
2026-06-22feat: trim chunks during generation via step-complete syncTail (CR-6)Adam Malczewski
The backend now persists chunks at step boundaries during generation (CR-6). The FE calls syncTail on each step-complete event to fetch the newly committed chunks. applyHistory clears the provisional array when new committed chunks arrive mid-generation (they're duplicates of what was folded from live events). The accumulating chunk (current in-progress step) is kept. This means trimTranscript can now drop oldest committed chunks uniformly during a long turn — no unbounded provisional growth. The browser never holds more than chatLimit chunks, even mid-generation. 3 new tests: clears provisional on new committed during generation, keeps provisional when no new chunks, keeps accumulating when clearing. 689 tests green.
2026-06-22docs: update backend-handoff — CR-6 resolved by backend, trim for relevanceAdam Malczewski
Backend shipped incremental seq assignment at step boundaries during generation. Marked CR-6 as RESOLVED with the FE adoption plan (option c: fold events for current step only, syncTail for sealed steps). Trimmed the verbose resolved-CR history to a compact table — the code is the source of truth now. 686 tests green.
2026-06-22fix(metrics): show turn/step metrics for compacted conversationsAdam Malczewski
Compacted conversations start with a system summary (role: "system") instead of a user message (role: "user"). The interleaveTurnMetrics function only detected segments by role === "user", so compacted conversations got zero segments and no metrics were emitted. Fix: when no user messages are found but metrics entries exist, treat the entire transcript as one segment. This places turn-metrics at the end and anchors step-metrics to any tool-batch groups by stepId. 686 tests green.
2026-06-22fix(metrics): tail-align when stepId matching fails — prevent misaligned turnsAdam Malczewski
When stepIds are absent on persisted chunks (or don't match), the sequential fallback was HEAD-aligning — matching the OLDEST entries (trimmed turns) to the NEWEST segments. This showed 'turn 1' on turn 20's content and placed the wrong metrics on the wrong segments. Fix: when stepId matching produces ZERO matches, use TAIL-ALIGNMENT instead — match the LAST T entries to the T segments (the loaded chunks are always the newest). The oldest entries (trimmed turns) are unmatched and emit standalone turn-metrics rows at the top. 686 tests green.
2026-06-22fix(metrics): preserve turn-metrics for trimmed turnsAdam Malczewski
When the chat limit unloads a turn's content (user message + chunks), the segment disappears and the turn-metrics row was lost. Now unmatched entries (fully trimmed turns) emit a standalone turn-metrics row at the top of the transcript, so the user still sees 'turn N · X tok' for unloaded turns. Note: trimming during generation only affects COMMITTED chunks (old turns). Provisional chunks (the in-flight turn) are never trimmed — the big trim happens at seal when provisional → committed. This is by design.
2026-06-22feat(metrics): show turn number in metrics bubble (turn N · ...)Adam Malczewski
The turn number comes from the entry's position in the metrics array (1-based), which is correct regardless of trimming since stepId matching aligns segments to the right entry. Now displays 'turn 3 · 12k tok' instead of just 'turn · 12k tok'.
2026-06-22fix(metrics): skip unanchored step-metrics — no more empty bubbles at tailAdam Malczewski
Step-metrics are only shown when anchored to their tool content (inline after the tool-call/result group). Steps whose chunks were trimmed (or text-only steps with no tool chunks) are now SKIPPED instead of piling up at the segment tail as empty 'step N · X tok' bubbles. The turn-total metrics row still shows the aggregate (tokens, duration, cache rate), so the conversation-level summary is preserved. Updated place.test.ts + ui.test.ts to anchor steps with tool-call groups where step-metrics are expected.
2026-06-22feat: show 5-char git hash next to hamburger for cache-bust detectionAdam Malczewski
Vite define bakes __APP_VERSION__ (git rev-parse --short=5 HEAD) at build time — survives bundling into the arch package deploy. Falls back to 'dev' when not in a git repo. Also fixes two noNonNullAssertion warnings in place.ts.
2026-06-22fix(metrics): stepId-based segment matching — robust against chat-limit ↵Adam Malczewski
trimming When the chat limit trims old chunks, head-aligning turn metrics to segments by position breaks (a trimmed user message removes a segment boundary, shifting all subsequent alignments by one). Fix: match segments to metrics entries by stepId overlap (pass 1), falling back to sequential matching for text-only segments with no stepId-bearing groups (pass 2). This prevents step/turn metrics from being placed on the wrong segment after trimming, while preserving the original behavior for text-only turns. 686 tests green.