@mycompbox/compbox-cli 1.13.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.
Files changed (98) hide show
  1. package/.tsbuildinfo +1 -0
  2. package/commands/configure.d.ts +24 -0
  3. package/commands/configure.d.ts.map +1 -0
  4. package/commands/configure.js +170 -0
  5. package/commands/configure.js.map +1 -0
  6. package/commands/doctor.d.ts +136 -0
  7. package/commands/doctor.d.ts.map +1 -0
  8. package/commands/doctor.js +606 -0
  9. package/commands/doctor.js.map +1 -0
  10. package/commands/install.d.ts +3 -0
  11. package/commands/install.d.ts.map +1 -0
  12. package/commands/install.js +88 -0
  13. package/commands/install.js.map +1 -0
  14. package/commands/list.d.ts +3 -0
  15. package/commands/list.d.ts.map +1 -0
  16. package/commands/list.js +141 -0
  17. package/commands/list.js.map +1 -0
  18. package/commands/login.d.ts +15 -0
  19. package/commands/login.d.ts.map +1 -0
  20. package/commands/login.js +102 -0
  21. package/commands/login.js.map +1 -0
  22. package/commands/publish.d.ts +3 -0
  23. package/commands/publish.d.ts.map +1 -0
  24. package/commands/publish.js +102 -0
  25. package/commands/publish.js.map +1 -0
  26. package/commands/run.d.ts +76 -0
  27. package/commands/run.d.ts.map +1 -0
  28. package/commands/run.js +417 -0
  29. package/commands/run.js.map +1 -0
  30. package/commands/service.d.ts +29 -0
  31. package/commands/service.d.ts.map +1 -0
  32. package/commands/service.js +142 -0
  33. package/commands/service.js.map +1 -0
  34. package/commands/update.d.ts +3 -0
  35. package/commands/update.d.ts.map +1 -0
  36. package/commands/update.js +141 -0
  37. package/commands/update.js.map +1 -0
  38. package/index.d.ts +3 -0
  39. package/index.d.ts.map +1 -0
  40. package/index.js +8508 -0
  41. package/index.js.map +1 -0
  42. package/package.json +30 -0
  43. package/utils/agent-invoker.d.ts +393 -0
  44. package/utils/agent-invoker.d.ts.map +1 -0
  45. package/utils/agent-invoker.js +1632 -0
  46. package/utils/agent-invoker.js.map +1 -0
  47. package/utils/api-client.d.ts +54 -0
  48. package/utils/api-client.d.ts.map +1 -0
  49. package/utils/api-client.js +214 -0
  50. package/utils/api-client.js.map +1 -0
  51. package/utils/auth-client.d.ts +61 -0
  52. package/utils/auth-client.d.ts.map +1 -0
  53. package/utils/auth-client.js +135 -0
  54. package/utils/auth-client.js.map +1 -0
  55. package/utils/claude-runtime.d.ts +116 -0
  56. package/utils/claude-runtime.d.ts.map +1 -0
  57. package/utils/claude-runtime.js +291 -0
  58. package/utils/claude-runtime.js.map +1 -0
  59. package/utils/config-store.d.ts +128 -0
  60. package/utils/config-store.d.ts.map +1 -0
  61. package/utils/config-store.js +137 -0
  62. package/utils/config-store.js.map +1 -0
  63. package/utils/file-manager.d.ts +32 -0
  64. package/utils/file-manager.d.ts.map +1 -0
  65. package/utils/file-manager.js +208 -0
  66. package/utils/file-manager.js.map +1 -0
  67. package/utils/keychain.d.ts +46 -0
  68. package/utils/keychain.d.ts.map +1 -0
  69. package/utils/keychain.js +167 -0
  70. package/utils/keychain.js.map +1 -0
  71. package/utils/loopback.d.ts +45 -0
  72. package/utils/loopback.d.ts.map +1 -0
  73. package/utils/loopback.js +95 -0
  74. package/utils/loopback.js.map +1 -0
  75. package/utils/mailbox-client.d.ts +98 -0
  76. package/utils/mailbox-client.d.ts.map +1 -0
  77. package/utils/mailbox-client.js +178 -0
  78. package/utils/mailbox-client.js.map +1 -0
  79. package/utils/mcp-config-writer.d.ts +133 -0
  80. package/utils/mcp-config-writer.d.ts.map +1 -0
  81. package/utils/mcp-config-writer.js +184 -0
  82. package/utils/mcp-config-writer.js.map +1 -0
  83. package/utils/pack-bundler.d.ts +30 -0
  84. package/utils/pack-bundler.d.ts.map +1 -0
  85. package/utils/pack-bundler.js +141 -0
  86. package/utils/pack-bundler.js.map +1 -0
  87. package/utils/prompt.d.ts +31 -0
  88. package/utils/prompt.d.ts.map +1 -0
  89. package/utils/prompt.js +86 -0
  90. package/utils/prompt.js.map +1 -0
  91. package/utils/table-formatter.d.ts +42 -0
  92. package/utils/table-formatter.d.ts.map +1 -0
  93. package/utils/table-formatter.js +125 -0
  94. package/utils/table-formatter.js.map +1 -0
  95. package/utils/version-resolver.d.ts +31 -0
  96. package/utils/version-resolver.d.ts.map +1 -0
  97. package/utils/version-resolver.js +75 -0
  98. package/utils/version-resolver.js.map +1 -0
@@ -0,0 +1,417 @@
1
+ /**
2
+ * `compbox run` — the Agent Runner daemon (ENG-E23 / ENG-122).
3
+ *
4
+ * Long-polls central for the next job assigned to this machine, claims it,
5
+ * and dispatches by type. This command IS the process a service supervisor
6
+ * (launchd / systemd via `brew services`, or a Windows Service) keeps alive —
7
+ * see the ENG-122 distribution decision (Homebrew tap + PowerShell installer,
8
+ * no hand-rolled installer).
9
+ *
10
+ * Scope note (ENG-122-1/2/4, honestly reflecting what's implemented): the
11
+ * poll/claim/dispatch/heartbeat/reconnect mechanics are complete. Real agent
12
+ * invocation is implemented for `job.type: epic_request` under BOTH
13
+ * `agentMode: api-key` (Anthropic Messages API directly) and
14
+ * `agentMode: claude-subscription` (shells out to the local `claude` CLI,
15
+ * using whichever account is logged in — personal Pro/Max or a Team seat) —
16
+ * see agent-invoker.ts. `start_execution` jobs still fall back to the honest
17
+ * "not implemented" completion below rather than faking anything — nobody
18
+ * is ever left staring at a silent "awaiting_input" forever; the browser's
19
+ * ENG-123-2 failure banner surfaces the reason.
20
+ */
21
+ import { Command } from 'commander';
22
+ import chalk from 'chalk';
23
+ import { readConfig, applyPxpipeEnv, resolveProjectDir, updateConfig, } from '../utils/config-store.js';
24
+ import { START_EXECUTION_KINDS } from '@mycompbox/shared';
25
+ import { retrieveSecret, MACHINE_TOKEN_ACCOUNT, AI_KEY_ACCOUNT, } from '../utils/keychain.js';
26
+ import { MailboxClient, MailboxClientError, } from '../utils/mailbox-client.js';
27
+ import { invokeEpicRequestViaApi, invokeEpicRequestViaSubscription, invokeStartExecutionPlan, invokeStartExecutionOrchestrate, } from '../utils/agent-invoker.js';
28
+ import { probeAgentRuntime, } from '../utils/claude-runtime.js';
29
+ // Long-poll wait requested per next-job call (the server clamps to its own max).
30
+ // Kept comfortably below the HTTP client timeout (see mailbox-client.ts): on
31
+ // Cloud Run the round-trip for a held connection intermittently added enough
32
+ // overhead that a 25s poll exceeded a 35s client timeout, so every idle poll
33
+ // errored and backed off (up to 30s) — leaving the daemon asleep when a job
34
+ // arrived, which read as a slow/stuck start. A shorter poll returns well within
35
+ // the (now wider) client timeout with margin to spare.
36
+ const POLL_WAIT_MS = 15_000;
37
+ /** Backoff schedule on transient errors (network/5xx): 1s, 2s, 4s, ... capped. */
38
+ const BACKOFF_BASE_MS = 1_000;
39
+ const BACKOFF_MAX_MS = 30_000;
40
+ /**
41
+ * Cadence for the explicit agent-runtime heartbeat (ENG-136). The runtime status
42
+ * rides ONLY on this POST (next-job is a GET and cannot carry it), so it is sent
43
+ * on its own clock — independent of the ~25s job-poll — every this-many ms.
44
+ */
45
+ const HEARTBEAT_INTERVAL_MS = 60_000;
46
+ /**
47
+ * Whether the agent-runtime heartbeat is due. Driven SOLELY by when the runtime
48
+ * status was last *sent* (`lastRuntimeSentMs`), never by next-job activity — this
49
+ * is the invariant whose violation (gating on a timer that next-job reset every
50
+ * ~25s) previously starved the 60s heartbeat so the status was never transmitted
51
+ * and machines showed "agent runtime not found" despite being able to run jobs.
52
+ * `lastRuntimeSentMs === 0` (nothing sent yet) is always due.
53
+ */
54
+ export function runtimeHeartbeatDue(nowMs, lastRuntimeSentMs, intervalMs = HEARTBEAT_INTERVAL_MS) {
55
+ return nowMs - lastRuntimeSentMs >= intervalMs;
56
+ }
57
+ function sleep(ms) {
58
+ return new Promise((resolve) => setTimeout(resolve, ms));
59
+ }
60
+ function backoffDelay(consecutiveErrors) {
61
+ return Math.min(BACKOFF_MAX_MS, BACKOFF_BASE_MS * 2 ** (consecutiveErrors - 1));
62
+ }
63
+ /**
64
+ * Runs the agent-runtime probe (ENG-136), swallowing ANY error: a probe must
65
+ * never stop the daemon loop or block job dispatch. `probeAgentRuntime` is
66
+ * contractually non-rejecting, but we defend against it anyway — on a thrown
67
+ * error we log a gray warning and return `previous` (the last known-good probe,
68
+ * or `undefined` at startup) so the daemon keeps reporting the most recent
69
+ * status rather than dropping it.
70
+ *
71
+ * Extracted (and exported) as a pure-ish, dependency-injectable unit so the
72
+ * error-swallowing behavior is testable without spawning a real `claude`.
73
+ */
74
+ export async function safeProbeAgentRuntime(probe, previous, log = (m) => { console.warn(chalk.gray(m)); }) {
75
+ try {
76
+ return await probe();
77
+ }
78
+ catch (error) {
79
+ const message = error instanceof Error ? error.message : String(error);
80
+ log(` Agent runtime probe failed (continuing to poll): ${message}`);
81
+ return previous;
82
+ }
83
+ }
84
+ /**
85
+ * One idle-heartbeat cycle (ENG-136): refresh the cached runtime probe (errors
86
+ * swallowed by {@link safeProbeAgentRuntime}) and send an explicit heartbeat
87
+ * carrying the latest known runtime status. The heartbeat POST body is the SOLE
88
+ * ingestion channel for runtime status — next-job is a GET and cannot carry it
89
+ * (architect correction H3).
90
+ *
91
+ * Heartbeat failure is best-effort (swallowed) — the next successful next-job
92
+ * call heartbeats server-side anyway. Returns `{ runtime, sent }` so the caller
93
+ * updates its cache regardless, but only advances its heartbeat clock when the
94
+ * ping actually landed.
95
+ */
96
+ export async function runHeartbeatCycle(deps) {
97
+ const runtime = await safeProbeAgentRuntime(deps.probe, deps.previous, deps.log);
98
+ try {
99
+ await deps.client.heartbeat(deps.machineToken, runtime);
100
+ return { runtime, sent: true };
101
+ }
102
+ catch {
103
+ // Best-effort — the next successful next-job call will heartbeat anyway.
104
+ return { runtime, sent: false };
105
+ }
106
+ }
107
+ /**
108
+ * Parse a claimed job's `payload` into a {@link StartExecutionPayload}, or null
109
+ * if malformed. The mailbox delivers `payload` as `unknown` — already an object
110
+ * in the common case (the API deserializes the stored JSON string, matching how
111
+ * `parseSeedPayload` treats it), but tolerant of a raw JSON string too.
112
+ */
113
+ export function parseStartExecutionPayload(payload) {
114
+ let parsed = payload;
115
+ if (typeof payload === 'string') {
116
+ try {
117
+ parsed = JSON.parse(payload);
118
+ }
119
+ catch {
120
+ return null;
121
+ }
122
+ }
123
+ if (typeof parsed !== 'object' || parsed === null)
124
+ return null;
125
+ const p = parsed;
126
+ if (!START_EXECUTION_KINDS.includes(p.kind))
127
+ return null;
128
+ if (p.kind === 'plan' && typeof p.epicRequestId === 'string' && p.epicRequestId.length > 0) {
129
+ return { kind: 'plan', epicRequestId: p.epicRequestId };
130
+ }
131
+ if (p.kind === 'orchestrate' && typeof p.epicId === 'string' && p.epicId.length > 0) {
132
+ return { kind: 'orchestrate', epicId: p.epicId };
133
+ }
134
+ return null;
135
+ }
136
+ /**
137
+ * Dispatch a `start_execution` job (ENG-164 / ENG-165). Routes on the payload
138
+ * `kind`:
139
+ * - `plan` → run the local @planner headless against the Epic Request.
140
+ * - `orchestrate` → run the local @orchestrator headless against the epic
141
+ * (ENG-165), halt-and-reporting a HARD-gate needs-review
142
+ * outcome rather than hanging.
143
+ * A malformed payload or a job missing prerequisites also fails cleanly.
144
+ */
145
+ async function handleStartExecution(ctx, job) {
146
+ const payload = parseStartExecutionPayload(job.payload);
147
+ if (!payload) {
148
+ await completeWithFailure(ctx, job, 'The start_execution job payload was missing or malformed (expected {kind:"plan",epicRequestId} or {kind:"orchestrate",epicId}).');
149
+ return;
150
+ }
151
+ if (payload.kind === 'plan') {
152
+ const userApiToken = ctx.userApiToken;
153
+ if (!userApiToken) {
154
+ await completeWithFailure(ctx, job, 'This device is not paired with a user API token, so the planner cannot run or record its epic. Run `compbox configure` to re-pair.');
155
+ return;
156
+ }
157
+ console.log(chalk.gray(' Running the planner headless (start_execution / plan)...'));
158
+ await runInvokerAndComplete(ctx, job, () => invokeStartExecutionPlan({
159
+ mailboxClient: ctx.client,
160
+ machineToken: ctx.machineToken,
161
+ jobId: job.id,
162
+ apiBaseUrl: ctx.apiBaseUrl,
163
+ userApiToken,
164
+ epicRequestId: payload.epicRequestId,
165
+ projectDir: ctx.projectDir,
166
+ }, {
167
+ // H4: keep this machine online during the long planner run — the poll
168
+ // loop (its own heartbeat) is blocked for the whole job.
169
+ heartbeat: () => ctx.client.heartbeat(ctx.machineToken).catch(() => undefined),
170
+ }));
171
+ return;
172
+ }
173
+ // kind === 'orchestrate' (ENG-165): run the local @orchestrator headless
174
+ // against the existing epic, reusing ENG-164's repo resolution + spawn profile.
175
+ const userApiToken = ctx.userApiToken;
176
+ if (!userApiToken) {
177
+ await completeWithFailure(ctx, job, 'This device is not paired with a user API token, so the orchestrator cannot run. Run `compbox configure` to re-pair.');
178
+ return;
179
+ }
180
+ console.log(chalk.gray(' Running the orchestrator headless (start_execution / orchestrate)...'));
181
+ await runInvokerAndComplete(ctx, job, () => invokeStartExecutionOrchestrate({
182
+ mailboxClient: ctx.client,
183
+ machineToken: ctx.machineToken,
184
+ jobId: job.id,
185
+ epicId: payload.epicId,
186
+ projectDir: ctx.projectDir,
187
+ }, {
188
+ // H4: keep this machine online during the long orchestrator run — the
189
+ // poll loop (its own heartbeat) is blocked for the whole job.
190
+ heartbeat: () => ctx.client.heartbeat(ctx.machineToken).catch(() => undefined),
191
+ }));
192
+ }
193
+ /** Runs an agent invoker and closes out the job with its result, logging either way. */
194
+ async function runInvokerAndComplete(ctx, job, invoke) {
195
+ try {
196
+ const outcome = await invoke();
197
+ await ctx.client.completeJob(ctx.machineToken, job.id, outcome.status, outcome.result);
198
+ console.log(outcome.status === 'done'
199
+ ? chalk.green(` Job ${job.id} completed: ${JSON.stringify(outcome.result)}`)
200
+ : chalk.yellow(` Job ${job.id} failed: ${JSON.stringify(outcome.result)}`));
201
+ }
202
+ catch (error) {
203
+ const message = error instanceof MailboxClientError ? error.message : 'complete-job failed';
204
+ console.error(chalk.red(` Failed to close out job ${job.id}: ${message}`));
205
+ }
206
+ }
207
+ /** Completes a job as failed with an explanatory `error` result, logging either way. */
208
+ async function completeWithFailure(ctx, job, error) {
209
+ try {
210
+ await ctx.client.completeJob(ctx.machineToken, job.id, 'failed', { error });
211
+ console.log(chalk.gray(` Marked ${job.id} as failed with an explanatory result.`));
212
+ }
213
+ catch (closeError) {
214
+ const message = closeError instanceof MailboxClientError ? closeError.message : 'complete-job failed';
215
+ console.error(chalk.red(` Failed to close out job ${job.id}: ${message}`));
216
+ }
217
+ }
218
+ /**
219
+ * Handles a claimed job: dispatches to the real agent-invoker when the
220
+ * job/mode combination is implemented, otherwise completes it as failed with
221
+ * a clear, honest reason rather than leaving it claimed/running forever or
222
+ * faking an interview.
223
+ */
224
+ async function handleJob(ctx, job) {
225
+ console.log(chalk.cyan(`\n→ Claimed job ${job.id} (type: ${job.type}, status: ${job.status})`));
226
+ const userApiToken = ctx.userApiToken;
227
+ const isEpicRequest = job.type === 'epic_request' && !!userApiToken;
228
+ if (isEpicRequest && userApiToken) {
229
+ if (ctx.aiMode === 'api-key') {
230
+ const { value: anthropicApiKey } = await retrieveSecret(AI_KEY_ACCOUNT);
231
+ if (anthropicApiKey) {
232
+ console.log(chalk.gray(' Running the request-formulator interview (api mode)...'));
233
+ await runInvokerAndComplete(ctx, job, () => invokeEpicRequestViaApi(job, {
234
+ mailboxClient: ctx.client,
235
+ machineToken: ctx.machineToken,
236
+ apiBaseUrl: ctx.apiBaseUrl,
237
+ userApiToken,
238
+ anthropicApiKey,
239
+ }));
240
+ return;
241
+ }
242
+ }
243
+ else if (ctx.aiMode === 'claude-subscription') {
244
+ console.log(chalk.gray(' Running the request-formulator interview (claude-subscription mode, local `claude` CLI)...'));
245
+ await runInvokerAndComplete(ctx, job, () => invokeEpicRequestViaSubscription(job, {
246
+ mailboxClient: ctx.client,
247
+ machineToken: ctx.machineToken,
248
+ apiBaseUrl: ctx.apiBaseUrl,
249
+ userApiToken,
250
+ }));
251
+ return;
252
+ }
253
+ }
254
+ // start_execution (ENG-164): route on the payload `kind` (plan/orchestrate).
255
+ // This replaces the old catch-all not-implemented fallback for this job type.
256
+ if (job.type === 'start_execution') {
257
+ await handleStartExecution(ctx, job);
258
+ return;
259
+ }
260
+ console.log(chalk.yellow(` ${job.type}/${ctx.aiMode ?? 'unset'} is not implemented yet in this daemon build (ENG-122-2).`));
261
+ await completeWithFailure(ctx, job, `Agent invocation for job type "${job.type}" with agentMode "${ctx.aiMode ?? 'unset'}" ` +
262
+ "isn't implemented yet in this daemon build. This job was claimed but could not be run.");
263
+ }
264
+ export const runCommand = new Command('run')
265
+ .description('Start the Agent Runner daemon — long-polls central for jobs assigned to this machine')
266
+ .option('--once', 'Run a single poll cycle and exit (testing)')
267
+ .option('--wait-ms <ms>', `Long-poll wait per request (default ${String(POLL_WAIT_MS)})`)
268
+ .option('--project-dir <path>', 'CompBox project repo the planner runs in for start_execution jobs (persisted; also settable via COMPBOX_PROJECT_DIR)')
269
+ .action(async (options) => {
270
+ // ENG-164 (H2): a `--project-dir` flag both configures THIS run and is
271
+ // persisted so future runs (and the background service) inherit it — a real
272
+ // SET path, not merely a read path. Resolution order is applied below.
273
+ if (options.projectDir && options.projectDir.trim().length > 0) {
274
+ updateConfig({ projectDir: options.projectDir.trim() });
275
+ }
276
+ const config = readConfig();
277
+ // pxpipe (ENG-E26): promote the persisted enable flag so the daemon routes
278
+ // through pxpipe even as a background service (no shell env inherited).
279
+ applyPxpipeEnv(config);
280
+ if (!config.apiBaseUrl) {
281
+ console.error(chalk.red('\nNot configured. Run `compbox login` first.'));
282
+ process.exit(1);
283
+ return;
284
+ }
285
+ if (!config.machineId) {
286
+ console.error(chalk.red('\nThis device is not paired. Run `compbox configure` first — it pairs the device and mints a machine token.'));
287
+ process.exit(1);
288
+ return;
289
+ }
290
+ if (config.aiMode === 'claude-subscription' && config.agentModeAcknowledged !== true) {
291
+ console.error(chalk.red('\nClaude Code CLI subscription mode requires an entitlement acknowledgment. Run `compbox configure` to confirm it.'));
292
+ process.exit(1);
293
+ return;
294
+ }
295
+ const { value: machineToken } = await retrieveSecret(MACHINE_TOKEN_ACCOUNT);
296
+ if (!machineToken) {
297
+ console.error(chalk.red('\nMachine token not found on this device. Run `compbox configure` again to re-pair.'));
298
+ process.exit(1);
299
+ return;
300
+ }
301
+ const waitMs = options.waitMs ? Number.parseInt(options.waitMs, 10) : POLL_WAIT_MS;
302
+ const client = new MailboxClient(config.apiBaseUrl);
303
+ // ENG-164 (H2): resolve the project repo once (flag → env → persisted config).
304
+ const projectDir = resolveProjectDir({ flag: options.projectDir, config });
305
+ const jobContext = {
306
+ client,
307
+ machineToken,
308
+ apiBaseUrl: config.apiBaseUrl,
309
+ aiMode: config.aiMode,
310
+ userApiToken: config.apiToken,
311
+ projectDir,
312
+ };
313
+ console.log(chalk.bold('\nCompBox Agent Runner\n'));
314
+ console.log(chalk.gray(` Central: ${config.apiBaseUrl}`));
315
+ console.log(chalk.gray(` Machine: ${config.machineName ?? config.machineId}`));
316
+ console.log(chalk.gray(` AI mode: ${config.aiMode ?? 'unset'}`));
317
+ console.log(chalk.gray(` Project: ${projectDir ?? '(unset — start_execution/plan jobs will fail until set)'}`));
318
+ console.log(chalk.gray(` Polling for jobs (long-poll, ~${String(Math.round(waitMs / 1000))}s per request)...\n`));
319
+ // Agent-runtime probe (ENG-136): probe the local `claude` runtime ONCE at
320
+ // startup and cache it; it is refreshed on the heartbeat cadence below and
321
+ // rides along in each explicit heartbeat POST so central can surface
322
+ // whether this machine can actually run subscription-mode jobs. Reuses
323
+ // ENG-135's bounded, always-kill, never-rejecting probe.
324
+ const runtimeProbe = () => probeAgentRuntime();
325
+ let agentRuntime = await safeProbeAgentRuntime(runtimeProbe, undefined);
326
+ if (agentRuntime) {
327
+ console.log(chalk.gray(` Agent runtime: ${agentRuntime.status} (${agentRuntime.detail})\n`));
328
+ }
329
+ // The agent-runtime status rides ONLY on the explicit heartbeat POST body
330
+ // (next-job is a GET and cannot carry it — ENG-136 H3). Send it ONCE at
331
+ // startup so the machine's readiness appears within seconds, and track its
332
+ // OWN cadence clock (`lastRuntimeSentAt`) below — one that next-job must NOT
333
+ // reset. Otherwise the ~25s job-poll perpetually resets the timer and the
334
+ // 60s runtime heartbeat never fires: the probed status is computed but never
335
+ // transmitted, central stays `unknown`, and the web shows "agent runtime not
336
+ // found" for a machine that can actually run jobs. (Regression fix.)
337
+ let lastRuntimeSentAt = 0;
338
+ if (agentRuntime) {
339
+ try {
340
+ await client.heartbeat(machineToken, agentRuntime);
341
+ lastRuntimeSentAt = Date.now();
342
+ }
343
+ catch {
344
+ // Best-effort — the loop below re-sends on its own cadence.
345
+ }
346
+ }
347
+ let running = true;
348
+ // Registering a SIGINT/SIGTERM handler disables Node's default
349
+ // terminate-on-signal behavior — the process becomes OUR responsibility
350
+ // to exit. Without a real process.exit() here, Ctrl+C appears to do
351
+ // nothing: `running` flips false, but the loop is typically blocked
352
+ // inside the in-flight long-poll (up to ~waitMs) and even once that
353
+ // resolves, lingering handles (axios's keep-alive connection pool) can
354
+ // keep the event loop alive indefinitely. Verified live: without this,
355
+ // Ctrl+C did not stop the daemon. A hard exit is the right tradeoff for
356
+ // a manual test/dev daemon — it may abandon an in-progress job's final
357
+ // completion call, which is acceptable here but would need a graceful
358
+ // drain (abort the in-flight request, let the current job finish) for
359
+ // a production-hardened version.
360
+ const shutdown = (signal) => {
361
+ if (!running)
362
+ return;
363
+ running = false;
364
+ console.log(chalk.gray(`\nReceived ${signal}, shutting down...`));
365
+ process.exit(0);
366
+ };
367
+ process.on('SIGINT', () => { shutdown('SIGINT'); });
368
+ process.on('SIGTERM', () => { shutdown('SIGTERM'); });
369
+ let consecutiveErrors = 0;
370
+ do {
371
+ let job = null;
372
+ try {
373
+ job = await client.nextJob(machineToken, waitMs);
374
+ consecutiveErrors = 0;
375
+ // next-job refreshes lastSeenAt server-side (machine-auth); the runtime
376
+ // status is sent separately below on its OWN cadence (do not couple it
377
+ // to next-job, or the runtime heartbeat is starved — see startup note).
378
+ }
379
+ catch (error) {
380
+ consecutiveErrors += 1;
381
+ const message = error instanceof MailboxClientError ? error.message : 'next-job request failed';
382
+ const delay = backoffDelay(consecutiveErrors);
383
+ console.error(chalk.red(`\n✖ next-job failed (attempt ${String(consecutiveErrors)}): ${message}`));
384
+ console.error(chalk.gray(` Reconnecting in ${String(Math.round(delay / 1000))}s...`));
385
+ if (options.once)
386
+ break;
387
+ await sleep(delay);
388
+ continue;
389
+ }
390
+ if (job) {
391
+ await handleJob(jobContext, job);
392
+ }
393
+ // Agent-runtime heartbeat (ENG-136): refresh the cached probe and re-send
394
+ // the status on its OWN cadence, independent of next-job. `lastRuntimeSentAt`
395
+ // is advanced ONLY when a runtime heartbeat is actually sent (never by
396
+ // next-job), so this fires every HEARTBEAT_INTERVAL_MS even while the ~25s
397
+ // job-poll runs continuously. The heartbeat POST body is the sole ingestion
398
+ // channel for runtime status (next-job is a GET and cannot carry it).
399
+ if (runtimeHeartbeatDue(Date.now(), lastRuntimeSentAt)) {
400
+ const cycle = await runHeartbeatCycle({
401
+ client,
402
+ machineToken,
403
+ probe: runtimeProbe,
404
+ previous: agentRuntime,
405
+ });
406
+ agentRuntime = cycle.runtime;
407
+ if (cycle.sent) {
408
+ lastRuntimeSentAt = Date.now();
409
+ }
410
+ }
411
+ if (options.once)
412
+ break;
413
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- `running` is mutated asynchronously by the SIGINT/SIGTERM handlers above; ESLint's control-flow analysis can't see that.
414
+ } while (running);
415
+ console.log(chalk.gray('Agent Runner stopped.'));
416
+ });
417
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * `compbox service install|uninstall|start|stop` — Windows Service adapter
3
+ * (ENG-122-3), the ONE platform without a Homebrew equivalent.
4
+ *
5
+ * On macOS/Linux, `brew services start compbox` handles this for us (see the
6
+ * ENG-122 distribution decision) — this command intentionally does nothing
7
+ * there and tells the user to use `brew services` instead.
8
+ *
9
+ * Implementation: wraps the built-in `sc.exe` (Service Control Manager CLI,
10
+ * present on every Windows install — no extra native dependency). This is a
11
+ * reasonable first pass, not a fully SCM-compliant service: a plain Node
12
+ * process registered this way runs under the SCM and restarts with the
13
+ * machine (`start= auto`), but does not itself handle SERVICE_CONTROL codes
14
+ * (pause/continue, custom stop reasons, etc.) the way a proper service host
15
+ * would. `compbox run`'s existing SIGINT/SIGTERM handling covers ordinary
16
+ * stop/restart. A more robust future upgrade would wrap the process with
17
+ * NSSM or the `node-windows` library for full SCM compliance — deferred.
18
+ *
19
+ * Validated on Windows via CI (ENG-167, GitHub `windows-latest`, run
20
+ * 29947646845): `service install` registers CompBoxAgentRunner with
21
+ * START_TYPE=AUTO_START and a correctly-quoted binPath (node exe + script each
22
+ * quoted, so install paths with spaces are safe), and `uninstall` removes it.
23
+ * NOT yet proven: the daemon *staying* RUNNING (needs a login/configure'd
24
+ * machine — without config `compbox run` exits immediately) and a literal
25
+ * reboot (CI runners are ephemeral; AUTO_START is the proxy for boot-persistence).
26
+ */
27
+ import { Command } from 'commander';
28
+ export declare const serviceCommand: Command;
29
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/commands/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,eAAO,MAAM,cAAc,SAE1B,CAAC"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * `compbox service install|uninstall|start|stop` — Windows Service adapter
3
+ * (ENG-122-3), the ONE platform without a Homebrew equivalent.
4
+ *
5
+ * On macOS/Linux, `brew services start compbox` handles this for us (see the
6
+ * ENG-122 distribution decision) — this command intentionally does nothing
7
+ * there and tells the user to use `brew services` instead.
8
+ *
9
+ * Implementation: wraps the built-in `sc.exe` (Service Control Manager CLI,
10
+ * present on every Windows install — no extra native dependency). This is a
11
+ * reasonable first pass, not a fully SCM-compliant service: a plain Node
12
+ * process registered this way runs under the SCM and restarts with the
13
+ * machine (`start= auto`), but does not itself handle SERVICE_CONTROL codes
14
+ * (pause/continue, custom stop reasons, etc.) the way a proper service host
15
+ * would. `compbox run`'s existing SIGINT/SIGTERM handling covers ordinary
16
+ * stop/restart. A more robust future upgrade would wrap the process with
17
+ * NSSM or the `node-windows` library for full SCM compliance — deferred.
18
+ *
19
+ * Validated on Windows via CI (ENG-167, GitHub `windows-latest`, run
20
+ * 29947646845): `service install` registers CompBoxAgentRunner with
21
+ * START_TYPE=AUTO_START and a correctly-quoted binPath (node exe + script each
22
+ * quoted, so install paths with spaces are safe), and `uninstall` removes it.
23
+ * NOT yet proven: the daemon *staying* RUNNING (needs a login/configure'd
24
+ * machine — without config `compbox run` exits immediately) and a literal
25
+ * reboot (CI runners are ephemeral; AUTO_START is the proxy for boot-persistence).
26
+ */
27
+ import { Command } from 'commander';
28
+ import chalk from 'chalk';
29
+ import { execFile } from 'node:child_process';
30
+ import { promisify } from 'node:util';
31
+ const execFileAsync = promisify(execFile);
32
+ const SERVICE_NAME = 'CompBoxAgentRunner';
33
+ const SERVICE_DISPLAY_NAME = 'CompBox Agent Runner';
34
+ function requireWindows() {
35
+ if (process.platform !== 'win32') {
36
+ console.error(chalk.red(`\n'compbox service' is Windows-only. On macOS/Linux, use Homebrew instead:\n` +
37
+ ` brew services start compbox\n` +
38
+ ` brew services stop compbox`));
39
+ return false;
40
+ }
41
+ return true;
42
+ }
43
+ async function runSc(args) {
44
+ return execFileAsync('sc.exe', args);
45
+ }
46
+ export const serviceCommand = new Command('service').description('Manage the Agent Runner as a Windows Service (macOS/Linux: use `brew services` instead)');
47
+ serviceCommand
48
+ .command('install')
49
+ .description('Register the Agent Runner as an always-on Windows Service (auto-start on boot)')
50
+ .action(async () => {
51
+ if (!requireWindows()) {
52
+ process.exit(1);
53
+ return;
54
+ }
55
+ const nodeExe = process.execPath;
56
+ const scriptPath = process.argv[1] ?? '';
57
+ const binPath = `"${nodeExe}" "${scriptPath}" run`;
58
+ try {
59
+ // sc.exe requires each `option=` and its value as SEPARATE argv tokens
60
+ // (`binPath=` then the value, `start=` then `auto`), NOT one mashed token
61
+ // like `binPath= <value>` or `start= auto`. Passed via execFile (no shell),
62
+ // a mashed token makes sc.exe reject the whole command. Node quotes the
63
+ // space-containing binPath value automatically on the Windows command line.
64
+ await runSc([
65
+ 'create',
66
+ SERVICE_NAME,
67
+ 'binPath=', binPath,
68
+ 'start=', 'auto',
69
+ 'DisplayName=', SERVICE_DISPLAY_NAME,
70
+ ]);
71
+ console.log(chalk.green(`\n✔ Service "${SERVICE_DISPLAY_NAME}" registered (starts automatically on boot).`));
72
+ console.log(chalk.gray(` Start it now with: compbox service start`));
73
+ }
74
+ catch (error) {
75
+ const message = error instanceof Error ? error.message : 'sc.exe create failed';
76
+ const stderr = error.stderr?.trim();
77
+ console.error(chalk.red(`\nFailed to install the service: ${message}`));
78
+ if (stderr)
79
+ console.error(chalk.red(` sc.exe: ${stderr}`));
80
+ console.error(chalk.gray(' If this is a permissions error, run the terminal as Administrator.'));
81
+ process.exit(1);
82
+ }
83
+ });
84
+ serviceCommand
85
+ .command('uninstall')
86
+ .description('Stop and remove the Windows Service')
87
+ .action(async () => {
88
+ if (!requireWindows()) {
89
+ process.exit(1);
90
+ return;
91
+ }
92
+ try {
93
+ await runSc(['stop', SERVICE_NAME]).catch(() => {
94
+ // Already stopped — not an error.
95
+ });
96
+ await runSc(['delete', SERVICE_NAME]);
97
+ console.log(chalk.green(`\n✔ Service "${SERVICE_DISPLAY_NAME}" removed.`));
98
+ }
99
+ catch (error) {
100
+ const message = error instanceof Error ? error.message : 'sc.exe delete failed';
101
+ console.error(chalk.red(`\nFailed to remove the service: ${message}`));
102
+ console.error(chalk.gray(' Try running this terminal as Administrator.'));
103
+ process.exit(1);
104
+ }
105
+ });
106
+ serviceCommand
107
+ .command('start')
108
+ .description('Start the registered Windows Service')
109
+ .action(async () => {
110
+ if (!requireWindows()) {
111
+ process.exit(1);
112
+ return;
113
+ }
114
+ try {
115
+ await runSc(['start', SERVICE_NAME]);
116
+ console.log(chalk.green(`\n✔ Service "${SERVICE_DISPLAY_NAME}" started.`));
117
+ }
118
+ catch (error) {
119
+ const message = error instanceof Error ? error.message : 'sc.exe start failed';
120
+ console.error(chalk.red(`\nFailed to start the service: ${message}`));
121
+ process.exit(1);
122
+ }
123
+ });
124
+ serviceCommand
125
+ .command('stop')
126
+ .description('Stop the running Windows Service')
127
+ .action(async () => {
128
+ if (!requireWindows()) {
129
+ process.exit(1);
130
+ return;
131
+ }
132
+ try {
133
+ await runSc(['stop', SERVICE_NAME]);
134
+ console.log(chalk.green(`\n✔ Service "${SERVICE_DISPLAY_NAME}" stopped.`));
135
+ }
136
+ catch (error) {
137
+ const message = error instanceof Error ? error.message : 'sc.exe stop failed';
138
+ console.error(chalk.red(`\nFailed to stop the service: ${message}`));
139
+ process.exit(1);
140
+ }
141
+ });
142
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/commands/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const updateCommand: Command;
3
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,eAAO,MAAM,aAAa,SAmKtB,CAAC"}