feat(limits): show Copilot premium-request counts, not just a percentage - #98

Merged
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts
Jul 25, 2026
Merged

feat(limits): show Copilot premium-request counts, not just a percentage#98
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts

Conversation

@pitimon

Copy link
Copy Markdown
Owner

Closes#97. From a user question: "can TokenTracker track GitHub Copilot credits?"

It already reads them. It was throwing the answer away.

The defect

fetchCopilotLimits pulls quota_snapshots.premium_interactions from api.github.com, which carries entitlement and remaining. buildCopilotWindow did this:

usedPercent=((entitlement-remaining)/entitlement)*100;returnbuildWindow({ usedPercent,resetAt: resetIso});// ← both numbers gone

So the card read Premium 53% when GitHub had said 158 of 300 used. "53%" needs arithmetic before it means anything. "142 left" is the decision.

Change

buildWindow takes optional used/limit and emits them only when a provider reports countable units. Everyone else passes neither, so the keys are omitted rather than set to null — other providers' payloads stay byte-identical and no consumer has to learn a field it will never see. A test pins that shape for Cursor.

Where a count exists, it replaces the percentage:

SurfaceWhy the count wins
Card chipThe 4-tier coloured dot and tint already carry severity, so dropping the percent sign loses nothing. Tooltip keeps both.
Limits page barThe bar is a proportional drawing of the percentage — printing 53% beside a 53%-wide bar repeats itself. 158/300 beside it does not.

Both follow the existing Used/Remaining toggle: 158/300 used, 142/300 left.

The count is clamped to the allowance. Copilot keeps billing past quota so remaining can go negative, and 312/300 used reads as a bug even when it's true — the percentage has always been clamped for the same reason.

Deliberately not in scope

  • Cost of over-quota premium requests. GitHub bills those per request; TokenTracker doesn't model it, and guessing would be worse than the silence.
  • Copilot token/cost rows. Those come from parseCopilotIncremental reading Copilot's OTEL export (COPILOT_OTEL_ENABLED=true) — a completely separate mechanism from quota, already explained by the in-app limits.copilot.otelHint panel. Users conflate the two; that's a docs problem, not this one.

Test plan

  • npm run ci:local — exit 0, 839/839 root (+6), 255 dashboard (+7)
  • There was no test anywhere for fetchCopilotLimits before this — grep -rl 'fetchCopilotLimits\|copilot_internal' test/ was empty. New file covers counts flowing through, percent_remaining-only (no denominator → no counts), over-quota clamping, the pre-existing all-zero-snapshot guard, and the no-token path
  • Reverted both source files against HEAD and re-ran: 2 server + 5 dashboard tests fail, confirming they exercise the change
  • Render assertions in UsageLimitsPanel.test.jsx, not just pure functions — the counts reach the screen through a copy() key, and a mistyped key renders as the raw key string while every getWindowCounts unit test still passes. That test also caught my own wrong prop guess (mode vs displayMode)
  • Caught while reviewing: one regression guard was passing vacuously — the Cursor fixture produced no windows, so the loop body never ran. Now asserts the windows exist before inspecting them
  • mock-data.ts ships a configured Copilot, so the chip is visible under dashboard:dev without a real Copilot install
  • Not verified against a live Copilot account — this machine reports configured: false (no token on disk), so the API-shape assumptions come from the existing parser, not from a live response

Note

README's quota bullet claimed the chips show "used %", which this change makes untrue — updated in the same commit rather than left to drift.

itarun.p added 3 commits July 25, 2026 10:15
A user asked whether TokenTracker can track GitHub Copilot credits. It
already reads them — and then throws the answer away.
`fetchCopilotLimits` pulls `quota_snapshots.premium_interactions` from
api.github.com, which carries `entitlement` and `remaining`. buildCopilotWindow
divided them into a percentage and dropped both numbers, so the card showed
"Premium 53%" when GitHub had said "158 of 300 used". 53% needs arithmetic
before it means anything; 142 left is the decision itself.
buildWindow now takes optional `used`/`limit` and emits them only when a
provider reports countable units. Everyone else passes neither, so the keys
are omitted rather than set to null — other providers' payloads stay
byte-identical and no consumer learns a field it will never see. A test
asserts that shape for Cursor.
On the surface, the count replaces the percentage where one exists:
- Card chip: the 4-tier coloured dot and tint already carry severity, so
dropping the percent sign loses nothing, and the tooltip keeps both.
- Limits page bar: the bar *is* a proportional drawing of the percentage, so
printing "53%" beside a 53%-wide bar repeats itself. "158/300" does not.
- Both follow the Used/Remaining toggle: 158/300 used, 142/300 left.
The count is clamped to the allowance. Copilot keeps billing past the quota
so `remaining` can go negative, and "312/300 used" reads as a bug even when
it is true — the percentage has always been clamped for the same reason.
There was no test anywhere for fetchCopilotLimits before this. The new file
also covers the pre-existing all-zero-snapshot guard and the no-token path,
and the mock data now ships a configured Copilot so the chip is visible under
`dashboard:dev` on a machine that has never signed in to Copilot.
README's quota bullet said the chips show "used %", which this makes untrue,
so it says what they show now.
Closes#97
Independent QA at xhigh returned SHIP: NO on the first cut. All three were
real and all three were mine; each is reproduced below and now has a
regression test.
1. Percentage and count could describe different realities.
`buildCopilotWindow` preferred `percent_remaining` for the bar while the
caption came from `entitlement`/`remaining`. With `percent_remaining: 30,
entitlement: 300, remaining: 72` that drew a 70%-wide bar captioned
"228/300" — which is 76%. The caption is the number the user reads, so the
percentage is now derived from the counts whenever both arrive;
`percent_remaining` stays the fallback for the case it exists to cover, a
percentage with no denominator.
2. A null count read as zero remaining.
`Number(null)` is 0, so `remaining: null` reported the entire allowance
consumed — "300/300" beside a percentage saying 10% used. That tells
someone their quota is gone when they have barely touched it. Counts now
require an actual finite number, and an absent one falls back to the
percentage with no counts emitted at all.
3. Clamping the wrong half in the dashboard.
`getWindowCounts` clamped only the low end, so an unclamped payload
rendered "312/300" in Used mode from `used: 312` AND in Remaining mode from
`used: -12`. Clamping into [0, limit] now happens before the mode flip. The
current server clamps, but a newer dashboard talks to whatever server is
installed — which is exactly what the discarded comment claimed to handle.
Also: README:99 still said the quota chips show a used percentage. I fixed
that claim at README:83 in the previous commit and assumed it was the only
one. It was not.
Refs #97
Non-blocking findings from the QA re-check. Both described the card chip as
showing label + %, which stopped being true when the count replaced it.
@pitimon
pitimon merged commit 493d693 into mainJul 25, 2026
1 check passed
@pitimon
pitimon deleted the feat/97-copilot-quota-counts branch July 25, 2026 03:44
@pitimonpitimon mentioned this pull request Jul 25, 2026
6 tasks
pitimon added a commit that referenced this pull request Jul 25, 2026
Ships #98 (issue #97): GitHub Copilot quota now reports the premium-request
count — "158/300", or "142/300" in Remaining mode — instead of a percentage
the reader has to convert. The numbers were already being fetched from
api.github.com and discarded after one division.
The independent Codex QA gate returned SHIP: NO on the first cut and all
three findings were real: the bar and its caption could be drawn from
different fields and disagree (70% beside 228/300, which is 76%); a null
`remaining` coerced to zero and reported the whole allowance consumed; and
the dashboard clamped only one end, so an unclamped payload could render
"312/300" in either mode. Fixed, each with a regression test built from the
exact reproduction.
First release where the `version` lifecycle hook from #96 did its job: the
bump synced TokenTrackerBar/project.yml and TokenTrackerWin.csproj, which is
what made 0.39.39–0.39.42 unable to cut a desktop build.
prepublishOnly re-vendored the LiteLLM seed: 2,522 models, no rate changes,
only _meta.generated_at moved.
Co-authored-by: itarun.p <itarun.p@somapait.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copilot quota: show the premium-request count, not just a percentage

1 participant

@pitimon
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(limits): show Copilot premium-request counts, not just a percentage - #98

Merged
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts
Jul 25, 2026
Merged

feat(limits): show Copilot premium-request counts, not just a percentage#98
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts

Conversation

@pitimon

Copy link
Copy Markdown
Owner

Closes#97. From a user question: "can TokenTracker track GitHub Copilot credits?"

It already reads them. It was throwing the answer away.

The defect

fetchCopilotLimits pulls quota_snapshots.premium_interactions from api.github.com, which carries entitlement and remaining. buildCopilotWindow did this:

usedPercent=((entitlement-remaining)/entitlement)*100;returnbuildWindow({ usedPercent,resetAt: resetIso});// ← both numbers gone

So the card read Premium 53% when GitHub had said 158 of 300 used. "53%" needs arithmetic before it means anything. "142 left" is the decision.

Change

buildWindow takes optional used/limit and emits them only when a provider reports countable units. Everyone else passes neither, so the keys are omitted rather than set to null — other providers' payloads stay byte-identical and no consumer has to learn a field it will never see. A test pins that shape for Cursor.

Where a count exists, it replaces the percentage:

SurfaceWhy the count wins
Card chipThe 4-tier coloured dot and tint already carry severity, so dropping the percent sign loses nothing. Tooltip keeps both.
Limits page barThe bar is a proportional drawing of the percentage — printing 53% beside a 53%-wide bar repeats itself. 158/300 beside it does not.

Both follow the existing Used/Remaining toggle: 158/300 used, 142/300 left.

The count is clamped to the allowance. Copilot keeps billing past quota so remaining can go negative, and 312/300 used reads as a bug even when it's true — the percentage has always been clamped for the same reason.

Deliberately not in scope

  • Cost of over-quota premium requests. GitHub bills those per request; TokenTracker doesn't model it, and guessing would be worse than the silence.
  • Copilot token/cost rows. Those come from parseCopilotIncremental reading Copilot's OTEL export (COPILOT_OTEL_ENABLED=true) — a completely separate mechanism from quota, already explained by the in-app limits.copilot.otelHint panel. Users conflate the two; that's a docs problem, not this one.

Test plan

  • npm run ci:local — exit 0, 839/839 root (+6), 255 dashboard (+7)
  • There was no test anywhere for fetchCopilotLimits before this — grep -rl 'fetchCopilotLimits\|copilot_internal' test/ was empty. New file covers counts flowing through, percent_remaining-only (no denominator → no counts), over-quota clamping, the pre-existing all-zero-snapshot guard, and the no-token path
  • Reverted both source files against HEAD and re-ran: 2 server + 5 dashboard tests fail, confirming they exercise the change
  • Render assertions in UsageLimitsPanel.test.jsx, not just pure functions — the counts reach the screen through a copy() key, and a mistyped key renders as the raw key string while every getWindowCounts unit test still passes. That test also caught my own wrong prop guess (mode vs displayMode)
  • Caught while reviewing: one regression guard was passing vacuously — the Cursor fixture produced no windows, so the loop body never ran. Now asserts the windows exist before inspecting them
  • mock-data.ts ships a configured Copilot, so the chip is visible under dashboard:dev without a real Copilot install
  • Not verified against a live Copilot account — this machine reports configured: false (no token on disk), so the API-shape assumptions come from the existing parser, not from a live response

Note

README's quota bullet claimed the chips show "used %", which this change makes untrue — updated in the same commit rather than left to drift.

itarun.p added 3 commits July 25, 2026 10:15
A user asked whether TokenTracker can track GitHub Copilot credits. It
already reads them — and then throws the answer away.
`fetchCopilotLimits` pulls `quota_snapshots.premium_interactions` from
api.github.com, which carries `entitlement` and `remaining`. buildCopilotWindow
divided them into a percentage and dropped both numbers, so the card showed
"Premium 53%" when GitHub had said "158 of 300 used". 53% needs arithmetic
before it means anything; 142 left is the decision itself.
buildWindow now takes optional `used`/`limit` and emits them only when a
provider reports countable units. Everyone else passes neither, so the keys
are omitted rather than set to null — other providers' payloads stay
byte-identical and no consumer learns a field it will never see. A test
asserts that shape for Cursor.
On the surface, the count replaces the percentage where one exists:
- Card chip: the 4-tier coloured dot and tint already carry severity, so
dropping the percent sign loses nothing, and the tooltip keeps both.
- Limits page bar: the bar *is* a proportional drawing of the percentage, so
printing "53%" beside a 53%-wide bar repeats itself. "158/300" does not.
- Both follow the Used/Remaining toggle: 158/300 used, 142/300 left.
The count is clamped to the allowance. Copilot keeps billing past the quota
so `remaining` can go negative, and "312/300 used" reads as a bug even when
it is true — the percentage has always been clamped for the same reason.
There was no test anywhere for fetchCopilotLimits before this. The new file
also covers the pre-existing all-zero-snapshot guard and the no-token path,
and the mock data now ships a configured Copilot so the chip is visible under
`dashboard:dev` on a machine that has never signed in to Copilot.
README's quota bullet said the chips show "used %", which this makes untrue,
so it says what they show now.
Closes#97
Independent QA at xhigh returned SHIP: NO on the first cut. All three were
real and all three were mine; each is reproduced below and now has a
regression test.
1. Percentage and count could describe different realities.
`buildCopilotWindow` preferred `percent_remaining` for the bar while the
caption came from `entitlement`/`remaining`. With `percent_remaining: 30,
entitlement: 300, remaining: 72` that drew a 70%-wide bar captioned
"228/300" — which is 76%. The caption is the number the user reads, so the
percentage is now derived from the counts whenever both arrive;
`percent_remaining` stays the fallback for the case it exists to cover, a
percentage with no denominator.
2. A null count read as zero remaining.
`Number(null)` is 0, so `remaining: null` reported the entire allowance
consumed — "300/300" beside a percentage saying 10% used. That tells
someone their quota is gone when they have barely touched it. Counts now
require an actual finite number, and an absent one falls back to the
percentage with no counts emitted at all.
3. Clamping the wrong half in the dashboard.
`getWindowCounts` clamped only the low end, so an unclamped payload
rendered "312/300" in Used mode from `used: 312` AND in Remaining mode from
`used: -12`. Clamping into [0, limit] now happens before the mode flip. The
current server clamps, but a newer dashboard talks to whatever server is
installed — which is exactly what the discarded comment claimed to handle.
Also: README:99 still said the quota chips show a used percentage. I fixed
that claim at README:83 in the previous commit and assumed it was the only
one. It was not.
Refs #97
Non-blocking findings from the QA re-check. Both described the card chip as
showing label + %, which stopped being true when the count replaced it.
@pitimon
pitimon merged commit 493d693 into mainJul 25, 2026
1 check passed
@pitimon
pitimon deleted the feat/97-copilot-quota-counts branch July 25, 2026 03:44
@pitimonpitimon mentioned this pull request Jul 25, 2026
6 tasks
pitimon added a commit that referenced this pull request Jul 25, 2026
Ships #98 (issue #97): GitHub Copilot quota now reports the premium-request
count — "158/300", or "142/300" in Remaining mode — instead of a percentage
the reader has to convert. The numbers were already being fetched from
api.github.com and discarded after one division.
The independent Codex QA gate returned SHIP: NO on the first cut and all
three findings were real: the bar and its caption could be drawn from
different fields and disagree (70% beside 228/300, which is 76%); a null
`remaining` coerced to zero and reported the whole allowance consumed; and
the dashboard clamped only one end, so an unclamped payload could render
"312/300" in either mode. Fixed, each with a regression test built from the
exact reproduction.
First release where the `version` lifecycle hook from #96 did its job: the
bump synced TokenTrackerBar/project.yml and TokenTrackerWin.csproj, which is
what made 0.39.39–0.39.42 unable to cut a desktop build.
prepublishOnly re-vendored the LiteLLM seed: 2,522 models, no rate changes,
only _meta.generated_at moved.
Co-authored-by: itarun.p <itarun.p@somapait.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copilot quota: show the premium-request count, not just a percentage

1 participant

@pitimon
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(limits): show Copilot premium-request counts, not just a percentage - #98

Merged
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts
Jul 25, 2026
Merged

feat(limits): show Copilot premium-request counts, not just a percentage#98
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts

Conversation

@pitimon

Copy link
Copy Markdown
Owner

Closes#97. From a user question: "can TokenTracker track GitHub Copilot credits?"

It already reads them. It was throwing the answer away.

The defect

fetchCopilotLimits pulls quota_snapshots.premium_interactions from api.github.com, which carries entitlement and remaining. buildCopilotWindow did this:

usedPercent=((entitlement-remaining)/entitlement)*100;returnbuildWindow({ usedPercent,resetAt: resetIso});// ← both numbers gone

So the card read Premium 53% when GitHub had said 158 of 300 used. "53%" needs arithmetic before it means anything. "142 left" is the decision.

Change

buildWindow takes optional used/limit and emits them only when a provider reports countable units. Everyone else passes neither, so the keys are omitted rather than set to null — other providers' payloads stay byte-identical and no consumer has to learn a field it will never see. A test pins that shape for Cursor.

Where a count exists, it replaces the percentage:

SurfaceWhy the count wins
Card chipThe 4-tier coloured dot and tint already carry severity, so dropping the percent sign loses nothing. Tooltip keeps both.
Limits page barThe bar is a proportional drawing of the percentage — printing 53% beside a 53%-wide bar repeats itself. 158/300 beside it does not.

Both follow the existing Used/Remaining toggle: 158/300 used, 142/300 left.

The count is clamped to the allowance. Copilot keeps billing past quota so remaining can go negative, and 312/300 used reads as a bug even when it's true — the percentage has always been clamped for the same reason.

Deliberately not in scope

  • Cost of over-quota premium requests. GitHub bills those per request; TokenTracker doesn't model it, and guessing would be worse than the silence.
  • Copilot token/cost rows. Those come from parseCopilotIncremental reading Copilot's OTEL export (COPILOT_OTEL_ENABLED=true) — a completely separate mechanism from quota, already explained by the in-app limits.copilot.otelHint panel. Users conflate the two; that's a docs problem, not this one.

Test plan

  • npm run ci:local — exit 0, 839/839 root (+6), 255 dashboard (+7)
  • There was no test anywhere for fetchCopilotLimits before this — grep -rl 'fetchCopilotLimits\|copilot_internal' test/ was empty. New file covers counts flowing through, percent_remaining-only (no denominator → no counts), over-quota clamping, the pre-existing all-zero-snapshot guard, and the no-token path
  • Reverted both source files against HEAD and re-ran: 2 server + 5 dashboard tests fail, confirming they exercise the change
  • Render assertions in UsageLimitsPanel.test.jsx, not just pure functions — the counts reach the screen through a copy() key, and a mistyped key renders as the raw key string while every getWindowCounts unit test still passes. That test also caught my own wrong prop guess (mode vs displayMode)
  • Caught while reviewing: one regression guard was passing vacuously — the Cursor fixture produced no windows, so the loop body never ran. Now asserts the windows exist before inspecting them
  • mock-data.ts ships a configured Copilot, so the chip is visible under dashboard:dev without a real Copilot install
  • Not verified against a live Copilot account — this machine reports configured: false (no token on disk), so the API-shape assumptions come from the existing parser, not from a live response

Note

README's quota bullet claimed the chips show "used %", which this change makes untrue — updated in the same commit rather than left to drift.

itarun.p added 3 commits July 25, 2026 10:15
A user asked whether TokenTracker can track GitHub Copilot credits. It
already reads them — and then throws the answer away.
`fetchCopilotLimits` pulls `quota_snapshots.premium_interactions` from
api.github.com, which carries `entitlement` and `remaining`. buildCopilotWindow
divided them into a percentage and dropped both numbers, so the card showed
"Premium 53%" when GitHub had said "158 of 300 used". 53% needs arithmetic
before it means anything; 142 left is the decision itself.
buildWindow now takes optional `used`/`limit` and emits them only when a
provider reports countable units. Everyone else passes neither, so the keys
are omitted rather than set to null — other providers' payloads stay
byte-identical and no consumer learns a field it will never see. A test
asserts that shape for Cursor.
On the surface, the count replaces the percentage where one exists:
- Card chip: the 4-tier coloured dot and tint already carry severity, so
dropping the percent sign loses nothing, and the tooltip keeps both.
- Limits page bar: the bar *is* a proportional drawing of the percentage, so
printing "53%" beside a 53%-wide bar repeats itself. "158/300" does not.
- Both follow the Used/Remaining toggle: 158/300 used, 142/300 left.
The count is clamped to the allowance. Copilot keeps billing past the quota
so `remaining` can go negative, and "312/300 used" reads as a bug even when
it is true — the percentage has always been clamped for the same reason.
There was no test anywhere for fetchCopilotLimits before this. The new file
also covers the pre-existing all-zero-snapshot guard and the no-token path,
and the mock data now ships a configured Copilot so the chip is visible under
`dashboard:dev` on a machine that has never signed in to Copilot.
README's quota bullet said the chips show "used %", which this makes untrue,
so it says what they show now.
Closes#97
Independent QA at xhigh returned SHIP: NO on the first cut. All three were
real and all three were mine; each is reproduced below and now has a
regression test.
1. Percentage and count could describe different realities.
`buildCopilotWindow` preferred `percent_remaining` for the bar while the
caption came from `entitlement`/`remaining`. With `percent_remaining: 30,
entitlement: 300, remaining: 72` that drew a 70%-wide bar captioned
"228/300" — which is 76%. The caption is the number the user reads, so the
percentage is now derived from the counts whenever both arrive;
`percent_remaining` stays the fallback for the case it exists to cover, a
percentage with no denominator.
2. A null count read as zero remaining.
`Number(null)` is 0, so `remaining: null` reported the entire allowance
consumed — "300/300" beside a percentage saying 10% used. That tells
someone their quota is gone when they have barely touched it. Counts now
require an actual finite number, and an absent one falls back to the
percentage with no counts emitted at all.
3. Clamping the wrong half in the dashboard.
`getWindowCounts` clamped only the low end, so an unclamped payload
rendered "312/300" in Used mode from `used: 312` AND in Remaining mode from
`used: -12`. Clamping into [0, limit] now happens before the mode flip. The
current server clamps, but a newer dashboard talks to whatever server is
installed — which is exactly what the discarded comment claimed to handle.
Also: README:99 still said the quota chips show a used percentage. I fixed
that claim at README:83 in the previous commit and assumed it was the only
one. It was not.
Refs #97
Non-blocking findings from the QA re-check. Both described the card chip as
showing label + %, which stopped being true when the count replaced it.
@pitimon
pitimon merged commit 493d693 into mainJul 25, 2026
1 check passed
@pitimon
pitimon deleted the feat/97-copilot-quota-counts branch July 25, 2026 03:44
@pitimonpitimon mentioned this pull request Jul 25, 2026
6 tasks
pitimon added a commit that referenced this pull request Jul 25, 2026
Ships #98 (issue #97): GitHub Copilot quota now reports the premium-request
count — "158/300", or "142/300" in Remaining mode — instead of a percentage
the reader has to convert. The numbers were already being fetched from
api.github.com and discarded after one division.
The independent Codex QA gate returned SHIP: NO on the first cut and all
three findings were real: the bar and its caption could be drawn from
different fields and disagree (70% beside 228/300, which is 76%); a null
`remaining` coerced to zero and reported the whole allowance consumed; and
the dashboard clamped only one end, so an unclamped payload could render
"312/300" in either mode. Fixed, each with a regression test built from the
exact reproduction.
First release where the `version` lifecycle hook from #96 did its job: the
bump synced TokenTrackerBar/project.yml and TokenTrackerWin.csproj, which is
what made 0.39.39–0.39.42 unable to cut a desktop build.
prepublishOnly re-vendored the LiteLLM seed: 2,522 models, no rate changes,
only _meta.generated_at moved.
Co-authored-by: itarun.p <itarun.p@somapait.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copilot quota: show the premium-request count, not just a percentage

1 participant

@pitimon
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(limits): show Copilot premium-request counts, not just a percentage - #98

Merged
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts
Jul 25, 2026
Merged

feat(limits): show Copilot premium-request counts, not just a percentage#98
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts

Conversation

@pitimon

Copy link
Copy Markdown
Owner

Closes#97. From a user question: "can TokenTracker track GitHub Copilot credits?"

It already reads them. It was throwing the answer away.

The defect

fetchCopilotLimits pulls quota_snapshots.premium_interactions from api.github.com, which carries entitlement and remaining. buildCopilotWindow did this:

usedPercent=((entitlement-remaining)/entitlement)*100;returnbuildWindow({ usedPercent,resetAt: resetIso});// ← both numbers gone

So the card read Premium 53% when GitHub had said 158 of 300 used. "53%" needs arithmetic before it means anything. "142 left" is the decision.

Change

buildWindow takes optional used/limit and emits them only when a provider reports countable units. Everyone else passes neither, so the keys are omitted rather than set to null — other providers' payloads stay byte-identical and no consumer has to learn a field it will never see. A test pins that shape for Cursor.

Where a count exists, it replaces the percentage:

SurfaceWhy the count wins
Card chipThe 4-tier coloured dot and tint already carry severity, so dropping the percent sign loses nothing. Tooltip keeps both.
Limits page barThe bar is a proportional drawing of the percentage — printing 53% beside a 53%-wide bar repeats itself. 158/300 beside it does not.

Both follow the existing Used/Remaining toggle: 158/300 used, 142/300 left.

The count is clamped to the allowance. Copilot keeps billing past quota so remaining can go negative, and 312/300 used reads as a bug even when it's true — the percentage has always been clamped for the same reason.

Deliberately not in scope

  • Cost of over-quota premium requests. GitHub bills those per request; TokenTracker doesn't model it, and guessing would be worse than the silence.
  • Copilot token/cost rows. Those come from parseCopilotIncremental reading Copilot's OTEL export (COPILOT_OTEL_ENABLED=true) — a completely separate mechanism from quota, already explained by the in-app limits.copilot.otelHint panel. Users conflate the two; that's a docs problem, not this one.

Test plan

  • npm run ci:local — exit 0, 839/839 root (+6), 255 dashboard (+7)
  • There was no test anywhere for fetchCopilotLimits before this — grep -rl 'fetchCopilotLimits\|copilot_internal' test/ was empty. New file covers counts flowing through, percent_remaining-only (no denominator → no counts), over-quota clamping, the pre-existing all-zero-snapshot guard, and the no-token path
  • Reverted both source files against HEAD and re-ran: 2 server + 5 dashboard tests fail, confirming they exercise the change
  • Render assertions in UsageLimitsPanel.test.jsx, not just pure functions — the counts reach the screen through a copy() key, and a mistyped key renders as the raw key string while every getWindowCounts unit test still passes. That test also caught my own wrong prop guess (mode vs displayMode)
  • Caught while reviewing: one regression guard was passing vacuously — the Cursor fixture produced no windows, so the loop body never ran. Now asserts the windows exist before inspecting them
  • mock-data.ts ships a configured Copilot, so the chip is visible under dashboard:dev without a real Copilot install
  • Not verified against a live Copilot account — this machine reports configured: false (no token on disk), so the API-shape assumptions come from the existing parser, not from a live response

Note

README's quota bullet claimed the chips show "used %", which this change makes untrue — updated in the same commit rather than left to drift.

itarun.p added 3 commits July 25, 2026 10:15
A user asked whether TokenTracker can track GitHub Copilot credits. It
already reads them — and then throws the answer away.
`fetchCopilotLimits` pulls `quota_snapshots.premium_interactions` from
api.github.com, which carries `entitlement` and `remaining`. buildCopilotWindow
divided them into a percentage and dropped both numbers, so the card showed
"Premium 53%" when GitHub had said "158 of 300 used". 53% needs arithmetic
before it means anything; 142 left is the decision itself.
buildWindow now takes optional `used`/`limit` and emits them only when a
provider reports countable units. Everyone else passes neither, so the keys
are omitted rather than set to null — other providers' payloads stay
byte-identical and no consumer learns a field it will never see. A test
asserts that shape for Cursor.
On the surface, the count replaces the percentage where one exists:
- Card chip: the 4-tier coloured dot and tint already carry severity, so
dropping the percent sign loses nothing, and the tooltip keeps both.
- Limits page bar: the bar *is* a proportional drawing of the percentage, so
printing "53%" beside a 53%-wide bar repeats itself. "158/300" does not.
- Both follow the Used/Remaining toggle: 158/300 used, 142/300 left.
The count is clamped to the allowance. Copilot keeps billing past the quota
so `remaining` can go negative, and "312/300 used" reads as a bug even when
it is true — the percentage has always been clamped for the same reason.
There was no test anywhere for fetchCopilotLimits before this. The new file
also covers the pre-existing all-zero-snapshot guard and the no-token path,
and the mock data now ships a configured Copilot so the chip is visible under
`dashboard:dev` on a machine that has never signed in to Copilot.
README's quota bullet said the chips show "used %", which this makes untrue,
so it says what they show now.
Closes#97
Independent QA at xhigh returned SHIP: NO on the first cut. All three were
real and all three were mine; each is reproduced below and now has a
regression test.
1. Percentage and count could describe different realities.
`buildCopilotWindow` preferred `percent_remaining` for the bar while the
caption came from `entitlement`/`remaining`. With `percent_remaining: 30,
entitlement: 300, remaining: 72` that drew a 70%-wide bar captioned
"228/300" — which is 76%. The caption is the number the user reads, so the
percentage is now derived from the counts whenever both arrive;
`percent_remaining` stays the fallback for the case it exists to cover, a
percentage with no denominator.
2. A null count read as zero remaining.
`Number(null)` is 0, so `remaining: null` reported the entire allowance
consumed — "300/300" beside a percentage saying 10% used. That tells
someone their quota is gone when they have barely touched it. Counts now
require an actual finite number, and an absent one falls back to the
percentage with no counts emitted at all.
3. Clamping the wrong half in the dashboard.
`getWindowCounts` clamped only the low end, so an unclamped payload
rendered "312/300" in Used mode from `used: 312` AND in Remaining mode from
`used: -12`. Clamping into [0, limit] now happens before the mode flip. The
current server clamps, but a newer dashboard talks to whatever server is
installed — which is exactly what the discarded comment claimed to handle.
Also: README:99 still said the quota chips show a used percentage. I fixed
that claim at README:83 in the previous commit and assumed it was the only
one. It was not.
Refs #97
Non-blocking findings from the QA re-check. Both described the card chip as
showing label + %, which stopped being true when the count replaced it.
@pitimon
pitimon merged commit 493d693 into mainJul 25, 2026
1 check passed
@pitimon
pitimon deleted the feat/97-copilot-quota-counts branch July 25, 2026 03:44
@pitimonpitimon mentioned this pull request Jul 25, 2026
6 tasks
pitimon added a commit that referenced this pull request Jul 25, 2026
Ships #98 (issue #97): GitHub Copilot quota now reports the premium-request
count — "158/300", or "142/300" in Remaining mode — instead of a percentage
the reader has to convert. The numbers were already being fetched from
api.github.com and discarded after one division.
The independent Codex QA gate returned SHIP: NO on the first cut and all
three findings were real: the bar and its caption could be drawn from
different fields and disagree (70% beside 228/300, which is 76%); a null
`remaining` coerced to zero and reported the whole allowance consumed; and
the dashboard clamped only one end, so an unclamped payload could render
"312/300" in either mode. Fixed, each with a regression test built from the
exact reproduction.
First release where the `version` lifecycle hook from #96 did its job: the
bump synced TokenTrackerBar/project.yml and TokenTrackerWin.csproj, which is
what made 0.39.39–0.39.42 unable to cut a desktop build.
prepublishOnly re-vendored the LiteLLM seed: 2,522 models, no rate changes,
only _meta.generated_at moved.
Co-authored-by: itarun.p <itarun.p@somapait.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copilot quota: show the premium-request count, not just a percentage

1 participant

@pitimon
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(limits): show Copilot premium-request counts, not just a percentage - #98

Merged
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts
Jul 25, 2026
Merged

feat(limits): show Copilot premium-request counts, not just a percentage#98
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts

Conversation

@pitimon

Copy link
Copy Markdown
Owner

Closes#97. From a user question: "can TokenTracker track GitHub Copilot credits?"

It already reads them. It was throwing the answer away.

The defect

fetchCopilotLimits pulls quota_snapshots.premium_interactions from api.github.com, which carries entitlement and remaining. buildCopilotWindow did this:

usedPercent=((entitlement-remaining)/entitlement)*100;returnbuildWindow({ usedPercent,resetAt: resetIso});// ← both numbers gone

So the card read Premium 53% when GitHub had said 158 of 300 used. "53%" needs arithmetic before it means anything. "142 left" is the decision.

Change

buildWindow takes optional used/limit and emits them only when a provider reports countable units. Everyone else passes neither, so the keys are omitted rather than set to null — other providers' payloads stay byte-identical and no consumer has to learn a field it will never see. A test pins that shape for Cursor.

Where a count exists, it replaces the percentage:

SurfaceWhy the count wins
Card chipThe 4-tier coloured dot and tint already carry severity, so dropping the percent sign loses nothing. Tooltip keeps both.
Limits page barThe bar is a proportional drawing of the percentage — printing 53% beside a 53%-wide bar repeats itself. 158/300 beside it does not.

Both follow the existing Used/Remaining toggle: 158/300 used, 142/300 left.

The count is clamped to the allowance. Copilot keeps billing past quota so remaining can go negative, and 312/300 used reads as a bug even when it's true — the percentage has always been clamped for the same reason.

Deliberately not in scope

  • Cost of over-quota premium requests. GitHub bills those per request; TokenTracker doesn't model it, and guessing would be worse than the silence.
  • Copilot token/cost rows. Those come from parseCopilotIncremental reading Copilot's OTEL export (COPILOT_OTEL_ENABLED=true) — a completely separate mechanism from quota, already explained by the in-app limits.copilot.otelHint panel. Users conflate the two; that's a docs problem, not this one.

Test plan

  • npm run ci:local — exit 0, 839/839 root (+6), 255 dashboard (+7)
  • There was no test anywhere for fetchCopilotLimits before this — grep -rl 'fetchCopilotLimits\|copilot_internal' test/ was empty. New file covers counts flowing through, percent_remaining-only (no denominator → no counts), over-quota clamping, the pre-existing all-zero-snapshot guard, and the no-token path
  • Reverted both source files against HEAD and re-ran: 2 server + 5 dashboard tests fail, confirming they exercise the change
  • Render assertions in UsageLimitsPanel.test.jsx, not just pure functions — the counts reach the screen through a copy() key, and a mistyped key renders as the raw key string while every getWindowCounts unit test still passes. That test also caught my own wrong prop guess (mode vs displayMode)
  • Caught while reviewing: one regression guard was passing vacuously — the Cursor fixture produced no windows, so the loop body never ran. Now asserts the windows exist before inspecting them
  • mock-data.ts ships a configured Copilot, so the chip is visible under dashboard:dev without a real Copilot install
  • Not verified against a live Copilot account — this machine reports configured: false (no token on disk), so the API-shape assumptions come from the existing parser, not from a live response

Note

README's quota bullet claimed the chips show "used %", which this change makes untrue — updated in the same commit rather than left to drift.

itarun.p added 3 commits July 25, 2026 10:15
A user asked whether TokenTracker can track GitHub Copilot credits. It
already reads them — and then throws the answer away.
`fetchCopilotLimits` pulls `quota_snapshots.premium_interactions` from
api.github.com, which carries `entitlement` and `remaining`. buildCopilotWindow
divided them into a percentage and dropped both numbers, so the card showed
"Premium 53%" when GitHub had said "158 of 300 used". 53% needs arithmetic
before it means anything; 142 left is the decision itself.
buildWindow now takes optional `used`/`limit` and emits them only when a
provider reports countable units. Everyone else passes neither, so the keys
are omitted rather than set to null — other providers' payloads stay
byte-identical and no consumer learns a field it will never see. A test
asserts that shape for Cursor.
On the surface, the count replaces the percentage where one exists:
- Card chip: the 4-tier coloured dot and tint already carry severity, so
dropping the percent sign loses nothing, and the tooltip keeps both.
- Limits page bar: the bar *is* a proportional drawing of the percentage, so
printing "53%" beside a 53%-wide bar repeats itself. "158/300" does not.
- Both follow the Used/Remaining toggle: 158/300 used, 142/300 left.
The count is clamped to the allowance. Copilot keeps billing past the quota
so `remaining` can go negative, and "312/300 used" reads as a bug even when
it is true — the percentage has always been clamped for the same reason.
There was no test anywhere for fetchCopilotLimits before this. The new file
also covers the pre-existing all-zero-snapshot guard and the no-token path,
and the mock data now ships a configured Copilot so the chip is visible under
`dashboard:dev` on a machine that has never signed in to Copilot.
README's quota bullet said the chips show "used %", which this makes untrue,
so it says what they show now.
Closes#97
Independent QA at xhigh returned SHIP: NO on the first cut. All three were
real and all three were mine; each is reproduced below and now has a
regression test.
1. Percentage and count could describe different realities.
`buildCopilotWindow` preferred `percent_remaining` for the bar while the
caption came from `entitlement`/`remaining`. With `percent_remaining: 30,
entitlement: 300, remaining: 72` that drew a 70%-wide bar captioned
"228/300" — which is 76%. The caption is the number the user reads, so the
percentage is now derived from the counts whenever both arrive;
`percent_remaining` stays the fallback for the case it exists to cover, a
percentage with no denominator.
2. A null count read as zero remaining.
`Number(null)` is 0, so `remaining: null` reported the entire allowance
consumed — "300/300" beside a percentage saying 10% used. That tells
someone their quota is gone when they have barely touched it. Counts now
require an actual finite number, and an absent one falls back to the
percentage with no counts emitted at all.
3. Clamping the wrong half in the dashboard.
`getWindowCounts` clamped only the low end, so an unclamped payload
rendered "312/300" in Used mode from `used: 312` AND in Remaining mode from
`used: -12`. Clamping into [0, limit] now happens before the mode flip. The
current server clamps, but a newer dashboard talks to whatever server is
installed — which is exactly what the discarded comment claimed to handle.
Also: README:99 still said the quota chips show a used percentage. I fixed
that claim at README:83 in the previous commit and assumed it was the only
one. It was not.
Refs #97
Non-blocking findings from the QA re-check. Both described the card chip as
showing label + %, which stopped being true when the count replaced it.
@pitimon
pitimon merged commit 493d693 into mainJul 25, 2026
1 check passed
@pitimon
pitimon deleted the feat/97-copilot-quota-counts branch July 25, 2026 03:44
@pitimonpitimon mentioned this pull request Jul 25, 2026
6 tasks
pitimon added a commit that referenced this pull request Jul 25, 2026
Ships #98 (issue #97): GitHub Copilot quota now reports the premium-request
count — "158/300", or "142/300" in Remaining mode — instead of a percentage
the reader has to convert. The numbers were already being fetched from
api.github.com and discarded after one division.
The independent Codex QA gate returned SHIP: NO on the first cut and all
three findings were real: the bar and its caption could be drawn from
different fields and disagree (70% beside 228/300, which is 76%); a null
`remaining` coerced to zero and reported the whole allowance consumed; and
the dashboard clamped only one end, so an unclamped payload could render
"312/300" in either mode. Fixed, each with a regression test built from the
exact reproduction.
First release where the `version` lifecycle hook from #96 did its job: the
bump synced TokenTrackerBar/project.yml and TokenTrackerWin.csproj, which is
what made 0.39.39–0.39.42 unable to cut a desktop build.
prepublishOnly re-vendored the LiteLLM seed: 2,522 models, no rate changes,
only _meta.generated_at moved.
Co-authored-by: itarun.p <itarun.p@somapait.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copilot quota: show the premium-request count, not just a percentage

1 participant

@pitimon
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(limits): show Copilot premium-request counts, not just a percentage - #98

Merged
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts
Jul 25, 2026
Merged

feat(limits): show Copilot premium-request counts, not just a percentage#98
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts

Conversation

@pitimon

Copy link
Copy Markdown
Owner

Closes#97. From a user question: "can TokenTracker track GitHub Copilot credits?"

It already reads them. It was throwing the answer away.

The defect

fetchCopilotLimits pulls quota_snapshots.premium_interactions from api.github.com, which carries entitlement and remaining. buildCopilotWindow did this:

usedPercent=((entitlement-remaining)/entitlement)*100;returnbuildWindow({ usedPercent,resetAt: resetIso});// ← both numbers gone

So the card read Premium 53% when GitHub had said 158 of 300 used. "53%" needs arithmetic before it means anything. "142 left" is the decision.

Change

buildWindow takes optional used/limit and emits them only when a provider reports countable units. Everyone else passes neither, so the keys are omitted rather than set to null — other providers' payloads stay byte-identical and no consumer has to learn a field it will never see. A test pins that shape for Cursor.

Where a count exists, it replaces the percentage:

SurfaceWhy the count wins
Card chipThe 4-tier coloured dot and tint already carry severity, so dropping the percent sign loses nothing. Tooltip keeps both.
Limits page barThe bar is a proportional drawing of the percentage — printing 53% beside a 53%-wide bar repeats itself. 158/300 beside it does not.

Both follow the existing Used/Remaining toggle: 158/300 used, 142/300 left.

The count is clamped to the allowance. Copilot keeps billing past quota so remaining can go negative, and 312/300 used reads as a bug even when it's true — the percentage has always been clamped for the same reason.

Deliberately not in scope

  • Cost of over-quota premium requests. GitHub bills those per request; TokenTracker doesn't model it, and guessing would be worse than the silence.
  • Copilot token/cost rows. Those come from parseCopilotIncremental reading Copilot's OTEL export (COPILOT_OTEL_ENABLED=true) — a completely separate mechanism from quota, already explained by the in-app limits.copilot.otelHint panel. Users conflate the two; that's a docs problem, not this one.

Test plan

  • npm run ci:local — exit 0, 839/839 root (+6), 255 dashboard (+7)
  • There was no test anywhere for fetchCopilotLimits before this — grep -rl 'fetchCopilotLimits\|copilot_internal' test/ was empty. New file covers counts flowing through, percent_remaining-only (no denominator → no counts), over-quota clamping, the pre-existing all-zero-snapshot guard, and the no-token path
  • Reverted both source files against HEAD and re-ran: 2 server + 5 dashboard tests fail, confirming they exercise the change
  • Render assertions in UsageLimitsPanel.test.jsx, not just pure functions — the counts reach the screen through a copy() key, and a mistyped key renders as the raw key string while every getWindowCounts unit test still passes. That test also caught my own wrong prop guess (mode vs displayMode)
  • Caught while reviewing: one regression guard was passing vacuously — the Cursor fixture produced no windows, so the loop body never ran. Now asserts the windows exist before inspecting them
  • mock-data.ts ships a configured Copilot, so the chip is visible under dashboard:dev without a real Copilot install
  • Not verified against a live Copilot account — this machine reports configured: false (no token on disk), so the API-shape assumptions come from the existing parser, not from a live response

Note

README's quota bullet claimed the chips show "used %", which this change makes untrue — updated in the same commit rather than left to drift.

itarun.p added 3 commits July 25, 2026 10:15
A user asked whether TokenTracker can track GitHub Copilot credits. It
already reads them — and then throws the answer away.
`fetchCopilotLimits` pulls `quota_snapshots.premium_interactions` from
api.github.com, which carries `entitlement` and `remaining`. buildCopilotWindow
divided them into a percentage and dropped both numbers, so the card showed
"Premium 53%" when GitHub had said "158 of 300 used". 53% needs arithmetic
before it means anything; 142 left is the decision itself.
buildWindow now takes optional `used`/`limit` and emits them only when a
provider reports countable units. Everyone else passes neither, so the keys
are omitted rather than set to null — other providers' payloads stay
byte-identical and no consumer learns a field it will never see. A test
asserts that shape for Cursor.
On the surface, the count replaces the percentage where one exists:
- Card chip: the 4-tier coloured dot and tint already carry severity, so
dropping the percent sign loses nothing, and the tooltip keeps both.
- Limits page bar: the bar *is* a proportional drawing of the percentage, so
printing "53%" beside a 53%-wide bar repeats itself. "158/300" does not.
- Both follow the Used/Remaining toggle: 158/300 used, 142/300 left.
The count is clamped to the allowance. Copilot keeps billing past the quota
so `remaining` can go negative, and "312/300 used" reads as a bug even when
it is true — the percentage has always been clamped for the same reason.
There was no test anywhere for fetchCopilotLimits before this. The new file
also covers the pre-existing all-zero-snapshot guard and the no-token path,
and the mock data now ships a configured Copilot so the chip is visible under
`dashboard:dev` on a machine that has never signed in to Copilot.
README's quota bullet said the chips show "used %", which this makes untrue,
so it says what they show now.
Closes#97
Independent QA at xhigh returned SHIP: NO on the first cut. All three were
real and all three were mine; each is reproduced below and now has a
regression test.
1. Percentage and count could describe different realities.
`buildCopilotWindow` preferred `percent_remaining` for the bar while the
caption came from `entitlement`/`remaining`. With `percent_remaining: 30,
entitlement: 300, remaining: 72` that drew a 70%-wide bar captioned
"228/300" — which is 76%. The caption is the number the user reads, so the
percentage is now derived from the counts whenever both arrive;
`percent_remaining` stays the fallback for the case it exists to cover, a
percentage with no denominator.
2. A null count read as zero remaining.
`Number(null)` is 0, so `remaining: null` reported the entire allowance
consumed — "300/300" beside a percentage saying 10% used. That tells
someone their quota is gone when they have barely touched it. Counts now
require an actual finite number, and an absent one falls back to the
percentage with no counts emitted at all.
3. Clamping the wrong half in the dashboard.
`getWindowCounts` clamped only the low end, so an unclamped payload
rendered "312/300" in Used mode from `used: 312` AND in Remaining mode from
`used: -12`. Clamping into [0, limit] now happens before the mode flip. The
current server clamps, but a newer dashboard talks to whatever server is
installed — which is exactly what the discarded comment claimed to handle.
Also: README:99 still said the quota chips show a used percentage. I fixed
that claim at README:83 in the previous commit and assumed it was the only
one. It was not.
Refs #97
Non-blocking findings from the QA re-check. Both described the card chip as
showing label + %, which stopped being true when the count replaced it.
@pitimon
pitimon merged commit 493d693 into mainJul 25, 2026
1 check passed
@pitimon
pitimon deleted the feat/97-copilot-quota-counts branch July 25, 2026 03:44
@pitimonpitimon mentioned this pull request Jul 25, 2026
6 tasks
pitimon added a commit that referenced this pull request Jul 25, 2026
Ships #98 (issue #97): GitHub Copilot quota now reports the premium-request
count — "158/300", or "142/300" in Remaining mode — instead of a percentage
the reader has to convert. The numbers were already being fetched from
api.github.com and discarded after one division.
The independent Codex QA gate returned SHIP: NO on the first cut and all
three findings were real: the bar and its caption could be drawn from
different fields and disagree (70% beside 228/300, which is 76%); a null
`remaining` coerced to zero and reported the whole allowance consumed; and
the dashboard clamped only one end, so an unclamped payload could render
"312/300" in either mode. Fixed, each with a regression test built from the
exact reproduction.
First release where the `version` lifecycle hook from #96 did its job: the
bump synced TokenTrackerBar/project.yml and TokenTrackerWin.csproj, which is
what made 0.39.39–0.39.42 unable to cut a desktop build.
prepublishOnly re-vendored the LiteLLM seed: 2,522 models, no rate changes,
only _meta.generated_at moved.
Co-authored-by: itarun.p <itarun.p@somapait.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copilot quota: show the premium-request count, not just a percentage

1 participant

@pitimon
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(limits): show Copilot premium-request counts, not just a percentage - #98

Merged
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts
Jul 25, 2026
Merged

feat(limits): show Copilot premium-request counts, not just a percentage#98
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts

Conversation

@pitimon

Copy link
Copy Markdown
Owner

Closes#97. From a user question: "can TokenTracker track GitHub Copilot credits?"

It already reads them. It was throwing the answer away.

The defect

fetchCopilotLimits pulls quota_snapshots.premium_interactions from api.github.com, which carries entitlement and remaining. buildCopilotWindow did this:

usedPercent=((entitlement-remaining)/entitlement)*100;returnbuildWindow({ usedPercent,resetAt: resetIso});// ← both numbers gone

So the card read Premium 53% when GitHub had said 158 of 300 used. "53%" needs arithmetic before it means anything. "142 left" is the decision.

Change

buildWindow takes optional used/limit and emits them only when a provider reports countable units. Everyone else passes neither, so the keys are omitted rather than set to null — other providers' payloads stay byte-identical and no consumer has to learn a field it will never see. A test pins that shape for Cursor.

Where a count exists, it replaces the percentage:

SurfaceWhy the count wins
Card chipThe 4-tier coloured dot and tint already carry severity, so dropping the percent sign loses nothing. Tooltip keeps both.
Limits page barThe bar is a proportional drawing of the percentage — printing 53% beside a 53%-wide bar repeats itself. 158/300 beside it does not.

Both follow the existing Used/Remaining toggle: 158/300 used, 142/300 left.

The count is clamped to the allowance. Copilot keeps billing past quota so remaining can go negative, and 312/300 used reads as a bug even when it's true — the percentage has always been clamped for the same reason.

Deliberately not in scope

  • Cost of over-quota premium requests. GitHub bills those per request; TokenTracker doesn't model it, and guessing would be worse than the silence.
  • Copilot token/cost rows. Those come from parseCopilotIncremental reading Copilot's OTEL export (COPILOT_OTEL_ENABLED=true) — a completely separate mechanism from quota, already explained by the in-app limits.copilot.otelHint panel. Users conflate the two; that's a docs problem, not this one.

Test plan

  • npm run ci:local — exit 0, 839/839 root (+6), 255 dashboard (+7)
  • There was no test anywhere for fetchCopilotLimits before this — grep -rl 'fetchCopilotLimits\|copilot_internal' test/ was empty. New file covers counts flowing through, percent_remaining-only (no denominator → no counts), over-quota clamping, the pre-existing all-zero-snapshot guard, and the no-token path
  • Reverted both source files against HEAD and re-ran: 2 server + 5 dashboard tests fail, confirming they exercise the change
  • Render assertions in UsageLimitsPanel.test.jsx, not just pure functions — the counts reach the screen through a copy() key, and a mistyped key renders as the raw key string while every getWindowCounts unit test still passes. That test also caught my own wrong prop guess (mode vs displayMode)
  • Caught while reviewing: one regression guard was passing vacuously — the Cursor fixture produced no windows, so the loop body never ran. Now asserts the windows exist before inspecting them
  • mock-data.ts ships a configured Copilot, so the chip is visible under dashboard:dev without a real Copilot install
  • Not verified against a live Copilot account — this machine reports configured: false (no token on disk), so the API-shape assumptions come from the existing parser, not from a live response

Note

README's quota bullet claimed the chips show "used %", which this change makes untrue — updated in the same commit rather than left to drift.

itarun.p added 3 commits July 25, 2026 10:15
A user asked whether TokenTracker can track GitHub Copilot credits. It
already reads them — and then throws the answer away.
`fetchCopilotLimits` pulls `quota_snapshots.premium_interactions` from
api.github.com, which carries `entitlement` and `remaining`. buildCopilotWindow
divided them into a percentage and dropped both numbers, so the card showed
"Premium 53%" when GitHub had said "158 of 300 used". 53% needs arithmetic
before it means anything; 142 left is the decision itself.
buildWindow now takes optional `used`/`limit` and emits them only when a
provider reports countable units. Everyone else passes neither, so the keys
are omitted rather than set to null — other providers' payloads stay
byte-identical and no consumer learns a field it will never see. A test
asserts that shape for Cursor.
On the surface, the count replaces the percentage where one exists:
- Card chip: the 4-tier coloured dot and tint already carry severity, so
dropping the percent sign loses nothing, and the tooltip keeps both.
- Limits page bar: the bar *is* a proportional drawing of the percentage, so
printing "53%" beside a 53%-wide bar repeats itself. "158/300" does not.
- Both follow the Used/Remaining toggle: 158/300 used, 142/300 left.
The count is clamped to the allowance. Copilot keeps billing past the quota
so `remaining` can go negative, and "312/300 used" reads as a bug even when
it is true — the percentage has always been clamped for the same reason.
There was no test anywhere for fetchCopilotLimits before this. The new file
also covers the pre-existing all-zero-snapshot guard and the no-token path,
and the mock data now ships a configured Copilot so the chip is visible under
`dashboard:dev` on a machine that has never signed in to Copilot.
README's quota bullet said the chips show "used %", which this makes untrue,
so it says what they show now.
Closes#97
Independent QA at xhigh returned SHIP: NO on the first cut. All three were
real and all three were mine; each is reproduced below and now has a
regression test.
1. Percentage and count could describe different realities.
`buildCopilotWindow` preferred `percent_remaining` for the bar while the
caption came from `entitlement`/`remaining`. With `percent_remaining: 30,
entitlement: 300, remaining: 72` that drew a 70%-wide bar captioned
"228/300" — which is 76%. The caption is the number the user reads, so the
percentage is now derived from the counts whenever both arrive;
`percent_remaining` stays the fallback for the case it exists to cover, a
percentage with no denominator.
2. A null count read as zero remaining.
`Number(null)` is 0, so `remaining: null` reported the entire allowance
consumed — "300/300" beside a percentage saying 10% used. That tells
someone their quota is gone when they have barely touched it. Counts now
require an actual finite number, and an absent one falls back to the
percentage with no counts emitted at all.
3. Clamping the wrong half in the dashboard.
`getWindowCounts` clamped only the low end, so an unclamped payload
rendered "312/300" in Used mode from `used: 312` AND in Remaining mode from
`used: -12`. Clamping into [0, limit] now happens before the mode flip. The
current server clamps, but a newer dashboard talks to whatever server is
installed — which is exactly what the discarded comment claimed to handle.
Also: README:99 still said the quota chips show a used percentage. I fixed
that claim at README:83 in the previous commit and assumed it was the only
one. It was not.
Refs #97
Non-blocking findings from the QA re-check. Both described the card chip as
showing label + %, which stopped being true when the count replaced it.
@pitimon
pitimon merged commit 493d693 into mainJul 25, 2026
1 check passed
@pitimon
pitimon deleted the feat/97-copilot-quota-counts branch July 25, 2026 03:44
@pitimonpitimon mentioned this pull request Jul 25, 2026
6 tasks
pitimon added a commit that referenced this pull request Jul 25, 2026
Ships #98 (issue #97): GitHub Copilot quota now reports the premium-request
count — "158/300", or "142/300" in Remaining mode — instead of a percentage
the reader has to convert. The numbers were already being fetched from
api.github.com and discarded after one division.
The independent Codex QA gate returned SHIP: NO on the first cut and all
three findings were real: the bar and its caption could be drawn from
different fields and disagree (70% beside 228/300, which is 76%); a null
`remaining` coerced to zero and reported the whole allowance consumed; and
the dashboard clamped only one end, so an unclamped payload could render
"312/300" in either mode. Fixed, each with a regression test built from the
exact reproduction.
First release where the `version` lifecycle hook from #96 did its job: the
bump synced TokenTrackerBar/project.yml and TokenTrackerWin.csproj, which is
what made 0.39.39–0.39.42 unable to cut a desktop build.
prepublishOnly re-vendored the LiteLLM seed: 2,522 models, no rate changes,
only _meta.generated_at moved.
Co-authored-by: itarun.p <itarun.p@somapait.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copilot quota: show the premium-request count, not just a percentage

1 participant

@pitimon
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(limits): show Copilot premium-request counts, not just a percentage - #98

Merged
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts
Jul 25, 2026
Merged

feat(limits): show Copilot premium-request counts, not just a percentage#98
pitimon merged 3 commits into
mainfrom
feat/97-copilot-quota-counts

Conversation

@pitimon

Copy link
Copy Markdown
Owner

Closes#97. From a user question: "can TokenTracker track GitHub Copilot credits?"

It already reads them. It was throwing the answer away.

The defect

fetchCopilotLimits pulls quota_snapshots.premium_interactions from api.github.com, which carries entitlement and remaining. buildCopilotWindow did this:

usedPercent=((entitlement-remaining)/entitlement)*100;returnbuildWindow({ usedPercent,resetAt: resetIso});// ← both numbers gone

So the card read Premium 53% when GitHub had said 158 of 300 used. "53%" needs arithmetic before it means anything. "142 left" is the decision.

Change

buildWindow takes optional used/limit and emits them only when a provider reports countable units. Everyone else passes neither, so the keys are omitted rather than set to null — other providers' payloads stay byte-identical and no consumer has to learn a field it will never see. A test pins that shape for Cursor.

Where a count exists, it replaces the percentage:

SurfaceWhy the count wins
Card chipThe 4-tier coloured dot and tint already carry severity, so dropping the percent sign loses nothing. Tooltip keeps both.
Limits page barThe bar is a proportional drawing of the percentage — printing 53% beside a 53%-wide bar repeats itself. 158/300 beside it does not.

Both follow the existing Used/Remaining toggle: 158/300 used, 142/300 left.

The count is clamped to the allowance. Copilot keeps billing past quota so remaining can go negative, and 312/300 used reads as a bug even when it's true — the percentage has always been clamped for the same reason.

Deliberately not in scope

  • Cost of over-quota premium requests. GitHub bills those per request; TokenTracker doesn't model it, and guessing would be worse than the silence.
  • Copilot token/cost rows. Those come from parseCopilotIncremental reading Copilot's OTEL export (COPILOT_OTEL_ENABLED=true) — a completely separate mechanism from quota, already explained by the in-app limits.copilot.otelHint panel. Users conflate the two; that's a docs problem, not this one.

Test plan

  • npm run ci:local — exit 0, 839/839 root (+6), 255 dashboard (+7)
  • There was no test anywhere for fetchCopilotLimits before this — grep -rl 'fetchCopilotLimits\|copilot_internal' test/ was empty. New file covers counts flowing through, percent_remaining-only (no denominator → no counts), over-quota clamping, the pre-existing all-zero-snapshot guard, and the no-token path
  • Reverted both source files against HEAD and re-ran: 2 server + 5 dashboard tests fail, confirming they exercise the change
  • Render assertions in UsageLimitsPanel.test.jsx, not just pure functions — the counts reach the screen through a copy() key, and a mistyped key renders as the raw key string while every getWindowCounts unit test still passes. That test also caught my own wrong prop guess (mode vs displayMode)
  • Caught while reviewing: one regression guard was passing vacuously — the Cursor fixture produced no windows, so the loop body never ran. Now asserts the windows exist before inspecting them
  • mock-data.ts ships a configured Copilot, so the chip is visible under dashboard:dev without a real Copilot install
  • Not verified against a live Copilot account — this machine reports configured: false (no token on disk), so the API-shape assumptions come from the existing parser, not from a live response

Note

README's quota bullet claimed the chips show "used %", which this change makes untrue — updated in the same commit rather than left to drift.

itarun.p added 3 commits July 25, 2026 10:15
A user asked whether TokenTracker can track GitHub Copilot credits. It
already reads them — and then throws the answer away.
`fetchCopilotLimits` pulls `quota_snapshots.premium_interactions` from
api.github.com, which carries `entitlement` and `remaining`. buildCopilotWindow
divided them into a percentage and dropped both numbers, so the card showed
"Premium 53%" when GitHub had said "158 of 300 used". 53% needs arithmetic
before it means anything; 142 left is the decision itself.
buildWindow now takes optional `used`/`limit` and emits them only when a
provider reports countable units. Everyone else passes neither, so the keys
are omitted rather than set to null — other providers' payloads stay
byte-identical and no consumer learns a field it will never see. A test
asserts that shape for Cursor.
On the surface, the count replaces the percentage where one exists:
- Card chip: the 4-tier coloured dot and tint already carry severity, so
dropping the percent sign loses nothing, and the tooltip keeps both.
- Limits page bar: the bar *is* a proportional drawing of the percentage, so
printing "53%" beside a 53%-wide bar repeats itself. "158/300" does not.
- Both follow the Used/Remaining toggle: 158/300 used, 142/300 left.
The count is clamped to the allowance. Copilot keeps billing past the quota
so `remaining` can go negative, and "312/300 used" reads as a bug even when
it is true — the percentage has always been clamped for the same reason.
There was no test anywhere for fetchCopilotLimits before this. The new file
also covers the pre-existing all-zero-snapshot guard and the no-token path,
and the mock data now ships a configured Copilot so the chip is visible under
`dashboard:dev` on a machine that has never signed in to Copilot.
README's quota bullet said the chips show "used %", which this makes untrue,
so it says what they show now.
Closes#97
Independent QA at xhigh returned SHIP: NO on the first cut. All three were
real and all three were mine; each is reproduced below and now has a
regression test.
1. Percentage and count could describe different realities.
`buildCopilotWindow` preferred `percent_remaining` for the bar while the
caption came from `entitlement`/`remaining`. With `percent_remaining: 30,
entitlement: 300, remaining: 72` that drew a 70%-wide bar captioned
"228/300" — which is 76%. The caption is the number the user reads, so the
percentage is now derived from the counts whenever both arrive;
`percent_remaining` stays the fallback for the case it exists to cover, a
percentage with no denominator.
2. A null count read as zero remaining.
`Number(null)` is 0, so `remaining: null` reported the entire allowance
consumed — "300/300" beside a percentage saying 10% used. That tells
someone their quota is gone when they have barely touched it. Counts now
require an actual finite number, and an absent one falls back to the
percentage with no counts emitted at all.
3. Clamping the wrong half in the dashboard.
`getWindowCounts` clamped only the low end, so an unclamped payload
rendered "312/300" in Used mode from `used: 312` AND in Remaining mode from
`used: -12`. Clamping into [0, limit] now happens before the mode flip. The
current server clamps, but a newer dashboard talks to whatever server is
installed — which is exactly what the discarded comment claimed to handle.
Also: README:99 still said the quota chips show a used percentage. I fixed
that claim at README:83 in the previous commit and assumed it was the only
one. It was not.
Refs #97
Non-blocking findings from the QA re-check. Both described the card chip as
showing label + %, which stopped being true when the count replaced it.
@pitimon
pitimon merged commit 493d693 into mainJul 25, 2026
1 check passed
@pitimon
pitimon deleted the feat/97-copilot-quota-counts branch July 25, 2026 03:44
@pitimonpitimon mentioned this pull request Jul 25, 2026
6 tasks
pitimon added a commit that referenced this pull request Jul 25, 2026
Ships #98 (issue #97): GitHub Copilot quota now reports the premium-request
count — "158/300", or "142/300" in Remaining mode — instead of a percentage
the reader has to convert. The numbers were already being fetched from
api.github.com and discarded after one division.
The independent Codex QA gate returned SHIP: NO on the first cut and all
three findings were real: the bar and its caption could be drawn from
different fields and disagree (70% beside 228/300, which is 76%); a null
`remaining` coerced to zero and reported the whole allowance consumed; and
the dashboard clamped only one end, so an unclamped payload could render
"312/300" in either mode. Fixed, each with a regression test built from the
exact reproduction.
First release where the `version` lifecycle hook from #96 did its job: the
bump synced TokenTrackerBar/project.yml and TokenTrackerWin.csproj, which is
what made 0.39.39–0.39.42 unable to cut a desktop build.
prepublishOnly re-vendored the LiteLLM seed: 2,522 models, no rate changes,
only _meta.generated_at moved.
Co-authored-by: itarun.p <itarun.p@somapait.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copilot quota: show the premium-request count, not just a percentage

1 participant

@pitimon