Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
81 changes: 74 additions & 7 deletions apps/desktop-tauri/src/floatbar/FloatBar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -327,33 +327,100 @@ describe("FloatBar", () => {

it("keeps an informational primary window when no secondary window is available", async () => {
tauriMocks.getCachedProviders.mockResolvedValue([
snapshot("claude", "Claude", 10, { informational: true }),
snapshot("claude", "Claude", 0, {
informational: true,
resetDescription: "No active 5h session",
}),
]);
tauriMocks.getSettingsSnapshot.mockResolvedValue(settings());

const { container } = renderFloatBar(bootstrap());
await waitFor(() => {
expect(container.querySelector(".floatbar__pill")?.getAttribute("title")).toContain(
"Claude: 10% used",
expect(container.querySelector(".floatbar__pill")?.getAttribute("title")).toBe(
"Claude: No active 5h session",
);
});
});

it("keeps an informational primary window when the secondary window is informational", async () => {
tauriMocks.getCachedProviders.mockResolvedValue([
snapshot("claude", "Claude", 10, {
snapshot("claude", "Claude", 0, {
informational: true,
secondary: { used: 90, informational: true },
resetDescription: "No active 5h session",
secondary: { used: 90, informational: true, resetDescription: "Weekly unavailable" },
}),
]);
tauriMocks.getSettingsSnapshot.mockResolvedValue(settings());

const { container } = renderFloatBar(bootstrap());
await waitFor(() => {
expect(container.querySelector(".floatbar__pill")?.getAttribute("title")).toContain(
"Claude: 10% used",
expect(container.querySelector(".floatbar__pill")?.getAttribute("title")).toBe(
"Claude: No active 5h session",
);
});
});

it("shows an informational metric's text instead of a percentage or reset wording", async () => {
tauriMocks.getCachedProviders.mockResolvedValue([
snapshot("litellm", "LiteLLM", 0, {
informational: true,
resetDescription: "No budget set",
}),
]);
tauriMocks.getSettingsSnapshot.mockResolvedValue(
settings({ enabledProviders: ["litellm"], floatBarShowResetInline: true }),
);

const { container } = renderFloatBar(
bootstrap({ enabledProviders: ["litellm"], floatBarShowResetInline: true }),
);
await waitFor(() => {
expect(container.querySelector(".floatbar__pill")).not.toBeNull();
});
const pill = container.querySelector(".floatbar__pill");
expect(pill?.getAttribute("title")).toBe("LiteLLM: No budget set");
expect(pill?.querySelector(".floatbar__pct")?.textContent).toBe("No budget set");
expect(pill?.textContent).not.toMatch(/%|Resets/);
expect(pill?.querySelector(".floatbar__reset")).toBeNull();
expect(pill?.classList.contains("floatbar__pill--ok")).toBe(true);
});

it("keeps the neutral tone for an informational metric in remaining mode", async () => {
tauriMocks.getCachedProviders.mockResolvedValue([
snapshot("cursor", "Cursor", 100, {
informational: true,
resetDescription: "$12.40 API-rate",
}),
]);
tauriMocks.getSettingsSnapshot.mockResolvedValue(
settings({ enabledProviders: ["cursor"], showAsUsed: false }),
);

const { container } = renderFloatBar(
bootstrap({ enabledProviders: ["cursor"], showAsUsed: false }),
);
await waitFor(() => {
expect(container.querySelector(".floatbar__pill")).not.toBeNull();
});
const pill = container.querySelector(".floatbar__pill");
expect(pill?.getAttribute("title")).toBe("Cursor: $12.40 API-rate");
expect(pill?.classList.contains("floatbar__pill--ok")).toBe(true);
});

it("uses an em dash for an informational metric without text and keeps a timestamp reset", async () => {
const resetsAt = new Date(Date.now() + (2 * 60 + 5) * 60_000).toISOString();
tauriMocks.getCachedProviders.mockResolvedValue([
snapshot("codex", "Codex", 0, { informational: true, resetsAt }),
]);
tauriMocks.getSettingsSnapshot.mockResolvedValue(settings());

const { container } = renderFloatBar(bootstrap());
await waitFor(() => {
expect(container.querySelector(".floatbar__pill")?.getAttribute("title")).toMatch(
/^Codex: —\nResets in 2h \d+m$/,
);
});
expect(container.querySelector(".floatbar__pct")?.textContent).toBe("—");
});

it("sorts providers by their selected rate window", async () => {
Expand Down
27 changes: 21 additions & 6 deletions apps/desktop-tauri/src/floatbar/FloatBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ function CostPill({
* Color follows usage: green default, amber when remaining drops below the
* high-usage threshold, red when remaining is below the critical threshold
* or the provider is exhausted.
*
* An informational metric (no budget set, a balance line, no active session)
* has no quota percentage. Like the tray card and the tray tooltip, the pill
* shows its text instead, keeps the neutral tone, and never turns that text
* into reset wording.
*/
function ProviderPill({
provider,
Expand All @@ -207,21 +212,29 @@ function ProviderPill({
stateLabel: string;
}) {
const rateWindow = provider.selectedMetric;
const informational = rateWindow.isInformational === true;
const remaining = Math.max(0, Math.min(100, rateWindow.remainingPercent));
const used = Math.max(0, Math.min(100, rateWindow.usedPercent));
const displayPercent = showAsUsed ? used : remaining;
const displaySuffix = showAsUsed ? usedSuffix : remainingSuffix;
const state = describeProviderState(provider.errorState);
const exhausted = rateWindow.isExhausted || state.isProblem;
let tone: "ok" | "warn" | "crit" = "ok";
if (exhausted || remaining <= critRemaining) tone = "crit";
else if (remaining <= highRemaining) tone = "warn";
if (state.isProblem) tone = "crit";
else if (!informational) {
if (rateWindow.isExhausted || remaining <= critRemaining) tone = "crit";
else if (remaining <= highRemaining) tone = "warn";
}

const brand = getProviderIcon(provider.providerId).brandColor;
const label = state.isProblem ? stateLabel : `${Math.round(displayPercent)}%`;
const infoText = rateWindow.resetDescription?.trim() || "—";
const label = state.isProblem
? stateLabel
: informational
? infoText
: `${Math.round(displayPercent)}%`;
const resetText = useFormattedResetTime(
rateWindow.resetsAt,
rateWindow.resetDescription,
informational ? null : rateWindow.resetDescription,
resetRelative,
);
const resetSuffix = resetText ? `\n${resetText}` : "";
Expand All @@ -237,7 +250,9 @@ function ProviderPill({
title={
state.isProblem
? `${provider.displayName}: ${stateLabel}`
: `${provider.displayName}: ${label} ${displaySuffix}${resetSuffix}`
: informational
? `${provider.displayName}: ${infoText}${resetSuffix}`
: `${provider.displayName}: ${label} ${displaySuffix}${resetSuffix}`
}
data-tauri-drag-region
style={{ "--brand": brand } as CSSProperties}
Expand Down