@claudexor/cli 1.0.1

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 (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +22 -0
  3. package/dist/args.d.ts +12 -0
  4. package/dist/args.d.ts.map +1 -0
  5. package/dist/args.js +88 -0
  6. package/dist/args.js.map +1 -0
  7. package/dist/attachment-resolver.d.ts +11 -0
  8. package/dist/attachment-resolver.d.ts.map +1 -0
  9. package/dist/attachment-resolver.js +61 -0
  10. package/dist/attachment-resolver.js.map +1 -0
  11. package/dist/capabilities.d.ts +13 -0
  12. package/dist/capabilities.d.ts.map +1 -0
  13. package/dist/capabilities.js +90 -0
  14. package/dist/capabilities.js.map +1 -0
  15. package/dist/claudexord.d.ts +3 -0
  16. package/dist/claudexord.d.ts.map +1 -0
  17. package/dist/claudexord.js +564 -0
  18. package/dist/claudexord.js.map +1 -0
  19. package/dist/cli-io.d.ts +28 -0
  20. package/dist/cli-io.d.ts.map +1 -0
  21. package/dist/cli-io.js +37 -0
  22. package/dist/cli-io.js.map +1 -0
  23. package/dist/cli.d.ts +3 -0
  24. package/dist/cli.d.ts.map +1 -0
  25. package/dist/cli.js +1459 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/command-registry.d.ts +105 -0
  28. package/dist/command-registry.d.ts.map +1 -0
  29. package/dist/command-registry.js +516 -0
  30. package/dist/command-registry.js.map +1 -0
  31. package/dist/daemon-lifecycle.d.ts +18 -0
  32. package/dist/daemon-lifecycle.d.ts.map +1 -0
  33. package/dist/daemon-lifecycle.js +62 -0
  34. package/dist/daemon-lifecycle.js.map +1 -0
  35. package/dist/daemon-run.d.ts +86 -0
  36. package/dist/daemon-run.d.ts.map +1 -0
  37. package/dist/daemon-run.js +269 -0
  38. package/dist/daemon-run.js.map +1 -0
  39. package/dist/decision.d.ts +18 -0
  40. package/dist/decision.d.ts.map +1 -0
  41. package/dist/decision.js +46 -0
  42. package/dist/decision.js.map +1 -0
  43. package/dist/live.d.ts +26 -0
  44. package/dist/live.d.ts.map +1 -0
  45. package/dist/live.js +311 -0
  46. package/dist/live.js.map +1 -0
  47. package/dist/mcp-runner.d.ts +41 -0
  48. package/dist/mcp-runner.d.ts.map +1 -0
  49. package/dist/mcp-runner.js +306 -0
  50. package/dist/mcp-runner.js.map +1 -0
  51. package/dist/ops-commands.d.ts +11 -0
  52. package/dist/ops-commands.d.ts.map +1 -0
  53. package/dist/ops-commands.js +358 -0
  54. package/dist/ops-commands.js.map +1 -0
  55. package/dist/orchestrate-options.d.ts +9 -0
  56. package/dist/orchestrate-options.d.ts.map +1 -0
  57. package/dist/orchestrate-options.js +16 -0
  58. package/dist/orchestrate-options.js.map +1 -0
  59. package/dist/orphan-reaper.d.ts +9 -0
  60. package/dist/orphan-reaper.d.ts.map +1 -0
  61. package/dist/orphan-reaper.js +97 -0
  62. package/dist/orphan-reaper.js.map +1 -0
  63. package/dist/orphan-sweeper.d.ts +7 -0
  64. package/dist/orphan-sweeper.d.ts.map +1 -0
  65. package/dist/orphan-sweeper.js +289 -0
  66. package/dist/orphan-sweeper.js.map +1 -0
  67. package/dist/plugins.d.ts +44 -0
  68. package/dist/plugins.d.ts.map +1 -0
  69. package/dist/plugins.js +1383 -0
  70. package/dist/plugins.js.map +1 -0
  71. package/dist/primary-output.d.ts +14 -0
  72. package/dist/primary-output.d.ts.map +1 -0
  73. package/dist/primary-output.js +34 -0
  74. package/dist/primary-output.js.map +1 -0
  75. package/dist/registry.d.ts +26 -0
  76. package/dist/registry.d.ts.map +1 -0
  77. package/dist/registry.js +71 -0
  78. package/dist/registry.js.map +1 -0
  79. package/dist/release.d.ts +14 -0
  80. package/dist/release.d.ts.map +1 -0
  81. package/dist/release.js +49 -0
  82. package/dist/release.js.map +1 -0
  83. package/dist/repl.d.ts +26 -0
  84. package/dist/repl.d.ts.map +1 -0
  85. package/dist/repl.js +277 -0
  86. package/dist/repl.js.map +1 -0
  87. package/dist/review-command.d.ts +3 -0
  88. package/dist/review-command.d.ts.map +1 -0
  89. package/dist/review-command.js +83 -0
  90. package/dist/review-command.js.map +1 -0
  91. package/dist/reviewer-options.d.ts +18 -0
  92. package/dist/reviewer-options.d.ts.map +1 -0
  93. package/dist/reviewer-options.js +110 -0
  94. package/dist/reviewer-options.js.map +1 -0
  95. package/dist/run-options.d.ts +8 -0
  96. package/dist/run-options.d.ts.map +1 -0
  97. package/dist/run-options.js +50 -0
  98. package/dist/run-options.js.map +1 -0
  99. package/dist/run-secret-scan.d.ts +2 -0
  100. package/dist/run-secret-scan.d.ts.map +1 -0
  101. package/dist/run-secret-scan.js +5 -0
  102. package/dist/run-secret-scan.js.map +1 -0
  103. package/dist/settings-command.d.ts +3 -0
  104. package/dist/settings-command.d.ts.map +1 -0
  105. package/dist/settings-command.js +202 -0
  106. package/dist/settings-command.js.map +1 -0
  107. package/dist/settings-display.d.ts +3 -0
  108. package/dist/settings-display.d.ts.map +1 -0
  109. package/dist/settings-display.js +33 -0
  110. package/dist/settings-display.js.map +1 -0
  111. package/dist/settings-service.d.ts +15 -0
  112. package/dist/settings-service.d.ts.map +1 -0
  113. package/dist/settings-service.js +91 -0
  114. package/dist/settings-service.js.map +1 -0
  115. package/dist/setup-jobs.d.ts +28 -0
  116. package/dist/setup-jobs.d.ts.map +1 -0
  117. package/dist/setup-jobs.js +477 -0
  118. package/dist/setup-jobs.js.map +1 -0
  119. package/dist/spec.d.ts +84 -0
  120. package/dist/spec.d.ts.map +1 -0
  121. package/dist/spec.js +438 -0
  122. package/dist/spec.js.map +1 -0
  123. package/dist/trust-command.d.ts +3 -0
  124. package/dist/trust-command.d.ts.map +1 -0
  125. package/dist/trust-command.js +80 -0
  126. package/dist/trust-command.js.map +1 -0
  127. package/dist/trust-services.d.ts +7 -0
  128. package/dist/trust-services.d.ts.map +1 -0
  129. package/dist/trust-services.js +35 -0
  130. package/dist/trust-services.js.map +1 -0
  131. package/package.json +59 -0
@@ -0,0 +1,86 @@
1
+ import { type DaemonClient as DaemonClientType } from "@claudexor/daemon";
2
+ import { type ControlApiAddress } from "./live.js";
3
+ /**
4
+ * Ensure a daemon (and its control API) is running and return a connected
5
+ * client + control-api address. Connects to the existing socket; if unreachable,
6
+ * AUTO-STARTS claudexord as a detached process and waits (bounded) for both the
7
+ * socket and the control-api.json pointer to come up. FAILS LOUDLY if the daemon
8
+ * cannot be started — never silently falls back to an in-process run (the apply
9
+ * gate refuses a run no daemon tracks, so an in-process run is un-unblockable).
10
+ */
11
+ export declare function ensureDaemon(timeoutMs?: number): Promise<{
12
+ client: DaemonClientType;
13
+ addr: ControlApiAddress;
14
+ }>;
15
+ /**
16
+ * Connect to an ALREADY-RUNNING daemon + control API WITHOUT ever spawning one.
17
+ * Returns null when no token exists, the socket is unreachable, or the control
18
+ * API is down. Used by read-only-looking run lookups (inspect/apply) so a typo'd
19
+ * run id reports "no such run" instead of silently launching a background daemon
20
+ * (`ensureDaemon`, by contrast, auto-starts and is reserved for paths that act —
21
+ * enqueue/decision).
22
+ */
23
+ export declare function connectDaemonIfRunning(): Promise<{
24
+ client: DaemonClientType;
25
+ addr: ControlApiAddress;
26
+ } | null>;
27
+ /**
28
+ * Poll until the daemon (socket + control API) is fully ready, or the timeout
29
+ * elapses. Lets `claudexor daemon start` return only once a subsequent `status`
30
+ * is guaranteed to succeed (no start/status race).
31
+ */
32
+ export declare function waitForDaemonReady(timeoutMs?: number): Promise<{
33
+ client: DaemonClientType;
34
+ addr: ControlApiAddress;
35
+ } | null>;
36
+ export interface DaemonRunOutcome {
37
+ runId: string;
38
+ runDir: string;
39
+ /** The daemon job state (honest terminal: succeeded | blocked | failed | no_op | ...). */
40
+ status: string;
41
+ jobId: string;
42
+ error?: string;
43
+ }
44
+ /**
45
+ * Enqueue a run via the control API and wait until the daemon binds its
46
+ * runId/runDir, then (optionally) wait for it to reach a terminal state.
47
+ * The run lives under the DAEMON dir, not project-local: apply/decision/inspect
48
+ * resolve it via the daemon/registry, and a blocked run is unblockable through
49
+ * `claudexor decision`.
50
+ */
51
+ export declare function enqueueAndAwait(client: DaemonClientType, addr: ControlApiAddress, body: Record<string, unknown>, opts?: {
52
+ waitForTerminal: boolean;
53
+ startTimeoutMs?: number;
54
+ /** Invoked each terminal-wait iteration once the run is bound (MCP uses
55
+ * this to bridge pendingInteractions -> host elicitation). Awaited: a
56
+ * long answer round-trip pauses status polling, never the run itself. */
57
+ onPollTick?: (info: {
58
+ runId: string;
59
+ }) => void | Promise<void>;
60
+ }): Promise<DaemonRunOutcome>;
61
+ /** Daemon job state -> CLI exit code (success terminals are 0; everything else 1). */
62
+ export declare function exitCodeForState(state: string): number;
63
+ /**
64
+ * The run's derived apply-gate verdict from GET /runs/:id (single producer:
65
+ * the delivery gate via the control API). Soft-fails to null — a detail
66
+ * hiccup must never eat a finished run's result. Shared by the CLI post-run
67
+ * hints and the MCP structured results so both surfaces tell the same truth.
68
+ */
69
+ export declare function fetchApplyEligibility(addr: ControlApiAddress, runId: string): Promise<{
70
+ eligible: boolean;
71
+ state: string | null;
72
+ reason: string | null;
73
+ requiredAction: string | null;
74
+ } | null>;
75
+ /**
76
+ * Machine-readable reason for a non-success DAEMON terminal (P2). `blocked` is a
77
+ * needs-human terminal that carries no `error`, so surface the actionable decision
78
+ * hint (mirrors text mode); other non-success terminals use the error or a state
79
+ * label. Success terminals return undefined (no `summary` key emitted).
80
+ */
81
+ export declare function daemonOutcomeSummary(out: {
82
+ runId: string;
83
+ status: string;
84
+ error?: string;
85
+ }): string | undefined;
86
+ //# sourceMappingURL=daemon-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-run.d.ts","sourceRoot":"","sources":["../src/daemon-run.ts"],"names":[],"mappings":"AAIA,OAAO,EAML,KAAK,YAAY,IAAI,gBAAgB,EACtC,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AA0BtE;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,SAAS,SAAS,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,CAAC,CAkDrH;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,GAAG,IAAI,CAAC,CAQpH;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,SAAS,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,GAAG,IAAI,CAAC,CAQlI;AAgBD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,iBAAiB,EACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,GAAE;IACJ,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;6EAEyE;IACzE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAsF3B;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAAC,CAanH;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAO/G"}
@@ -0,0 +1,269 @@
1
+ import process from "node:process";
2
+ import { spawn } from "node:child_process";
3
+ import { existsSync } from "node:fs";
4
+ import { fileURLToPath } from "node:url";
5
+ import { DaemonClient, daemonDir, defaultSocketPath, ensureToken, readToken, } from "@claudexor/daemon";
6
+ import { harnessRuntimeEnv } from "@claudexor/core";
7
+ import { controlApiAddress } from "./live.js";
8
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
9
+ /** Is something accepting on the daemon socket right now? (cheap reachability probe). */
10
+ async function daemonReachable(client) {
11
+ try {
12
+ await client.health();
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ /** Is the daemon's control-api up and answering /healthz right now? */
20
+ async function controlApiReachable() {
21
+ try {
22
+ const addr = controlApiAddress();
23
+ const res = await fetch(`${addr.baseUrl}/healthz`, { signal: AbortSignal.timeout(1500) });
24
+ return res.ok ? addr : null;
25
+ }
26
+ catch {
27
+ return null;
28
+ }
29
+ }
30
+ /**
31
+ * Ensure a daemon (and its control API) is running and return a connected
32
+ * client + control-api address. Connects to the existing socket; if unreachable,
33
+ * AUTO-STARTS claudexord as a detached process and waits (bounded) for both the
34
+ * socket and the control-api.json pointer to come up. FAILS LOUDLY if the daemon
35
+ * cannot be started — never silently falls back to an in-process run (the apply
36
+ * gate refuses a run no daemon tracks, so an in-process run is un-unblockable).
37
+ */
38
+ export async function ensureDaemon(timeoutMs = 30_000) {
39
+ const token = ensureToken();
40
+ const socketPath = defaultSocketPath();
41
+ let client = new DaemonClient(socketPath, token);
42
+ const ok = await daemonReachable(client);
43
+ if (!ok) {
44
+ // Auto-start the daemon entry (the same one `claudexor daemon start` spawns).
45
+ const daemonScript = fileURLToPath(new URL("./claudexord.js", import.meta.url));
46
+ if (!existsSync(daemonScript)) {
47
+ throw new Error(`cannot auto-start the daemon: entry not found at ${daemonScript} (run \`pnpm build\`)`);
48
+ }
49
+ const child = spawn(process.execPath, [daemonScript], { detached: true, stdio: "ignore", env: harnessRuntimeEnv() });
50
+ child.unref();
51
+ // Wait for the socket to accept connections (health round-trip).
52
+ const deadline = Date.now() + timeoutMs;
53
+ let started = false;
54
+ while (Date.now() < deadline) {
55
+ await sleep(150);
56
+ // Re-read the token: ensureToken() above generated it before spawn, and the
57
+ // daemon reuses the same per-user token file, so this client stays valid.
58
+ client = new DaemonClient(socketPath, token);
59
+ if (await daemonReachable(client)) {
60
+ started = true;
61
+ break;
62
+ }
63
+ }
64
+ if (!started) {
65
+ throw new Error(`daemon did not come up within ${Math.round(timeoutMs / 1000)}s after auto-start (socket ${socketPath}); check \`claudexor daemon logs\``);
66
+ }
67
+ }
68
+ // The control API (HTTP/SSE viewport over the daemon) is what streams events
69
+ // and resolves the run for apply/decision. Wait for its pointer to be written.
70
+ let addr = await controlApiReachable();
71
+ if (!addr) {
72
+ const deadline = Date.now() + 10_000;
73
+ while (Date.now() < deadline && !addr) {
74
+ await sleep(150);
75
+ addr = await controlApiReachable();
76
+ }
77
+ }
78
+ if (!addr) {
79
+ throw new Error(`daemon is up but its control API is not reachable (no ${daemonDir()}/control-api.json); it may be disabled by CLAUDEXOR_NO_CONTROL_API=1`);
80
+ }
81
+ return { client, addr };
82
+ }
83
+ /**
84
+ * Connect to an ALREADY-RUNNING daemon + control API WITHOUT ever spawning one.
85
+ * Returns null when no token exists, the socket is unreachable, or the control
86
+ * API is down. Used by read-only-looking run lookups (inspect/apply) so a typo'd
87
+ * run id reports "no such run" instead of silently launching a background daemon
88
+ * (`ensureDaemon`, by contrast, auto-starts and is reserved for paths that act —
89
+ * enqueue/decision).
90
+ */
91
+ export async function connectDaemonIfRunning() {
92
+ const token = readToken();
93
+ if (!token)
94
+ return null;
95
+ const client = new DaemonClient(defaultSocketPath(), token);
96
+ if (!(await daemonReachable(client)))
97
+ return null;
98
+ const addr = await controlApiReachable();
99
+ if (!addr)
100
+ return null;
101
+ return { client, addr };
102
+ }
103
+ /**
104
+ * Poll until the daemon (socket + control API) is fully ready, or the timeout
105
+ * elapses. Lets `claudexor daemon start` return only once a subsequent `status`
106
+ * is guaranteed to succeed (no start/status race).
107
+ */
108
+ export async function waitForDaemonReady(timeoutMs = 15_000) {
109
+ const deadline = Date.now() + timeoutMs;
110
+ for (;;) {
111
+ const conn = await connectDaemonIfRunning();
112
+ if (conn)
113
+ return conn;
114
+ if (Date.now() >= deadline)
115
+ return null;
116
+ await sleep(150);
117
+ }
118
+ }
119
+ const TERMINAL_STATES = new Set([
120
+ "succeeded",
121
+ "no_op",
122
+ "ungated",
123
+ "review_not_run",
124
+ "blocked",
125
+ "failed",
126
+ "cancelled",
127
+ "interrupted",
128
+ "exhausted",
129
+ "not_converged",
130
+ "stuck_no_progress",
131
+ ]);
132
+ /**
133
+ * Enqueue a run via the control API and wait until the daemon binds its
134
+ * runId/runDir, then (optionally) wait for it to reach a terminal state.
135
+ * The run lives under the DAEMON dir, not project-local: apply/decision/inspect
136
+ * resolve it via the daemon/registry, and a blocked run is unblockable through
137
+ * `claudexor decision`.
138
+ */
139
+ export async function enqueueAndAwait(client, addr, body, opts = { waitForTerminal: true }) {
140
+ const startRes = await fetch(`${addr.baseUrl}/runs`, {
141
+ method: "POST",
142
+ headers: { Authorization: `Bearer ${addr.token}`, "content-type": "application/json" },
143
+ body: JSON.stringify(body),
144
+ });
145
+ const startText = await startRes.text();
146
+ const start = startText ? JSON.parse(startText) : {};
147
+ if (!startRes.ok) {
148
+ throw new Error(typeof start["error"] === "string" ? start["error"] : `run enqueue failed (HTTP ${startRes.status})`);
149
+ }
150
+ const jobId = String(start["jobId"] ?? "");
151
+ let runId = typeof start["runId"] === "string" ? start["runId"] : "";
152
+ let runDir = typeof start["runDir"] === "string" ? start["runDir"] : "";
153
+ // Ctrl-C while the CLI waits on a daemon run must CANCEL THE RUN, not just
154
+ // kill the waiting CLI (which would leave the daemon mutating the tree with
155
+ // nobody watching — the orphan the audit called out). First signal posts the
156
+ // typed cancel and keeps waiting for the honest terminal; a second signal
157
+ // force-quits the CLI (the daemon still owns the cancel).
158
+ let sigCount = 0;
159
+ const onSignal = () => {
160
+ sigCount += 1;
161
+ if (sigCount >= 2)
162
+ process.exit(130);
163
+ process.stderr.write("\ncancelling daemon run (Ctrl-C again to detach)...\n");
164
+ void fetch(`${addr.baseUrl}/runs/${encodeURIComponent(jobId)}/control`, {
165
+ method: "POST",
166
+ headers: { Authorization: `Bearer ${addr.token}`, "content-type": "application/json" },
167
+ body: JSON.stringify({ control: { kind: "cancel", reason: "ctrl-c on the waiting CLI" } }),
168
+ }).then(async (res) => {
169
+ if (!res.ok) {
170
+ process.stderr.write(`cancel request failed: HTTP ${res.status} ${(await res.text()).slice(0, 200)}\n`);
171
+ }
172
+ }).catch((err) => {
173
+ process.stderr.write(`cancel request failed: ${err instanceof Error ? err.message : String(err)}\n`);
174
+ });
175
+ };
176
+ process.on("SIGINT", onSignal);
177
+ process.on("SIGTERM", onSignal);
178
+ const removeSignalHandlers = () => {
179
+ process.removeListener("SIGINT", onSignal);
180
+ process.removeListener("SIGTERM", onSignal);
181
+ };
182
+ try {
183
+ // A 202 (queued) response carries only the jobId; poll the daemon socket
184
+ // until the run binds its id/dir (single canonical state source).
185
+ const startDeadline = Date.now() + (opts.startTimeoutMs ?? 30_000);
186
+ while ((!runId || !runDir) && Date.now() < startDeadline) {
187
+ if (!jobId)
188
+ break;
189
+ const rec = await client.status(jobId);
190
+ if (rec.runId && rec.runDir) {
191
+ runId = rec.runId;
192
+ runDir = rec.runDir;
193
+ break;
194
+ }
195
+ if (TERMINAL_STATES.has(rec.state) && !rec.runDir) {
196
+ // Terminal with no runDir = the run never materialized (e.g. validation
197
+ // failure pre-run-dir). Surface it honestly.
198
+ return { runId: rec.runId ?? "", runDir: "", status: rec.state, jobId, error: rec.error };
199
+ }
200
+ await sleep(120);
201
+ }
202
+ if (!runId || !runDir) {
203
+ throw new Error(`run did not start within the timeout (jobId ${jobId})`);
204
+ }
205
+ if (!opts.waitForTerminal) {
206
+ // The caller keeps watching this run (text mode streams it); hand the
207
+ // signal responsibility back with the outcome.
208
+ const rec = jobId ? await client.status(jobId) : null;
209
+ return { runId, runDir, status: rec?.state ?? "running", jobId };
210
+ }
211
+ // Poll the daemon socket for the terminal job state (the canonical outcome).
212
+ for (;;) {
213
+ const rec = await client.status(jobId);
214
+ if (TERMINAL_STATES.has(rec.state)) {
215
+ return { runId: rec.runId ?? runId, runDir: rec.runDir ?? runDir, status: rec.state, jobId, error: rec.error };
216
+ }
217
+ if (opts.onPollTick)
218
+ await opts.onPollTick({ runId: rec.runId ?? runId });
219
+ await sleep(250);
220
+ }
221
+ }
222
+ finally {
223
+ removeSignalHandlers();
224
+ }
225
+ }
226
+ /** Daemon job state -> CLI exit code (success terminals are 0; everything else 1). */
227
+ export function exitCodeForState(state) {
228
+ return state === "succeeded" || state === "no_op" || state === "ungated" || state === "review_not_run" ? 0 : 1;
229
+ }
230
+ /**
231
+ * The run's derived apply-gate verdict from GET /runs/:id (single producer:
232
+ * the delivery gate via the control API). Soft-fails to null — a detail
233
+ * hiccup must never eat a finished run's result. Shared by the CLI post-run
234
+ * hints and the MCP structured results so both surfaces tell the same truth.
235
+ */
236
+ export async function fetchApplyEligibility(addr, runId) {
237
+ if (!runId)
238
+ return null;
239
+ try {
240
+ const res = await fetch(`${addr.baseUrl}/runs/${encodeURIComponent(runId)}`, {
241
+ headers: { authorization: `Bearer ${addr.token}` },
242
+ });
243
+ if (!res.ok)
244
+ return null;
245
+ const detail = (await res.json());
246
+ const v = detail["applyEligibility"];
247
+ return v && typeof v === "object" ? v : null;
248
+ }
249
+ catch {
250
+ return null;
251
+ }
252
+ }
253
+ /**
254
+ * Machine-readable reason for a non-success DAEMON terminal (P2). `blocked` is a
255
+ * needs-human terminal that carries no `error`, so surface the actionable decision
256
+ * hint (mirrors text mode); other non-success terminals use the error or a state
257
+ * label. Success terminals return undefined (no `summary` key emitted).
258
+ */
259
+ export function daemonOutcomeSummary(out) {
260
+ if (out.error)
261
+ return out.error;
262
+ if (exitCodeForState(out.status) === 0)
263
+ return undefined;
264
+ if (out.status === "blocked") {
265
+ return `run blocked: needs a human decision — claudexor decision ${out.runId} --accept-risk | --rerun --feedback "..."`;
266
+ }
267
+ return `run ${out.status}`;
268
+ }
269
+ //# sourceMappingURL=daemon-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-run.js","sourceRoot":"","sources":["../src/daemon-run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { type ParsedArgs } from "./args.js";
2
+ export type DecisionResolution = {
3
+ ok: true;
4
+ action: string;
5
+ body: Record<string, unknown>;
6
+ } | {
7
+ ok: false;
8
+ message: string;
9
+ };
10
+ /**
11
+ * Pure mapping of `claudexor decision` flags to a typed RunDecisionAction
12
+ * request body. Exactly one action flag is required; rerun needs --feedback;
13
+ * accept-clean-patch may carry a validated --apply-mode. Returns an honest
14
+ * error message instead of a body when the flags are invalid (the command
15
+ * surfaces it on stderr and exits 2).
16
+ */
17
+ export declare function resolveDecisionBody(args: ParsedArgs): DecisionResolution;
18
+ //# sourceMappingURL=decision.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision.d.ts","sourceRoot":"","sources":["../src/decision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAa/D,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC3D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnC;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,kBAAkB,CA2BxE"}
@@ -0,0 +1,46 @@
1
+ import { flagBool, flagStr } from "./args.js";
2
+ /** The five typed RunDecisionAction values, mapped from their CLI action flags. */
3
+ const ACTION_FLAGS = [
4
+ { flag: "accept-risk", action: "accept_risk" },
5
+ { flag: "override", action: "override_needs_human" },
6
+ { flag: "revert", action: "revert_run" },
7
+ { flag: "accept-clean-patch", action: "accept_clean_patch" },
8
+ { flag: "rerun", action: "rerun_with_feedback" },
9
+ ];
10
+ const APPLY_MODES = ["artifact_only", "apply", "branch", "commit", "pr"];
11
+ /**
12
+ * Pure mapping of `claudexor decision` flags to a typed RunDecisionAction
13
+ * request body. Exactly one action flag is required; rerun needs --feedback;
14
+ * accept-clean-patch may carry a validated --apply-mode. Returns an honest
15
+ * error message instead of a body when the flags are invalid (the command
16
+ * surfaces it on stderr and exits 2).
17
+ */
18
+ export function resolveDecisionBody(args) {
19
+ const chosen = ACTION_FLAGS.filter((f) => flagBool(args, f.flag));
20
+ if (chosen.length === 0) {
21
+ return { ok: false, message: "one action is required (--accept-risk | --override | --revert | --accept-clean-patch | --rerun)" };
22
+ }
23
+ if (chosen.length > 1) {
24
+ return { ok: false, message: `only one action at a time (got ${chosen.map((c) => `--${c.flag}`).join(", ")})` };
25
+ }
26
+ const action = chosen[0].action;
27
+ const body = { action };
28
+ if (action === "rerun_with_feedback") {
29
+ const feedback = flagStr(args, "feedback");
30
+ if (!feedback || !feedback.trim()) {
31
+ return { ok: false, message: '--rerun requires --feedback "<text>"' };
32
+ }
33
+ body["feedback"] = feedback;
34
+ }
35
+ if (action === "accept_clean_patch") {
36
+ const applyMode = flagStr(args, "apply-mode");
37
+ if (applyMode !== undefined) {
38
+ if (!APPLY_MODES.includes(applyMode)) {
39
+ return { ok: false, message: `invalid --apply-mode '${applyMode}' (expected apply|branch|commit|pr|artifact_only)` };
40
+ }
41
+ body["applyMode"] = applyMode;
42
+ }
43
+ }
44
+ return { ok: true, action, body };
45
+ }
46
+ //# sourceMappingURL=decision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision.js","sourceRoot":"","sources":["../src/decision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAmB,MAAM,WAAW,CAAC;AAE/D,mFAAmF;AACnF,MAAM,YAAY,GAAuC;IACvD,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE;IAC9C,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,sBAAsB,EAAE;IACpD,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE;IACxC,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,oBAAoB,EAAE;IAC5D,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE;CACjD,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,eAAe,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;AAMzE;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAgB;IAClD,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAClE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,iGAAiG,EAAE,CAAC;IACnI,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,kCAAkC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IAClH,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC;IACjC,MAAM,IAAI,GAA4B,EAAE,MAAM,EAAE,CAAC;IACjD,IAAI,MAAM,KAAK,qBAAqB,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC3C,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;YAClC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,sCAAsC,EAAE,CAAC;QACxE,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC;IAC9B,CAAC;IACD,IAAI,MAAM,KAAK,oBAAoB,EAAE,CAAC;QACpC,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAC9C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBACrC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,yBAAyB,SAAS,mDAAmD,EAAE,CAAC;YACvH,CAAC;YACD,IAAI,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC;QAChC,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACpC,CAAC"}
package/dist/live.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import type { InteractionAnswerSet, InteractionQuestion } from "@claudexor/schema";
2
+ /**
3
+ * One concise line per run event for live terminal progress. Returns null for
4
+ * noise (heartbeats, raw harness deltas we do not surface in a TTY).
5
+ */
6
+ export declare function formatRunEventLine(ev: Record<string, unknown>): string | null;
7
+ /**
8
+ * Prompt the questions on the controlling TTY. Returns null on a non-TTY
9
+ * stdin or when the deadline passes (the engine then declines benignly).
10
+ */
11
+ export declare function promptQuestionsOnTty(interactionId: string, questions: InteractionQuestion[], timeoutAt?: string): Promise<InteractionAnswerSet | null>;
12
+ export interface ControlApiAddress {
13
+ baseUrl: string;
14
+ token: string;
15
+ }
16
+ export declare function controlApiAddress(): ControlApiAddress;
17
+ /**
18
+ * `claudexor follow <run_id>`: live SSE tail of a daemon-backed run with full
19
+ * replay (persisted seq), bounded reconnects via Last-Event-ID, and
20
+ * interactive TTY answering of harness questions. Exit honesty: a
21
+ * stream that ends WITHOUT a terminal event is a LOSS (exit 1, "stream
22
+ * lost"), never a silent success — success requires an observed terminal or
23
+ * an `end` frame the server sent after one.
24
+ */
25
+ export declare function followRun(runId: string, json: boolean): Promise<number>;
26
+ //# sourceMappingURL=live.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAQnF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAoD7E;AAMD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,mBAAmB,EAAE,EAChC,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAoDtC;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,iBAAiB,IAAI,iBAAiB,CAKrD;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAkG7E"}