@tokenfactory/acc-runner 0.2.0-internal

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.
Files changed (58) hide show
  1. package/README.md +116 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +77 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/config.d.ts +15 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +48 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/doctor.d.ts +13 -0
  11. package/dist/doctor.d.ts.map +1 -0
  12. package/dist/doctor.js +251 -0
  13. package/dist/doctor.js.map +1 -0
  14. package/dist/gh.d.ts +16 -0
  15. package/dist/gh.d.ts.map +1 -0
  16. package/dist/gh.js +37 -0
  17. package/dist/gh.js.map +1 -0
  18. package/dist/git.d.ts +9 -0
  19. package/dist/git.d.ts.map +1 -0
  20. package/dist/git.js +25 -0
  21. package/dist/git.js.map +1 -0
  22. package/dist/keychain.d.ts +21 -0
  23. package/dist/keychain.d.ts.map +1 -0
  24. package/dist/keychain.js +45 -0
  25. package/dist/keychain.js.map +1 -0
  26. package/dist/login.d.ts +8 -0
  27. package/dist/login.d.ts.map +1 -0
  28. package/dist/login.js +124 -0
  29. package/dist/login.js.map +1 -0
  30. package/dist/logout.d.ts +2 -0
  31. package/dist/logout.d.ts.map +1 -0
  32. package/dist/logout.js +31 -0
  33. package/dist/logout.js.map +1 -0
  34. package/dist/prompt.d.ts +38 -0
  35. package/dist/prompt.d.ts.map +1 -0
  36. package/dist/prompt.js +78 -0
  37. package/dist/prompt.js.map +1 -0
  38. package/dist/supabase.d.ts +4 -0
  39. package/dist/supabase.d.ts.map +1 -0
  40. package/dist/supabase.js +22 -0
  41. package/dist/supabase.js.map +1 -0
  42. package/dist/task-runner.d.ts +48 -0
  43. package/dist/task-runner.d.ts.map +1 -0
  44. package/dist/task-runner.js +222 -0
  45. package/dist/task-runner.js.map +1 -0
  46. package/dist/types.d.ts +77 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +10 -0
  49. package/dist/types.js.map +1 -0
  50. package/dist/version-check.d.ts +17 -0
  51. package/dist/version-check.d.ts.map +1 -0
  52. package/dist/version-check.js +40 -0
  53. package/dist/version-check.js.map +1 -0
  54. package/dist/watch.d.ts +12 -0
  55. package/dist/watch.d.ts.map +1 -0
  56. package/dist/watch.js +132 -0
  57. package/dist/watch.js.map +1 -0
  58. package/package.json +36 -0
package/README.md ADDED
@@ -0,0 +1,116 @@
1
+ # `@tokenfactory/acc-runner`
2
+
3
+ Local runner for [Agent Control Center](https://github.com/tokenfactory-pvt-ltd/agent-control-center).
4
+ Subscribes to ACC over Supabase Realtime; on a task assignment, spawns
5
+ your local `claude` CLI with the rendered prompt, streams logs back, and
6
+ opens a PR via `gh` when done.
7
+
8
+ > Status: internal beta. Ships with ACC v0.2.0-internal.
9
+
10
+ ## Install
11
+
12
+ ```sh
13
+ pnpm add -g @tokenfactory/acc-runner
14
+ # or
15
+ npm i -g @tokenfactory/acc-runner
16
+ ```
17
+
18
+ Requires:
19
+
20
+ - Node.js 20.6+
21
+ - `claude` (Claude Code CLI) in `$PATH`
22
+ - `gh` (GitHub CLI) in `$PATH`, authenticated (`gh auth login`)
23
+ - `git`, configured with `user.email`
24
+ - A local clone of the target repo (default `~/work/TechArch`)
25
+
26
+ Run `acc-runner doctor` after install to verify all the above.
27
+
28
+ ## Configuration
29
+
30
+ The CLI reads from environment variables — set these in your shell
31
+ profile so `acc-runner watch` finds them.
32
+
33
+ | Variable | Required | Notes |
34
+ | ------------------------- | :------: | ----------------------------------------------------- |
35
+ | `ACC_PUBLIC_URL` | ✓ | e.g. `https://acc.techarch.dev` |
36
+ | `ACC_SUPABASE_URL` | ✓ | Mirror of the SPA's `VITE_SUPABASE_URL` |
37
+ | `ACC_SUPABASE_ANON_KEY` | ✓ | Same anon key the SPA uses |
38
+ | `ACC_REPO_PATH` | | Defaults to `~/work/TechArch` |
39
+ | `ACC_TARGET_REPO` | | Defaults to `tokenfactory-pvt-ltd/TechArch` |
40
+ | `ACC_INTEGRATION_BRANCH` | | Defaults to `acc/integration` |
41
+
42
+ ## Quickstart
43
+
44
+ ```sh
45
+ acc-runner login # device-code OAuth in your browser
46
+ acc-runner doctor # verify env (all green)
47
+ acc-runner watch # long-running; receives + executes tasks
48
+ ```
49
+
50
+ Then, in ACC, assign a task to this machine and click **Start**. The CLI
51
+ will:
52
+
53
+ 1. Transition the task to `running`
54
+ 2. `git fetch && git checkout -B acc/T-XX-<slug>`
55
+ 3. Pipe the rendered prompt into `claude --print`
56
+ 4. Stream stdout/stderr to `acc.task_events` (visible in the History tab)
57
+ 5. `git push` and open a PR titled `[T-XX] <task title>`
58
+
59
+ ## Commands
60
+
61
+ ### `acc-runner login`
62
+
63
+ Device-code OAuth flow. Stores a JWT in your OS keychain (`acc-runner`
64
+ service) and registers this machine in `acc.runners`.
65
+
66
+ ### `acc-runner logout`
67
+
68
+ Clears the keychain entry and marks this runner offline.
69
+
70
+ ### `acc-runner watch`
71
+
72
+ Subscribes to a Realtime broadcast channel scoped to your runner. Sends a
73
+ heartbeat every 4s. Cancellation is honored via `task_cancelled`
74
+ broadcasts (sends SIGTERM to the in-flight `claude` child).
75
+
76
+ ### `acc-runner doctor`
77
+
78
+ Runs every environment check and prints a green/red list. Exits 0 if all
79
+ pass, 1 otherwise. Suitable for CI.
80
+
81
+ ### `acc-runner version`
82
+
83
+ Prints the CLI version and the protocol version it speaks. The server
84
+ exposes a minimum-protocol-version pin at `/api/runner/min-version`; the
85
+ CLI refuses to start if behind.
86
+
87
+ ## Troubleshooting
88
+
89
+ **`✗ Not signed in. Run \`acc-runner login\` first.`** — keychain entry
90
+ was cleared or never created. Run `acc-runner login`.
91
+
92
+ **`✗ keychain read/write` (FAIL)** — on Linux, install `libsecret`. On
93
+ macOS, ensure your login keychain is unlocked. On Windows, run from a
94
+ session with credential manager access.
95
+
96
+ **`✗ register_runner failed`** — the migration that ships the
97
+ `acc.register_runner` RPC may not be applied to your environment yet.
98
+ Coordinate with the operator who ran `supabase db push`.
99
+
100
+ **Task transitions to `failed` immediately** — check the History tab for
101
+ the underlying error. Common causes: `git fetch` permission denied (push
102
+ auth), `claude --print` returned non-zero, or the rendered prompt lacked
103
+ acceptance criteria.
104
+
105
+ ## Security notes
106
+
107
+ - The CLI never reads or writes your git credentials, gh credentials, or
108
+ Anthropic API keys. It calls binaries you already have authenticated.
109
+ - The Supabase JWT is short-lived; the CLI stores it in your OS keychain
110
+ via `keytar`, never in plaintext on disk.
111
+ - Heartbeat interval is 4s — do not tighten this. The server expects to
112
+ see it; tighter intervals consume the Realtime budget.
113
+
114
+ ## License
115
+
116
+ Proprietary. Not for redistribution.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * acc-runner — CLI entry point. commander wires subcommands into named
4
+ * functions in their own files; this module is intentionally thin.
5
+ */
6
+ import { Command } from "commander";
7
+ import chalk from "chalk";
8
+ import { createRequire } from "node:module";
9
+ import { loginCommand } from "./login.js";
10
+ import { logoutCommand } from "./logout.js";
11
+ import { watchCommand } from "./watch.js";
12
+ import { doctorCommand } from "./doctor.js";
13
+ import { PROTOCOL_VERSION } from "./types.js";
14
+ const require = createRequire(import.meta.url);
15
+ const pkg = require("../package.json");
16
+ const program = new Command();
17
+ program
18
+ .name("acc-runner")
19
+ .description("Agent Control Center local runner. Subscribes to ACC, spawns Claude Code on assignment, and opens a PR when done.")
20
+ .version(`${pkg.version} (protocol v${PROTOCOL_VERSION})`);
21
+ program
22
+ .command("login")
23
+ .description("Sign in via device-code OAuth and register this machine.")
24
+ .action(async () => {
25
+ try {
26
+ await loginCommand();
27
+ }
28
+ catch (err) {
29
+ console.error(chalk.red(`✗ ${err.message}`));
30
+ process.exitCode = 1;
31
+ }
32
+ });
33
+ program
34
+ .command("logout")
35
+ .description("Clear the local session and mark this runner offline.")
36
+ .action(async () => {
37
+ try {
38
+ await logoutCommand();
39
+ }
40
+ catch (err) {
41
+ console.error(chalk.red(`✗ ${err.message}`));
42
+ process.exitCode = 1;
43
+ }
44
+ });
45
+ program
46
+ .command("watch")
47
+ .description("Long-running. Receive task assignments and execute them.")
48
+ .action(async () => {
49
+ try {
50
+ await watchCommand();
51
+ // Keep the process alive — stop() runs in the SIGINT handler.
52
+ await new Promise(() => { });
53
+ }
54
+ catch (err) {
55
+ console.error(chalk.red(`✗ ${err.message}`));
56
+ process.exitCode = 1;
57
+ }
58
+ });
59
+ program
60
+ .command("doctor")
61
+ .description("Run environment checks. Exit 0 if all green, 1 otherwise.")
62
+ .action(async () => {
63
+ const code = await doctorCommand();
64
+ process.exitCode = code;
65
+ });
66
+ program
67
+ .command("version")
68
+ .description("Print CLI + protocol versions.")
69
+ .action(() => {
70
+ console.log(`acc-runner ${pkg.version}`);
71
+ console.log(`protocol ${PROTOCOL_VERSION}`);
72
+ });
73
+ program.parseAsync(process.argv).catch((err) => {
74
+ console.error(chalk.red(`✗ ${err.message}`));
75
+ process.exit(1);
76
+ });
77
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface RunnerConfig {
2
+ publicUrl: string;
3
+ supabaseUrl: string;
4
+ supabaseAnonKey: string;
5
+ repoPath: string;
6
+ targetRepo: string;
7
+ integrationBranch: string;
8
+ }
9
+ export declare function loadConfig(): RunnerConfig;
10
+ /**
11
+ * Best-effort version of loadConfig() for commands that should still
12
+ * partially succeed without env (e.g. `version`, `--help`).
13
+ */
14
+ export declare function loadConfigOrNull(): RunnerConfig | null;
15
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAUD,wBAAgB,UAAU,IAAI,YAAY,CAazC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,YAAY,GAAG,IAAI,CAMtD"}
package/dist/config.js ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Resolved runtime config for the CLI. Reads from environment variables
3
+ * so the binary stays portable across machines without rebuilding.
4
+ *
5
+ * Required at runtime:
6
+ * ACC_PUBLIC_URL — e.g. https://acc.techarch.dev
7
+ * ACC_SUPABASE_URL — Supabase project URL (mirror of VITE_SUPABASE_URL)
8
+ * ACC_SUPABASE_ANON_KEY — Supabase anon key (used for the JS client)
9
+ *
10
+ * Optional:
11
+ * ACC_REPO_PATH — local clone of TechArch (defaults to ~/work/TechArch)
12
+ * ACC_TARGET_REPO — slug, defaults to tokenfactory-pvt-ltd/TechArch
13
+ * ACC_INTEGRATION_BRANCH — base branch for new PRs, defaults to acc/integration
14
+ */
15
+ import os from "node:os";
16
+ import path from "node:path";
17
+ function envRequired(name) {
18
+ const v = (process.env[name] ?? "").trim();
19
+ if (!v) {
20
+ throw new Error(`Missing required env var: ${name}`);
21
+ }
22
+ return v;
23
+ }
24
+ export function loadConfig() {
25
+ const repoPath = process.env.ACC_REPO_PATH?.trim() ||
26
+ path.resolve(os.homedir(), "work", "TechArch");
27
+ return {
28
+ publicUrl: envRequired("ACC_PUBLIC_URL"),
29
+ supabaseUrl: envRequired("ACC_SUPABASE_URL"),
30
+ supabaseAnonKey: envRequired("ACC_SUPABASE_ANON_KEY"),
31
+ repoPath,
32
+ targetRepo: process.env.ACC_TARGET_REPO?.trim() || "tokenfactory-pvt-ltd/TechArch",
33
+ integrationBranch: process.env.ACC_INTEGRATION_BRANCH?.trim() || "acc/integration",
34
+ };
35
+ }
36
+ /**
37
+ * Best-effort version of loadConfig() for commands that should still
38
+ * partially succeed without env (e.g. `version`, `--help`).
39
+ */
40
+ export function loadConfigOrNull() {
41
+ try {
42
+ return loadConfig();
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ }
48
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAW7B,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,QAAQ,GACZ,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE;QACjC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IACjD,OAAO;QACL,SAAS,EAAE,WAAW,CAAC,gBAAgB,CAAC;QACxC,WAAW,EAAE,WAAW,CAAC,kBAAkB,CAAC;QAC5C,eAAe,EAAE,WAAW,CAAC,uBAAuB,CAAC;QACrD,QAAQ;QACR,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,+BAA+B;QAClF,iBAAiB,EACf,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,IAAI,EAAE,IAAI,iBAAiB;KAClE,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC;QACH,OAAO,UAAU,EAAE,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ interface CheckOutcome {
2
+ name: string;
3
+ ok: boolean;
4
+ detail: string;
5
+ fix?: string;
6
+ }
7
+ export interface DoctorOptions {
8
+ /** Stub the checks for tests. */
9
+ checks?: Array<() => Promise<CheckOutcome>>;
10
+ }
11
+ export declare function doctorCommand(options?: DoctorOptions): Promise<number>;
12
+ export {};
13
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAaA,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AA6ND,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;CAC7C;AAQD,wBAAsB,aAAa,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CA+BhF"}
package/dist/doctor.js ADDED
@@ -0,0 +1,251 @@
1
+ /**
2
+ * `acc-runner doctor` — environment checks. Returns 0 if all green, 1 if
3
+ * any check failed. Each check carries a remediation hint so users can
4
+ * self-serve.
5
+ */
6
+ import { execa } from "execa";
7
+ import chalk from "chalk";
8
+ import { loadConfigOrNull } from "./config.js";
9
+ import { loadSession } from "./keychain.js";
10
+ import { createRunnerClient } from "./supabase.js";
11
+ import { checkVersion } from "./version-check.js";
12
+ import { PROTOCOL_VERSION } from "./types.js";
13
+ async function checkBinary(bin, args) {
14
+ try {
15
+ const { stdout } = await execa(bin, args, { env: process.env });
16
+ const first = stdout.split(/\r?\n/)[0]?.trim() ?? bin;
17
+ return { ok: true, detail: first };
18
+ }
19
+ catch (err) {
20
+ return { ok: false, detail: err.message.split("\n")[0] };
21
+ }
22
+ }
23
+ async function checkNode() {
24
+ const major = Number(process.versions.node.split(".")[0]);
25
+ return {
26
+ name: "node 20+",
27
+ ok: major >= 20,
28
+ detail: `node ${process.versions.node}`,
29
+ fix: "Install Node 20.6+ (https://nodejs.org).",
30
+ };
31
+ }
32
+ async function checkClaude() {
33
+ const r = await checkBinary("claude", ["--version"]);
34
+ return {
35
+ name: "claude CLI in PATH",
36
+ ok: r.ok,
37
+ detail: r.detail,
38
+ fix: "Install Claude Code (https://claude.com/claude-code) and re-run.",
39
+ };
40
+ }
41
+ async function checkGh() {
42
+ const ghOk = await checkBinary("gh", ["--version"]);
43
+ if (!ghOk.ok) {
44
+ return {
45
+ name: "gh CLI in PATH",
46
+ ok: false,
47
+ detail: ghOk.detail,
48
+ fix: "Install GitHub CLI (https://cli.github.com).",
49
+ };
50
+ }
51
+ try {
52
+ await execa("gh", ["auth", "status"], { env: process.env });
53
+ return { name: "gh CLI in PATH", ok: true, detail: ghOk.detail };
54
+ }
55
+ catch {
56
+ return {
57
+ name: "gh CLI in PATH",
58
+ ok: false,
59
+ detail: "gh installed but not authenticated",
60
+ fix: "Run `gh auth login`.",
61
+ };
62
+ }
63
+ }
64
+ async function checkGit() {
65
+ const r = await checkBinary("git", ["--version"]);
66
+ if (!r.ok) {
67
+ return {
68
+ name: "git installed",
69
+ ok: false,
70
+ detail: r.detail,
71
+ fix: "Install git (https://git-scm.com).",
72
+ };
73
+ }
74
+ // Soft-check that user.email is set; agents can't push commits without it.
75
+ try {
76
+ const { stdout } = await execa("git", ["config", "user.email"], { env: process.env });
77
+ if (!stdout.trim())
78
+ throw new Error("user.email empty");
79
+ return { name: "git installed and configured", ok: true, detail: r.detail };
80
+ }
81
+ catch {
82
+ return {
83
+ name: "git installed and configured",
84
+ ok: false,
85
+ detail: "git.user.email is not set",
86
+ fix: "Run `git config --global user.email <you@example.com>`.",
87
+ };
88
+ }
89
+ }
90
+ async function checkKeychain() {
91
+ try {
92
+ const keytar = (await import("keytar"));
93
+ const k = keytar.default ?? keytar;
94
+ await k.setPassword("acc-runner-doctor", "sentinel", "ok");
95
+ const v = await k.getPassword("acc-runner-doctor", "sentinel");
96
+ await k.deletePassword("acc-runner-doctor", "sentinel");
97
+ return {
98
+ name: "keychain read/write",
99
+ ok: v === "ok",
100
+ detail: v === "ok" ? "ok" : `unexpected: ${String(v)}`,
101
+ };
102
+ }
103
+ catch (err) {
104
+ return {
105
+ name: "keychain read/write",
106
+ ok: false,
107
+ detail: err.message.split("\n")[0],
108
+ fix: "On Linux: install libsecret. On macOS/Windows: ensure the keychain service is unlocked.",
109
+ };
110
+ }
111
+ }
112
+ async function checkServer(publicUrl) {
113
+ try {
114
+ const res = await fetch(`${publicUrl.replace(/\/+$/, "")}/api/health`, {
115
+ headers: { "User-Agent": `acc-runner/${PROTOCOL_VERSION}` },
116
+ });
117
+ if (!res.ok) {
118
+ return {
119
+ name: "/api/health reachable",
120
+ ok: false,
121
+ detail: `HTTP ${res.status}`,
122
+ fix: "Check ACC_PUBLIC_URL points to a deployment that is up.",
123
+ };
124
+ }
125
+ return { name: "/api/health reachable", ok: true, detail: "200 OK" };
126
+ }
127
+ catch (err) {
128
+ return {
129
+ name: "/api/health reachable",
130
+ ok: false,
131
+ detail: err.message.split("\n")[0],
132
+ fix: "Check ACC_PUBLIC_URL and your network connection.",
133
+ };
134
+ }
135
+ }
136
+ async function checkProtocolVersion(publicUrl) {
137
+ const r = await checkVersion(publicUrl);
138
+ if (r.ok) {
139
+ return {
140
+ name: "protocol version",
141
+ ok: true,
142
+ detail: `server min v${r.serverMin}, you have v${PROTOCOL_VERSION}`,
143
+ };
144
+ }
145
+ if (r.reason === "outdated") {
146
+ return {
147
+ name: "protocol version",
148
+ ok: false,
149
+ detail: `server min v${r.serverMin}, you have v${PROTOCOL_VERSION}`,
150
+ fix: "Run `pnpm add -g @tokenfactory/acc-runner@latest`.",
151
+ };
152
+ }
153
+ return {
154
+ name: "protocol version",
155
+ ok: false,
156
+ detail: r.detail ?? "unreachable",
157
+ fix: "Check ACC_PUBLIC_URL and connectivity.",
158
+ };
159
+ }
160
+ async function checkRegistration() {
161
+ const cfg = loadConfigOrNull();
162
+ if (!cfg) {
163
+ return {
164
+ name: "runner registered",
165
+ ok: false,
166
+ detail: "ACC_PUBLIC_URL / ACC_SUPABASE_URL / ACC_SUPABASE_ANON_KEY not set",
167
+ fix: "Populate the env vars in .env.example.",
168
+ };
169
+ }
170
+ const session = await loadSession();
171
+ if (!session) {
172
+ return {
173
+ name: "runner registered",
174
+ ok: false,
175
+ detail: "no session in keychain",
176
+ fix: "Run `acc-runner login`.",
177
+ };
178
+ }
179
+ try {
180
+ const supabase = createRunnerClient(cfg, session.jwt);
181
+ const { data, error } = await supabase
182
+ .from("runners")
183
+ .select("id,bound_user_id,status")
184
+ .eq("id", session.runner_id)
185
+ .maybeSingle();
186
+ if (error) {
187
+ return {
188
+ name: "runner registered",
189
+ ok: false,
190
+ detail: error.message,
191
+ fix: "Re-run `acc-runner login`.",
192
+ };
193
+ }
194
+ if (!data) {
195
+ return {
196
+ name: "runner registered",
197
+ ok: false,
198
+ detail: `runner row ${session.runner_id} not found`,
199
+ fix: "Re-run `acc-runner login`.",
200
+ };
201
+ }
202
+ if (data.bound_user_id !== session.user_id) {
203
+ return {
204
+ name: "runner registered",
205
+ ok: false,
206
+ detail: "runner bound to a different user",
207
+ fix: "Run `acc-runner logout` then `acc-runner login` again.",
208
+ };
209
+ }
210
+ return { name: "runner registered", ok: true, detail: `${session.runner_id} (status=${data.status})` };
211
+ }
212
+ catch (err) {
213
+ return {
214
+ name: "runner registered",
215
+ ok: false,
216
+ detail: err.message.split("\n")[0],
217
+ fix: "Re-run `acc-runner login`.",
218
+ };
219
+ }
220
+ }
221
+ function format(outcome) {
222
+ const tag = outcome.ok ? chalk.green("[OK ]") : chalk.red("[FAIL]");
223
+ const fix = !outcome.ok && outcome.fix ? chalk.gray(`\n → ${outcome.fix}`) : "";
224
+ return `${tag} ${outcome.name.padEnd(28, " ")} ${chalk.gray(outcome.detail)}${fix}`;
225
+ }
226
+ export async function doctorCommand(options = {}) {
227
+ const cfg = loadConfigOrNull();
228
+ const checks = options.checks ?? [
229
+ checkNode,
230
+ checkClaude,
231
+ checkGh,
232
+ checkGit,
233
+ checkKeychain,
234
+ ...(cfg ? [() => checkServer(cfg.publicUrl)] : []),
235
+ ...(cfg ? [() => checkProtocolVersion(cfg.publicUrl)] : []),
236
+ checkRegistration,
237
+ ];
238
+ let failed = 0;
239
+ for (const fn of checks) {
240
+ const outcome = await fn();
241
+ if (!outcome.ok)
242
+ failed++;
243
+ console.log(format(outcome));
244
+ }
245
+ if (!cfg && !options.checks) {
246
+ console.log(chalk.yellow("\n! ACC_PUBLIC_URL / ACC_SUPABASE_URL / ACC_SUPABASE_ANON_KEY are not set; server-side checks were skipped."));
247
+ failed += 1;
248
+ }
249
+ return failed === 0 ? 0 : 1;
250
+ }
251
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
package/dist/gh.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ export interface OpenPRArgs {
2
+ title: string;
3
+ body: string;
4
+ base: string;
5
+ head?: string;
6
+ /** Open as draft. Defaults to false (matches Track P2-C convention). */
7
+ draft?: boolean;
8
+ }
9
+ export interface GhRunner {
10
+ isAuthenticated(): Promise<boolean>;
11
+ openPR(repoPath: string, args: OpenPRArgs): Promise<{
12
+ url: string;
13
+ }>;
14
+ }
15
+ export declare const gh: GhRunner;
16
+ //# sourceMappingURL=gh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gh.d.ts","sourceRoot":"","sources":["../src/gh.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACtE;AAED,eAAO,MAAM,EAAE,EAAE,QA2BhB,CAAC"}
package/dist/gh.js ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * gh CLI wrapper. We rely on whatever auth `gh auth status` already has —
3
+ * never touching the user's credentials.
4
+ */
5
+ import { execa } from "execa";
6
+ export const gh = {
7
+ async isAuthenticated() {
8
+ try {
9
+ await execa("gh", ["auth", "status"], { env: process.env });
10
+ return true;
11
+ }
12
+ catch {
13
+ return false;
14
+ }
15
+ },
16
+ async openPR(repoPath, args) {
17
+ const argv = [
18
+ "pr",
19
+ "create",
20
+ "--title",
21
+ args.title,
22
+ "--body",
23
+ args.body,
24
+ "--base",
25
+ args.base,
26
+ ];
27
+ if (args.head)
28
+ argv.push("--head", args.head);
29
+ if (args.draft)
30
+ argv.push("--draft");
31
+ const { stdout } = await execa("gh", argv, { cwd: repoPath, env: process.env });
32
+ // gh prints the PR URL on the last line of stdout.
33
+ const url = stdout.trim().split(/\r?\n/).pop() ?? "";
34
+ return { url };
35
+ },
36
+ };
37
+ //# sourceMappingURL=gh.js.map
package/dist/gh.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gh.js","sourceRoot":"","sources":["../src/gh.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAgB9B,MAAM,CAAC,MAAM,EAAE,GAAa;IAC1B,KAAK,CAAC,eAAe;QACnB,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YAC5D,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI;QACzB,MAAM,IAAI,GAAG;YACX,IAAI;YACJ,QAAQ;YACR,SAAS;YACT,IAAI,CAAC,KAAK;YACV,QAAQ;YACR,IAAI,CAAC,IAAI;YACT,QAAQ;YACR,IAAI,CAAC,IAAI;SACV,CAAC;QACF,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAChF,mDAAmD;QACnD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QACrD,OAAO,EAAE,GAAG,EAAE,CAAC;IACjB,CAAC;CACF,CAAC"}
package/dist/git.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export interface GitRunner {
2
+ fetch(repoPath: string): Promise<void>;
3
+ checkout(repoPath: string, branch: string): Promise<void>;
4
+ push(repoPath: string, branch: string): Promise<void>;
5
+ /** True when the working tree has no uncommitted changes. */
6
+ isClean(repoPath: string): Promise<boolean>;
7
+ }
8
+ export declare const git: GitRunner;
9
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,6DAA6D;IAC7D,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7C;AAMD,eAAO,MAAM,GAAG,EAAE,SAejB,CAAC"}