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.
| Artifacts: an hourly view of operations and errors, and SSH must meter its git before it ships | 1 | import type { User, Viewer } from "./identity"; |
| 2 | import type { RepoPath } from "./repos"; | |
| 3 | import 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. | |
| Artifacts: an hourly view of operations and errors, and SSH must meter its git before it ships | 12 | */ |
| 13 | export 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. */ |
| Artifacts: an hourly view of operations and errors, and SSH must meter its git before it ships | 35 | export type ProviderKind = "models" | "alerts" | "tracker"; |
| 36 | ||
| 37 | export 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. */ |
| Artifacts: an hourly view of operations and errors, and SSH must meter its git before it ships | 57 | model?: string; |
| 58 | }; | |
| AI Gateway: OpenAI's format, open models, and your own providers | 59 | |
| Artifacts: an hourly view of operations and errors, and SSH must meter its git before it ships | 60 | export 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 | ||
| 79 | export type Connected = { | |
| 80 | connection: Connection; | |
| 81 | /** A signing secret g1t made, shown this once. */ | |
| 82 | signingSecret: string | null; | |
| 83 | }; | |
| 84 | ||
| 85 | export 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. */ | |
| 95 | export 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 | ||
| 105 | export 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 | ||
| 116 | export type ConnectInput = { | |
| 117 | provider: Provider; | |
| 118 | name?: string; | |
| 119 | config?: ConnectionConfig; | |
| 120 | secret?: string; | |
| 121 | signingSecret?: string; | |
| 122 | }; | |
| 123 | ||
| 124 | export 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. */ | |
| 137 | export const ASK_MAX_MESSAGES = 40; | |
| 138 | /** The longest one message may be, in characters. */ | |
| 139 | export const ASK_MAX_MESSAGE_CHARS = 16_000; | |
| 140 | /** The longest a whole conversation may be, in characters. */ | |
| 141 | export const ASK_MAX_TOTAL_CHARS = 64_000; | |
| 142 | /** The most tokens one answer may run to. */ | |
| 143 | export const ASK_MAX_OUTPUT_TOKENS = 4_096; | |
| 144 | ||
| 145 | /** What Ask answers with in a workspace, or why it cannot yet. */ | |
| 146 | export 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 | ||
| 155 | export type AskRole = "user" | "assistant"; | |
| 156 | export type AskMessage = { role: AskRole; content: string }; | |
| 157 | ||
| 158 | /** Where the person asking is, so the answer is about their work. */ | |
| 159 | export type AskPage = { | |
| 160 | path?: string | null; | |
| 161 | repo?: RepoPath | null; | |
| 162 | issue?: number | null; | |
| 163 | pull?: number | null; | |
| Ask answers "what shipped today" for the asker's own today, and says what changed rather than only how much. "Today" begins at the asker's local midnight: integrations reads the time zone on their profile, or failing that the one their browser sends with the question (the Ask panel and the Chat composer send it; chat keeps it on a question to @g1t, an IANA name only), works out with the runtime's Intl when their day began in UTC (local_day.rs, tested across zones west and east of UTC and on a half hour), and the system prompt says "they are in America/Denver, where it is 2026-10-12: today means since 2026-10-12T06:00:00Z"; without a zone it stays UTC. get_workspace_activity's answer gains `landed`: for the repositories whose default branch was pushed to in the span (busiest first, at most eight), the commits made in the span, one line each (repo, short sha, subject, author, time, link), at most forty, so a workspace that pushes to main rather than merging pull requests still shows what shipped; the prompt has Ask say what those changes were, pass `since` as the start of the asker's today, and narrow the kinds or the span when `complete` is false rather than guessing. A question asked in Chat keeps the direct message's path when its page has none of its own. The quality bar (bench/ask) asks through the direct message with @g1t, as the panel and Chat do now: it opens it, marks a new conversation, posts each question and follows g1t's answer to its end, and grades the steps, sources and proposals it kept. Its first run on production, with tools, had shipped-today pass every check (8/8) and the judge mark it 2.83, for the UTC day and the thin summary this fixes. Checked: cargo test for the workspace (the actions crates' repository-file tests on their own, as on this machine they cannot find their files from the workspace), the wasm build of integrations and the API, the TypeScript typecheck, every workspace's tests, the deploy tool's and the plugin's tests, and the OpenAPI document regenerated. | 164 | /** The browser's IANA time zone, such as `America/Denver`: what "today" means when their profile names none. */ |
| 165 | time_zone?: string | null; | |
| Merge branch 'ask-g1t' | 166 | }; |
| 167 | ||
| 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. | 168 | /** The most rounds of tool calls one answer takes before it must answer. */ |
| 169 | export const ASK_MAX_TOOL_ROUNDS = 10; | |
| 170 | /** The most tool calls one answer makes, across its rounds. */ | |
| 171 | export const ASK_MAX_TOOL_CALLS = 30; | |
| 172 | /** The most characters of one tool's result the model is given; more is trimmed, with a note. */ | |
| 173 | export const ASK_MAX_TOOL_RESULT_CHARS = 16_000; | |
| 174 | /** The most characters of tool results one answer gives the model in all. */ | |
| 175 | export const ASK_MAX_TOOL_TOTAL_CHARS = 120_000; | |
| 176 | /** How long one answer may spend calling tools, in seconds. */ | |
| 177 | export const ASK_MAX_TOOL_SECONDS = 120; | |
| 178 | /** The most sources one answer lists. */ | |
| 179 | export const ASK_MAX_SOURCES = 12; | |
| 180 | ||
| 181 | /** | |
| 182 | * Where a step of an answer is. `refused`: Ask did not run it (it only | |
| 183 | * reads and hands work off, or the answer had used its tool calls). | |
| 184 | */ | |
| 185 | export type AskToolStatus = "running" | "done" | "failed" | "refused"; | |
| 186 | ||
| 187 | /** A page on g1t an answer drew on; `cited` when the answer links to it. */ | |
| 188 | export type AskSource = { title: string; url: string; cited: boolean }; | |
| 189 | ||
| 190 | /** | |
| 191 | * One line of an `ask` answer, as newline-delimited JSON: `meta`, then | |
| 192 | * `text` as it comes and a `tool` line as each step starts and ends (the | |
| 193 | * same `id` twice), then `sources` and `done`, or `error` at any point. | |
| 194 | */ | |
| Merge branch 'ask-g1t' | 195 | export type AskEvent = |
| 196 | | { type: "meta"; provider: Provider; provider_label: string; model: string } | |
| 197 | | { 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. | 198 | | { |
| 199 | type: "tool"; | |
| 200 | id: string; | |
| 201 | /** The tool, such as `pull_request`, and its action, such as `list`. */ | |
| 202 | name: string; | |
| 203 | action: string | null; | |
| 204 | /** What it does, for a person: "Read pull requests in acme/web". */ | |
| 205 | label: string; | |
| 206 | status: AskToolStatus; | |
| 207 | summary: string | null; | |
| 208 | link: string | null; | |
| 209 | } | |
| 210 | | { type: "sources"; sources: AskSource[] } | |
| 211 | | { | |
| 212 | /** | |
| 213 | * Work Ask proposes to hand to a session in the person's own harness: | |
| 214 | * on an issue, or a new one with `title` and `body`. Nothing has | |
| 215 | * started; the person starts it from the card the answer shows. | |
| 216 | */ | |
| 217 | type: "proposal"; | |
| 218 | id: string; | |
| 219 | repo: string; | |
| 220 | issue: number | null; | |
| 221 | title: string | null; | |
| 222 | body: string | null; | |
| 223 | mode: "plan" | "implement" | "review"; | |
| 224 | instruction: string | null; | |
| 225 | } | |
| Merge branch 'ask-g1t' | 226 | | { type: "done"; stop_reason: string | null } |
| 227 | | { type: "error"; message: string }; | |
| 228 | ||
| Artifacts: an hourly view of operations and errors, and SSH must meter its git before it ships | 229 | export 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>>; | |
| 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. | 237 | import(actor: User, repo: RepoPath, reference: string): Promise<Result<{ number: number; item: ContextItem; created: boolean }>>; |
| Artifacts: an hourly view of operations and errors, and SSH must meter its git before it ships | 238 | links(repo: RepoPath, number: number): Promise<Link[]>; |
| Merge branch 'ask-g1t' | 239 | /** What Ask answers with. Members only. */ |
| 240 | askSettings(workspace: string, viewer: Viewer): Promise<Result<AskSetup>>; | |
| 241 | /** Chooses Ask's connection and model; a null connection turns it off. Owners only. */ | |
| 242 | setAskSettings(actor: User, workspace: string, connectionId: string | null, model: string | null): Promise<Result<AskSetup>>; | |
| 243 | /** | |
| 244 | * One answer, as the service's response: newline-delimited `AskEvent`s, | |
| 245 | * streamed. Members only. Call it on the binding itself, not through | |
| 246 | * anything that reads the whole body first. `signal` stops the answer. | |
| 247 | */ | |
| 248 | ask(actor: User, workspace: string, messages: AskMessage[], page: AskPage, signal?: AbortSignal): Promise<Response>; | |
| Artifacts: an hourly view of operations and errors, and SSH must meter its git before it ships | 249 | } |
| 250 | ||
| 251 | /** What each provider is for, as people choose between them. */ | |
| 252 | export const PROVIDERS: Record<Provider, { label: string; kind: ProviderKind }> = { | |
| 253 | anthropic: { label: "Anthropic", kind: "models" }, | |
| 254 | openai: { label: "OpenAI", kind: "models" }, | |
| 255 | gemini: { label: "Google Gemini", kind: "models" }, | |
| 256 | xai: { label: "xAI", kind: "models" }, | |
| 257 | mistral: { label: "Mistral", kind: "models" }, | |
| 258 | deepseek: { label: "DeepSeek", kind: "models" }, | |
| 259 | azure_openai: { label: "Azure OpenAI", kind: "models" }, | |
| 260 | openrouter: { label: "OpenRouter", kind: "models" }, | |
| 261 | groq: { label: "Groq", kind: "models" }, | |
| 262 | together: { label: "Together AI", kind: "models" }, | |
| 263 | fireworks: { label: "Fireworks AI", kind: "models" }, | |
| 264 | cerebras: { label: "Cerebras", kind: "models" }, | |
| 265 | anthropic_endpoint: { label: "Anthropic-compatible endpoint", kind: "models" }, | |
| 266 | openai_endpoint: { label: "OpenAI-compatible endpoint", kind: "models" }, | |
| 267 | sentry: { label: "Sentry", kind: "alerts" }, | |
| 268 | datadog: { label: "Datadog", kind: "alerts" }, | |
| 269 | webhook: { label: "Webhook", kind: "alerts" }, | |
| 270 | jira: { label: "Jira", kind: "tracker" }, | |
| 271 | linear: { label: "Linear", kind: "tracker" }, | |
| 272 | }; |
This file's history is long; its oldest lines are credited to the oldest commit read.