Skip to content
2,053 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";
Deploy scripts live in the repository3import type { User, Viewer } from "./identity";
4import type { RepoPath } from "./repos";
5import type { Result } from "./result";
6
7/** Millionths of a US dollar in one dollar: the unit money is held in. */
8export const MICROS_PER_DOLLAR = 1_000_000;
9
10/** Whether workspaces are charged for agents at all, and with real money. */
11export type BillingStatus = {
12 /**
13 * False when no card processor is configured: nothing is charged, and who
14 * may run agents is decided some other way.
15 */
16 enabled: boolean;
17 /** False while the card processor is in its test mode, where cards are not real. */
18 live: boolean;
19 /**
20 * True while g1t is being built out: runs are recorded with what they
21 * cost, but nothing is charged and no credit is needed. Not forever.
22 */
23 free?: boolean;
24};
25
26/** A workspace's standing. */
27export type BillingAccount = {
28 workspace: string;
29 /**
30 * Credit left, in millionths of a dollar. Can dip below zero by the cost
31 * of the runs that were under way when it ran out.
32 */
33 balanceMicros: number;
34 status: BillingStatus;
35 /** What is added to a run's cost, in percent. */
36 marginPercent: number;
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;
Deploy scripts live in the repository39};
40
41/** One line of a workspace's statement. */
42export type LedgerEntry = {
43 id: string;
44 /** Credit bought with a card, or an agent's run. */
45 kind: "top_up" | "usage";
46 /** Positive for credit added, negative for usage. */
47 amountMicros: number;
48 description: string;
49 /** For usage: the repository and pull request the agent worked on. */
50 repo: string | null;
51 number: number | null;
52 /** For usage: `implement`, `review` or `update`. */
53 task: string | null;
54 /** For usage: the model, by its public name. */
55 model: string | null;
56 /** For usage: who paid the model provider. */
57 billedTo: "g1t" | "workspace";
58 /** For a top-up: the username of whoever paid. */
59 createdBy: string | null;
60 /** RFC 3339. */
61 createdAt: string;
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;
Deploy scripts live in the repository76};
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
Deploy scripts live in the repository142/** What lets a sandbox, and nothing else, report what its run cost. */
143export type RunTicket = { runId: string; token: string };
144
145/**
146 * What agents cost, charged to the workspace they worked for. A workspace
147 * buys credit; each run deducts its cost plus g1t's margin; with no credit,
148 * no agent starts.
149 */
150/**
151 * The free allowance on g1t's hosted models for a workspace not otherwise
152 * open to them: a few dollars of model cost each, out of one pool, until a
153 * date. Mirrors `Trial` in `crates/contracts/src/billing.rs`.
154 */
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging155/**
156 * How an account is charged. Standard unless g1t set otherwise in sudo:
157 * custom terms are a discount (0 to 100%), a ceiling, or both. A 100%
158 * discount charges nothing and shows the usage at its price. `comped` is
159 * from before discounts and reads as 100%; billing no longer writes it.
160 */
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;
Spend adds up on one ledger. Charged this month has one definition, price less discount, included usage and credit, shared by the plan card, the spend limit, Spend and the top bar; the limit had counted usage not yet closed at full price before the discount, so a comped workspace read as charged a cent. Every agent line on the ledger names the agent and who asked, repository runs by g1t included, so Spent is the sum of its products, Agents is the agent product, and by agent adds up to it; the billing API returns by_agent and by_person. The usage and billing guide says how spend is counted.730 /**
731 * Charged this month, which the spend limit is measured against: usage at
732 * price less the discount, included usage, the trial, pools and credit,
733 * with usage metered through the month counted on the same terms. The
734 * same number as the month's `UsageTotals.chargedMicros`.
735 */
Two limits, real invoices, trust that grows by itself, sales signals736 spentMicros?: number;
737 /** True while the owners have not chosen a limit, so the automatic one applies: $200, or twice last month's spend. */
738 defaultSpendLimit?: boolean;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look739 /** 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 signals740 availableMicros?: number | null;
741 /** How the ceiling grows from here, in a sentence. */
742 growth?: string | null;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look743 /** Paid in advance and not used yet; raises what can be used before work stops by as much. */
744 prepaidMicros?: number;
745 /** The highest ceiling the workspace has had. */
746 maxCeilingMicros?: number | null;
747 /** The most owners may raise the limit to themselves, once: twice the highest ceiling. Null once used. */
748 raiseOnceMicros?: number | null;
749 /** When the one-time raise was used. */
750 raisedAt?: string | null;
751 /** A paid workspace's first billing cycle, on the starting ceiling. */
752 firstMonth?: boolean;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit753 /** The budget's alerts, in percent of the spend limit: some of 50, 75, 90 and 100. */
754 alertLevels?: number[];
755 /** Whether usage pauses at the spend limit (the default); off, it only alerts. */
756 pauseAtLimit?: boolean;
757 /** An HTTPS address told of each budget alert. */
758 budgetWebhook?: string | null;
Usage limits: unpaid usage can only go so far759};
760
Prices keep themselves current with what g1t pays761/** One metered unit: what it costs g1t and what it is sold at; the price follows the cost. */
762export type Price = {
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put763 meter:
764 | "sandbox_second"
765 | "build_second"
766 | "app_requests"
767 | "app_cpu"
768 | "app_month"
769 | "custom_domain_month"
770 | "private_storage"
771 | "embedding_tokens"
772 | "scan_cpu"
773 | "scan_rows"
774 | string;
Prices keep themselves current with what g1t pays775 title: string;
776 unit: string;
777 costMicros: number;
778 markupPercent: number;
779 priceMicros: number;
780 /** `list`: Cloudflare's published price. `cloudflare`: measured from Cloudflare's bill. */
781 source: "list" | "cloudflare" | string;
782 checkedAt: string | null;
783 updatedAt: string;
784};
785
786export type PriceChange = {
787 meter: string;
788 oldCostMicros: number;
789 newCostMicros: number;
790 markupPercent: number;
Prices are what g1t pays plus 20%, from the first second791 /** The markup before, when the change was to the markup rather than the cost. */
792 oldMarkupPercent?: number;
Prices keep themselves current with what g1t pays793 reason: string;
794 createdAt: string;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily795 /** When a change still to come takes effect: a rise is announced before it is charged. */
796 effectiveAt?: string;
Prices keep themselves current with what g1t pays797};
798
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put799export type PriceBook = {
800 prices: Price[];
801 changes: PriceChange[];
802 modelMarginPercent: number;
803 /** Every plan, as sold now. */
804 plans?: FeaturePlan[];
805 /** What is free, and the capped budgets that pay for it. */
806 free?: FreeTier | null;
807};
Prices keep themselves current with what g1t pays808
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas809/** One kind of meter's usage this month, from `usage_meters`. */
810export type MeterUsage = {
811 /** `agents`, `builds`, `requests`, `domains`, `git_storage` or `search_scans`. */
812 key: string;
813 label: string;
814 /** At price (cost plus 20%, on the account's terms), before what paid for it. */
815 micros: number;
816 /** How much, when it is known: `12 runs`, `41 build minutes`. */
817 quantity?: string | null;
818};
819
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put820/** What g1t gives without a plan; each is paid for by a capped budget. */
821export type FreeTier = {
822 /** Each new workspace's trial credit, once. */
823 trialWorkspaceMicros: number;
824 /** Trial grants each month, in all; new trials wait when it is spent. */
825 trialMonthlyPoolMicros: number;
826 /** g1t's open-source pool each month, and any one repository's share. */
827 ossPoolMicros: number;
828 ossRepoMicros: number;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas829 /** 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 put830 freePrivateStorageBytes: number;
Audit logs are kept by plan: a week on free, 90 days on the plan, and what staff set for an account in sudo831 /** Days of audit log a free workspace keeps. */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put832 auditRetentionDays: number;
Audit logs are kept by plan: a week on free, 90 days on the plan, and what staff set for an account in sudo833 /** Days of audit log the g1t plan keeps, and g1t's own and enterprise workspaces; longer by arrangement. */
834 planAuditRetentionDays?: number;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look835 /** 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 put836 minChargeMicros: number;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas837 /** 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 look838 gitOperationsIncluded?: number;
839 /** A new paid workspace's ceiling in its first month. */
840 paidStartCeilingMicros?: number;
841 /** The most a one-click goodwill credit can cost g1t. */
842 overageForgiveCostMicros?: number;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put843};
844
845/**
846 * A workspace's trial credit: one grant per workspace, made the first time
847 * it uses something, out of a pool that resets each calendar month. Mirrors
848 * `Trial` in `crates/contracts/src/billing.rs`.
849 */
Deploy scripts live in the repository850export type Trial = {
851 open: boolean;
852 usedMicros: number;
853 limitMicros: number;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put854 /** No longer used: trials do not end on a date. */
Deploy scripts live in the repository855 endsAt: string | null;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put856 /** Why it is closed: `off`, `used` (this workspace's grant is spent) or `pool` (this month's are given out). */
Deploy scripts live in the repository857 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 put858 /** Whether the workspace has its grant already. */
859 granted?: boolean;
860 /** With `pool`: when new trials start again, the first of next month. */
861 waitsUntil?: string | null;
Deploy scripts live in the repository862};
863
864/**
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.865 * What a workspace has: the g1t plan (`plan`), and Security and quality
866 * (`security`), which comes with the plan at no price of its own. Deployments
867 * are part of the plan too; `has_feature` for either answers whether the
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar868 * workspace has the plan. Mirrors `Feature` in `crates/contracts/src/billing.rs`.
Deploy scripts live in the repository869 */
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar870export type Feature = "plan" | "deployments" | "security";
Deploy scripts live in the repository871
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas872/**
873 * What deployments cost g1t, in millionths of a dollar: fallbacks for when
874 * billing's price book cannot be read. Not an allowance: on the plan every
875 * unit is metered from the first, at cost plus 20%, and drawn from the
876 * plan's included usage first. Projects, previews and the apps behind them
877 * are not metered at all. Mirrors `deployment_costs`.
878 */
879export const DEPLOYMENT_COSTS = {
Deploy scripts live in the repository880 microsPerMillionRequests: 300_000,
881 microsPerMillionCpuMs: 20_000,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas882 /** 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 look883 microsPerBuildSecond: 15,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas884 /** One custom domain for a month. */
Agents and memory, checks and conflicts, profiles, slug renames, custom domains885 microsPerDomainMonth: 100_000,
Deploy scripts live in the repository886} as const;
887
888export type FeaturePlan = {
889 feature: Feature;
890 title: string;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person891 /** Charged every month while the plan is on, in cents, excluding tax. */
Deploy scripts live in the repository892 monthlyCents: number;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person893 /** The card processing fee on top each month, in cents (0 when off), excluding tax. */
894 cardFeeCents?: number;
Deploy scripts live in the repository895 /** What the price includes, one line each. */
896 includes: string[];
897 /** How usage past the allowance is charged. */
898 overage: string;
899};
900
901export type SubscriptionStatus = "active" | "canceling" | "past_due" | "canceled";
902
903export type Subscription = {
904 feature: Feature;
905 status: SubscriptionStatus;
906 /** RFC 3339: when the period paid for ends. */
907 periodEnd: string | null;
908 startedBy: string;
909 startedAt: string;
910};
911
912/** A feature as a workspace sees it. */
913export type FeatureState = {
914 plan: FeaturePlan;
915 subscription: Subscription | null;
916 /** Whether the feature works for the workspace now. */
917 on: boolean;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put918 /** On without a plan: comped terms, or given by g1t. Nothing to pay or turn off. */
919 included?: boolean;
Deploy scripts live in the repository920};
921
922export interface BillingApi {
923 status(): Promise<BillingStatus>;
924 /** Members of the workspace only. */
925 account(workspace: string, viewer: Viewer): Promise<Result<BillingAccount>>;
926 /** Newest first. Members of the workspace only. */
927 ledger(workspace: string, viewer: Viewer): Promise<Result<LedgerEntry[]>>;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging928 /** Credits from g1t, newest first, with what is left of each. Members only. */
929 credits(workspace: string, viewer: Viewer): Promise<Result<Credits>>;
The statement is a month at a time, a line per kind of charge930 /** A month of the ledger, grouped by `day` (default) or `project`. Members only. */
931 statement(workspace: string, viewer: Viewer, month?: string | null, group?: "day" | "project"): Promise<Result<Statement>>;
932 /** One statement line's entries, 50 at a time; `before` is the last id seen. */
933 statementEntries(
934 workspace: string,
935 viewer: Viewer,
936 filter: { month: string; kind: string; day?: string | null; project?: string | null; before?: string | null },
937 ): Promise<Result<LedgerEntry[]>>;
Deploy scripts live in the repository938 /** What the workspace's agents cost since `since`, broken down. Members only. */
939 usage(workspace: string, viewer: Viewer, since: string): Promise<Result<Usage>>;
940 /**
Mission control shows model usage, yours and the workspace's: tokens, cost, active days, cache share, each day, and the mix941 * The model tokens the workspace's runs used, day by day over the last
942 * `days` (42, at most 366), for everyone or for one `person`. Members
943 * only; a member may ask only for themselves, an owner for anyone.
944 */
945 tokenUsage(workspace: string, viewer: User, options?: { person?: string; days?: number }): Promise<Result<TokenUsage>>;
946 /**
947 * What one model answer used, added to its run's count for the day. The
948 * model proxy sends it; for usage views only, as runs are priced from AI
949 * Gateway. False when there was nothing to count.
950 */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens951 /** What the AI Gateway offers on g1t's key, with prices per million tokens. */
952 gatewayModels(): Promise<GatewayModel[]>;
Merge branch 'main' into actions-toolkit-oidc-artifacts953 /** Every purpose's default model as it applies now, and each job's tier and effort. */
954 modelDefaults(): Promise<ModelDefaults>;
955 /** What one provider lists now, from the models service's discovery. */
956 recordDiscovery(provider: string, models: ProviderModel[], by: string, error?: string | null): Promise<DiscoveryResult>;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens957 /**
958 * Whether a workspace's next AI Gateway request may go to g1t's models:
959 * fails with `payment_required` and what to do when it is over its spend
960 * limit, out of AI credit, or not on the plan.
961 */
962 gatewayAdmit(workspace: string): Promise<Result<boolean>>;
963 /** Logs one AI Gateway request, and charges it when it used tokens on g1t's models. */
964 recordGateway(record: GatewayRecord): Promise<Result<boolean>>;
965 /** A workspace's recent AI Gateway requests, newest first. Members only. */
966 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 mix967 recordTokens(usage: {
968 workspace: string;
969 /** The model session's id, one per run. */
970 session: string;
971 /** The person the run is for, by username. */
972 person?: string | null;
973 model: string;
Merge branch 'model-routing'974 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 mix975 input: number;
976 output: number;
977 cacheRead: number;
978 cacheWrite: number;
979 }): Promise<Result<boolean>>;
980 /**
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look981 * Prepays usage ($25 at least) and returns the page to send the person to:
982 * by card with 3-D Secure, or by bank transfer from $1,000. Owners only.
983 * The payment's id comes back to `returnUrl` as `session`.
Deploy scripts live in the repository984 */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look985 checkout(
986 actor: User,
987 workspace: string,
988 amountCents: number,
989 returnUrl: string,
990 method?: "card" | "bank_transfer",
991 ): Promise<Result<{ url: string }>>;
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace992 /**
993 * Stripe's hosted billing page for the workspace: card, invoices, billing
994 * email and address. g1t never handles card numbers. Owners only.
995 */
996 billingPortal(actor: User, workspace: string, returnUrl: string): Promise<Result<{ url: string }>>;
Deploy scripts live in the repository997 /** Credits a payment once the processor says it was made. Safe to repeat. */
998 confirm(workspace: string, viewer: Viewer, session: string): Promise<Result<BillingAccount>>;
999 /**
1000 * Whether a workspace may start an agent now, asked before anything is
1001 * opened for it. A failure, with the reason to show, when it has no credit.
1002 */
1003 canStart(workspace: string): Promise<Result<boolean>>;
1004 /** A workspace's free allowance on g1t's hosted models; `exempt` are open to them anyway. */
1005 trial(workspace: string, exempt: string[]): Promise<Trial>;
1006 /**
1007 * Asks whether a workspace may start an agent and opens the run it will be
1008 * charged for. Null when billing is off; a failure when there is no credit.
1009 */
1010 /** Every paid feature and the workspace's plan for each. Members only. */
1011 features(workspace: string, viewer: Viewer): Promise<Result<FeatureState[]>>;
1012 /**
1013 * Starts the card page for a feature's monthly plan. Owners only. The
1014 * page's id comes back to `returnUrl` as `session`.
1015 */
1016 subscribe(actor: User, workspace: string, feature: Feature, returnUrl: string): Promise<Result<{ url: string }>>;
1017 /** Turns the feature on once the plan is paid for. Safe to repeat. */
1018 confirmSubscription(workspace: string, viewer: Viewer, session: string): Promise<Result<FeatureState>>;
1019 /** Ends a plan at the end of its period, or (`resume`) takes that back. Owners only. */
1020 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 person1021 /** Which of the workspaces are free (on no paid plan); none where payments are not set up. */
1022 freeWorkspaces(workspaces: string[]): Promise<string[]>;
Deploy scripts live in the repository1023 /** Whether a feature works for a workspace now; a failure with the reason when not. */
1024 hasFeature(workspace: string, feature: Feature): Promise<Result<boolean>>;
1025 /**
1026 * Usage past a plan's allowance, charged from credit at cost plus the
1027 * margin, once per `reference`. False if it was charged before.
1028 */
1029 chargeFeature(charge: {
1030 workspace: string;
1031 feature: Feature;
1032 costMicros: number;
1033 description: string;
1034 repo?: string | null;
1035 reference: string;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put1036 /** For a build: how long it ran, so the plan's included build time pays for what it can. */
1037 buildSeconds?: number | null;
Deploy scripts live in the repository1038 }): Promise<Result<boolean>>;
Prices keep themselves current with what g1t pays1039 /**
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put1040 * What a source cost g1t so far this month, so the workspace's limit
1041 * counts it now. Replaces the last report. Billing charges `context`
1042 * and `security` itself once the month is over; `deployments` charges
1043 * its own.
Prices keep themselves current with what g1t pays1044 */
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1045 notePending(
1046 workspace: string,
1047 source: "deployments" | "domains" | "context" | "security",
1048 costMicros: number,
1049 /** How much of it, for the Billing page: `1.2 million requests and 3.4 million CPU ms`. */
1050 detail?: string | null,
1051 ): Promise<boolean>;
1052 /**
1053 * This month's usage, one line per kind of meter, at what it is charged
1054 * before the plan's included usage or a pool paid for it. Members only.
1055 */
1056 usageMeters(workspace: string, viewer: Viewer): Promise<Result<MeterUsage[]>>;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1057 /** 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 put1058 entitlements(workspace: string): Promise<Entitlements>;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1059 /**
1060 * Holds a start's estimated cost before the work starts. A failure's code says why not:
1061 * `paused`, `limit`, `not_paid`, `trial_used` or `oss_pool_empty`, with a message for the owner.
1062 */
1063 reserve(reservation: {
1064 workspace: string;
1065 repo: RepoPath;
1066 public: boolean;
1067 kind: ComputeKind;
1068 /** The most the work is expected to cost g1t, before the margin. */
1069 estimateMicros: number;
1070 }): Promise<Result<ReservationHeld>>;
1071 /** Releases a reservation's hold with what the work cost g1t, before the margin. Safe to repeat. */
1072 settle(reservationId: string, actualMicros: number): Promise<Result<boolean>>;
1073 /** Stripe's page to save and verify a card (3-D Secure, never charged). Owners only. */
1074 cardCheck(actor: User, workspace: string, returnUrl: string): Promise<Result<{ url: string }>>;
1075 /** Records the card check once Stripe says it passed, and grants the trial if it can. Safe to repeat. */
1076 confirmCardCheck(workspace: string, viewer: Viewer, session: string): Promise<Result<Entitlements>>;
1077 /** An owner asks for a higher limit, or for help with usage past what was meant. */
1078 requestLimit(
1079 actor: User,
1080 workspace: string,
1081 request: { kind: "limit" | "overage"; amountMicros: number; reason: string; expectedMonthlyMicros: number },
1082 ): Promise<Result<LimitRequest>>;
1083 /** The workspace's requests and their answers, newest first. Members only. */
1084 limitRequests(workspace: string, viewer: Viewer): Promise<Result<LimitRequest[]>>;
1085 /**
1086 * The owners' own caps on agents: one run's spend ($0.10 to $100) and one issue's ($1 to $1,000).
1087 * Null goes back to the default ($2 and $10). A cap staff set wins. Owners only.
1088 */
1089 setCaps(actor: User, workspace: string, caps: { runCapMicros: number | null; issueCapMicros: number | null }): Promise<Result<Entitlements>>;
1090 /** An owner's answer to a spend spike: keep going for 24 hours, or stop. */
1091 confirmSpike(actor: User, workspace: string, keepGoing: boolean): Promise<Result<Entitlements>>;
Prices keep themselves current with what g1t pays1092 /** Every metered price and the recent changes. Public. */
1093 prices(): Promise<PriceBook>;
Usage limits: unpaid usage can only go so far1094 /** A workspace's limit, for its members. */
1095 limit(workspace: string, viewer: Viewer): Promise<Result<Limit>>;
1096 /** The same, for the services that enforce it. */
1097 checkLimit(workspace: string): Promise<Result<Limit>>;
Every sandbox is metered by the second1098 /**
Two limits, real invoices, trust that grows by itself, sales signals1099 * The owners' own monthly limit, up to what is available; null goes back
1100 * to the default, and `useFullLimit` uses everything available. Owners only.
1101 */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1102 setSpendLimit(
1103 actor: User,
1104 workspace: string,
1105 spendLimitMicros: number | null,
1106 useFullLimit?: boolean,
1107 /** Use the one-time raise: up to twice the highest ceiling, once per workspace. */
1108 raiseOnce?: boolean,
1109 ): Promise<Result<Limit>>;
Two limits, real invoices, trust that grows by itself, sales signals1110 /** The workspace's invoices from g1t, newest first. Members only. */
1111 invoices(workspace: string, viewer: Viewer): Promise<Result<WorkspaceInvoice[]>>;
1112 /**
Every sandbox is metered by the second1113 * How long a sandbox ran for a workspace, reported when it stops. Its
Prices are what g1t pays plus 20%, from the first second1114 * cost is recorded and every second is charged, from the first. False if
1115 * `reference` was recorded before.
Every sandbox is metered by the second1116 */
1117 recordSandbox(usage: {
1118 workspace: string;
1119 seconds: number;
1120 description: string;
1121 repo?: string | null;
1122 reference: string;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1123 /** What ran; checks, workflows and the merge queue on public repositories may use the open-source pool. */
1124 kind?: ComputeKind | null;
1125 /** vCPU-seconds used, when the sandbox can tell: the run is priced on its own CPU. */
1126 cpuSeconds?: number | null;
1127 /** The reservation it started under, settled with this cost. */
1128 reservationId?: string | null;
Fast pages, required checks on the branch, self-hosted runners, honest incidents1129 /** It ran on one of the workspace's self-hosted runners: its minutes go on usage at $0. */
1130 selfHosted?: boolean;
1131 /** The machine it ran on, by label (`g1t-4core`); absent, the standard one. */
1132 instance?: string | null;
Spend adds up on one ledger. Charged this month has one definition, price less discount, included usage and credit, shared by the plan card, the spend limit, Spend and the top bar; the limit had counted usage not yet closed at full price before the discount, so a comped workspace read as charged a cent. Every agent line on the ledger names the agent and who asked, repository runs by g1t included, so Spent is the sum of its products, Agents is the agent product, and by agent adds up to it; the billing API returns by_agent and by_person. The usage and billing guide says how spend is counted.1133 /** The agent whose work this was, by handle (`g1t` for g1t's own runs on a repository); absent for checks, workflows and builds. */
1134 agent?: string | null;
1135 /** Who asked for the work, by username. */
1136 askedBy?: string | null;
Every sandbox is metered by the second1137 }): Promise<Result<boolean>>;
Deploy scripts live in the repository1138 startRun(run: {
1139 workspace: string;
1140 repo: RepoPath;
1141 number: number;
1142 task: string;
1143 model: string;
1144 /** `workspace` when the run uses the workspace's own model provider. */
1145 billedTo?: "g1t" | "workspace";
Merge branch 'model-routing'1146 /**
1147 * The model session's id: the run is settled at AI Gateway's price by
1148 * it, and on the workspace's own provider its tokens are counted under
1149 * it for the agent rate.
1150 */
Prices keep themselves current with what g1t pays1151 session?: string | null;
Merge branch 'model-routing'1152 /** The tier g1t routed the run to: `small`, `large` or `frontier`. */
1153 tier?: "small" | "large" | "frontier" | null;
Spend adds up on one ledger. Charged this month has one definition, price less discount, included usage and credit, shared by the plan card, the spend limit, Spend and the top bar; the limit had counted usage not yet closed at full price before the discount, so a comped workspace read as charged a cent. Every agent line on the ledger names the agent and who asked, repository runs by g1t included, so Spent is the sum of its products, Agents is the agent product, and by agent adds up to it; the billing API returns by_agent and by_person. The usage and billing guide says how spend is counted.1154 /** The agent doing the work, by handle: a workspace agent's, or `g1t` for g1t's own work on a repository. Every line of the run carries it. */
1155 agent?: string | null;
1156 /** Who asked, by username; none for a routine's or another agent's work. */
1157 askedBy?: string | null;
Deploy scripts live in the repository1158 }): Promise<Result<RunTicket | null>>;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1159 /** Usage over a range of days (`YYYY-MM-DD`, both included), at price, by product, meter, project and day. Members only. */
1160 usageReport(
1161 workspace: string,
1162 viewer: Viewer,
1163 range: { from: string; until: string; products?: string[]; projects?: string[] },
1164 ): Promise<Result<UsageReport>>;
1165 /** The workspace's prepaid AI credit, auto-reload and prices. Members only. */
1166 aiCredit(workspace: string, viewer: Viewer): Promise<Result<AiCredit>>;
1167 /** 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`. */
1168 buyAiCredit(actor: User, workspace: string, amountCents: number, returnUrl: string): Promise<Result<{ url: string }>>;
1169 /** Credits a purchase once Stripe says it was paid, once. Safe to repeat. */
1170 confirmAiCredit(workspace: string, viewer: Viewer, session: string): Promise<Result<AiCredit>>;
1171 /** Auto-reload's settings. Owners only. */
1172 setAiReload(
1173 actor: User,
1174 workspace: string,
1175 reload: { enabled: boolean; thresholdMicros: number; targetMicros: number; monthlyMaxMicros: number },
1176 ): Promise<Result<AiCredit>>;
1177 /** The monthly budget: the spend limit, its alerts, whether usage pauses at 100%, and a webhook. Owners only. */
1178 setBudget(
1179 actor: User,
1180 workspace: string,
1181 budget: { amountMicros: number | null; alerts: number[]; pauseAtLimit: boolean; webhook: string | null; keepLimit?: boolean },
1182 ): Promise<Result<Limit>>;
1183 /** Invoice details from the Stripe customer, the default payment method, invoices and the next invoice. Members only. */
1184 billingDetails(workspace: string, viewer: Viewer): Promise<Result<BillingDetails>>;
1185 /** Saves invoice details on the Stripe customer; absent fields stay, empty clears. Owners only. */
1186 setBillingDetails(actor: User, workspace: string, details: BillingDetailsInput): Promise<Result<BillingDetails>>;
Deploy scripts live in the repository1187}
1188
1189
1190/** One slice of usage: what it was for, what it cost, how many runs. */
1191export type UsageSlice = { key: string; micros: number; runs: number };
1192
Mission control shows model usage, yours and the workspace's: tokens, cost, active days, cache share, each day, and the mix1193/** The model tokens runs used over a window of days. */
1194export type TokenUsage = {
1195 /** `YYYY-MM-DD`, the first day counted. */
1196 since: string;
1197 /** The window's length: 42 unless asked, 366 at most. */
1198 days: number;
1199 /** Null for the whole workspace. */
1200 person: string | null;
1201 totalTokens: number;
1202 inputTokens: number;
1203 outputTokens: number;
1204 cacheReadTokens: number;
1205 cacheWriteTokens: number;
1206 /** What those runs were charged, as `usage` measures it. */
1207 costMicros: number;
1208 /** Days in the window with any tokens. */
1209 activeDays: number;
1210 /** Every day in the window, oldest first, zeros included. */
1211 byDay: { day: string; tokens: number }[];
1212};
1213
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1214// --- AI Gateway -------------------------------------------------------------
1215
1216/** A model the AI Gateway offers on g1t's key, with its prices per million tokens. */
1217export type GatewayModel = {
AI Gateway: OpenAI's format, open models, and your own providers1218 /**
1219 * The provider's own id, such as `claude-sonnet-5-5` or
1220 * `@cf/openai/gpt-oss-120b`. A request names it as it is or with its
1221 * provider in front (`anthropic/claude-sonnet-5-5`).
1222 */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1223 model: string;
1224 /** For people: `Claude Sonnet 5.5`. */
1225 name: string;
AI Gateway: OpenAI's format, open models, and your own providers1226 /** `anthropic` or `workers-ai`. */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1227 provider: string;
AI Gateway: OpenAI's format, open models, and your own providers1228 /** `chat`, or `embeddings` for a model that only embeds text. */
1229 kind?: "chat" | "embeddings";
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1230 inputMicros: number;
1231 outputMicros: number;
1232 cacheReadMicros: number;
AI Gateway: OpenAI's format, open models, and your own providers1233 /** Cache writes that live five minutes. */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1234 cacheWriteMicros: number;
AI Gateway: OpenAI's format, open models, and your own providers1235 /** Cache writes that live an hour. */
1236 cacheWrite1hMicros?: number;
1237 /**
1238 * Priced by the prompt's length: a request whose prompt (input, cache
1239 * read and cache write tokens) is longer than this is charged entirely at
1240 * the `over` prices. 0 or absent for one price.
1241 */
1242 threshold?: number;
1243 overInputMicros?: number;
1244 overOutputMicros?: number;
1245 overCacheReadMicros?: number;
1246 overCacheWriteMicros?: number;
1247 overCacheWrite1hMicros?: number;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1248};
1249
Merge branch 'main' into actions-toolkit-oidc-artifacts1250// --- The model catalogue ------------------------------------------------------
1251
1252/** Where a model stands: only `available` ones are routed to. */
1253export type ModelStatus = "available" | "new" | "deprecated" | "retired";
1254
1255/** One model in g1t's catalogue: its prices and what g1t knows about it. */
1256export type CatalogueModel = GatewayModel & {
1257 /** Other ids the provider lists it by, such as a dated one. */
1258 aliases: string[];
1259 family: string;
1260 /** The agent tier it suits: `small`, `large`, `frontier`, or empty. */
1261 tierHint: string;
1262 contextWindow: number;
1263 maxOutput: number;
1264 /** Any of `effort`, `thinking`, `tools`, `vision`, `embeddings`. */
1265 capabilities: string[];
1266 dimensions: number;
1267 status: ModelStatus;
1268 /** Its prices are known. An unpriced model is never routed to, offered or charged for. */
1269 priced: boolean;
1270 source: "discovered" | "staff";
1271 firstSeenAt: string | null;
1272 lastSeenAt: string | null;
1273 missingSince: string | null;
1274 approvedBy: string | null;
1275 approvedAt: string | null;
1276 note: string;
1277 /** A typical agent run on it, in millionths of a dollar; 0 when unpriced or embeddings. */
1278 typicalRunMicros: number;
1279};
1280
1281/** One model as its provider lists it, from the models service's discovery. */
1282export type ProviderModel = {
1283 id: string;
1284 name: string;
1285 /** `chat`, `embeddings`, or anything else (counted as listed, never added). */
1286 kind: string;
1287 contextWindow: number;
1288 maxOutput: number;
1289 capabilities: string[];
1290 /** Workers AI lists a price per million tokens; Anthropic does not. */
1291 price: { inputMicros: number; outputMicros: number } | null;
1292};
1293
1294/** What one check of a provider found. */
1295export type DiscoveryResult = {
1296 provider: string;
1297 checkedAt: string;
1298 by: string;
1299 listed: number;
1300 added: string[];
1301 deprecated: string[];
1302 restored: string[];
1303 error: string | null;
1304};
1305
1306/** The purposes a default model is chosen for. */
1307export type ModelPurpose = "tier_small" | "tier_large" | "tier_frontier" | "background" | "gateway_first";
1308
1309/** One purpose's default, as staff last set it. */
1310export type ModelDefault = {
1311 /** A `ModelPurpose`, or `job_<kind>`. */
1312 purpose: string;
1313 model: string | null;
1314 /** For a job: `small`, `large`, `frontier` or `change`. */
1315 tier: string | null;
1316 effort: string | null;
1317 updatedAt: string;
1318 updatedBy: string;
1319 reason: string;
1320};
1321
1322/** A model purpose's default as it applies now. */
1323export type ResolvedModel = {
1324 purpose: string;
1325 chosen: string;
1326 /** The model to use; null when nothing suits (callers keep their own fallback). */
1327 model: GatewayModel | null;
1328 capabilities: string[];
1329 /** Why it is not the chosen model, in a sentence. */
1330 note: string | null;
1331};
1332
1333/** One kind of agent job's starting tier and effort. */
1334export type JobDefault = { kind: string; tier: string; effort: string | null };
1335
1336/** Every purpose's model as it applies now, and each job's tier and effort. */
1337export type ModelDefaults = { models: ResolvedModel[]; jobs: JobDefault[] };
1338
1339/** One check of one provider. */
1340export type ModelCheck = {
1341 id: string;
1342 provider: string;
1343 checkedAt: string;
1344 by: string;
1345 listed: number;
1346 added: string[];
1347 deprecated: string[];
1348 error: string | null;
1349};
1350
1351/** The tokens of the typical agent run estimates are priced from. */
1352export type TypicalRun = { requests: number; input: number; output: number; cacheRead: number; cacheWrite: number };
1353
1354/** sudo's Agents & models. */
1355export type AdminModels = {
1356 catalogue: CatalogueModel[];
1357 defaults: ModelDefault[];
1358 resolved: ModelDefaults;
1359 checks: ModelCheck[];
1360 typical: TypicalRun;
1361};
1362
1363/** A model's prices as staff confirm them, per million tokens in millionths of a dollar. */
1364export type ModelPrices = {
1365 inputMicros: number;
1366 outputMicros: number;
1367 cacheReadMicros: number;
1368 cacheWriteMicros: number;
1369 cacheWrite1hMicros: number;
1370 threshold: number;
1371 overInputMicros: number;
1372 overOutputMicros: number;
1373 overCacheReadMicros: number;
1374 overCacheWriteMicros: number;
1375 overCacheWrite1hMicros: number;
1376};
1377
1378/** The models service's `Discovery` entrypoint, for sudo's "Check for new models". */
1379export interface ModelDiscoveryApi {
1380 /** Lists every provider's models now and records what changed: one result per provider. */
1381 check(by: string): Promise<DiscoveryResult[]>;
1382}
1383
AI Gateway: OpenAI's format, open models, and your own providers1384/** The format a gateway request was sent in. */
1385export type GatewayFormat = "anthropic" | "openai";
1386
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1387/** One AI Gateway request, as the model proxy reports it to billing. */
1388export type GatewayRecord = {
1389 /** `gw_…`, chosen by the proxy; recording it twice records it once. */
1390 id: string;
1391 workspace: string;
1392 tokenId: string;
1393 tokenName?: string | null;
1394 model: string;
1395 input: number;
1396 output: number;
1397 cacheRead: number;
AI Gateway: OpenAI's format, open models, and your own providers1398 /** Every cache write, of either lifetime. */
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1399 cacheWrite: number;
AI Gateway: OpenAI's format, open models, and your own providers1400 /** Of `cacheWrite`, those that live an hour. */
1401 cacheWriteHour?: number;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1402 /** The HTTP status the caller was answered with. */
1403 status: number;
1404 /** On the workspace's own provider key: counted, never charged. */
1405 ownKey: boolean;
AI Gateway: OpenAI's format, open models, and your own providers1406 format: GatewayFormat;
1407 /**
1408 * Who served it: `anthropic` or `workers-ai` on g1t's key, the
1409 * connection's provider on the workspace's own. Empty when it never got
1410 * that far.
1411 */
1412 provider: string;
1413 /** On the workspace's own provider: the connection's name. */
1414 connection?: string | null;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1415 streamed: boolean;
1416 durationMs: number;
1417 error?: string | null;
1418};
1419
1420/** One AI Gateway request, as its log keeps it. */
1421export type GatewayRequest = {
1422 id: string;
1423 createdAt: string;
1424 model: string;
1425 tokenId: string;
1426 tokenName: string | null;
1427 input: number;
1428 output: number;
1429 cacheRead: number;
1430 cacheWrite: number;
AI Gateway: OpenAI's format, open models, and your own providers1431 /** Of `cacheWrite`, those that live an hour. */
1432 cacheWriteHour: number;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1433 /** What the tokens cost at the model's price. */
1434 costMicros: number;
1435 /** What the workspace was charged, before included usage and credit paid for it; 0 on its own key. */
1436 chargedMicros: number;
1437 status: number;
1438 ownKey: boolean;
AI Gateway: OpenAI's format, open models, and your own providers1439 format: GatewayFormat;
1440 /** `anthropic` or `workers-ai` on g1t's key; the connection's provider on the workspace's own. */
1441 provider: string;
1442 /** On the workspace's own provider: the connection's name. */
1443 connection: string | null;
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1444 streamed: boolean;
1445 durationMs: number;
1446 error: string | null;
1447};
1448
1449/** A page of AI Gateway requests, newest first. */
1450export type GatewayRequests = {
1451 requests: GatewayRequest[];
1452 /** The `before` for the next page, when there is one. */
1453 next: string | null;
1454 /** How many days requests are kept. */
1455 retentionDays: number;
1456};
1457
Deploy scripts live in the repository1458/** What a workspace's agents cost over a period. */
1459export type Usage = {
1460 since: string;
1461 /** Charged, including g1t's margin. */
1462 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 charged1463 /** 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 for1464 coveredMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1465 /** What the account's discount took off the price; usage at price is spent + covered + this. */
1466 discountMicros?: number;
1467 /** The account's discount now, in percent; with one, the slices are at price. */
1468 discountPercent?: number | null;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1469 /** Usage at price: spent + covered + discount, from the same ledger lines. The one usage figure every page shows. */
1470 priceMicros?: number;
Deploy scripts live in the repository1471 /** What g1t's model provider charged, before the margin. */
1472 costMicros: number;
1473 /** What runs on the workspace's own provider cost there, estimated. Not charged by g1t. */
1474 providerMicros: number;
1475 /** What the runs used, at cost: g1t's models and the workspace's own provider together. */
1476 usedMicros: number;
1477 /** g1t charges nothing for now; the slices then measure usage at cost. */
1478 free: boolean;
1479 runs: number;
1480 /** Spend per day and task, keyed `YYYY-MM-DD/task`. */
1481 byDay: UsageSlice[];
1482 byTask: UsageSlice[];
1483 byRepo: UsageSlice[];
1484 /** Keyed `namespace/name#number`. */
1485 byPull: UsageSlice[];
1486 byModel: UsageSlice[];
1487 /** Credit bought in the period. */
1488 addedMicros: number;
1489};
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1490
1491/** One of g1t's products (a "bucket") on one day. Money in micros. */
1492export type CostDay = { day: string; bucket: string; cfCostMicros: number; ownCostMicros: number; valueMicros: number; cashMicros: number };
1493
1494/** One product over the range: what customers were charged at price against what it cost. */
1495export type ProductMargin = {
1496 bucket: string;
1497 title: string;
1498 /** Cloudflare's bill, or g1t's own figure where Cloudflare does not bill it (`costSource`). */
1499 costMicros: number;
1500 cfCostMicros: number;
1501 ownCostMicros: number;
1502 valueMicros: number;
1503 marginMicros: number;
1504 marginPercent: number | null;
1505 costSource: "cloudflare" | "ledger" | string;
1506 /** Running g1t, paid for by the plan. */
1507 overhead: boolean;
1508};
1509
1510/** 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 it1511export type OverallMargin = {
1512 usageMicros: number;
1513 plansMicros: number;
1514 costMicros: number;
1515 marginMicros: number;
1516 marginPercent: number | null;
1517 /** Of costMicros, what went on usage g1t gave away on purpose: comped workspaces, free periods, the trial and the open-source pool. */
1518 givenMicros?: number;
1519 /** Money in against costMicros - givenMicros. */
1520 soldMarginMicros?: number;
1521 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 running1522 /** Usage sold: usageMicros against what that usage cost, less what was given. */
1523 usageCostMicros?: number;
1524 usageMarginMicros?: number;
1525 usageMarginPercent?: number | null;
1526 /** Running g1t: plansMicros against the platform's cost, less its given share. */
1527 runningCostMicros?: number;
1528 /** Cost no mapping names, less its given share. */
1529 unmappedCostMicros?: number;
1530 /** givenMicros by why. Free is free periods, free allowances and overruns g1t covered. */
1531 givenCompedMicros?: number;
1532 givenFreeMicros?: number;
1533 givenTrialMicros?: number;
1534 givenPoolMicros?: number;
Merge branch 'worktree-agent-a633ac0f7f66d419d'1535 /** What discounts on an account's terms took below cost plus the margin: given, not margin lost. */
1536 givenDiscountMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1537 /** Credits from g1t spent on usage, by kind: given, never money in. Refunds come off money in instead. */
1538 givenCreditPromotionalMicros?: number;
1539 givenCreditGoodwillMicros?: number;
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb971540 /** What testing resets wiped that g1t paid for: the usage still happened, so its cost is given, never a leak. */
1541 givenResetMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1542 /** Credits over the range: given (every kind), spent on usage, and refunds' money given back. */
1543 creditsGivenMicros?: number;
1544 creditsUsedMicros?: number;
1545 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 running1546 /** 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)1547 /** What the plan's included usage paid for, at price: money in for usage, paid out of plansMicros. */
1548 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 running1549 cloudflareCostMicros?: number;
1550 modelsCostMicros?: number;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person1551 /** Tax collected with payments over the range, net of refunds: owed to tax authorities, never cash or revenue. */
1552 taxCollectedMicros?: number;
1553 /** Card processing fees passed on with card payments, net of refunds: they pay Stripe's fee, not revenue. */
1554 cardFeesMicros?: number;
Merge Cloudflare's usage over its billing cycle: every page read, included amounts once a cycle, a projection, test-mode charges never money in (billing 0052)1555 /** What workspaces were charged while payments were not live (Stripe's test mode): given, never money in. */
1556 givenUnpaidMicros?: number;
1557 /** Cloudflare's subscriptions over the range: each day's share of the billing cycle it is in. */
1558 subscriptionsMicros?: number;
1559 /** What AI Gateway priced g1t's own provider traffic at over the range, beside the ledger's model cost. */
1560 gatewayCostMicros?: number;
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1561};
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1562
1563/** A count, cost or leak that does not add up. */
1564export type CostDrift = {
1565 bucket: string;
1566 title: string;
1567 kind: "count" | "cost" | "leak" | string;
1568 ours: number;
1569 cloudflare: number;
1570 deltaPercent: number | null;
1571 detail: string;
1572 foundAt: string;
1573};
1574
1575export type MarginAlert = {
1576 id: string;
1577 kind: "margin" | "overall" | "leak" | "drift" | "workspace" | string;
1578 /** The product, or the workspace. */
1579 subject: string;
1580 detail: string;
1581 since: string;
1582 openedAt: string;
1583 emailedAt: string | null;
1584};
1585
1586/** A change to a price, measured from what Cloudflare charged. */
1587export type PriceProposal = {
1588 id: string;
1589 meter: string;
1590 title: string;
1591 unit: string;
1592 currentCostMicros: number;
1593 proposedCostMicros: number;
1594 changePercent: number;
1595 markupPercent: number;
1596 reason: string;
1597 source: "keeper" | "reconciler" | string;
1598 /** Far off the current cost: look before approving. */
1599 suspect: boolean;
1600 status: "open" | "applied" | "approved" | "rejected" | "superseded" | string;
1601 createdAt: string;
1602 decidedAt: string | null;
1603 decidedBy: string | null;
1604 note: string | null;
1605 effectiveAt: string | null;
1606};
1607
1608/** One version of one meter's price; never changed once written. */
1609export type PriceVersion = {
1610 id: string;
1611 meter: string;
1612 version: number;
1613 costMicros: number;
1614 markupPercent: number;
1615 priceMicros: number;
1616 effectiveAt: string;
1617 reason: string;
1618 createdBy: string;
1619 appliedAt: string | null;
Merge costs and margin review: gateway query, own spend, discount meters, superseded rises1620 /**
1621 * What `costMicros` is: `cost`, what g1t pays for a unit; `rate`, a price
1622 * g1t sets with no cost behind it (the agent rate), so it is no cost;
1623 * `weight`, a multiplier in millionths, not money. Absent from older
1624 * billing: read as `cost`.
1625 */
1626 basis?: "cost" | "rate" | "weight" | "";
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1627};
1628
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's1629/** 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 sold1630export 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's1631
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1632export 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 daily1633
1634export type CostLineSummary = {
1635 product: string;
1636 meter: string;
1637 rawName: string;
1638 unit: string;
1639 source: string;
1640 quantity: number;
1641 costMicros: number;
1642 /** Absent when no mapping claims it. */
1643 bucket: string | null;
1644};
1645
1646export type CostMapping = {
1647 product: string;
1648 meter: string;
1649 bucket: string;
1650 priceMeter: string | null;
1651 ownMeter: string | null;
1652 scaleToOwn: boolean;
1653 driftPercent: number;
1654 note: string;
1655 updatedAt: string;
1656 updatedBy: string;
1657};
1658
1659export type CostMappingInput = {
1660 product: string;
1661 meter: string;
1662 bucket?: string;
1663 priceMeter?: string | null;
1664 ownMeter?: string | null;
1665 scaleToOwn?: boolean;
1666 driftPercent?: number | null;
1667 note?: string;
1668 remove?: boolean;
1669};
1670
1671export type CostSettings = {
1672 autoApply: boolean;
1673 autoApplyPercent: number;
1674 noticeDays: number;
1675 marginFloorPercent: number;
1676 alertDays: number;
1677 minDailyCostMicros: number;
1678 anomalyFactor: number;
1679 anomalyFloorMicros: number;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1680 /** Pass Stripe's card fee on as its own line when AI credit is bought by card. */
1681 cardFee: boolean;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1682};
1683
1684export type CostsReport = {
1685 configured: boolean;
1686 fetchedAt: string | null;
1687 since: string;
1688 until: string;
1689 days: CostDay[];
1690 products: ProductMargin[];
1691 overall: OverallMargin;
1692 drift: CostDrift[];
1693 alerts: MarginAlert[];
1694 proposals: PriceProposal[];
1695 versions: PriceVersion[];
1696 topWorkspaces: WorkspaceCost[];
1697 lines: CostLineSummary[];
1698 mappings: CostMapping[];
1699 settings: CostSettings;
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1700 /** g1t's own spend against its two caps. */
1701 caps: SpendCaps;
Merge Cloudflare's usage over its billing cycle: every page read, included amounts once a cycle, a projection, test-mode charges never money in (billing 0052)1702 /** Cloudflare's current billing cycle: usage cost so far by meter, and the projection. Absent until the bill is read. */
1703 cycle?: CloudflareCycle | null;
1704 /** The last read of Cloudflare's billable usage: what came back. */
1705 billRead?: BillRead | null;
1706 /** Of the range's cost, what no workspace's usage could carry: running g1t, attributed to no one. */
1707 unattributedMicros?: number;
1708};
1709
1710/** Cloudflare's billing cycle, as its Billable usage page shows it. */
1711export type CloudflareCycle = {
1712 /** First and last days, YYYY-MM-DD, UTC. */
1713 start: string;
1714 end: string;
1715 days: number;
1716 /** Days from its start to today, today included. */
1717 daysElapsed: number;
1718 /** Usage cost so far, after the included allowances. */
1719 usageMicros: number;
1720 /** usageMicros over the days elapsed, times the cycle's days. */
1721 projectedMicros: number;
1722 averageDailyMicros: number;
1723 /** Cloudflare's subscriptions for the cycle (not on the usage bill). */
1724 subscriptionsMicros: number;
1725 meters: CycleMeter[];
1726};
1727
1728/** One of Cloudflare's meters over the cycle so far. */
1729export type CycleMeter = {
1730 product: string;
1731 meter: string;
1732 rawName: string;
1733 unit: string;
1734 quantity: number;
1735 /** What the cycle includes; null without a list price. */
1736 included: number | null;
1737 billableQuantity: number;
1738 costMicros: number;
1739 /** cloudflare: Cloudflare's own cost; list: the list price past the included amount; none: no list price known. */
1740 basis: "cloudflare" | "list" | "none" | string;
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1741};
1742
Merge Cloudflare's usage over its billing cycle: every page read, included amounts once a cycle, a projection, test-mode charges never money in (billing 0052)1743/** What the last read of Cloudflare's billable usage got back. */
1744export type BillRead = {
1745 readAt: string;
1746 since: string;
1747 until: string;
1748 rows: number;
1749 pages: number;
1750 consumedRows: number;
1751 pricingOnlyRows: number;
1752 costedRows: number;
1753};
1754
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)1755/** One level of the platform pause, as sudo shows it. Snake case, as billing sends it. */
1756export type PauseState = {
1757 level: PauseLevel;
1758 paused: boolean;
1759 note: string | null;
1760 set_by: string | null;
1761 set_at: string | null;
1762 /** Set by billing's usage watcher, not a person. */
1763 auto: boolean;
1764};
1765
1766/** One platform metric over an hour or the month so far. */
1767export type PlatformMetric = {
1768 metric: string;
1769 title: string;
1770 value: number;
1771 /** Its hourly threshold (`PLATFORM_HOURLY_*`); 0: none. */
1772 threshold: number;
1773 /** The script, queue, database or namespace that counted most. */
1774 top_name: string | null;
1775 top_value: number | null;
1776};
1777
1778/** A breach billing's usage watcher found. */
1779export type PlatformBreach = {
1780 id: string;
1781 metric: string;
1782 hour: string;
1783 rule: "threshold" | "spike";
1784 value: number;
1785 threshold: number;
1786 severe: boolean;
1787 top_name: string | null;
1788 detail: string;
1789 /** Levels it paused. */
1790 paused: PauseLevel[];
1791 opened_at: string;
1792 emailed_at: string | null;
1793};
1794
The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were.1795/** Billing's `admin_platform_guard`: the platform pause and usage watcher
1796 * (docs.g1t.sh/guides/deploy-to-cloudflare/#spend-guardrails). */
Merge platform pause and the hourly usage watcher: staff can pause compute, schedules, indexing or renders for everyone, the watcher emails on a breach and is never blind quietly, and the models proxy holds each run to its cap (billing 0051, integrations 0006)1797export type PlatformGuard = {
1798 levels: PauseState[];
1799 /** The last hour read, `YYYY-MM-DDTHH:00:00Z`. */
1800 hour: string | null;
1801 last_hour: PlatformMetric[];
1802 month: string;
1803 month_to_date: PlatformMetric[];
1804 breaches: PlatformBreach[];
1805 /** Whether billing can read Cloudflare's analytics. */
1806 can_read: boolean;
1807 /** `AUTO_PAUSE`: the levels a severe breach may pause. */
1808 auto_pause: PauseLevel[];
1809 /** What the latest run could not see: each query that failed, with its error. */
1810 blind?: { key: string; dataset: string; error: string }[];
1811 /** The latest run found every dataset empty: the wrong account, or a token that cannot see it. */
1812 empty?: boolean;
1813 /** The hour the latest run read. */
1814 last_run?: string | null;
1815};
1816
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1817/** What g1t pays for itself, at cost, against its caps (billing's `budget`). */
1818export type SpendCaps = {
1819 /** Today (UTC), YYYY-MM-DD, and this month, YYYY-MM. */
1820 day: string;
1821 month: string;
1822 /** What g1t paid for itself today across every workspace. */
1823 todayMicros: number;
1824 /** `PLATFORM_DAILY_SPEND_CAP_MICROS`; 0: no breaker. */
1825 dailyCapMicros: number;
1826 /** New hosted-model agent runs g1t would pay for are paused. */
1827 tripped: boolean;
1828 trippedAt: string | null;
1829 liftedBy: string | null;
1830 liftedAt: string | null;
1831 liftNote: string | null;
1832 /** This month so far, by what paid: comped, trial, oss, given, unpaid. */
1833 monthBuckets: { bucket: string; title: string; micros: number }[];
1834 comped: CompedBudget[];
1835 /** Free workspaces' share of reconciled costs this month (git, storage, platform). */
1836 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 & pricing1837 /** 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 pays1838 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 & pricing1839 fixedSource?: "cloudflare" | "estimate" | string;
1840 fixedReadAt?: string | null;
1841 /** Each subscription, when read from Cloudflare. */
1842 fixedItems?: { name: string; monthlyMicros: number }[];
Merge Cloudflare's usage over its billing cycle: every page read, included amounts once a cycle, a projection, test-mode charges never money in (billing 0052)1843 /** Of fixedMonthlyMicros, this calendar month's days so far, each at its billing cycle's daily share. */
1844 fixedMonthMicros?: number;
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1845 /** Money in this month, through the last reconciled day. */
1846 revenueMicros: number;
Merge costs and margin review: gateway query, own spend, discount meters, superseded rises1847 /**
1848 * Of this month's buckets, what was spent on workspaces whose billing a
1849 * testing reset later wiped (still g1t's spend; the reconciled figures
1850 * have it only where the reset kept it), and those workspaces.
1851 */
1852 resetMicros?: number;
1853 resetWorkspaces?: string[];
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1854};
1855
1856/** A comped account's monthly budget, at cost. */
1857export type CompedBudget = {
1858 account: string;
1859 name: string;
1860 usedMicros: number;
1861 /** 0: no budget. */
1862 ceilingMicros: number;
1863 /** `COMPED_MONTHLY_CEILING_MICROS`, not the account's own limit. */
1864 defaultCeiling: boolean;
1865 /** 50, 75, 90, 100, or 0. */
1866 level: number;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1867};
1868
1869export type CostsRun = { lines: number; days: number; proposals: number; alerts: number; problems: string[] };
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1870
1871/** The product families the Usage page groups meters into, in order. */
1872export const PRODUCTS = [
1873 { key: "agent", label: "Agent" },
1874 { key: "sandboxes", label: "Sandboxes" },
1875 { key: "gateway", label: "AI Gateway" },
1876 { key: "deployments", label: "Deployments" },
1877 { key: "git_storage", label: "Git & storage" },
1878 { key: "packages", label: "Packages" },
1879 { key: "security", label: "Security & quality" },
1880 { key: "search", label: "Search" },
1881] as const;
1882
1883export type ProductKey = (typeof PRODUCTS)[number]["key"];
1884
1885/** What usage came to over a range, and what paid for it: price − discount − included − credits = charged. */
1886export type UsageTotals = {
1887 /** Usage at price, pending usage included. */
1888 priceMicros: number;
1889 discountMicros: number;
1890 /** Paid by the plan's included usage, the trial and g1t's pools. */
1891 includedMicros: number;
1892 /** Paid by AI credit and credit from g1t. */
1893 creditsMicros: number;
1894 /** Left for the workspace to pay. */
1895 chargedMicros: number;
1896 /** Metered this month, charged when it closes. */
1897 pendingMicros: number;
Money is written one way. A single formatter turns millionths of a dollar into dollars, rounding half up on whole micros rather than on a float, so the same sum reads the same on every page: under a cent reads <$0.01 on a total and exactly nothing is $0.00, while the statement's lines, a session's receipt, the price book and an agent's effort costs carry up to four places where the fraction of a cent is the point; the six formatters that each rounded their own way are gone. This month is the calendar month in UTC from its first day to today everywhere, and billing counts the month's not-yet-closed usage in any range that reaches into the current month, so the top bar's pill, Spend, Home and Usage ask for the same days and get the same figure; Home now reads the usage report the others read instead of adding up statements. Usage's pending sentence says what of that usage the close will charge after the discount and included usage, which the billing API returns as pending_charged_micros. A reconciliation test holds the pill, Spend, Home and Usage to one number for one month. The usage and billing guide says how amounts are written and what this month means.1898 /** What of `pendingMicros` will be charged at the close, after the discount and what g1t covers; absent from an older billing. */
1899 pendingChargedMicros?: number;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1900 costMicros: number;
1901};
1902
1903export type UsageDay = { day: string; product: string; micros: number };
1904
Spend adds up on one ledger. Charged this month has one definition, price less discount, included usage and credit, shared by the plan card, the spend limit, Spend and the top bar; the limit had counted usage not yet closed at full price before the discount, so a comped workspace read as charged a cent. Every agent line on the ledger names the agent and who asked, repository runs by g1t included, so Spent is the sum of its products, Agents is the agent product, and by agent adds up to it; the billing API returns by_agent and by_person. The usage and billing guide says how spend is counted.1905/** One agent's (by handle) or one person's (by username) share of the agent product, at price; an empty key for lines attributed to no one. */
1906export type UsageShare = { key: string; label: string; micros: number; count: number };
1907
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1908export type UsageAllowance = { used: number; of: number; unit: string };
1909
1910export type ProjectUsage = { project: string; micros: number; quantity: number };
1911
1912/** One meter over a range. */
1913export type MeterLine = {
1914 key: string;
1915 label: string;
1916 product: string;
1917 /** `tokens`, `seconds`, `bytes`, `operations`, `requests` or `entries`. */
1918 unit: string;
1919 quantity: number;
1920 micros: number;
1921 pendingMicros?: number;
1922 /** Every day of the range, oldest first, at price. */
1923 daily: number[];
1924 allowance?: UsageAllowance | null;
1925 byProject: ProjectUsage[];
Merge branch 'model-routing'1926 /** How the quantity is counted, when that needs saying (the agent rate's token weights). */
1927 note?: string | null;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1928};
1929
1930export type FeatureUsage = { key: string; label: string; micros: number; count: number };
1931
1932export type ProductUsage = { key: string; label: string; micros: number; meters: MeterLine[]; features?: FeatureUsage[] };
1933
Merge branch 'model-routing'1934/** The tokens one model used over a range, as the model proxy counted them. */
1935export type ModelTokens = { model: string; input: number; output: number; cacheRead: number; cacheWrite: number };
1936
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1937export type UsageReport = {
1938 from: string;
1939 until: string;
1940 totals: UsageTotals;
1941 days: UsageDay[];
1942 products: ProductUsage[];
1943 projects: string[];
Merge branch 'model-routing'1944 /** Agent tokens by model over the range, most first. */
1945 models?: ModelTokens[];
Spend adds up on one ledger. Charged this month has one definition, price less discount, included usage and credit, shared by the plan card, the spend limit, Spend and the top bar; the limit had counted usage not yet closed at full price before the discount, so a comped workspace read as charged a cent. Every agent line on the ledger names the agent and who asked, repository runs by g1t included, so Spent is the sum of its products, Agents is the agent product, and by agent adds up to it; the billing API returns by_agent and by_person. The usage and billing guide says how spend is counted.1946 /** The agent product by the agent that did the work, most first; their sum is the agent product's total. */
1947 byAgent?: UsageShare[];
1948 /** The agent product by who asked; work no person asked for under an empty key. */
1949 byPerson?: UsageShare[];
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1950 /** The plan's included usage this month, in micros. */
1951 included?: UsageAllowance | null;
1952 discountPercent?: number | null;
1953 aiCreditMicros: number;
1954 creditMicros: number;
1955 trialMicros?: number | null;
1956 plan: PlanKind;
1957 free: boolean;
1958};
1959
1960export type AiReload = {
1961 enabled: boolean;
1962 thresholdMicros: number;
1963 targetMicros: number;
1964 monthlyMaxMicros: number;
1965 reloadedMicros?: number;
1966 failedAt?: string | null;
1967 error?: string | null;
1968};
1969
1970export type CardFee = { on: boolean; percentMicros: number; fixedCents: number };
1971
1972/** Prepaid AI credit: what Agent and AI Gateway usage draws on. */
1973export type AiCredit = {
1974 balanceMicros: number;
1975 purchasedMicros: number;
1976 givenMicros: number;
1977 grants: CreditGrant[];
1978 /** A 100% discount pays for AI usage: nothing to buy. */
1979 freeViaDiscount: boolean;
1980 /** Invoiced after use (an enterprise). */
1981 postpaid: boolean;
1982 /** New runs on g1t's models are refused for want of credit. */
1983 blocked: boolean;
1984 canBuy: boolean;
1985 presetsCents: number[];
1986 minCents: number;
1987 maxCents: number;
1988 cardFee: CardFee;
1989 reload: AiReload;
1990 /** The agent rate per million tokens, at price. */
1991 agentRateMicros: number;
1992 modelMarkupPercent: number;
1993 gatewayMarkupPercent: number;
1994 upgradeCreditMicros: number;
1995 expiresDays: number;
1996};
1997
1998export type PostalAddress = { line1: string; line2: string; city: string; state: string; postalCode: string; country: string };
1999
2000export type PaymentMethod = {
2001 kind: string;
2002 brand?: string | null;
2003 last4?: string | null;
2004 expMonth?: number | null;
2005 expYear?: number | null;
2006};
2007
2008export type StripeInvoice = {
2009 id: string;
2010 number?: string | null;
2011 status: string;
2012 totalCents: number;
2013 currency: string;
2014 createdAt: string;
2015 description?: string | null;
2016 hostedUrl?: string | null;
2017 pdfUrl?: string | null;
2018};
2019
2020export type UpcomingInvoice = { closesAt: string; subscriptionsMicros: number; usageMicros: number; totalMicros: number };
2021
2022export type BillingDetails = {
2023 customer: boolean;
2024 email: string | null;
2025 name: string | null;
2026 address: PostalAddress | null;
2027 taxIdType: string | null;
2028 taxId: string | null;
2029 poNumber: string | null;
2030 language: string | null;
2031 paymentMethod: PaymentMethod | null;
2032 invoices: StripeInvoice[];
2033 upcoming: UpcomingInvoice;
2034 unavailable?: string | null;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person2035 /** Whether Stripe Tax can place the customer from the address; without it nothing is charged. */
2036 taxLocation?: boolean;
2037 /** Set when g1t did not charge for want of a billing address. */
2038 taxAddressNeededAt?: string | null;
2039 /** Stripe's check of the tax ID: pending, verified, unverified or unavailable. */
2040 taxIdStatus?: string | null;
2041 /** none, exempt or reverse, as set at Stripe. */
2042 taxExempt?: string | null;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit2043};
2044
2045export type BillingDetailsInput = {
2046 email?: string;
2047 name?: string;
2048 address?: PostalAddress;
2049 taxIdType?: string;
2050 taxId?: string;
2051 poNumber?: string;
2052 language?: string;
2053};

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