Skip to content

Commit b3fa684

Browse files
asizikovCopilot
andcommitted
fix: address additional PR review feedback
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 6b6c650 commit b3fa684

9 files changed

Lines changed: 64 additions & 45 deletions

File tree

.github/workflows/pages.yml

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ concurrency:
1515

1616
env:
1717
CI: true
18-
NODE_VERSION: '24'
18+
NODE_VERSION: '20'
1919

2020
defaults:
2121
run:
@@ -28,8 +28,6 @@ jobs:
2828
timeout-minutes: 15
2929
permissions:
3030
contents: read
31-
pages: write
32-
id-token: write
3331
steps:
3432
- name: Checkout repository
3533
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
@@ -51,14 +49,39 @@ jobs:
5149
run: npm run test
5250

5351
- name: Configure GitHub Pages
54-
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
52+
run: npm run build
53+
54+
pages-artifact:
55+
name: Prepare Pages artifact
56+
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
57+
runs-on: ubuntu-latest
58+
needs: build
59+
timeout-minutes: 15
60+
permissions:
61+
contents: read
62+
pages: write
63+
id-token: write
64+
steps:
65+
- name: Checkout repository
66+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
67+
68+
- name: Set up Node.js
69+
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
70+
with:
71+
node-version: ${{ env.NODE_VERSION }}
72+
cache: 'npm'
73+
cache-dependency-path: package-lock.json
74+
75+
- name: Install dependencies
76+
run: npm ci
77+
78+
- name: Configure GitHub Pages
5579
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5
5680

5781
- name: Build production bundle
5882
run: npm run build
5983

6084
- name: Upload Pages artifact
61-
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
6285
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
6386
with:
6487
path: dist
@@ -70,7 +93,7 @@ jobs:
7093
name: github-pages
7194
url: ${{ steps.deployment.outputs.page_url }}
7295
runs-on: ubuntu-latest
73-
needs: build
96+
needs: pages-artifact
7497
timeout-minutes: 10
7598
permissions:
7699
pages: write

src/App.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,6 @@ function App() {
338338
dailyUsageData={dailyUsageData}
339339
rangeStart={rangeStart}
340340
rangeEnd={rangeEnd}
341-
pooledAicCredits={pooledAicCredits}
342341
/>
343342
) : activeView === 'models' ? (
344343
modelUsage && modelUsage.models.length > 0 ? (

src/components/UploadPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function UploadPage({
3333
</svg>
3434
<h1 className="upload-screen__title">Copilot Billing Preview</h1>
3535
<p className="upload-screen__subtitle">
36-
GitHub is moving to <strong>AI Credit based billing</strong> for Copilot. Starting May 2026, usage
36+
GitHub is moving to <strong>AI Credits-based billing</strong> for Copilot. Starting May 2026, usage
3737
will be measured in AI Credits (AICs) instead of Premium Requests (PRUs). This tool helps you
3838
understand how the change will impact your bill.
3939
</p>

src/views/CostCentersView.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type CostCenterRow = {
1919
function getTopRows(entries: [string, CostTotals | CostCenterUserTotals][]): CostCenterRow[] {
2020
return entries
2121
.map(([label, totals]) => ({ label, totals }))
22-
.sort((a, b) => b.totals.netAmount - a.totals.netAmount)
22+
.sort((a, b) => Math.max(b.totals.netAmount, b.totals.aicNetAmount) - Math.max(a.totals.netAmount, a.totals.aicNetAmount))
2323
.slice(0, MAX_DETAIL_ROWS)
2424
}
2525

@@ -98,16 +98,16 @@ export function CostCentersView({ data, rangeStart }: { data: CostCenterResult;
9898
{savings > 0 ? (
9999
<>
100100
<strong>{selectedCostCenterName}</strong>'s <strong>{periodLabel}</strong> usage would cost{' '}
101-
<strong>{formatUsd(savings)} less</strong> under AI Credit based billing
101+
<strong>{formatUsd(savings)} less</strong> under AI Credits-based billing
102102
</>
103103
) : savings < 0 ? (
104104
<>
105105
<strong>{selectedCostCenterName}</strong>'s <strong>{periodLabel}</strong> usage would cost{' '}
106-
<strong>{formatUsd(Math.abs(savings))} more</strong> under AI Credit based billing
106+
<strong>{formatUsd(Math.abs(savings))} more</strong> under AI Credits-based billing
107107
</>
108108
) : (
109109
<>
110-
<strong>{selectedCostCenterName}</strong>'s <strong>{periodLabel}</strong> usage cost would be the same under AI Credit based billing
110+
<strong>{selectedCostCenterName}</strong>'s <strong>{periodLabel}</strong> usage cost would be the same under AI Credits-based billing
111111
</>
112112
)}
113113
</p>
@@ -135,7 +135,7 @@ export function CostCentersView({ data, rangeStart }: { data: CostCenterResult;
135135
</div>
136136
</div>
137137
<div className="card comparison-card">
138-
<div className="comparison-card__label">AI Credit based billing (AICs)</div>
138+
<div className="comparison-card__label">AI Credits-based billing (AICs)</div>
139139
<div className="comparison-card__big-number comparison-card__big-number--aic">{formatUsd(totals.aicNetAmount)}</div>
140140
<div className="comparison-card__period">{formatAic(totals.aicQuantity)} AICs</div>
141141
<div className="comparison-card__rate">1 AIC = $0.01</div>
@@ -162,7 +162,7 @@ export function CostCentersView({ data, rangeStart }: { data: CostCenterResult;
162162
<div className="entitlement-banner__body">
163163
<strong className="entitlement-banner__title">Pooled entitlements are coming</strong>
164164
<p className="entitlement-banner__text">
165-
Under AI Credit based billing, entitlements will be pooled across all licensed users in your organization. No more unused capacity going to waste from idle users.
165+
Under AI Credits-based billing, entitlements will be pooled across all licensed users in your organization. No more unused capacity going to waste from idle users.
166166
</p>
167167
</div>
168168
<a

src/views/FaqView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const FAQ_ITEMS: { question: string; answer: string }[] = [
33
question:
44
'Why do I see two rows with one Premium Request to the same model that cost different amounts of AI Credits?',
55
answer:
6-
'Not every request is the same. Saying "Hi" or "Thank you" to Claude Opus 4.6 costs 3 PRUs but consumes very few tokens (AI Credits) — that\'s a waste. At the same time, a complex and detailed plan implementation can run for a long time and consume a lot of AI Credits. AI Credit based billing reflects the actual work done, so short trivial exchanges become cheaper while long, intensive tasks are billed by what they truly consume.',
6+
'Not every request is the same. Saying "Hi" or "Thank you" to Claude Opus 4.6 costs 3 PRUs but consumes very few tokens (AI Credits) — that\'s a waste. At the same time, a complex and detailed plan implementation can run for a long time and consume a lot of AI Credits. AI Credits-based billing reflects the actual work done, so short trivial exchanges become cheaper while long, intensive tasks are billed by what they truly consume.',
77
},
88
]
99

src/views/ModelsView.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,11 @@ export function ModelsView({ modelUsage, aicDiscountRate, rangeStart, rangeEnd }
9797
{periodLabel && (
9898
<p className="comparison-framing">
9999
{savings > 0 ? (
100-
<><strong>{selectedModel}</strong>'s <strong>{periodLabel}</strong> usage would cost{' '}<strong>{formatUsd(savings)} less</strong> under AI Credit based billing</>
100+
<><strong>{selectedModel}</strong>'s <strong>{periodLabel}</strong> usage would cost{' '}<strong>{formatUsd(savings)} less</strong> under AI Credits-based billing</>
101101
) : savings < 0 ? (
102-
<><strong>{selectedModel}</strong>'s <strong>{periodLabel}</strong> usage would cost{' '}<strong>{formatUsd(Math.abs(savings))} more</strong> under AI Credit based billing</>
102+
<><strong>{selectedModel}</strong>'s <strong>{periodLabel}</strong> usage would cost{' '}<strong>{formatUsd(Math.abs(savings))} more</strong> under AI Credits-based billing</>
103103
) : (
104-
<><strong>{selectedModel}</strong>'s <strong>{periodLabel}</strong> usage cost would be the same under AI Credit based billing</>
104+
<><strong>{selectedModel}</strong>'s <strong>{periodLabel}</strong> usage cost would be the same under AI Credits-based billing</>
105105
)}
106106
</p>
107107
)}
@@ -128,7 +128,7 @@ export function ModelsView({ modelUsage, aicDiscountRate, rangeStart, rangeEnd }
128128
</div>
129129
</div>
130130
<div className="card comparison-card">
131-
<div className="comparison-card__label">AI Credit based billing (AICs)</div>
131+
<div className="comparison-card__label">AI Credits-based billing (AICs)</div>
132132
<div className="comparison-card__big-number comparison-card__big-number--aic">{formatUsd(selectedModelAicNetAmount)}</div>
133133
<div className="comparison-card__period">{formatAic(selectedModelTotals.aicQuantity)} AICs</div>
134134
<div className="comparison-card__rate">1 AIC = $0.01</div>

src/views/OverviewView.tsx

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@ import { DualAxisLineChart } from '../components'
22
import type { DailyUsageData } from '../pipeline/aggregators/dailyUsageAggregator'
33
import { fillDataForRange } from '../utils/fillDataForRange'
44
import { formatAic, formatUsd } from '../utils/format'
5-
import { calculateOverviewAicDiscountRate } from '../utils/overviewBilling'
65

76
type OverviewViewProps = {
87
error: string | null
98
fileName: string | null
109
dailyUsageData: DailyUsageData[]
1110
rangeStart: string | null
1211
rangeEnd: string | null
13-
pooledAicCredits: number
1412
}
1513

1614
function createEmptyDailyUsage(date: string): DailyUsageData {
@@ -32,7 +30,6 @@ export function OverviewView({
3230
dailyUsageData,
3331
rangeStart,
3432
rangeEnd,
35-
pooledAicCredits,
3633
}: OverviewViewProps) {
3734
const filledDailyUsageData = fillDataForRange(dailyUsageData, rangeStart, rangeEnd, createEmptyDailyUsage)
3835

@@ -42,16 +39,16 @@ export function OverviewView({
4239
totals.aicQuantity += day.aicQuantity
4340
totals.grossAmount += day.grossAmount
4441
totals.aicGrossAmount += day.aicGrossAmount
42+
totals.aicNetAmount += day.aicNetAmount
4543
totals.discountAmount += day.discountAmount
4644
totals.netAmount += day.netAmount
4745
return totals
4846
},
4947
{ requests: 0, aicQuantity: 0, grossAmount: 0, aicGrossAmount: 0, aicNetAmount: 0, discountAmount: 0, netAmount: 0 },
5048
)
5149

52-
const aicDiscountRate = calculateOverviewAicDiscountRate(dailyUsageData, pooledAicCredits)
53-
const aicDiscount = aicDiscountRate * overviewTotals.aicGrossAmount
54-
const aicNetAmount = Math.max(overviewTotals.aicGrossAmount - aicDiscount, 0)
50+
const aicNetAmount = overviewTotals.aicNetAmount
51+
const aicDiscount = Math.max(overviewTotals.aicGrossAmount - aicNetAmount, 0)
5552
const periodLabel = rangeStart
5653
? new Date(rangeStart + 'T00:00:00').toLocaleString('en-US', { month: 'long', year: 'numeric' })
5754
: null
@@ -70,13 +67,13 @@ export function OverviewView({
7067
{dailyUsageData.length > 0 && (
7168
<section>
7269
<div className="context-banner">
73-
<h2 className="context-banner__title">GitHub Copilot is moving to AI Credit based billing</h2>
70+
<h2 className="context-banner__title">GitHub Copilot is moving to AI Credits-based billing</h2>
7471
<p className="context-banner__body">
7572
Starting May 1, 2026, Copilot usage will be measured in AI Credits (AICs) instead of Premium Requests (PRUs). <strong className="aic-callout">1 AIC = $0.01.</strong> This preview shows what your usage would look like under the new pricing.
7673
</p>
7774
{fileName && (
7875
<p className="context-banner__note">
79-
Note: This is a preview estimate based on your uploaded report ({fileName}). Actual bills under AI Credit based billing may differ based on model mix and final pricing.
76+
Note: This is a preview estimate based on your uploaded report ({fileName}). Actual bills under AI Credits-based billing may differ based on model mix and final pricing.
8077
</p>
8178
)}
8279
<a
@@ -85,7 +82,7 @@ export function OverviewView({
8582
target="_blank"
8683
rel="noopener noreferrer"
8784
>
88-
Learn more about AI Credit based billing &rarr;
85+
Learn more about AI Credits-based billing &rarr;
8986
</a>
9087
</div>
9188

@@ -94,16 +91,16 @@ export function OverviewView({
9491
{savings > 0 ? (
9592
<>
9693
Your <strong>{periodLabel}</strong> usage would cost{' '}
97-
<strong>{formatUsd(savings)} less</strong> under AI Credit based billing
94+
<strong>{formatUsd(savings)} less</strong> under AI Credits-based billing
9895
</>
9996
) : savings < 0 ? (
10097
<>
10198
Your <strong>{periodLabel}</strong> usage would cost{' '}
102-
<strong>{formatUsd(Math.abs(savings))} more</strong> under AI Credit based billing
99+
<strong>{formatUsd(Math.abs(savings))} more</strong> under AI Credits-based billing
103100
</>
104101
) : (
105102
<>
106-
Your <strong>{periodLabel}</strong> usage cost would be the same under AI Credit based billing
103+
Your <strong>{periodLabel}</strong> usage cost would be the same under AI Credits-based billing
107104
</>
108105
)}
109106
</p>
@@ -131,7 +128,7 @@ export function OverviewView({
131128
</div>
132129
</div>
133130
<div className="card comparison-card">
134-
<div className="comparison-card__label">AI Credit based billing (AICs)</div>
131+
<div className="comparison-card__label">AI Credits-based billing (AICs)</div>
135132
<div className="comparison-card__big-number comparison-card__big-number--aic">{formatUsd(aicNetAmount)}</div>
136133
<div className="comparison-card__period">{formatAic(overviewTotals.aicQuantity)} AICs</div>
137134
<div className="comparison-card__rate">1 AIC = $0.01</div>
@@ -198,7 +195,7 @@ export function OverviewView({
198195
<div className="entitlement-banner__body">
199196
<strong className="entitlement-banner__title">Pooled entitlements are coming</strong>
200197
<p className="entitlement-banner__text">
201-
Under AI Credit based billing, entitlements will be pooled across all licensed users in your organization. No more unused capacity going to waste from idle users.
198+
Under AI Credits-based billing, entitlements will be pooled across all licensed users in your organization. No more unused capacity going to waste from idle users.
202199
</p>
203200
</div>
204201
<a
@@ -231,7 +228,7 @@ export function OverviewView({
231228
</div>
232229
<div className="next-steps__card">
233230
<h3 className="next-steps__card-title">Read the docs</h3>
234-
<p className="next-steps__card-body">Learn how AI Credit based billing works and how to plan for the transition.</p>
231+
<p className="next-steps__card-body">Learn how AI Credits-based billing works and how to plan for the transition.</p>
235232
<a href="https://docs.github.com/billing" className="next-steps__cta" target="_blank" rel="noopener noreferrer">View documentation &rarr;</a>
236233
</div>
237234
</div>

src/views/ReportGuideView.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const SAMPLE_ROW_2_ANNOTATIONS: { index: number; label: string; note: string }[]
6262
{
6363
index: 4,
6464
label: 'model',
65-
note: '"GPT-4.1" — a Base Model with a 0× PRU Multiplier. Requests to Base Models were not included in billing reports before AI Credit based billing, but now appear because every model consumes AI Credits (AICs).',
65+
note: '"GPT-4.1" — a Base Model with a 0× PRU Multiplier. Requests to Base Models were not included in billing reports before AI Credits-based billing, but now appear because every model consumes AI Credits (AICs).',
6666
},
6767
{
6868
index: 5,
@@ -88,12 +88,12 @@ const SAMPLE_ROW_2_ANNOTATIONS: { index: number; label: string; note: string }[]
8888
{
8989
index: 15,
9090
label: 'aic_quantity',
91-
note: '≈ 24.9 AICs consumed. Under AI Credit based billing, even Base Models consume AI Credits proportional to actual token usage.',
91+
note: '≈ 24.9 AICs consumed. Under AI Credits-based billing, even Base Models consume AI Credits proportional to actual token usage.',
9292
},
9393
{
9494
index: 16,
9595
label: 'aic_gross_amount',
96-
note: '≈ $0.249 (24.9 AICs × $0.01). This is what the same usage would cost under AI Credit based billing.',
96+
note: '≈ $0.249 (24.9 AICs × $0.01). This is what the same usage would cost under AI Credits-based billing.',
9797
},
9898
]
9999

@@ -136,12 +136,12 @@ const SAMPLE_ROW_1_ANNOTATIONS: { index: number; label: string; note: string }[]
136136
{
137137
index: 15,
138138
label: 'aic_quantity',
139-
note: '≈ 3.107 AICs — the AI Credit based billing equivalent of this request. AICs represent the actual tokens consumed.',
139+
note: '≈ 3.107 AICs — the AI Credits-based billing equivalent of this request. AICs represent the actual tokens consumed.',
140140
},
141141
{
142142
index: 16,
143143
label: 'aic_gross_amount',
144-
note: '≈ $0.031 (3.107 AICs × $0.01). Under AI Credit based billing this request would cost roughly $0.03.',
144+
note: '≈ $0.031 (3.107 AICs × $0.01). Under AI Credits-based billing this request would cost roughly $0.03.',
145145
},
146146
]
147147

@@ -202,7 +202,7 @@ export function ReportGuideView() {
202202
<strong>Claude Haiku 4.5</strong> in <strong>Auto</strong> mode. Auto-mode selection applies a 10% PRU
203203
discount, so 0.9 PRUs were billed at $0.04 each — a gross PRU cost of <strong>$0.036</strong>. The user's
204204
1,000 PRU/month entitlement covers this in full, so the net PRU charge is <strong>$0.00</strong>. Under
205-
AI Credit based billing, the same request would cost approximately <strong>$0.031</strong> (≈ 3.1 AICs at $0.01
205+
AI Credits-based billing, the same request would cost approximately <strong>$0.031</strong> (≈ 3.1 AICs at $0.01
206206
each).
207207
</p>
208208

@@ -215,7 +215,7 @@ export function ReportGuideView() {
215215
On <strong>11 March 2026</strong>, user <strong>mona</strong> made <strong>≈ 25 requests</strong> to{' '}
216216
<strong>GPT-4.1</strong>, a Base Model. Because Base Models carry a <strong>0× PRU Multiplier</strong>, the
217217
gross PRU cost is <strong>$0.00</strong> and this usage would not have appeared in the billing report under
218-
the old model. Under AI Credit based billing, however, the same usage consumed <strong>≈ 24.9 AICs</strong> at
218+
the old model. Under AI Credits-based billing, however, the same usage consumed <strong>≈ 24.9 AICs</strong> at
219219
$0.01 each, producing an AI Credit based cost of approximately <strong>$0.249</strong>.
220220
</p>
221221

0 commit comments

Comments
 (0)