diff options
| author | Adam Malczewski <[email protected]> | 2026-06-12 01:10:56 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-12 01:10:56 +0900 |
| commit | 0e71903cc1419d20fbd593fd7330defdc4628af2 (patch) | |
| tree | c669251424f49f6d8e5b3ec17e03f486d46740a1 /src/core/metrics/format.ts | |
| parent | 6bd7b39f6f53dd8f3743347a1cb72c2f74424dd8 (diff) | |
| download | dispatch-web-0e71903cc1419d20fbd593fd7330defdc4628af2.tar.gz dispatch-web-0e71903cc1419d20fbd593fd7330defdc4628af2.zip | |
feat(chat): old-Dispatch composer layout — textarea + send + status bar
Restore the ergonomic composer from old Dispatch: an auto-resizing textarea
(1→7 lines) with a fixed-width Send button beside it, and a status bar BELOW
holding a status icon · context-window fill bar (escalating success/warning/
error color) · compact token count (current / limit · pct%).
The bar reuses the latest turn's contextSize as current usage and HARDCODES a
1,000,000-token window limit as a placeholder (real per-model limit is the next
backend ask). Absorbs the standalone ContextSizeBadge (removed). Pure helpers
computeContextUsage + formatCompactTokens added to core/metrics (tested).
540 tests green.
Diffstat (limited to 'src/core/metrics/format.ts')
| -rw-r--r-- | src/core/metrics/format.ts | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/src/core/metrics/format.ts b/src/core/metrics/format.ts index d8dd2cc..4d69f25 100644 --- a/src/core/metrics/format.ts +++ b/src/core/metrics/format.ts @@ -28,6 +28,45 @@ export function formatContextSize(n: number | undefined): string { return `${formatTokens(n)} tokens in context`; } +/** + * Compact token count for a slim status bar: `812`, `12.3k`, `1.2M`. Full + * thousands-separated numbers live elsewhere; this trades precision for width. + */ +export function formatCompactTokens(n: number): string { + if (n < 1000) return `${n}`; + if (n < 1_000_000) { + const k = n / 1000; + return `${k >= 100 ? Math.round(k) : k.toFixed(1)}k`; + } + const m = n / 1_000_000; + return `${m >= 100 ? Math.round(m) : m.toFixed(1)}M`; +} + +/** + * Context-window occupancy: the current size against a max window limit. + * + * `current` is the latest turn's context size (0 when unknown); `max` is the + * model's window limit (or `null` when unknown). `percent` is + * `current / max * 100` clamped to [0, 100], UNROUNDED (the UI picks the + * precision) — so a few-thousand-token context against a 1,000,000 window still + * reads non-zero. `percent` is `null` when `max` is unknown (no bar/denominator). + */ +export interface ContextUsage { + readonly current: number; + readonly max: number | null; + readonly percent: number | null; +} + +export function computeContextUsage( + contextSize: number | undefined, + contextLimit: number | null | undefined, +): ContextUsage { + const current = contextSize ?? 0; + const max = typeof contextLimit === "number" && contextLimit > 0 ? contextLimit : null; + const percent = max === null ? null : Math.max(0, Math.min(100, (current / max) * 100)); + return { current, max, percent }; +} + /** Compute tokens-per-second. Returns null when elapsed time is absent or zero. */ export function computeTps(outputTokens: number, elapsedMs: number | undefined): number | null { if (elapsedMs === undefined || elapsedMs <= 0) return null; |
