fix(bar): read codex rollout tail via fs so quota surfaces under node

defaultTailLines used Bun.spawn(['tail',...]), but the ccs server (and
'ccs bar launch') runs under node where Bun is undefined — it threw, the
per-path catch swallowed it, and Codex quota silently never appeared in real
deployments (it only worked under the bun-run dev harness). Replace with a
pure fs read: runtime- and OS-agnostic, no subprocess. Verified under node:
surfaces a live rollout's rate_limits (primary/secondary).
This commit is contained in:
Tam Nhu Tran
2026-06-09 21:11:01 -04:00
parent 2f8745bc1f
commit 2e99b58d09
@@ -167,17 +167,19 @@ function collectRolloutFiles(
}
/**
* Default tail using Bun.spawn (macOS-safe: no tac, no GNU timeout).
* Reads the last `lines` lines so we never load a huge session into memory.
* Default tail via a pure fs read. Must work under BOTH node and bun: the `ccs`
* CLI (and `ccs bar launch`) runs under node, where `Bun.spawn` is undefined —
* the previous Bun-only implementation threw there, so Codex quota silently
* never surfaced in real deployments (only under the bun-run dev harness).
* Reading the JSONL and slicing the tail is cheap (session rollouts are small)
* and carries no runtime/OS/subprocess dependency.
*/
async function defaultTailLines(file: string, lines: number): Promise<string[]> {
const proc = Bun.spawn(['tail', `-${lines}`, file], {
stdout: 'pipe',
stderr: 'ignore',
});
const text = await new Response(proc.stdout).text();
await proc.exited;
return text.split('\n').filter((l) => l.trim().length > 0);
const text = await fs.promises.readFile(file, 'utf8');
return text
.split('\n')
.filter((l) => l.trim().length > 0)
.slice(-lines);
}
function computeQuotaPercentage(rate: CodexRateLimits): number {