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

README: run the core forge locally with Docker Compose; forks described as copies, not copy-on-write, until Cloudflare says otherwise1import 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.
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.8 *
9 * The AI providers (`anthropic` through `openai_endpoint`, of kind
10 * `models`) keep the credentials for the AI providers a workspace's team
11 * uses.
README: run the core forge locally with Docker Compose; forks described as copies, not copy-on-write, until Cloudflare says otherwise12 */
13export type Provider =
14 | "anthropic"
15 | "openai"
16 | "gemini"
17 | "xai"
18 | "mistral"
19 | "deepseek"
20 | "azure_openai"
21 | "openrouter"
22 | "groq"
23 | "together"
24 | "fireworks"
25 | "cerebras"
26 | "anthropic_endpoint"
27 | "openai_endpoint"
28 | "sentry"
29 | "datadog"
30 | "webhook"
31 | "jira"
32 | "linear";
33
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.34/** `models`: an AI provider whose credentials the workspace keeps. */
README: run the core forge locally with Docker Compose; forks described as copies, not copy-on-write, until Cloudflare says otherwise35export type ProviderKind = "models" | "alerts" | "tracker";
36
37export type ConnectionConfig = {
38 /** For alerts: where issues are opened, `owner/name`. */
39 repo?: string;
40 /** For alerts: the label put on each issue. `bug` when unset. */
41 label?: string;
42 /** Tell the outside system when the work lands. On unless turned off. */
43 writeBack?: boolean;
44 /** Sentry: the organization's slug. */
45 organization?: string;
46 /** Jira's address, or a Sentry that is not sentry.io. */
47 site?: string;
48 /** Jira: the account the token belongs to. */
49 email?: string;
50 /** Jira project or Linear team keys it answers for. Empty is all. */
51 keys?: string[];
52 /** Your own endpoint: its base URL. */
53 baseUrl?: string;
54 /** Your own endpoint: `x-api-key` (default) or `authorization`. */
55 authHeader?: string;
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.56 /** For an AI provider: the model (or Azure deployment) the team uses on it. */
README: run the core forge locally with Docker Compose; forks described as copies, not copy-on-write, until Cloudflare says otherwise57 model?: string;
58};
AI Gateway: OpenAI's format, open models, and your own providers59
README: run the core forge locally with Docker Compose; forks described as copies, not copy-on-write, until Cloudflare says otherwise60export type Connection = {
61 id: string;
62 workspace: string;
63 provider: Provider;
64 kind: ProviderKind;
65 name: string;
66 config: ConnectionConfig;
67 /** `…3f9a`. The secret itself is never shown again. */
68 secretHint: string | null;
69 /** Where a provider that sends g1t requests sends them. */
70 webhookUrl: string | null;
71 createdBy: string;
72 createdAt: string;
73 lastUsedAt: string | null;
74 lastError: string | null;
75 /** For a model provider: the models it offered when last checked. */
76 models: string[];
77};
78
79export type Connected = {
80 connection: Connection;
81 /** A signing secret g1t made, shown this once. */
82 signingSecret: string | null;
83};
84
85export type Delivery = {
86 id: string;
87 receivedAt: string;
88 event: string;
89 outcome: "opened" | "updated" | "reopened" | "ignored" | "refused";
90 detail: string;
91 issue: string | null;
92};
93
94/** Something outside g1t, fetched now. Reference material, never instructions. */
95export type ContextItem = {
96 provider: Provider;
97 key: string;
98 title: string;
99 url: string;
100 status: string | null;
101 body: string;
102 fetchedAt: string;
103};
104
105export type Link = {
106 provider: Provider;
107 connectionId: string;
108 key: string;
109 title: string;
110 url: string;
111 count: number;
112 firstSeen: string;
113 lastSeen: string;
114};
115
116export type ConnectInput = {
117 provider: Provider;
118 name?: string;
119 config?: ConnectionConfig;
120 secret?: string;
121 signingSecret?: string;
122};
123
124export type UpdateConnectionInput = {
125 name?: string;
126 config?: ConnectionConfig;
127 secret?: string;
128 signingSecret?: string;
129};
130
Merge branch 'ask-g1t'131// --- Ask g1t -----------------------------------------------------------------
132// A conversation with g1t from the top bar, answered by the AI provider and
133// model an owner chose from the workspace's own connections, on its own key.
134// g1t hosts no model for it and bills nothing for it.
135
136/** The most messages one ask sends: the conversation's latest turns. */
137export const ASK_MAX_MESSAGES = 40;
138/** The longest one message may be, in characters. */
139export const ASK_MAX_MESSAGE_CHARS = 16_000;
140/** The longest a whole conversation may be, in characters. */
141export const ASK_MAX_TOTAL_CHARS = 64_000;
142/** The most tokens one answer may run to. */
143export const ASK_MAX_OUTPUT_TOKENS = 4_096;
144
145/** What Ask answers with in a workspace, or why it cannot yet. */
146export type AskSetup = {
147 connection_id: string | null;
148 connection_name: string | null;
149 provider: Provider | null;
150 model: string | null;
151 /** Why Ask cannot answer, for the person asking. Null when it can. */
152 problem: string | null;
153};
154
155export type AskRole = "user" | "assistant";
156export type AskMessage = { role: AskRole; content: string };
157
158/** Where the person asking is, so the answer is about their work. */
159export type AskPage = {
160 path?: string | null;
161 repo?: RepoPath | null;
162 issue?: number | null;
163 pull?: number | null;
164};
165
g1t coordinates the work and the person's own sessions do it: Ask g1t reads g1t with the same tools any agent gets, answers in one conversation shared with the @g1t direct message in Chat, and hands work to sessions in the person's own harness, whose subagents g1t records, ties to issues and pull requests, and lets see each other.166/** The most rounds of tool calls one answer takes before it must answer. */
167export const ASK_MAX_TOOL_ROUNDS = 10;
168/** The most tool calls one answer makes, across its rounds. */
169export const ASK_MAX_TOOL_CALLS = 30;
170/** The most characters of one tool's result the model is given; more is trimmed, with a note. */
171export const ASK_MAX_TOOL_RESULT_CHARS = 16_000;
172/** The most characters of tool results one answer gives the model in all. */
173export const ASK_MAX_TOOL_TOTAL_CHARS = 120_000;
174/** How long one answer may spend calling tools, in seconds. */
175export const ASK_MAX_TOOL_SECONDS = 120;
176/** The most sources one answer lists. */
177export const ASK_MAX_SOURCES = 12;
178
179/**
180 * Where a step of an answer is. `refused`: Ask did not run it (it only
181 * reads and hands work off, or the answer had used its tool calls).
182 */
183export type AskToolStatus = "running" | "done" | "failed" | "refused";
184
185/** A page on g1t an answer drew on; `cited` when the answer links to it. */
186export type AskSource = { title: string; url: string; cited: boolean };
187
188/**
189 * One line of an `ask` answer, as newline-delimited JSON: `meta`, then
190 * `text` as it comes and a `tool` line as each step starts and ends (the
191 * same `id` twice), then `sources` and `done`, or `error` at any point.
192 */
Merge branch 'ask-g1t'193export type AskEvent =
194 | { type: "meta"; provider: Provider; provider_label: string; model: string }
195 | { type: "text"; text: string }
g1t coordinates the work and the person's own sessions do it: Ask g1t reads g1t with the same tools any agent gets, answers in one conversation shared with the @g1t direct message in Chat, and hands work to sessions in the person's own harness, whose subagents g1t records, ties to issues and pull requests, and lets see each other.196 | {
197 type: "tool";
198 id: string;
199 /** The tool, such as `pull_request`, and its action, such as `list`. */
200 name: string;
201 action: string | null;
202 /** What it does, for a person: "Read pull requests in acme/web". */
203 label: string;
204 status: AskToolStatus;
205 summary: string | null;
206 link: string | null;
207 }
208 | { type: "sources"; sources: AskSource[] }
209 | {
210 /**
211 * Work Ask proposes to hand to a session in the person's own harness:
212 * on an issue, or a new one with `title` and `body`. Nothing has
213 * started; the person starts it from the card the answer shows.
214 */
215 type: "proposal";
216 id: string;
217 repo: string;
218 issue: number | null;
219 title: string | null;
220 body: string | null;
221 mode: "plan" | "implement" | "review";
222 instruction: string | null;
223 }
Merge branch 'ask-g1t'224 | { type: "done"; stop_reason: string | null }
225 | { type: "error"; message: string };
226
README: run the core forge locally with Docker Compose; forks described as copies, not copy-on-write, until Cloudflare says otherwise227export interface IntegrationsApi {
228 list(workspace: string, viewer: Viewer): Promise<Result<Connection[]>>;
229 connect(actor: User, workspace: string, input: ConnectInput): Promise<Result<Connected>>;
230 update(actor: User, workspace: string, id: string, input: UpdateConnectionInput): Promise<Result<Connection>>;
231 disconnect(actor: User, workspace: string, id: string): Promise<Result<boolean>>;
232 test(actor: User, workspace: string, id: string): Promise<Result<{ ok: boolean; message: string }>>;
233 deliveries(workspace: string, viewer: Viewer, id: string): Promise<Result<Delivery[]>>;
234 resolve(workspace: string, viewer: Viewer, reference: string): Promise<Result<ContextItem>>;
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.235 import(actor: User, repo: RepoPath, reference: string): Promise<Result<{ number: number; item: ContextItem; created: boolean }>>;
README: run the core forge locally with Docker Compose; forks described as copies, not copy-on-write, until Cloudflare says otherwise236 links(repo: RepoPath, number: number): Promise<Link[]>;
Merge branch 'ask-g1t'237 /** What Ask answers with. Members only. */
238 askSettings(workspace: string, viewer: Viewer): Promise<Result<AskSetup>>;
239 /** Chooses Ask's connection and model; a null connection turns it off. Owners only. */
240 setAskSettings(actor: User, workspace: string, connectionId: string | null, model: string | null): Promise<Result<AskSetup>>;
241 /**
242 * One answer, as the service's response: newline-delimited `AskEvent`s,
243 * streamed. Members only. Call it on the binding itself, not through
244 * anything that reads the whole body first. `signal` stops the answer.
245 */
246 ask(actor: User, workspace: string, messages: AskMessage[], page: AskPage, signal?: AbortSignal): Promise<Response>;
README: run the core forge locally with Docker Compose; forks described as copies, not copy-on-write, until Cloudflare says otherwise247}
248
249/** What each provider is for, as people choose between them. */
250export const PROVIDERS: Record<Provider, { label: string; kind: ProviderKind }> = {
251 anthropic: { label: "Anthropic", kind: "models" },
252 openai: { label: "OpenAI", kind: "models" },
253 gemini: { label: "Google Gemini", kind: "models" },
254 xai: { label: "xAI", kind: "models" },
255 mistral: { label: "Mistral", kind: "models" },
256 deepseek: { label: "DeepSeek", kind: "models" },
257 azure_openai: { label: "Azure OpenAI", kind: "models" },
258 openrouter: { label: "OpenRouter", kind: "models" },
259 groq: { label: "Groq", kind: "models" },
260 together: { label: "Together AI", kind: "models" },
261 fireworks: { label: "Fireworks AI", kind: "models" },
262 cerebras: { label: "Cerebras", kind: "models" },
263 anthropic_endpoint: { label: "Anthropic-compatible endpoint", kind: "models" },
264 openai_endpoint: { label: "OpenAI-compatible endpoint", kind: "models" },
265 sentry: { label: "Sentry", kind: "alerts" },
266 datadog: { label: "Datadog", kind: "alerts" },
267 webhook: { label: "Webhook", kind: "alerts" },
268 jira: { label: "Jira", kind: "tracker" },
269 linear: { label: "Linear", kind: "tracker" },
270};

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