Skip to content
77 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 sidebar asks billing whether it is on, not for the account, so no page waits on the card processor1/**
2 * Putting an agent on something in one step (`RunnerService.delegate`):
3 * what is said about the agent once its issue is open, whatever became of
4 * it. Pure, so it is tested on its own.
5 */
6import type { AgentStart, Delegated, Issue, Pull } from "@g1t/contracts";
7
8const SITE = "https://g1t.sh";
9
10/**
11 * What the workspace's agents have no model is said as. `preview`: g1t's
12 * hosted models are closed to it because billing takes no real money yet.
13 */
14export function noModelMessage(workspace: string, preview = false): string {
15 if (preview) {
16 return `g1t's hosted models are not open to the ${workspace} workspace yet: during the preview they run only for a few invited workspaces. An owner can connect the workspace's own model provider under Integrations, and its agents start at once.`;
17 }
18 return `The ${workspace} workspace has no model for its agents: its free allowance on g1t's models is used up or over. An owner can connect the workspace's own model provider under Integrations, and its agents start at once.`;
19}
20
21/**
22 * Where the fix for a refusal is: the workspace's billing page (its limit
23 * and per-issue caps have anchors there), its model settings, or support,
24 * which has no page to fix it on.
25 */
26export function fixUrlFor(code: string, workspace: string): string | null {
27 const slug = workspace.toLowerCase();
28 switch (code) {
29 case "not_paid":
30 case "trial_used":
31 case "oss_pool_empty":
32 return `${SITE}/${slug}/-/billing`;
33 case "limit":
34 return `${SITE}/${slug}/-/billing#limit`;
35 case "issue_cap":
36 return `${SITE}/${slug}/-/billing#caps`;
37 case "no_model":
Integrations are a directory of connectors, for a workspace and for each person38 return `${SITE}/${slug}/-/integrations/models`;
The sidebar asks billing whether it is on, not for the account, so no page waits on the card processor39 default:
40 return null;
41 }
42}
43
44/** The agent at work on `pull`. */
45export function started(issue: Issue, pull: Pull): Delegated {
46 return { issue, pull, agent: { status: "started", code: null, message: null, fixUrl: null } };
47}
48
49/** Every agent slot is busy: it starts by itself when one frees up. */
50export function queued(issue: Issue, message: string): Delegated {
51 return { issue, pull: null, agent: { status: "queued", code: "waiting", message, fixUrl: null } };
52}
53
54/** It did not start: why, and where to fix it. */
55export function notStarted(issue: Issue, code: string, message: string, workspace: string): Delegated {
56 const agent: AgentStart = { status: "not_started", code, message, fixUrl: fixUrlFor(code, workspace) };
57 return { issue, pull: null, agent };
58}
59
60/** The issue's title and body, tidied, and the checks with blank ones left out. */
61export function delegateInput(input: { title?: unknown; body?: unknown; checks?: unknown; labels?: unknown }): {
62 title: string;
63 body: string;
64 checks: string[];
65 labels: string[];
66} {
67 const list = (value: unknown) =>
68 (Array.isArray(value) ? value : typeof value === "string" ? value.split("\n") : [])
69 .map((item) => String(item).trim())
70 .filter(Boolean);
71 return {
72 title: typeof input.title === "string" ? input.title.trim() : "",
73 body: typeof input.body === "string" ? input.body.trim() : "",
74 checks: list(input.checks),
75 labels: list(input.labels),
76 };
77}

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