Skip to content
271 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.

The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.1/**
2 * Spend's arithmetic and wording (routes/workspace/spend.tsx and the top
3 * bar's spend pill): which days a period covers, what the price book says
4 * about pricing, a day-by-day series, a task's receipt from its session
5 * tree, and what each budget does when it is reached. Pure, with type-only
6 * imports, so it is tested on its own. Every number comes from a service;
7 * nothing here invents one.
8 */
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.9import type { AgentSession, PriceBook, SpendPeriod, SpendSlice, UsageDay, UsageReport, UsageShare } from "@g1t/contracts";
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.10
11/** Whose spend: your own (what agents did for you), or the whole workspace's. */
12export type SpendScope = "me" | "workspace";
13
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.14/**
15 * What agents cost over the report's range, at price: the agent product
16 * (model tokens, the agent rate and agents' sandbox time), every agent's
17 * replies, sessions and runs on repositories together. The top bar's and
18 * Spend's "Agents" figure, from the same ledger as "Spent", so it is part
19 * of it: Spent = Agents + the other products.
20 */
21export function agentMicros(report: Pick<UsageReport, "products">): number {
22 return report.products.find((p) => p.key === "agent")?.micros ?? 0;
23}
24
25/**
26 * The agent product by the agent that did the work and by who asked, as
27 * Spend's slices, from the ledger's own attribution. Null when billing did
28 * not attribute the range (a report from before attribution), so the
29 * caller can fall back to the agents service's own count.
30 */
31export function attributionSlices(report: Pick<UsageReport, "byAgent" | "byPerson"> | null): { agent: SpendSlice[]; person: SpendSlice[] } | null {
32 if (!report?.byAgent || !report.byPerson) return null;
33 const slice = (s: UsageShare): SpendSlice => ({ key: s.key, label: s.label, micros: s.micros, count: s.count });
34 return { agent: report.byAgent.map(slice), person: report.byPerson.map(slice) };
35}
36
37/** Where an agent's slice opens: its own Spend tab, for a slice that names one. */
38export function agentSpendHref(slug: string, slice: Pick<SpendSlice, "key">): string | null {
39 return slice.key ? `/${slug}/-/agents/${slice.key}/spend` : null;
40}
41
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.42export const SPEND_PERIODS: { key: SpendPeriod; label: string; short: string }[] = [
43 { key: "month", label: "This month", short: "This month" },
44 { key: "last_month", label: "Last month", short: "Last month" },
45 { key: "30d", label: "Last 30 days", short: "30 days" },
46 { key: "7d", label: "Last 7 days", short: "7 days" },
47];
48
49export function readPeriod(raw: string | null | undefined): SpendPeriod {
50 return SPEND_PERIODS.some((p) => p.key === raw) ? (raw as SpendPeriod) : "month";
51}
52
53export function periodLabel(period: SpendPeriod): string {
54 return SPEND_PERIODS.find((p) => p.key === period)?.label ?? "This month";
55}
56
57/** Whose view a request asks for: the workspace's only for someone who may see it. */
58export function readScope(raw: string | null | undefined, mayWorkspace: boolean): SpendScope {
59 if (!mayWorkspace) return "me";
60 return raw === "me" ? "me" : "workspace";
61}
62
63const iso = (at: Date) => at.toISOString().slice(0, 10);
64
65/**
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.66 * This month, in UTC: its first day to today, both included. The one
67 * range "this month" means on every page: the top bar's pill, Spend's
68 * "This month", Home's "this month so far" and Usage's current cycle all
69 * read it, so the same month shows the same number everywhere. Billing
70 * adds the month's usage not yet closed (`pending_micros`) to any range
71 * that reaches into the current month, so `until` need not be month end.
72 */
73export function monthSpan(now: Date): { from: string; until: string } {
74 return { from: iso(new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1))), until: iso(now) };
75}
76
77/**
78 * What the workspace used over the report's range, at price: the figure
79 * the pill, Spend's "Spent", Home's "this month so far" and Usage's
80 * "Usage at price" all show. Billing already measures at cost while g1t
81 * is free, so the report's price is the one figure in every mode.
82 */
83export function spentMicros(report: Pick<UsageReport, "totals">): number {
84 return report.totals.priceMicros;
85}
86
87/**
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.88 * The days a period covers in UTC, both ends included, as the agents
89 * service counts them (services/agents/src/budget.ts `spendSpan`).
90 */
91export function spanFor(period: SpendPeriod, now: Date): { from: string; until: string } {
92 const y = now.getUTCFullYear();
93 const m = now.getUTCMonth();
94 const d = now.getUTCDate();
95 switch (period) {
96 case "last_month":
97 return { from: iso(new Date(Date.UTC(y, m - 1, 1))), until: iso(new Date(Date.UTC(y, m, 0))) };
98 case "7d":
99 return { from: iso(new Date(Date.UTC(y, m, d - 6))), until: iso(now) };
100 case "30d":
101 return { from: iso(new Date(Date.UTC(y, m, d - 29))), until: iso(now) };
102 default:
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.103 return monthSpan(now);
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.104 }
105}
106
107/** Every day from `from` to `until`, with what was spent on it; days with none are 0. */
108export function daySeries(from: string, until: string, spent: { day: string; micros: number }[]): { day: string; micros: number }[] {
109 const by = new Map<string, number>();
110 for (const s of spent) by.set(s.day, (by.get(s.day) ?? 0) + s.micros);
111 const out: { day: string; micros: number }[] = [];
112 const at = new Date(`${from}T00:00:00Z`);
113 const end = new Date(`${until}T00:00:00Z`);
114 if (Number.isNaN(at.getTime()) || Number.isNaN(end.getTime())) return out;
115 for (let n = 0; at <= end && n < 400; n++) {
116 const key = iso(at);
117 out.push({ day: key, micros: by.get(key) ?? 0 });
118 at.setUTCDate(at.getUTCDate() + 1);
119 }
120 return out;
121}
122
123/** Usage's days (one row per product a day) as one total a day. */
124export function usageByDay(days: UsageDay[]): { day: string; micros: number }[] {
125 return days.map((d) => ({ day: d.day, micros: d.micros }));
126}
127
128/** What the price book says about pricing, for the page's pricing card. */
129export type Pricing = {
130 /** What models are marked up, in percent: 0 is the provider's price. */
131 modelMarkupPercent: number;
132 /** What g1t's own metered work is marked up: one figure, or the range across meters. */
133 markup: { min: number; max: number } | null;
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.134 /** g1t's agent rate per million tokens, on g1t's models and on your own key, in force now. Null when the book has none. */
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.135 agentRateMicros: number | null;
136 agentRateOwnMicros: number | null;
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.137 /** The agent rate still to come, when it is $0 now and a dated version waits: its price and the day it starts. */
138 agentRateComing: { micros: number; from: string } | null;
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.139};
140
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.141/**
142 * Meters that are not something g1t runs at a cost: models (at the
143 * provider's price), AI Gateway, card fees (Stripe's), flat activations,
144 * and per-token rates with their weights.
145 */
146const NOT_RUN = (meter: string) =>
147 meter === "agent_models" || meter === "gateway_models" || meter.startsWith("agent_token") || meter.startsWith("card_fee") || meter === "security_activation";
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.148
149export function pricingOf(book: PriceBook): Pricing {
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.150 const run = book.prices.filter((p) => !NOT_RUN(p.meter) && p.costMicros > 0);
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.151 const markups = run.map((p) => p.markupPercent);
152 const rate = (meter: string) => {
153 const price = book.prices.find((p) => p.meter === meter);
154 return price ? price.priceMicros : null;
155 };
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.156 const coming = book.changes.find((c) => c.meter === "agent_tokens" && c.effectiveAt);
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.157 return {
158 modelMarkupPercent: book.modelMarginPercent,
159 markup: markups.length ? { min: Math.min(...markups), max: Math.max(...markups) } : null,
160 agentRateMicros: rate("agent_tokens"),
161 agentRateOwnMicros: rate("agent_tokens_own"),
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.162 agentRateComing: coming ? { micros: coming.newCostMicros, from: coming.effectiveAt!.slice(0, 10) } : null,
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.163 };
164}
165
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.166/** "$0.25 per million tokens", or "$0.25 per million tokens from 2026-10-22" while it waits for its date. */
167export function agentRateLabel(pricing: Pick<Pricing, "agentRateMicros" | "agentRateComing">, money: (micros: number) => string): string {
168 if (pricing.agentRateMicros && pricing.agentRateMicros > 0) return `${money(pricing.agentRateMicros)} per million tokens`;
169 if (pricing.agentRateComing) return `${money(pricing.agentRateComing.micros)} per million tokens from ${pricing.agentRateComing.from}`;
170 return "Per million tokens";
171}
172
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.173/** "20%", or "15–20%" when meters differ. */
174export function markupLabel(markup: { min: number; max: number }): string {
175 return markup.min === markup.max ? `${markup.min}%` : `${markup.min}–${markup.max}%`;
176}
177
178/** One line of a task's receipt: one session of its tree. */
179export type ReceiptLine = {
180 session: AgentSession;
181 depth: number;
182 /** What this session's own steps were charged (a root's charge includes its tree's). */
183 ownMicros: number;
184};
185
186export type Receipt = {
187 root: AgentSession;
188 lines: ReceiptLine[];
189 /** The whole tree, as the root's charge counts it. */
190 chargedMicros: number;
191 /** The model answers at the provider's price, every session's together. */
192 providerMicros: number;
193 inputTokens: number;
194 outputTokens: number;
195 steps: number;
196 toolCalls: number;
197};
198
199/**
200 * A task's receipt from its session tree (root first, as the agents
201 * service gives it): each session's own charge, children under their
202 * parents, and the totals. A child's charge is added to the root as it is
203 * spent, so the root's own share is its charge less its children's.
204 */
205export function receiptOf(tree: AgentSession[], rootId: string): Receipt | null {
206 const root = tree.find((s) => s.id === rootId) ?? tree.find((s) => s.parent_id == null);
207 if (!root) return null;
208 const children = new Map<string, AgentSession[]>();
209 for (const s of tree) {
210 if (s.id === root.id || !s.parent_id) continue;
211 children.set(s.parent_id, [...(children.get(s.parent_id) ?? []), s]);
212 }
213 const lines: ReceiptLine[] = [];
214 const seen = new Set<string>();
215 const walk = (s: AgentSession, depth: number) => {
216 if (seen.has(s.id)) return;
217 seen.add(s.id);
218 lines.push({ session: s, depth, ownMicros: s.charged_micros });
219 for (const kid of [...(children.get(s.id) ?? [])].sort((a, b) => a.created_at.localeCompare(b.created_at))) walk(kid, depth + 1);
220 };
221 walk(root, 0);
222 const others = lines.slice(1).reduce((n, l) => n + l.ownMicros, 0);
223 lines[0]!.ownMicros = Math.max(0, root.charged_micros - others);
224 const sum = (pick: (s: AgentSession) => number) => lines.reduce((n, l) => n + (pick(l.session) || 0), 0);
225 return {
226 root,
227 lines,
228 chargedMicros: root.charged_micros,
229 providerMicros: sum((s) => s.cost_micros ?? 0),
230 inputTokens: sum((s) => s.input_tokens),
231 outputTokens: sum((s) => s.output_tokens),
232 steps: sum((s) => s.steps),
233 toolCalls: sum((s) => s.tool_calls),
234 };
235}
236
237/** A count of tokens for a receipt: "412K", "1.2M", "830". */
238export function tokenCount(n: number): string {
239 if (n >= 1_000_000) return `${(n / 1_000_000).toLocaleString("en-US", { maximumFractionDigits: 1 })}M`;
240 if (n >= 10_000) return `${Math.round(n / 1000).toLocaleString("en-US")}K`;
241 if (n >= 1000) return `${(n / 1000).toLocaleString("en-US", { maximumFractionDigits: 1 })}K`;
242 return n.toLocaleString("en-US");
243}
244
245/** How far through a budget: 0 to 1 (more when over), null with none. */
246export function shareOfBudget(spent: number, budget: number | null | undefined): number | null {
247 return budget != null && budget > 0 ? Math.max(0, spent) / budget : null;
248}
249
250/** "62%" of a budget, for a pill or a row; empty with none. */
251export function percentLabel(spent: number, budget: number | null | undefined): string {
252 const share = shareOfBudget(spent, budget);
253 return share == null ? "" : `${Math.round(share * 100)}%`;
254}
255
256/** The slices a person's own view leaves out: the "who asked" one is only ever them. */
257export function withoutSelf(slices: SpendSlice[], username: string): SpendSlice[] {
258 return slices.filter((s) => s.key !== username);
259}
260
261/** What a level of budget does when it is reached, as the page says it. */
262export const AT_LIMIT = {
263 workspace: (pauses: boolean) =>
264 pauses
265 ? "New work stops until the month turns or an owner raises it: agents, workflows, builds and deploys. Work already running finishes."
266 : "Owners are alerted, and work goes on; g1t's own ceiling still applies.",
267 agents: "No agent takes new work until the 1st, or until an owner raises it.",
268 person: "Agents take no new work for that person until the 1st; they say so where they were asked.",
269 agent: "That agent takes no new work until the 1st, or the next day for a daily cap.",
270 session: "The session stops at Needs approval, and an owner decides whether it goes on.",
271} as const;