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

Usage while free is shown at cost; agents get rustfmt and clippy1import type { User, Viewer } from "./identity";
2import type { RepoPath } from "./repos";
3import type { Result } from "./result";
4
5/**
6 * A workspace's connections to systems outside g1t. Mirrors
7 * `crates/contracts/src/integrations.rs`, which says what each does.
8 */
9export type Provider =
10 | "anthropic"
11 | "openai"
12 | "gemini"
13 | "xai"
14 | "mistral"
15 | "deepseek"
16 | "azure_openai"
17 | "openrouter"
18 | "groq"
19 | "together"
20 | "fireworks"
21 | "cerebras"
22 | "anthropic_endpoint"
23 | "openai_endpoint"
24 | "sentry"
25 | "datadog"
26 | "webhook"
27 | "jira"
28 | "linear";
29
30export type ProviderKind = "models" | "alerts" | "tracker";
31
32export type ConnectionConfig = {
33 /** For alerts: where issues are opened, `owner/name`. */
34 repo?: string;
35 /** For alerts: put a g1t agent on each issue opened. */
36 assign?: boolean;
37 /** For alerts: the label put on each issue. `bug` when unset. */
38 label?: string;
39 /** Tell the outside system when the work lands. On unless turned off. */
40 writeBack?: boolean;
41 /** Sentry: the organization's slug. */
42 organization?: string;
43 /** Jira's address, or a Sentry that is not sentry.io. */
44 site?: string;
45 /** Jira: the account the token belongs to. */
46 email?: string;
47 /** Jira project or Linear team keys it answers for. Empty is all. */
48 keys?: string[];
49 /** Your own endpoint: its base URL. */
50 baseUrl?: string;
51 /** Your own endpoint: `x-api-key` (default) or `authorization`. */
52 authHeader?: string;
53 /** Models: the model used when a route to this connection names none. */
54 model?: string;
AI Gateway: OpenAI's format, open models, and your own providers55 /**
56 * Models: which AI Gateway requests go to this connection, by the model
57 * they name: ids (`gpt-5.5`) or prefixes ending in `*` (`gpt-*`,
58 * `ollama/*`, `*`). A `/*` prefix is taken off before sending. Absent:
59 * `claude-*` on an Anthropic key or Anthropic-compatible endpoint,
60 * nothing on the others.
61 */
62 gatewayModels?: string[];
Usage while free is shown at cost; agents get rustfmt and clippy63};
64
AI Gateway: OpenAI's format, open models, and your own providers65/** One of a workspace's own model providers, for the AI Gateway. Carries its key: for the model proxy only. */
66export type GatewayProvider = {
67 id: string;
68 name: string;
69 /** `anthropic`, `openai`, `openai_endpoint`… */
70 provider: string;
71 api: "anthropic" | "openai";
72 /** OpenAI's own API (or Azure's). */
73 official: boolean;
74 /** Without `/v1` for Anthropic's API, with it for OpenAI's. */
75 baseUrl: string;
76 apiKey: string | null;
77 /** `x-api-key`, `authorization` (as `Bearer`) or `api-key`. */
78 authHeader: string;
79 gatewayToken?: string | null;
80 /** The models it takes: ids and `*` prefixes. */
81 patterns: string[];
82 /** The models the provider listed when last checked. */
83 models: string[];
84};
85
86/** The AI Gateway models a connection takes when it names none. */
87export function gatewayPatterns(provider: Provider, config: ConnectionConfig): string[] {
88 if (config.gatewayModels) return config.gatewayModels;
89 return provider === "anthropic" || provider === "anthropic_endpoint" ? ["claude-*"] : [];
90}
91
Usage while free is shown at cost; agents get rustfmt and clippy92export type Connection = {
93 id: string;
94 workspace: string;
95 provider: Provider;
96 kind: ProviderKind;
97 name: string;
98 config: ConnectionConfig;
99 /** `…3f9a`. The secret itself is never shown again. */
100 secretHint: string | null;
101 /** Where a provider that sends g1t requests sends them. */
102 webhookUrl: string | null;
103 createdBy: string;
104 createdAt: string;
105 lastUsedAt: string | null;
106 lastError: string | null;
107 /** For a model provider: the models it offered when last checked. */
108 models: string[];
109};
110
111/** The kinds of work a model is chosen for, and `default` for the rest. */
112export const MODEL_TASKS = ["default", "implement", "review", "plan", "update"] as const;
113export type ModelTask = (typeof MODEL_TASKS)[number];
114
115/** Where one kind of work's model requests go: g1t's hosted models when `connectionId` is null. */
116export type ModelRoute = { task: ModelTask; connectionId: string | null; model: string | null };
117
118export type Connected = {
119 connection: Connection;
120 /** A signing secret g1t made, shown this once. */
121 signingSecret: string | null;
122};
123
124export type Delivery = {
125 id: string;
126 receivedAt: string;
127 event: string;
128 outcome: "opened" | "updated" | "reopened" | "ignored" | "refused";
129 detail: string;
130 issue: string | null;
131};
132
133/** Something outside g1t, fetched now. Reference material, never instructions. */
134export type ContextItem = {
135 provider: Provider;
136 key: string;
137 title: string;
138 url: string;
139 status: string | null;
140 body: string;
141 fetchedAt: string;
142};
143
144export type Link = {
145 provider: Provider;
146 connectionId: string;
147 key: string;
148 title: string;
149 url: string;
150 count: number;
151 firstSeen: string;
152 lastSeen: string;
153};
154
Merge branch 'model-routing'155/**
156 * How capable, and how costly, a model g1t routes to is: `small` (fast),
157 * `large` (standard) or `frontier` (most capable).
158 */
159export type ModelTier = "small" | "large" | "frontier";
160
161/** The tiers, cheapest first. */
162export const MODEL_TIERS: ModelTier[] = ["small", "large", "frontier"];
163
Usage while free is shown at cost; agents get rustfmt and clippy164export type ModelSession = {
165 token: string;
166 billedTo: "g1t" | "workspace";
167 providerName: string | null;
168 model: string | null;
Merge branch 'model-routing'169 /**
170 * Names the run in AI Gateway's logs (`metadata.session`) and its tokens
171 * in billing's count, on g1t's models and the workspace's own alike.
172 */
Prices keep themselves current with what g1t pays173 id: string;
Merge branch 'model-routing'174 /**
175 * The tier the workspace chose for this work on g1t's models, instead of
176 * Auto; the run goes there. Null for Auto, and on its own providers.
177 */
178 tierChoice?: ModelTier | null;
Usage while free is shown at cost; agents get rustfmt and clippy179};
180
181export type ModelUpstream = {
182 route: "g1t" | "anthropic" | "endpoint";
183 /** The API the provider speaks, which the proxy translates to. */
184 api: "anthropic" | "openai";
185 /** The model every request of the run goes to, when the route names one. */
186 model: string | null;
187 /** OpenAI's own API. */
188 official: boolean;
189 /** Which provider, by name, for its quirks. */
190 provider: string;
191 workspace: string;
192 repo: string;
193 number: number;
194 task: string;
Prices keep themselves current with what g1t pays195 /** The session's id; see `ModelSession.id`. */
196 session: string;
Auto model routing: the cheapest tier that can do each piece of work, a retry goes up a tier, and each run records its tier197 /** For `g1t`: the tier the run was routed to. */
Merge branch 'model-routing'198 tier?: ModelTier | null;
Mission control shows model usage, yours and the workspace's: tokens, cost, active days, cache share, each day, and the mix199 /** The person the run is for, by username. Null when nobody asked; never `g1t`. */
200 requestedBy: string | null;
Usage while free is shown at cost; agents get rustfmt and clippy201 baseUrl: string | null;
202 apiKey: string | null;
203 authHeader: string | null;
204 /** For an endpoint behind an authenticated Cloudflare AI Gateway: its token. */
205 gatewayToken?: string | null;
Merge platform pause and the hourly usage watcher: staff can pause compute, schedules, indexing or renders for everyone, the watcher emails on a breach and is never blind quietly, and the models proxy holds each run to its cap (billing 0051, integrations 0006)206 /**
207 * The most the run may spend on models, in millionths of a dollar: the
208 * lower of its project's cost cap and its plan's. The proxy refuses the
209 * run's requests once it has spent this. Null until the sandbox sets it.
210 */
211 capMicros?: number | null;
Usage while free is shown at cost; agents get rustfmt and clippy212};
213
214export type ConnectInput = {
215 provider: Provider;
216 name?: string;
217 config?: ConnectionConfig;
218 secret?: string;
219 signingSecret?: string;
220};
221
222export type UpdateConnectionInput = {
223 name?: string;
224 config?: ConnectionConfig;
225 secret?: string;
226 signingSecret?: string;
227};
228
229export interface IntegrationsApi {
230 list(workspace: string, viewer: Viewer): Promise<Result<Connection[]>>;
231 connect(actor: User, workspace: string, input: ConnectInput): Promise<Result<Connected>>;
232 update(actor: User, workspace: string, id: string, input: UpdateConnectionInput): Promise<Result<Connection>>;
233 disconnect(actor: User, workspace: string, id: string): Promise<Result<boolean>>;
234 test(actor: User, workspace: string, id: string): Promise<Result<{ ok: boolean; message: string }>>;
235 deliveries(workspace: string, viewer: Viewer, id: string): Promise<Result<Delivery[]>>;
236 resolve(workspace: string, viewer: Viewer, reference: string): Promise<Result<ContextItem>>;
237 /** For g1t's agents: what `text` refers to outside g1t, fetched. */
238 references(workspace: string, text: string, limit?: number): Promise<ContextItem[]>;
239 import(actor: User, repo: RepoPath, reference: string, assign: boolean): Promise<Result<{ number: number; item: ContextItem; created: boolean }>>;
Each agent has an Abilities tab: g1t's built-ins, always on within the asker's access; its computer, coming; each connected integration's actions one row each, read, import, comment or resolve, with a level for each, alone, alone when the person asked for it, ask first or never, and whose connection it runs on; and MCP servers an owner adds. Reading is alone, writing inside g1t follows today's choices, anything that leaves g1t asks first, and production deploys can't go above ask. The agents service enforces every level: ask first posts a card to allow or deny and parks a session until it's answered, a refusal names its rule in the transcript and the audit log, and a missing ability posts a request to owners. The agent abilities guide says how.240 /**
241 * For g1t's agents (docs.g1t.sh/guides/agent-abilities/): comments on
242 * the item `reference` names, in the system that knows it (Linear, Jira
243 * or Sentry), on the workspace's connection, with `link` (a g1t address)
244 * at the end. The actor is the person the agent acts for; they must be a
245 * member. Returns the item.
246 */
247 comment(actor: User, workspace: string, reference: string, text: string, link: string): Promise<Result<ContextItem>>;
248 /** For g1t's agents: marks a Sentry issue resolved, with a note and `link`. Only Sentry items can be closed. */
249 close(actor: User, workspace: string, reference: string, text: string, link: string): Promise<Result<ContextItem>>;
Usage while free is shown at cost; agents get rustfmt and clippy250 links(repo: RepoPath, number: number): Promise<Link[]>;
251 modelProvider(workspace: string): Promise<Connection | null>;
252 openModelSession(run: {
253 workspace: string;
254 repo: RepoPath;
255 number: number;
256 task: string;
257 hostedOpen: boolean;
Auto model routing: the cheapest tier that can do each piece of work, a retry goes up a tier, and each run records its tier258 /** The tier the run is routed to on g1t's hosted models, for the gateway's logs. */
Merge branch 'model-routing'259 tier?: ModelTier | null;
Mission control shows model usage, yours and the workspace's: tokens, cost, active days, cache share, each day, and the mix260 /** The person the run is for, by username, so its tokens show under them. */
261 requestedBy?: string | null;
Usage while free is shown at cost; agents get rustfmt and clippy262 }): Promise<Result<ModelSession>>;
263 routes(workspace: string, viewer: Viewer): Promise<Result<ModelRoute[]>>;
264 setRoutes(actor: User, workspace: string, routes: ModelRoute[]): Promise<Result<ModelRoute[]>>;
265 modelUpstream(token: string): Promise<ModelUpstream | null>;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily266 /**
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens267 * Where a workspace's AI Gateway requests go on its own key: its first
268 * Anthropic or Anthropic-compatible model provider, with task `gateway`.
269 * Null sends them to g1t's models.
270 */
271 gatewayUpstream(workspace: string): Promise<ModelUpstream | null>;
272 /**
AI Gateway: OpenAI's format, open models, and your own providers273 * The workspace's own model providers, in the order they were connected,
274 * with their keys and which AI Gateway models each takes. For the model
275 * proxy only.
276 */
277 gatewayProviders(workspace: string): Promise<GatewayProvider[]>;
278 /**
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily279 * Ends the model sessions whose tokens hash to these (SHA-256, lowercase
280 * hex) when their run finishes, so the tokens stop working then. Returns
281 * how many were open.
282 */
283 closeModelSessions(tokenHashes: string[]): Promise<number>;
Merge platform pause and the hourly usage watcher: staff can pause compute, schedules, indexing or renders for everyone, the watcher emails on a breach and is never blind quietly, and the models proxy holds each run to its cap (billing 0051, integrations 0006)284 /**
285 * Sets the most the runs whose model tokens hash to these may spend on
286 * models, in millionths of a dollar, which the model proxy holds them
287 * to. Zero clears it. Returns how many open sessions it set.
288 */
289 capModelSessions(tokenHashes: string[], capMicros: number): Promise<number>;
Usage while free is shown at cost; agents get rustfmt and clippy290}
291
292/** What each provider is for, as people choose between them. */
293export const PROVIDERS: Record<Provider, { label: string; kind: ProviderKind }> = {
294 anthropic: { label: "Anthropic", kind: "models" },
295 openai: { label: "OpenAI", kind: "models" },
296 gemini: { label: "Google Gemini", kind: "models" },
297 xai: { label: "xAI", kind: "models" },
298 mistral: { label: "Mistral", kind: "models" },
299 deepseek: { label: "DeepSeek", kind: "models" },
300 azure_openai: { label: "Azure OpenAI", kind: "models" },
301 openrouter: { label: "OpenRouter", kind: "models" },
302 groq: { label: "Groq", kind: "models" },
303 together: { label: "Together AI", kind: "models" },
304 fireworks: { label: "Fireworks AI", kind: "models" },
305 cerebras: { label: "Cerebras", kind: "models" },
306 anthropic_endpoint: { label: "Anthropic-compatible endpoint", kind: "models" },
307 openai_endpoint: { label: "OpenAI-compatible endpoint", kind: "models" },
308 sentry: { label: "Sentry", kind: "alerts" },
309 datadog: { label: "Datadog", kind: "alerts" },
310 webhook: { label: "Webhook", kind: "alerts" },
311 jira: { label: "Jira", kind: "tracker" },
312 linear: { label: "Linear", kind: "tracker" },
313};

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