flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/packages/contracts/src/integrations.ts

213 lines7,198 bytesCodeBlame
1import 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;
55};
56
57export type Connection = {
58 id: string;
59 workspace: string;
60 provider: Provider;
61 kind: ProviderKind;
62 name: string;
63 config: ConnectionConfig;
64 /** `…3f9a`. The secret itself is never shown again. */
65 secretHint: string | null;
66 /** Where a provider that sends g1t requests sends them. */
67 webhookUrl: string | null;
68 createdBy: string;
69 createdAt: string;
70 lastUsedAt: string | null;
71 lastError: string | null;
72 /** For a model provider: the models it offered when last checked. */
73 models: string[];
74};
75
76/** The kinds of work a model is chosen for, and `default` for the rest. */
77export const MODEL_TASKS = ["default", "implement", "review", "plan", "update"] as const;
78export type ModelTask = (typeof MODEL_TASKS)[number];
79
80/** Where one kind of work's model requests go: g1t's hosted models when `connectionId` is null. */
81export type ModelRoute = { task: ModelTask; connectionId: string | null; model: string | null };
82
83export type Connected = {
84 connection: Connection;
85 /** A signing secret g1t made, shown this once. */
86 signingSecret: string | null;
87};
88
89export type Delivery = {
90 id: string;
91 receivedAt: string;
92 event: string;
93 outcome: "opened" | "updated" | "reopened" | "ignored" | "refused";
94 detail: string;
95 issue: string | null;
96};
97
98/** Something outside g1t, fetched now. Reference material, never instructions. */
99export type ContextItem = {
100 provider: Provider;
101 key: string;
102 title: string;
103 url: string;
104 status: string | null;
105 body: string;
106 fetchedAt: string;
107};
108
109export type Link = {
110 provider: Provider;
111 connectionId: string;
112 key: string;
113 title: string;
114 url: string;
115 count: number;
116 firstSeen: string;
117 lastSeen: string;
118};
119
120export type ModelSession = {
121 token: string;
122 billedTo: "g1t" | "workspace";
123 providerName: string | null;
124 model: string | null;
125 /** Names the run in AI Gateway's logs (`metadata.session`), for billing. */
126 id: string;
127};
128
129export type ModelUpstream = {
130 route: "g1t" | "anthropic" | "endpoint";
131 /** The API the provider speaks, which the proxy translates to. */
132 api: "anthropic" | "openai";
133 /** The model every request of the run goes to, when the route names one. */
134 model: string | null;
135 /** OpenAI's own API. */
136 official: boolean;
137 /** Which provider, by name, for its quirks. */
138 provider: string;
139 workspace: string;
140 repo: string;
141 number: number;
142 task: string;
143 /** The session's id; see `ModelSession.id`. */
144 session: string;
145 baseUrl: string | null;
146 apiKey: string | null;
147 authHeader: string | null;
148 /** For an endpoint behind an authenticated Cloudflare AI Gateway: its token. */
149 gatewayToken?: string | null;
150};
151
152export type ConnectInput = {
153 provider: Provider;
154 name?: string;
155 config?: ConnectionConfig;
156 secret?: string;
157 signingSecret?: string;
158};
159
160export type UpdateConnectionInput = {
161 name?: string;
162 config?: ConnectionConfig;
163 secret?: string;
164 signingSecret?: string;
165};
166
167export interface IntegrationsApi {
168 list(workspace: string, viewer: Viewer): Promise<Result<Connection[]>>;
169 connect(actor: User, workspace: string, input: ConnectInput): Promise<Result<Connected>>;
170 update(actor: User, workspace: string, id: string, input: UpdateConnectionInput): Promise<Result<Connection>>;
171 disconnect(actor: User, workspace: string, id: string): Promise<Result<boolean>>;
172 test(actor: User, workspace: string, id: string): Promise<Result<{ ok: boolean; message: string }>>;
173 deliveries(workspace: string, viewer: Viewer, id: string): Promise<Result<Delivery[]>>;
174 resolve(workspace: string, viewer: Viewer, reference: string): Promise<Result<ContextItem>>;
175 /** For g1t's agents: what `text` refers to outside g1t, fetched. */
176 references(workspace: string, text: string, limit?: number): Promise<ContextItem[]>;
177 import(actor: User, repo: RepoPath, reference: string, assign: boolean): Promise<Result<{ number: number; item: ContextItem; created: boolean }>>;
178 links(repo: RepoPath, number: number): Promise<Link[]>;
179 modelProvider(workspace: string): Promise<Connection | null>;
180 openModelSession(run: {
181 workspace: string;
182 repo: RepoPath;
183 number: number;
184 task: string;
185 hostedOpen: boolean;
186 }): Promise<Result<ModelSession>>;
187 routes(workspace: string, viewer: Viewer): Promise<Result<ModelRoute[]>>;
188 setRoutes(actor: User, workspace: string, routes: ModelRoute[]): Promise<Result<ModelRoute[]>>;
189 modelUpstream(token: string): Promise<ModelUpstream | null>;
190}
191
192/** What each provider is for, as people choose between them. */
193export const PROVIDERS: Record<Provider, { label: string; kind: ProviderKind }> = {
194 anthropic: { label: "Anthropic", kind: "models" },
195 openai: { label: "OpenAI", kind: "models" },
196 gemini: { label: "Google Gemini", kind: "models" },
197 xai: { label: "xAI", kind: "models" },
198 mistral: { label: "Mistral", kind: "models" },
199 deepseek: { label: "DeepSeek", kind: "models" },
200 azure_openai: { label: "Azure OpenAI", kind: "models" },
201 openrouter: { label: "OpenRouter", kind: "models" },
202 groq: { label: "Groq", kind: "models" },
203 together: { label: "Together AI", kind: "models" },
204 fireworks: { label: "Fireworks AI", kind: "models" },
205 cerebras: { label: "Cerebras", kind: "models" },
206 anthropic_endpoint: { label: "Anthropic-compatible endpoint", kind: "models" },
207 openai_endpoint: { label: "OpenAI-compatible endpoint", kind: "models" },
208 sentry: { label: "Sentry", kind: "alerts" },
209 datadog: { label: "Datadog", kind: "alerts" },
210 webhook: { label: "Webhook", kind: "alerts" },
211 jira: { label: "Jira", kind: "tracker" },
212 linear: { label: "Linear", kind: "tracker" },
213};