Skip to content
2,069 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

What g1t can't do yet, and an open letter to Cloudflare1import type { ComputeKind, Reservation } from "./compute";
Merge platform pause and the hourly usage watcher: staff can pause compute, schedules, indexing or renders for everyone, the watcher emails on a breach and is never blind quietly, and the models proxy holds each run to its cap (billing 0051, integrations 0006)2import type { PauseLevel } from "./platform";
What g1t can't do yet, and an open letter to Cloudflare3import type { User, Viewer } from "./identity";
4import type { RepoPath } from "./repos";
5import type { Result } from "./result";
6
7/** Millionths of a US dollar in one dollar: the unit money is held in. */
8export const MICROS_PER_DOLLAR = 1_000_000;
9
10/** Whether workspaces are charged for agents at all, and with real money. */
11export type BillingStatus = {
12 /**
13 * False when no card processor is configured: nothing is charged, and who
14 * may run agents is decided some other way.
15 */
16 enabled: boolean;
17 /** False while the card processor is in its test mode, where cards are not real. */
18 live: boolean;
19 /**
20 * True while g1t is being built out: runs are recorded with what they
21 * cost, but nothing is charged and no credit is needed. Not forever.
22 */
23 free?: boolean;
24};
25
26/** A workspace's standing. */
27export type BillingAccount = {
28 workspace: string;
29 /**
30 * Credit left, in millionths of a dollar. Can dip below zero by the cost
31 * of the runs that were under way when it ran out.
32 */
33 balanceMicros: number;
34 status: BillingStatus;
35 /** What is added to a run's cost, in percent. */
36 marginPercent: number;
37 /** The card charged near the limit and when a month closes, if one is saved. */
38 card?: { brand: string; last4: string; expMonth: number; expYear: number } | null;
39};
40
41/** One line of a workspace's statement. */
42export type LedgerEntry = {
43 id: string;
44 /** Credit bought with a card, or an agent's run. */
45 kind: "top_up" | "usage";
46 /** Positive for credit added, negative for usage. */
47 amountMicros: number;
48 description: string;
49 /** For usage: the repository and pull request the agent worked on. */
50 repo: string | null;
51 number: number | null;
52 /** For usage: `implement`, `review` or `update`. */
53 task: string | null;
54 /** For usage: the model, by its public name. */
55 model: string | null;
56 /** For usage: who paid the model provider. */
57 billedTo: "g1t" | "workspace";
58 /** For a top-up: the username of whoever paid. */
59 createdBy: string | null;
60 /** RFC 3339. */
61 createdAt: string;
62 /** The workspace the line belongs to, which tells an enterprise's lines apart. */
63 workspace?: string | null;
64 /** For usage: what the plan's included usage paid of it. `amountMicros` is what is left to pay. */
65 creditMicros?: number;
66 /** For usage: what the workspace's trial credit paid of it. */
67 trialMicros?: number;
68 /** For usage: what g1t's open-source pool paid of it. */
69 ossMicros?: number;
70 /** For usage: what g1t covered itself, such as a trial's last run past its credit. */
71 givenMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging72 /** For usage: what the account's discount took off its price. */
73 discountMicros?: number;
74 /** For a credit from g1t, and for what of one expired or was revoked: its kind. */
75 creditKind?: CreditKind;
What g1t can't do yet, and an open letter to Cloudflare76};
77
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging78/**
79 * Why g1t gave a workspace credit. Promotional (a welcome, a referral) and
80 * goodwill (an apology) are given away when spent; a refund gives back
81 * money already paid, and never expires.
82 */
83export type CreditKind = "promotional" | "goodwill" | "refund" | "purchased";
84
85/** One credit g1t gave, with what of it was used: spent before anything paid in advance, the soonest-expiring first. */
86export type CreditGrant = {
87 /** `crd_…`, the grant's ledger reference. */
88 id: string;
89 workspace: string;
90 kind: CreditKind;
91 amountMicros: number;
92 usedMicros: number;
93 /** What can still be spent: nothing once it expired or was revoked. */
94 leftMicros: number;
95 note: string;
96 /** A refund: what it refunds, and the day of it. */
97 refundFor?: string | null;
98 refundDay?: string | null;
99 /** RFC 3339; null never expires. */
100 expiresAt: string | null;
101 createdBy: string;
102 createdAt: string;
103 state: "open" | "used" | "expired" | "revoked";
104 closedAt?: string | null;
105 closedNote?: string | null;
106 closedBy?: string | null;
107 /** What expiring or revoking took off the balance. */
108 closedMicros?: number;
109 /** What it pays for: all usage, or models only (spent first). */
110 scope?: "all" | "models";
111 /** Where it came from. */
Usage, Billing settings and prepaid AI credit; fixes from the UX audit112 source?: "staff" | "purchase" | "promo_code" | "upgrade";
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging113};
114
115/** A workspace's credits from g1t, newest first. */
116export type Credits = { grants: CreditGrant[]; leftMicros: number };
117
118/** One month's credits of one kind: given, spent that month, and taken back unused. */
119export type CreditMonth = {
120 month: string;
121 kind: CreditKind;
122 givenMicros: number;
123 grants: number;
124 usedMicros: number;
125 expiredMicros: number;
126 revokedMicros: number;
127};
128
129/** Every credit g1t gave (at most 200, filtered), the last 12 months by kind, and who gave them. */
130export type AdminCredits = { grants: CreditGrant[]; months: CreditMonth[]; staff: string[] };
131
132/** What a credit from sudo is, past its amount and note. */
133export type CreditOptions = {
134 kind: CreditKind;
135 /** RFC 3339; never for a refund. */
136 expiresAt?: string | null;
137 /** A refund: what it is for, and the day refunded (`YYYY-MM-DD`). */
138 refundFor?: string | null;
139 refundDay?: string | null;
140};
141
What g1t can't do yet, and an open letter to Cloudflare142/** What lets a sandbox, and nothing else, report what its run cost. */
143export type RunTicket = { runId: string; token: string };
144
145/**
146 * What agents cost, charged to the workspace they worked for. A workspace
147 * buys credit; each run deducts its cost plus g1t's margin; with no credit,
148 * no agent starts.
149 */
150/**
151 * The free allowance on g1t's hosted models for a workspace not otherwise
152 * open to them: a few dollars of model cost each, out of one pool, until a
153 * date. Mirrors `Trial` in `crates/contracts/src/billing.rs`.
154 */
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging155/**
156 * How an account is charged. Standard unless g1t set otherwise in sudo:
157 * custom terms are a discount (0 to 100%), a ceiling, or both. A 100%
158 * discount charges nothing and shows the usage at its price. `comped` is
159 * from before discounts and reads as 100%; billing no longer writes it.
160 */
What g1t can't do yet, and an open letter to Cloudflare161export type Terms = {
162 kind: "standard" | "comped" | "custom";
163 discountPercent: number;
164 ceilingMicros: number | null;
165 note: string;
166 until: string | null;
167 setBy: string | null;
168 setAt: string | null;
169};
170
171/**
172 * Who pays: a workspace's own account, or an enterprise's, which pays for
173 * several workspaces with one bill and one limit.
174 */
175export type PayingAccount = {
176 id: string;
177 kind: "workspace" | "enterprise";
178 name: string;
179 terms: Terms;
180 workspaces: string[];
181 /** Where an enterprise's invoices go. */
182 billingEmail?: string | null;
183 /** An enterprise's invoices, newest first. */
184 invoices?: EnterpriseInvoice[];
185 createdAt: string;
186 /** What g1t staff set for the account beyond its terms. */
187 allowances?: Allowances;
188};
189
190/** Set per account by g1t staff in sudo, on top of its terms. */
191export type Allowances = {
192 /** The g1t plan without its monthly price; usage is charged as usual. Comped accounts have it anyway. */
193 plan: boolean;
194 /** Each public repository's monthly cap on g1t's open-source pool; null for the default. */
195 ossRepoMicros: number | null;
196 /** Each workspace's trial credit, outside the monthly pool; null for the default. */
197 trialMicros: number | null;
198 /** Agents at once, in place of the plan's (2 in the first month or on the trial, then 10); null for the default. */
199 maxConcurrentAgents?: number | null;
200 /** One run's spend cap, in place of the owners' and the default $2; null for none. */
201 runCapMicros?: number | null;
202 /** What one issue's agents may spend in all, in place of the owners' and the default $10; null for none. */
203 issueCapMicros?: number | null;
Audit logs are kept by plan: a week on free, 90 days on the plan, and what staff set for an account in sudo204 /** Days of audit log its workspaces keep, in place of the plan's (7 free, 90 on the plan), longer or shorter; null for the plan's. */
205 auditRetentionDays?: number | null;
What g1t can't do yet, and an open letter to Cloudflare206 /** A hold on new compute, with why; null for none. */
207 hold?: string | null;
208};
209
210// --- Entitlements, and compute started under a reservation ------------------
211//
212// Every service that starts compute asks billing first:
213// 1. `entitlements(workspace)`: what it may do at all, its caps, and whether compute is paused.
214// 2. `reserve(...)`: holds the estimate against what may pay for it, so starts at the same moment
215// cannot overshoot together. Answers who pays first, or refuses with a stable code
216// (`not_paid`, `trial_used`, `limit`, `paused`, `oss_pool_empty`) and a message for the owner.
217// 3. `settle(reservationId, actualMicros)`: releases the hold. The charge goes on the ledger the usual way.
218// A reservation never settled lapses after `RESERVATION_HOURS`.
219
220/** A reservation that is never settled stops holding after this long. */
221export const RESERVATION_HOURS = 3;
222/** What a ceiling reads as when there is none (g1t's own workspaces). */
223export const UNLIMITED_MICROS = 1_000_000_000_000_000;
224
225/** What a workspace pays g1t on, as far as compute is concerned. Mirrors `PlanKind`. */
226export type PlanKind = "free" | "paid" | "internal" | "enterprise";
227
228// `ComputeKind` (what compute is for), `PaidBy` (who pays first: credit, trial, oss, on_demand) and
229// `Reservation` are in `./compute`, with the gate that calls `reserve` and `settle`.
230
231/** One level reached: 50, 75, 90 or 100 percent. */
232export type UsageAlert = {
233 /** `included` (the plan's included usage), `spend_limit` or `ceiling`. */
234 meter: "included" | "spend_limit" | "ceiling" | string;
235 level: number;
236 usedMicros: number;
237 limitMicros: number;
238 message: string;
239};
240
241/** An hour's spend well above the workspace's usual: new compute waits for an owner. */
242export type Spike = {
243 id: string;
244 /** `open` (waiting), `continued` (keep going) or `stopped`. */
245 status: "open" | "continued" | "stopped" | string;
246 hourMicros: number;
247 averageMicros: number;
248 detectedAt: string;
249 decidedBy?: string | null;
250 decidedAt?: string | null;
251 /** While continued: until when, unless spend doubles again first. */
252 until?: string | null;
253};
254
255/** What a workspace may do now. Mirrors `Entitlements` in `crates/contracts/src/billing.rs`. */
256export type Entitlements = {
257 workspace: string;
258 plan: PlanKind;
259 /** May start sandboxes, models, deployments and semantic search at all: paid, internal, enterprise, or free with trial credit left. */
260 compute: boolean;
261 /** The one-time trial credit left; 0 if none or used. */
262 trialMicrosLeft: number;
263 /** A card check has been done; the trial and the open-source pool need it. */
264 trialVerified: boolean;
265 /** A paid workspace still in its first billing cycle. */
266 firstMonth: boolean;
267 /** 2 in the first month or on the trial, 10 after; staff can override it. */
268 maxConcurrentAgents: number;
269 /** 60 in the first month or on the trial; otherwise the guardrails' own caps. */
270 maxRunMinutes: number;
271 /** One run's spend cap, $2 by default; staff can override it. */
272 runCapMicros: number;
273 /** Agent spend on one issue in all, $10 by default. */
274 issueCapMicros: number;
275 /** g1t's ceiling on usage not yet paid for; `UNLIMITED_MICROS` for g1t's own; 0 for free. */
276 ceilingMicros: number;
277 /** Usage not yet paid for this month, prepayment taken off. */
278 exposureMicros: number;
279 /** Why new compute is paused, for the owner; null when it is not. */
280 paused: string | null;
281 /** What open reservations hold now. */
282 heldMicros?: number;
283 /** Paid in advance and not used yet. */
284 prepaidMicros?: number;
285 /** The plan's included usage each month, and what of it is used. */
286 includedMicros?: number;
287 includedUsedMicros?: number;
Audit logs are kept by plan: a week on free, 90 days on the plan, and what staff set for an account in sudo288 /** How far back the audit log can be read and exported, and what is kept: the plan's days, or what g1t staff set for the account. */
What g1t can't do yet, and an open letter to Cloudflare289 auditRetentionDays: number;
Audit logs are kept by plan: a week on free, 90 days on the plan, and what staff set for an account in sudo290 /** Whether `auditRetentionDays` is what staff set for the account rather than the plan's. */
291 auditRetentionCustom?: boolean;
What g1t can't do yet, and an open letter to Cloudflare292 /** Private repository storage free for every workspace: past it, the plan pays and a free workspace's pushes stop. */
293 freePrivateStorageBytes: number;
294 /** The last daily measure of the workspace's private repositories (a lower bound). */
295 privateStorageBytes: number;
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member296 /** On a paid plan: package storage past the free amounts is charged, never refused. */
297 hasPlan?: boolean;
298 /** Package storage free for every workspace (public, and private): past it a free workspace's pushes are refused. */
299 packagePublicFreeBytes?: number;
300 packagePrivateFreeBytes?: number;
What g1t can't do yet, and an open letter to Cloudflare301 /** What g1t's open-source pool paid for the workspace this month. */
302 ossPaidMicros: number;
303 /** Deploy build time this month, every second of it metered. */
304 buildSecondsUsed?: number;
305 /** Git operations this month, and how many are free for every workspace. */
306 gitOperations?: number;
307 gitOperationsIncluded?: number;
308 /** The smallest amount a card is charged when a month closes. */
309 minChargeMicros: number;
310 /** A spend spike waiting for an owner, or decided. */
311 spike?: Spike | null;
312 /** Where usage stands against what is included and the limits, from 50%. */
313 alerts?: UsageAlert[];
314};
315
316/** A hold on a start's estimated cost, as billing answers it (`Reservation` in `./compute`, and more). */
317export type ReservationHeld = Reservation & {
318 /** What is held, at cost; may be less than the estimate for a free workspace's last bit of trial. */
319 heldMicros?: number;
320 /** When the hold lapses if never settled. */
321 expiresAt?: string;
322};
323
324/** A request to g1t: a higher limit, or help with usage past what was meant. */
325export type LimitRequest = {
326 id: string;
327 workspace: string;
328 kind: "limit" | "overage" | string;
329 amountMicros: number;
330 reason: string;
331 expectedMonthlyMicros: number;
332 status: "open" | "approved" | "declined" | string;
333 decidedMicros?: number | null;
334 decidedBy?: string | null;
335 /** The answer, as the owner sees it. */
336 answer?: string | null;
337 createdBy: string;
338 createdAt: string;
339 decidedAt?: string | null;
340};
341
342/** What staff see beside a request. */
343export type WorkspaceHistory = {
344 plan: PlanKind | null;
345 months: MonthFigures[];
346 paidClearedMicros: number;
347 payments: number;
348 disputes: number;
349 declines: number;
350 firstSeen: string | null;
351 ceilingMicros: number | null;
352 maxCeilingMicros: number | null;
353 spendLimitMicros: number | null;
354 lastHourMicros: number;
355 averageHourMicros: number;
356 lastDayMicros: number;
357};
358
359export type LimitRequestReview = { request: LimitRequest; history: WorkspaceHistory };
360
361/** What a one-time goodwill credit comes to: the margin on the overage, always, plus its cost up to the cap. */
362export type Goodwill = {
363 overageMicros: number;
364 marginMicros: number;
365 costMicros: number;
366 creditMicros: number;
367 absorbedMicros: number;
368};
369
370/** A workspace whose month went well past its usual, or hit a spike. */
371export type Overage = {
372 workspace: string;
373 plan: PlanKind;
374 typicalMonthMicros: number;
375 thisMonthMicros: number;
376 costMicros: number;
377 marginMicros: number;
378 spike: Spike | null;
379 topEntries: LedgerEntry[];
380 goodwill: Goodwill;
381 goodwillAvailable: boolean;
382 lastGoodwillAt: string | null;
383 request: LimitRequest | null;
384};
385
386/** One workspace's recent pace. */
387export type Velocity = {
388 workspace: string;
389 plan: PlanKind;
390 lastHourMicros: number;
391 averageHourMicros: number;
392 lastDayMicros: number;
393 thisMonthMicros: number;
394 ratio: number;
395 spike: Spike | null;
396 firstSeen: string | null;
397};
398
399/** g1t's capped budgets for free usage this month. */
400export type Pools = {
401 month: string;
402 trialGrantedMicros: number;
403 trialPoolMicros: number;
404 trialGrants: number;
405 ossUsedMicros: number;
406 ossPoolMicros: number;
407 ossRepoMicros: number;
408};
409
410export type AccountSummary = {
411 account: PayingAccount;
412 limit: Limit;
413 chargedMicros: number;
414 costMicros: number;
415 paidMicros: number;
416 /** The same figures for each of the account's workspaces that has any. */
417 byWorkspace: WorkspaceFigures[];
418 /** The last six months, oldest first. */
419 months?: MonthFigures[];
420};
421
422/** One workspace's share of an `AccountSummary`. */
423export type WorkspaceFigures = { workspace: string; chargedMicros: number; costMicros: number; paidMicros: number };
424
425export type StripeStatus = {
426 /** `test` or `live`, from the key; `off` without one. */
427 mode: "test" | "live" | "off" | string;
Stripe's webhook secret is a Worker secret, STRIPE_WEBHOOK_SECRET, from a destination made in Stripe's dashboard428 /** Whether `STRIPE_WEBHOOK_SECRET` is set, so events can be checked. */
429 secretSet: boolean;
430 /** The destination at billing's address in Stripe, as Stripe has it. */
431 webhook: { url: string; endpointId: string; status: "enabled" | "disabled" | string; events: string[]; createdAt: string } | null;
432 /** Events billing handles that the destination does not send. */
433 missingEvents: string[];
What g1t can't do yet, and an open letter to Cloudflare434 recentEvents: { id: string; kind: string; outcome: string; receivedAt: string }[];
435 error: string | null;
436};
437
438/** An enterprise's invoice: one line per workspace, paid on Stripe's page. */
439export type EnterpriseInvoice = {
440 invoiceId: string;
441 hostedUrl: string | null;
442 amountMicros: number;
443 status: "open" | "paid" | "overdue" | "void" | string;
444 period: string;
445 lines: { workspace: string; amountMicros: number }[];
446 createdAt: string;
447};
448
449/** A workspace's invoice: monthly, or when charged near its limit. Itemised, in Stripe's billing page. */
450export type WorkspaceInvoice = {
451 invoiceId: string;
452 workspace: string;
453 reason: "month" | "threshold" | string;
454 period: string;
455 amountMicros: number;
456 status: "paid" | "open" | "failed" | "void" | string;
457 hostedUrl: string | null;
458 pdfUrl: string | null;
459 lines: { description: string; amountMicros: number }[];
460 createdAt: string;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person461 /** The card processing fee on top of `amountMicros` when charged to a card, and the tax Stripe added once known. */
462 feeMicros?: number;
463 taxMicros?: number;
What g1t can't do yet, and an open letter to Cloudflare464};
465
466/** A month of the ledger, grouped by day or project, a line per kind of charge. */
467export type Statement = {
468 month: string;
469 months: string[];
470 groups: {
471 key: string;
472 label: string;
473 /** `coveredMicros`: what the plan's included usage, the trial, the open-source pool or g1t paid, not in `chargedMicros`. */
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging474 /** `priceMicros`: usage at its price; `discountMicros`: what the account's discount took off it. */
475 lines: {
476 kind: string;
477 count: number;
478 chargedMicros: number;
479 costMicros: number;
480 coveredMicros?: number;
481 priceMicros?: number;
482 discountMicros?: number;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person483 /** On `Tax` and `Card processing fees` lines: what was paid with payments on top of what reached the balance. Never charged. */
484 passedMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging485 }[];
What g1t can't do yet, and an open letter to Cloudflare486 chargedMicros: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging487 priceMicros?: number;
488 discountMicros?: number;
What g1t can't do yet, and an open letter to Cloudflare489 }[];
490 totals: {
491 chargedMicros: number;
492 paidMicros: number;
493 costMicros: number;
494 entries: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging495 /** Usage at price, and what the discount took off: charged is the price less the discount and what paid for it. */
496 priceMicros?: number;
497 discountMicros?: number;
498 /** The account's discount now, in percent; absent without one. */
499 discountPercent?: number | null;
What g1t can't do yet, and an open letter to Cloudflare500 /** What paid for usage before it was charged, such as "Paid by g1t's open-source pool". */
501 covered?: { source: "included" | "trial" | "oss_pool" | "given" | string; label: string; micros: number }[];
502 /** Owed when the month closed but under the minimum charge: on the next invoice. */
503 carriedMicros?: number;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person504 /** Tax and card processing fees paid with the month's payments, on top of `paidMicros`. */
505 taxMicros?: number;
506 cardFeeMicros?: number;
What g1t can't do yet, and an open letter to Cloudflare507 };
508};
509
510export type MonthFigures = {
511 month: string;
512 /** Usage charged, after what paid for it first. */
513 chargedMicros: number;
514 /** What usage cost g1t: never a workspace's own model provider. */
515 costMicros: number;
516 paidMicros: number;
517 /** The plan's monthly price, paid. */
518 plansMicros?: number;
519 /** What g1t gave at price (internal use, trials, the open-source pool, goodwill, covered). Not margin. */
520 givenMicros?: number;
521};
522
523/** What g1t gave this month from one source. */
524export type GivenFigures = { source: "internal" | "trial" | "oss_pool" | "goodwill" | "covered" | string; label: string; micros: number; costMicros: number };
525
526/** One internal workspace's use this month, and why it is not charged. */
527export type InternalUse = { workspace: string; reason: string; costMicros: number; entries: number };
528
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily529export type SignalKind = "at_limit" | "near_ceiling" | "declined" | "growing" | "established" | "first_payment" | "high_spend" | "cost_over_revenue";
What g1t can't do yet, and an open letter to Cloudflare530
531/** Why a workspace is worth reaching out to. */
532export type Signal = {
533 workspace: string;
534 kind: SignalKind;
535 detail: string;
536 valueMicros: number;
537 stage: string | null;
538 owner: string | null;
539 nextStep?: string | null;
540 /** When the next step is due, YYYY-MM-DD. */
541 nextAt?: string | null;
542};
543
544/** One invoice g1t has sent, a workspace's or an enterprise's. */
545export type InvoiceSummary = {
546 invoiceId: string;
547 kind: "workspace" | "enterprise";
548 account: string;
549 name: string;
550 reason: string;
551 period: string;
552 amountMicros: number;
553 status: string;
554 hostedUrl: string | null;
555 createdAt: string;
556 paidAt: string | null;
557};
558
559export type SalesStage = "none" | "lead" | "contacted" | "negotiating" | "won" | "lost" | "churn_risk";
560
561export type SalesRecord = {
562 workspace: string;
563 stage: SalesStage | string;
564 owner: string | null;
565 nextStep: string | null;
566 nextAt: string | null;
567 notes: { id: string; text: string; by: string; createdAt: string }[];
568 updatedAt: string | null;
569};
570
571export type Overview = {
572 month: string;
573 months: MonthFigures[];
574 byKind: { kind: string; chargedMicros: number; costMicros: number }[];
575 payingWorkspaces: number;
576 stopped: number;
577 nearCeiling: number;
578 declined: number;
579 openInvoicesMicros: number;
580 followUpsDue: number;
581 /** g1t's capped budgets for free usage, this month. */
582 pools?: Pools | null;
583 /** Usage charged plus the plan's price paid, this month. */
584 revenueMicros?: number;
585 activePlans?: number;
586 planMrrMicros?: number;
587 /** What g1t gave this month, by source, apart from its margin. */
588 given?: GivenFigures[];
589 /** g1t's own and Flagon's workspaces: what their use cost, and why they are not charged. */
590 internal?: InternalUse[];
591 openRequests?: number;
592 overages?: number;
593 openSpikes?: number;
594};
595
596/** A customer's Stripe billing page, for staff to send them. */
597export type BillingLink = {
598 /** One-time and short-lived, signed in already. */
599 portalUrl: string;
600 /** The page's sign-in, which does not expire: the customer signs in by email. */
601 loginUrl: string | null;
602 customerEmail: string | null;
603 expiresNote: string;
604};
605
606export type AdminAction = { id: string; account: string; action: string; detail: string; by: string; createdAt: string };
607
608export type AccountDetail = {
609 summary: AccountSummary;
610 workspaces: Limit[];
611 ledger: LedgerEntry[];
612 audit: AdminAction[];
613};
614
615/** Staff-only billing, for sudo.g1t.sh. Every change names who made it. */
616export interface BillingAdminApi {
617 accounts(query?: string): Promise<AccountSummary[]>;
618 account(id: string): Promise<Result<AccountDetail>>;
619 setTerms(id: string, terms: Terms, by: string): Promise<Result<PayingAccount>>;
620 /** Team on or off without charge, and the account's share of the pools. Needs a note. */
621 setAllowances(id: string, allowances: Allowances, note: string, by: string): Promise<Result<PayingAccount>>;
622 createEnterprise(name: string, workspaces: string[], by: string): Promise<Result<PayingAccount>>;
623 attach(workspace: string, account: string | null, by: string): Promise<Result<PayingAccount>>;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging624 /** Credit for a workspace: promotional, goodwill or a refund; the owners are emailed. */
625 credit(workspace: string, amountMicros: number, note: string, by: string, options?: CreditOptions): Promise<Result<LedgerEntry>>;
626 /** Every credit g1t gave, filtered, with each month's totals by kind. */
627 credits(filter?: { workspace?: string | null; kind?: CreditKind | null; month?: string | null; by?: string | null }): Promise<AdminCredits>;
628 /** What is left of a credit, taken back, with why. */
629 revokeCredit(id: string, note: string, by: string): Promise<Result<CreditGrant>>;
sudo: reset a test workspace's billing so it starts again as a new customer; refused on a live Stripe key, for comped workspaces and for an enterprise's630 /** A test workspace's billing wiped, to start again as a new customer. Only on Stripe's test key; never comped or enterprise. Logged. */
631 resetBilling(workspace: string, confirm: string, note: string, by: string): Promise<Result<BillingReset>>;
What g1t can't do yet, and an open letter to Cloudflare632 /** The workspace's Stripe billing page, to send to the customer. Logged. */
633 billingLink(workspace: string, by: string): Promise<Result<BillingLink>>;
634 /** Where billing stands with Stripe; with `setup`, registers the webhook first. */
Stripe's webhook secret is a Worker secret, STRIPE_WEBHOOK_SECRET, from a destination made in Stripe's dashboard635 /** Stripe's state for billing; `fix` enables the destination and adds missing events first. */
636 stripe(fix?: boolean, by?: string): Promise<StripeStatus>;
What g1t can't do yet, and an open letter to Cloudflare637 /** Where an enterprise's invoices go; makes its Stripe customer. */
638 enterpriseBilling(id: string, email: string, by: string): Promise<Result<PayingAccount>>;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person639 /** The enterprise's billing address and tax ID, on its Stripe customer: Stripe Tax works its invoices out from them. */
640 enterpriseAddress(id: string, address: PostalAddress, taxIdType: string | null, taxId: string | null, by: string): Promise<Result<boolean>>;
What g1t can't do yet, and an open letter to Cloudflare641 /** Sends an enterprise its invoice now, for what its workspaces owe. */
642 invoiceEnterprise(id: string, by: string): Promise<Result<EnterpriseInvoice>>;
643 /** Exactly these workspaces' accounts, such as one page of the list. */
644 accountsFor(workspaces: string[]): Promise<AccountSummary[]>;
645 /** Every workspace worth reaching out to, most urgent first. */
646 signals(): Promise<Signal[]>;
647 /** The business at a glance. */
648 overview(): Promise<Overview>;
649 /** A workspace's sales record. */
650 sales(workspace: string): Promise<SalesRecord>;
651 setSales(workspace: string, record: { stage: string; owner?: string | null; nextStep?: string | null; nextAt?: string | null }, by: string): Promise<Result<SalesRecord>>;
652 addNote(workspace: string, text: string, by: string): Promise<Result<SalesRecord>>;
653 /** A workspace's invoices from g1t, for staff. */
654 workspaceInvoices(workspace: string): Promise<WorkspaceInvoice[]>;
655 /** Every invoice g1t has sent, newest first. */
656 allInvoices(filter?: { status?: string; month?: string }): Promise<InvoiceSummary[]>;
657 /** Every change made in sudo and by Stripe, newest first, 100 at a time. */
658 audit(filter?: { by?: string; action?: string; before?: string }): Promise<AdminAction[]>;
659 /** Limit and overage requests, with each workspace's history; `open` by default. */
660 limitRequests(status?: "open" | "approved" | "declined" | "all"): Promise<LimitRequestReview[]>;
661 /** Approve (at the amount asked, or another) or decline; the owner is told in the app and by email. */
662 decideLimitRequest(id: string, decision: "approve" | "decline", amountMicros: number | null, note: string, by: string): Promise<Result<LimitRequest>>;
663 /** The Overages queue. */
664 overages(): Promise<Overage[]>;
665 /** A goodwill credit; no amount is the one-click credit. Larger, or a second in 12 months, needs a reason. */
666 goodwill(workspace: string, amountMicros: number | null, reason: string, by: string, day?: string | null): Promise<Result<LedgerEntry>>;
667 /** Workspaces spending in the last day, fastest first. */
668 velocity(): Promise<Velocity[]>;
669 /** Money that reached g1t outside the card pages, such as a bank transfer: entered as a payment. */
670 recordPayment(workspace: string, amountMicros: number, reference: string, note: string, by: string): Promise<Result<LedgerEntry>>;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily671 /** Costs & margin: Cloudflare's bill against what g1t charged, over the last `days` (7 to 90, 30 by default). */
672 costs(days?: number): Promise<CostsReport>;
673 /** The open margin alerts, for the banner on every page. */
674 costAlerts(): Promise<MarginAlert[]>;
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays675 /** g1t's own spend against its caps: the daily breaker and comped budgets. */
676 spendCaps(): Promise<SpendCaps>;
677 /** Lets hosted-model runs start again for the rest of today (UTC); needs a note. */
678 liftBreaker(note: string, by: string): Promise<Result<SpendCaps>>;
Merge platform pause and the hourly usage watcher: staff can pause compute, schedules, indexing or renders for everyone, the watcher emails on a breach and is never blind quietly, and the models proxy holds each run to its cap (billing 0051, integrations 0006)679 /** Platform pauses, the last hour of platform usage, the month so far and the last day's breaches (billing's platform.rs). */
680 platformGuard(): Promise<PlatformGuard>;
681 /** Pauses or resumes one level across g1t; needs a note, recorded in the audit log. */
682 setPause(level: PauseLevel, paused: boolean, note: string, by: string): Promise<Result<PlatformGuard>>;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily683 /** Approve or reject a price proposal; a rejection needs a note. An approved rise waits out the notice period. */
684 decideProposal(id: string, decision: "approve" | "reject", note: string, by: string): Promise<Result<PriceProposal>>;
685 setCostSettings(settings: CostSettings, by: string): Promise<Result<CostSettings>>;
686 setCostMapping(mapping: CostMappingInput, by: string): Promise<Result<CostMapping>>;
687 /** Reads Cloudflare's bill and reconciles now, as the daily run does. */
688 runCosts(by: string): Promise<Result<CostsRun>>;
Merge branch 'main' into actions-toolkit-oidc-artifacts689 /** Agents & models: the catalogue, each purpose's default, and the latest checks. */
690 models(): Promise<AdminModels>;
691 /** Approve a model (its prices confirmed), retire it, or restore it. Needs a reason. */
692 decideModel(
693 model: string,
694 decision: "approve" | "retire" | "restore",
695 details: { name?: string | null; tierHint?: string | null; prices?: ModelPrices | null },
696 reason: string,
697 by: string,
698 ): Promise<Result<CatalogueModel>>;
699 /** One purpose's default: a model, or for a job its tier and effort. Needs a reason. */
700 setModelDefault(
701 purpose: string,
702 value: { model?: string | null; tier?: string | null; effort?: string | null },
703 reason: string,
704 by: string,
705 ): Promise<Result<ModelDefault>>;
What g1t can't do yet, and an open letter to Cloudflare706}
707
708/** How much a workspace has earned g1t's trust with money. */
709export type Trust = "new" | "paid" | "established" | "reviewed" | "internal";
710
711/**
712 * How far a workspace's unpaid usage has gone this month, and where its
713 * work stops: past `ceilingMicros`, no new sandboxes, builds or app
714 * requests. Usage counts at its cost to g1t or its charge, whichever is
715 * more, so it counts while g1t is free too.
716 */
717export type Limit = {
718 workspace: string;
719 /** The account that pays: the workspace's own (`ws_<slug>`), or its enterprise's. */
720 account: string;
721 accountName: string;
722 trust: Trust;
723 exposureMicros: number;
724 /** The lower of g1t's ceiling and the owner's spend limit; null for g1t's own. */
725 ceilingMicros: number | null;
726 trustCeilingMicros: number | null;
727 spendLimitMicros: number | null;
728 state: "ok" | "warning" | "stopped";
729 message: string | null;
Spend adds up on one ledger. Charged this month has one definition, price less discount, included usage and credit, shared by the plan card, the spend limit, Spend and the top bar; the limit had counted usage not yet closed at full price before the discount, so a comped workspace read as charged a cent. Every agent line on the ledger names the agent and who asked, repository runs by g1t included, so Spent is the sum of its products, Agents is the agent product, and by agent adds up to it; the billing API returns by_agent and by_person. The usage and billing guide says how spend is counted.730 /**
731 * Charged this month, which the spend limit is measured against: usage at
732 * price less the discount, included usage, the trial, pools and credit,
733 * with usage metered through the month counted on the same terms. The
734 * same number as the month's `UsageTotals.chargedMicros`.
735 */
What g1t can't do yet, and an open letter to Cloudflare736 spentMicros?: number;
737 /** True while the owners have not chosen a limit, so the automatic one applies: $200, or twice last month's spend. */
738 defaultSpendLimit?: boolean;
739 /** The most owners may set their own limit to without asking: the highest ceiling ever, plus what is prepaid. */
740 availableMicros?: number | null;
741 /** How the ceiling grows from here, in a sentence. */
742 growth?: string | null;
743 /** Paid in advance and not used yet; raises what can be used before work stops by as much. */
744 prepaidMicros?: number;
745 /** The highest ceiling the workspace has had. */
746 maxCeilingMicros?: number | null;
747 /** The most owners may raise the limit to themselves, once: twice the highest ceiling. Null once used. */
748 raiseOnceMicros?: number | null;
749 /** When the one-time raise was used. */
750 raisedAt?: string | null;
751 /** A paid workspace's first billing cycle, on the starting ceiling. */
752 firstMonth?: boolean;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit753 /** The budget's alerts, in percent of the spend limit: some of 50, 75, 90 and 100. */
754 alertLevels?: number[];
755 /** Whether usage pauses at the spend limit (the default); off, it only alerts. */
756 pauseAtLimit?: boolean;
757 /** An HTTPS address told of each budget alert. */
758 budgetWebhook?: string | null;
What g1t can't do yet, and an open letter to Cloudflare759};
760
761/** One metered unit: what it costs g1t and what it is sold at; the price follows the cost. */
762export type Price = {
763 meter:
764 | "sandbox_second"
765 | "build_second"
766 | "app_requests"
767 | "app_cpu"
768 | "app_month"
769 | "custom_domain_month"
770 | "private_storage"
771 | "embedding_tokens"
772 | "scan_cpu"
773 | "scan_rows"
774 | string;
775 title: string;
776 unit: string;
777 costMicros: number;
778 markupPercent: number;
779 priceMicros: number;
780 /** `list`: Cloudflare's published price. `cloudflare`: measured from Cloudflare's bill. */
781 source: "list" | "cloudflare" | string;
782 checkedAt: string | null;
783 updatedAt: string;
784};
785
786export type PriceChange = {
787 meter: string;
788 oldCostMicros: number;
789 newCostMicros: number;
790 markupPercent: number;
791 /** The markup before, when the change was to the markup rather than the cost. */
792 oldMarkupPercent?: number;
793 reason: string;
794 createdAt: string;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily795 /** When a change still to come takes effect: a rise is announced before it is charged. */
796 effectiveAt?: string;
What g1t can't do yet, and an open letter to Cloudflare797};
798
799export type PriceBook = {
800 prices: Price[];
801 changes: PriceChange[];
802 modelMarginPercent: number;
803 /** Every plan, as sold now. */
804 plans?: FeaturePlan[];
805 /** What is free, and the capped budgets that pay for it. */
806 free?: FreeTier | null;
807};
808
809/** One kind of meter's usage this month, from `usage_meters`. */
810export type MeterUsage = {
811 /** `agents`, `builds`, `requests`, `domains`, `git_storage` or `search_scans`. */
812 key: string;
813 label: string;
814 /** At price (cost plus 20%, on the account's terms), before what paid for it. */
815 micros: number;
816 /** How much, when it is known: `12 runs`, `41 build minutes`. */
817 quantity?: string | null;
818};
819
820/** What g1t gives without a plan; each is paid for by a capped budget. */
821export type FreeTier = {
822 /** Each new workspace's trial credit, once. */
823 trialWorkspaceMicros: number;
824 /** Trial grants each month, in all; new trials wait when it is spent. */
825 trialMonthlyPoolMicros: number;
826 /** g1t's open-source pool each month, and any one repository's share. */
827 ossPoolMicros: number;
828 ossRepoMicros: number;
829 /** Private repository storage free for every workspace. Past it, the plan pays; a free workspace's pushes stop. */
830 freePrivateStorageBytes: number;
Audit logs are kept by plan: a week on free, 90 days on the plan, and what staff set for an account in sudo831 /** Days of audit log a free workspace keeps. */
What g1t can't do yet, and an open letter to Cloudflare832 auditRetentionDays: number;
Audit logs are kept by plan: a week on free, 90 days on the plan, and what staff set for an account in sudo833 /** Days of audit log the g1t plan keeps, and g1t's own and enterprise workspaces; longer by arrangement. */
834 planAuditRetentionDays?: number;
What g1t can't do yet, and an open letter to Cloudflare835 /** The smallest amount a card is charged when a month closes; less carries over. */
836 minChargeMicros: number;
837 /** Git operations free for every workspace each month. Past it, the plan pays; a free workspace is slowed down. */
838 gitOperationsIncluded?: number;
839 /** A new paid workspace's ceiling in its first month. */
840 paidStartCeilingMicros?: number;
841 /** The most a one-click goodwill credit can cost g1t. */
842 overageForgiveCostMicros?: number;
843};
844
845/**
846 * A workspace's trial credit: one grant per workspace, made the first time
847 * it uses something, out of a pool that resets each calendar month. Mirrors
848 * `Trial` in `crates/contracts/src/billing.rs`.
849 */
850export type Trial = {
851 open: boolean;
852 usedMicros: number;
853 limitMicros: number;
854 /** No longer used: trials do not end on a date. */
855 endsAt: string | null;
856 /** Why it is closed: `off`, `used` (this workspace's grant is spent) or `pool` (this month's are given out). */
857 reason: "off" | "ended" | "used" | "pool" | null;
858 /** Whether the workspace has its grant already. */
859 granted?: boolean;
860 /** With `pool`: when new trials start again, the first of next month. */
861 waitsUntil?: string | null;
862};
863
864/**
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.865 * What a workspace has: the g1t plan (`plan`), and Security and quality
866 * (`security`), which comes with the plan at no price of its own. Deployments
867 * are part of the plan too; `has_feature` for either answers whether the
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar868 * workspace has the plan. Mirrors `Feature` in `crates/contracts/src/billing.rs`.
What g1t can't do yet, and an open letter to Cloudflare869 */
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar870export type Feature = "plan" | "deployments" | "security";
What g1t can't do yet, and an open letter to Cloudflare871
872/**
873 * What deployments cost g1t, in millionths of a dollar: fallbacks for when
874 * billing's price book cannot be read. Not an allowance: on the plan every
875 * unit is metered from the first, at cost plus 20%, and drawn from the
876 * plan's included usage first. Projects, previews and the apps behind them
877 * are not metered at all. Mirrors `deployment_costs`.
878 */
879export const DEPLOYMENT_COSTS = {
880 microsPerMillionRequests: 300_000,
881 microsPerMillionCpuMs: 20_000,
882 /** One second of a build's sandbox: a fallback; billing charges the price book's `build_second`. */
883 microsPerBuildSecond: 15,
884 /** One custom domain for a month. */
885 microsPerDomainMonth: 100_000,
Merge branch 'worktree-agent-a0d1a64e2033a58ed' into claude/cool-newton-7nm8r9886 /**
887 * Container apps, at Cloudflare Containers' list prices: a vCPU-second
888 * $0.00002, a GiB-second of memory $0.0000025, a GB-second of disk
889 * $0.00000007, the Durable Object in front of each instance while it
890 * runs (128 MB at $12.50 per million GB-seconds), and a GB of egress
891 * at $0.05, the most Cloudflare charges for one anywhere (Oceania, Korea
892 * and Taiwan; $0.025 in North America and Europe), since g1t cannot
893 * tell where a container's traffic went.
894 */
895 container: {
896 vcpuSecond: 20,
897 memoryGibSecond: 2.5,
898 diskGbSecond: 0.07,
899 instanceSecond: 1.5625,
900 egressGb: 50_000,
901 },
What g1t can't do yet, and an open letter to Cloudflare902} as const;
903
904export type FeaturePlan = {
905 feature: Feature;
906 title: string;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person907 /** Charged every month while the plan is on, in cents, excluding tax. */
What g1t can't do yet, and an open letter to Cloudflare908 monthlyCents: number;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person909 /** The card processing fee on top each month, in cents (0 when off), excluding tax. */
910 cardFeeCents?: number;
What g1t can't do yet, and an open letter to Cloudflare911 /** What the price includes, one line each. */
912 includes: string[];
913 /** How usage past the allowance is charged. */
914 overage: string;
915};
916
917export type SubscriptionStatus = "active" | "canceling" | "past_due" | "canceled";
918
919export type Subscription = {
920 feature: Feature;
921 status: SubscriptionStatus;
922 /** RFC 3339: when the period paid for ends. */
923 periodEnd: string | null;
924 startedBy: string;
925 startedAt: string;
926};
927
928/** A feature as a workspace sees it. */
929export type FeatureState = {
930 plan: FeaturePlan;
931 subscription: Subscription | null;
932 /** Whether the feature works for the workspace now. */
933 on: boolean;
934 /** On without a plan: comped terms, or given by g1t. Nothing to pay or turn off. */
935 included?: boolean;
936};
937
938export interface BillingApi {
939 status(): Promise<BillingStatus>;
940 /** Members of the workspace only. */
941 account(workspace: string, viewer: Viewer): Promise<Result<BillingAccount>>;
942 /** Newest first. Members of the workspace only. */
943 ledger(workspace: string, viewer: Viewer): Promise<Result<LedgerEntry[]>>;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging944 /** Credits from g1t, newest first, with what is left of each. Members only. */
945 credits(workspace: string, viewer: Viewer): Promise<Result<Credits>>;
What g1t can't do yet, and an open letter to Cloudflare946 /** A month of the ledger, grouped by `day` (default) or `project`. Members only. */
947 statement(workspace: string, viewer: Viewer, month?: string | null, group?: "day" | "project"): Promise<Result<Statement>>;
948 /** One statement line's entries, 50 at a time; `before` is the last id seen. */
949 statementEntries(
950 workspace: string,
951 viewer: Viewer,
952 filter: { month: string; kind: string; day?: string | null; project?: string | null; before?: string | null },
953 ): Promise<Result<LedgerEntry[]>>;
954 /** What the workspace's agents cost since `since`, broken down. Members only. */
955 usage(workspace: string, viewer: Viewer, since: string): Promise<Result<Usage>>;
956 /**
Mission control shows model usage, yours and the workspace's: tokens, cost, active days, cache share, each day, and the mix957 * The model tokens the workspace's runs used, day by day over the last
958 * `days` (42, at most 366), for everyone or for one `person`. Members
959 * only; a member may ask only for themselves, an owner for anyone.
960 */
961 tokenUsage(workspace: string, viewer: User, options?: { person?: string; days?: number }): Promise<Result<TokenUsage>>;
962 /**
963 * What one model answer used, added to its run's count for the day. The
964 * model proxy sends it; for usage views only, as runs are priced from AI
965 * Gateway. False when there was nothing to count.
966 */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens967 /** What the AI Gateway offers on g1t's key, with prices per million tokens. */
968 gatewayModels(): Promise<GatewayModel[]>;
Merge branch 'main' into actions-toolkit-oidc-artifacts969 /** Every purpose's default model as it applies now, and each job's tier and effort. */
970 modelDefaults(): Promise<ModelDefaults>;
971 /** What one provider lists now, from the models service's discovery. */
972 recordDiscovery(provider: string, models: ProviderModel[], by: string, error?: string | null): Promise<DiscoveryResult>;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens973 /**
974 * Whether a workspace's next AI Gateway request may go to g1t's models:
975 * fails with `payment_required` and what to do when it is over its spend
976 * limit, out of AI credit, or not on the plan.
977 */
978 gatewayAdmit(workspace: string): Promise<Result<boolean>>;
979 /** Logs one AI Gateway request, and charges it when it used tokens on g1t's models. */
980 recordGateway(record: GatewayRecord): Promise<Result<boolean>>;
981 /** A workspace's recent AI Gateway requests, newest first. Members only. */
982 gatewayRequests(workspace: string, viewer: Viewer, options?: { limit?: number; before?: string | null }): Promise<Result<GatewayRequests>>;
Mission control shows model usage, yours and the workspace's: tokens, cost, active days, cache share, each day, and the mix983 recordTokens(usage: {
984 workspace: string;
985 /** The model session's id, one per run. */
986 session: string;
987 /** The person the run is for, by username. */
988 person?: string | null;
989 model: string;
Merge branch 'model-routing'990 tier?: "small" | "large" | "frontier" | null;
Mission control shows model usage, yours and the workspace's: tokens, cost, active days, cache share, each day, and the mix991 input: number;
992 output: number;
993 cacheRead: number;
994 cacheWrite: number;
995 }): Promise<Result<boolean>>;
996 /**
What g1t can't do yet, and an open letter to Cloudflare997 * Prepays usage ($25 at least) and returns the page to send the person to:
998 * by card with 3-D Secure, or by bank transfer from $1,000. Owners only.
999 * The payment's id comes back to `returnUrl` as `session`.
1000 */
1001 checkout(
1002 actor: User,
1003 workspace: string,
1004 amountCents: number,
1005 returnUrl: string,
1006 method?: "card" | "bank_transfer",
1007 ): Promise<Result<{ url: string }>>;
1008 /**
1009 * Stripe's hosted billing page for the workspace: card, invoices, billing
1010 * email and address. g1t never handles card numbers. Owners only.
1011 */
1012 billingPortal(actor: User, workspace: string, returnUrl: string): Promise<Result<{ url: string }>>;
1013 /** Credits a payment once the processor says it was made. Safe to repeat. */
1014 confirm(workspace: string, viewer: Viewer, session: string): Promise<Result<BillingAccount>>;
1015 /**
1016 * Whether a workspace may start an agent now, asked before anything is
1017 * opened for it. A failure, with the reason to show, when it has no credit.
1018 */
1019 canStart(workspace: string): Promise<Result<boolean>>;
1020 /** A workspace's free allowance on g1t's hosted models; `exempt` are open to them anyway. */
1021 trial(workspace: string, exempt: string[]): Promise<Trial>;
1022 /**
1023 * Asks whether a workspace may start an agent and opens the run it will be
1024 * charged for. Null when billing is off; a failure when there is no credit.
1025 */
1026 /** Every paid feature and the workspace's plan for each. Members only. */
1027 features(workspace: string, viewer: Viewer): Promise<Result<FeatureState[]>>;
1028 /**
1029 * Starts the card page for a feature's monthly plan. Owners only. The
1030 * page's id comes back to `returnUrl` as `session`.
1031 */
1032 subscribe(actor: User, workspace: string, feature: Feature, returnUrl: string): Promise<Result<{ url: string }>>;
1033 /** Turns the feature on once the plan is paid for. Safe to repeat. */
1034 confirmSubscription(workspace: string, viewer: Viewer, session: string): Promise<Result<FeatureState>>;
1035 /** Ends a plan at the end of its period, or (`resume`) takes that back. Owners only. */
1036 cancelSubscription(actor: User, workspace: string, feature: Feature, resume?: boolean): Promise<Result<FeatureState>>;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person1037 /** Which of the workspaces are free (on no paid plan); none where payments are not set up. */
1038 freeWorkspaces(workspaces: string[]): Promise<string[]>;
What g1t can't do yet, and an open letter to Cloudflare1039 /** Whether a feature works for a workspace now; a failure with the reason when not. */
1040 hasFeature(workspace: string, feature: Feature): Promise<Result<boolean>>;
1041 /**
1042 * Usage past a plan's allowance, charged from credit at cost plus the
1043 * margin, once per `reference`. False if it was charged before.
1044 */
1045 chargeFeature(charge: {
1046 workspace: string;
1047 feature: Feature;
1048 costMicros: number;
1049 description: string;
1050 repo?: string | null;
1051 reference: string;
1052 /** For a build: how long it ran, so the plan's included build time pays for what it can. */
1053 buildSeconds?: number | null;
1054 }): Promise<Result<boolean>>;
1055 /**
1056 * What a source cost g1t so far this month, so the workspace's limit
1057 * counts it now. Replaces the last report. Billing charges `context`
1058 * and `security` itself once the month is over; `deployments` charges
1059 * its own.
1060 */
1061 notePending(
1062 workspace: string,
1063 source: "deployments" | "domains" | "context" | "security",
1064 costMicros: number,
1065 /** How much of it, for the Billing page: `1.2 million requests and 3.4 million CPU ms`. */
1066 detail?: string | null,
1067 ): Promise<boolean>;
1068 /**
1069 * This month's usage, one line per kind of meter, at what it is charged
1070 * before the plan's included usage or a pool paid for it. Members only.
1071 */
1072 usageMeters(workspace: string, viewer: Viewer): Promise<Result<MeterUsage[]>>;
1073 /** What the workspace may do now: its plan, caps, pause, trial, and what the plan gives it. */
1074 entitlements(workspace: string): Promise<Entitlements>;
1075 /**
1076 * Holds a start's estimated cost before the work starts. A failure's code says why not:
1077 * `paused`, `limit`, `not_paid`, `trial_used` or `oss_pool_empty`, with a message for the owner.
1078 */
1079 reserve(reservation: {
1080 workspace: string;
1081 repo: RepoPath;
1082 public: boolean;
1083 kind: ComputeKind;
1084 /** The most the work is expected to cost g1t, before the margin. */
1085 estimateMicros: number;
1086 }): Promise<Result<ReservationHeld>>;
1087 /** Releases a reservation's hold with what the work cost g1t, before the margin. Safe to repeat. */
1088 settle(reservationId: string, actualMicros: number): Promise<Result<boolean>>;
1089 /** Stripe's page to save and verify a card (3-D Secure, never charged). Owners only. */
1090 cardCheck(actor: User, workspace: string, returnUrl: string): Promise<Result<{ url: string }>>;
1091 /** Records the card check once Stripe says it passed, and grants the trial if it can. Safe to repeat. */
1092 confirmCardCheck(workspace: string, viewer: Viewer, session: string): Promise<Result<Entitlements>>;
1093 /** An owner asks for a higher limit, or for help with usage past what was meant. */
1094 requestLimit(
1095 actor: User,
1096 workspace: string,
1097 request: { kind: "limit" | "overage"; amountMicros: number; reason: string; expectedMonthlyMicros: number },
1098 ): Promise<Result<LimitRequest>>;
1099 /** The workspace's requests and their answers, newest first. Members only. */
1100 limitRequests(workspace: string, viewer: Viewer): Promise<Result<LimitRequest[]>>;
1101 /**
1102 * The owners' own caps on agents: one run's spend ($0.10 to $100) and one issue's ($1 to $1,000).
1103 * Null goes back to the default ($2 and $10). A cap staff set wins. Owners only.
1104 */
1105 setCaps(actor: User, workspace: string, caps: { runCapMicros: number | null; issueCapMicros: number | null }): Promise<Result<Entitlements>>;
1106 /** An owner's answer to a spend spike: keep going for 24 hours, or stop. */
1107 confirmSpike(actor: User, workspace: string, keepGoing: boolean): Promise<Result<Entitlements>>;
1108 /** Every metered price and the recent changes. Public. */
1109 prices(): Promise<PriceBook>;
1110 /** A workspace's limit, for its members. */
1111 limit(workspace: string, viewer: Viewer): Promise<Result<Limit>>;
1112 /** The same, for the services that enforce it. */
1113 checkLimit(workspace: string): Promise<Result<Limit>>;
1114 /**
1115 * The owners' own monthly limit, up to what is available; null goes back
1116 * to the default, and `useFullLimit` uses everything available. Owners only.
1117 */
1118 setSpendLimit(
1119 actor: User,
1120 workspace: string,
1121 spendLimitMicros: number | null,
1122 useFullLimit?: boolean,
1123 /** Use the one-time raise: up to twice the highest ceiling, once per workspace. */
1124 raiseOnce?: boolean,
1125 ): Promise<Result<Limit>>;
1126 /** The workspace's invoices from g1t, newest first. Members only. */
1127 invoices(workspace: string, viewer: Viewer): Promise<Result<WorkspaceInvoice[]>>;
1128 /**
1129 * How long a sandbox ran for a workspace, reported when it stops. Its
1130 * cost is recorded and every second is charged, from the first. False if
1131 * `reference` was recorded before.
1132 */
1133 recordSandbox(usage: {
1134 workspace: string;
1135 seconds: number;
1136 description: string;
1137 repo?: string | null;
1138 reference: string;
1139 /** What ran; checks, workflows and the merge queue on public repositories may use the open-source pool. */
1140 kind?: ComputeKind | null;
1141 /** vCPU-seconds used, when the sandbox can tell: the run is priced on its own CPU. */
1142 cpuSeconds?: number | null;
1143 /** The reservation it started under, settled with this cost. */
1144 reservationId?: string | null;
1145 /** It ran on one of the workspace's self-hosted runners: its minutes go on usage at $0. */
1146 selfHosted?: boolean;
1147 /** The machine it ran on, by label (`g1t-4core`); absent, the standard one. */
1148 instance?: string | null;
Spend adds up on one ledger. Charged this month has one definition, price less discount, included usage and credit, shared by the plan card, the spend limit, Spend and the top bar; the limit had counted usage not yet closed at full price before the discount, so a comped workspace read as charged a cent. Every agent line on the ledger names the agent and who asked, repository runs by g1t included, so Spent is the sum of its products, Agents is the agent product, and by agent adds up to it; the billing API returns by_agent and by_person. The usage and billing guide says how spend is counted.1149 /** The agent whose work this was, by handle (`g1t` for g1t's own runs on a repository); absent for checks, workflows and builds. */
1150 agent?: string | null;
1151 /** Who asked for the work, by username. */
1152 askedBy?: string | null;
What g1t can't do yet, and an open letter to Cloudflare1153 }): Promise<Result<boolean>>;
1154 startRun(run: {
1155 workspace: string;
1156 repo: RepoPath;
1157 number: number;
1158 task: string;
1159 model: string;
1160 /** `workspace` when the run uses the workspace's own model provider. */
1161 billedTo?: "g1t" | "workspace";
Merge branch 'model-routing'1162 /**
1163 * The model session's id: the run is settled at AI Gateway's price by
1164 * it, and on the workspace's own provider its tokens are counted under
1165 * it for the agent rate.
1166 */
What g1t can't do yet, and an open letter to Cloudflare1167 session?: string | null;
Merge branch 'model-routing'1168 /** The tier g1t routed the run to: `small`, `large` or `frontier`. */
1169 tier?: "small" | "large" | "frontier" | null;
Spend adds up on one ledger. Charged this month has one definition, price less discount, included usage and credit, shared by the plan card, the spend limit, Spend and the top bar; the limit had counted usage not yet closed at full price before the discount, so a comped workspace read as charged a cent. Every agent line on the ledger names the agent and who asked, repository runs by g1t included, so Spent is the sum of its products, Agents is the agent product, and by agent adds up to it; the billing API returns by_agent and by_person. The usage and billing guide says how spend is counted.1170 /** The agent doing the work, by handle: a workspace agent's, or `g1t` for g1t's own work on a repository. Every line of the run carries it. */
1171 agent?: string | null;
1172 /** Who asked, by username; none for a routine's or another agent's work. */
1173 askedBy?: string | null;
What g1t can't do yet, and an open letter to Cloudflare1174 }): Promise<Result<RunTicket | null>>;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1175 /** Usage over a range of days (`YYYY-MM-DD`, both included), at price, by product, meter, project and day. Members only. */
1176 usageReport(
1177 workspace: string,
1178 viewer: Viewer,
1179 range: { from: string; until: string; products?: string[]; projects?: string[] },
1180 ): Promise<Result<UsageReport>>;
1181 /** The workspace's prepaid AI credit, auto-reload and prices. Members only. */
1182 aiCredit(workspace: string, viewer: Viewer): Promise<Result<AiCredit>>;
1183 /** Stripe's page to buy AI credit ( to ,000, the card fee on its own line). Owners only. The page's id comes back to `returnUrl` as `ai_credit`. */
1184 buyAiCredit(actor: User, workspace: string, amountCents: number, returnUrl: string): Promise<Result<{ url: string }>>;
1185 /** Credits a purchase once Stripe says it was paid, once. Safe to repeat. */
1186 confirmAiCredit(workspace: string, viewer: Viewer, session: string): Promise<Result<AiCredit>>;
1187 /** Auto-reload's settings. Owners only. */
1188 setAiReload(
1189 actor: User,
1190 workspace: string,
1191 reload: { enabled: boolean; thresholdMicros: number; targetMicros: number; monthlyMaxMicros: number },
1192 ): Promise<Result<AiCredit>>;
1193 /** The monthly budget: the spend limit, its alerts, whether usage pauses at 100%, and a webhook. Owners only. */
1194 setBudget(
1195 actor: User,
1196 workspace: string,
1197 budget: { amountMicros: number | null; alerts: number[]; pauseAtLimit: boolean; webhook: string | null; keepLimit?: boolean },
1198 ): Promise<Result<Limit>>;
1199 /** Invoice details from the Stripe customer, the default payment method, invoices and the next invoice. Members only. */
1200 billingDetails(workspace: string, viewer: Viewer): Promise<Result<BillingDetails>>;
1201 /** Saves invoice details on the Stripe customer; absent fields stay, empty clears. Owners only. */
1202 setBillingDetails(actor: User, workspace: string, details: BillingDetailsInput): Promise<Result<BillingDetails>>;
What g1t can't do yet, and an open letter to Cloudflare1203}
1204
1205
1206/** One slice of usage: what it was for, what it cost, how many runs. */
1207export type UsageSlice = { key: string; micros: number; runs: number };
1208
Mission control shows model usage, yours and the workspace's: tokens, cost, active days, cache share, each day, and the mix1209/** The model tokens runs used over a window of days. */
1210export type TokenUsage = {
1211 /** `YYYY-MM-DD`, the first day counted. */
1212 since: string;
1213 /** The window's length: 42 unless asked, 366 at most. */
1214 days: number;
1215 /** Null for the whole workspace. */
1216 person: string | null;
1217 totalTokens: number;
1218 inputTokens: number;
1219 outputTokens: number;
1220 cacheReadTokens: number;
1221 cacheWriteTokens: number;
1222 /** What those runs were charged, as `usage` measures it. */
1223 costMicros: number;
1224 /** Days in the window with any tokens. */
1225 activeDays: number;
1226 /** Every day in the window, oldest first, zeros included. */
1227 byDay: { day: string; tokens: number }[];
1228};
1229
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1230// --- AI Gateway -------------------------------------------------------------
1231
1232/** A model the AI Gateway offers on g1t's key, with its prices per million tokens. */
1233export type GatewayModel = {
AI Gateway: OpenAI's format, open models, and your own providers1234 /**
1235 * The provider's own id, such as `claude-sonnet-5-5` or
1236 * `@cf/openai/gpt-oss-120b`. A request names it as it is or with its
1237 * provider in front (`anthropic/claude-sonnet-5-5`).
1238 */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1239 model: string;
1240 /** For people: `Claude Sonnet 5.5`. */
1241 name: string;
AI Gateway: OpenAI's format, open models, and your own providers1242 /** `anthropic` or `workers-ai`. */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1243 provider: string;
AI Gateway: OpenAI's format, open models, and your own providers1244 /** `chat`, or `embeddings` for a model that only embeds text. */
1245 kind?: "chat" | "embeddings";
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1246 inputMicros: number;
1247 outputMicros: number;
1248 cacheReadMicros: number;
AI Gateway: OpenAI's format, open models, and your own providers1249 /** Cache writes that live five minutes. */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1250 cacheWriteMicros: number;
AI Gateway: OpenAI's format, open models, and your own providers1251 /** Cache writes that live an hour. */
1252 cacheWrite1hMicros?: number;
1253 /**
1254 * Priced by the prompt's length: a request whose prompt (input, cache
1255 * read and cache write tokens) is longer than this is charged entirely at
1256 * the `over` prices. 0 or absent for one price.
1257 */
1258 threshold?: number;
1259 overInputMicros?: number;
1260 overOutputMicros?: number;
1261 overCacheReadMicros?: number;
1262 overCacheWriteMicros?: number;
1263 overCacheWrite1hMicros?: number;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1264};
1265
Merge branch 'main' into actions-toolkit-oidc-artifacts1266// --- The model catalogue ------------------------------------------------------
1267
1268/** Where a model stands: only `available` ones are routed to. */
1269export type ModelStatus = "available" | "new" | "deprecated" | "retired";
1270
1271/** One model in g1t's catalogue: its prices and what g1t knows about it. */
1272export type CatalogueModel = GatewayModel & {
1273 /** Other ids the provider lists it by, such as a dated one. */
1274 aliases: string[];
1275 family: string;
1276 /** The agent tier it suits: `small`, `large`, `frontier`, or empty. */
1277 tierHint: string;
1278 contextWindow: number;
1279 maxOutput: number;
1280 /** Any of `effort`, `thinking`, `tools`, `vision`, `embeddings`. */
1281 capabilities: string[];
1282 dimensions: number;
1283 status: ModelStatus;
1284 /** Its prices are known. An unpriced model is never routed to, offered or charged for. */
1285 priced: boolean;
1286 source: "discovered" | "staff";
1287 firstSeenAt: string | null;
1288 lastSeenAt: string | null;
1289 missingSince: string | null;
1290 approvedBy: string | null;
1291 approvedAt: string | null;
1292 note: string;
1293 /** A typical agent run on it, in millionths of a dollar; 0 when unpriced or embeddings. */
1294 typicalRunMicros: number;
1295};
1296
1297/** One model as its provider lists it, from the models service's discovery. */
1298export type ProviderModel = {
1299 id: string;
1300 name: string;
1301 /** `chat`, `embeddings`, or anything else (counted as listed, never added). */
1302 kind: string;
1303 contextWindow: number;
1304 maxOutput: number;
1305 capabilities: string[];
1306 /** Workers AI lists a price per million tokens; Anthropic does not. */
1307 price: { inputMicros: number; outputMicros: number } | null;
1308};
1309
1310/** What one check of a provider found. */
1311export type DiscoveryResult = {
1312 provider: string;
1313 checkedAt: string;
1314 by: string;
1315 listed: number;
1316 added: string[];
1317 deprecated: string[];
1318 restored: string[];
1319 error: string | null;
1320};
1321
1322/** The purposes a default model is chosen for. */
1323export type ModelPurpose = "tier_small" | "tier_large" | "tier_frontier" | "background" | "gateway_first";
1324
1325/** One purpose's default, as staff last set it. */
1326export type ModelDefault = {
1327 /** A `ModelPurpose`, or `job_<kind>`. */
1328 purpose: string;
1329 model: string | null;
1330 /** For a job: `small`, `large`, `frontier` or `change`. */
1331 tier: string | null;
1332 effort: string | null;
1333 updatedAt: string;
1334 updatedBy: string;
1335 reason: string;
1336};
1337
1338/** A model purpose's default as it applies now. */
1339export type ResolvedModel = {
1340 purpose: string;
1341 chosen: string;
1342 /** The model to use; null when nothing suits (callers keep their own fallback). */
1343 model: GatewayModel | null;
1344 capabilities: string[];
1345 /** Why it is not the chosen model, in a sentence. */
1346 note: string | null;
1347};
1348
1349/** One kind of agent job's starting tier and effort. */
1350export type JobDefault = { kind: string; tier: string; effort: string | null };
1351
1352/** Every purpose's model as it applies now, and each job's tier and effort. */
1353export type ModelDefaults = { models: ResolvedModel[]; jobs: JobDefault[] };
1354
1355/** One check of one provider. */
1356export type ModelCheck = {
1357 id: string;
1358 provider: string;
1359 checkedAt: string;
1360 by: string;
1361 listed: number;
1362 added: string[];
1363 deprecated: string[];
1364 error: string | null;
1365};
1366
1367/** The tokens of the typical agent run estimates are priced from. */
1368export type TypicalRun = { requests: number; input: number; output: number; cacheRead: number; cacheWrite: number };
1369
1370/** sudo's Agents & models. */
1371export type AdminModels = {
1372 catalogue: CatalogueModel[];
1373 defaults: ModelDefault[];
1374 resolved: ModelDefaults;
1375 checks: ModelCheck[];
1376 typical: TypicalRun;
1377};
1378
1379/** A model's prices as staff confirm them, per million tokens in millionths of a dollar. */
1380export type ModelPrices = {
1381 inputMicros: number;
1382 outputMicros: number;
1383 cacheReadMicros: number;
1384 cacheWriteMicros: number;
1385 cacheWrite1hMicros: number;
1386 threshold: number;
1387 overInputMicros: number;
1388 overOutputMicros: number;
1389 overCacheReadMicros: number;
1390 overCacheWriteMicros: number;
1391 overCacheWrite1hMicros: number;
1392};
1393
1394/** The models service's `Discovery` entrypoint, for sudo's "Check for new models". */
1395export interface ModelDiscoveryApi {
1396 /** Lists every provider's models now and records what changed: one result per provider. */
1397 check(by: string): Promise<DiscoveryResult[]>;
1398}
1399
AI Gateway: OpenAI's format, open models, and your own providers1400/** The format a gateway request was sent in. */
1401export type GatewayFormat = "anthropic" | "openai";
1402
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1403/** One AI Gateway request, as the model proxy reports it to billing. */
1404export type GatewayRecord = {
1405 /** `gw_…`, chosen by the proxy; recording it twice records it once. */
1406 id: string;
1407 workspace: string;
1408 tokenId: string;
1409 tokenName?: string | null;
1410 model: string;
1411 input: number;
1412 output: number;
1413 cacheRead: number;
AI Gateway: OpenAI's format, open models, and your own providers1414 /** Every cache write, of either lifetime. */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1415 cacheWrite: number;
AI Gateway: OpenAI's format, open models, and your own providers1416 /** Of `cacheWrite`, those that live an hour. */
1417 cacheWriteHour?: number;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1418 /** The HTTP status the caller was answered with. */
1419 status: number;
1420 /** On the workspace's own provider key: counted, never charged. */
1421 ownKey: boolean;
AI Gateway: OpenAI's format, open models, and your own providers1422 format: GatewayFormat;
1423 /**
1424 * Who served it: `anthropic` or `workers-ai` on g1t's key, the
1425 * connection's provider on the workspace's own. Empty when it never got
1426 * that far.
1427 */
1428 provider: string;
1429 /** On the workspace's own provider: the connection's name. */
1430 connection?: string | null;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1431 streamed: boolean;
1432 durationMs: number;
1433 error?: string | null;
1434};
1435
1436/** One AI Gateway request, as its log keeps it. */
1437export type GatewayRequest = {
1438 id: string;
1439 createdAt: string;
1440 model: string;
1441 tokenId: string;
1442 tokenName: string | null;
1443 input: number;
1444 output: number;
1445 cacheRead: number;
1446 cacheWrite: number;
AI Gateway: OpenAI's format, open models, and your own providers1447 /** Of `cacheWrite`, those that live an hour. */
1448 cacheWriteHour: number;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1449 /** What the tokens cost at the model's price. */
1450 costMicros: number;
1451 /** What the workspace was charged, before included usage and credit paid for it; 0 on its own key. */
1452 chargedMicros: number;
1453 status: number;
1454 ownKey: boolean;
AI Gateway: OpenAI's format, open models, and your own providers1455 format: GatewayFormat;
1456 /** `anthropic` or `workers-ai` on g1t's key; the connection's provider on the workspace's own. */
1457 provider: string;
1458 /** On the workspace's own provider: the connection's name. */
1459 connection: string | null;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1460 streamed: boolean;
1461 durationMs: number;
1462 error: string | null;
1463};
1464
1465/** A page of AI Gateway requests, newest first. */
1466export type GatewayRequests = {
1467 requests: GatewayRequest[];
1468 /** The `before` for the next page, when there is one. */
1469 next: string | null;
1470 /** How many days requests are kept. */
1471 retentionDays: number;
1472};
1473
What g1t can't do yet, and an open letter to Cloudflare1474/** What a workspace's agents cost over a period. */
1475export type Usage = {
1476 since: string;
1477 /** Charged, including g1t's margin. */
1478 spentMicros: number;
Billing and Usage reconcile: own-provider runs leave Billing's at-price total, and Usage's not-charged part is at price less charged1479 /** What g1t's usage came to at price, less what was charged: the plan's included usage, the trial, a pool or a free period paid it. Usage at price is `spentMicros` plus this. */
Billing's usage total is labeled at price, and Usage says what part of it was paid for1480 coveredMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1481 /** What the account's discount took off the price; usage at price is spent + covered + this. */
1482 discountMicros?: number;
1483 /** The account's discount now, in percent; with one, the slices are at price. */
1484 discountPercent?: number | null;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1485 /** Usage at price: spent + covered + discount, from the same ledger lines. The one usage figure every page shows. */
1486 priceMicros?: number;
What g1t can't do yet, and an open letter to Cloudflare1487 /** What g1t's model provider charged, before the margin. */
1488 costMicros: number;
1489 /** What runs on the workspace's own provider cost there, estimated. Not charged by g1t. */
1490 providerMicros: number;
1491 /** What the runs used, at cost: g1t's models and the workspace's own provider together. */
1492 usedMicros: number;
1493 /** g1t charges nothing for now; the slices then measure usage at cost. */
1494 free: boolean;
1495 runs: number;
1496 /** Spend per day and task, keyed `YYYY-MM-DD/task`. */
1497 byDay: UsageSlice[];
1498 byTask: UsageSlice[];
1499 byRepo: UsageSlice[];
1500 /** Keyed `namespace/name#number`. */
1501 byPull: UsageSlice[];
1502 byModel: UsageSlice[];
1503 /** Credit bought in the period. */
1504 addedMicros: number;
1505};
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1506
1507/** One of g1t's products (a "bucket") on one day. Money in micros. */
1508export type CostDay = { day: string; bucket: string; cfCostMicros: number; ownCostMicros: number; valueMicros: number; cashMicros: number };
1509
1510/** One product over the range: what customers were charged at price against what it cost. */
1511export type ProductMargin = {
1512 bucket: string;
1513 title: string;
1514 /** Cloudflare's bill, or g1t's own figure where Cloudflare does not bill it (`costSource`). */
1515 costMicros: number;
1516 cfCostMicros: number;
1517 ownCostMicros: number;
1518 valueMicros: number;
1519 marginMicros: number;
1520 marginPercent: number | null;
1521 costSource: "cloudflare" | "ledger" | string;
1522 /** Running g1t, paid for by the plan. */
1523 overhead: boolean;
1524};
1525
1526/** All of g1t: money in (usage and the plan) against every cost. */
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1527export type OverallMargin = {
1528 usageMicros: number;
1529 plansMicros: number;
1530 costMicros: number;
1531 marginMicros: number;
1532 marginPercent: number | null;
1533 /** Of costMicros, what went on usage g1t gave away on purpose: comped workspaces, free periods, the trial and the open-source pool. */
1534 givenMicros?: number;
1535 /** Money in against costMicros - givenMicros. */
1536 soldMarginMicros?: number;
1537 soldMarginPercent?: number | null;
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1538 /** Usage sold: usageMicros against what that usage cost, less what was given. */
1539 usageCostMicros?: number;
1540 usageMarginMicros?: number;
1541 usageMarginPercent?: number | null;
1542 /** Running g1t: plansMicros against the platform's cost, less its given share. */
1543 runningCostMicros?: number;
1544 /** Cost no mapping names, less its given share. */
1545 unmappedCostMicros?: number;
1546 /** givenMicros by why. Free is free periods, free allowances and overruns g1t covered. */
1547 givenCompedMicros?: number;
1548 givenFreeMicros?: number;
1549 givenTrialMicros?: number;
1550 givenPoolMicros?: number;
Merge branch 'worktree-agent-a633ac0f7f66d419d'1551 /** What discounts on an account's terms took below cost plus the margin: given, not margin lost. */
1552 givenDiscountMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1553 /** Credits from g1t spent on usage, by kind: given, never money in. Refunds come off money in instead. */
1554 givenCreditPromotionalMicros?: number;
1555 givenCreditGoodwillMicros?: number;
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb971556 /** What testing resets wiped that g1t paid for: the usage still happened, so its cost is given, never a leak. */
1557 givenResetMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1558 /** Credits over the range: given (every kind), spent on usage, and refunds' money given back. */
1559 creditsGivenMicros?: number;
1560 creditsUsedMicros?: number;
1561 creditsRefundedMicros?: number;
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1562 /** costMicros by who g1t pays: Cloudflare's bill (billed, after included allowances) and model providers (tokens, not on Cloudflare's bill). */
Costs: the plan's included usage counts as paid for the usage it covered, out of what plans leave for running g1t; the run button shows it is running with CSS alone (sudo ships no JavaScript)1563 /** What the plan's included usage paid for, at price: money in for usage, paid out of plansMicros. */
1564 includedMicros?: number;
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1565 cloudflareCostMicros?: number;
1566 modelsCostMicros?: number;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person1567 /** Tax collected with payments over the range, net of refunds: owed to tax authorities, never cash or revenue. */
1568 taxCollectedMicros?: number;
1569 /** Card processing fees passed on with card payments, net of refunds: they pay Stripe's fee, not revenue. */
1570 cardFeesMicros?: number;
Merge Cloudflare's usage over its billing cycle: every page read, included amounts once a cycle, a projection, test-mode charges never money in (billing 0052)1571 /** What workspaces were charged while payments were not live (Stripe's test mode): given, never money in. */
1572 givenUnpaidMicros?: number;
1573 /** Cloudflare's subscriptions over the range: each day's share of the billing cycle it is in. */
1574 subscriptionsMicros?: number;
1575 /** What AI Gateway priced g1t's own provider traffic at over the range, beside the ledger's model cost. */
1576 gatewayCostMicros?: number;
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1577};
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1578
1579/** A count, cost or leak that does not add up. */
1580export type CostDrift = {
1581 bucket: string;
1582 title: string;
1583 kind: "count" | "cost" | "leak" | string;
1584 ours: number;
1585 cloudflare: number;
1586 deltaPercent: number | null;
1587 detail: string;
1588 foundAt: string;
1589};
1590
1591export type MarginAlert = {
1592 id: string;
1593 kind: "margin" | "overall" | "leak" | "drift" | "workspace" | string;
1594 /** The product, or the workspace. */
1595 subject: string;
1596 detail: string;
1597 since: string;
1598 openedAt: string;
1599 emailedAt: string | null;
1600};
1601
1602/** A change to a price, measured from what Cloudflare charged. */
1603export type PriceProposal = {
1604 id: string;
1605 meter: string;
1606 title: string;
1607 unit: string;
1608 currentCostMicros: number;
1609 proposedCostMicros: number;
1610 changePercent: number;
1611 markupPercent: number;
1612 reason: string;
1613 source: "keeper" | "reconciler" | string;
1614 /** Far off the current cost: look before approving. */
1615 suspect: boolean;
1616 status: "open" | "applied" | "approved" | "rejected" | "superseded" | string;
1617 createdAt: string;
1618 decidedAt: string | null;
1619 decidedBy: string | null;
1620 note: string | null;
1621 effectiveAt: string | null;
1622};
1623
1624/** One version of one meter's price; never changed once written. */
1625export type PriceVersion = {
1626 id: string;
1627 meter: string;
1628 version: number;
1629 costMicros: number;
1630 markupPercent: number;
1631 priceMicros: number;
1632 effectiveAt: string;
1633 reason: string;
1634 createdBy: string;
1635 appliedAt: string | null;
Merge costs and margin review: gateway query, own spend, discount meters, superseded rises1636 /**
1637 * What `costMicros` is: `cost`, what g1t pays for a unit; `rate`, a price
1638 * g1t sets with no cost behind it (the agent rate), so it is no cost;
1639 * `weight`, a multiplier in millionths, not money. Absent from older
1640 * billing: read as `cost`.
1641 */
1642 basis?: "cost" | "rate" | "weight" | "";
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1643};
1644
sudo: reset a test workspace's billing so it starts again as a new customer; refused on a live Stripe key, for comped workspaces and for an enterprise's1645/** What `resetBilling` removed. */
sudo: a billing reset runs the costs analysis again so every figure is fresh; every submit button shows it is working (CSS only); no margin percentage on less than a cent sold1646export type BillingReset = { workspace: string; rows: number; refreshed?: boolean };
sudo: reset a test workspace's billing so it starts again as a new customer; refused on a live Stripe key, for comped workspaces and for an enterprise's1647
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1648export type WorkspaceCost = { workspace: string; costMicros: number; revenueMicros: number; givenMicros?: number; internal: boolean };
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1649
1650export type CostLineSummary = {
1651 product: string;
1652 meter: string;
1653 rawName: string;
1654 unit: string;
1655 source: string;
1656 quantity: number;
1657 costMicros: number;
1658 /** Absent when no mapping claims it. */
1659 bucket: string | null;
1660};
1661
1662export type CostMapping = {
1663 product: string;
1664 meter: string;
1665 bucket: string;
1666 priceMeter: string | null;
1667 ownMeter: string | null;
1668 scaleToOwn: boolean;
1669 driftPercent: number;
1670 note: string;
1671 updatedAt: string;
1672 updatedBy: string;
1673};
1674
1675export type CostMappingInput = {
1676 product: string;
1677 meter: string;
1678 bucket?: string;
1679 priceMeter?: string | null;
1680 ownMeter?: string | null;
1681 scaleToOwn?: boolean;
1682 driftPercent?: number | null;
1683 note?: string;
1684 remove?: boolean;
1685};
1686
1687export type CostSettings = {
1688 autoApply: boolean;
1689 autoApplyPercent: number;
1690 noticeDays: number;
1691 marginFloorPercent: number;
1692 alertDays: number;
1693 minDailyCostMicros: number;
1694 anomalyFactor: number;
1695 anomalyFloorMicros: number;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1696 /** Pass Stripe's card fee on as its own line when AI credit is bought by card. */
1697 cardFee: boolean;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1698};
1699
1700export type CostsReport = {
1701 configured: boolean;
1702 fetchedAt: string | null;
1703 since: string;
1704 until: string;
1705 days: CostDay[];
1706 products: ProductMargin[];
1707 overall: OverallMargin;
1708 drift: CostDrift[];
1709 alerts: MarginAlert[];
1710 proposals: PriceProposal[];
1711 versions: PriceVersion[];
1712 topWorkspaces: WorkspaceCost[];
1713 lines: CostLineSummary[];
1714 mappings: CostMapping[];
1715 settings: CostSettings;
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1716 /** g1t's own spend against its two caps. */
1717 caps: SpendCaps;
Merge Cloudflare's usage over its billing cycle: every page read, included amounts once a cycle, a projection, test-mode charges never money in (billing 0052)1718 /** Cloudflare's current billing cycle: usage cost so far by meter, and the projection. Absent until the bill is read. */
1719 cycle?: CloudflareCycle | null;
1720 /** The last read of Cloudflare's billable usage: what came back. */
1721 billRead?: BillRead | null;
1722 /** Of the range's cost, what no workspace's usage could carry: running g1t, attributed to no one. */
1723 unattributedMicros?: number;
1724};
1725
1726/** Cloudflare's billing cycle, as its Billable usage page shows it. */
1727export type CloudflareCycle = {
1728 /** First and last days, YYYY-MM-DD, UTC. */
1729 start: string;
1730 end: string;
1731 days: number;
1732 /** Days from its start to today, today included. */
1733 daysElapsed: number;
1734 /** Usage cost so far, after the included allowances. */
1735 usageMicros: number;
1736 /** usageMicros over the days elapsed, times the cycle's days. */
1737 projectedMicros: number;
1738 averageDailyMicros: number;
1739 /** Cloudflare's subscriptions for the cycle (not on the usage bill). */
1740 subscriptionsMicros: number;
1741 meters: CycleMeter[];
1742};
1743
1744/** One of Cloudflare's meters over the cycle so far. */
1745export type CycleMeter = {
1746 product: string;
1747 meter: string;
1748 rawName: string;
1749 unit: string;
1750 quantity: number;
1751 /** What the cycle includes; null without a list price. */
1752 included: number | null;
1753 billableQuantity: number;
1754 costMicros: number;
1755 /** cloudflare: Cloudflare's own cost; list: the list price past the included amount; none: no list price known. */
1756 basis: "cloudflare" | "list" | "none" | string;
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1757};
1758
Merge Cloudflare's usage over its billing cycle: every page read, included amounts once a cycle, a projection, test-mode charges never money in (billing 0052)1759/** What the last read of Cloudflare's billable usage got back. */
1760export type BillRead = {
1761 readAt: string;
1762 since: string;
1763 until: string;
1764 rows: number;
1765 pages: number;
1766 consumedRows: number;
1767 pricingOnlyRows: number;
1768 costedRows: number;
1769};
1770
Merge platform pause and the hourly usage watcher: staff can pause compute, schedules, indexing or renders for everyone, the watcher emails on a breach and is never blind quietly, and the models proxy holds each run to its cap (billing 0051, integrations 0006)1771/** One level of the platform pause, as sudo shows it. Snake case, as billing sends it. */
1772export type PauseState = {
1773 level: PauseLevel;
1774 paused: boolean;
1775 note: string | null;
1776 set_by: string | null;
1777 set_at: string | null;
1778 /** Set by billing's usage watcher, not a person. */
1779 auto: boolean;
1780};
1781
1782/** One platform metric over an hour or the month so far. */
1783export type PlatformMetric = {
1784 metric: string;
1785 title: string;
1786 value: number;
1787 /** Its hourly threshold (`PLATFORM_HOURLY_*`); 0: none. */
1788 threshold: number;
1789 /** The script, queue, database or namespace that counted most. */
1790 top_name: string | null;
1791 top_value: number | null;
1792};
1793
1794/** A breach billing's usage watcher found. */
1795export type PlatformBreach = {
1796 id: string;
1797 metric: string;
1798 hour: string;
1799 rule: "threshold" | "spike";
1800 value: number;
1801 threshold: number;
1802 severe: boolean;
1803 top_name: string | null;
1804 detail: string;
1805 /** Levels it paused. */
1806 paused: PauseLevel[];
1807 opened_at: string;
1808 emailed_at: string | null;
1809};
1810
The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were.1811/** Billing's `admin_platform_guard`: the platform pause and usage watcher
1812 * (docs.g1t.sh/guides/deploy-to-cloudflare/#spend-guardrails). */
Merge platform pause and the hourly usage watcher: staff can pause compute, schedules, indexing or renders for everyone, the watcher emails on a breach and is never blind quietly, and the models proxy holds each run to its cap (billing 0051, integrations 0006)1813export type PlatformGuard = {
1814 levels: PauseState[];
1815 /** The last hour read, `YYYY-MM-DDTHH:00:00Z`. */
1816 hour: string | null;
1817 last_hour: PlatformMetric[];
1818 month: string;
1819 month_to_date: PlatformMetric[];
1820 breaches: PlatformBreach[];
1821 /** Whether billing can read Cloudflare's analytics. */
1822 can_read: boolean;
1823 /** `AUTO_PAUSE`: the levels a severe breach may pause. */
1824 auto_pause: PauseLevel[];
1825 /** What the latest run could not see: each query that failed, with its error. */
1826 blind?: { key: string; dataset: string; error: string }[];
1827 /** The latest run found every dataset empty: the wrong account, or a token that cannot see it. */
1828 empty?: boolean;
1829 /** The hour the latest run read. */
1830 last_run?: string | null;
1831};
1832
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1833/** What g1t pays for itself, at cost, against its caps (billing's `budget`). */
1834export type SpendCaps = {
1835 /** Today (UTC), YYYY-MM-DD, and this month, YYYY-MM. */
1836 day: string;
1837 month: string;
1838 /** What g1t paid for itself today across every workspace. */
1839 todayMicros: number;
1840 /** `PLATFORM_DAILY_SPEND_CAP_MICROS`; 0: no breaker. */
1841 dailyCapMicros: number;
1842 /** New hosted-model agent runs g1t would pay for are paused. */
1843 tripped: boolean;
1844 trippedAt: string | null;
1845 liftedBy: string | null;
1846 liftedAt: string | null;
1847 liftNote: string | null;
1848 /** This month so far, by what paid: comped, trial, oss, given, unpaid. */
1849 monthBuckets: { bucket: string; title: string; micros: number }[];
1850 comped: CompedBudget[];
1851 /** Free workspaces' share of reconciled costs this month (git, storage, platform). */
1852 freeTierMicros: number;
Costs: Cloudflare's subscriptions read from Cloudflare each day, the estimate only until then; sudo's costs split into Costs & margin and Bill & pricing1853 /** Cloudflare's subscriptions a month: read from Cloudflare each day, else `CLOUDFLARE_FIXED_MONTHLY_MICROS`, an estimate. */
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1854 fixedMonthlyMicros: number;
Costs: Cloudflare's subscriptions read from Cloudflare each day, the estimate only until then; sudo's costs split into Costs & margin and Bill & pricing1855 fixedSource?: "cloudflare" | "estimate" | string;
1856 fixedReadAt?: string | null;
1857 /** Each subscription, when read from Cloudflare. */
1858 fixedItems?: { name: string; monthlyMicros: number }[];
Merge Cloudflare's usage over its billing cycle: every page read, included amounts once a cycle, a projection, test-mode charges never money in (billing 0052)1859 /** Of fixedMonthlyMicros, this calendar month's days so far, each at its billing cycle's daily share. */
1860 fixedMonthMicros?: number;
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1861 /** Money in this month, through the last reconciled day. */
1862 revenueMicros: number;
Merge costs and margin review: gateway query, own spend, discount meters, superseded rises1863 /**
1864 * Of this month's buckets, what was spent on workspaces whose billing a
1865 * testing reset later wiped (still g1t's spend; the reconciled figures
1866 * have it only where the reset kept it), and those workspaces.
1867 */
1868 resetMicros?: number;
1869 resetWorkspaces?: string[];
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1870};
1871
1872/** A comped account's monthly budget, at cost. */
1873export type CompedBudget = {
1874 account: string;
1875 name: string;
1876 usedMicros: number;
1877 /** 0: no budget. */
1878 ceilingMicros: number;
1879 /** `COMPED_MONTHLY_CEILING_MICROS`, not the account's own limit. */
1880 defaultCeiling: boolean;
1881 /** 50, 75, 90, 100, or 0. */
1882 level: number;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1883};
1884
1885export type CostsRun = { lines: number; days: number; proposals: number; alerts: number; problems: string[] };
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1886
1887/** The product families the Usage page groups meters into, in order. */
1888export const PRODUCTS = [
1889 { key: "agent", label: "Agent" },
1890 { key: "sandboxes", label: "Sandboxes" },
1891 { key: "gateway", label: "AI Gateway" },
1892 { key: "deployments", label: "Deployments" },
1893 { key: "git_storage", label: "Git & storage" },
1894 { key: "packages", label: "Packages" },
1895 { key: "security", label: "Security & quality" },
1896 { key: "search", label: "Search" },
1897] as const;
1898
1899export type ProductKey = (typeof PRODUCTS)[number]["key"];
1900
1901/** What usage came to over a range, and what paid for it: price − discount − included − credits = charged. */
1902export type UsageTotals = {
1903 /** Usage at price, pending usage included. */
1904 priceMicros: number;
1905 discountMicros: number;
1906 /** Paid by the plan's included usage, the trial and g1t's pools. */
1907 includedMicros: number;
1908 /** Paid by AI credit and credit from g1t. */
1909 creditsMicros: number;
1910 /** Left for the workspace to pay. */
1911 chargedMicros: number;
1912 /** Metered this month, charged when it closes. */
1913 pendingMicros: number;
Money is written one way. A single formatter turns millionths of a dollar into dollars, rounding half up on whole micros rather than on a float, so the same sum reads the same on every page: under a cent reads <$0.01 on a total and exactly nothing is $0.00, while the statement's lines, a session's receipt, the price book and an agent's effort costs carry up to four places where the fraction of a cent is the point; the six formatters that each rounded their own way are gone. This month is the calendar month in UTC from its first day to today everywhere, and billing counts the month's not-yet-closed usage in any range that reaches into the current month, so the top bar's pill, Spend, Home and Usage ask for the same days and get the same figure; Home now reads the usage report the others read instead of adding up statements. Usage's pending sentence says what of that usage the close will charge after the discount and included usage, which the billing API returns as pending_charged_micros. A reconciliation test holds the pill, Spend, Home and Usage to one number for one month. The usage and billing guide says how amounts are written and what this month means.1914 /** What of `pendingMicros` will be charged at the close, after the discount and what g1t covers; absent from an older billing. */
1915 pendingChargedMicros?: number;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1916 costMicros: number;
1917};
1918
1919export type UsageDay = { day: string; product: string; micros: number };
1920
Spend adds up on one ledger. Charged this month has one definition, price less discount, included usage and credit, shared by the plan card, the spend limit, Spend and the top bar; the limit had counted usage not yet closed at full price before the discount, so a comped workspace read as charged a cent. Every agent line on the ledger names the agent and who asked, repository runs by g1t included, so Spent is the sum of its products, Agents is the agent product, and by agent adds up to it; the billing API returns by_agent and by_person. The usage and billing guide says how spend is counted.1921/** One agent's (by handle) or one person's (by username) share of the agent product, at price; an empty key for lines attributed to no one. */
1922export type UsageShare = { key: string; label: string; micros: number; count: number };
1923
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1924export type UsageAllowance = { used: number; of: number; unit: string };
1925
1926export type ProjectUsage = { project: string; micros: number; quantity: number };
1927
1928/** One meter over a range. */
1929export type MeterLine = {
1930 key: string;
1931 label: string;
1932 product: string;
1933 /** `tokens`, `seconds`, `bytes`, `operations`, `requests` or `entries`. */
1934 unit: string;
1935 quantity: number;
1936 micros: number;
1937 pendingMicros?: number;
1938 /** Every day of the range, oldest first, at price. */
1939 daily: number[];
1940 allowance?: UsageAllowance | null;
1941 byProject: ProjectUsage[];
Merge branch 'model-routing'1942 /** How the quantity is counted, when that needs saying (the agent rate's token weights). */
1943 note?: string | null;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1944};
1945
1946export type FeatureUsage = { key: string; label: string; micros: number; count: number };
1947
1948export type ProductUsage = { key: string; label: string; micros: number; meters: MeterLine[]; features?: FeatureUsage[] };
1949
Merge branch 'model-routing'1950/** The tokens one model used over a range, as the model proxy counted them. */
1951export type ModelTokens = { model: string; input: number; output: number; cacheRead: number; cacheWrite: number };
1952
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1953export type UsageReport = {
1954 from: string;
1955 until: string;
1956 totals: UsageTotals;
1957 days: UsageDay[];
1958 products: ProductUsage[];
1959 projects: string[];
Merge branch 'model-routing'1960 /** Agent tokens by model over the range, most first. */
1961 models?: ModelTokens[];
Spend adds up on one ledger. Charged this month has one definition, price less discount, included usage and credit, shared by the plan card, the spend limit, Spend and the top bar; the limit had counted usage not yet closed at full price before the discount, so a comped workspace read as charged a cent. Every agent line on the ledger names the agent and who asked, repository runs by g1t included, so Spent is the sum of its products, Agents is the agent product, and by agent adds up to it; the billing API returns by_agent and by_person. The usage and billing guide says how spend is counted.1962 /** The agent product by the agent that did the work, most first; their sum is the agent product's total. */
1963 byAgent?: UsageShare[];
1964 /** The agent product by who asked; work no person asked for under an empty key. */
1965 byPerson?: UsageShare[];
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1966 /** The plan's included usage this month, in micros. */
1967 included?: UsageAllowance | null;
1968 discountPercent?: number | null;
1969 aiCreditMicros: number;
1970 creditMicros: number;
1971 trialMicros?: number | null;
1972 plan: PlanKind;
1973 free: boolean;
1974};
1975
1976export type AiReload = {
1977 enabled: boolean;
1978 thresholdMicros: number;
1979 targetMicros: number;
1980 monthlyMaxMicros: number;
1981 reloadedMicros?: number;
1982 failedAt?: string | null;
1983 error?: string | null;
1984};
1985
1986export type CardFee = { on: boolean; percentMicros: number; fixedCents: number };
1987
1988/** Prepaid AI credit: what Agent and AI Gateway usage draws on. */
1989export type AiCredit = {
1990 balanceMicros: number;
1991 purchasedMicros: number;
1992 givenMicros: number;
1993 grants: CreditGrant[];
1994 /** A 100% discount pays for AI usage: nothing to buy. */
1995 freeViaDiscount: boolean;
1996 /** Invoiced after use (an enterprise). */
1997 postpaid: boolean;
1998 /** New runs on g1t's models are refused for want of credit. */
1999 blocked: boolean;
2000 canBuy: boolean;
2001 presetsCents: number[];
2002 minCents: number;
2003 maxCents: number;
2004 cardFee: CardFee;
2005 reload: AiReload;
2006 /** The agent rate per million tokens, at price. */
2007 agentRateMicros: number;
2008 modelMarkupPercent: number;
2009 gatewayMarkupPercent: number;
2010 upgradeCreditMicros: number;
2011 expiresDays: number;
2012};
2013
2014export type PostalAddress = { line1: string; line2: string; city: string; state: string; postalCode: string; country: string };
2015
2016export type PaymentMethod = {
2017 kind: string;
2018 brand?: string | null;
2019 last4?: string | null;
2020 expMonth?: number | null;
2021 expYear?: number | null;
2022};
2023
2024export type StripeInvoice = {
2025 id: string;
2026 number?: string | null;
2027 status: string;
2028 totalCents: number;
2029 currency: string;
2030 createdAt: string;
2031 description?: string | null;
2032 hostedUrl?: string | null;
2033 pdfUrl?: string | null;
2034};
2035
2036export type UpcomingInvoice = { closesAt: string; subscriptionsMicros: number; usageMicros: number; totalMicros: number };
2037
2038export type BillingDetails = {
2039 customer: boolean;
2040 email: string | null;
2041 name: string | null;
2042 address: PostalAddress | null;
2043 taxIdType: string | null;
2044 taxId: string | null;
2045 poNumber: string | null;
2046 language: string | null;
2047 paymentMethod: PaymentMethod | null;
2048 invoices: StripeInvoice[];
2049 upcoming: UpcomingInvoice;
2050 unavailable?: string | null;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person2051 /** Whether Stripe Tax can place the customer from the address; without it nothing is charged. */
2052 taxLocation?: boolean;
2053 /** Set when g1t did not charge for want of a billing address. */
2054 taxAddressNeededAt?: string | null;
2055 /** Stripe's check of the tax ID: pending, verified, unverified or unavailable. */
2056 taxIdStatus?: string | null;
2057 /** none, exempt or reverse, as set at Stripe. */
2058 taxExempt?: string | null;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit2059};
2060
2061export type BillingDetailsInput = {
2062 email?: string;
2063 name?: string;
2064 address?: PostalAddress;
2065 taxIdType?: string;
2066 taxId?: string;
2067 poNumber?: string;
2068 language?: string;
2069};

This file's history is long; its oldest lines are credited to the oldest commit read.