From 084f4d75fce7d27b5d06ae73d741ecb121b55c17 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Tue, 2 Jun 2026 14:30:57 +0900 Subject: Fix cache req badge wrap, remove cache cost note, pace-aware key usage bars --- .../src/lib/components/CacheRatePanel.svelte | 7 +------ .../frontend/src/lib/components/KeyUsage.svelte | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/packages/frontend/src/lib/components/CacheRatePanel.svelte b/packages/frontend/src/lib/components/CacheRatePanel.svelte index c35cbb5..88985a0 100644 --- a/packages/frontend/src/lib/components/CacheRatePanel.svelte +++ b/packages/frontend/src/lib/components/CacheRatePanel.svelte @@ -55,7 +55,7 @@ const lastHitPct = $derived( {#if tabTitle} {tabTitle} {/if} - {cacheStats.requests} req + {cacheStats.requests} req @@ -120,10 +120,5 @@ const lastHitPct = $derived( - -

- Cache reads cost ~10% of fresh input; writes cost ~25% more. A high hit - rate after the first turn means caching is working. Resets on reload. -

{/if} diff --git a/packages/frontend/src/lib/components/KeyUsage.svelte b/packages/frontend/src/lib/components/KeyUsage.svelte index 00d179e..7c0cadc 100644 --- a/packages/frontend/src/lib/components/KeyUsage.svelte +++ b/packages/frontend/src/lib/components/KeyUsage.svelte @@ -131,6 +131,17 @@ function progressClass(utilization: number): string { return "progress-success"; } +// Pace-aware coloring for cycle bars that show a "time dot" (elapsed % of the +// reset window). Red once usage hits 90%, otherwise green when usage is at or +// behind the dot and orange when it has run ahead of it. Falls back to the +// plain threshold coloring when no dot is present (elapsedPct < 0). +function pacedProgressClass(percentUsed: number, elapsedPct: number): string { + if (percentUsed >= 90) return "progress-error"; + if (elapsedPct < 0) return progressClass(percentUsed / 100); + if (percentUsed <= elapsedPct) return "progress-success"; + return "progress-warning"; +} + function formatDate(ts: number): string { const diff = ts - Date.now(); const days = Math.floor(diff / 86400000); @@ -245,7 +256,7 @@ function hasBucketData(bucket: UsageBucket | undefined): boolean { {p}%
- + {#if tp >= 0}
{/if} @@ -266,7 +277,7 @@ function hasBucketData(bucket: UsageBucket | undefined): boolean { {p}%
- + {#if tp >= 0}
{/if} @@ -330,7 +341,7 @@ function hasBucketData(bucket: UsageBucket | undefined): boolean { {p}%
- + {#if tp >= 0}
{/if} @@ -351,7 +362,7 @@ function hasBucketData(bucket: UsageBucket | undefined): boolean { {p}%
- + {#if tp >= 0}
{/if} @@ -372,7 +383,7 @@ function hasBucketData(bucket: UsageBucket | undefined): boolean { {p}%
- + {#if tp >= 0}
{/if} -- cgit v1.2.3 From 3f0bfe76ceabd1cb53727f1d9ae84d7494054d7f Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Tue, 2 Jun 2026 14:31:37 +0900 Subject: Add HANDOFF.md for m1/minor-fixes --- HANDOFF.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 HANDOFF.md diff --git a/HANDOFF.md b/HANDOFF.md new file mode 100644 index 0000000..8d6960b --- /dev/null +++ b/HANDOFF.md @@ -0,0 +1,38 @@ +# Handoff — m1/minor-fixes + +Three small, independent UI fixes in the Dispatch frontend. + +## Files changed +- `packages/frontend/src/lib/components/CacheRatePanel.svelte` + - **Fix 1:** Added `whitespace-nowrap` to the requests-count badge (`{cacheStats.requests} req`) so it no longer wraps to a second line. + - **Fix 2:** Removed the trailing explanatory paragraph ("Cache reads cost ~10% of fresh input; writes cost ~25% more…"). +- `packages/frontend/src/lib/components/KeyUsage.svelte` + - **Fix 3:** Added `pacedProgressClass(percentUsed, elapsedPct)` and applied it to the 5 bars that render a "time dot" (Claude 5-Hour/Weekly, opencode-go 5-Hour/Weekly/Monthly). + +## Public surface changed +- None externally. No exported API, prop, or type changes. +- New module-internal helper `pacedProgressClass` in `KeyUsage.svelte` (not exported). Existing `progressClass` retained and reused as the fallback. + +## Fix 3 coloring logic +`pacedProgressClass(percentUsed, elapsedPct)`: +- `percentUsed >= 90` → `progress-error` (red) — always, per spec. +- no time dot (`elapsedPct < 0`, e.g. missing `resetsAt`) → fall back to existing `progressClass` thresholds. +- `percentUsed <= elapsedPct` → `progress-success` (green; equal counts as green/on-pace). +- otherwise (usage ran ahead of the dot) → `progress-warning` (orange). + +Applied only to the 5 dot-bearing bars. The 3 Copilot/Gemini bars were intentionally left on the original `progressClass` (confirmed unused/out of scope by the requester). + +## Verification status — PASS +- `bun run check` (biome): **PASS** — "Checked 163 files… No fixes applied." +- `bun run test` (vitest): **PASS** — 35 test files, 552 tests passed. +- Re-verified after `git merge --no-edit dev` (was already up to date) — still all-green. +- Note: `bun install` was required first; deps were not present in the worktree. + +## Published +- Yes. Committed `084f4d7`, merged `dev` down (already up to date), pushed fast-forward `7c527b4..084f4d7 → dev`. + +## Assumptions / known gaps +- Per requester: Copilot & Gemini usage bars are unused, so they keep the old threshold coloring (untouched). +- Red threshold is `>= 90%` (exactly 90 is red); tie between usage and the dot resolves to green — both confirmed by requester. +- Dot-less / hidden-dot cycle bars fall back to the original `progressClass` thresholds (confirmed option "a"). +- Changes are presentation-only (Tailwind/daisyUI classes + a coloring helper); no automated tests were added for the Svelte markup, consistent with the existing repo (no component-render tests for these panels). User visually confirmed the result before publish. -- cgit v1.2.3 From 2756730aeba633c3cc331500bcfb9a67d85dc892 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Tue, 2 Jun 2026 14:39:20 +0900 Subject: Add status bar beneath chat input with send/stop button and context display Restructure ChatInput into two stacked bars: - Top bar: auto-resizing textarea + fixed-width send/stop button that morphs in place (no layout shift) across idle/generating states. - Bottom bar: agent status icon, context-window fill bar, and compact token count + percent (inert bar when model max is unknown). Wire contextLimit prop from App.svelte into ChatInput, reusing the shared computeContextUsage helper so it agrees with the sidebar. --- packages/frontend/src/App.svelte | 2 +- .../frontend/src/lib/components/ChatInput.svelte | 145 ++++++++++++++++----- 2 files changed, 111 insertions(+), 36 deletions(-) diff --git a/packages/frontend/src/App.svelte b/packages/frontend/src/App.svelte index ecfdc9f..a0b25b7 100644 --- a/packages/frontend/src/App.svelte +++ b/packages/frontend/src/App.svelte @@ -174,7 +174,7 @@ onMount(() => {
- +
diff --git a/packages/frontend/src/lib/components/ChatInput.svelte b/packages/frontend/src/lib/components/ChatInput.svelte index 0c99078..95712c7 100644 --- a/packages/frontend/src/lib/components/ChatInput.svelte +++ b/packages/frontend/src/lib/components/ChatInput.svelte @@ -1,6 +1,9 @@ -
- {#if agentStatus === "running"} +
+ +
+ + - {:else if agentStatus === "idle"} - - - - {:else if agentStatus === "error"} - - - - - - {/if} - - +
+ + +
+ + + {#if agentStatus === "running"} + + {:else if agentStatus === "error"} + + + + + + {:else} + + + + {/if} + + + + {#if usage.percent !== null} + + {:else} + + + {/if} + + + + {#if hasUsage} + {fmtCompact(usage.current)}{#if usage.max !== null} / {fmtCompact(usage.max)}{/if} + {#if usage.percent !== null} + · {usage.percent.toFixed(1)}% + {/if} + {:else} + — tokens + {/if} + +
-- cgit v1.2.3 From a9097498b0e90f45a0eaf1ce2d43275dc9ac8fa4 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Tue, 2 Jun 2026 14:40:21 +0900 Subject: Add HANDOFF.md for sb/status-bar --- HANDOFF.md | 75 +++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/HANDOFF.md b/HANDOFF.md index 8d6960b..5755279 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -1,38 +1,63 @@ -# Handoff — m1/minor-fixes +# Handoff — sb/status-bar -Three small, independent UI fixes in the Dispatch frontend. +Add a status bar beneath the chat input that houses the send button and shows +generation status + context-window usage. ## Files changed -- `packages/frontend/src/lib/components/CacheRatePanel.svelte` - - **Fix 1:** Added `whitespace-nowrap` to the requests-count badge (`{cacheStats.requests} req`) so it no longer wraps to a second line. - - **Fix 2:** Removed the trailing explanatory paragraph ("Cache reads cost ~10% of fresh input; writes cost ~25% more…"). -- `packages/frontend/src/lib/components/KeyUsage.svelte` - - **Fix 3:** Added `pacedProgressClass(percentUsed, elapsedPct)` and applied it to the 5 bars that render a "time dot" (Claude 5-Hour/Weekly, opencode-go 5-Hour/Weekly/Monthly). +- `packages/frontend/src/lib/components/ChatInput.svelte` — restructured into + **two stacked bars** (wrapped in `flex flex-col`): + - **Top bar:** the existing auto-resizing textarea + a single, fixed-width + (`w-20`) send/stop button that morphs in place so the layout never shifts. + Three states: + - not generating → `btn-primary` **Send**, disabled when the box is empty + (unchanged look). + - generating + empty box → **Stop** (`btn-error btn-outline`, spinner + + "Stop"), calls `tabStore.stopGeneration(tabId)`. + - generating + text in box → enabled **Send** (queues the message via + `tabStore.sendMessage`). + - **Bottom bar:** agent status icon on the left (✓ idle / spinner running / + ✗ error), a context-window fill `progress` bar filling the middle, and a + compact token count + percent on the right (e.g. `12.3k / 200k · 6.1%`). + When the model's max context is unknown the bar renders inert/disabled + (`opacity-40`, no value) and the right side shows the bare current token + count with no percent. Before the first response it reads `— tokens`. +- `packages/frontend/src/App.svelte` — pass the already-computed `contextLimit` + into `` (same value handed to the sidebar). ## Public surface changed -- None externally. No exported API, prop, or type changes. -- New module-internal helper `pacedProgressClass` in `KeyUsage.svelte` (not exported). Existing `progressClass` retained and reused as the fallback. - -## Fix 3 coloring logic -`pacedProgressClass(percentUsed, elapsedPct)`: -- `percentUsed >= 90` → `progress-error` (red) — always, per spec. -- no time dot (`elapsedPct < 0`, e.g. missing `resetsAt`) → fall back to existing `progressClass` thresholds. -- `percentUsed <= elapsedPct` → `progress-success` (green; equal counts as green/on-pace). -- otherwise (usage ran ahead of the dot) → `progress-warning` (orange). - -Applied only to the 5 dot-bearing bars. The 3 Copilot/Gemini bars were intentionally left on the original `progressClass` (confirmed unused/out of scope by the requester). +- `ChatInput.svelte` gained one optional prop: `contextLimit?: number | null` + (defaults to `null`). No other exported API/type changes. +- Reuses the shared `computeContextUsage()` helper (`lib/context-window.ts`) and + the same fill-color thresholds (calm→warning→danger) as the Context Window + sidebar panel, so the two displays always agree. Compact `k`/`M` token + formatting is local to `ChatInput` (the sidebar keeps full `toLocaleString`). + +## Design decisions (agreed with requester) +- Two stacked bars; send button kept (not dropped) for discoverability. +- Send and Stop are the **same button** at a fixed width — no layout jump. +- Bottom bar: status icon left; context number + percent right; progress bar + fills the remaining width; disabled/inert bar when the model has no known max. +- Token format: compact (`12.3k`) for the slim bar. ## Verification status — PASS - `bun run check` (biome): **PASS** — "Checked 163 files… No fixes applied." -- `bun run test` (vitest): **PASS** — 35 test files, 552 tests passed. -- Re-verified after `git merge --no-edit dev` (was already up to date) — still all-green. +- `bun run test` (vitest): **PASS** — 35 files, 552 tests. +- `bun run --cwd packages/frontend typecheck` (svelte-check): **PASS** — 0 + errors, 0 warnings. +- Re-verified all three after `git merge --no-edit dev` — still all-green. - Note: `bun install` was required first; deps were not present in the worktree. ## Published -- Yes. Committed `084f4d7`, merged `dev` down (already up to date), pushed fast-forward `7c527b4..084f4d7 → dev`. +- Yes. Feature commit `2756730`, merged `dev` down (`f0207a7`, clean merge — + picked up another agent's CacheRatePanel/KeyUsage changes + their HANDOFF.md), + pushed fast-forward `3f0bfe7..f0207a7 → dev`. +- This HANDOFF.md was rewritten from the incoming `m1/minor-fixes` handoff (that + content remains preserved in git history on its own merge). ## Assumptions / known gaps -- Per requester: Copilot & Gemini usage bars are unused, so they keep the old threshold coloring (untouched). -- Red threshold is `>= 90%` (exactly 90 is red); tie between usage and the dot resolves to green — both confirmed by requester. -- Dot-less / hidden-dot cycle bars fall back to the original `progressClass` thresholds (confirmed option "a"). -- Changes are presentation-only (Tailwind/daisyUI classes + a coloring helper); no automated tests were added for the Svelte markup, consistent with the existing repo (no component-render tests for these panels). User visually confirmed the result before publish. +- User visually confirmed the UI before merge ("sweet, merge it in"). +- No component-render tests were added for the Svelte markup, consistent with + the existing repo (these panels have no render tests). Logic is exercised + indirectly via the unchanged `computeContextUsage` unit tests. +- Context usage reflects the most recent turn (`last.inputTokens + + last.outputTokens`) — identical semantics to the sidebar panel. -- cgit v1.2.3