mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-10-19 18:23:41 +00:00
fix(plan): move the Copilot credits bar onto the estimate and print whole credits (#1199)
This commit is contained in:
parent
d879d6590b
commit
616a1fada2
7 changed files with 20 additions and 13 deletions
|
|
@ -160,7 +160,8 @@ see the #927 ruling in `src/session-cache.ts`).
|
|||
figure)`), and `codeburn status --format json | jq .plans.copilot` carries
|
||||
`spentCredits` (exact only), `estimatedCredits` (exact plus estimate),
|
||||
`creditRatedCalls` / `creditUnratedCalls`, `creditsIncomplete` and a plain
|
||||
`creditsNote`. The bar and `percentUsed` deliberately stay on the exact figure.
|
||||
`creditsNote`. The bar and `percentUsed` follow `estimatedCredits` while any
|
||||
request is unrated, and the exact figure once every request carries one.
|
||||
For the live authoritative number, use the menubar's GitHub quota endpoint
|
||||
(separate system, PR #1200).
|
||||
- **Sync.** `codeburn sync push` holds a copilot session until it has been
|
||||
|
|
|
|||
|
|
@ -557,9 +557,9 @@ export function planBudgetHeadline(planUsage: PlanUsage): string {
|
|||
if (unrated > 0) {
|
||||
const rated = planUsage.creditRatedCalls ?? 0
|
||||
const estimated = planUsage.estimatedCredits ?? spent
|
||||
// Tenths, not the exact-figure precision: the bulk of this number is
|
||||
// priced from tokens, so more digits would claim accuracy it lacks.
|
||||
const shown = formatCredits(Math.round(estimated * 10) / 10)
|
||||
// Whole credits only: the bulk of this number is priced from tokens,
|
||||
// so decimals would claim accuracy it lacks.
|
||||
const shown = formatCredits(Math.round(estimated))
|
||||
return `${planLabel(planUsage)}: ~${shown} / ${formatCredits(budget)} AI Credits (estimated; ${rated} of ${rated + unrated} requests carry GitHub's exact figure)`
|
||||
}
|
||||
return `${planLabel(planUsage)}: ${formatCredits(spent)} / ${formatCredits(budget)} AI Credits`
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -152,7 +152,7 @@ export function copilotCreditsNote(rated: number, unrated: number): string {
|
|||
if (unrated === 0) {
|
||||
return `All ${rated} Copilot requests in this period carry GitHub's exact credit figure, so spentCredits is complete.`
|
||||
}
|
||||
return `${rated} of ${rated + unrated} Copilot requests carry GitHub's exact credit figure (Copilot CLI session-store rows are the only local source that has it). spentCredits counts only those; estimatedCredits adds the rest priced from tokens at listed API rates, which is a floor because request multipliers and cached-token pricing are not modelled. percentUsed still tracks spentCredits.`
|
||||
return `${rated} of ${rated + unrated} Copilot requests carry GitHub's exact credit figure (Copilot CLI session-store rows are the only local source that has it). spentCredits counts only those; estimatedCredits adds the rest priced from tokens at listed API rates, which is a floor because request multipliers and cached-token pricing are not modelled. percentUsed tracks estimatedCredits while any request is unrated.`
|
||||
}
|
||||
|
||||
export function projectMonthEnd(
|
||||
|
|
@ -203,7 +203,11 @@ export function getPlanUsageFromProjects(plan: Plan, projects: ProjectSummary[],
|
|||
if (isCopilotCreditsPlan(plan)) {
|
||||
const { spentCredits, estimatedCredits, creditRatedCalls, creditUnratedCalls, creditsIncomplete } = copilotCreditSpend(projects)
|
||||
const budgetCredits = plan.monthlyCredits ?? 0
|
||||
const percentUsed = budgetCredits > 0 ? (spentCredits / budgetCredits) * 100 : 0
|
||||
// The bar follows the estimate once any request lacks an exact figure:
|
||||
// a bar at 0% beside a 19k real bill is the misleading picture #1199
|
||||
// reported, and the estimate is a floor, so it under-alerts, never over.
|
||||
const barCredits = creditUnratedCalls > 0 ? estimatedCredits : spentCredits
|
||||
const percentUsed = budgetCredits > 0 ? (barCredits / budgetCredits) * 100 : 0
|
||||
const spent = creditsToUsd(spentCredits)
|
||||
const status: PlanStatus = percentUsed > 100 ? 'over' : percentUsed >= PLAN_NEAR_THRESHOLD_PCT ? 'near' : 'under'
|
||||
const projectedMonthUsd = projectMonthEnd(projects, periodStart, periodEnd, today, spent, call => planCallSpend(plan, call))
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ describe('plan budget copy', () => {
|
|||
creditUnratedCalls: 469,
|
||||
})
|
||||
expect(planBudgetHeadline(copilot))
|
||||
.toBe("Copilot Max: ~9800.4 / 20000 AI Credits (estimated; 4 of 473 requests carry GitHub's exact figure)")
|
||||
.toBe("Copilot Max: ~9800 / 20000 AI Credits (estimated; 4 of 473 requests carry GitHub's exact figure)")
|
||||
expect(planBudgetHeadline(copilot)).not.toContain('—')
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -504,7 +504,7 @@ describe('copilot AI credit plan math', () => {
|
|||
expect(usage.status).toBe('under')
|
||||
})
|
||||
|
||||
it('does not fill the credits bar from token costUSD when nanoAiu is missing', () => {
|
||||
it('fills the credits bar from the token estimate when nanoAiu is missing', () => {
|
||||
const usage = getPlanUsageFromProjects(copilotPro, [
|
||||
usageProject([
|
||||
usageCall({
|
||||
|
|
@ -517,7 +517,9 @@ describe('copilot AI credit plan math', () => {
|
|||
|
||||
expect(usage.spentCredits).toBe(0)
|
||||
expect(usage.creditsIncomplete).toBe(true)
|
||||
expect(usage.percentUsed).toBe(0)
|
||||
// 42 USD at 0.01 USD per credit against the 1500-credit Pro budget.
|
||||
expect(usage.percentUsed).toBe(280)
|
||||
expect(usage.status).toBe('over')
|
||||
expect(usage.spentApiEquivalentUsd).toBe(0)
|
||||
})
|
||||
|
||||
|
|
@ -618,7 +620,7 @@ describe('copilot AI credit plan math', () => {
|
|||
expect(spend.creditsIncomplete).toBe(true)
|
||||
})
|
||||
|
||||
it('leaves the bar and percentUsed on the exact figure while exposing the estimate', () => {
|
||||
it('moves the bar and percentUsed onto the estimate while exposing the exact figure', () => {
|
||||
const usage = getPlanUsageFromProjects(copilotPro, [
|
||||
usageProject([
|
||||
usageCall({ provider: 'copilot', costUSD: 0.42, timestamp: '2026-08-05T12:00:00.000Z' }),
|
||||
|
|
@ -626,7 +628,7 @@ describe('copilot AI credit plan math', () => {
|
|||
], today)
|
||||
|
||||
expect(usage.spentCredits).toBe(0)
|
||||
expect(usage.percentUsed).toBe(0)
|
||||
expect(usage.percentUsed).toBeCloseTo(2.8, 10)
|
||||
expect(usage.estimatedCredits).toBeCloseTo(42, 10)
|
||||
expect(usage.creditUnratedCalls).toBe(1)
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue