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 name | 1 | import type { ServiceBinding } from "./clients"; |
| 2 | import type { User } from "./identity"; | |
| 3 | import 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 name | 12 | * and the site shows no GitHub buttons. |
| 13 | */ | |
| 14 | ||
| 15 | export type GithubPurpose = "sign_in" | "link"; | |
| 16 | ||
| 17 | /** How a return from GitHub ended. */ | |
| 18 | export type GithubFinished = | |
| Merge main (membership, two-factor, GitHub repo roles) into tokens | 19 | | { |
| 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 name | 26 | | { 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 name | 31 | |
| 32 | export type GithubPending = { | |
| 33 | login: string; | |
| 34 | kind: "link" | "username"; | |
| 35 | suggestion: string | null; | |
| 36 | next: string; | |
| 37 | }; | |
| 38 | ||
| 39 | export 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 | ||
| 47 | export type GithubAccountView = { | |
| 48 | enabled: boolean; | |
| 49 | account: GithubAccount | null; | |
| 50 | hasPassword: boolean; | |
| 51 | }; | |
| 52 | ||
| 53 | export 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 | */ | |
| 69 | export 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 name | 80 | export type GithubAppStatus = { |
| 81 | configured: boolean; | |
| 82 | installUrl: string | null; | |
| 83 | linked: boolean; | |
| 84 | installations: GithubInstallation[]; | |
| 85 | }; | |
| 86 | ||
| 87 | export 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 name | 95 | linkedTo: string | null; |
| 96 | }; | |
| 97 | ||
| 98 | export 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 name | 106 | export 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 name | 113 | syncedAt: string | null; |
| 114 | lastError: string | null; | |
| 115 | issuesImported: number; | |
| 116 | }; | |
| 117 | ||
| 118 | export type GithubImportInput = { | |
| 119 | installationId: number; | |
| 120 | githubRepoId: number; | |
| 121 | name?: string; | |
| 122 | private?: boolean; | |
| 123 | issues: boolean; | |
| 124 | }; | |
| 125 | ||
| 126 | async 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. */ | |
| 137 | export 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 name | 147 | 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. */ | |
| 154 | export 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 name | 161 | 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.