Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions lib/tui-status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const variantSuffixes: ReasoningVariant[] = [
"none",
];
const STATUS_SEPARATOR = ` ${String.fromCharCode(183)} `;
const MS_PER_DAY = 24 * 60 * 60 * 1000;
const WARNING_LIMIT_LEFT_PERCENT = 25;
const DANGER_LIMIT_LEFT_PERCENT = 10;
const MASKED_EMAIL = "*****";
Expand Down Expand Up @@ -302,11 +303,14 @@ function formatQuota(quota: CompactQuotaStatus): string | undefined {
}

function maxStatusChars(width: number | undefined): number {
if (!width || !Number.isFinite(width)) return 32;
if (width >= 120) return 48;
if (width >= 96) return 40;
if (width >= 78) return 32;
if (width >= 60) return 22;
// Budgets are ~54% of each tier's minimum width (up from ~40%): the
// day-context reset labels and typical account hints no longer fit at
// 40%, which degraded informative candidates on mid-width terminals.
if (!width || !Number.isFinite(width)) return 42;
if (width >= 120) return 64;
if (width >= 96) return 52;
if (width >= 78) return 42;
if (width >= 60) return 32;
return 12;
}

Expand Down Expand Up @@ -401,11 +405,30 @@ function formatResetTime(resetAtMs: number | undefined): string | undefined {
}
const date = new Date(resetAtMs);
if (!Number.isFinite(date.getTime())) return undefined;
return date.toLocaleTimeString(undefined, {
const time = date.toLocaleTimeString(undefined, {
hour: "2-digit",
minute: "2-digit",
hour12: false,
});
const now = new Date();
const sameDay =
now.getFullYear() === date.getFullYear() &&
now.getMonth() === date.getMonth() &&
now.getDate() === date.getDate();
if (sameDay) return time;
const dayDiff = (date.setHours(0, 0, 0, 0) - now.setHours(0, 0, 0, 0)) /
MS_PER_DAY;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
// Within a week each weekday occurs exactly once, so the weekday alone
// disambiguates weekly windows; beyond that the absolute date does.
if (dayDiff > 0 && dayDiff < 7) {
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Outdated
const weekday = date.toLocaleDateString(undefined, { weekday: "short" });
return `${weekday} ${time}`;
}
const day = date.toLocaleDateString(undefined, {
month: "short",
day: "2-digit",
});
return `${day} ${time}`;
}

function formatUpdatedAge(fetchedAt: number | undefined, now: number): string {
Expand Down
68 changes: 58 additions & 10 deletions test/tui-status.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, it } from "vitest";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";

import {
formatPromptStatusText,
Expand All @@ -10,16 +10,17 @@ import {
type PromptStatusMessage,
} from "../lib/tui-status.js";

const sep = ` ${String.fromCharCode(183)} `;
const quota: CompactQuotaStatus = {
type: "ready",
limits: [
{ label: "5h", leftPercent: 88 },
{ label: "7d", leftPercent: 83 },
],
stale: false,
};

describe("TUI prompt status helpers", () => {
const sep = ` ${String.fromCharCode(183)} `;
const quota: CompactQuotaStatus = {
type: "ready",
limits: [
{ label: "5h", leftPercent: 88 },
{ label: "7d", leftPercent: 83 },
],
stale: false,
};

it("formats prompt status text from supplied quota labels", () => {
expect(
Expand Down Expand Up @@ -335,3 +336,50 @@ describe("TUI prompt status helpers", () => {
expect(resolvePromptReasoningVariant({ config })).toBe("xhigh");
});
});

describe("formatResetTime day context", () => {
// Freeze the clock so day-distance assertions are stable.
const realNow = Date.now;
const now = Date.UTC(2026, 8, 5, 12, 0); // 2026-09-05T12:00Z

beforeEach(() => {
vi.spyOn(Date, "now").mockReturnValue(now);
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
afterEach(() => {
vi.spyOn(Date, "now").mockRestore();
void realNow;
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Outdated
});

it("keeps time-only format for same-day resets", () => {
const out = formatPromptStatusText({
quota: {
...quota,
limits: [{ label: "5h", leftPercent: 8, resetAtMs: Date.UTC(2026, 8, 5, 18, 30) }],
},
width: 120,
});
expect(out).toMatch(/resets \d{2}:\d{2}$/);
});

it("adds weekday for resets within the coming week", () => {
const out = formatPromptStatusText({
quota: {
...quota,
limits: [{ label: "7d", leftPercent: 0, resetAtMs: Date.UTC(2026, 8, 8, 2, 25) }],
},
width: 120,
});
Comment thread
greptile-apps[bot] marked this conversation as resolved.
expect(out).toMatch(/resets [A-Z][a-z]{2} \d{2}:\d{2}$/);
});

it("uses absolute date beyond a week", () => {
const out = formatPromptStatusText({
quota: {
...quota,
limits: [{ label: "7d", leftPercent: 0, resetAtMs: Date.UTC(2026, 8, 15, 2, 25) }],
},
width: 120,
});
expect(out).toMatch(/resets [A-Z][a-z]{2} \d{2} \d{2}:\d{2}$/);
});
});