@nairon-ai/aegis 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,19 +22,68 @@ Minimal fix branch -> PR -> stop
22
22
 
23
23
  ## Start Here
24
24
 
25
- If you want to connect Aegis to another repo and monitor its bugs, follow [docs/SETUP.md](docs/SETUP.md).
26
-
27
- Short version:
28
-
29
- 1. In your product repo, run `npx @nairon-ai/aegis init`.
30
- 2. Create a Cloudflare account and use Workers Paid for deployed cloud mode.
31
- 3. Log in with `npx wrangler login`.
32
- 4. Create GitHub access for the repo Aegis should fix.
33
- 5. Run `npx @nairon-ai/aegis setup`.
34
- 6. Add `bug` and `ready to implement` labels to the monitored repo.
35
- 7. Run `npx @nairon-ai/aegis pickup --dry-run`.
36
- 8. Run `npx @nairon-ai/aegis deploy`.
37
- 9. Add webhooks after deploy.
25
+ If you want to connect Aegis to another repo and monitor its bugs, run Aegis from the product repo you want it to fix.
26
+
27
+ For example, if Aegis should monitor `KeyLead-Team/keylead`, run every setup command from your local KeyLead checkout:
28
+
29
+ ```bash
30
+ cd ~/Desktop/keylead
31
+ npx --yes @nairon-ai/aegis@latest init
32
+ npx --yes @nairon-ai/aegis@latest setup
33
+ ```
34
+
35
+ First prove Aegis can see a ready bug locally:
36
+
37
+ ```bash
38
+ npx --yes @nairon-ai/aegis@latest status
39
+ npx --yes @nairon-ai/aegis@latest pickup --dry-run
40
+ ```
41
+
42
+ Only deploy after `pickup --dry-run` finds the test issue.
43
+
44
+ Full setup guide: [docs/SETUP.md](docs/SETUP.md).
45
+
46
+ ### First Local Test
47
+
48
+ No Cloudflare required for this part.
49
+
50
+ 1. `cd` into the product repo Aegis should monitor.
51
+ 2. Run `npx --yes @nairon-ai/aegis@latest init`.
52
+ 3. Create a GitHub token for that repo with Contents, Issues, and Pull Requests read/write access.
53
+ 4. Run `npx --yes @nairon-ai/aegis@latest setup`.
54
+ 5. Choose `plan-first` and `minimal` for the first test.
55
+ 6. Add `bug` and `ready to implement` labels to the monitored GitHub repo.
56
+ 7. Create a test bug issue with both labels.
57
+ 8. Run `npx --yes @nairon-ai/aegis@latest pickup --dry-run`.
58
+
59
+ Good first result:
60
+
61
+ ```text
62
+ github:#123 would run - ready bug with enough context
63
+ ```
64
+
65
+ If you see `No ready bugs found`, check `MONITORED_REPO`, exact label names, issue state, and GitHub token access.
66
+
67
+ ### GitHub Access Choices
68
+
69
+ During `setup`, choose one:
70
+
71
+ - `GitHub token (recommended first test)`: fastest path. Best for proving Aegis can see ready bugs.
72
+ - `One-click GitHub App`: best for deployed/team use. Aegis opens a browser page, creates the app, asks you to install it on the repo, then saves the credentials.
73
+ - `Paste existing GitHub App credentials`: only if you already made an app manually.
74
+
75
+ The repo prompt accepts either `owner/repo` or a full GitHub URL like `https://github.com/KeyLead-Team/keylead`.
76
+
77
+ ### Deployed AFK Mode
78
+
79
+ Deploy only after the local dry-run works.
80
+
81
+ 1. Create a Cloudflare account.
82
+ 2. Enable Workers Paid.
83
+ 3. Start Docker locally.
84
+ 4. Log in with `npx wrangler login`.
85
+ 5. Run `npx --yes @nairon-ai/aegis@latest deploy`.
86
+ 6. Add GitHub/Linear/Telegram webhooks using the Worker URL printed by deploy.
38
87
 
39
88
  ## Two Repos
40
89
 
@@ -55,9 +55,9 @@ This directory configures Aegis for this repository.
55
55
  ## First Run
56
56
 
57
57
  \`\`\`bash
58
- npx @nairon-ai/aegis setup
59
- npx @nairon-ai/aegis pickup --dry-run
60
- npx @nairon-ai/aegis deploy
58
+ npx --yes @nairon-ai/aegis@latest setup
59
+ npx --yes @nairon-ai/aegis@latest pickup --dry-run
60
+ npx --yes @nairon-ai/aegis@latest deploy
61
61
  \`\`\`
62
62
 
63
63
  For the first test, use:
@@ -98,11 +98,11 @@ export function runInit() {
98
98
  writeIfMissing(resolve(PROJECT_AEGIS_DIR, "README.md"), README);
99
99
  consola.success("Created .aegis/");
100
100
  consola.log("\nNext:");
101
- consola.log(" 1. npx @nairon-ai/aegis setup");
101
+ consola.log(" 1. npx --yes @nairon-ai/aegis@latest setup");
102
102
  consola.log(" 2. create GitHub labels: bug, ready to implement");
103
103
  consola.log(" 3. create a tiny test bug issue");
104
- consola.log(" 4. npx @nairon-ai/aegis pickup --dry-run");
105
- consola.log(" 5. npx @nairon-ai/aegis deploy");
104
+ consola.log(" 4. npx --yes @nairon-ai/aegis@latest pickup --dry-run");
105
+ consola.log(" 5. npx --yes @nairon-ai/aegis@latest deploy");
106
106
  consola.log("");
107
107
  }
108
108
  function writeIfMissing(path, contents) {
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4CnB,CAAC;AAEF,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCd,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;IACxC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,qCAAqC,EAAE;IAC1E,KAAK,CAAC,GAAG;QACR,OAAO,EAAE,CAAC;IACX,CAAC;CACD,CAAC,CAAC;AAEH,MAAM,UAAU,OAAO;IACtB,SAAS,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,cAAc,CAAC,OAAO,CAAC,iBAAiB,EAAE,YAAY,CAAC,EAAE,eAAe,CAAC,CAAC;IAC1E,cAAc,CAAC,OAAO,CAAC,iBAAiB,EAAE,cAAc,CAAC,EAAE,WAAW,CAAC,CAAC;IACxE,cAAc,CAAC,OAAO,CAAC,iBAAiB,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;IAChE,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACvB,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACjB,CAAC;AAED,SAAS,cAAc,CAAC,IAAY,EAAE,QAAgB;IACrD,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC;QACzC,OAAO;IACR,CAAC;IACD,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4CnB,CAAC;AAEF,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCd,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;IACxC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,qCAAqC,EAAE;IAC1E,KAAK,CAAC,GAAG;QACR,OAAO,EAAE,CAAC;IACX,CAAC;CACD,CAAC,CAAC;AAEH,MAAM,UAAU,OAAO;IACtB,SAAS,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,cAAc,CAAC,OAAO,CAAC,iBAAiB,EAAE,YAAY,CAAC,EAAE,eAAe,CAAC,CAAC;IAC1E,cAAc,CAAC,OAAO,CAAC,iBAAiB,EAAE,cAAc,CAAC,EAAE,WAAW,CAAC,CAAC;IACxE,cAAc,CAAC,OAAO,CAAC,iBAAiB,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;IAChE,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACvB,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;IACvE,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACjB,CAAC;AAED,SAAS,cAAc,CAAC,IAAY,EAAE,QAAgB;IACrD,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC;QACzC,OAAO;IACR,CAAC;IACD,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,YAAY,qDAKvB,CAAC;AAEH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAuBpD"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,YAAY,qDAKvB,CAAC;AAEH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAuBpD"}
@@ -2,6 +2,7 @@ import { existsSync, readFileSync } from "node:fs";
2
2
  import { resolve } from "node:path";
3
3
  import { defineCommand } from "citty";
4
4
  import { consola } from "consola";
5
+ import { runGitHubAppFlow } from "../github-app-flow.js";
5
6
  import { resolveEnvFileForWrite } from "../paths.js";
6
7
  import { detectSetupState, printState, saveConfig } from "../state.js";
7
8
  export const setupCommand = defineCommand({
@@ -33,39 +34,55 @@ export async function runSetupWizard() {
33
34
  consola.log("");
34
35
  }
35
36
  async function setupRepo(config) {
36
- config.monitoredRepo = await promptText("GitHub repo to monitor (owner/repo):", config.monitoredRepo);
37
+ config.monitoredRepo = normalizeGitHubRepo(await promptText("GitHub repo to monitor (owner/repo):", config.monitoredRepo));
37
38
  config.baseBranch = await promptText("Base branch:", config.baseBranch ?? "main");
38
39
  }
39
40
  async function setupGitHub(config) {
40
41
  consola.log("\nGitHub access");
41
- consola.info("For the first test, a fine-grained token is fastest. For shared/team use, use a GitHub App.");
42
+ consola.info("For the first test, a fine-grained token is fastest. For deployed/team use, use the one-click GitHub App flow.");
42
43
  const method = (await consola.prompt("Auth method:", {
43
44
  type: "select",
44
45
  options: [
45
- { label: "GitHub App (recommended)", value: "app" },
46
- { label: "GitHub token (simpler local testing)", value: "token" },
46
+ { label: "GitHub token (recommended first test)", value: "token" },
47
+ { label: "One-click GitHub App (best for deployed/team use)", value: "app-flow" },
48
+ { label: "Paste existing GitHub App credentials", value: "app-manual" },
47
49
  ],
48
50
  }));
49
51
  if (method === "token") {
50
52
  config.githubToken = await promptText("GitHub token with contents/issues/PR read-write access:", config.githubToken);
53
+ config.githubAppId = undefined;
54
+ config.githubAppPrivateKey = undefined;
55
+ config.githubInstallationId = undefined;
51
56
  }
52
- else {
53
- config.githubAppId = await promptText("GitHub App ID:", config.githubAppId);
54
- const keyPath = await promptText("Path to GitHub App private key .pem:", undefined);
55
- if (keyPath) {
56
- const resolved = resolve(keyPath.replace(/^~/, process.env.HOME ?? "~"));
57
- if (existsSync(resolved)) {
58
- config.githubAppPrivateKey = Buffer.from(readFileSync(resolved, "utf-8")).toString("base64");
59
- consola.success("Loaded private key");
60
- }
61
- else {
62
- consola.warn(`File not found: ${resolved}`);
63
- }
57
+ else if (method === "app-flow") {
58
+ if (!config.monitoredRepo) {
59
+ consola.warn("Set the monitored repo first.");
60
+ return;
61
+ }
62
+ try {
63
+ const app = await runGitHubAppFlow({
64
+ monitoredRepo: config.monitoredRepo,
65
+ workerUrl: config.workerUrl,
66
+ });
67
+ config.githubAppId = app.appId;
68
+ config.githubAppPrivateKey = Buffer.from(app.privateKey, "utf-8").toString("base64");
69
+ config.githubInstallationId = app.installationId;
70
+ config.githubWebhookSecret = app.webhookSecret;
71
+ config.githubToken = undefined;
72
+ consola.success("Saved GitHub App credentials from GitHub.");
64
73
  }
65
- if (!config.githubAppPrivateKey) {
66
- config.githubAppPrivateKey = Buffer.from(await promptText("Paste GitHub App private key PEM:", config.githubAppPrivateKey)).toString("base64");
74
+ catch (error) {
75
+ consola.warn(error instanceof Error ? error.message : String(error));
76
+ consola.info("Falling back to manual GitHub App credentials.");
77
+ await setupGitHubAppManual(config);
67
78
  }
68
- config.githubInstallationId = await promptText("GitHub App installation ID:", config.githubInstallationId);
79
+ }
80
+ else {
81
+ await setupGitHubAppManual(config);
82
+ }
83
+ if (config.githubWebhookSecret) {
84
+ consola.info("GitHub webhook secret is already configured.");
85
+ return;
69
86
  }
70
87
  const generateSecret = (await consola.prompt("Generate a GitHub webhook secret?", {
71
88
  type: "confirm",
@@ -78,6 +95,25 @@ async function setupGitHub(config) {
78
95
  consola.info("Use this same value when you add the GitHub App or repo webhook.");
79
96
  }
80
97
  }
98
+ async function setupGitHubAppManual(config) {
99
+ config.githubAppId = await promptText("GitHub App ID:", config.githubAppId);
100
+ const keyPath = await promptText("Path to GitHub App private key .pem:", undefined);
101
+ if (keyPath) {
102
+ const resolved = resolve(keyPath.replace(/^~/, process.env.HOME ?? "~"));
103
+ if (existsSync(resolved)) {
104
+ config.githubAppPrivateKey = Buffer.from(readFileSync(resolved, "utf-8")).toString("base64");
105
+ consola.success("Loaded private key");
106
+ }
107
+ else {
108
+ consola.warn(`File not found: ${resolved}`);
109
+ }
110
+ }
111
+ if (!config.githubAppPrivateKey) {
112
+ config.githubAppPrivateKey = Buffer.from(await promptText("Paste GitHub App private key PEM:", config.githubAppPrivateKey)).toString("base64");
113
+ }
114
+ config.githubInstallationId = await promptText("GitHub App installation ID:", config.githubInstallationId);
115
+ config.githubToken = undefined;
116
+ }
81
117
  async function setupLinear(config) {
82
118
  const enable = (await consola.prompt("Connect Linear too?", {
83
119
  type: "confirm",
@@ -160,4 +196,17 @@ async function promptText(message, initial) {
160
196
  }));
161
197
  return value?.trim() ?? "";
162
198
  }
199
+ function normalizeGitHubRepo(input) {
200
+ const value = input
201
+ .trim()
202
+ .replace(/\.git$/, "")
203
+ .replace(/\/$/, "");
204
+ const urlMatch = value.match(/github\.com[:/]([^/\s]+)\/([^/\s]+)$/i);
205
+ if (urlMatch)
206
+ return `${urlMatch[1]}/${urlMatch[2]}`;
207
+ const shorthandMatch = value.match(/^([^/\s]+)\/([^/\s]+)$/);
208
+ if (shorthandMatch)
209
+ return `${shorthandMatch[1]}/${shorthandMatch[2]}`;
210
+ return value;
211
+ }
163
212
  //# sourceMappingURL=setup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { type ManifestResult } from "../github/manifest.js";
2
+ export type GitHubAppFlowResult = ManifestResult & {
3
+ installationId: string;
4
+ };
5
+ export declare function runGitHubAppFlow(options: {
6
+ monitoredRepo: string;
7
+ workerUrl?: string;
8
+ }): Promise<GitHubAppFlowResult>;
9
+ //# sourceMappingURL=github-app-flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-app-flow.d.ts","sourceRoot":"","sources":["../../src/cli/github-app-flow.ts"],"names":[],"mappings":"AAIA,OAAO,EACN,KAAK,cAAc,EAInB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG;IAClD,cAAc,EAAE,MAAM,CAAC;CACvB,CAAC;AAIF,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAC/C,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA2G/B"}
@@ -0,0 +1,190 @@
1
+ import { spawn } from "node:child_process";
2
+ import { randomBytes, randomUUID } from "node:crypto";
3
+ import { createServer } from "node:http";
4
+ import { consola } from "consola";
5
+ import { exchangeManifestCode, generateManifest, getManifestCreationUrl, } from "../github/manifest.js";
6
+ export async function runGitHubAppFlow(options) {
7
+ const [owner, repo] = options.monitoredRepo.split("/");
8
+ if (!owner || !repo) {
9
+ throw new Error("GitHub App setup needs MONITORED_REPO in owner/repo format.");
10
+ }
11
+ const ownerType = await detectOwnerType(owner);
12
+ const state = randomUUID();
13
+ const appName = buildAppName(owner, repo);
14
+ let createdApp;
15
+ const result = await new Promise((resolve, reject) => {
16
+ const server = createServer(async (request, response) => {
17
+ try {
18
+ const host = request.headers.host;
19
+ if (!host) {
20
+ writeText(response, 400, "Missing Host header.");
21
+ return;
22
+ }
23
+ const currentUrl = new URL(request.url ?? "/", `http://${host}`);
24
+ const baseUrl = `http://${host}`;
25
+ if (currentUrl.pathname === "/") {
26
+ const manifest = generateManifest({
27
+ appName,
28
+ redirectUrl: `${baseUrl}/callback`,
29
+ setupUrl: `${baseUrl}/installed`,
30
+ webhookUrl: options.workerUrl
31
+ ? `${options.workerUrl.replace(/\/$/, "")}/webhook/github`
32
+ : "https://example.com/aegis/webhook/github",
33
+ webhookActive: Boolean(options.workerUrl),
34
+ });
35
+ writeHtml(response, renderManifestForm({
36
+ actionUrl: getManifestCreationUrl(ownerType === "Organization" ? owner : undefined, state),
37
+ manifest,
38
+ owner,
39
+ repo,
40
+ appName,
41
+ webhookActive: Boolean(options.workerUrl),
42
+ }));
43
+ return;
44
+ }
45
+ if (currentUrl.pathname === "/callback") {
46
+ if (currentUrl.searchParams.get("state") !== state) {
47
+ writeText(response, 400, "State mismatch. Close this tab and rerun aegis setup.");
48
+ return;
49
+ }
50
+ const code = currentUrl.searchParams.get("code");
51
+ if (!code) {
52
+ writeText(response, 400, "Missing GitHub manifest code.");
53
+ return;
54
+ }
55
+ createdApp = await exchangeManifestCode(code);
56
+ const installUrl = `${createdApp.htmlUrl}/installations/new`;
57
+ consola.success(`Created GitHub App: ${createdApp.appName}`);
58
+ consola.info(`Install it on ${options.monitoredRepo}: ${installUrl}`);
59
+ writeHtml(response, renderInstallPage(installUrl, options.monitoredRepo));
60
+ return;
61
+ }
62
+ if (currentUrl.pathname === "/installed") {
63
+ const installationId = currentUrl.searchParams.get("installation_id");
64
+ if (!installationId || !createdApp) {
65
+ writeText(response, 400, "Install callback was missing installation_id. Copy the installation ID from the GitHub URL and rerun setup.");
66
+ return;
67
+ }
68
+ writeHtml(response, renderDonePage());
69
+ resolve({ ...createdApp, installationId });
70
+ setTimeout(() => server.close(), 250);
71
+ return;
72
+ }
73
+ writeText(response, 404, "Not found.");
74
+ }
75
+ catch (error) {
76
+ reject(error);
77
+ writeText(response, 500, error instanceof Error ? error.message : String(error));
78
+ setTimeout(() => server.close(), 250);
79
+ }
80
+ });
81
+ server.on("error", reject);
82
+ server.listen(0, "127.0.0.1", () => {
83
+ const address = server.address();
84
+ if (!address || typeof address === "string") {
85
+ reject(new Error("Could not start local GitHub App setup server."));
86
+ return;
87
+ }
88
+ const url = `http://127.0.0.1:${address.port}/`;
89
+ consola.info("Opening GitHub App setup in your browser.");
90
+ consola.info("Click Create GitHub App, then Install, then select only the monitored repo.");
91
+ consola.info(`If the browser does not open, paste this URL:\n${url}`);
92
+ openBrowser(url);
93
+ });
94
+ });
95
+ return result;
96
+ }
97
+ async function detectOwnerType(owner) {
98
+ try {
99
+ const response = await fetch(`https://api.github.com/users/${owner}`, {
100
+ headers: {
101
+ Accept: "application/vnd.github+json",
102
+ "X-GitHub-Api-Version": "2022-11-28",
103
+ },
104
+ });
105
+ if (!response.ok)
106
+ return "Organization";
107
+ const data = (await response.json());
108
+ return data.type === "User" ? "User" : "Organization";
109
+ }
110
+ catch {
111
+ return "Organization";
112
+ }
113
+ }
114
+ function buildAppName(owner, repo) {
115
+ const suffix = randomBytes(2).toString("hex");
116
+ return `aegis-${owner}-${repo}-${suffix}`
117
+ .toLowerCase()
118
+ .replace(/[^a-z0-9-]/g, "-")
119
+ .replace(/-+/g, "-")
120
+ .slice(0, 34);
121
+ }
122
+ function openBrowser(url) {
123
+ const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
124
+ const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
125
+ const child = spawn(command, args, { detached: true, stdio: "ignore" });
126
+ child.unref();
127
+ }
128
+ function renderManifestForm(options) {
129
+ return page("Create Aegis GitHub App", `
130
+ <h1>Create Aegis GitHub App</h1>
131
+ <p>This will create a private GitHub App for <strong>${escapeHtml(options.owner)}/${escapeHtml(options.repo)}</strong>.</p>
132
+ <ul>
133
+ <li>Permissions: contents, issues, pull requests</li>
134
+ <li>Events: issues, issue comments, pull requests</li>
135
+ <li>App name: ${escapeHtml(options.appName)}</li>
136
+ <li>Webhook: ${options.webhookActive ? "enabled" : "disabled until deploy"}</li>
137
+ </ul>
138
+ <form action="${escapeHtml(options.actionUrl)}" method="post">
139
+ <input type="hidden" name="manifest" value="${escapeHtml(JSON.stringify(options.manifest))}">
140
+ <button type="submit">Create GitHub App</button>
141
+ </form>
142
+ `);
143
+ }
144
+ function renderInstallPage(installUrl, repo) {
145
+ return page("Install Aegis GitHub App", `
146
+ <h1>GitHub App created</h1>
147
+ <p>Now install it on <strong>${escapeHtml(repo)}</strong>. Choose <strong>Only select repositories</strong> and pick that repo.</p>
148
+ <p><a class="button" href="${escapeHtml(installUrl)}">Install GitHub App</a></p>
149
+ `);
150
+ }
151
+ function renderDonePage() {
152
+ return page("Aegis GitHub App Connected", `
153
+ <h1>Aegis is connected</h1>
154
+ <p>You can close this tab and return to your terminal.</p>
155
+ `);
156
+ }
157
+ function page(title, body) {
158
+ return `<!doctype html>
159
+ <html lang="en">
160
+ <head>
161
+ <meta charset="utf-8">
162
+ <meta name="viewport" content="width=device-width, initial-scale=1">
163
+ <title>${escapeHtml(title)}</title>
164
+ <style>
165
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; max-width: 680px; margin: 64px auto; padding: 0 24px; color: #111827; line-height: 1.5; }
166
+ h1 { font-size: 28px; margin-bottom: 12px; }
167
+ button, .button { display: inline-block; border: 0; border-radius: 6px; background: #166534; color: white; padding: 10px 14px; font: inherit; text-decoration: none; cursor: pointer; }
168
+ ul { padding-left: 22px; }
169
+ </style>
170
+ </head>
171
+ <body>${body}</body>
172
+ </html>`;
173
+ }
174
+ function writeHtml(response, html) {
175
+ response.writeHead(200, { "content-type": "text/html; charset=utf-8" });
176
+ response.end(html);
177
+ }
178
+ function writeText(response, status, text) {
179
+ response.writeHead(status, { "content-type": "text/plain; charset=utf-8" });
180
+ response.end(text);
181
+ }
182
+ function escapeHtml(value) {
183
+ return value
184
+ .replace(/&/g, "&amp;")
185
+ .replace(/</g, "&lt;")
186
+ .replace(/>/g, "&gt;")
187
+ .replace(/"/g, "&quot;")
188
+ .replace(/'/g, "&#39;");
189
+ }
190
+ //# sourceMappingURL=github-app-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-app-flow.js","sourceRoot":"","sources":["../../src/cli/github-app-flow.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@
12
12
  */
13
13
  export type ManifestResult = {
14
14
  appId: string;
15
+ slug: string;
15
16
  appName: string;
16
17
  privateKey: string;
17
18
  webhookSecret: string;
@@ -22,13 +23,22 @@ export type ManifestResult = {
22
23
  /**
23
24
  * Generate the GitHub App manifest JSON.
24
25
  */
25
- export declare function generateManifest(callbackUrl: string): Record<string, unknown>;
26
+ export declare function generateManifest(options: {
27
+ appName: string;
28
+ redirectUrl: string;
29
+ setupUrl: string;
30
+ webhookUrl: string;
31
+ webhookActive: boolean;
32
+ }): Record<string, unknown>;
26
33
  /**
27
34
  * Exchange a manifest code for full app credentials.
28
35
  */
29
36
  export declare function exchangeManifestCode(code: string): Promise<ManifestResult>;
30
37
  /**
31
- * Get the manifest creation URL that the user opens in their browser.
38
+ * Get the manifest creation URL for manual fallback.
39
+ *
40
+ * GitHub requires the manifest to be POSTed to this URL. Do not send users here
41
+ * directly without a form body.
32
42
  */
33
- export declare function getManifestCreationUrl(manifest: Record<string, unknown>): string;
43
+ export declare function getManifestCreationUrl(owner?: string, state?: string): string;
34
44
  //# sourceMappingURL=manifest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/github/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAWH,MAAM,MAAM,cAAc,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAc7E;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAkChF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAGhF"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/github/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAWH,MAAM,MAAM,cAAc,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;CACvB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiB1B;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAmChF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAK7E"}
@@ -20,16 +20,19 @@ const MANIFEST_EVENTS = ["issues", "issue_comment", "pull_request"];
20
20
  /**
21
21
  * Generate the GitHub App manifest JSON.
22
22
  */
23
- export function generateManifest(callbackUrl) {
23
+ export function generateManifest(options) {
24
24
  return {
25
- name: "aegis-bot",
25
+ name: options.appName,
26
26
  url: "https://github.com/Nairon-AI/aegis",
27
+ description: "Self-hosted AFK bug-fixing agent for ready GitHub issues.",
27
28
  hook_attributes: {
28
- url: callbackUrl,
29
- active: true,
29
+ url: options.webhookUrl,
30
+ active: options.webhookActive,
30
31
  },
31
- redirect_url: callbackUrl,
32
- callback_urls: [callbackUrl],
32
+ redirect_url: options.redirectUrl,
33
+ callback_urls: [options.redirectUrl, options.setupUrl],
34
+ setup_url: options.setupUrl,
35
+ setup_on_update: true,
33
36
  public: false,
34
37
  default_permissions: MANIFEST_PERMISSIONS,
35
38
  default_events: MANIFEST_EVENTS,
@@ -53,6 +56,7 @@ export async function exchangeManifestCode(code) {
53
56
  const data = (await response.json());
54
57
  return {
55
58
  appId: String(data.id),
59
+ slug: data.slug,
56
60
  appName: data.name,
57
61
  privateKey: data.pem,
58
62
  webhookSecret: data.webhook_secret,
@@ -62,10 +66,15 @@ export async function exchangeManifestCode(code) {
62
66
  };
63
67
  }
64
68
  /**
65
- * Get the manifest creation URL that the user opens in their browser.
69
+ * Get the manifest creation URL for manual fallback.
70
+ *
71
+ * GitHub requires the manifest to be POSTed to this URL. Do not send users here
72
+ * directly without a form body.
66
73
  */
67
- export function getManifestCreationUrl(manifest) {
68
- const encoded = encodeURIComponent(JSON.stringify(manifest));
69
- return `https://github.com/settings/apps/new?manifest=${encoded}`;
74
+ export function getManifestCreationUrl(owner, state) {
75
+ const base = owner
76
+ ? `https://github.com/organizations/${owner}/settings/apps/new`
77
+ : "https://github.com/settings/apps/new";
78
+ return state ? `${base}?state=${encodeURIComponent(state)}` : base;
70
79
  }
71
80
  //# sourceMappingURL=manifest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/github/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,oBAAoB,GAAG;IAC5B,QAAQ,EAAE,OAAO;IACjB,aAAa,EAAE,OAAO;IACtB,MAAM,EAAE,OAAO;IACf,QAAQ,EAAE,MAAM;CAChB,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC;AAYpE;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IACnD,OAAO;QACN,IAAI,EAAE,WAAW;QACjB,GAAG,EAAE,oCAAoC;QACzC,eAAe,EAAE;YAChB,GAAG,EAAE,WAAW;YAChB,MAAM,EAAE,IAAI;SACZ;QACD,YAAY,EAAE,WAAW;QACzB,aAAa,EAAE,CAAC,WAAW,CAAC;QAC5B,MAAM,EAAE,KAAK;QACb,mBAAmB,EAAE,oBAAoB;QACzC,cAAc,EAAE,eAAe;KAC/B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAY;IACtD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,wCAAwC,IAAI,cAAc,EAAE;QACxF,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACR,MAAM,EAAE,6BAA6B;YACrC,sBAAsB,EAAE,YAAY;SACpC;KACD,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CASlC,CAAC;IAEF,OAAO;QACN,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,IAAI,CAAC,IAAI;QAClB,UAAU,EAAE,IAAI,CAAC,GAAG;QACpB,aAAa,EAAE,IAAI,CAAC,cAAc;QAClC,QAAQ,EAAE,IAAI,CAAC,SAAS;QACxB,YAAY,EAAE,IAAI,CAAC,aAAa;QAChC,OAAO,EAAE,IAAI,CAAC,QAAQ;KACtB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAiC;IACvE,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC7D,OAAO,iDAAiD,OAAO,EAAE,CAAC;AACnE,CAAC"}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/github/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,oBAAoB,GAAG;IAC5B,QAAQ,EAAE,OAAO;IACjB,aAAa,EAAE,OAAO;IACtB,MAAM,EAAE,OAAO;IACf,QAAQ,EAAE,MAAM;CAChB,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC;AAapE;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAMhC;IACA,OAAO;QACN,IAAI,EAAE,OAAO,CAAC,OAAO;QACrB,GAAG,EAAE,oCAAoC;QACzC,WAAW,EAAE,2DAA2D;QACxE,eAAe,EAAE;YAChB,GAAG,EAAE,OAAO,CAAC,UAAU;YACvB,MAAM,EAAE,OAAO,CAAC,aAAa;SAC7B;QACD,YAAY,EAAE,OAAO,CAAC,WAAW;QACjC,aAAa,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC;QACtD,SAAS,EAAE,OAAO,CAAC,QAAQ;QAC3B,eAAe,EAAE,IAAI;QACrB,MAAM,EAAE,KAAK;QACb,mBAAmB,EAAE,oBAAoB;QACzC,cAAc,EAAE,eAAe;KAC/B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAY;IACtD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,wCAAwC,IAAI,cAAc,EAAE;QACxF,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACR,MAAM,EAAE,6BAA6B;YACrC,sBAAsB,EAAE,YAAY;SACpC;KACD,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CASlC,CAAC;IAEF,OAAO;QACN,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,IAAI;QAClB,UAAU,EAAE,IAAI,CAAC,GAAG;QACpB,aAAa,EAAE,IAAI,CAAC,cAAc;QAClC,QAAQ,EAAE,IAAI,CAAC,SAAS;QACxB,YAAY,EAAE,IAAI,CAAC,aAAa;QAChC,OAAO,EAAE,IAAI,CAAC,QAAQ;KACtB,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAc,EAAE,KAAc;IACpE,MAAM,IAAI,GAAG,KAAK;QACjB,CAAC,CAAC,oCAAoC,KAAK,oBAAoB;QAC/D,CAAC,CAAC,sCAAsC,CAAC;IAC1C,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,UAAU,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACpE,CAAC"}
package/docs/SETUP.md CHANGED
@@ -88,7 +88,7 @@ Pick one path.
88
88
 
89
89
  ### Option A: GitHub Token
90
90
 
91
- Fastest first setup. Good for proving the repo works.
91
+ Fastest first setup. Use this for the first local dry-run.
92
92
 
93
93
  Create a fine-grained personal access token:
94
94
 
@@ -100,11 +100,32 @@ Create a fine-grained personal access token:
100
100
 
101
101
  The token lets Aegis scan issues, create branches, push fixes, and open PRs.
102
102
 
103
- ### Option B: GitHub App
103
+ ### Option B: One-Click GitHub App
104
104
 
105
- Better for teams and production use.
105
+ Better for deployed/team use. The setup wizard can create the GitHub App for you.
106
106
 
107
- Create a GitHub App with:
107
+ When `aegis setup` asks for `Auth method`, choose:
108
+
109
+ ```text
110
+ One-click GitHub App (best for deployed/team use)
111
+ ```
112
+
113
+ Aegis opens a browser page. You click:
114
+
115
+ 1. `Create GitHub App`
116
+ 2. `Install`
117
+ 3. `Only select repositories`
118
+ 4. Pick the monitored repo
119
+
120
+ The CLI saves the App ID, private key, webhook secret, and installation ID into `.aegis/.env`.
121
+
122
+ If you have not deployed yet, the app webhook starts disabled. That is fine for local dry-run. After deploy, add the repo webhook from Step 9.
123
+
124
+ ### Option C: Existing GitHub App
125
+
126
+ Use this only if you already have an app.
127
+
128
+ The app needs:
108
129
 
109
130
  - Contents: read/write
110
131
  - Issues: read/write
@@ -130,9 +151,9 @@ npx @nairon-ai/aegis setup
130
151
 
131
152
  Important answers:
132
153
 
133
- - `GitHub repo to monitor`: the app repo, for example `acme/web-app`
154
+ - `GitHub repo to monitor`: the app repo, for example `acme/web-app` or `https://github.com/acme/web-app`
134
155
  - `Base branch`: usually `main`
135
- - GitHub auth: token or app credentials from Step 3
156
+ - GitHub auth: use `GitHub token` for the first test, or `One-click GitHub App` for deployed/team use
136
157
  - `GitHub webhook secret`: generate one and keep it in `.aegis/.env`
137
158
  - `Automation mode`: start with `plan-first`
138
159
  - `Context profile`: start with `minimal`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nairon-ai/aegis",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Self-hosted AFK bug-fixing agent for GitHub Issues and Linear",
5
5
  "type": "module",
6
6
  "repository": {
@@ -57,9 +57,9 @@ This directory configures Aegis for this repository.
57
57
  ## First Run
58
58
 
59
59
  \`\`\`bash
60
- npx @nairon-ai/aegis setup
61
- npx @nairon-ai/aegis pickup --dry-run
62
- npx @nairon-ai/aegis deploy
60
+ npx --yes @nairon-ai/aegis@latest setup
61
+ npx --yes @nairon-ai/aegis@latest pickup --dry-run
62
+ npx --yes @nairon-ai/aegis@latest deploy
63
63
  \`\`\`
64
64
 
65
65
  For the first test, use:
@@ -102,11 +102,11 @@ export function runInit(): void {
102
102
  writeIfMissing(resolve(PROJECT_AEGIS_DIR, "README.md"), README);
103
103
  consola.success("Created .aegis/");
104
104
  consola.log("\nNext:");
105
- consola.log(" 1. npx @nairon-ai/aegis setup");
105
+ consola.log(" 1. npx --yes @nairon-ai/aegis@latest setup");
106
106
  consola.log(" 2. create GitHub labels: bug, ready to implement");
107
107
  consola.log(" 3. create a tiny test bug issue");
108
- consola.log(" 4. npx @nairon-ai/aegis pickup --dry-run");
109
- consola.log(" 5. npx @nairon-ai/aegis deploy");
108
+ consola.log(" 4. npx --yes @nairon-ai/aegis@latest pickup --dry-run");
109
+ consola.log(" 5. npx --yes @nairon-ai/aegis@latest deploy");
110
110
  consola.log("");
111
111
  }
112
112
 
@@ -3,6 +3,7 @@ import { resolve } from "node:path";
3
3
  import { defineCommand } from "citty";
4
4
  import { consola } from "consola";
5
5
  import type { AegisCliConfig } from "../../shared/types.js";
6
+ import { runGitHubAppFlow } from "../github-app-flow.js";
6
7
  import { resolveEnvFileForWrite } from "../paths.js";
7
8
  import { detectSetupState, printState, saveConfig } from "../state.js";
8
9
 
@@ -39,9 +40,8 @@ export async function runSetupWizard(): Promise<void> {
39
40
  }
40
41
 
41
42
  async function setupRepo(config: AegisCliConfig): Promise<void> {
42
- config.monitoredRepo = await promptText(
43
- "GitHub repo to monitor (owner/repo):",
44
- config.monitoredRepo,
43
+ config.monitoredRepo = normalizeGitHubRepo(
44
+ await promptText("GitHub repo to monitor (owner/repo):", config.monitoredRepo),
45
45
  );
46
46
  config.baseBranch = await promptText("Base branch:", config.baseBranch ?? "main");
47
47
  }
@@ -49,13 +49,14 @@ async function setupRepo(config: AegisCliConfig): Promise<void> {
49
49
  async function setupGitHub(config: AegisCliConfig): Promise<void> {
50
50
  consola.log("\nGitHub access");
51
51
  consola.info(
52
- "For the first test, a fine-grained token is fastest. For shared/team use, use a GitHub App.",
52
+ "For the first test, a fine-grained token is fastest. For deployed/team use, use the one-click GitHub App flow.",
53
53
  );
54
54
  const method = (await consola.prompt("Auth method:", {
55
55
  type: "select",
56
56
  options: [
57
- { label: "GitHub App (recommended)", value: "app" },
58
- { label: "GitHub token (simpler local testing)", value: "token" },
57
+ { label: "GitHub token (recommended first test)", value: "token" },
58
+ { label: "One-click GitHub App (best for deployed/team use)", value: "app-flow" },
59
+ { label: "Paste existing GitHub App credentials", value: "app-manual" },
59
60
  ],
60
61
  })) as string;
61
62
 
@@ -64,29 +65,37 @@ async function setupGitHub(config: AegisCliConfig): Promise<void> {
64
65
  "GitHub token with contents/issues/PR read-write access:",
65
66
  config.githubToken,
66
67
  );
67
- } else {
68
- config.githubAppId = await promptText("GitHub App ID:", config.githubAppId);
69
- const keyPath = await promptText("Path to GitHub App private key .pem:", undefined);
70
- if (keyPath) {
71
- const resolved = resolve(keyPath.replace(/^~/, process.env.HOME ?? "~"));
72
- if (existsSync(resolved)) {
73
- config.githubAppPrivateKey = Buffer.from(readFileSync(resolved, "utf-8")).toString(
74
- "base64",
75
- );
76
- consola.success("Loaded private key");
77
- } else {
78
- consola.warn(`File not found: ${resolved}`);
79
- }
68
+ config.githubAppId = undefined;
69
+ config.githubAppPrivateKey = undefined;
70
+ config.githubInstallationId = undefined;
71
+ } else if (method === "app-flow") {
72
+ if (!config.monitoredRepo) {
73
+ consola.warn("Set the monitored repo first.");
74
+ return;
80
75
  }
81
- if (!config.githubAppPrivateKey) {
82
- config.githubAppPrivateKey = Buffer.from(
83
- await promptText("Paste GitHub App private key PEM:", config.githubAppPrivateKey),
84
- ).toString("base64");
76
+ try {
77
+ const app = await runGitHubAppFlow({
78
+ monitoredRepo: config.monitoredRepo,
79
+ workerUrl: config.workerUrl,
80
+ });
81
+ config.githubAppId = app.appId;
82
+ config.githubAppPrivateKey = Buffer.from(app.privateKey, "utf-8").toString("base64");
83
+ config.githubInstallationId = app.installationId;
84
+ config.githubWebhookSecret = app.webhookSecret;
85
+ config.githubToken = undefined;
86
+ consola.success("Saved GitHub App credentials from GitHub.");
87
+ } catch (error) {
88
+ consola.warn(error instanceof Error ? error.message : String(error));
89
+ consola.info("Falling back to manual GitHub App credentials.");
90
+ await setupGitHubAppManual(config);
85
91
  }
86
- config.githubInstallationId = await promptText(
87
- "GitHub App installation ID:",
88
- config.githubInstallationId,
89
- );
92
+ } else {
93
+ await setupGitHubAppManual(config);
94
+ }
95
+
96
+ if (config.githubWebhookSecret) {
97
+ consola.info("GitHub webhook secret is already configured.");
98
+ return;
90
99
  }
91
100
 
92
101
  const generateSecret = (await consola.prompt("Generate a GitHub webhook secret?", {
@@ -101,6 +110,30 @@ async function setupGitHub(config: AegisCliConfig): Promise<void> {
101
110
  }
102
111
  }
103
112
 
113
+ async function setupGitHubAppManual(config: AegisCliConfig): Promise<void> {
114
+ config.githubAppId = await promptText("GitHub App ID:", config.githubAppId);
115
+ const keyPath = await promptText("Path to GitHub App private key .pem:", undefined);
116
+ if (keyPath) {
117
+ const resolved = resolve(keyPath.replace(/^~/, process.env.HOME ?? "~"));
118
+ if (existsSync(resolved)) {
119
+ config.githubAppPrivateKey = Buffer.from(readFileSync(resolved, "utf-8")).toString("base64");
120
+ consola.success("Loaded private key");
121
+ } else {
122
+ consola.warn(`File not found: ${resolved}`);
123
+ }
124
+ }
125
+ if (!config.githubAppPrivateKey) {
126
+ config.githubAppPrivateKey = Buffer.from(
127
+ await promptText("Paste GitHub App private key PEM:", config.githubAppPrivateKey),
128
+ ).toString("base64");
129
+ }
130
+ config.githubInstallationId = await promptText(
131
+ "GitHub App installation ID:",
132
+ config.githubInstallationId,
133
+ );
134
+ config.githubToken = undefined;
135
+ }
136
+
104
137
  async function setupLinear(config: AegisCliConfig): Promise<void> {
105
138
  const enable = (await consola.prompt("Connect Linear too?", {
106
139
  type: "confirm",
@@ -215,3 +248,15 @@ async function promptText(message: string, initial: string | undefined): Promise
215
248
  })) as string;
216
249
  return value?.trim() ?? "";
217
250
  }
251
+
252
+ function normalizeGitHubRepo(input: string): string {
253
+ const value = input
254
+ .trim()
255
+ .replace(/\.git$/, "")
256
+ .replace(/\/$/, "");
257
+ const urlMatch = value.match(/github\.com[:/]([^/\s]+)\/([^/\s]+)$/i);
258
+ if (urlMatch) return `${urlMatch[1]}/${urlMatch[2]}`;
259
+ const shorthandMatch = value.match(/^([^/\s]+)\/([^/\s]+)$/);
260
+ if (shorthandMatch) return `${shorthandMatch[1]}/${shorthandMatch[2]}`;
261
+ return value;
262
+ }
@@ -0,0 +1,248 @@
1
+ import { spawn } from "node:child_process";
2
+ import { randomBytes, randomUUID } from "node:crypto";
3
+ import { type ServerResponse, createServer } from "node:http";
4
+ import { consola } from "consola";
5
+ import {
6
+ type ManifestResult,
7
+ exchangeManifestCode,
8
+ generateManifest,
9
+ getManifestCreationUrl,
10
+ } from "../github/manifest.js";
11
+
12
+ export type GitHubAppFlowResult = ManifestResult & {
13
+ installationId: string;
14
+ };
15
+
16
+ type OwnerType = "Organization" | "User";
17
+
18
+ export async function runGitHubAppFlow(options: {
19
+ monitoredRepo: string;
20
+ workerUrl?: string;
21
+ }): Promise<GitHubAppFlowResult> {
22
+ const [owner, repo] = options.monitoredRepo.split("/");
23
+ if (!owner || !repo) {
24
+ throw new Error("GitHub App setup needs MONITORED_REPO in owner/repo format.");
25
+ }
26
+
27
+ const ownerType = await detectOwnerType(owner);
28
+ const state = randomUUID();
29
+ const appName = buildAppName(owner, repo);
30
+ let createdApp: ManifestResult | undefined;
31
+
32
+ const result = await new Promise<GitHubAppFlowResult>((resolve, reject) => {
33
+ const server = createServer(async (request, response) => {
34
+ try {
35
+ const host = request.headers.host;
36
+ if (!host) {
37
+ writeText(response, 400, "Missing Host header.");
38
+ return;
39
+ }
40
+ const currentUrl = new URL(request.url ?? "/", `http://${host}`);
41
+ const baseUrl = `http://${host}`;
42
+
43
+ if (currentUrl.pathname === "/") {
44
+ const manifest = generateManifest({
45
+ appName,
46
+ redirectUrl: `${baseUrl}/callback`,
47
+ setupUrl: `${baseUrl}/installed`,
48
+ webhookUrl: options.workerUrl
49
+ ? `${options.workerUrl.replace(/\/$/, "")}/webhook/github`
50
+ : "https://example.com/aegis/webhook/github",
51
+ webhookActive: Boolean(options.workerUrl),
52
+ });
53
+ writeHtml(
54
+ response,
55
+ renderManifestForm({
56
+ actionUrl: getManifestCreationUrl(
57
+ ownerType === "Organization" ? owner : undefined,
58
+ state,
59
+ ),
60
+ manifest,
61
+ owner,
62
+ repo,
63
+ appName,
64
+ webhookActive: Boolean(options.workerUrl),
65
+ }),
66
+ );
67
+ return;
68
+ }
69
+
70
+ if (currentUrl.pathname === "/callback") {
71
+ if (currentUrl.searchParams.get("state") !== state) {
72
+ writeText(response, 400, "State mismatch. Close this tab and rerun aegis setup.");
73
+ return;
74
+ }
75
+ const code = currentUrl.searchParams.get("code");
76
+ if (!code) {
77
+ writeText(response, 400, "Missing GitHub manifest code.");
78
+ return;
79
+ }
80
+ createdApp = await exchangeManifestCode(code);
81
+ const installUrl = `${createdApp.htmlUrl}/installations/new`;
82
+ consola.success(`Created GitHub App: ${createdApp.appName}`);
83
+ consola.info(`Install it on ${options.monitoredRepo}: ${installUrl}`);
84
+ writeHtml(response, renderInstallPage(installUrl, options.monitoredRepo));
85
+ return;
86
+ }
87
+
88
+ if (currentUrl.pathname === "/installed") {
89
+ const installationId = currentUrl.searchParams.get("installation_id");
90
+ if (!installationId || !createdApp) {
91
+ writeText(
92
+ response,
93
+ 400,
94
+ "Install callback was missing installation_id. Copy the installation ID from the GitHub URL and rerun setup.",
95
+ );
96
+ return;
97
+ }
98
+ writeHtml(response, renderDonePage());
99
+ resolve({ ...createdApp, installationId });
100
+ setTimeout(() => server.close(), 250);
101
+ return;
102
+ }
103
+
104
+ writeText(response, 404, "Not found.");
105
+ } catch (error) {
106
+ reject(error);
107
+ writeText(response, 500, error instanceof Error ? error.message : String(error));
108
+ setTimeout(() => server.close(), 250);
109
+ }
110
+ });
111
+
112
+ server.on("error", reject);
113
+ server.listen(0, "127.0.0.1", () => {
114
+ const address = server.address();
115
+ if (!address || typeof address === "string") {
116
+ reject(new Error("Could not start local GitHub App setup server."));
117
+ return;
118
+ }
119
+ const url = `http://127.0.0.1:${address.port}/`;
120
+ consola.info("Opening GitHub App setup in your browser.");
121
+ consola.info("Click Create GitHub App, then Install, then select only the monitored repo.");
122
+ consola.info(`If the browser does not open, paste this URL:\n${url}`);
123
+ openBrowser(url);
124
+ });
125
+ });
126
+
127
+ return result;
128
+ }
129
+
130
+ async function detectOwnerType(owner: string): Promise<OwnerType> {
131
+ try {
132
+ const response = await fetch(`https://api.github.com/users/${owner}`, {
133
+ headers: {
134
+ Accept: "application/vnd.github+json",
135
+ "X-GitHub-Api-Version": "2022-11-28",
136
+ },
137
+ });
138
+ if (!response.ok) return "Organization";
139
+ const data = (await response.json()) as { type?: string };
140
+ return data.type === "User" ? "User" : "Organization";
141
+ } catch {
142
+ return "Organization";
143
+ }
144
+ }
145
+
146
+ function buildAppName(owner: string, repo: string): string {
147
+ const suffix = randomBytes(2).toString("hex");
148
+ return `aegis-${owner}-${repo}-${suffix}`
149
+ .toLowerCase()
150
+ .replace(/[^a-z0-9-]/g, "-")
151
+ .replace(/-+/g, "-")
152
+ .slice(0, 34);
153
+ }
154
+
155
+ function openBrowser(url: string): void {
156
+ const command =
157
+ process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
158
+ const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
159
+ const child = spawn(command, args, { detached: true, stdio: "ignore" });
160
+ child.unref();
161
+ }
162
+
163
+ function renderManifestForm(options: {
164
+ actionUrl: string;
165
+ manifest: Record<string, unknown>;
166
+ owner: string;
167
+ repo: string;
168
+ appName: string;
169
+ webhookActive: boolean;
170
+ }): string {
171
+ return page(
172
+ "Create Aegis GitHub App",
173
+ `
174
+ <h1>Create Aegis GitHub App</h1>
175
+ <p>This will create a private GitHub App for <strong>${escapeHtml(options.owner)}/${escapeHtml(
176
+ options.repo,
177
+ )}</strong>.</p>
178
+ <ul>
179
+ <li>Permissions: contents, issues, pull requests</li>
180
+ <li>Events: issues, issue comments, pull requests</li>
181
+ <li>App name: ${escapeHtml(options.appName)}</li>
182
+ <li>Webhook: ${options.webhookActive ? "enabled" : "disabled until deploy"}</li>
183
+ </ul>
184
+ <form action="${escapeHtml(options.actionUrl)}" method="post">
185
+ <input type="hidden" name="manifest" value="${escapeHtml(JSON.stringify(options.manifest))}">
186
+ <button type="submit">Create GitHub App</button>
187
+ </form>
188
+ `,
189
+ );
190
+ }
191
+
192
+ function renderInstallPage(installUrl: string, repo: string): string {
193
+ return page(
194
+ "Install Aegis GitHub App",
195
+ `
196
+ <h1>GitHub App created</h1>
197
+ <p>Now install it on <strong>${escapeHtml(repo)}</strong>. Choose <strong>Only select repositories</strong> and pick that repo.</p>
198
+ <p><a class="button" href="${escapeHtml(installUrl)}">Install GitHub App</a></p>
199
+ `,
200
+ );
201
+ }
202
+
203
+ function renderDonePage(): string {
204
+ return page(
205
+ "Aegis GitHub App Connected",
206
+ `
207
+ <h1>Aegis is connected</h1>
208
+ <p>You can close this tab and return to your terminal.</p>
209
+ `,
210
+ );
211
+ }
212
+
213
+ function page(title: string, body: string): string {
214
+ return `<!doctype html>
215
+ <html lang="en">
216
+ <head>
217
+ <meta charset="utf-8">
218
+ <meta name="viewport" content="width=device-width, initial-scale=1">
219
+ <title>${escapeHtml(title)}</title>
220
+ <style>
221
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; max-width: 680px; margin: 64px auto; padding: 0 24px; color: #111827; line-height: 1.5; }
222
+ h1 { font-size: 28px; margin-bottom: 12px; }
223
+ button, .button { display: inline-block; border: 0; border-radius: 6px; background: #166534; color: white; padding: 10px 14px; font: inherit; text-decoration: none; cursor: pointer; }
224
+ ul { padding-left: 22px; }
225
+ </style>
226
+ </head>
227
+ <body>${body}</body>
228
+ </html>`;
229
+ }
230
+
231
+ function writeHtml(response: ServerResponse, html: string): void {
232
+ response.writeHead(200, { "content-type": "text/html; charset=utf-8" });
233
+ response.end(html);
234
+ }
235
+
236
+ function writeText(response: ServerResponse, status: number, text: string): void {
237
+ response.writeHead(status, { "content-type": "text/plain; charset=utf-8" });
238
+ response.end(text);
239
+ }
240
+
241
+ function escapeHtml(value: string): string {
242
+ return value
243
+ .replace(/&/g, "&amp;")
244
+ .replace(/</g, "&lt;")
245
+ .replace(/>/g, "&gt;")
246
+ .replace(/"/g, "&quot;")
247
+ .replace(/'/g, "&#39;");
248
+ }
@@ -22,6 +22,7 @@ const MANIFEST_EVENTS = ["issues", "issue_comment", "pull_request"];
22
22
 
23
23
  export type ManifestResult = {
24
24
  appId: string;
25
+ slug: string;
25
26
  appName: string;
26
27
  privateKey: string;
27
28
  webhookSecret: string;
@@ -33,16 +34,25 @@ export type ManifestResult = {
33
34
  /**
34
35
  * Generate the GitHub App manifest JSON.
35
36
  */
36
- export function generateManifest(callbackUrl: string): Record<string, unknown> {
37
+ export function generateManifest(options: {
38
+ appName: string;
39
+ redirectUrl: string;
40
+ setupUrl: string;
41
+ webhookUrl: string;
42
+ webhookActive: boolean;
43
+ }): Record<string, unknown> {
37
44
  return {
38
- name: "aegis-bot",
45
+ name: options.appName,
39
46
  url: "https://github.com/Nairon-AI/aegis",
47
+ description: "Self-hosted AFK bug-fixing agent for ready GitHub issues.",
40
48
  hook_attributes: {
41
- url: callbackUrl,
42
- active: true,
49
+ url: options.webhookUrl,
50
+ active: options.webhookActive,
43
51
  },
44
- redirect_url: callbackUrl,
45
- callback_urls: [callbackUrl],
52
+ redirect_url: options.redirectUrl,
53
+ callback_urls: [options.redirectUrl, options.setupUrl],
54
+ setup_url: options.setupUrl,
55
+ setup_on_update: true,
46
56
  public: false,
47
57
  default_permissions: MANIFEST_PERMISSIONS,
48
58
  default_events: MANIFEST_EVENTS,
@@ -79,6 +89,7 @@ export async function exchangeManifestCode(code: string): Promise<ManifestResult
79
89
 
80
90
  return {
81
91
  appId: String(data.id),
92
+ slug: data.slug,
82
93
  appName: data.name,
83
94
  privateKey: data.pem,
84
95
  webhookSecret: data.webhook_secret,
@@ -89,9 +100,14 @@ export async function exchangeManifestCode(code: string): Promise<ManifestResult
89
100
  }
90
101
 
91
102
  /**
92
- * Get the manifest creation URL that the user opens in their browser.
103
+ * Get the manifest creation URL for manual fallback.
104
+ *
105
+ * GitHub requires the manifest to be POSTed to this URL. Do not send users here
106
+ * directly without a form body.
93
107
  */
94
- export function getManifestCreationUrl(manifest: Record<string, unknown>): string {
95
- const encoded = encodeURIComponent(JSON.stringify(manifest));
96
- return `https://github.com/settings/apps/new?manifest=${encoded}`;
108
+ export function getManifestCreationUrl(owner?: string, state?: string): string {
109
+ const base = owner
110
+ ? `https://github.com/organizations/${owner}/settings/apps/new`
111
+ : "https://github.com/settings/apps/new";
112
+ return state ? `${base}?state=${encodeURIComponent(state)}` : base;
97
113
  }