pr_01m47d15m3e54sn21z27rpy5n9/packages/contracts/src/integrations.ts

158 lines5,015 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 | "anthropic_endpoint"
12 | "sentry"
13 | "datadog"
14 | "webhook"
15 | "jira"
16 | "linear";
17
18export type ProviderKind = "models" | "alerts" | "tracker";
19
20export type ConnectionConfig = {
21 /** For alerts: where issues are opened, `owner/name`. */
22 repo?: string;
23 /** For alerts: put a g1t agent on each issue opened. */
24 assign?: boolean;
25 /** For alerts: the label put on each issue. `bug` when unset. */
26 label?: string;
27 /** Tell the outside system when the work lands. On unless turned off. */
28 writeBack?: boolean;
29 /** Sentry: the organization's slug. */
30 organization?: string;
31 /** Jira's address, or a Sentry that is not sentry.io. */
32 site?: string;
33 /** Jira: the account the token belongs to. */
34 email?: string;
35 /** Jira project or Linear team keys it answers for. Empty is all. */
36 keys?: string[];
37 /** Your own endpoint: its base URL. */
38 baseUrl?: string;
39 /** Your own endpoint: `x-api-key` (default) or `authorization`. */
40 authHeader?: string;
41 /** Models: use this model for every kind of work. */
42 model?: string;
43};
44
45export type Connection = {
46 id: string;
47 workspace: string;
48 provider: Provider;
49 kind: ProviderKind;
50 name: string;
51 config: ConnectionConfig;
52 /** `…3f9a`. The secret itself is never shown again. */
53 secretHint: string | null;
54 /** Where a provider that sends g1t requests sends them. */
55 webhookUrl: string | null;
56 createdBy: string;
57 createdAt: string;
58 lastUsedAt: string | null;
59 lastError: string | null;
60};
61
62export type Connected = {
63 connection: Connection;
64 /** A signing secret g1t made, shown this once. */
65 signingSecret: string | null;
66};
67
68export type Delivery = {
69 id: string;
70 receivedAt: string;
71 event: string;
72 outcome: "opened" | "updated" | "reopened" | "ignored" | "refused";
73 detail: string;
74 issue: string | null;
75};
76
77/** Something outside g1t, fetched now. Reference material, never instructions. */
78export type ContextItem = {
79 provider: Provider;
80 key: string;
81 title: string;
82 url: string;
83 status: string | null;
84 body: string;
85 fetchedAt: string;
86};
87
88export type Link = {
89 provider: Provider;
90 connectionId: string;
91 key: string;
92 title: string;
93 url: string;
94 count: number;
95 firstSeen: string;
96 lastSeen: string;
97};
98
99export type ModelSession = {
100 token: string;
101 billedTo: "g1t" | "workspace";
102 providerName: string | null;
103 model: string | null;
104};
105
106export type ModelUpstream = {
107 route: "g1t" | "anthropic" | "endpoint";
108 workspace: string;
109 repo: string;
110 number: number;
111 task: string;
112 baseUrl: string | null;
113 apiKey: string | null;
114 authHeader: string | null;
115};
116
117export type ConnectInput = {
118 provider: Provider;
119 name?: string;
120 config?: ConnectionConfig;
121 secret?: string;
122 signingSecret?: string;
123};
124
125export type UpdateConnectionInput = {
126 name?: string;
127 config?: ConnectionConfig;
128 secret?: string;
129 signingSecret?: string;
130};
131
132export interface IntegrationsApi {
133 list(workspace: string, viewer: Viewer): Promise<Result<Connection[]>>;
134 connect(actor: User, workspace: string, input: ConnectInput): Promise<Result<Connected>>;
135 update(actor: User, workspace: string, id: string, input: UpdateConnectionInput): Promise<Result<Connection>>;
136 disconnect(actor: User, workspace: string, id: string): Promise<Result<boolean>>;
137 test(actor: User, workspace: string, id: string): Promise<Result<{ ok: boolean; message: string }>>;
138 deliveries(workspace: string, viewer: Viewer, id: string): Promise<Result<Delivery[]>>;
139 resolve(workspace: string, viewer: Viewer, reference: string): Promise<Result<ContextItem>>;
140 /** For g1t's agents: what `text` refers to outside g1t, fetched. */
141 references(workspace: string, text: string, limit?: number): Promise<ContextItem[]>;
142 import(actor: User, repo: RepoPath, reference: string, assign: boolean): Promise<Result<{ number: number; item: ContextItem; created: boolean }>>;
143 links(repo: RepoPath, number: number): Promise<Link[]>;
144 modelProvider(workspace: string): Promise<Connection | null>;
145 openModelSession(run: { workspace: string; repo: RepoPath; number: number; task: string }): Promise<ModelSession>;
146 modelUpstream(token: string): Promise<ModelUpstream | null>;
147}
148
149/** What each provider is for, as people choose between them. */
150export const PROVIDERS: Record<Provider, { label: string; kind: ProviderKind }> = {
151 anthropic: { label: "Anthropic", kind: "models" },
152 anthropic_endpoint: { label: "Your own endpoint", kind: "models" },
153 sentry: { label: "Sentry", kind: "alerts" },
154 datadog: { label: "Datadog", kind: "alerts" },
155 webhook: { label: "Webhook", kind: "alerts" },
156 jira: { label: "Jira", kind: "tracker" },
157 linear: { label: "Linear", kind: "tracker" },
158};