feat(cockpit): quick wins — sync chip, cost budget guard, digest, recent commits (W3)
Four small, high-delight features that turn passive capture into glanceable signals.
- Sync chip on project cards: ahead/behind vs upstream + last-commit time, folded
into the existing concurrent per-repo metadata pass (git rev-list --count
--left-right @{u}...HEAD + git log -1 --format=%ct; no upstream → undefined, no route).
- Cost budget guard: COST_BUDGET_USD env (0 = off); a per-session one-shot latch
(Session.budgetNotified, cost is monotonic so never re-armed) fires a single push
on threshold crossing in manager.handleStatusLine; the already-broadcast telemetry
frame carries the warn (tg-cost-warn styling derived from costUsd>=budget via
/config/ui — no new ServerMessage). web-push title added to sw-push.js.
- "While you were away" digest: GET /digest?since= → {finished, needsInput, stuck,
totalCostUsd, sessions[]} aggregate over manager.list(); FE banner on reconnect.
- Recent commits per project: src/http/git-log.ts (NUL-delimited git log → CommitInfo[]),
GET /projects/log?path= (isValidGitDir), textContent-inert render in project detail.
All git via execFile (no shell) + validated cwd; new routes read-only; commit
messages rendered via textContent. Verified: typecheck + build:web clean, 1904 pass
at --test-timeout=30000 (two default-5s failures are slow-sandbox real-subprocess
timeout flakes — the known ring-buffer test + a new real-git-clone sync test — not
logic regressions).
This commit is contained in:
@@ -188,7 +188,9 @@ export async function fetchLiveSessions(): Promise<LiveSessionInfo[]> {
|
||||
*
|
||||
* Shows: context-usage bar (>80% = warning colour), $cost chip, model chip,
|
||||
* and a PR badge. When `telemetry.at` is older than `staleTtlMs` the container
|
||||
* receives the class `tg-stale` so CSS can grey it out.
|
||||
* receives the class `tg-stale` so CSS can grey it out. When `costBudgetUsd` is
|
||||
* set (>0) and `costUsd >= costBudgetUsd`, the cost chip gets `tg-cost-warn`
|
||||
* (W3 quick-wins b), mirroring the ctx>80% warn path.
|
||||
*
|
||||
* Security: all telemetry strings are set via `textContent` (SEC-H5); the PR
|
||||
* link href is only set when `url.protocol === 'https:'` (SEC-L5).
|
||||
@@ -198,6 +200,7 @@ export function renderTelemetryGauge(
|
||||
container: HTMLElement,
|
||||
telemetry: StatusTelemetry | null,
|
||||
staleTtlMs: number,
|
||||
costBudgetUsd?: number,
|
||||
): void {
|
||||
// Clear existing children
|
||||
while (container.firstChild) container.removeChild(container.firstChild)
|
||||
@@ -221,9 +224,13 @@ export function renderTelemetryGauge(
|
||||
container.append(bar)
|
||||
}
|
||||
|
||||
// Cost chip
|
||||
// Cost chip — W3(b): warn-styled once cost crosses the configured budget.
|
||||
if (telemetry.costUsd !== undefined) {
|
||||
container.append(el('span', 'tg-cost', `$${telemetry.costUsd.toFixed(4)}`))
|
||||
const cost = el('span', 'tg-cost', `$${telemetry.costUsd.toFixed(4)}`)
|
||||
if (costBudgetUsd !== undefined && costBudgetUsd > 0 && telemetry.costUsd >= costBudgetUsd) {
|
||||
cost.classList.add('tg-cost-warn')
|
||||
}
|
||||
container.append(cost)
|
||||
}
|
||||
|
||||
// Model chip
|
||||
|
||||
Reference in New Issue
Block a user