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

Project settings say who created the project, by name1import type { ServiceBinding } from "./clients";
2import type { User } from "./identity";
3import type { Result } from "./result";
4
5/**
6 * GitHub: signing in with a GitHub account, and bringing repositories
7 * across through g1t's GitHub App. Mirrors `crates/contracts/src/github.rs`.
8 *
9 * The identity service keeps linked accounts and their user tokens; the
Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them.10 * integrations service keeps installations, the repositories imported
11 * through them and the app's webhook. With no app configured, `enabled`/`configured` are false
Project settings say who created the project, by name12 * and the site shows no GitHub buttons.
13 */
14
15export type GithubPurpose = "sign_in" | "link";
16
17/** How a return from GitHub ended. */
18export type GithubFinished =
Merge main (membership, two-factor, GitHub repo roles) into tokens19 | {
20 kind: "signed_in";
21 /** `twoFactorChallenge` is set, and `sessionToken` empty, while the account's two-factor code is still to come. */
22 signedIn: { user: User; sessionToken: string; twoFactorChallenge?: string | null };
23 created: boolean;
24 next: string;
25 }
Project settings say who created the project, by name26 | { kind: "linked"; login: string; next: string }
27 /** An account has one of its verified emails: sign in to it, then claim. */
28 | { kind: "needs_link"; pending: string; login: string; next: string }
Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them.29 /** A new account waiting on a username. */
30 | { kind: "needs_username"; pending: string; login: string; suggestion: string; next: string };
Project settings say who created the project, by name31
32export type GithubPending = {
33 login: string;
34 kind: "link" | "username";
35 suggestion: string | null;
36 next: string;
37};
38
39export type GithubAccount = {
40 githubId: number;
41 login: string;
42 linkedAt: string;
43 /** Whether g1t holds a working user token for it. */
44 authorized: boolean;
45};
46
47export type GithubAccountView = {
48 enabled: boolean;
49 account: GithubAccount | null;
50 hasPassword: boolean;
51};
52
53export type GithubInstallation = {
54 id: number;
55 workspace: string;
56 account: string;
57 accountType: string;
58 repositorySelection: "all" | "selected" | string;
59 suspended: boolean;
60 settingsUrl: string;
61 createdAt: string;
62};
63
A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how.64/**
65 * An installation of the app the person's own GitHub account can see,
66 * from `github_visible_installations`: how one installed on GitHub
67 * directly is found and added to a workspace.
68 */
69export type GithubVisibleInstallation = {
70 id: number;
71 account: string;
72 accountType: string;
73 repositorySelection: "all" | "selected" | string;
74 suspended: boolean;
75 settingsUrl: string;
76 /** The person's workspaces it is recorded in already. */
77 recordedIn: string[];
78};
79
Project settings say who created the project, by name80export type GithubAppStatus = {
81 configured: boolean;
82 installUrl: string | null;
83 linked: boolean;
84 installations: GithubInstallation[];
85};
86
87export type GithubRepository = {
88 id: number;
89 fullName: string;
90 name: string;
91 private: boolean;
92 description: string | null;
93 defaultBranch: string;
Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them.94 /** The g1t repository already imported from it, as `workspace/name`. */
Project settings say who created the project, by name95 linkedTo: string | null;
96};
97
98export type GithubRepositories = {
99 repositories: GithubRepository[];
100 total: number;
101 page: number;
102 perPage: number;
103};
104
Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them.105/** Where a g1t repository was imported from on GitHub. The import is copied once: the g1t repository is then its own. */
Project settings say who created the project, by name106export type GithubRepoLink = {
107 repoId: string;
108 repo: string;
109 installationId: number;
110 githubRepoId: number;
111 fullName: string;
Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them.112 /** RFC 3339: when it was imported. */
Project settings say who created the project, by name113 syncedAt: string | null;
114 lastError: string | null;
115 issuesImported: number;
116};
117
118export type GithubImportInput = {
119 installationId: number;
120 githubRepoId: number;
121 name?: string;
122 private?: boolean;
123 issues: boolean;
124};
125
126async function rpc<T>(service: ServiceBinding, method: string, args: object): Promise<T> {
127 const response = await service.fetch(`https://service/rpc/${method}`, {
128 method: "POST",
129 headers: { "content-type": "application/json" },
130 body: JSON.stringify(args),
131 });
132 if (!response.ok) throw new Error(`${method} failed with status ${response.status}`);
133 return (await response.json()) as T;
134}
135
136/** Signing in with GitHub: methods of the identity service. */
137export function githubSignInClient(identity: ServiceBinding) {
138 const call = <T>(method: string, args: object) => rpc<T>(identity, method, args);
139 return {
140 enabled: () => call<boolean>("github_enabled", {}),
141 start: (input: { purpose: GithubPurpose; user?: User | null; redirectUri: string; next: string; inviteCode?: string | null }) =>
142 call<Result<{ authorizeUrl: string; state: string }>>("github_start", input),
143 finish: (state: string, code: string) => call<Result<GithubFinished>>("github_finish", { state, code }),
144 pending: (pending: string) => call<Result<GithubPending>>("github_pending", { pending }),
Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them.145 signUp: (pending: string, username: string) =>
146 call<Result<{ user: User; sessionToken: string }>>("github_sign_up", { pending, username }),
Project settings say who created the project, by name147 claim: (pending: string, user: User) => call<Result<GithubAccount>>("github_claim", { pending, user }),
148 account: (user: User) => call<GithubAccountView>("github_account", { user }),
149 unlink: (user: User) => call<Result<boolean>>("github_unlink", { user }),
150 };
151}
152
153/** g1t's GitHub App: methods of the integrations service. */
154export function githubAppClient(integrations: ServiceBinding) {
155 const call = <T>(method: string, args: object) => rpc<T>(integrations, method, args);
156 return {
157 status: (viewer: User, workspace: string) => call<Result<GithubAppStatus>>("github_status", { viewer, workspace }),
158 addInstallation: (actor: User, workspace: string, installationId: number) =>
159 call<Result<GithubInstallation>>("github_add_installation", { actor, workspace, installationId }),
A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how.160 visibleInstallations: (actor: User) => call<Result<GithubVisibleInstallation[]>>("github_visible_installations", { actor }),
Project settings say who created the project, by name161 removeInstallation: (actor: User, workspace: string, installationId: number) =>
162 call<Result<boolean>>("github_remove_installation", { actor, workspace, installationId }),
163 repositories: (actor: User, workspace: string, installationId: number, page?: number) =>
164 call<Result<GithubRepositories>>("github_repositories", { actor, workspace, installationId, page: page ?? null }),
165 import: (actor: User, workspace: string, input: GithubImportInput) =>
166 call<Result<GithubRepoLink>>("github_import", { actor, workspace, ...input }),
167 link: (repoId: string) => call<GithubRepoLink | null>("github_link", { repoId }),
168 };
169}

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