Skip to content
1,971 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.

Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1import 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";
Agents as a team: lifecycle, merge queue, billing and a new shell3import 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;
Free while g1t is being built out; agents can check out their own forks19 /**
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;
Agents as a team: lifecycle, merge queue, billing and a new shell24};
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;
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace37 /** 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;
Agents as a team: lifecycle, merge queue, billing and a new shell39};
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;
Integrations: your own model provider, alerts that open issues, tickets agents read56 /** For usage: who paid the model provider. */
57 billedTo: "g1t" | "workspace";
Agents as a team: lifecycle, merge queue, billing and a new shell58 /** For a top-up: the username of whoever paid. */
59 createdBy: string | null;
60 /** RFC 3339. */
61 createdAt: string;
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace62 /** The workspace the line belongs to, which tells an enterprise's lines apart. */
63 workspace?: string | null;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look64 /** For usage: what the plan's included usage paid of it. `amountMicros` is what is left to pay. */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put65 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;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look70 /** 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;
Agents as a team: lifecycle, merge queue, billing and a new shell76};
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
Agents as a team: lifecycle, merge queue, billing and a new shell142/** 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 */
A free allowance on g1t's models, so anyone can try its agents150/**
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 */
Billing accounts, terms and enterprises; g1t is no longer free161export 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[];
Stripe webhooks, enterprise invoices, and sudo for both181 /** Where an enterprise's invoices go. */
182 billingEmail?: string | null;
183 /** An enterprise's invoices, newest first. */
184 invoices?: EnterpriseInvoice[];
Billing accounts, terms and enterprises; g1t is no longer free185 createdAt: string;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put186 /** 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 = {
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look192 /** The g1t plan without its monthly price; usage is charged as usual. Comped accounts have it anyway. */
193 plan: boolean;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put194 /** 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;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look198 /** 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;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look206 /** A hold on new compute, with why; null for none. */
207 hold?: string | null;
Billing accounts, terms and enterprises; g1t is no longer free208};
209
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look210// --- 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`. */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put256export type Entitlements = {
257 workspace: string;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look258 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. */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put289 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;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas292 /** Private repository storage free for every workspace: past it, the plan pays and a free workspace's pushes stop. */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put293 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;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put301 /** What g1t's open-source pool paid for the workspace this month. */
302 ossPaidMicros: number;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas303 /** 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. */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look306 gitOperations?: number;
307 gitOperationsIncluded?: number;
308 /** The smallest amount a card is charged when a month closes. */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put309 minChargeMicros: number;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look310 /** 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;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put340};
341
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look342/** 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
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put399/** 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
Billing accounts, terms and enterprises; g1t is no longer free410export type AccountSummary = {
411 account: PayingAccount;
412 limit: Limit;
413 chargedMicros: number;
414 costMicros: number;
415 paidMicros: number;
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace416 /** The same figures for each of the account's workspaces that has any. */
417 byWorkspace: WorkspaceFigures[];
Two limits, real invoices, trust that grows by itself, sales signals418 /** The last six months, oldest first. */
419 months?: MonthFigures[];
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace420};
421
422/** One workspace's share of an `AccountSummary`. */
423export type WorkspaceFigures = { workspace: string; chargedMicros: number; costMicros: number; paidMicros: number };
424
Stripe webhooks, enterprise invoices, and sudo for both425export 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[];
Stripe webhooks, enterprise invoices, and sudo for both434 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
Two limits, real invoices, trust that grows by itself, sales signals449/** 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;
Two limits, real invoices, trust that grows by itself, sales signals464};
465
The statement is a month at a time, a line per kind of charge466/** 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;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look473 /** `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 }[];
The statement is a month at a time, a line per kind of charge486 chargedMicros: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging487 priceMicros?: number;
488 discountMicros?: number;
The statement is a month at a time, a line per kind of charge489 }[];
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put490 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;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put500 /** What paid for usage before it was charged, such as "Paid by g1t's open-source pool". */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look501 covered?: { source: "included" | "trial" | "oss_pool" | "given" | string; label: string; micros: number }[];
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put502 /** 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;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put507 };
The statement is a month at a time, a line per kind of charge508};
509
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look510export 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 };
Two limits, real invoices, trust that grows by itself, sales signals528
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";
Two limits, real invoices, trust that grows by itself, sales signals530
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;
Billing lists every invoice and every staff change; signals carry follow-ups539 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;
Two limits, real invoices, trust that grows by itself, sales signals557};
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;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put581 /** g1t's capped budgets for free usage, this month. */
582 pools?: Pools | null;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look583 /** 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;
Two limits, real invoices, trust that grows by itself, sales signals594};
595
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace596/** 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;
Billing accounts, terms and enterprises; g1t is no longer free604};
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>>;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put620 /** 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>>;
Billing accounts, terms and enterprises; g1t is no longer free622 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>>;
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace632 /** The workspace's Stripe billing page, to send to the customer. Logged. */
633 billingLink(workspace: string, by: string): Promise<Result<BillingLink>>;
Stripe webhooks, enterprise invoices, and sudo for both634 /** 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>;
Stripe webhooks, enterprise invoices, and sudo for both637 /** 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>>;
Stripe webhooks, enterprise invoices, and sudo for both641 /** 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[]>;
Two limits, real invoices, trust that grows by itself, sales signals645 /** 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[]>;
Billing lists every invoice and every staff change; signals carry follow-ups655 /** 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[]>;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look659 /** 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>>;
Billing accounts, terms and enterprises; g1t is no longer free706}
707
Usage limits: unpaid usage can only go so far708/** How much a workspace has earned g1t's trust with money. */
Two limits, real invoices, trust that grows by itself, sales signals709export type Trust = "new" | "paid" | "established" | "reviewed" | "internal";
Usage limits: unpaid usage can only go so far710
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;
Billing accounts, terms and enterprises; g1t is no longer free719 /** The account that pays: the workspace's own (`ws_<slug>`), or its enterprise's. */
720 account: string;
721 accountName: string;
Usage limits: unpaid usage can only go so far722 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;
Two limits, real invoices, trust that grows by itself, sales signals730 /** Charged this month: what the spend limit is measured against. */
731 spentMicros?: number;
732 /** True while the owners have not chosen a limit, so the automatic one applies: $200, or twice last month's spend. */
733 defaultSpendLimit?: boolean;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look734 /** The most owners may set their own limit to without asking: the highest ceiling ever, plus what is prepaid. */
Two limits, real invoices, trust that grows by itself, sales signals735 availableMicros?: number | null;
736 /** How the ceiling grows from here, in a sentence. */
737 growth?: string | null;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look738 /** Paid in advance and not used yet; raises what can be used before work stops by as much. */
739 prepaidMicros?: number;
740 /** The highest ceiling the workspace has had. */
741 maxCeilingMicros?: number | null;
742 /** The most owners may raise the limit to themselves, once: twice the highest ceiling. Null once used. */
743 raiseOnceMicros?: number | null;
744 /** When the one-time raise was used. */
745 raisedAt?: string | null;
746 /** A paid workspace's first billing cycle, on the starting ceiling. */
747 firstMonth?: boolean;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit748 /** The budget's alerts, in percent of the spend limit: some of 50, 75, 90 and 100. */
749 alertLevels?: number[];
750 /** Whether usage pauses at the spend limit (the default); off, it only alerts. */
751 pauseAtLimit?: boolean;
752 /** An HTTPS address told of each budget alert. */
753 budgetWebhook?: string | null;
Usage limits: unpaid usage can only go so far754};
755
Prices keep themselves current with what g1t pays756/** One metered unit: what it costs g1t and what it is sold at; the price follows the cost. */
757export type Price = {
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put758 meter:
759 | "sandbox_second"
760 | "build_second"
761 | "app_requests"
762 | "app_cpu"
763 | "app_month"
764 | "custom_domain_month"
765 | "private_storage"
766 | "embedding_tokens"
767 | "scan_cpu"
768 | "scan_rows"
769 | string;
Prices keep themselves current with what g1t pays770 title: string;
771 unit: string;
772 costMicros: number;
773 markupPercent: number;
774 priceMicros: number;
775 /** `list`: Cloudflare's published price. `cloudflare`: measured from Cloudflare's bill. */
776 source: "list" | "cloudflare" | string;
777 checkedAt: string | null;
778 updatedAt: string;
779};
780
781export type PriceChange = {
782 meter: string;
783 oldCostMicros: number;
784 newCostMicros: number;
785 markupPercent: number;
Prices are what g1t pays plus 20%, from the first second786 /** The markup before, when the change was to the markup rather than the cost. */
787 oldMarkupPercent?: number;
Prices keep themselves current with what g1t pays788 reason: string;
789 createdAt: string;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily790 /** When a change still to come takes effect: a rise is announced before it is charged. */
791 effectiveAt?: string;
Prices keep themselves current with what g1t pays792};
793
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put794export type PriceBook = {
795 prices: Price[];
796 changes: PriceChange[];
797 modelMarginPercent: number;
798 /** Every plan, as sold now. */
799 plans?: FeaturePlan[];
800 /** What is free, and the capped budgets that pay for it. */
801 free?: FreeTier | null;
802};
Prices keep themselves current with what g1t pays803
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas804/** One kind of meter's usage this month, from `usage_meters`. */
805export type MeterUsage = {
806 /** `agents`, `builds`, `requests`, `domains`, `git_storage` or `search_scans`. */
807 key: string;
808 label: string;
809 /** At price (cost plus 20%, on the account's terms), before what paid for it. */
810 micros: number;
811 /** How much, when it is known: `12 runs`, `41 build minutes`. */
812 quantity?: string | null;
813};
814
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put815/** What g1t gives without a plan; each is paid for by a capped budget. */
816export type FreeTier = {
817 /** Each new workspace's trial credit, once. */
818 trialWorkspaceMicros: number;
819 /** Trial grants each month, in all; new trials wait when it is spent. */
820 trialMonthlyPoolMicros: number;
821 /** g1t's open-source pool each month, and any one repository's share. */
822 ossPoolMicros: number;
823 ossRepoMicros: number;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas824 /** Private repository storage free for every workspace. Past it, the plan pays; a free workspace's pushes stop. */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put825 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 sudo826 /** Days of audit log a free workspace keeps. */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put827 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 sudo828 /** Days of audit log the g1t plan keeps, and g1t's own and enterprise workspaces; longer by arrangement. */
829 planAuditRetentionDays?: number;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look830 /** The smallest amount a card is charged when a month closes; less carries over. */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put831 minChargeMicros: number;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas832 /** Git operations free for every workspace each month. Past it, the plan pays; a free workspace is slowed down. */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look833 gitOperationsIncluded?: number;
834 /** A new paid workspace's ceiling in its first month. */
835 paidStartCeilingMicros?: number;
836 /** The most a one-click goodwill credit can cost g1t. */
837 overageForgiveCostMicros?: number;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put838};
839
840/**
841 * A workspace's trial credit: one grant per workspace, made the first time
842 * it uses something, out of a pool that resets each calendar month. Mirrors
843 * `Trial` in `crates/contracts/src/billing.rs`.
844 */
A free allowance on g1t's models, so anyone can try its agents845export type Trial = {
846 open: boolean;
847 usedMicros: number;
848 limitMicros: number;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put849 /** No longer used: trials do not end on a date. */
A free allowance on g1t's models, so anyone can try its agents850 endsAt: string | null;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put851 /** Why it is closed: `off`, `used` (this workspace's grant is spent) or `pool` (this month's are given out). */
A free allowance on g1t's models, so anyone can try its agents852 reason: "off" | "ended" | "used" | "pool" | null;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put853 /** Whether the workspace has its grant already. */
854 granted?: boolean;
855 /** With `pool`: when new trials start again, the first of next month. */
856 waitsUntil?: string | null;
A free allowance on g1t's models, so anyone can try its agents857};
858
Paid features: a workspace turns on Deployments with a monthly plan859/**
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar860 * What a workspace pays a monthly price for: the g1t plan (`plan`), and the
861 * Security and quality activation (`security`), sold on its own. Deployments
862 * are part of the plan; `has_feature` for `deployments` answers whether the
863 * workspace has the plan. Mirrors `Feature` in `crates/contracts/src/billing.rs`.
Paid features: a workspace turns on Deployments with a monthly plan864 */
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar865export type Feature = "plan" | "deployments" | "security";
Paid features: a workspace turns on Deployments with a monthly plan866
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas867/**
868 * What deployments cost g1t, in millionths of a dollar: fallbacks for when
869 * billing's price book cannot be read. Not an allowance: on the plan every
870 * unit is metered from the first, at cost plus 20%, and drawn from the
871 * plan's included usage first. Projects, previews and the apps behind them
872 * are not metered at all. Mirrors `deployment_costs`.
873 */
874export const DEPLOYMENT_COSTS = {
Paid features: a workspace turns on Deployments with a monthly plan875 microsPerMillionRequests: 300_000,
876 microsPerMillionCpuMs: 20_000,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas877 /** One second of a build's sandbox: a fallback; billing charges the price book's `build_second`. */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look878 microsPerBuildSecond: 15,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas879 /** One custom domain for a month. */
Agents and memory, checks and conflicts, profiles, slug renames, custom domains880 microsPerDomainMonth: 100_000,
Paid features: a workspace turns on Deployments with a monthly plan881} as const;
882
883export type FeaturePlan = {
884 feature: Feature;
885 title: string;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person886 /** Charged every month while the plan is on, in cents, excluding tax. */
Paid features: a workspace turns on Deployments with a monthly plan887 monthlyCents: number;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person888 /** The card processing fee on top each month, in cents (0 when off), excluding tax. */
889 cardFeeCents?: number;
Paid features: a workspace turns on Deployments with a monthly plan890 /** What the price includes, one line each. */
891 includes: string[];
892 /** How usage past the allowance is charged. */
893 overage: string;
894};
895
896export type SubscriptionStatus = "active" | "canceling" | "past_due" | "canceled";
897
898export type Subscription = {
899 feature: Feature;
900 status: SubscriptionStatus;
901 /** RFC 3339: when the period paid for ends. */
902 periodEnd: string | null;
903 startedBy: string;
904 startedAt: string;
905};
906
907/** A feature as a workspace sees it. */
908export type FeatureState = {
909 plan: FeaturePlan;
910 subscription: Subscription | null;
911 /** Whether the feature works for the workspace now. */
912 on: boolean;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put913 /** On without a plan: comped terms, or given by g1t. Nothing to pay or turn off. */
914 included?: boolean;
Paid features: a workspace turns on Deployments with a monthly plan915};
916
Agents as a team: lifecycle, merge queue, billing and a new shell917export interface BillingApi {
918 status(): Promise<BillingStatus>;
919 /** Members of the workspace only. */
920 account(workspace: string, viewer: Viewer): Promise<Result<BillingAccount>>;
921 /** Newest first. Members of the workspace only. */
922 ledger(workspace: string, viewer: Viewer): Promise<Result<LedgerEntry[]>>;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging923 /** Credits from g1t, newest first, with what is left of each. Members only. */
924 credits(workspace: string, viewer: Viewer): Promise<Result<Credits>>;
The statement is a month at a time, a line per kind of charge925 /** A month of the ledger, grouped by `day` (default) or `project`. Members only. */
926 statement(workspace: string, viewer: Viewer, month?: string | null, group?: "day" | "project"): Promise<Result<Statement>>;
927 /** One statement line's entries, 50 at a time; `before` is the last id seen. */
928 statementEntries(
929 workspace: string,
930 viewer: Viewer,
931 filter: { month: string; kind: string; day?: string | null; project?: string | null; before?: string | null },
932 ): Promise<Result<LedgerEntry[]>>;
Usage, like a hosting provider's: what agents cost, per day, task, repository and pull request933 /** What the workspace's agents cost since `since`, broken down. Members only. */
934 usage(workspace: string, viewer: Viewer, since: string): Promise<Result<Usage>>;
Agents as a team: lifecycle, merge queue, billing and a new shell935 /**
Mission control shows model usage, yours and the workspace's: tokens, cost, active days, cache share, each day, and the mix936 * The model tokens the workspace's runs used, day by day over the last
937 * `days` (42, at most 366), for everyone or for one `person`. Members
938 * only; a member may ask only for themselves, an owner for anyone.
939 */
940 tokenUsage(workspace: string, viewer: User, options?: { person?: string; days?: number }): Promise<Result<TokenUsage>>;
941 /**
942 * What one model answer used, added to its run's count for the day. The
943 * model proxy sends it; for usage views only, as runs are priced from AI
944 * Gateway. False when there was nothing to count.
945 */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens946 /** What the AI Gateway offers on g1t's key, with prices per million tokens. */
947 gatewayModels(): Promise<GatewayModel[]>;
Merge branch 'main' into actions-toolkit-oidc-artifacts948 /** Every purpose's default model as it applies now, and each job's tier and effort. */
949 modelDefaults(): Promise<ModelDefaults>;
950 /** What one provider lists now, from the models service's discovery. */
951 recordDiscovery(provider: string, models: ProviderModel[], by: string, error?: string | null): Promise<DiscoveryResult>;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens952 /**
953 * Whether a workspace's next AI Gateway request may go to g1t's models:
954 * fails with `payment_required` and what to do when it is over its spend
955 * limit, out of AI credit, or not on the plan.
956 */
957 gatewayAdmit(workspace: string): Promise<Result<boolean>>;
958 /** Logs one AI Gateway request, and charges it when it used tokens on g1t's models. */
959 recordGateway(record: GatewayRecord): Promise<Result<boolean>>;
960 /** A workspace's recent AI Gateway requests, newest first. Members only. */
961 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 mix962 recordTokens(usage: {
963 workspace: string;
964 /** The model session's id, one per run. */
965 session: string;
966 /** The person the run is for, by username. */
967 person?: string | null;
968 model: string;
Merge branch 'model-routing'969 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 mix970 input: number;
971 output: number;
972 cacheRead: number;
973 cacheWrite: number;
974 }): Promise<Result<boolean>>;
975 /**
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look976 * Prepays usage ($25 at least) and returns the page to send the person to:
977 * by card with 3-D Secure, or by bank transfer from $1,000. Owners only.
978 * The payment's id comes back to `returnUrl` as `session`.
Agents as a team: lifecycle, merge queue, billing and a new shell979 */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look980 checkout(
981 actor: User,
982 workspace: string,
983 amountCents: number,
984 returnUrl: string,
985 method?: "card" | "bank_transfer",
986 ): Promise<Result<{ url: string }>>;
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace987 /**
988 * Stripe's hosted billing page for the workspace: card, invoices, billing
989 * email and address. g1t never handles card numbers. Owners only.
990 */
991 billingPortal(actor: User, workspace: string, returnUrl: string): Promise<Result<{ url: string }>>;
Agents as a team: lifecycle, merge queue, billing and a new shell992 /** Credits a payment once the processor says it was made. Safe to repeat. */
993 confirm(workspace: string, viewer: Viewer, session: string): Promise<Result<BillingAccount>>;
994 /**
995 * Whether a workspace may start an agent now, asked before anything is
996 * opened for it. A failure, with the reason to show, when it has no credit.
997 */
998 canStart(workspace: string): Promise<Result<boolean>>;
A free allowance on g1t's models, so anyone can try its agents999 /** A workspace's free allowance on g1t's hosted models; `exempt` are open to them anyway. */
1000 trial(workspace: string, exempt: string[]): Promise<Trial>;
Agents as a team: lifecycle, merge queue, billing and a new shell1001 /**
1002 * Asks whether a workspace may start an agent and opens the run it will be
1003 * charged for. Null when billing is off; a failure when there is no credit.
1004 */
Paid features: a workspace turns on Deployments with a monthly plan1005 /** Every paid feature and the workspace's plan for each. Members only. */
1006 features(workspace: string, viewer: Viewer): Promise<Result<FeatureState[]>>;
1007 /**
1008 * Starts the card page for a feature's monthly plan. Owners only. The
1009 * page's id comes back to `returnUrl` as `session`.
1010 */
1011 subscribe(actor: User, workspace: string, feature: Feature, returnUrl: string): Promise<Result<{ url: string }>>;
1012 /** Turns the feature on once the plan is paid for. Safe to repeat. */
1013 confirmSubscription(workspace: string, viewer: Viewer, session: string): Promise<Result<FeatureState>>;
1014 /** Ends a plan at the end of its period, or (`resume`) takes that back. Owners only. */
1015 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 person1016 /** Which of the workspaces are free (on no paid plan); none where payments are not set up. */
1017 freeWorkspaces(workspaces: string[]): Promise<string[]>;
Paid features: a workspace turns on Deployments with a monthly plan1018 /** Whether a feature works for a workspace now; a failure with the reason when not. */
1019 hasFeature(workspace: string, feature: Feature): Promise<Result<boolean>>;
1020 /**
1021 * Usage past a plan's allowance, charged from credit at cost plus the
1022 * margin, once per `reference`. False if it was charged before.
1023 */
1024 chargeFeature(charge: {
1025 workspace: string;
1026 feature: Feature;
1027 costMicros: number;
1028 description: string;
1029 repo?: string | null;
1030 reference: string;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put1031 /** For a build: how long it ran, so the plan's included build time pays for what it can. */
1032 buildSeconds?: number | null;
Paid features: a workspace turns on Deployments with a monthly plan1033 }): Promise<Result<boolean>>;
Prices keep themselves current with what g1t pays1034 /**
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put1035 * What a source cost g1t so far this month, so the workspace's limit
1036 * counts it now. Replaces the last report. Billing charges `context`
1037 * and `security` itself once the month is over; `deployments` charges
1038 * its own.
Prices keep themselves current with what g1t pays1039 */
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1040 notePending(
1041 workspace: string,
1042 source: "deployments" | "domains" | "context" | "security",
1043 costMicros: number,
1044 /** How much of it, for the Billing page: `1.2 million requests and 3.4 million CPU ms`. */
1045 detail?: string | null,
1046 ): Promise<boolean>;
1047 /**
1048 * This month's usage, one line per kind of meter, at what it is charged
1049 * before the plan's included usage or a pool paid for it. Members only.
1050 */
1051 usageMeters(workspace: string, viewer: Viewer): Promise<Result<MeterUsage[]>>;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1052 /** What the workspace may do now: its plan, caps, pause, trial, and what the plan gives it. */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put1053 entitlements(workspace: string): Promise<Entitlements>;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1054 /**
1055 * Holds a start's estimated cost before the work starts. A failure's code says why not:
1056 * `paused`, `limit`, `not_paid`, `trial_used` or `oss_pool_empty`, with a message for the owner.
1057 */
1058 reserve(reservation: {
1059 workspace: string;
1060 repo: RepoPath;
1061 public: boolean;
1062 kind: ComputeKind;
1063 /** The most the work is expected to cost g1t, before the margin. */
1064 estimateMicros: number;
1065 }): Promise<Result<ReservationHeld>>;
1066 /** Releases a reservation's hold with what the work cost g1t, before the margin. Safe to repeat. */
1067 settle(reservationId: string, actualMicros: number): Promise<Result<boolean>>;
1068 /** Stripe's page to save and verify a card (3-D Secure, never charged). Owners only. */
1069 cardCheck(actor: User, workspace: string, returnUrl: string): Promise<Result<{ url: string }>>;
1070 /** Records the card check once Stripe says it passed, and grants the trial if it can. Safe to repeat. */
1071 confirmCardCheck(workspace: string, viewer: Viewer, session: string): Promise<Result<Entitlements>>;
1072 /** An owner asks for a higher limit, or for help with usage past what was meant. */
1073 requestLimit(
1074 actor: User,
1075 workspace: string,
1076 request: { kind: "limit" | "overage"; amountMicros: number; reason: string; expectedMonthlyMicros: number },
1077 ): Promise<Result<LimitRequest>>;
1078 /** The workspace's requests and their answers, newest first. Members only. */
1079 limitRequests(workspace: string, viewer: Viewer): Promise<Result<LimitRequest[]>>;
1080 /**
1081 * The owners' own caps on agents: one run's spend ($0.10 to $100) and one issue's ($1 to $1,000).
1082 * Null goes back to the default ($2 and $10). A cap staff set wins. Owners only.
1083 */
1084 setCaps(actor: User, workspace: string, caps: { runCapMicros: number | null; issueCapMicros: number | null }): Promise<Result<Entitlements>>;
1085 /** An owner's answer to a spend spike: keep going for 24 hours, or stop. */
1086 confirmSpike(actor: User, workspace: string, keepGoing: boolean): Promise<Result<Entitlements>>;
Prices keep themselves current with what g1t pays1087 /** Every metered price and the recent changes. Public. */
1088 prices(): Promise<PriceBook>;
Usage limits: unpaid usage can only go so far1089 /** A workspace's limit, for its members. */
1090 limit(workspace: string, viewer: Viewer): Promise<Result<Limit>>;
1091 /** The same, for the services that enforce it. */
1092 checkLimit(workspace: string): Promise<Result<Limit>>;
Every sandbox is metered by the second1093 /**
Two limits, real invoices, trust that grows by itself, sales signals1094 * The owners' own monthly limit, up to what is available; null goes back
1095 * to the default, and `useFullLimit` uses everything available. Owners only.
1096 */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1097 setSpendLimit(
1098 actor: User,
1099 workspace: string,
1100 spendLimitMicros: number | null,
1101 useFullLimit?: boolean,
1102 /** Use the one-time raise: up to twice the highest ceiling, once per workspace. */
1103 raiseOnce?: boolean,
1104 ): Promise<Result<Limit>>;
Two limits, real invoices, trust that grows by itself, sales signals1105 /** The workspace's invoices from g1t, newest first. Members only. */
1106 invoices(workspace: string, viewer: Viewer): Promise<Result<WorkspaceInvoice[]>>;
1107 /**
Every sandbox is metered by the second1108 * How long a sandbox ran for a workspace, reported when it stops. Its
Prices are what g1t pays plus 20%, from the first second1109 * cost is recorded and every second is charged, from the first. False if
1110 * `reference` was recorded before.
Every sandbox is metered by the second1111 */
1112 recordSandbox(usage: {
1113 workspace: string;
1114 seconds: number;
1115 description: string;
1116 repo?: string | null;
1117 reference: string;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1118 /** What ran; checks, workflows and the merge queue on public repositories may use the open-source pool. */
1119 kind?: ComputeKind | null;
1120 /** vCPU-seconds used, when the sandbox can tell: the run is priced on its own CPU. */
1121 cpuSeconds?: number | null;
1122 /** The reservation it started under, settled with this cost. */
1123 reservationId?: string | null;
Fast pages, required checks on the branch, self-hosted runners, honest incidents1124 /** It ran on one of the workspace's self-hosted runners: its minutes go on usage at $0. */
1125 selfHosted?: boolean;
1126 /** The machine it ran on, by label (`g1t-4core`); absent, the standard one. */
1127 instance?: string | null;
Every sandbox is metered by the second1128 }): Promise<Result<boolean>>;
Agents as a team: lifecycle, merge queue, billing and a new shell1129 startRun(run: {
1130 workspace: string;
1131 repo: RepoPath;
1132 number: number;
1133 task: string;
1134 model: string;
Integrations: your own model provider, alerts that open issues, tickets agents read1135 /** `workspace` when the run uses the workspace's own model provider. */
1136 billedTo?: "g1t" | "workspace";
Merge branch 'model-routing'1137 /**
1138 * The model session's id: the run is settled at AI Gateway's price by
1139 * it, and on the workspace's own provider its tokens are counted under
1140 * it for the agent rate.
1141 */
Prices keep themselves current with what g1t pays1142 session?: string | null;
Merge branch 'model-routing'1143 /** The tier g1t routed the run to: `small`, `large` or `frontier`. */
1144 tier?: "small" | "large" | "frontier" | null;
Agents as a team: lifecycle, merge queue, billing and a new shell1145 }): Promise<Result<RunTicket | null>>;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1146 /** Usage over a range of days (`YYYY-MM-DD`, both included), at price, by product, meter, project and day. Members only. */
1147 usageReport(
1148 workspace: string,
1149 viewer: Viewer,
1150 range: { from: string; until: string; products?: string[]; projects?: string[] },
1151 ): Promise<Result<UsageReport>>;
1152 /** The workspace's prepaid AI credit, auto-reload and prices. Members only. */
1153 aiCredit(workspace: string, viewer: Viewer): Promise<Result<AiCredit>>;
1154 /** 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`. */
1155 buyAiCredit(actor: User, workspace: string, amountCents: number, returnUrl: string): Promise<Result<{ url: string }>>;
1156 /** Credits a purchase once Stripe says it was paid, once. Safe to repeat. */
1157 confirmAiCredit(workspace: string, viewer: Viewer, session: string): Promise<Result<AiCredit>>;
1158 /** Auto-reload's settings. Owners only. */
1159 setAiReload(
1160 actor: User,
1161 workspace: string,
1162 reload: { enabled: boolean; thresholdMicros: number; targetMicros: number; monthlyMaxMicros: number },
1163 ): Promise<Result<AiCredit>>;
1164 /** The monthly budget: the spend limit, its alerts, whether usage pauses at 100%, and a webhook. Owners only. */
1165 setBudget(
1166 actor: User,
1167 workspace: string,
1168 budget: { amountMicros: number | null; alerts: number[]; pauseAtLimit: boolean; webhook: string | null; keepLimit?: boolean },
1169 ): Promise<Result<Limit>>;
1170 /** Invoice details from the Stripe customer, the default payment method, invoices and the next invoice. Members only. */
1171 billingDetails(workspace: string, viewer: Viewer): Promise<Result<BillingDetails>>;
1172 /** Saves invoice details on the Stripe customer; absent fields stay, empty clears. Owners only. */
1173 setBillingDetails(actor: User, workspace: string, details: BillingDetailsInput): Promise<Result<BillingDetails>>;
Agents as a team: lifecycle, merge queue, billing and a new shell1174}
Usage, like a hosting provider's: what agents cost, per day, task, repository and pull request1175
1176
1177/** One slice of usage: what it was for, what it cost, how many runs. */
1178export type UsageSlice = { key: string; micros: number; runs: number };
1179
Mission control shows model usage, yours and the workspace's: tokens, cost, active days, cache share, each day, and the mix1180/** The model tokens runs used over a window of days. */
1181export type TokenUsage = {
1182 /** `YYYY-MM-DD`, the first day counted. */
1183 since: string;
1184 /** The window's length: 42 unless asked, 366 at most. */
1185 days: number;
1186 /** Null for the whole workspace. */
1187 person: string | null;
1188 totalTokens: number;
1189 inputTokens: number;
1190 outputTokens: number;
1191 cacheReadTokens: number;
1192 cacheWriteTokens: number;
1193 /** What those runs were charged, as `usage` measures it. */
1194 costMicros: number;
1195 /** Days in the window with any tokens. */
1196 activeDays: number;
1197 /** Every day in the window, oldest first, zeros included. */
1198 byDay: { day: string; tokens: number }[];
1199};
1200
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1201// --- AI Gateway -------------------------------------------------------------
1202
1203/** A model the AI Gateway offers on g1t's key, with its prices per million tokens. */
1204export type GatewayModel = {
AI Gateway: OpenAI's format, open models, and your own providers1205 /**
1206 * The provider's own id, such as `claude-sonnet-5-5` or
1207 * `@cf/openai/gpt-oss-120b`. A request names it as it is or with its
1208 * provider in front (`anthropic/claude-sonnet-5-5`).
1209 */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1210 model: string;
1211 /** For people: `Claude Sonnet 5.5`. */
1212 name: string;
AI Gateway: OpenAI's format, open models, and your own providers1213 /** `anthropic` or `workers-ai`. */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1214 provider: string;
AI Gateway: OpenAI's format, open models, and your own providers1215 /** `chat`, or `embeddings` for a model that only embeds text. */
1216 kind?: "chat" | "embeddings";
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1217 inputMicros: number;
1218 outputMicros: number;
1219 cacheReadMicros: number;
AI Gateway: OpenAI's format, open models, and your own providers1220 /** Cache writes that live five minutes. */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1221 cacheWriteMicros: number;
AI Gateway: OpenAI's format, open models, and your own providers1222 /** Cache writes that live an hour. */
1223 cacheWrite1hMicros?: number;
1224 /**
1225 * Priced by the prompt's length: a request whose prompt (input, cache
1226 * read and cache write tokens) is longer than this is charged entirely at
1227 * the `over` prices. 0 or absent for one price.
1228 */
1229 threshold?: number;
1230 overInputMicros?: number;
1231 overOutputMicros?: number;
1232 overCacheReadMicros?: number;
1233 overCacheWriteMicros?: number;
1234 overCacheWrite1hMicros?: number;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1235};
1236
Merge branch 'main' into actions-toolkit-oidc-artifacts1237// --- The model catalogue ------------------------------------------------------
1238
1239/** Where a model stands: only `available` ones are routed to. */
1240export type ModelStatus = "available" | "new" | "deprecated" | "retired";
1241
1242/** One model in g1t's catalogue: its prices and what g1t knows about it. */
1243export type CatalogueModel = GatewayModel & {
1244 /** Other ids the provider lists it by, such as a dated one. */
1245 aliases: string[];
1246 family: string;
1247 /** The agent tier it suits: `small`, `large`, `frontier`, or empty. */
1248 tierHint: string;
1249 contextWindow: number;
1250 maxOutput: number;
1251 /** Any of `effort`, `thinking`, `tools`, `vision`, `embeddings`. */
1252 capabilities: string[];
1253 dimensions: number;
1254 status: ModelStatus;
1255 /** Its prices are known. An unpriced model is never routed to, offered or charged for. */
1256 priced: boolean;
1257 source: "discovered" | "staff";
1258 firstSeenAt: string | null;
1259 lastSeenAt: string | null;
1260 missingSince: string | null;
1261 approvedBy: string | null;
1262 approvedAt: string | null;
1263 note: string;
1264 /** A typical agent run on it, in millionths of a dollar; 0 when unpriced or embeddings. */
1265 typicalRunMicros: number;
1266};
1267
1268/** One model as its provider lists it, from the models service's discovery. */
1269export type ProviderModel = {
1270 id: string;
1271 name: string;
1272 /** `chat`, `embeddings`, or anything else (counted as listed, never added). */
1273 kind: string;
1274 contextWindow: number;
1275 maxOutput: number;
1276 capabilities: string[];
1277 /** Workers AI lists a price per million tokens; Anthropic does not. */
1278 price: { inputMicros: number; outputMicros: number } | null;
1279};
1280
1281/** What one check of a provider found. */
1282export type DiscoveryResult = {
1283 provider: string;
1284 checkedAt: string;
1285 by: string;
1286 listed: number;
1287 added: string[];
1288 deprecated: string[];
1289 restored: string[];
1290 error: string | null;
1291};
1292
1293/** The purposes a default model is chosen for. */
1294export type ModelPurpose = "tier_small" | "tier_large" | "tier_frontier" | "background" | "gateway_first";
1295
1296/** One purpose's default, as staff last set it. */
1297export type ModelDefault = {
1298 /** A `ModelPurpose`, or `job_<kind>`. */
1299 purpose: string;
1300 model: string | null;
1301 /** For a job: `small`, `large`, `frontier` or `change`. */
1302 tier: string | null;
1303 effort: string | null;
1304 updatedAt: string;
1305 updatedBy: string;
1306 reason: string;
1307};
1308
1309/** A model purpose's default as it applies now. */
1310export type ResolvedModel = {
1311 purpose: string;
1312 chosen: string;
1313 /** The model to use; null when nothing suits (callers keep their own fallback). */
1314 model: GatewayModel | null;
1315 capabilities: string[];
1316 /** Why it is not the chosen model, in a sentence. */
1317 note: string | null;
1318};
1319
1320/** One kind of agent job's starting tier and effort. */
1321export type JobDefault = { kind: string; tier: string; effort: string | null };
1322
1323/** Every purpose's model as it applies now, and each job's tier and effort. */
1324export type ModelDefaults = { models: ResolvedModel[]; jobs: JobDefault[] };
1325
1326/** One check of one provider. */
1327export type ModelCheck = {
1328 id: string;
1329 provider: string;
1330 checkedAt: string;
1331 by: string;
1332 listed: number;
1333 added: string[];
1334 deprecated: string[];
1335 error: string | null;
1336};
1337
1338/** The tokens of the typical agent run estimates are priced from. */
1339export type TypicalRun = { requests: number; input: number; output: number; cacheRead: number; cacheWrite: number };
1340
1341/** sudo's Agents & models. */
1342export type AdminModels = {
1343 catalogue: CatalogueModel[];
1344 defaults: ModelDefault[];
1345 resolved: ModelDefaults;
1346 checks: ModelCheck[];
1347 typical: TypicalRun;
1348};
1349
1350/** A model's prices as staff confirm them, per million tokens in millionths of a dollar. */
1351export type ModelPrices = {
1352 inputMicros: number;
1353 outputMicros: number;
1354 cacheReadMicros: number;
1355 cacheWriteMicros: number;
1356 cacheWrite1hMicros: number;
1357 threshold: number;
1358 overInputMicros: number;
1359 overOutputMicros: number;
1360 overCacheReadMicros: number;
1361 overCacheWriteMicros: number;
1362 overCacheWrite1hMicros: number;
1363};
1364
1365/** The models service's `Discovery` entrypoint, for sudo's "Check for new models". */
1366export interface ModelDiscoveryApi {
1367 /** Lists every provider's models now and records what changed: one result per provider. */
1368 check(by: string): Promise<DiscoveryResult[]>;
1369}
1370
AI Gateway: OpenAI's format, open models, and your own providers1371/** The format a gateway request was sent in. */
1372export type GatewayFormat = "anthropic" | "openai";
1373
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1374/** One AI Gateway request, as the model proxy reports it to billing. */
1375export type GatewayRecord = {
1376 /** `gw_…`, chosen by the proxy; recording it twice records it once. */
1377 id: string;
1378 workspace: string;
1379 tokenId: string;
1380 tokenName?: string | null;
1381 model: string;
1382 input: number;
1383 output: number;
1384 cacheRead: number;
AI Gateway: OpenAI's format, open models, and your own providers1385 /** Every cache write, of either lifetime. */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1386 cacheWrite: number;
AI Gateway: OpenAI's format, open models, and your own providers1387 /** Of `cacheWrite`, those that live an hour. */
1388 cacheWriteHour?: number;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1389 /** The HTTP status the caller was answered with. */
1390 status: number;
1391 /** On the workspace's own provider key: counted, never charged. */
1392 ownKey: boolean;
AI Gateway: OpenAI's format, open models, and your own providers1393 format: GatewayFormat;
1394 /**
1395 * Who served it: `anthropic` or `workers-ai` on g1t's key, the
1396 * connection's provider on the workspace's own. Empty when it never got
1397 * that far.
1398 */
1399 provider: string;
1400 /** On the workspace's own provider: the connection's name. */
1401 connection?: string | null;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1402 streamed: boolean;
1403 durationMs: number;
1404 error?: string | null;
1405};
1406
1407/** One AI Gateway request, as its log keeps it. */
1408export type GatewayRequest = {
1409 id: string;
1410 createdAt: string;
1411 model: string;
1412 tokenId: string;
1413 tokenName: string | null;
1414 input: number;
1415 output: number;
1416 cacheRead: number;
1417 cacheWrite: number;
AI Gateway: OpenAI's format, open models, and your own providers1418 /** Of `cacheWrite`, those that live an hour. */
1419 cacheWriteHour: number;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1420 /** What the tokens cost at the model's price. */
1421 costMicros: number;
1422 /** What the workspace was charged, before included usage and credit paid for it; 0 on its own key. */
1423 chargedMicros: number;
1424 status: number;
1425 ownKey: boolean;
AI Gateway: OpenAI's format, open models, and your own providers1426 format: GatewayFormat;
1427 /** `anthropic` or `workers-ai` on g1t's key; the connection's provider on the workspace's own. */
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/** A page of AI Gateway requests, newest first. */
1437export type GatewayRequests = {
1438 requests: GatewayRequest[];
1439 /** The `before` for the next page, when there is one. */
1440 next: string | null;
1441 /** How many days requests are kept. */
1442 retentionDays: number;
1443};
1444
Usage, like a hosting provider's: what agents cost, per day, task, repository and pull request1445/** What a workspace's agents cost over a period. */
1446export type Usage = {
1447 since: string;
1448 /** Charged, including g1t's margin. */
1449 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 charged1450 /** 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 for1451 coveredMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1452 /** What the account's discount took off the price; usage at price is spent + covered + this. */
1453 discountMicros?: number;
1454 /** The account's discount now, in percent; with one, the slices are at price. */
1455 discountPercent?: number | null;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1456 /** Usage at price: spent + covered + discount, from the same ledger lines. The one usage figure every page shows. */
1457 priceMicros?: number;
Integrations: your own model provider, alerts that open issues, tickets agents read1458 /** What g1t's model provider charged, before the margin. */
Usage, like a hosting provider's: what agents cost, per day, task, repository and pull request1459 costMicros: number;
Integrations: your own model provider, alerts that open issues, tickets agents read1460 /** What runs on the workspace's own provider cost there, estimated. Not charged by g1t. */
1461 providerMicros: number;
Usage while free is shown at cost; agents get rustfmt and clippy1462 /** What the runs used, at cost: g1t's models and the workspace's own provider together. */
1463 usedMicros: number;
1464 /** g1t charges nothing for now; the slices then measure usage at cost. */
1465 free: boolean;
Usage, like a hosting provider's: what agents cost, per day, task, repository and pull request1466 runs: number;
1467 /** Spend per day and task, keyed `YYYY-MM-DD/task`. */
1468 byDay: UsageSlice[];
1469 byTask: UsageSlice[];
1470 byRepo: UsageSlice[];
1471 /** Keyed `namespace/name#number`. */
1472 byPull: UsageSlice[];
1473 byModel: UsageSlice[];
1474 /** Credit bought in the period. */
1475 addedMicros: number;
1476};
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1477
1478/** One of g1t's products (a "bucket") on one day. Money in micros. */
1479export type CostDay = { day: string; bucket: string; cfCostMicros: number; ownCostMicros: number; valueMicros: number; cashMicros: number };
1480
1481/** One product over the range: what customers were charged at price against what it cost. */
1482export type ProductMargin = {
1483 bucket: string;
1484 title: string;
1485 /** Cloudflare's bill, or g1t's own figure where Cloudflare does not bill it (`costSource`). */
1486 costMicros: number;
1487 cfCostMicros: number;
1488 ownCostMicros: number;
1489 valueMicros: number;
1490 marginMicros: number;
1491 marginPercent: number | null;
1492 costSource: "cloudflare" | "ledger" | string;
1493 /** Running g1t, paid for by the plan. */
1494 overhead: boolean;
1495};
1496
1497/** 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 it1498export type OverallMargin = {
1499 usageMicros: number;
1500 plansMicros: number;
1501 costMicros: number;
1502 marginMicros: number;
1503 marginPercent: number | null;
1504 /** Of costMicros, what went on usage g1t gave away on purpose: comped workspaces, free periods, the trial and the open-source pool. */
1505 givenMicros?: number;
1506 /** Money in against costMicros - givenMicros. */
1507 soldMarginMicros?: number;
1508 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 running1509 /** Usage sold: usageMicros against what that usage cost, less what was given. */
1510 usageCostMicros?: number;
1511 usageMarginMicros?: number;
1512 usageMarginPercent?: number | null;
1513 /** Running g1t: plansMicros against the platform's cost, less its given share. */
1514 runningCostMicros?: number;
1515 /** Cost no mapping names, less its given share. */
1516 unmappedCostMicros?: number;
1517 /** givenMicros by why. Free is free periods, free allowances and overruns g1t covered. */
1518 givenCompedMicros?: number;
1519 givenFreeMicros?: number;
1520 givenTrialMicros?: number;
1521 givenPoolMicros?: number;
Merge branch 'worktree-agent-a633ac0f7f66d419d'1522 /** What discounts on an account's terms took below cost plus the margin: given, not margin lost. */
1523 givenDiscountMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1524 /** Credits from g1t spent on usage, by kind: given, never money in. Refunds come off money in instead. */
1525 givenCreditPromotionalMicros?: number;
1526 givenCreditGoodwillMicros?: number;
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb971527 /** What testing resets wiped that g1t paid for: the usage still happened, so its cost is given, never a leak. */
1528 givenResetMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1529 /** Credits over the range: given (every kind), spent on usage, and refunds' money given back. */
1530 creditsGivenMicros?: number;
1531 creditsUsedMicros?: number;
1532 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 running1533 /** 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)1534 /** What the plan's included usage paid for, at price: money in for usage, paid out of plansMicros. */
1535 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 running1536 cloudflareCostMicros?: number;
1537 modelsCostMicros?: number;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person1538 /** Tax collected with payments over the range, net of refunds: owed to tax authorities, never cash or revenue. */
1539 taxCollectedMicros?: number;
1540 /** Card processing fees passed on with card payments, net of refunds: they pay Stripe's fee, not revenue. */
1541 cardFeesMicros?: 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 it1542};
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1543
1544/** A count, cost or leak that does not add up. */
1545export type CostDrift = {
1546 bucket: string;
1547 title: string;
1548 kind: "count" | "cost" | "leak" | string;
1549 ours: number;
1550 cloudflare: number;
1551 deltaPercent: number | null;
1552 detail: string;
1553 foundAt: string;
1554};
1555
1556export type MarginAlert = {
1557 id: string;
1558 kind: "margin" | "overall" | "leak" | "drift" | "workspace" | string;
1559 /** The product, or the workspace. */
1560 subject: string;
1561 detail: string;
1562 since: string;
1563 openedAt: string;
1564 emailedAt: string | null;
1565};
1566
1567/** A change to a price, measured from what Cloudflare charged. */
1568export type PriceProposal = {
1569 id: string;
1570 meter: string;
1571 title: string;
1572 unit: string;
1573 currentCostMicros: number;
1574 proposedCostMicros: number;
1575 changePercent: number;
1576 markupPercent: number;
1577 reason: string;
1578 source: "keeper" | "reconciler" | string;
1579 /** Far off the current cost: look before approving. */
1580 suspect: boolean;
1581 status: "open" | "applied" | "approved" | "rejected" | "superseded" | string;
1582 createdAt: string;
1583 decidedAt: string | null;
1584 decidedBy: string | null;
1585 note: string | null;
1586 effectiveAt: string | null;
1587};
1588
1589/** One version of one meter's price; never changed once written. */
1590export type PriceVersion = {
1591 id: string;
1592 meter: string;
1593 version: number;
1594 costMicros: number;
1595 markupPercent: number;
1596 priceMicros: number;
1597 effectiveAt: string;
1598 reason: string;
1599 createdBy: string;
1600 appliedAt: string | null;
Merge costs and margin review: gateway query, own spend, discount meters, superseded rises1601 /**
1602 * What `costMicros` is: `cost`, what g1t pays for a unit; `rate`, a price
1603 * g1t sets with no cost behind it (the agent rate), so it is no cost;
1604 * `weight`, a multiplier in millionths, not money. Absent from older
1605 * billing: read as `cost`.
1606 */
1607 basis?: "cost" | "rate" | "weight" | "";
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1608};
1609
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's1610/** 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 sold1611export 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's1612
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1613export 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 daily1614
1615export type CostLineSummary = {
1616 product: string;
1617 meter: string;
1618 rawName: string;
1619 unit: string;
1620 source: string;
1621 quantity: number;
1622 costMicros: number;
1623 /** Absent when no mapping claims it. */
1624 bucket: string | null;
1625};
1626
1627export type CostMapping = {
1628 product: string;
1629 meter: string;
1630 bucket: string;
1631 priceMeter: string | null;
1632 ownMeter: string | null;
1633 scaleToOwn: boolean;
1634 driftPercent: number;
1635 note: string;
1636 updatedAt: string;
1637 updatedBy: string;
1638};
1639
1640export type CostMappingInput = {
1641 product: string;
1642 meter: string;
1643 bucket?: string;
1644 priceMeter?: string | null;
1645 ownMeter?: string | null;
1646 scaleToOwn?: boolean;
1647 driftPercent?: number | null;
1648 note?: string;
1649 remove?: boolean;
1650};
1651
1652export type CostSettings = {
1653 autoApply: boolean;
1654 autoApplyPercent: number;
1655 noticeDays: number;
1656 marginFloorPercent: number;
1657 alertDays: number;
1658 minDailyCostMicros: number;
1659 anomalyFactor: number;
1660 anomalyFloorMicros: number;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1661 /** Pass Stripe's card fee on as its own line when AI credit is bought by card. */
1662 cardFee: boolean;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1663};
1664
1665export type CostsReport = {
1666 configured: boolean;
1667 fetchedAt: string | null;
1668 since: string;
1669 until: string;
1670 days: CostDay[];
1671 products: ProductMargin[];
1672 overall: OverallMargin;
1673 drift: CostDrift[];
1674 alerts: MarginAlert[];
1675 proposals: PriceProposal[];
1676 versions: PriceVersion[];
1677 topWorkspaces: WorkspaceCost[];
1678 lines: CostLineSummary[];
1679 mappings: CostMapping[];
1680 settings: CostSettings;
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1681 /** g1t's own spend against its two caps. */
1682 caps: SpendCaps;
1683};
1684
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)1685/** One level of the platform pause, as sudo shows it. Snake case, as billing sends it. */
1686export type PauseState = {
1687 level: PauseLevel;
1688 paused: boolean;
1689 note: string | null;
1690 set_by: string | null;
1691 set_at: string | null;
1692 /** Set by billing's usage watcher, not a person. */
1693 auto: boolean;
1694};
1695
1696/** One platform metric over an hour or the month so far. */
1697export type PlatformMetric = {
1698 metric: string;
1699 title: string;
1700 value: number;
1701 /** Its hourly threshold (`PLATFORM_HOURLY_*`); 0: none. */
1702 threshold: number;
1703 /** The script, queue, database or namespace that counted most. */
1704 top_name: string | null;
1705 top_value: number | null;
1706};
1707
1708/** A breach billing's usage watcher found. */
1709export type PlatformBreach = {
1710 id: string;
1711 metric: string;
1712 hour: string;
1713 rule: "threshold" | "spike";
1714 value: number;
1715 threshold: number;
1716 severe: boolean;
1717 top_name: string | null;
1718 detail: string;
1719 /** Levels it paused. */
1720 paused: PauseLevel[];
1721 opened_at: string;
1722 emailed_at: string | null;
1723};
1724
1725/** Billing's `admin_platform_guard`: the platform pause and usage watcher (docs/SPEND-GUARDRAILS.md). */
1726export type PlatformGuard = {
1727 levels: PauseState[];
1728 /** The last hour read, `YYYY-MM-DDTHH:00:00Z`. */
1729 hour: string | null;
1730 last_hour: PlatformMetric[];
1731 month: string;
1732 month_to_date: PlatformMetric[];
1733 breaches: PlatformBreach[];
1734 /** Whether billing can read Cloudflare's analytics. */
1735 can_read: boolean;
1736 /** `AUTO_PAUSE`: the levels a severe breach may pause. */
1737 auto_pause: PauseLevel[];
1738 /** What the latest run could not see: each query that failed, with its error. */
1739 blind?: { key: string; dataset: string; error: string }[];
1740 /** The latest run found every dataset empty: the wrong account, or a token that cannot see it. */
1741 empty?: boolean;
1742 /** The hour the latest run read. */
1743 last_run?: string | null;
1744};
1745
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1746/** What g1t pays for itself, at cost, against its caps (billing's `budget`). */
1747export type SpendCaps = {
1748 /** Today (UTC), YYYY-MM-DD, and this month, YYYY-MM. */
1749 day: string;
1750 month: string;
1751 /** What g1t paid for itself today across every workspace. */
1752 todayMicros: number;
1753 /** `PLATFORM_DAILY_SPEND_CAP_MICROS`; 0: no breaker. */
1754 dailyCapMicros: number;
1755 /** New hosted-model agent runs g1t would pay for are paused. */
1756 tripped: boolean;
1757 trippedAt: string | null;
1758 liftedBy: string | null;
1759 liftedAt: string | null;
1760 liftNote: string | null;
1761 /** This month so far, by what paid: comped, trial, oss, given, unpaid. */
1762 monthBuckets: { bucket: string; title: string; micros: number }[];
1763 comped: CompedBudget[];
1764 /** Free workspaces' share of reconciled costs this month (git, storage, platform). */
1765 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 & pricing1766 /** 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 pays1767 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 & pricing1768 fixedSource?: "cloudflare" | "estimate" | string;
1769 fixedReadAt?: string | null;
1770 /** Each subscription, when read from Cloudflare. */
1771 fixedItems?: { name: string; monthlyMicros: number }[];
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1772 /** Money in this month, through the last reconciled day. */
1773 revenueMicros: number;
Merge costs and margin review: gateway query, own spend, discount meters, superseded rises1774 /**
1775 * Of this month's buckets, what was spent on workspaces whose billing a
1776 * testing reset later wiped (still g1t's spend; the reconciled figures
1777 * have it only where the reset kept it), and those workspaces.
1778 */
1779 resetMicros?: number;
1780 resetWorkspaces?: string[];
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1781};
1782
1783/** A comped account's monthly budget, at cost. */
1784export type CompedBudget = {
1785 account: string;
1786 name: string;
1787 usedMicros: number;
1788 /** 0: no budget. */
1789 ceilingMicros: number;
1790 /** `COMPED_MONTHLY_CEILING_MICROS`, not the account's own limit. */
1791 defaultCeiling: boolean;
1792 /** 50, 75, 90, 100, or 0. */
1793 level: number;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1794};
1795
1796export type CostsRun = { lines: number; days: number; proposals: number; alerts: number; problems: string[] };
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1797
1798/** The product families the Usage page groups meters into, in order. */
1799export const PRODUCTS = [
1800 { key: "agent", label: "Agent" },
1801 { key: "sandboxes", label: "Sandboxes" },
1802 { key: "gateway", label: "AI Gateway" },
1803 { key: "deployments", label: "Deployments" },
1804 { key: "git_storage", label: "Git & storage" },
1805 { key: "packages", label: "Packages" },
1806 { key: "security", label: "Security & quality" },
1807 { key: "search", label: "Search" },
1808] as const;
1809
1810export type ProductKey = (typeof PRODUCTS)[number]["key"];
1811
1812/** What usage came to over a range, and what paid for it: price − discount − included − credits = charged. */
1813export type UsageTotals = {
1814 /** Usage at price, pending usage included. */
1815 priceMicros: number;
1816 discountMicros: number;
1817 /** Paid by the plan's included usage, the trial and g1t's pools. */
1818 includedMicros: number;
1819 /** Paid by AI credit and credit from g1t. */
1820 creditsMicros: number;
1821 /** Left for the workspace to pay. */
1822 chargedMicros: number;
1823 /** Metered this month, charged when it closes. */
1824 pendingMicros: number;
1825 costMicros: number;
1826};
1827
1828export type UsageDay = { day: string; product: string; micros: number };
1829
1830export type UsageAllowance = { used: number; of: number; unit: string };
1831
1832export type ProjectUsage = { project: string; micros: number; quantity: number };
1833
1834/** One meter over a range. */
1835export type MeterLine = {
1836 key: string;
1837 label: string;
1838 product: string;
1839 /** `tokens`, `seconds`, `bytes`, `operations`, `requests` or `entries`. */
1840 unit: string;
1841 quantity: number;
1842 micros: number;
1843 pendingMicros?: number;
1844 /** Every day of the range, oldest first, at price. */
1845 daily: number[];
1846 allowance?: UsageAllowance | null;
1847 byProject: ProjectUsage[];
Merge branch 'model-routing'1848 /** How the quantity is counted, when that needs saying (the agent rate's token weights). */
1849 note?: string | null;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1850};
1851
1852export type FeatureUsage = { key: string; label: string; micros: number; count: number };
1853
1854export type ProductUsage = { key: string; label: string; micros: number; meters: MeterLine[]; features?: FeatureUsage[] };
1855
Merge branch 'model-routing'1856/** The tokens one model used over a range, as the model proxy counted them. */
1857export type ModelTokens = { model: string; input: number; output: number; cacheRead: number; cacheWrite: number };
1858
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1859export type UsageReport = {
1860 from: string;
1861 until: string;
1862 totals: UsageTotals;
1863 days: UsageDay[];
1864 products: ProductUsage[];
1865 projects: string[];
Merge branch 'model-routing'1866 /** Agent tokens by model over the range, most first. */
1867 models?: ModelTokens[];
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1868 /** The plan's included usage this month, in micros. */
1869 included?: UsageAllowance | null;
1870 discountPercent?: number | null;
1871 aiCreditMicros: number;
1872 creditMicros: number;
1873 trialMicros?: number | null;
1874 plan: PlanKind;
1875 free: boolean;
1876};
1877
1878export type AiReload = {
1879 enabled: boolean;
1880 thresholdMicros: number;
1881 targetMicros: number;
1882 monthlyMaxMicros: number;
1883 reloadedMicros?: number;
1884 failedAt?: string | null;
1885 error?: string | null;
1886};
1887
1888export type CardFee = { on: boolean; percentMicros: number; fixedCents: number };
1889
1890/** Prepaid AI credit: what Agent and AI Gateway usage draws on. */
1891export type AiCredit = {
1892 balanceMicros: number;
1893 purchasedMicros: number;
1894 givenMicros: number;
1895 grants: CreditGrant[];
1896 /** A 100% discount pays for AI usage: nothing to buy. */
1897 freeViaDiscount: boolean;
1898 /** Invoiced after use (an enterprise). */
1899 postpaid: boolean;
1900 /** New runs on g1t's models are refused for want of credit. */
1901 blocked: boolean;
1902 canBuy: boolean;
1903 presetsCents: number[];
1904 minCents: number;
1905 maxCents: number;
1906 cardFee: CardFee;
1907 reload: AiReload;
1908 /** The agent rate per million tokens, at price. */
1909 agentRateMicros: number;
1910 modelMarkupPercent: number;
1911 gatewayMarkupPercent: number;
1912 upgradeCreditMicros: number;
1913 expiresDays: number;
1914};
1915
1916export type PostalAddress = { line1: string; line2: string; city: string; state: string; postalCode: string; country: string };
1917
1918export type PaymentMethod = {
1919 kind: string;
1920 brand?: string | null;
1921 last4?: string | null;
1922 expMonth?: number | null;
1923 expYear?: number | null;
1924};
1925
1926export type StripeInvoice = {
1927 id: string;
1928 number?: string | null;
1929 status: string;
1930 totalCents: number;
1931 currency: string;
1932 createdAt: string;
1933 description?: string | null;
1934 hostedUrl?: string | null;
1935 pdfUrl?: string | null;
1936};
1937
1938export type UpcomingInvoice = { closesAt: string; subscriptionsMicros: number; usageMicros: number; totalMicros: number };
1939
1940export type BillingDetails = {
1941 customer: boolean;
1942 email: string | null;
1943 name: string | null;
1944 address: PostalAddress | null;
1945 taxIdType: string | null;
1946 taxId: string | null;
1947 poNumber: string | null;
1948 language: string | null;
1949 paymentMethod: PaymentMethod | null;
1950 invoices: StripeInvoice[];
1951 upcoming: UpcomingInvoice;
1952 unavailable?: string | null;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person1953 /** Whether Stripe Tax can place the customer from the address; without it nothing is charged. */
1954 taxLocation?: boolean;
1955 /** Set when g1t did not charge for want of a billing address. */
1956 taxAddressNeededAt?: string | null;
1957 /** Stripe's check of the tax ID: pending, verified, unverified or unavailable. */
1958 taxIdStatus?: string | null;
1959 /** none, exempt or reverse, as set at Stripe. */
1960 taxExempt?: string | null;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1961};
1962
1963export type BillingDetailsInput = {
1964 email?: string;
1965 name?: string;
1966 address?: PostalAddress;
1967 taxIdType?: string;
1968 taxId?: string;
1969 poNumber?: string;
1970 language?: string;
1971};

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