From 34e84bc86ed4bae29c436a589852ed63804cf682 Mon Sep 17 00:00:00 2001 From: Abhijith14 <53612189+Abhijith14@users.noreply.github.com> Date: Mon, 27 Jul 2026 06:18:41 +0530 Subject: [PATCH] fix(tray): show real percentage when no declared candidate is present A plan can expose progress lines that are absent from its plugin manifest's declared primary candidates. Usage-based Codex accounts (Self_serve_business_usage_based) report only a "Credits" progress line and never "Session", which is the only candidate codex declares via primaryOrder. getTrayPrimaryBars then matched no label, left fraction undefined, and the tray rendered "--%" even though a perfectly usable progress line was present (used 1000 / limit 1000). Fall back to the first progress line in the runtime data when none of the declared candidates match, so the tray shows a real number. Plugins that declare no candidates at all are still skipped, exactly as before. --- src/lib/tray-primary-progress.test.ts | 41 +++++++++++++++++++++++++++ src/lib/tray-primary-progress.ts | 27 ++++++++++-------- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/lib/tray-primary-progress.test.ts b/src/lib/tray-primary-progress.test.ts index f2989a5ba..f233f31b6 100644 --- a/src/lib/tray-primary-progress.test.ts +++ b/src/lib/tray-primary-progress.test.ts @@ -302,5 +302,46 @@ describe("getTrayPrimaryBars", () => { }) expect(bars).toEqual([]) }) + + it("falls back to the first progress line when no declared candidate is present", () => { + // Usage-based Codex plans report only "Credits", never the declared "Session" + // candidate. Without a fallback the tray renders "--%" instead of a real number. + const bars = getTrayPrimaryBars({ + pluginsMeta: [ + { + id: "codex", + name: "Codex", + iconUrl: "", + primaryCandidates: ["Session"], + lines: [], + }, + ], + pluginSettings: { order: ["codex"], disabled: [] }, + pluginStates: { + codex: { + data: { + providerId: "codex", + displayName: "Codex", + iconUrl: "", + lines: [ + { + type: "progress", + label: "Credits", + used: 1000, + limit: 1000, + format: { kind: "count", suffix: "credits" }, + }, + ], + }, + loading: false, + error: null, + }, + }, + displayMode: "left", + }) + + // 1000 of 1000 used, "left" mode -> 0 remaining -> 0%, not undefined + expect(bars).toEqual([{ id: "codex", fraction: 0 }]) + }) }) diff --git a/src/lib/tray-primary-progress.ts b/src/lib/tray-primary-progress.ts index a139e29df..6ff0e88d6 100644 --- a/src/lib/tray-primary-progress.ts +++ b/src/lib/tray-primary-progress.ts @@ -65,18 +65,21 @@ export function getTrayPrimaryBars(args: { const primaryLabel = meta.primaryCandidates.find((label) => data.lines.some((line) => isProgressLine(line) && line.label === label) ) - if (primaryLabel) { - const primaryLine = data.lines.find( - (line): line is ProgressLine => - isProgressLine(line) && line.label === primaryLabel - ) - if (primaryLine && primaryLine.limit > 0) { - const shownAmount = - displayMode === "used" - ? primaryLine.used - : primaryLine.limit - primaryLine.used - fraction = clamp01(shownAmount / primaryLine.limit) - } + // Some plans expose none of the declared candidates (usage-based Codex reports only + // "Credits", never "Session"). Fall back to the first progress line so the tray shows + // a real number instead of "--%". + const primaryLine = primaryLabel + ? data.lines.find( + (line): line is ProgressLine => + isProgressLine(line) && line.label === primaryLabel + ) + : data.lines.find((line): line is ProgressLine => isProgressLine(line)) + if (primaryLine && primaryLine.limit > 0) { + const shownAmount = + displayMode === "used" + ? primaryLine.used + : primaryLine.limit - primaryLine.used + fraction = clamp01(shownAmount / primaryLine.limit) } }