flagon-io/g1t

public

Git for AI scale: a forge for thousands of agents working on the same code at once.

g1t/packages/contracts/src/billing.ts

654 lines25,479 bytesCodeBlame

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.

Agents as a team: lifecycle, merge queue, billing and a new shell1import type { User, Viewer } from "./identity";
2import type { RepoPath } from "./repos";
3import type { Result } from "./result";
4
5/** Millionths of a US dollar in one dollar: the unit money is held in. */
6export const MICROS_PER_DOLLAR = 1_000_000;
7
8/** Whether workspaces are charged for agents at all, and with real money. */
9export type BillingStatus = {
10 /**
11 * False when no card processor is configured: nothing is charged, and who
12 * may run agents is decided some other way.
13 */
14 enabled: boolean;
15 /** False while the card processor is in its test mode, where cards are not real. */
16 live: boolean;
Free while g1t is being built out; agents can check out their own forks17 /**
18 * True while g1t is being built out: runs are recorded with what they
19 * cost, but nothing is charged and no credit is needed. Not forever.
20 */
21 free?: boolean;
Agents as a team: lifecycle, merge queue, billing and a new shell22};
23
24/** A workspace's standing. */
25export type BillingAccount = {
26 workspace: string;
27 /**
28 * Credit left, in millionths of a dollar. Can dip below zero by the cost
29 * of the runs that were under way when it ran out.
30 */
31 balanceMicros: number;
32 status: BillingStatus;
33 /** What is added to a run's cost, in percent. */
34 marginPercent: number;
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace35 /** The card charged near the limit and when a month closes, if one is saved. */
36 card?: { brand: string; last4: string; expMonth: number; expYear: number } | null;
Agents as a team: lifecycle, merge queue, billing and a new shell37};
38
39/** One line of a workspace's statement. */
40export type LedgerEntry = {
41 id: string;
42 /** Credit bought with a card, or an agent's run. */
43 kind: "top_up" | "usage";
44 /** Positive for credit added, negative for usage. */
45 amountMicros: number;
46 description: string;
47 /** For usage: the repository and pull request the agent worked on. */
48 repo: string | null;
49 number: number | null;
50 /** For usage: `implement`, `review` or `update`. */
51 task: string | null;
52 /** For usage: the model, by its public name. */
53 model: string | null;
Integrations: your own model provider, alerts that open issues, tickets agents read54 /** For usage: who paid the model provider. */
55 billedTo: "g1t" | "workspace";
Agents as a team: lifecycle, merge queue, billing and a new shell56 /** For a top-up: the username of whoever paid. */
57 createdBy: string | null;
58 /** RFC 3339. */
59 createdAt: string;
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace60 /** The workspace the line belongs to, which tells an enterprise's lines apart. */
61 workspace?: string | null;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put62 /** For usage: what the Team plan's credit paid of it. `amountMicros` is what is left to pay. */
63 creditMicros?: number;
64 /** For usage: what the workspace's trial credit paid of it. */
65 trialMicros?: number;
66 /** For usage: what g1t's open-source pool paid of it. */
67 ossMicros?: number;
Agents as a team: lifecycle, merge queue, billing and a new shell68};
69
70/** What lets a sandbox, and nothing else, report what its run cost. */
71export type RunTicket = { runId: string; token: string };
72
73/**
74 * What agents cost, charged to the workspace they worked for. A workspace
75 * buys credit; each run deducts its cost plus g1t's margin; with no credit,
76 * no agent starts.
77 */
A free allowance on g1t's models, so anyone can try its agents78/**
79 * The free allowance on g1t's hosted models for a workspace not otherwise
80 * open to them: a few dollars of model cost each, out of one pool, until a
81 * date. Mirrors `Trial` in `crates/contracts/src/billing.rs`.
82 */
Billing accounts, terms and enterprises; g1t is no longer free83/** How an account is charged. Standard unless g1t set otherwise in sudo. */
84export type Terms = {
85 kind: "standard" | "comped" | "custom";
86 discountPercent: number;
87 ceilingMicros: number | null;
88 note: string;
89 until: string | null;
90 setBy: string | null;
91 setAt: string | null;
92};
93
94/**
95 * Who pays: a workspace's own account, or an enterprise's, which pays for
96 * several workspaces with one bill and one limit.
97 */
98export type PayingAccount = {
99 id: string;
100 kind: "workspace" | "enterprise";
101 name: string;
102 terms: Terms;
103 workspaces: string[];
Stripe webhooks, enterprise invoices, and sudo for both104 /** Where an enterprise's invoices go. */
105 billingEmail?: string | null;
106 /** An enterprise's invoices, newest first. */
107 invoices?: EnterpriseInvoice[];
Billing accounts, terms and enterprises; g1t is no longer free108 createdAt: string;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put109 /** What g1t staff set for the account beyond its terms. */
110 allowances?: Allowances;
111};
112
113/** Set per account by g1t staff in sudo, on top of its terms. */
114export type Allowances = {
115 /** The Team plan without paying for it. Comped accounts have it anyway. */
116 team: boolean;
117 /** Each public repository's monthly cap on g1t's open-source pool; null for the default. */
118 ossRepoMicros: number | null;
119 /** Each workspace's trial credit, outside the monthly pool; null for the default. */
120 trialMicros: number | null;
Billing accounts, terms and enterprises; g1t is no longer free121};
122
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put123/** What a workspace's plans give it now. Mirrors `Entitlements` in `crates/contracts/src/billing.rs`. */
124export type Entitlements = {
125 workspace: string;
126 /** Whether the Team plan is on: paid for, comped, or given by g1t. */
127 team: boolean;
128 /** How far back the audit log can be read and exported. */
129 auditRetentionDays: number;
130 /** Private repository storage included before it is charged. */
131 freePrivateStorageBytes: number;
132 /** The last daily measure of the workspace's private repositories (a lower bound). */
133 privateStorageBytes: number;
134 /** The Team credit each month, and what of it is used this month. */
135 teamCreditMicros: number;
136 teamCreditUsedMicros: number;
137 /** What g1t's open-source pool paid for the workspace this month. */
138 ossPaidMicros: number;
139 /** Build time the Deployments plan includes each month, and used. */
140 buildSecondsIncluded: number;
141 buildSecondsUsed: number;
142 /** The smallest amount a card is charged; less carries over. */
143 minChargeMicros: number;
144};
145
146/** g1t's capped budgets for free usage this month. */
147export type Pools = {
148 month: string;
149 trialGrantedMicros: number;
150 trialPoolMicros: number;
151 trialGrants: number;
152 ossUsedMicros: number;
153 ossPoolMicros: number;
154 ossRepoMicros: number;
155};
156
Billing accounts, terms and enterprises; g1t is no longer free157export type AccountSummary = {
158 account: PayingAccount;
159 limit: Limit;
160 chargedMicros: number;
161 costMicros: number;
162 paidMicros: number;
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace163 /** The same figures for each of the account's workspaces that has any. */
164 byWorkspace: WorkspaceFigures[];
Two limits, real invoices, trust that grows by itself, sales signals165 /** The last six months, oldest first. */
166 months?: MonthFigures[];
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace167};
168
169/** One workspace's share of an `AccountSummary`. */
170export type WorkspaceFigures = { workspace: string; chargedMicros: number; costMicros: number; paidMicros: number };
171
Stripe webhooks, enterprise invoices, and sudo for both172export type StripeStatus = {
173 /** `test` or `live`, from the key; `off` without one. */
174 mode: "test" | "live" | "off" | string;
175 webhook: { url: string; endpointId: string; events: string[]; createdBy: string; createdAt: string } | null;
176 recentEvents: { id: string; kind: string; outcome: string; receivedAt: string }[];
177 error: string | null;
178};
179
180/** An enterprise's invoice: one line per workspace, paid on Stripe's page. */
181export type EnterpriseInvoice = {
182 invoiceId: string;
183 hostedUrl: string | null;
184 amountMicros: number;
185 status: "open" | "paid" | "overdue" | "void" | string;
186 period: string;
187 lines: { workspace: string; amountMicros: number }[];
188 createdAt: string;
189};
190
Two limits, real invoices, trust that grows by itself, sales signals191/** A workspace's invoice: monthly, or when charged near its limit. Itemised, in Stripe's billing page. */
192export type WorkspaceInvoice = {
193 invoiceId: string;
194 workspace: string;
195 reason: "month" | "threshold" | string;
196 period: string;
197 amountMicros: number;
198 status: "paid" | "open" | "failed" | "void" | string;
199 hostedUrl: string | null;
200 pdfUrl: string | null;
201 lines: { description: string; amountMicros: number }[];
202 createdAt: string;
203};
204
The statement is a month at a time, a line per kind of charge205/** A month of the ledger, grouped by day or project, a line per kind of charge. */
206export type Statement = {
207 month: string;
208 months: string[];
209 groups: {
210 key: string;
211 label: string;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put212 /** `coveredMicros`: what the Team credit, the trial or the open-source pool paid, not in `chargedMicros`. */
213 lines: { kind: string; count: number; chargedMicros: number; costMicros: number; coveredMicros?: number }[];
The statement is a month at a time, a line per kind of charge214 chargedMicros: number;
215 }[];
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put216 totals: {
217 chargedMicros: number;
218 paidMicros: number;
219 costMicros: number;
220 entries: number;
221 /** What paid for usage before it was charged, such as "Paid by g1t's open-source pool". */
222 covered?: { source: "team_credit" | "trial" | "oss_pool" | string; label: string; micros: number }[];
223 /** Owed when the month closed but under the minimum charge: on the next invoice. */
224 carriedMicros?: number;
225 };
The statement is a month at a time, a line per kind of charge226};
227
Two limits, real invoices, trust that grows by itself, sales signals228export type MonthFigures = { month: string; chargedMicros: number; costMicros: number; paidMicros: number };
229
230export type SignalKind = "at_limit" | "near_ceiling" | "declined" | "growing" | "established" | "first_payment" | "high_spend";
231
232/** Why a workspace is worth reaching out to. */
233export type Signal = {
234 workspace: string;
235 kind: SignalKind;
236 detail: string;
237 valueMicros: number;
238 stage: string | null;
239 owner: string | null;
Billing lists every invoice and every staff change; signals carry follow-ups240 nextStep?: string | null;
241 /** When the next step is due, YYYY-MM-DD. */
242 nextAt?: string | null;
243};
244
245/** One invoice g1t has sent, a workspace's or an enterprise's. */
246export type InvoiceSummary = {
247 invoiceId: string;
248 kind: "workspace" | "enterprise";
249 account: string;
250 name: string;
251 reason: string;
252 period: string;
253 amountMicros: number;
254 status: string;
255 hostedUrl: string | null;
256 createdAt: string;
257 paidAt: string | null;
Two limits, real invoices, trust that grows by itself, sales signals258};
259
260export type SalesStage = "none" | "lead" | "contacted" | "negotiating" | "won" | "lost" | "churn_risk";
261
262export type SalesRecord = {
263 workspace: string;
264 stage: SalesStage | string;
265 owner: string | null;
266 nextStep: string | null;
267 nextAt: string | null;
268 notes: { id: string; text: string; by: string; createdAt: string }[];
269 updatedAt: string | null;
270};
271
272export type Overview = {
273 month: string;
274 months: MonthFigures[];
275 byKind: { kind: string; chargedMicros: number; costMicros: number }[];
276 payingWorkspaces: number;
277 stopped: number;
278 nearCeiling: number;
279 declined: number;
280 openInvoicesMicros: number;
281 followUpsDue: number;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put282 /** g1t's capped budgets for free usage, this month. */
283 pools?: Pools | null;
Two limits, real invoices, trust that grows by itself, sales signals284};
285
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace286/** A customer's Stripe billing page, for staff to send them. */
287export type BillingLink = {
288 /** One-time and short-lived, signed in already. */
289 portalUrl: string;
290 /** The page's sign-in, which does not expire: the customer signs in by email. */
291 loginUrl: string | null;
292 customerEmail: string | null;
293 expiresNote: string;
Billing accounts, terms and enterprises; g1t is no longer free294};
295
296export type AdminAction = { id: string; account: string; action: string; detail: string; by: string; createdAt: string };
297
298export type AccountDetail = {
299 summary: AccountSummary;
300 workspaces: Limit[];
301 ledger: LedgerEntry[];
302 audit: AdminAction[];
303};
304
305/** Staff-only billing, for sudo.g1t.sh. Every change names who made it. */
306export interface BillingAdminApi {
307 accounts(query?: string): Promise<AccountSummary[]>;
308 account(id: string): Promise<Result<AccountDetail>>;
309 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 put310 /** Team on or off without charge, and the account's share of the pools. Needs a note. */
311 setAllowances(id: string, allowances: Allowances, note: string, by: string): Promise<Result<PayingAccount>>;
Billing accounts, terms and enterprises; g1t is no longer free312 createEnterprise(name: string, workspaces: string[], by: string): Promise<Result<PayingAccount>>;
313 attach(workspace: string, account: string | null, by: string): Promise<Result<PayingAccount>>;
314 credit(workspace: string, amountMicros: number, note: string, by: string): Promise<Result<LedgerEntry>>;
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace315 /** The workspace's Stripe billing page, to send to the customer. Logged. */
316 billingLink(workspace: string, by: string): Promise<Result<BillingLink>>;
Stripe webhooks, enterprise invoices, and sudo for both317 /** Where billing stands with Stripe; with `setup`, registers the webhook first. */
318 stripe(setup?: boolean, by?: string): Promise<StripeStatus>;
319 /** Where an enterprise's invoices go; makes its Stripe customer. */
320 enterpriseBilling(id: string, email: string, by: string): Promise<Result<PayingAccount>>;
321 /** Sends an enterprise its invoice now, for what its workspaces owe. */
322 invoiceEnterprise(id: string, by: string): Promise<Result<EnterpriseInvoice>>;
323 /** Exactly these workspaces' accounts, such as one page of the list. */
324 accountsFor(workspaces: string[]): Promise<AccountSummary[]>;
Two limits, real invoices, trust that grows by itself, sales signals325 /** Every workspace worth reaching out to, most urgent first. */
326 signals(): Promise<Signal[]>;
327 /** The business at a glance. */
328 overview(): Promise<Overview>;
329 /** A workspace's sales record. */
330 sales(workspace: string): Promise<SalesRecord>;
331 setSales(workspace: string, record: { stage: string; owner?: string | null; nextStep?: string | null; nextAt?: string | null }, by: string): Promise<Result<SalesRecord>>;
332 addNote(workspace: string, text: string, by: string): Promise<Result<SalesRecord>>;
333 /** A workspace's invoices from g1t, for staff. */
334 workspaceInvoices(workspace: string): Promise<WorkspaceInvoice[]>;
Billing lists every invoice and every staff change; signals carry follow-ups335 /** Every invoice g1t has sent, newest first. */
336 allInvoices(filter?: { status?: string; month?: string }): Promise<InvoiceSummary[]>;
337 /** Every change made in sudo and by Stripe, newest first, 100 at a time. */
338 audit(filter?: { by?: string; action?: string; before?: string }): Promise<AdminAction[]>;
Billing accounts, terms and enterprises; g1t is no longer free339}
340
Usage limits: unpaid usage can only go so far341/** How much a workspace has earned g1t's trust with money. */
Two limits, real invoices, trust that grows by itself, sales signals342export type Trust = "new" | "paid" | "established" | "reviewed" | "internal";
Usage limits: unpaid usage can only go so far343
344/**
345 * How far a workspace's unpaid usage has gone this month, and where its
346 * work stops: past `ceilingMicros`, no new sandboxes, builds or app
347 * requests. Usage counts at its cost to g1t or its charge, whichever is
348 * more, so it counts while g1t is free too.
349 */
350export type Limit = {
351 workspace: string;
Billing accounts, terms and enterprises; g1t is no longer free352 /** The account that pays: the workspace's own (`ws_<slug>`), or its enterprise's. */
353 account: string;
354 accountName: string;
Usage limits: unpaid usage can only go so far355 trust: Trust;
356 exposureMicros: number;
357 /** The lower of g1t's ceiling and the owner's spend limit; null for g1t's own. */
358 ceilingMicros: number | null;
359 trustCeilingMicros: number | null;
360 spendLimitMicros: number | null;
361 state: "ok" | "warning" | "stopped";
362 message: string | null;
Two limits, real invoices, trust that grows by itself, sales signals363 /** Charged this month: what the spend limit is measured against. */
364 spentMicros?: number;
365 /** True while the owners have not chosen a limit, so the automatic one applies: $200, or twice last month's spend. */
366 defaultSpendLimit?: boolean;
367 /** The most owners may set their own limit to; past it, they contact g1t. */
368 availableMicros?: number | null;
369 /** How the ceiling grows from here, in a sentence. */
370 growth?: string | null;
Usage limits: unpaid usage can only go so far371};
372
Prices keep themselves current with what g1t pays373/** One metered unit: what it costs g1t and what it is sold at; the price follows the cost. */
374export type Price = {
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put375 meter:
376 | "sandbox_second"
377 | "build_second"
378 | "app_requests"
379 | "app_cpu"
380 | "app_month"
381 | "custom_domain_month"
382 | "private_storage"
383 | "embedding_tokens"
384 | "scan_cpu"
385 | "scan_rows"
386 | string;
Prices keep themselves current with what g1t pays387 title: string;
388 unit: string;
389 costMicros: number;
390 markupPercent: number;
391 priceMicros: number;
392 /** `list`: Cloudflare's published price. `cloudflare`: measured from Cloudflare's bill. */
393 source: "list" | "cloudflare" | string;
394 checkedAt: string | null;
395 updatedAt: string;
396};
397
398export type PriceChange = {
399 meter: string;
400 oldCostMicros: number;
401 newCostMicros: number;
402 markupPercent: number;
Prices are what g1t pays plus 20%, from the first second403 /** The markup before, when the change was to the markup rather than the cost. */
404 oldMarkupPercent?: number;
Prices keep themselves current with what g1t pays405 reason: string;
406 createdAt: string;
407};
408
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put409export type PriceBook = {
410 prices: Price[];
411 changes: PriceChange[];
412 modelMarginPercent: number;
413 /** Every plan, as sold now. */
414 plans?: FeaturePlan[];
415 /** What is free, and the capped budgets that pay for it. */
416 free?: FreeTier | null;
417};
Prices keep themselves current with what g1t pays418
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put419/** What g1t gives without a plan; each is paid for by a capped budget. */
420export type FreeTier = {
421 /** Each new workspace's trial credit, once. */
422 trialWorkspaceMicros: number;
423 /** Trial grants each month, in all; new trials wait when it is spent. */
424 trialMonthlyPoolMicros: number;
425 /** g1t's open-source pool each month, and any one repository's share. */
426 ossPoolMicros: number;
427 ossRepoMicros: number;
428 /** Private repository storage before it is charged. */
429 freePrivateStorageBytes: number;
430 /** Days of audit log without Team. */
431 auditRetentionDays: number;
432 /** The smallest amount a card is charged; less carries over. */
433 minChargeMicros: number;
434};
435
436/**
437 * A workspace's trial credit: one grant per workspace, made the first time
438 * it uses something, out of a pool that resets each calendar month. Mirrors
439 * `Trial` in `crates/contracts/src/billing.rs`.
440 */
A free allowance on g1t's models, so anyone can try its agents441export type Trial = {
442 open: boolean;
443 usedMicros: number;
444 limitMicros: number;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put445 /** No longer used: trials do not end on a date. */
A free allowance on g1t's models, so anyone can try its agents446 endsAt: string | null;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put447 /** Why it is closed: `off`, `used` (this workspace's grant is spent) or `pool` (this month's are given out). */
A free allowance on g1t's models, so anyone can try its agents448 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 put449 /** Whether the workspace has its grant already. */
450 granted?: boolean;
451 /** With `pool`: when new trials start again, the first of next month. */
452 waitsUntil?: string | null;
A free allowance on g1t's models, so anyone can try its agents453};
454
Paid features: a workspace turns on Deployments with a monthly plan455/**
456 * A paid feature a workspace turns on with a monthly plan, as Cloudflare's
457 * Workers for Platforms or Vercel's Pro are bought. Never free: neither
458 * `free` nor the model allowance covers it. Mirrors `Feature` in
459 * `crates/contracts/src/billing.rs`.
460 */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put461export type Feature = "deployments" | "team";
Paid features: a workspace turns on Deployments with a monthly plan462
463/** What the Deployments plan includes each month. Mirrors `deployments_allowance`. */
464export const DEPLOYMENTS_ALLOWANCE = {
465 apps: 10,
466 requests: 1_000_000,
467 cpuMs: 3_000_000,
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put468 /** Build time included: 200 minutes. Billing's `DEPLOYMENTS_BUILD_SECONDS` decides. */
469 buildSeconds: 12_000,
Paid features: a workspace turns on Deployments with a monthly plan470 /** What Cloudflare charges g1t past that, in millionths of a dollar. */
471 microsPerAppMonth: 20_000,
472 microsPerMillionRequests: 300_000,
473 microsPerMillionCpuMs: 20_000,
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put474 /** One second of a build's sandbox, past the included build time. */
Deployments: a preview for every pull request, production on g1t.page475 microsPerBuildSecond: 21,
Agents and memory, checks and conflicts, profiles, slug renames, custom domains476 /** Custom domains across the workspace, and what each one past that costs g1t a month. */
477 customDomains: 3,
478 microsPerDomainMonth: 100_000,
Paid features: a workspace turns on Deployments with a monthly plan479} as const;
480
481export type FeaturePlan = {
482 feature: Feature;
483 title: string;
484 /** Charged every month while the plan is on, in cents. */
485 monthlyCents: number;
486 /** What the price includes, one line each. */
487 includes: string[];
488 /** How usage past the allowance is charged. */
489 overage: string;
490};
491
492export type SubscriptionStatus = "active" | "canceling" | "past_due" | "canceled";
493
494export type Subscription = {
495 feature: Feature;
496 status: SubscriptionStatus;
497 /** RFC 3339: when the period paid for ends. */
498 periodEnd: string | null;
499 startedBy: string;
500 startedAt: string;
501};
502
503/** A feature as a workspace sees it. */
504export type FeatureState = {
505 plan: FeaturePlan;
506 subscription: Subscription | null;
507 /** Whether the feature works for the workspace now. */
508 on: boolean;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put509 /** On without a plan: comped terms, or given by g1t. Nothing to pay or turn off. */
510 included?: boolean;
Paid features: a workspace turns on Deployments with a monthly plan511};
512
Agents as a team: lifecycle, merge queue, billing and a new shell513export interface BillingApi {
514 status(): Promise<BillingStatus>;
515 /** Members of the workspace only. */
516 account(workspace: string, viewer: Viewer): Promise<Result<BillingAccount>>;
517 /** Newest first. Members of the workspace only. */
518 ledger(workspace: string, viewer: Viewer): Promise<Result<LedgerEntry[]>>;
The statement is a month at a time, a line per kind of charge519 /** A month of the ledger, grouped by `day` (default) or `project`. Members only. */
520 statement(workspace: string, viewer: Viewer, month?: string | null, group?: "day" | "project"): Promise<Result<Statement>>;
521 /** One statement line's entries, 50 at a time; `before` is the last id seen. */
522 statementEntries(
523 workspace: string,
524 viewer: Viewer,
525 filter: { month: string; kind: string; day?: string | null; project?: string | null; before?: string | null },
526 ): Promise<Result<LedgerEntry[]>>;
Usage, like a hosting provider's: what agents cost, per day, task, repository and pull request527 /** What the workspace's agents cost since `since`, broken down. Members only. */
528 usage(workspace: string, viewer: Viewer, since: string): Promise<Result<Usage>>;
Agents as a team: lifecycle, merge queue, billing and a new shell529 /**
530 * Starts a card payment for credit and returns the page to send the
531 * person to. Owners only. The payment's id comes back to `returnUrl` as
532 * `session`.
533 */
534 checkout(actor: User, workspace: string, amountCents: number, returnUrl: string): Promise<Result<{ url: string }>>;
Billing on Stripe's pages, month-end charges, warnings; sudo by workspace535 /**
536 * Stripe's hosted billing page for the workspace: card, invoices, billing
537 * email and address. g1t never handles card numbers. Owners only.
538 */
539 billingPortal(actor: User, workspace: string, returnUrl: string): Promise<Result<{ url: string }>>;
Agents as a team: lifecycle, merge queue, billing and a new shell540 /** Credits a payment once the processor says it was made. Safe to repeat. */
541 confirm(workspace: string, viewer: Viewer, session: string): Promise<Result<BillingAccount>>;
542 /**
543 * Whether a workspace may start an agent now, asked before anything is
544 * opened for it. A failure, with the reason to show, when it has no credit.
545 */
546 canStart(workspace: string): Promise<Result<boolean>>;
A free allowance on g1t's models, so anyone can try its agents547 /** A workspace's free allowance on g1t's hosted models; `exempt` are open to them anyway. */
548 trial(workspace: string, exempt: string[]): Promise<Trial>;
Agents as a team: lifecycle, merge queue, billing and a new shell549 /**
550 * Asks whether a workspace may start an agent and opens the run it will be
551 * charged for. Null when billing is off; a failure when there is no credit.
552 */
Paid features: a workspace turns on Deployments with a monthly plan553 /** Every paid feature and the workspace's plan for each. Members only. */
554 features(workspace: string, viewer: Viewer): Promise<Result<FeatureState[]>>;
555 /**
556 * Starts the card page for a feature's monthly plan. Owners only. The
557 * page's id comes back to `returnUrl` as `session`.
558 */
559 subscribe(actor: User, workspace: string, feature: Feature, returnUrl: string): Promise<Result<{ url: string }>>;
560 /** Turns the feature on once the plan is paid for. Safe to repeat. */
561 confirmSubscription(workspace: string, viewer: Viewer, session: string): Promise<Result<FeatureState>>;
562 /** Ends a plan at the end of its period, or (`resume`) takes that back. Owners only. */
563 cancelSubscription(actor: User, workspace: string, feature: Feature, resume?: boolean): Promise<Result<FeatureState>>;
564 /** Whether a feature works for a workspace now; a failure with the reason when not. */
565 hasFeature(workspace: string, feature: Feature): Promise<Result<boolean>>;
566 /**
567 * Usage past a plan's allowance, charged from credit at cost plus the
568 * margin, once per `reference`. False if it was charged before.
569 */
570 chargeFeature(charge: {
571 workspace: string;
572 feature: Feature;
573 costMicros: number;
574 description: string;
575 repo?: string | null;
576 reference: string;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put577 /** For a build: how long it ran, so the plan's included build time pays for what it can. */
578 buildSeconds?: number | null;
Paid features: a workspace turns on Deployments with a monthly plan579 }): Promise<Result<boolean>>;
Prices keep themselves current with what g1t pays580 /**
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put581 * What a source cost g1t so far this month, so the workspace's limit
582 * counts it now. Replaces the last report. Billing charges `context`
583 * and `security` itself once the month is over; `deployments` charges
584 * its own.
Prices keep themselves current with what g1t pays585 */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put586 notePending(workspace: string, source: "deployments" | "context" | "security", costMicros: number): Promise<boolean>;
587 /** What the workspace's plans give it now: Team, audit retention, storage, credit used. */
588 entitlements(workspace: string): Promise<Entitlements>;
Prices keep themselves current with what g1t pays589 /** Every metered price and the recent changes. Public. */
590 prices(): Promise<PriceBook>;
Usage limits: unpaid usage can only go so far591 /** A workspace's limit, for its members. */
592 limit(workspace: string, viewer: Viewer): Promise<Result<Limit>>;
593 /** The same, for the services that enforce it. */
594 checkLimit(workspace: string): Promise<Result<Limit>>;
Every sandbox is metered by the second595 /**
Two limits, real invoices, trust that grows by itself, sales signals596 * The owners' own monthly limit, up to what is available; null goes back
597 * to the default, and `useFullLimit` uses everything available. Owners only.
598 */
599 setSpendLimit(actor: User, workspace: string, spendLimitMicros: number | null, useFullLimit?: boolean): Promise<Result<Limit>>;
600 /** The workspace's invoices from g1t, newest first. Members only. */
601 invoices(workspace: string, viewer: Viewer): Promise<Result<WorkspaceInvoice[]>>;
602 /**
Every sandbox is metered by the second603 * How long a sandbox ran for a workspace, reported when it stops. Its
Prices are what g1t pays plus 20%, from the first second604 * cost is recorded and every second is charged, from the first. False if
605 * `reference` was recorded before.
Every sandbox is metered by the second606 */
607 recordSandbox(usage: {
608 workspace: string;
609 seconds: number;
610 description: string;
611 repo?: string | null;
612 reference: string;
613 }): Promise<Result<boolean>>;
Agents as a team: lifecycle, merge queue, billing and a new shell614 startRun(run: {
615 workspace: string;
616 repo: RepoPath;
617 number: number;
618 task: string;
619 model: string;
Integrations: your own model provider, alerts that open issues, tickets agents read620 /** `workspace` when the run uses the workspace's own model provider. */
621 billedTo?: "g1t" | "workspace";
Prices keep themselves current with what g1t pays622 /** The model session's id, so the run can be settled at AI Gateway's price. */
623 session?: string | null;
Agents as a team: lifecycle, merge queue, billing and a new shell624 }): Promise<Result<RunTicket | null>>;
625}
Usage, like a hosting provider's: what agents cost, per day, task, repository and pull request626
627
628/** One slice of usage: what it was for, what it cost, how many runs. */
629export type UsageSlice = { key: string; micros: number; runs: number };
630
631/** What a workspace's agents cost over a period. */
632export type Usage = {
633 since: string;
634 /** Charged, including g1t's margin. */
635 spentMicros: number;
Integrations: your own model provider, alerts that open issues, tickets agents read636 /** What g1t's model provider charged, before the margin. */
Usage, like a hosting provider's: what agents cost, per day, task, repository and pull request637 costMicros: number;
Integrations: your own model provider, alerts that open issues, tickets agents read638 /** What runs on the workspace's own provider cost there, estimated. Not charged by g1t. */
639 providerMicros: number;
Usage while free is shown at cost; agents get rustfmt and clippy640 /** What the runs used, at cost: g1t's models and the workspace's own provider together. */
641 usedMicros: number;
642 /** g1t charges nothing for now; the slices then measure usage at cost. */
643 free: boolean;
Usage, like a hosting provider's: what agents cost, per day, task, repository and pull request644 runs: number;
645 /** Spend per day and task, keyed `YYYY-MM-DD/task`. */
646 byDay: UsageSlice[];
647 byTask: UsageSlice[];
648 byRepo: UsageSlice[];
649 /** Keyed `namespace/name#number`. */
650 byPull: UsageSlice[];
651 byModel: UsageSlice[];
652 /** Credit bought in the period. */
653 addedMicros: number;
654};