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 site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 1 | import { ArrowRight, Bot, Cloud, Laptop, Plus, ServerCog, Workflow } from "lucide-react"; |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 2 | import type { ReactNode } from "react"; |
| 3 | import { Link } from "react-router"; | |
| 4 | ||
| 5 | import { RUN_KIND_LABEL, type Runner, type RunKind } from "@g1t/contracts"; | |
| 6 | ||
| 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. | 7 | import { money } from "../lib/money"; |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 8 | import { type CloudWork, machineTime, perMinute } from "../lib/runners"; |
| 9 | import type { RunnersAction, RunnersPageData } from "../lib/runners.server"; | |
| Merge the desktop app's runner: it starts with the app for the signed-in person, sandboxed by default and running nothing where no sandbox is available yet, registers through the site, keeps itself up to date, and says everywhere what it is doing, why it is not, and how to fix it. | 10 | import { DesktopRunners } from "./desktop-runners"; |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 11 | import { Groups, NewRunner, RunnerRow, RunnerSettingsForm, STATUS } from "./runners"; |
| 12 | import { EmptyState, ErrorText, TimeAgo } from "./ui"; | |
| 13 | import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip"; | |
| 14 | ||
| 15 | /** The most of what runs on g1t's cloud the card lists before saying how many more. */ | |
| 16 | const CLOUD_SHOWN = 6; | |
| 17 | ||
| 18 | function Section({ id, title, about, action, children }: { id?: string; title: string; about?: ReactNode; action?: ReactNode; children: ReactNode }) { | |
| 19 | return ( | |
| 20 | <section id={id} className="scroll-mt-6 space-y-3"> | |
| 21 | <div className="flex flex-wrap items-end justify-between gap-x-4 gap-y-1"> | |
| 22 | <div className="min-w-0"> | |
| 23 | <h2 className="text-base font-semibold tracking-tight">{title}</h2> | |
| 24 | {about && <div className="mt-0.5 text-sm text-muted">{about}</div>} | |
| 25 | </div> | |
| 26 | {action} | |
| 27 | </div> | |
| 28 | {children} | |
| 29 | </section> | |
| 30 | ); | |
| 31 | } | |
| 32 | ||
| 33 | /** One figure in a place's card: a label and its value. */ | |
| 34 | function Figure({ label, hint, children }: { label: string; hint?: string; children: ReactNode }) { | |
| 35 | return ( | |
| 36 | <div className="flex items-baseline justify-between gap-3 py-2 text-sm"> | |
| 37 | <dt className="text-muted"> | |
| 38 | {hint ? ( | |
| 39 | <Tooltip> | |
| 40 | <TooltipTrigger asChild> | |
| 41 | <span className="cursor-help underline decoration-line-strong decoration-dotted underline-offset-4">{label}</span> | |
| 42 | </TooltipTrigger> | |
| 43 | <TooltipContent>{hint}</TooltipContent> | |
| 44 | </Tooltip> | |
| 45 | ) : ( | |
| 46 | label | |
| 47 | )} | |
| 48 | </dt> | |
| 49 | <dd className="min-w-0 text-right text-fg tabular-nums">{children}</dd> | |
| 50 | </div> | |
| 51 | ); | |
| 52 | } | |
| 53 | ||
| 54 | function Unknown({ what }: { what: string }) { | |
| 55 | return <span className="text-faint">{what} didn't answer</span>; | |
| 56 | } | |
| 57 | ||
| 58 | function PlaceCard({ icon, title, tag, about, headline, children }: { icon: ReactNode; title: string; tag: ReactNode; about: string; headline: ReactNode; children: ReactNode }) { | |
| 59 | return ( | |
| 60 | <section className="flex min-w-0 flex-col rounded-2xl border border-line bg-surface"> | |
| 61 | <header className="px-5 pt-4"> | |
| 62 | <div className="flex items-center gap-2"> | |
| 63 | <span className="grid size-7 shrink-0 place-items-center rounded-lg bg-raised text-fg-soft">{icon}</span> | |
| 64 | <h2 className="text-sm font-semibold">{title}</h2> | |
| 65 | <span className="ml-auto">{tag}</span> | |
| 66 | </div> | |
| 67 | <p className="mt-2 text-sm leading-relaxed text-muted">{about}</p> | |
| 68 | </header> | |
| 69 | <div className="px-5 pt-4">{headline}</div> | |
| 70 | <dl className="mt-2 divide-y divide-line border-t border-line px-5 py-1">{children}</dl> | |
| 71 | </section> | |
| 72 | ); | |
| 73 | } | |
| 74 | ||
| 75 | function kindLabel(work: CloudWork): string { | |
| 76 | if (work.kind === "workflow") return "Workflow job"; | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 77 | return RUN_KIND_LABEL[work.detail as RunKind] ?? "Sandbox run"; |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 78 | } |
| 79 | ||
| 80 | function CloudList({ data }: { data: RunnersPageData }) { | |
| 81 | const cloud = data.cloud; | |
| 82 | if (!cloud) return <p className="px-5 py-4 text-sm text-muted">What runs on g1t's cloud can't be read right now.</p>; | |
| 83 | if (cloud.running.length === 0) { | |
| 84 | return ( | |
| 85 | <p className="px-5 py-4 text-sm text-muted"> | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 86 | Nothing is running here now. A sandbox starts for each run or job and stops when it ends{cloud.queued > 0 ? `; ${cloud.queued} waiting to start` : ""}. |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 87 | </p> |
| 88 | ); | |
| 89 | } | |
| 90 | const shown = cloud.running.slice(0, CLOUD_SHOWN); | |
| 91 | const rest = cloud.running.length - shown.length; | |
| 92 | return ( | |
| 93 | <ul className="divide-y divide-line"> | |
| 94 | {shown.map((work) => ( | |
| 95 | <li key={`${work.kind}:${work.id}`} className="flex items-center gap-3 px-5 py-2.5"> | |
| 96 | <span className="grid size-6 shrink-0 place-items-center rounded-md bg-info/12 text-info" aria-hidden> | |
| 97 | {work.kind === "agent" ? <Bot size={13} /> : <Workflow size={13} />} | |
| 98 | </span> | |
| 99 | <div className="min-w-0 grow"> | |
| 100 | <Link to={work.href} className="block truncate text-sm text-fg hover:underline"> | |
| 101 | {work.title} | |
| 102 | </Link> | |
| 103 | <p className="truncate text-xs text-muted"> | |
| 104 | {kindLabel(work)} · {work.repo} | |
| 105 | </p> | |
| 106 | </div> | |
| 107 | {work.startedAt && ( | |
| 108 | <span className="shrink-0 text-xs text-faint"> | |
| 109 | <TimeAgo at={work.startedAt} /> | |
| 110 | </span> | |
| 111 | )} | |
| 112 | </li> | |
| 113 | ))} | |
| 114 | {(rest > 0 || cloud.more || cloud.queued > 0) && ( | |
| 115 | <li className="px-5 py-2.5 text-xs text-muted"> | |
| 116 | {[rest > 0 || cloud.more ? `${rest > 0 ? rest : "More"}${cloud.more ? "+" : ""} more running` : null, cloud.queued > 0 ? `${cloud.queued} waiting to start` : null] | |
| 117 | .filter(Boolean) | |
| 118 | .join(" · ")} | |
| 119 | </li> | |
| 120 | )} | |
| 121 | </ul> | |
| 122 | ); | |
| 123 | } | |
| 124 | ||
| 125 | function StatusCounts({ runners }: { runners: Runner[] }) { | |
| 126 | const counts = { busy: 0, online: 0, offline: 0 } as Record<Runner["status"], number>; | |
| 127 | for (const runner of runners) counts[runner.status] += 1; | |
| 128 | return ( | |
| 129 | <ul className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-muted"> | |
| 130 | {(["busy", "online", "offline"] as const).map((status) => ( | |
| 131 | <li key={status} className="flex items-center gap-1.5"> | |
| 132 | <span className={`size-2 rounded-full ${STATUS[status].dot}`} aria-hidden /> | |
| 133 | <span className="text-fg tabular-nums">{counts[status]}</span> {STATUS[status].label.toLowerCase()} | |
| 134 | </li> | |
| 135 | ))} | |
| 136 | </ul> | |
| 137 | ); | |
| 138 | } | |
| 139 | ||
| 140 | /** The workspace's Runners page: g1t's cloud and its own runners, side by side. */ | |
| 141 | export function RunnersPage({ data, action, slug }: { data: RunnersPageData; action: RunnersAction | undefined; slug: string }) { | |
| 142 | const own = data.runners; | |
| 143 | const online = own.filter((runner) => runner.status !== "offline").length; | |
| 144 | const cost = data.cost; | |
| 145 | const running = data.cloud?.running.length ?? null; | |
| 146 | const usage = `/${slug}/-/usage`; | |
| 147 | return ( | |
| 148 | <div className="space-y-10"> | |
| 149 | <header className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between"> | |
| 150 | <div className="min-w-0"> | |
| 151 | <h1 className="text-[1.75rem] leading-tight font-semibold tracking-tight">Runners</h1> | |
| 152 | <p className="mt-1.5 max-w-2xl text-sm leading-relaxed text-muted"> | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 153 | The machines your workflow jobs, checks and merge queue run on. g1t's cloud needs nothing set up; your own runners are any machine with{" "} |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 154 | <code className="font-mono text-fg-soft">g1t-runner</code> on it, and time on them is free. |
| 155 | </p> | |
| 156 | </div> | |
| 157 | <a | |
| 158 | href="#add" | |
| 159 | className="inline-flex h-9 shrink-0 items-center gap-1.5 self-start rounded-lg bg-accent px-3.5 text-sm font-medium text-bg transition-colors hover:bg-accent-hover" | |
| 160 | > | |
| 161 | <Plus size={15} /> | |
| 162 | Add a runner | |
| 163 | </a> | |
| 164 | </header> | |
| 165 | ||
| 166 | {(action?.notice || action?.error || data.error) && ( | |
| 167 | <div> | |
| 168 | {action?.notice && <p className="text-sm text-success">{action.notice}</p>} | |
| 169 | <ErrorText>{action?.error ?? data.error ?? null}</ErrorText> | |
| 170 | </div> | |
| 171 | )} | |
| 172 | ||
| 173 | <div className="grid items-start gap-5 lg:grid-cols-2"> | |
| 174 | <PlaceCard | |
| 175 | icon={<Cloud size={15} />} | |
| 176 | title="g1t cloud" | |
| 177 | tag={<span className="rounded-full bg-raised px-2 py-0.5 text-xs text-fg-soft">Managed by g1t</span>} | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 178 | about="A fresh sandbox for every run and workflow job, stopped when it ends. Billed by the second at the price below." |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 179 | headline={ |
| 180 | <div className="flex items-baseline gap-2"> | |
| 181 | <span className="text-3xl font-semibold tracking-tight tabular-nums">{running ?? "–"}</span> | |
| 182 | <span className="text-sm text-muted">running now</span> | |
| 183 | </div> | |
| 184 | } | |
| 185 | > | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 186 | <Figure label="This month" hint="Sandbox time on your usage, at price, from the first of the month."> |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 187 | {cost ? ( |
| 188 | <> | |
| 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. | 189 | {machineTime(cost.cloudSeconds)} · {money(cost.cloudMicros)} |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 190 | </> |
| 191 | ) : ( | |
| 192 | <Unknown what="Billing" /> | |
| 193 | )} | |
| 194 | </Figure> | |
| 195 | {data.prices ? ( | |
| 196 | <Figure label="Price" hint={`From g1t's price book: ${data.prices.map((price) => price.title).join("; ")}.`}> | |
| 197 | <span className="flex flex-wrap justify-end gap-x-1"> | |
| 198 | {data.prices.map((price, at) => ( | |
| 199 | <span key={price.meter} className="whitespace-nowrap"> | |
| 200 | {at > 0 && "+ "} | |
| 201 | {perMinute(price.perMinuteMicros)}/{price.unit} | |
| 202 | </span> | |
| 203 | ))} | |
| 204 | </span> | |
| 205 | </Figure> | |
| 206 | ) : ( | |
| 207 | <Figure label="Price"> | |
| 208 | <Unknown what="Billing" /> | |
| 209 | </Figure> | |
| 210 | )} | |
| 211 | </PlaceCard> | |
| 212 | ||
| 213 | <PlaceCard | |
| 214 | icon={<ServerCog size={15} />} | |
| 215 | title="Your runners" | |
| 216 | tag={<span className="rounded-full bg-success/12 px-2 py-0.5 text-xs font-medium text-success">Free</span>} | |
| 217 | about="Your own machines: Linux, macOS or Windows, anywhere they can reach g1t. They only connect out, and take the work whose labels they have." | |
| 218 | headline={ | |
| 219 | <div className="space-y-2"> | |
| 220 | <div className="flex items-baseline gap-2"> | |
| 221 | <span className="text-3xl font-semibold tracking-tight tabular-nums">{own.length === 0 ? 0 : online}</span> | |
| 222 | <span className="text-sm text-muted">{own.length === 0 ? "runners yet" : `of ${own.length} online`}</span> | |
| 223 | </div> | |
| 224 | {own.length > 0 && <StatusCounts runners={own} />} | |
| 225 | </div> | |
| 226 | } | |
| 227 | > | |
| 228 | <Figure label="This month" hint="Self-hosted runner time on your usage, from the first of the month. It is never charged."> | |
| 229 | {cost ? ( | |
| 230 | <> | |
| 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. | 231 | {machineTime(cost.ownSeconds)} · {money(0)} |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 232 | </> |
| 233 | ) : ( | |
| 234 | <Unknown what="Billing" /> | |
| 235 | )} | |
| 236 | </Figure> | |
| 237 | <Figure label="Waiting for one of them"> | |
| 238 | {data.waiting ? ( | |
| 239 | data.waiting.jobs + data.waiting.tasks === 0 ? ( | |
| 240 | "Nothing" | |
| 241 | ) : ( | |
| 242 | [ | |
| 243 | data.waiting.jobs > 0 ? `${data.waiting.jobs} ${data.waiting.jobs === 1 ? "job" : "jobs"}` : null, | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 244 | data.waiting.tasks > 0 ? `${data.waiting.tasks} sandbox ${data.waiting.tasks === 1 ? "run" : "runs"}` : null, |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 245 | ] |
| 246 | .filter(Boolean) | |
| 247 | .join(", ") | |
| 248 | ) | |
| 249 | ) : ( | |
| 250 | <Unknown what="Actions" /> | |
| 251 | )} | |
| 252 | </Figure> | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 253 | <Figure label="Takes sandbox runs"> |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 254 | {data.settings ? (data.settings.agentsOnSelfHosted ? `Yes, labelled ${data.settings.agentLabels.join(", ")}` : "No") : "–"} |
| 255 | </Figure> | |
| 256 | </PlaceCard> | |
| 257 | </div> | |
| 258 | ||
| 259 | <div className="grid items-start gap-5 lg:grid-cols-2"> | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 260 | <Section title="On g1t cloud now" about="Sandbox runs and workflow jobs in g1t's sandboxes."> |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 261 | <div className="rounded-2xl border border-line bg-surface"> |
| 262 | <CloudList data={data} /> | |
| 263 | </div> | |
| 264 | </Section> | |
| 265 | <Section | |
| 266 | title="Machine time" | |
| 267 | about={cost ? `${cost.from} to ${cost.until}, as your usage shows it.` : "From your usage."} | |
| 268 | action={ | |
| 269 | <Link to={usage} className="inline-flex items-center gap-1 text-xs text-muted hover:text-fg"> | |
| 270 | Usage | |
| 271 | <ArrowRight size={12} /> | |
| 272 | </Link> | |
| 273 | } | |
| 274 | > | |
| 275 | <TimeSplit data={data} /> | |
| 276 | </Section> | |
| 277 | </div> | |
| 278 | ||
| 279 | <Section title="Your runners" about={own.length === 0 ? "None yet." : `${online} of ${own.length} online. A runner that hasn't been heard from for 90 seconds is offline.`}> | |
| 280 | {own.length === 0 ? ( | |
| 281 | <EmptyState title="No runners of your own yet"> | |
| 282 | <a href="#add" className="underline underline-offset-2"> | |
| 283 | Add one | |
| 284 | </a>{" "} | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 285 | to run jobs on your hardware. It connects out to g1t; nothing needs to reach the machine. |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 286 | </EmptyState> |
| 287 | ) : ( | |
| 288 | <ul className="divide-y divide-line rounded-2xl border border-line bg-surface"> | |
| 289 | {own.map((runner) => ( | |
| 290 | <RunnerRow key={runner.id} runner={runner} manage /> | |
| 291 | ))} | |
| 292 | </ul> | |
| 293 | )} | |
| 294 | </Section> | |
| 295 | ||
| Merge the desktop app's runner: it starts with the app for the signed-in person, sandboxed by default and running nothing where no sandbox is available yet, registers through the site, keeps itself up to date, and says everywhere what it is doing, why it is not, and how to fix it. | 296 | <Section |
| 297 | id="desktops" | |
| 298 | title="Desktops" | |
| 299 | about="Computers with the g1t desktop app, whose runner runs while g1t is open there: what each is doing, and when it isn't running, why and the fix." | |
| 300 | > | |
| Merge the desktop runner's settings: a card for each kind of job, Linux and Windows, each with its state, job, cause and fix, and its own Start and Stop; an honest wait for a release's sandbox images, checked again by itself; and the same on the Runners page. | 301 | <DesktopRunners desktops={data.desktops} slug={slug} runners={own} /> |
| Merge the desktop app's runner: it starts with the app for the signed-in person, sandboxed by default and running nothing where no sandbox is available yet, registers through the site, keeps itself up to date, and says everywhere what it is doing, why it is not, and how to fix it. | 302 | </Section> |
| 303 | ||
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 304 | <Section title="Where work runs" about="For every project in the workspace, unless a project says otherwise in its own settings."> |
| 305 | <div className="grid gap-3 md:grid-cols-3"> | |
| 306 | <WhereCard icon={<Workflow size={15} />} title="Workflow jobs"> | |
| 307 | Each job's <code className="font-mono text-fg-soft">runs-on</code> decides. <code className="font-mono text-fg-soft">ubuntu-latest</code>,{" "} | |
| 308 | <code className="font-mono text-fg-soft">g1t-4core</code> and other Linux labels run on g1t cloud;{" "} | |
| 309 | <code className="font-mono text-fg-soft">self-hosted</code> and your own labels run on your runners. | |
| 310 | </WhereCard> | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 311 | <WhereCard icon={<Bot size={15} />} title="Checks and the merge queue"> |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 312 | {data.settings?.agentsOnSelfHosted |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 313 | ? `Checks, merge checks and the merge queue run on your runners labelled ${data.settings.agentLabels.join(", ")}.` |
| 314 | : "Checks, merge checks and the merge queue run on g1t cloud. Switch them to your runners below."} | |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 315 | </WhereCard> |
| Merge the desktop app's runner: it starts with the app for the signed-in person, sandboxed by default and running nothing where no sandbox is available yet, registers through the site, keeps itself up to date, and says everywhere what it is doing, why it is not, and how to fix it. | 316 | <WhereCard icon={<Laptop size={15} />} title="Your desktop"> |
| 317 | The g1t desktop app runs a runner while it's open, sandboxed and labelled <code className="font-mono text-fg-soft">desktop</code>, for jobs that ask for{" "} | |
| 318 | <code className="font-mono text-fg-soft">self-hosted</code>. Each desktop is under <a href="#desktops" className="underline underline-offset-2">Desktops</a>. | |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 319 | </WhereCard> |
| 320 | </div> | |
| 321 | <RunnerSettingsForm | |
| 322 | key={data.settings ? `${data.settings.agentsOnSelfHosted}:${data.settings.forkPullRequests}:${data.settings.agentLabels.join(",")}` : "none"} | |
| 323 | data={data} | |
| 324 | manage | |
| 325 | scope="workspace" | |
| 326 | /> | |
| 327 | </Section> | |
| 328 | ||
| 329 | <Section | |
| 330 | id="add" | |
| 331 | title="Add a runner" | |
| 332 | about="Download g1t-runner, register it with a token made here, and start it. Linux, macOS and Windows, x64 and arm64, or Docker." | |
| 333 | > | |
| 334 | <NewRunner token={action?.token ?? null} groups={data.groups} repoScoped={false} /> | |
| 335 | </Section> | |
| 336 | ||
| 337 | <Section title="Groups" about="Which repositories may use which runners. A runner joins the default group, every repository, unless its token names another."> | |
| 338 | <Groups groups={data.groups} repositories={data.repositories} manage action={action} /> | |
| 339 | </Section> | |
| 340 | ||
| 341 | </div> | |
| 342 | ); | |
| 343 | } | |
| 344 | ||
| Merge the desktop app's runner: it starts with the app for the signed-in person, sandboxed by default and running nothing where no sandbox is available yet, registers through the site, keeps itself up to date, and says everywhere what it is doing, why it is not, and how to fix it. | 345 | function WhereCard({ icon, title, children }: { icon: ReactNode; title: string; children: ReactNode }) { |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 346 | return ( |
| Merge the desktop app's runner: it starts with the app for the signed-in person, sandboxed by default and running nothing where no sandbox is available yet, registers through the site, keeps itself up to date, and says everywhere what it is doing, why it is not, and how to fix it. | 347 | <div className="rounded-2xl border border-line bg-surface p-4"> |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 348 | <h3 className="flex items-center gap-2 text-sm font-medium"> |
| 349 | <span className="text-muted">{icon}</span> | |
| 350 | {title} | |
| 351 | </h3> | |
| 352 | <p className="mt-2 text-sm leading-relaxed text-muted">{children}</p> | |
| 353 | </div> | |
| 354 | ); | |
| 355 | } | |
| 356 | ||
| 357 | /** This month's machine time, g1t cloud's against the workspace's own, as one bar. */ | |
| 358 | function TimeSplit({ data }: { data: RunnersPageData }) { | |
| 359 | const cost = data.cost; | |
| 360 | if (!cost) { | |
| 361 | return ( | |
| 362 | <div className="rounded-2xl border border-line bg-surface px-5 py-4 text-sm text-muted">Billing didn't answer, so this month's time can't be shown right now.</div> | |
| 363 | ); | |
| 364 | } | |
| 365 | const total = cost.cloudSeconds + cost.ownSeconds; | |
| 366 | return ( | |
| 367 | <div className="rounded-2xl border border-line bg-surface px-5 py-4"> | |
| 368 | {total === 0 ? ( | |
| 369 | <p className="text-sm text-muted">No machine time yet this month.</p> | |
| 370 | ) : ( | |
| 371 | <div className="flex h-2.5 gap-[2px] overflow-hidden rounded-full" role="img" aria-label="This month's machine time by where it ran"> | |
| 372 | {cost.cloudSeconds > 0 && <span className="h-full min-w-[3px] bg-info" style={{ flexGrow: cost.cloudSeconds }} />} | |
| 373 | {cost.ownSeconds > 0 && <span className="h-full min-w-[3px] bg-success" style={{ flexGrow: cost.ownSeconds }} />} | |
| 374 | </div> | |
| 375 | )} | |
| 376 | <ul className="mt-3 space-y-2 text-sm"> | |
| 377 | <li className="flex items-center gap-2"> | |
| 378 | <span className="size-2 shrink-0 rounded-[2px] bg-info" aria-hidden /> | |
| 379 | <span className="min-w-0 grow truncate text-fg-soft">g1t cloud</span> | |
| 380 | <span className="text-muted tabular-nums">{machineTime(cost.cloudSeconds)}</span> | |
| 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. | 381 | <span className="w-20 text-right text-fg tabular-nums">{money(cost.cloudMicros)}</span> |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 382 | </li> |
| 383 | <li className="flex items-center gap-2"> | |
| 384 | <span className="size-2 shrink-0 rounded-[2px] bg-success" aria-hidden /> | |
| 385 | <span className="min-w-0 grow truncate text-fg-soft">Your runners</span> | |
| 386 | <span className="text-muted tabular-nums">{machineTime(cost.ownSeconds)}</span> | |
| 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. | 387 | <span className="w-20 text-right text-fg tabular-nums">{money(0)}</span> |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 388 | </li> |
| 389 | </ul> | |
| 390 | <p className="mt-4 text-[0.6875rem] leading-relaxed text-faint"> | |
| 391 | {cost.free ? "Usage at cost: g1t charges nothing for it now." : "At price, before your plan's included usage or credit paid for any of it."} Models are separate. | |
| 392 | </p> | |
| 393 | </div> | |
| 394 | ); | |
| 395 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.