Skip to content

Commit

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.

syntaqxcommitted Parent6c3b446Browse files
62 files+58−390/62 viewed
+1−1
17671767 "Choose what happens when a team is asked to review a pull request. Off, everyone in it is asked. On (`enabled`), g1t picks `count` people from it (1 to 10, never the pull request's author) and asks them, and the team stays shown as asked beside them: `round_robin` picks whoever this team asked least recently, `load_balance` whoever has the fewest pull requests waiting on their review. `skip_busy` leaves out anyone with `busy_at` or more waiting; `include_child_teams` also picks from its child teams' people; `excluded` lists usernames never picked; `notify_team` also tells the rest of the team. Fields left out keep their current value. Owners of the workspace and the team's maintainers. People only. Returns the team."
17681768 }
17691769 Op::GetUsage => {
1770− "A workspace's usage over a range of days, at price, and what paid for it. `from` and `until` are UTC days, `YYYY-MM-DD`, with `until` included and at most 400 days in all; left out, the current month so far. `products` narrows it to product families (agent, sandboxes, gateway, deployments, git_storage, packages, security, search) and `projects` to repositories (\"owner/name\"). Returns `totals`: `price_micros` less `discount_micros`, `included_micros` and `credits_micros` is `charged_micros`, what is left for the workspace to pay; `pending_micros` is metered this month and charged when it closes; `cost_micros` is what it cost g1t. Then `days` (each day and product with usage), `products` (every family, with its meters: quantity, unit, amount, a `daily` amount for each day of the range, any `allowance`, the split `by_project`, and a `note` where the quantity needs one: the agent rate's meters, `agent_rate` and `agent_rate_own` (on the workspace's own model key), count weighted tokens and name the weights), `projects` (every repository with usage in the range), `models` (the agent's input, output, cache-read and cache-write tokens by model, most first), `by_agent` and `by_person` (the agent product at price by the agent that did the work, by handle, and by who asked, by username; `g1t` is g1t's own runs on repositories, an empty key is work attributed to no one; each sums to the agent product), and the AI credit and other credit left now. With `group_by` (`product`, `project` or `day`), `groups` adds up the range that way. Amounts are whole millionths of a dollar. Members of the workspace only."
1770+ "A workspace's usage over a range of days, at price, and what paid for it. `from` and `until` are UTC days, `YYYY-MM-DD`, with `until` included and at most 400 days in all; left out, the current month so far. `products` narrows it to product families (agent, sandboxes, gateway, deployments, git_storage, packages, security, search) and `projects` to repositories (\"owner/name\"). Returns `totals`: `price_micros` less `discount_micros`, `included_micros` and `credits_micros` is `charged_micros`, what is left for the workspace to pay; `pending_micros` is metered this month and charged when it closes, counted in any range that reaches into the current month, and `pending_charged_micros` is what of it will be charged then, after the discount and what g1t covers; `cost_micros` is what it cost g1t. Then `days` (each day and product with usage), `products` (every family, with its meters: quantity, unit, amount, a `daily` amount for each day of the range, any `allowance`, the split `by_project`, and a `note` where the quantity needs one: the agent rate's meters, `agent_rate` and `agent_rate_own` (on the workspace's own model key), count weighted tokens and name the weights), `projects` (every repository with usage in the range), `models` (the agent's input, output, cache-read and cache-write tokens by model, most first), `by_agent` and `by_person` (the agent product at price by the agent that did the work, by handle, and by who asked, by username; `g1t` is g1t's own runs on repositories, an empty key is work attributed to no one; each sums to the agent product), and the AI credit and other credit left now. With `group_by` (`product`, `project` or `day`), `groups` adds up the range that way. Amounts are whole millionths of a dollar. Members of the workspace only."
17711771 }
17721772 Op::GetBudget => {
17731773 "A workspace's budget: its monthly spend limit (`amount_micros`; `automatic` is true while the owners have not set one, and it is then $200 or twice last month's spend), what was charged this month (`spent_micros`), the most the owners may set it to themselves (`max_amount_micros`), its `alerts` (percent of the limit, each emailed to the owners once a month), whether usage pauses at the limit (`pause_at_limit`), the `webhook` told of each alert, and `state`: `ok`, `warning` or `stopped`, with a `message` when work is stopped or close to it. Members of the workspace only."
+1−0
62416241 "credits_micros": 18000000,
62426242 "charged_micros": 10210000,
62436243 "pending_micros": 1340000,
6244+ "pending_charged_micros": 1340000,
62446245 "cost_micros": 40100000
62456246 },
62466247 "days": [
+20−2
538538 | **Agents** | The agent product within Spent: model tokens, the [agent rate](#the-agent-rate) and agents' sandbox time, for every agent's chat replies, sessions and runs on repositories. Each entry names the agent that did the work (g1t's own runs on your repositories are **@g1t**) and the person who asked, so **by agent** and **by person** are the same money sliced two ways, and the agents add up to the product. | The top bar's spend pill, Spend's **Agents** tile and its **Agents** and **People** slices, Usage's **Agent** product |
539539 | **Charged** | What is left for the workspace to pay this month: usage at price, less your discount, less what included usage, the trial, a pool or g1t paid, less what [credit](#credits-from-g1t) paid. Never below zero: a workspace with a 100% discount is charged exactly nothing. Usage metered through the month and charged when it closes (storage, git operations, scans, embeddings, domains, app traffic) counts now on the same terms. | Billing's plan card, Spend's **Charged**, the top bar's **Workspace** view, and the figure your [spend limit](#your-spend-limit) is measured against |
540540
541+**This month** is the calendar month in UTC, from its first day to today,
542+on every page: the top bar's pill, Spend's **This month**, Home's "this
543+month so far" and Usage's current billing cycle ask billing for the same
544+days and show the same figure. Usage metered through the month and
545+charged when it closes (storage, git operations, scans, embeddings,
546+domains, app traffic) has no day of its own, so it counts in any range
547+that reaches into the current month, and Usage's receipt says what of it
548+will be charged at the close on your terms: your discount and included
549+usage come off it then, the same as the rest.
550+
551+Every amount is written the same way: to the cent, rounded half up on
552+whole millionths of a dollar, so the same sum never reads differently on
553+two pages. Under a cent reads **<$0.01** rather than $0.00 on a total,
554+and exactly nothing is $0.00. Where the fraction of a cent is the point,
555+the [statement](#the-statement), a session's receipt, the
556+[price book](https://g1t.sh/pricing) and an agent's effort costs, amounts carry up to
557+four places (`$0.0063`).
558+
541559 The [agent budgets](/guides/agent-budgets/) count the same entries at
542560 the same price, before any discount or included usage: an agent's chat
543561 replies and sessions against its own budget, its team's, the person's and
545563 predictable; the spend limit is on what is charged.
546564
547565 Through the API, `GET /workspaces/:workspace/usage` answers with the
548−products, `by_agent` and `by_person`, and `totals.charged_micros`;
566+products, `by_agent` and `by_person`, and `totals.charged_micros`, with `totals.pending_charged_micros` for what of the pending usage the close will charge;
549567 `GET /workspaces/:workspace/budget` answers with the spend limit and
550568 `spent_micros`, the same charged figure.
551569
11201138 before included usage or a pool paid for it) and a `quantity` such as
11211139 *42 build minutes*, each at price (what was charged plus what paid for it), as Usage measures it.
11221140
1123−**`usage_report`** (`workspace`, `viewer`, `from`, `until`, optional `products` and `projects`; members only) is what the Usage page reads: totals (`priceMicros`, `discountMicros`, `includedMicros`, `creditsMicros`, `chargedMicros`, `pendingMicros`), each day's usage by product, and every product family with its meters, their daily figures and their projects.
1141+**`usage_report`** (`workspace`, `viewer`, `from`, `until`, optional `products` and `projects`; members only) is what the Usage page reads: totals (`priceMicros`, `discountMicros`, `includedMicros`, `creditsMicros`, `chargedMicros`, `pendingMicros`, `pendingChargedMicros`), each day's usage by product, and every product family with its meters, their daily figures and their projects.
11241142
11251143 **`reserve`** holds the work's estimated cost before it starts, so starts
11261144 at the same moment cannot overshoot together. `kind` is `agent`, `check`,
+0−0

Binary or large file; its contents are not shown.

+2−3
4343 import { shownStep } from "../lib/agent-step";
4444 import { inlinePlain } from "../lib/inline-markdown";
4545 import { InlineMarkdown } from "./inline-markdown";
46+import { microsOf, money } from "../lib/money";
4647
4748 /** How often a page with something running asks again. */
4849 export const LIVE_MS = 4000;
5354 }
5455
5556 export function formatCost(usd: number | null | undefined): string | null {
56− if (usd == null) return null;
57− if (usd > 0 && usd < 0.01) return "<$0.01";
58− return `$${usd.toFixed(2)}`;
57+ return usd == null ? null : money(microsOf(usd));
5958 }
6059
6160 function span(ms: number): string {
+1−1
2323 import { type BuilderDefinition, type ChangeRow, changeRows, integrationHint } from "../../lib/agent-builder";
2424 import { PRESETS, TIER_LABELS, cleanHandle, dollarsField, microsFromDollars } from "../../lib/agent-form";
2525 import { cn } from "../../lib/cn";
26−import { money } from "../../lib/usage";
26+import { money } from "../../lib/money";
2727
2828 const FIELD =
2929 "w-full rounded-md border border-line bg-bg px-3 py-2 text-sm outline-none transition-colors placeholder:text-faint hover:border-line-strong focus:border-accent-dim";
+1−1
1919 import { Field, FieldDescription, FieldError, FieldLabel } from "../ui/field";
2020 import { Input, InputAddon, InputGroup } from "../ui/input";
2121 import { dollarsField } from "../../lib/agent-form";
22−import { money } from "../../lib/usage";
22+import { money } from "../../lib/money";
2323 import { PrivateTitle, SpendOfCap } from "./parts";
2424
2525 /** What Agents mode's actions answer. */
+1−1
1010 import { TimeAgo } from "../ui";
1111 import { Card } from "../ui/card";
1212 import { cn } from "../../lib/cn";
13−import { money } from "../../lib/usage";
13+import { money } from "../../lib/money";
1414 import { kindLabel, meterTone, monthDays, sessionStatus, shareOf, shortDay, topSlices, whereLabel } from "./format";
1515
1616 /** Where a session's page is. */
+5−5
1212
1313 import type { AiCredit, BillingDetails, FeatureState, Limit, UsageReport } from "@g1t/contracts";
1414
15−import { PLUS_TAX, type PlanStatus, cardFeeCents, dollars, feeAndTax, wholeDollars } from "../lib/billing";
16−import { money } from "../lib/usage";
15+import { PLUS_TAX, type PlanStatus, cardFeeCents, feeAndTax } from "../lib/billing";
16+import { money, wholeDollars } from "../lib/money";
1717 import { Card } from "./billing";
1818 import { ErrorText, SubmitButton } from "./ui";
1919 import { Checkbox } from "./ui/checkbox";
106106 <span className="block text-xs text-faint">with {wholeDollars(report?.included?.of ?? 10_000_000)} of usage included</span>
107107 {status.kind !== "comped" && status.kind !== "enterprise" && (
108108 <span className="block text-xs text-faint">
109− {plan?.cardFeeCents ? `+ ${dollars(plan.cardFeeCents * 10_000)} card processing fee, ` : ""}
109+ {plan?.cardFeeCents ? `+ ${money(plan.cardFeeCents * 10_000)} card processing fee, ` : ""}
110110 {plan?.cardFeeCents ? PLUS_TAX : "Plus tax where it applies"}
111111 </span>
112112 )}
214214 // What is chosen, so the fee shows before Stripe's page does.
215215 const [chosenCents, setChosenCents] = useState(2_500);
216216 const chosenFee = cardFeeCents(chosenCents, fee);
217− const stripeFee = `Stripe's ${(fee.percentMicros / 10_000).toFixed(1)}% + ${dollars(fee.fixedCents * 10_000)}`;
217+ const stripeFee = `Stripe's ${(fee.percentMicros / 10_000).toFixed(1)}% + ${money(fee.fixedCents * 10_000)}`;
218218 const feeText = !fee.on
219219 ? `${feeAndTax(0)}.`
220220 : chosenCents > 0
237237 ? "Agent and AI Gateway usage is free for this workspace under its discount: shown at its price, then the discount."
238238 : credit.postpaid
239239 ? "This workspace's enterprise is invoiced for Agent and AI Gateway usage after use: no credit needed."
240− : `Prepaid credit for Agent and AI Gateway usage, spent before anything else. Models at the provider's price${credit.modelMarkupPercent ? ` plus ${credit.modelMarkupPercent}%` : ""}, plus the agent rate${rate > 0 ? ` (${dollars(rate)} per million tokens)` : ""}. Credit expires ${credit.expiresDays === 365 ? "1 year" : `${credit.expiresDays} days`} after purchase.`
240+ : `Prepaid credit for Agent and AI Gateway usage, spent before anything else. Models at the provider's price${credit.modelMarkupPercent ? ` plus ${credit.modelMarkupPercent}%` : ""}, plus the agent rate${rate > 0 ? ` (${money(rate)} per million tokens)` : ""}. Credit expires ${credit.expiresDays === 365 ? "1 year" : `${credit.expiresDays} days`} after purchase.`
241241 }
242242 aside={
243243 <p className="shrink-0 sm:text-right">
+10−11
2020 alertTone,
2121 cardFeeCents,
2222 creditLine,
23− dollars,
2423 gigabytes,
2524 requestStatus,
2625 share,
2726 shortDay,
2827 shownMeters,
2928 spendRange,
30− wholeDollars,
3129 } from "../lib/billing";
30+import { money, wholeDollars } from "../lib/money";
3231 import { ErrorText, SubmitButton } from "./ui";
3332 import { Badge } from "./ui/badge";
3433 import { RadioGroup, RadioGroupItem } from "./ui/radio-group";
126125 <div className="flex flex-wrap justify-between gap-x-4 text-sm">
127126 <span className="text-muted">{label}</span>
128127 <span className="tabular-nums">
129− {dollars(used)}
130− {of != null && <span className="text-faint"> of {dollars(of)}</span>}
128+ {money(used)}
129+ {of != null && <span className="text-faint"> of {money(of)}</span>}
131130 </span>
132131 </div>
133132 <div className="mt-1.5 h-1.5 overflow-hidden rounded-full bg-line" role="presentation">
236235 <span className="text-sm text-muted"> / month</span>
237236 <span className="block text-xs text-faint">per workspace, never per seat</span>
238237 <span className="block text-xs text-faint">
239− {plan?.cardFeeCents ? `+ ${dollars(plan.cardFeeCents * 10_000)} card processing fee, ${PLUS_TAX}` : "Plus tax where it applies"}
238+ {plan?.cardFeeCents ? `+ ${money(plan.cardFeeCents * 10_000)} card processing fee, ${PLUS_TAX}` : "Plus tax where it applies"}
240239 </span>
241240 </p>
242241 }
348347 <span className="block truncate text-xs text-faint">{row.quantity ?? "None yet"}</span>
349348 )}
350349 </span>
351− <span className={`shrink-0 tabular-nums ${row.micros > 0 ? "" : "text-faint"}`}>{dollars(row.micros)}</span>
350+ <span className={`shrink-0 tabular-nums ${row.micros > 0 ? "" : "text-faint"}`}>{money(row.micros)}</span>
352351 </li>
353352 ))}
354353 </ul>
356355 {/* At price, before the plan's included usage, the trial and the pools paid
357356 their part: Usage shows what was charged. */}
358357 <span className="font-medium">Total at price</span>
359− <span className="font-medium tabular-nums">{dollars(total)}</span>
358+ <span className="font-medium tabular-nums">{money(total)}</span>
360359 </div>
361360 <p className="mt-2 text-xs text-faint">
362361 {comped
363362 ? "What this workspace's usage comes to at price. Its 100% discount takes all of it off."
364363 : on
365− ? `Drawn from the included usage first, then charged up to your spend limit. Projects, previews and repositories are never charged, and the first ${freeStorage} of private storage and ${freeGit} git operations a month are free. App traffic, custom domains, storage and git operations are counted through the month and charged when it closes.`
364+ ? `Drawn from the included usage first, then charged up to your spend limit. Projects, previews and repositories are never charged, and the first ${freeStorage} of private storage and ${freeGit} git operations a month are free. App traffic, custom domains, storage and git operations are counted through the month and charged when it closes, after the included usage and any discount, like the rest.`
366365 : `The forge is free: ${freeStorage} of private storage and ${freeGit} git operations a month. Agents run from the trial, and checks, workflows and the merge queue on public repositories from the open-source pool; together they pay part of this total: Usage shows what was charged.`}
367366 </p>
368367 </div>
628627 aside={
629628 <p className="shrink-0 sm:text-right">
630629 <span className="block text-xs text-muted">Credit left</span>
631− <span className="text-xl font-semibold tabular-nums">{dollars(credits.leftMicros)}</span>
630+ <span className="text-xl font-semibold tabular-nums">{money(credits.leftMicros)}</span>
632631 </p>
633632 }
634633 >
664663 cardFee?: { on: boolean; percentMicros: number; fixedCents: number } | null;
665664 error?: string;
666665 }) {
667− const fees = PREPAY.presets.map((amount) => `${dollars(cardFeeCents(amount * 100, cardFee) * 10_000)} on ${wholeDollars(amount * 1_000_000)}`);
666+ const fees = PREPAY.presets.map((amount) => `${money(cardFeeCents(amount * 100, cardFee) * 10_000)} on ${wholeDollars(amount * 1_000_000)}`);
668667 return (
669668 <Card
670669 id="prepay"
674673 aside={
675674 <p className="shrink-0 sm:text-right">
676675 <span className="block text-xs text-muted">Prepaid balance</span>
677− <span className="text-xl font-semibold tabular-nums">{dollars(prepaidMicros)}</span>
676+ <span className="text-xl font-semibold tabular-nums">{money(prepaidMicros)}</span>
678677 </p>
679678 }
680679 >
+2−2
1616 import { Button } from "../ui/button";
1717 import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
1818 import { Skeleton } from "../ui/skeleton";
19−import { formatDollars } from "../../lib/agent-form";
19+import { wholeDollars } from "../../lib/money";
2020 import type { UserCard } from "../../lib/hovercard";
2121 import { localTime } from "../../lib/time-zone";
2222
182182 <p className="flex justify-between text-xs">
183183 <span>This month</span>
184184 <span className="tabular-nums">
185− {formatDollars(agent.spent_month_micros)} of {formatDollars(cap)}
185+ {wholeDollars(agent.spent_month_micros)} of {wholeDollars(cap)}
186186 </span>
187187 </p>
188188 <div className="mt-1 h-1.5 overflow-hidden rounded-full bg-line">
+2−2
1717 import { Card } from "./ui/card";
1818 import { cn } from "../lib/cn";
1919 import { EFFORT_OPTIONS, acceptedLabel, costAt, costLine, effortLabel, savingLabel, totalSaving } from "../lib/effort";
20−import { money } from "../lib/usage";
20+import { money } from "../lib/money";
2121
2222 /**
2323 * The five settings as one segmented control, radio inputs underneath so
105105 {effortLabel(level.effort)}
106106 {costs.effort === level.effort && <span className="ml-1.5 text-faint">now</span>}
107107 </td>
108− <td className="py-1.5 pr-3">{at ? money(at.typical_micros!) : <span className="text-faint">Not measured</span>}</td>
108+ <td className="py-1.5 pr-3">{at ? money(at.typical_micros!, { precise: true }) : <span className="text-faint">Not measured</span>}</td>
109109 <td className="py-1.5 pr-3 text-muted">{level.sessions}</td>
110110 <td className="py-1.5 text-muted">{acceptedLabel(at) || "—"}</td>
111111 </tr>
+2−2
88 import type { GatewayRequest } from "@g1t/contracts";
99
1010 import { cacheKinds, duration, formatLabel, servedBy, shortCount, statusTone, tokenKinds } from "../lib/gateway";
11−import { money } from "../lib/usage";
11+import { money } from "../lib/money";
1212 import { TimeAgo } from "./ui";
1313 import { Badge } from "./ui/badge";
1414 import { Card } from "./ui/card";
7272 </span>
7373 </Hint>
7474 ) : (
75− money(request.chargedMicros)
75+ money(request.chargedMicros, { precise: true })
7676 )}
7777 </td>
7878 <td className="px-3 py-2 whitespace-nowrap">
+5−4
4242 OUTCOME_LABEL,
4343 SOURCE_LABEL,
4444 WINDOWS,
45− dollars,
4645 trendLabel,
4746 waited,
4847 whenShort,
4948 } from "../lib/home";
5049 import { cn } from "../lib/cn";
50+import { money } from "../lib/money";
5151 import { ButtonLink } from "./ui";
5252 import { Skeleton } from "./ui/skeleton";
5353 import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip";
651651 <Quiet>Billing didn&apos;t answer, so spend can&apos;t be shown right now.</Quiet>
652652 ) : (
653653 <div className="px-5 pb-5">
654− <div className="text-3xl font-semibold tracking-tight text-fg tabular-nums">{dollars(spend.totalMicros)}</div>
654+ <div className="text-3xl font-semibold tracking-tight text-fg tabular-nums">{money(spend.totalMicros)}</div>
655655 <p className="mt-1 text-xs text-muted">
656− {spend.from === spend.to ? utcDay(spend.from) : `${utcDay(spend.from)} – ${utcDay(spend.to)}`} · {dollars(spend.monthMicros)} this month so far
656+ {spend.from === spend.to ? utcDay(spend.from) : `${utcDay(spend.from)} – ${utcDay(spend.to)}`}
657+ {spend.monthMicros != null && ` · ${money(spend.monthMicros)} this month so far`}
657658 </p>
658659 {spend.lines.length === 0 ? (
659660 <p className="mt-4 text-sm text-muted">Nothing on the statement {inSpan(span)}.</p>
669670 <li key={line.kind} className="flex items-center gap-2 text-sm">
670671 <span className={`size-2 shrink-0 rounded-[2px] ${kindColour(line.kind)}`} aria-hidden />
671672 <span className="min-w-0 grow truncate text-fg-soft">{line.kind}</span>
672− <span className="text-fg tabular-nums">{dollars(line.micros)}</span>
673+ <span className="text-fg tabular-nums">{money(line.micros)}</span>
673674 </li>
674675 ))}
675676 </ul>
+3−3
2323 parseTab,
2424 signedPercent,
2525 sortRows,
26− usd,
2726 whyFor,
2827 } from "../lib/mission-control";
2928 import { cn } from "../lib/cn";
29+import { microsOf, money } from "../lib/money";
3030 import { AgentComposer, type ComposerResult } from "./agent-composer";
3131 import { AgentSetup } from "./agent-setup";
3232 import { InboxNeedsCard } from "./inbox";
5454 /** Rows a tab shows before "See all". */
5555 const ROWS = 6;
5656
57−const dollars = (micros: number) => `$${(Math.max(0, micros) / 1_000_000).toFixed(2)}`;
57+const dollars = (micros: number) => money(Math.max(0, micros));
5858 const plural = (n: number, one: string, many = `${one}s`) => `${n.toLocaleString("en-US")} ${n === 1 ? one : many}`;
5959
6060 // --- Small pieces -----------------------------------------------------------------
11511151 to={`/${workspace}/-/usage`}
11521152 className="mt-4 flex items-center justify-between border-t border-line pt-3 text-xs text-muted hover:text-fg"
11531153 >
1154− <span>Usage at price this week: {usd(stats.weekCost)}</span>
1154+ <span>Usage at price this week: {money(microsOf(stats.weekCost))}</span>
11551155 <ChevronRight size={12} />
11561156 </Link>
11571157 )}
+2−1
1515
1616 import type { IssueProgress, Plan } from "@g1t/contracts";
1717 import { Avatar } from "./ui/avatar";
18+import { money } from "../lib/money";
1819
1920 type Look = { label: string; icon: ReactNode; ring: string; text: string; bar: string; live?: boolean };
2021
233234 ["Needs you", String(needsYou), needsYou > 0 ? "text-warn" : "text-muted"],
234235 [
235236 "Agents have cost",
236− costMicros == null ? "—" : `$${(costMicros / 1_000_000).toFixed(2)}`,
237+ costMicros == null ? "—" : money(costMicros),
237238 "text-fg",
238239 ],
239240 ].map(([label, value, tone]) => (
+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

This change is too large to show in full.