@rallycry/conveyor-agent 8.13.0 → 9.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.
package/dist/cli.js CHANGED
@@ -1,27 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- ProjectRunner,
4
3
  SessionRunner,
5
4
  applyBootstrapToEnv,
6
5
  buildSessionPreviewPorts,
6
+ createServiceLogger,
7
7
  fetchBootstrap,
8
8
  loadConveyorConfig,
9
9
  loadForwardPorts,
10
10
  runSetupCommand,
11
11
  runStartCommand
12
- } from "./chunk-L7Q2JZJX.js";
13
- import "./chunk-FDWECEDJ.js";
14
- import {
15
- createServiceLogger
16
- } from "./chunk-TN2YYT2V.js";
12
+ } from "./chunk-JH7GUOGW.js";
17
13
 
18
14
  // src/cli.ts
19
15
  import { readFileSync } from "fs";
20
- import { join, dirname } from "path";
16
+ import { join, dirname as dirname2 } from "path";
21
17
  import { fileURLToPath } from "url";
22
18
 
23
19
  // src/setup/sidecars.ts
24
20
  import net from "net";
21
+ import { mkdir, writeFile } from "fs/promises";
22
+ import { dirname } from "path";
25
23
  var POSTGRES_TIMEOUT_MS = 3e4;
26
24
  var FIREBASE_TIMEOUT_MS = 6e4;
27
25
  var FALLBACK_TIMEOUT_MS = 3e4;
@@ -29,6 +27,18 @@ var DEFAULT_POLL_INTERVAL_MS = 1e3;
29
27
  var DEFAULT_PROBE_TIMEOUT_MS = 2e3;
30
28
  var POSTGRES_DEFAULT_PORT = 5432;
31
29
  var FIREBASE_DEFAULT_PORT = 9099;
30
+ async function startLazySidecars(env, onLog) {
31
+ const markerPath = env.CONVEYOR_SIDECAR_START_FILE;
32
+ if (!markerPath) return;
33
+ try {
34
+ await mkdir(dirname(markerPath), { recursive: true });
35
+ await writeFile(markerPath, "start\n", "utf8");
36
+ onLog("Started lazy sidecars");
37
+ } catch (err) {
38
+ const message = err instanceof Error ? err.message : String(err);
39
+ onLog(`WARNING: failed to start lazy sidecars: ${message}`);
40
+ }
41
+ }
32
42
  function parseHostPort(value, defaultPort) {
33
43
  const trimmed = value.trim().replace(/^[a-z]+:\/\//i, "");
34
44
  if (!trimmed) return null;
@@ -114,6 +124,7 @@ async function waitForSidecars(opts = {}) {
114
124
  pollIntervalMs = DEFAULT_POLL_INTERVAL_MS,
115
125
  probe = defaultProbe
116
126
  } = opts;
127
+ await startLazySidecars(env, onLog);
117
128
  const targets = resolveSidecarTargets(env);
118
129
  if (targets.length === 0) return;
119
130
  await Promise.all(
@@ -149,7 +160,7 @@ async function checkSessionTaskIdentity(params) {
149
160
 
150
161
  // src/cli.ts
151
162
  if (process.argv.includes("--version")) {
152
- const __dirname = dirname(fileURLToPath(import.meta.url));
163
+ const __dirname = dirname2(fileURLToPath(import.meta.url));
153
164
  const pkgPath = join(__dirname, "..", "package.json");
154
165
  const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
155
166
  process.stdout.write(pkg.version + "\n");
@@ -184,17 +195,10 @@ async function bootstrapFromCodespace(apiUrl, instanceName) {
184
195
  process.exit(1);
185
196
  }
186
197
  applyBootstrapToEnv(result.config);
187
- if (result.config.mode === "project") {
188
- logger.info("Bootstrap complete (project mode)", {
189
- projectId: result.config.projectId,
190
- attempts: result.attempts
191
- });
192
- } else {
193
- logger.info("Bootstrap complete", {
194
- taskId: result.config.taskId,
195
- attempts: result.attempts
196
- });
197
- }
198
+ logger.info("Bootstrap complete", {
199
+ taskId: result.config.taskId,
200
+ attempts: result.attempts
201
+ });
198
202
  }
199
203
  function isExpectedAbortError(error) {
200
204
  const message = error.message || "";
@@ -223,7 +227,7 @@ process.on("unhandledRejection", (reason) => {
223
227
  var DEFAULT_CONVEYOR_API_URL = "https://api.conveyor.rallycryapp.com";
224
228
  var conveyorApiUrl = process.env.CONVEYOR_API_URL || DEFAULT_CONVEYOR_API_URL;
225
229
  var INSTANCE_NAME = process.env.CODESPACE_NAME || process.env.CLAUDESPACE_NAME;
226
- if (INSTANCE_NAME && !process.env.CONVEYOR_TASK_TOKEN && !process.env.CONVEYOR_PROJECT_TOKEN) {
230
+ if (INSTANCE_NAME && !process.env.CONVEYOR_TASK_TOKEN) {
227
231
  if (!conveyorApiUrl) {
228
232
  logger.error("Could not resolve CONVEYOR_API_URL for codespace bootstrap");
229
233
  process.exit(1);
@@ -231,207 +235,158 @@ if (INSTANCE_NAME && !process.env.CONVEYOR_TASK_TOKEN && !process.env.CONVEYOR_P
231
235
  await bootstrapFromCodespace(conveyorApiUrl, INSTANCE_NAME);
232
236
  conveyorApiUrl = process.env.CONVEYOR_API_URL ?? conveyorApiUrl;
233
237
  }
234
- var CONVEYOR_PROJECT_TOKEN = process.env.CONVEYOR_PROJECT_TOKEN;
235
- var CONVEYOR_PROJECT_ID = process.env.CONVEYOR_PROJECT_ID;
236
- if (CONVEYOR_PROJECT_TOKEN && CONVEYOR_PROJECT_ID) {
237
- const CONVEYOR_PROJECT_DIR = process.env.CONVEYOR_WORKSPACE ?? process.cwd();
238
- if (!conveyorApiUrl) {
239
- logger.error("Could not resolve CONVEYOR_API_URL for project runner mode");
240
- process.exit(1);
241
- }
242
- logger.info("Starting project runner", { projectId: CONVEYOR_PROJECT_ID });
243
- const runner = new ProjectRunner({
244
- conveyorApiUrl,
245
- projectToken: CONVEYOR_PROJECT_TOKEN,
246
- projectId: CONVEYOR_PROJECT_ID,
247
- projectDir: CONVEYOR_PROJECT_DIR
248
- });
249
- process.on("SIGTERM", () => {
250
- logger.info("Received SIGTERM, stopping project runner");
251
- void runner.stop();
252
- setTimeout(() => {
253
- logger.warn("Forcing exit after SIGTERM timeout");
254
- process.exit(1);
255
- }, 4e4).unref();
256
- });
257
- process.on("SIGINT", () => {
258
- logger.info("Received SIGINT, stopping project runner");
259
- void runner.stop();
260
- setTimeout(() => {
261
- logger.warn("Forcing exit after SIGINT timeout");
262
- process.exit(1);
263
- }, 4e4).unref();
264
- });
265
- runner.start().then(() => {
266
- process.exit(0);
267
- }).catch((error) => {
268
- const msg = error instanceof Error ? error.message : String(error);
269
- logger.error("Project runner failed", { error: msg });
270
- process.exit(1);
238
+ var CONVEYOR_TASK_TOKEN = process.env.CONVEYOR_TASK_TOKEN;
239
+ var CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;
240
+ var CONVEYOR_WORKSPACE = process.env.CONVEYOR_WORKSPACE ?? process.cwd();
241
+ var CONVEYOR_MODE = process.env.CONVEYOR_MODE ?? "task";
242
+ var CONVEYOR_AGENT_MODE = process.env.CONVEYOR_AGENT_MODE || void 0;
243
+ var CONVEYOR_IS_AUTO = CONVEYOR_AGENT_MODE ? CONVEYOR_AGENT_MODE === "auto" : process.env.CONVEYOR_IS_AUTO === "true";
244
+ if (!CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {
245
+ logger.error("Missing required environment variables");
246
+ logger.error(" CONVEYOR_TASK_TOKEN - JWT token for task authentication");
247
+ logger.error(" CONVEYOR_TASK_ID - ID of the task to execute");
248
+ logger.error("");
249
+ logger.error("CONVEYOR_API_URL is provided via codespace secret or bootstrap.");
250
+ logger.error("");
251
+ logger.error("Optional:");
252
+ logger.error(" CONVEYOR_MODE - Runner mode: 'task' (default) or 'pm'");
253
+ logger.error(" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)");
254
+ process.exit(1);
255
+ }
256
+ if (CONVEYOR_MODE !== "task" && CONVEYOR_MODE !== "pm" && CONVEYOR_MODE !== "code-review") {
257
+ logger.error("Invalid CONVEYOR_MODE", {
258
+ mode: CONVEYOR_MODE,
259
+ expected: ["task", "pm", "code-review"]
271
260
  });
272
- } else {
273
- const CONVEYOR_TASK_TOKEN = process.env.CONVEYOR_TASK_TOKEN;
274
- const CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;
275
- const CONVEYOR_WORKSPACE = process.env.CONVEYOR_WORKSPACE ?? process.cwd();
276
- const CONVEYOR_MODE = process.env.CONVEYOR_MODE ?? "task";
277
- const CONVEYOR_AGENT_MODE = process.env.CONVEYOR_AGENT_MODE || void 0;
278
- const CONVEYOR_IS_AUTO = CONVEYOR_AGENT_MODE ? CONVEYOR_AGENT_MODE === "auto" : process.env.CONVEYOR_IS_AUTO === "true";
279
- if (!CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {
280
- logger.error("Missing required environment variables");
281
- logger.error(" CONVEYOR_TASK_TOKEN - JWT token for task authentication");
282
- logger.error(" CONVEYOR_TASK_ID - ID of the task to execute");
283
- logger.error("");
284
- logger.error("CONVEYOR_API_URL is provided via codespace secret or bootstrap.");
285
- logger.error("");
286
- logger.error("Optional:");
287
- logger.error(" CONVEYOR_MODE - Runner mode: 'task' (default) or 'pm'");
288
- logger.error(" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)");
289
- process.exit(1);
290
- }
291
- if (CONVEYOR_MODE !== "task" && CONVEYOR_MODE !== "pm" && CONVEYOR_MODE !== "code-review") {
292
- logger.error("Invalid CONVEYOR_MODE", {
293
- mode: CONVEYOR_MODE,
294
- expected: ["task", "pm", "code-review"]
295
- });
296
- process.exit(1);
297
- }
298
- logger.info("Starting agent", { mode: CONVEYOR_MODE });
299
- const lifecycleOverrides = process.env.CLAUDESPACE_NAME ? { idleTimeoutMs: 60 * 60 * 1e3 } : { gitFlushIntervalMs: 0 };
300
- const runner = new SessionRunner(
301
- {
302
- connection: {
303
- apiUrl: conveyorApiUrl ?? "",
304
- taskToken: CONVEYOR_TASK_TOKEN,
305
- // CONVEYOR_SESSION_ID is the CodespaceSession ID for BaseService ACL.
306
- // Falls back to CONVEYOR_TASK_ID for backward compat (codespace bootstrap sets only task ID).
307
- sessionId: process.env.CONVEYOR_SESSION_ID ?? CONVEYOR_TASK_ID,
308
- runnerMode: CONVEYOR_MODE
309
- },
310
- runnerMode: CONVEYOR_MODE,
311
- isAuto: CONVEYOR_IS_AUTO,
312
- workspaceDir: CONVEYOR_WORKSPACE,
313
- agentMode: CONVEYOR_AGENT_MODE,
314
- lifecycle: lifecycleOverrides
261
+ process.exit(1);
262
+ }
263
+ logger.info("Starting agent", { mode: CONVEYOR_MODE });
264
+ var lifecycleOverrides = process.env.CLAUDESPACE_NAME ? { idleTimeoutMs: 60 * 60 * 1e3 } : { gitFlushIntervalMs: 0 };
265
+ var runner = new SessionRunner(
266
+ {
267
+ connection: {
268
+ apiUrl: conveyorApiUrl ?? "",
269
+ taskToken: CONVEYOR_TASK_TOKEN,
270
+ // CONVEYOR_SESSION_ID is the CodespaceSession ID for BaseService ACL.
271
+ // Falls back to CONVEYOR_TASK_ID for backward compat (codespace bootstrap sets only task ID).
272
+ sessionId: process.env.CONVEYOR_SESSION_ID ?? CONVEYOR_TASK_ID,
273
+ runnerMode: CONVEYOR_MODE
315
274
  },
316
- {
317
- onStatusChange: (status) => {
318
- logger.info("Status changed", { status });
319
- },
320
- onEvent: (event) => {
321
- const detail = event.message ?? event.content ?? event.summary ?? "";
322
- if (detail) {
323
- logger.info(detail, { eventType: event.type });
324
- }
275
+ runnerMode: CONVEYOR_MODE,
276
+ isAuto: CONVEYOR_IS_AUTO,
277
+ workspaceDir: CONVEYOR_WORKSPACE,
278
+ agentMode: CONVEYOR_AGENT_MODE,
279
+ lifecycle: lifecycleOverrides
280
+ },
281
+ {
282
+ onStatusChange: (status) => {
283
+ logger.info("Status changed", { status });
284
+ },
285
+ onEvent: (event) => {
286
+ const detail = event.message ?? event.content ?? event.summary ?? "";
287
+ if (detail) {
288
+ logger.info(detail, { eventType: event.type });
325
289
  }
326
290
  }
327
- );
328
- const skipShutdownFlush = process.env.CONVEYOR_SKIP_SHUTDOWN_GIT_FLUSH === "true";
329
- const shutdownAgent = (signal) => {
330
- if (skipShutdownFlush) {
331
- logger.info(`Received ${signal}, stopping agent (git flush handled by project runner)`);
291
+ }
292
+ );
293
+ var shutdownAgent = (signal) => {
294
+ logger.info(`Received ${signal}, flushing git and stopping agent`);
295
+ void (async () => {
296
+ try {
297
+ await runner.flushGitOnShutdown();
298
+ } finally {
332
299
  runner.stop();
333
- } else {
334
- logger.info(`Received ${signal}, flushing git and stopping agent`);
335
- void (async () => {
336
- try {
337
- await runner.flushGitOnShutdown();
338
- } finally {
339
- runner.stop();
340
- }
341
- })();
342
300
  }
343
- setTimeout(
344
- () => {
345
- logger.warn(`Forcing exit after ${signal} timeout`);
346
- process.exit(1);
347
- },
348
- skipShutdownFlush ? 1e4 : 45e3
349
- ).unref();
350
- };
351
- process.on("SIGTERM", () => shutdownAgent("SIGTERM"));
352
- process.on("SIGINT", () => shutdownAgent("SIGINT"));
353
- await runner.connect();
354
- void checkSessionTaskIdentity({
355
- sessionId: process.env.CONVEYOR_SESSION_ID,
356
- taskId: CONVEYOR_TASK_ID,
357
- fetchSessionTaskId: async (sessionId) => {
358
- const ctx = await runner.connection.call("getTaskContext", { sessionId });
359
- return ctx.id;
360
- },
361
- logger
362
- });
363
- const conveyorConfig = loadConveyorConfig();
364
- if (conveyorConfig) {
365
- void (async () => {
366
- const logOutput = (stream, data) => {
367
- runner.connection.sendEvent({ type: "setup_output", stream, data });
368
- (stream === "stderr" ? process.stderr : process.stdout).write(data);
369
- };
370
- await waitForSidecars({
371
- onLog: (message) => logOutput("stdout", `[sidecars] ${message}
301
+ })();
302
+ setTimeout(() => {
303
+ logger.warn(`Forcing exit after ${signal} timeout`);
304
+ process.exit(1);
305
+ }, 45e3).unref();
306
+ };
307
+ process.on("SIGTERM", () => shutdownAgent("SIGTERM"));
308
+ process.on("SIGINT", () => shutdownAgent("SIGINT"));
309
+ await runner.connect();
310
+ void checkSessionTaskIdentity({
311
+ sessionId: process.env.CONVEYOR_SESSION_ID,
312
+ taskId: CONVEYOR_TASK_ID,
313
+ fetchSessionTaskId: async (sessionId) => {
314
+ const ctx = await runner.connection.call("getTaskContext", { sessionId });
315
+ return ctx.id;
316
+ },
317
+ logger
318
+ });
319
+ var conveyorConfig = loadConveyorConfig();
320
+ if (conveyorConfig) {
321
+ void (async () => {
322
+ const logOutput = (stream, data) => {
323
+ runner.connection.sendEvent({ type: "setup_output", stream, data });
324
+ (stream === "stderr" ? process.stderr : process.stdout).write(data);
325
+ };
326
+ await waitForSidecars({
327
+ onLog: (message) => logOutput("stdout", `[sidecars] ${message}
372
328
  `)
329
+ });
330
+ if (conveyorConfig.setupCommand) {
331
+ logger.info("Running setup command (background)", {
332
+ command: conveyorConfig.setupCommand
373
333
  });
374
- if (conveyorConfig.setupCommand) {
375
- logger.info("Running setup command (background)", {
376
- command: conveyorConfig.setupCommand
377
- });
378
- try {
379
- await runSetupCommand(conveyorConfig.setupCommand, CONVEYOR_WORKSPACE, logOutput);
380
- logger.info("Setup command completed");
381
- } catch (error) {
382
- const msg = error instanceof Error ? error.message : "Setup command failed";
383
- logger.error("Setup command failed", { error: msg });
384
- runner.connection.sendEvent({ type: "setup_error", message: msg });
385
- }
334
+ try {
335
+ await runSetupCommand(conveyorConfig.setupCommand, CONVEYOR_WORKSPACE, logOutput);
336
+ logger.info("Setup command completed");
337
+ } catch (error) {
338
+ const msg = error instanceof Error ? error.message : "Setup command failed";
339
+ logger.error("Setup command failed", { error: msg });
340
+ runner.connection.sendEvent({ type: "setup_error", message: msg });
386
341
  }
387
- let startCommandRunning = false;
388
- if (conveyorConfig.startCommand) {
389
- logger.info("Running start command", { command: conveyorConfig.startCommand });
390
- const child = runStartCommand(
391
- conveyorConfig.startCommand,
392
- CONVEYOR_WORKSPACE,
393
- (stream, data) => {
394
- runner.connection.sendEvent({ type: "start_command_output", stream, data });
395
- (stream === "stderr" ? process.stderr : process.stdout).write(data);
396
- }
397
- );
398
- startCommandRunning = true;
399
- child.on("exit", (code, signal) => {
400
- logger.info("Start command exited", { code, signal });
342
+ }
343
+ let startCommandRunning = false;
344
+ if (conveyorConfig.startCommand) {
345
+ logger.info("Running start command", { command: conveyorConfig.startCommand });
346
+ const child = runStartCommand(
347
+ conveyorConfig.startCommand,
348
+ CONVEYOR_WORKSPACE,
349
+ (stream, data) => {
350
+ runner.connection.sendEvent({ type: "start_command_output", stream, data });
351
+ (stream === "stderr" ? process.stderr : process.stdout).write(data);
352
+ }
353
+ );
354
+ startCommandRunning = true;
355
+ child.on("exit", (code, signal) => {
356
+ logger.info("Start command exited", { code, signal });
357
+ runner.connection.sendEvent({
358
+ type: "start_command_exited",
359
+ code,
360
+ signal,
361
+ message: `start command exited${code === null ? "" : ` with code ${code}`}${signal ? ` (signal: ${signal})` : ""}`
362
+ });
363
+ if (code !== null && code !== 0) {
401
364
  runner.connection.sendEvent({
402
- type: "start_command_exited",
403
- code,
404
- signal,
405
- message: `start command exited${code === null ? "" : ` with code ${code}`}${signal ? ` (signal: ${signal})` : ""}`
365
+ type: "start_command_error",
366
+ message: `start command exited with code ${code}${signal ? ` (signal: ${signal})` : ""}`
406
367
  });
407
- if (code !== null && code !== 0) {
408
- runner.connection.sendEvent({
409
- type: "start_command_error",
410
- message: `start command exited with code ${code}${signal ? ` (signal: ${signal})` : ""}`
411
- });
412
- }
413
- });
414
- child.on("error", (err) => {
415
- logger.error("Start command error", { error: err.message });
416
- runner.connection.sendEvent({ type: "start_command_error", message: err.message });
417
- });
418
- }
419
- const forwardPorts = await loadForwardPorts(CONVEYOR_WORKSPACE);
420
- const previewPorts = buildSessionPreviewPorts(forwardPorts);
421
- runner.connection.sendEvent({
422
- type: "setup_complete",
423
- startCommandRunning,
424
- previewPort: conveyorConfig.previewPort,
425
- ...previewPorts.length > 0 ? { previewPorts } : {}
368
+ }
426
369
  });
427
- })();
428
- }
429
- runner.run().then(() => {
430
- process.exit(runner.finalState === "error" ? 1 : 0);
431
- }).catch((error) => {
432
- const msg = error instanceof Error ? error.message : String(error);
433
- logger.error("Agent runner failed", { error: msg });
434
- process.exit(1);
435
- });
370
+ child.on("error", (err) => {
371
+ logger.error("Start command error", { error: err.message });
372
+ runner.connection.sendEvent({ type: "start_command_error", message: err.message });
373
+ });
374
+ }
375
+ const forwardPorts = await loadForwardPorts(CONVEYOR_WORKSPACE);
376
+ const previewPorts = buildSessionPreviewPorts(forwardPorts);
377
+ runner.connection.sendEvent({
378
+ type: "setup_complete",
379
+ startCommandRunning,
380
+ previewPort: conveyorConfig.previewPort,
381
+ ...previewPorts.length > 0 ? { previewPorts } : {}
382
+ });
383
+ })();
436
384
  }
385
+ runner.run().then(() => {
386
+ process.exit(runner.finalState === "error" ? 1 : 0);
387
+ }).catch((error) => {
388
+ const msg = error instanceof Error ? error.message : String(error);
389
+ logger.error("Agent runner failed", { error: msg });
390
+ process.exit(1);
391
+ });
437
392
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/setup/sidecars.ts","../src/utils/session-identity.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { SessionRunner } from \"./runner/session-runner.js\";\nimport { ProjectRunner } from \"./runner/project-runner.js\";\nimport type { AgentRunnerStatus, RunnerMode } from \"@project/shared\";\nimport { createServiceLogger } from \"./utils/logger.js\";\nimport {\n applyBootstrapToEnv,\n buildSessionPreviewPorts,\n fetchBootstrap,\n loadConveyorConfig,\n loadForwardPorts,\n runSetupCommand,\n runStartCommand,\n waitForSidecars,\n} from \"./setup/index.js\";\nimport { checkSessionTaskIdentity } from \"./utils/session-identity.js\";\n\n// Handle --version flag before any other initialization\nif (process.argv.includes(\"--version\")) {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(__dirname, \"..\", \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n process.stdout.write(pkg.version + \"\\n\");\n process.exit(0);\n}\n\nconst logger = createServiceLogger(\"CLI\");\n\nasync function bootstrapFromCodespace(apiUrl: string, instanceName: string): Promise<void> {\n const bootstrapToken = process.env.CONVEYOR_BOOTSTRAP_TOKEN;\n const apiUrlFromEnv = Boolean(process.env.CONVEYOR_API_URL);\n logger.info(\"Bootstrapping from codespace\", {\n codespace: instanceName,\n apiUrl,\n apiUrlFromEnv,\n bootstrapTokenPresent: Boolean(bootstrapToken),\n });\n const result = await fetchBootstrap({\n apiUrl,\n instanceName,\n bootstrapToken,\n });\n if (!result.ok) {\n logger.error(\"Bootstrap failed after retries\", {\n reason: result.reason,\n attempts: result.attempts,\n status: result.status,\n detail: result.detail,\n apiUrl,\n apiUrlFromEnv,\n bootstrapTokenPresent: Boolean(bootstrapToken),\n hint: apiUrlFromEnv\n ? \"Verify the codespace was created by this Conveyor deployment and that the bootstrap token is current.\"\n : \"CONVEYOR_API_URL was not set as a codespace secret — agent fell back to the built-in default. Re-create the codespace, or push CONVEYOR_API_URL via project settings.\",\n });\n process.exit(1);\n }\n applyBootstrapToEnv(result.config);\n if (result.config.mode === \"project\") {\n logger.info(\"Bootstrap complete (project mode)\", {\n projectId: result.config.projectId,\n attempts: result.attempts,\n });\n } else {\n logger.info(\"Bootstrap complete\", {\n taskId: result.config.taskId,\n attempts: result.attempts,\n });\n }\n}\n\n// Helper to detect expected abort errors from SDK cleanup\nfunction isExpectedAbortError(error: Error | NodeJS.ErrnoException): boolean {\n const message = error.message || \"\";\n const hasAbortMessage = /operation aborted/i.test(message) || /abort/i.test(message);\n const hasAbortCode = !(\"code\" in error) || error.code === undefined || error.code === \"ABORT_ERR\";\n return hasAbortMessage && hasAbortCode;\n}\n\nprocess.on(\"uncaughtException\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EPIPE\") return;\n\n if (isExpectedAbortError(err)) {\n logger.info(\"Ignored expected abort after shutdown\", { error: err.message, code: err.code });\n return;\n }\n\n logger.error(\"Uncaught exception\", { error: err.message, code: err.code });\n process.exit(1);\n});\n\nprocess.on(\"unhandledRejection\", (reason: unknown) => {\n const err = reason instanceof Error ? reason : new Error(String(reason));\n\n if (isExpectedAbortError(err)) {\n logger.info(\"Ignored expected abort rejection after shutdown\", { error: err.message });\n return;\n }\n\n logger.error(\"Unhandled rejection\", { error: err.message });\n process.exit(1);\n});\n\nconst DEFAULT_CONVEYOR_API_URL = \"https://api.conveyor.rallycryapp.com\";\nlet conveyorApiUrl = process.env.CONVEYOR_API_URL || DEFAULT_CONVEYOR_API_URL;\n\n// Step 1: Codespace bootstrap\nconst INSTANCE_NAME = process.env.CODESPACE_NAME || process.env.CLAUDESPACE_NAME;\nif (INSTANCE_NAME && !process.env.CONVEYOR_TASK_TOKEN && !process.env.CONVEYOR_PROJECT_TOKEN) {\n if (!conveyorApiUrl) {\n logger.error(\"Could not resolve CONVEYOR_API_URL for codespace bootstrap\");\n process.exit(1);\n }\n await bootstrapFromCodespace(conveyorApiUrl, INSTANCE_NAME);\n conveyorApiUrl = process.env.CONVEYOR_API_URL ?? conveyorApiUrl;\n}\n\n// Step 2: Read env vars (bootstrap may have set them)\nconst CONVEYOR_PROJECT_TOKEN = process.env.CONVEYOR_PROJECT_TOKEN;\nconst CONVEYOR_PROJECT_ID = process.env.CONVEYOR_PROJECT_ID;\n\n// Step 3: Branch on mode\nif (CONVEYOR_PROJECT_TOKEN && CONVEYOR_PROJECT_ID) {\n const CONVEYOR_PROJECT_DIR = process.env.CONVEYOR_WORKSPACE ?? process.cwd();\n\n if (!conveyorApiUrl) {\n logger.error(\"Could not resolve CONVEYOR_API_URL for project runner mode\");\n process.exit(1);\n }\n\n logger.info(\"Starting project runner\", { projectId: CONVEYOR_PROJECT_ID });\n\n const runner = new ProjectRunner({\n conveyorApiUrl,\n projectToken: CONVEYOR_PROJECT_TOKEN,\n projectId: CONVEYOR_PROJECT_ID,\n projectDir: CONVEYOR_PROJECT_DIR,\n });\n\n process.on(\"SIGTERM\", () => {\n logger.info(\"Received SIGTERM, stopping project runner\");\n void runner.stop();\n setTimeout(() => {\n logger.warn(\"Forcing exit after SIGTERM timeout\");\n process.exit(1);\n }, 40_000).unref();\n });\n\n process.on(\"SIGINT\", () => {\n logger.info(\"Received SIGINT, stopping project runner\");\n void runner.stop();\n setTimeout(() => {\n logger.warn(\"Forcing exit after SIGINT timeout\");\n process.exit(1);\n }, 40_000).unref();\n });\n\n runner\n .start()\n .then(() => {\n // start() resolves once stop() resolves the lifecycle promise (UI disconnect,\n // shutdown signal, or SIGINT/SIGTERM). Exit so the terminal returns to the shell\n // instead of hanging on lingering socket.io/PTY handles.\n process.exit(0);\n })\n .catch((error: unknown) => {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(\"Project runner failed\", { error: msg });\n process.exit(1);\n });\n} else {\n const CONVEYOR_TASK_TOKEN = process.env.CONVEYOR_TASK_TOKEN;\n const CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;\n const CONVEYOR_WORKSPACE = process.env.CONVEYOR_WORKSPACE ?? process.cwd();\n const CONVEYOR_MODE = (process.env.CONVEYOR_MODE ?? \"task\") as RunnerMode;\n const CONVEYOR_AGENT_MODE = process.env.CONVEYOR_AGENT_MODE || undefined;\n const CONVEYOR_IS_AUTO = CONVEYOR_AGENT_MODE\n ? CONVEYOR_AGENT_MODE === \"auto\"\n : process.env.CONVEYOR_IS_AUTO === \"true\";\n\n if (!CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {\n logger.error(\"Missing required environment variables\");\n logger.error(\" CONVEYOR_TASK_TOKEN - JWT token for task authentication\");\n logger.error(\" CONVEYOR_TASK_ID - ID of the task to execute\");\n logger.error(\"\");\n logger.error(\"CONVEYOR_API_URL is provided via codespace secret or bootstrap.\");\n logger.error(\"\");\n logger.error(\"Optional:\");\n logger.error(\" CONVEYOR_MODE - Runner mode: 'task' (default) or 'pm'\");\n logger.error(\" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)\");\n process.exit(1);\n }\n\n if (CONVEYOR_MODE !== \"task\" && CONVEYOR_MODE !== \"pm\" && CONVEYOR_MODE !== \"code-review\") {\n logger.error(\"Invalid CONVEYOR_MODE\", {\n mode: CONVEYOR_MODE,\n expected: [\"task\", \"pm\", \"code-review\"],\n });\n process.exit(1);\n }\n\n logger.info(\"Starting agent\", { mode: CONVEYOR_MODE });\n\n // Claudespace pods: longer idle timeout to stay alive for incoming messages.\n // Non-claudespace environments (local, workspace, GitHub Codespaces) have\n // persistent state and don't need the periodic WIP commit safety net, so\n // disable the git flush timer for them.\n const lifecycleOverrides = process.env.CLAUDESPACE_NAME\n ? { idleTimeoutMs: 60 * 60 * 1000 }\n : { gitFlushIntervalMs: 0 };\n\n const runner = new SessionRunner(\n {\n connection: {\n apiUrl: conveyorApiUrl ?? \"\",\n taskToken: CONVEYOR_TASK_TOKEN,\n // CONVEYOR_SESSION_ID is the CodespaceSession ID for BaseService ACL.\n // Falls back to CONVEYOR_TASK_ID for backward compat (codespace bootstrap sets only task ID).\n sessionId: process.env.CONVEYOR_SESSION_ID ?? CONVEYOR_TASK_ID,\n runnerMode: CONVEYOR_MODE,\n },\n runnerMode: CONVEYOR_MODE,\n isAuto: CONVEYOR_IS_AUTO,\n workspaceDir: CONVEYOR_WORKSPACE,\n agentMode: CONVEYOR_AGENT_MODE as import(\"@project/shared\").AgentMode | undefined,\n lifecycle: lifecycleOverrides,\n },\n {\n onStatusChange: (status: AgentRunnerStatus) => {\n logger.info(\"Status changed\", { status });\n },\n onEvent: (event: Record<string, unknown>) => {\n const detail =\n (event.message as string) ?? (event.content as string) ?? (event.summary as string) ?? \"\";\n if (detail) {\n logger.info(detail, { eventType: event.type as string });\n }\n },\n },\n );\n\n // Children of a local project runner skip the shutdown git flush — the\n // parent flushes every child working tree after the kill, and the flush's\n // token RPC + pushes can outlast the parent's SIGTERM→SIGKILL window.\n const skipShutdownFlush = process.env.CONVEYOR_SKIP_SHUTDOWN_GIT_FLUSH === \"true\";\n\n const shutdownAgent = (signal: \"SIGTERM\" | \"SIGINT\") => {\n if (skipShutdownFlush) {\n logger.info(`Received ${signal}, stopping agent (git flush handled by project runner)`);\n runner.stop();\n } else {\n logger.info(`Received ${signal}, flushing git and stopping agent`);\n // Flush WIP commit + push BEFORE stop() tears down the connection, since\n // the token-refresh RPC needs a live socket. Then stop the runner.\n void (async () => {\n try {\n await runner.flushGitOnShutdown();\n } finally {\n runner.stop();\n }\n })();\n }\n setTimeout(\n () => {\n logger.warn(`Forcing exit after ${signal} timeout`);\n process.exit(1);\n },\n skipShutdownFlush ? 10_000 : 45_000,\n ).unref();\n };\n\n process.on(\"SIGTERM\", () => shutdownAgent(\"SIGTERM\"));\n process.on(\"SIGINT\", () => shutdownAgent(\"SIGINT\"));\n\n // Connect first so setup/start output is forwarded to the API\n await runner.connect();\n\n // Defense-in-depth: warn loudly if CONVEYOR_SESSION_ID decodes to a different\n // task than CONVEYOR_TASK_ID. Authoritative checks are server-side\n // (requireTaskAuth + partial-unique index on active CodespaceSessions). This\n // is a visibility net in case those regress — see SEC-9 postmortem in\n // .claude/rules/agent-codespace.md.\n void checkSessionTaskIdentity({\n sessionId: process.env.CONVEYOR_SESSION_ID,\n taskId: CONVEYOR_TASK_ID,\n fetchSessionTaskId: async (sessionId) => {\n const ctx = await runner.connection.call(\"getTaskContext\", { sessionId });\n return ctx.id;\n },\n logger,\n });\n\n // Run setup + start commands in the background so the agent can start\n // fetching context and thinking immediately. The dev environment will be\n // ready by the time the agent needs to actually execute anything in it.\n // Start command still runs after setup (install must finish before `bun\n // run dev` works), but both are decoupled from runner.run().\n //\n // INVARIANT: failures inside this IIFE are NON-FATAL. Any throw or non-zero\n // exit from setup/start must surface as a chat event, never as process.exit.\n // The agent continues so the user can still interact with it and debug.\n const conveyorConfig = loadConveyorConfig();\n if (conveyorConfig) {\n void (async () => {\n const logOutput = (stream: \"stdout\" | \"stderr\", data: string) => {\n runner.connection.sendEvent({ type: \"setup_output\", stream, data });\n (stream === \"stderr\" ? process.stderr : process.stdout).write(data);\n };\n\n // Gate setup/start on sidecar readiness. This wait used to live in the pod\n // entrypoint AHEAD of the agent launch, blocking the thinking loop on\n // postgres/firebase boot it never needed. It now runs here — inside the\n // background IIFE, in parallel with runner.run() — so it only delays\n // setup/start (which genuinely need a warm postgres), not the agent.\n await waitForSidecars({\n onLog: (message) => logOutput(\"stdout\", `[sidecars] ${message}\\n`),\n });\n\n if (conveyorConfig.setupCommand) {\n logger.info(\"Running setup command (background)\", {\n command: conveyorConfig.setupCommand,\n });\n try {\n await runSetupCommand(conveyorConfig.setupCommand, CONVEYOR_WORKSPACE, logOutput);\n logger.info(\"Setup command completed\");\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Setup command failed\";\n logger.error(\"Setup command failed\", { error: msg });\n runner.connection.sendEvent({ type: \"setup_error\", message: msg });\n }\n }\n\n let startCommandRunning = false;\n if (conveyorConfig.startCommand) {\n logger.info(\"Running start command\", { command: conveyorConfig.startCommand });\n const child = runStartCommand(\n conveyorConfig.startCommand,\n CONVEYOR_WORKSPACE,\n (stream, data) => {\n runner.connection.sendEvent({ type: \"start_command_output\", stream, data });\n (stream === \"stderr\" ? process.stderr : process.stdout).write(data);\n },\n );\n startCommandRunning = true;\n child.on(\"exit\", (code, signal) => {\n logger.info(\"Start command exited\", { code, signal });\n runner.connection.sendEvent({\n type: \"start_command_exited\",\n code,\n signal,\n message: `start command exited${code === null ? \"\" : ` with code ${code}`}${signal ? ` (signal: ${signal})` : \"\"}`,\n });\n // Surface non-zero exits as a loud chat message too, so users know\n // their dev server crashed and the agent may hit tool-use failures.\n if (code !== null && code !== 0) {\n runner.connection.sendEvent({\n type: \"start_command_error\",\n message: `start command exited with code ${code}${signal ? ` (signal: ${signal})` : \"\"}`,\n });\n }\n });\n child.on(\"error\", (err) => {\n logger.error(\"Start command error\", { error: err.message });\n runner.connection.sendEvent({ type: \"start_command_error\", message: err.message });\n });\n }\n\n const forwardPorts = await loadForwardPorts(CONVEYOR_WORKSPACE);\n const previewPorts = buildSessionPreviewPorts(forwardPorts);\n runner.connection.sendEvent({\n type: \"setup_complete\",\n startCommandRunning,\n previewPort: conveyorConfig.previewPort,\n ...(previewPorts.length > 0 ? { previewPorts } : {}),\n });\n })();\n }\n\n // Start the main agent lifecycle immediately in parallel with setup\n // (context fetch, mode resolution, core loop).\n runner\n .run()\n .then(() => {\n // Exit with code 0 for clean shutdown (entrypoint won't restart),\n // code 1 for errors (entrypoint will restart).\n process.exit(runner.finalState === \"error\" ? 1 : 0);\n })\n .catch((error: unknown) => {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(\"Agent runner failed\", { error: msg });\n process.exit(1);\n });\n}\n","import net from \"node:net\";\n\n/**\n * Sidecar readiness gate.\n *\n * Previously the pod entrypoint blocked on postgres/firebase coming up BEFORE it\n * launched the agent, so the agent's thinking loop paid for up to ~60s of\n * sidecar boot it never needed. That wait now lives here and runs inside the\n * agent's background setup IIFE — it gates only `setupCommand`/`startCommand`\n * (which genuinely need a warm postgres), never the agent loop.\n *\n * Semantics deliberately match the old entrypoint: best-effort, NON-FATAL on\n * timeout (log a warning and continue), and a no-op when no sidecar env vars are\n * present. Per-target timeouts mirror what the entrypoint learned the hard way —\n * the firebase auth emulator cold-boots slowly and doesn't bind 9099 until ~50s\n * after its container starts, so it gets 60s while postgres gets 30s.\n */\n\nexport interface SidecarTarget {\n /** Human label for logs (e.g. \"postgres\"). */\n name: string;\n host: string;\n port: number;\n /** Per-target readiness deadline in ms (overridden by an explicit opts.timeoutMs). */\n timeoutMs?: number;\n}\n\nexport interface WaitForSidecarsOptions {\n /** Env to read targets from. Defaults to `process.env`. */\n env?: NodeJS.ProcessEnv;\n /** Progress sink (one line per message, no trailing newline). */\n onLog?: (message: string) => void;\n /** Force a single deadline for every target, overriding per-target defaults. */\n timeoutMs?: number;\n /** Delay between probe attempts in ms. */\n pollIntervalMs?: number;\n /** TCP probe seam — returns true once the target accepts a connection. */\n probe?: (target: SidecarTarget) => Promise<boolean>;\n}\n\nconst POSTGRES_TIMEOUT_MS = 30_000;\nconst FIREBASE_TIMEOUT_MS = 60_000;\nconst FALLBACK_TIMEOUT_MS = 30_000;\nconst DEFAULT_POLL_INTERVAL_MS = 1_000;\nconst DEFAULT_PROBE_TIMEOUT_MS = 2_000;\n\nconst POSTGRES_DEFAULT_PORT = 5432;\nconst FIREBASE_DEFAULT_PORT = 9099;\n\nfunction parseHostPort(value: string, defaultPort: number): { host: string; port: number } | null {\n const trimmed = value.trim().replace(/^[a-z]+:\\/\\//i, \"\");\n if (!trimmed) return null;\n const idx = trimmed.lastIndexOf(\":\");\n if (idx === -1) {\n return { host: trimmed, port: defaultPort };\n }\n const host = trimmed.slice(0, idx) || \"localhost\";\n const port = Number(trimmed.slice(idx + 1));\n return { host, port: Number.isFinite(port) ? port : defaultPort };\n}\n\n/**\n * Resolve the sidecar targets the agent should wait for from env. Mirrors the\n * entrypoint's conditions: postgres when `DATABASE_URL` is set, firebase auth\n * emulator when `FIREBASE_AUTH_EMULATOR_HOST` is set.\n */\nexport function resolveSidecarTargets(env: NodeJS.ProcessEnv = process.env): SidecarTarget[] {\n const targets: SidecarTarget[] = [];\n\n const databaseUrl = env.DATABASE_URL;\n if (databaseUrl) {\n try {\n const url = new URL(databaseUrl);\n const host = url.hostname || \"localhost\";\n const port = url.port ? Number(url.port) : POSTGRES_DEFAULT_PORT;\n if (Number.isFinite(port)) {\n targets.push({ name: \"postgres\", host, port, timeoutMs: POSTGRES_TIMEOUT_MS });\n }\n } catch {\n // Unparseable DATABASE_URL — skip rather than crash the setup path.\n }\n }\n\n const firebaseHost = env.FIREBASE_AUTH_EMULATOR_HOST;\n if (firebaseHost) {\n const parsed = parseHostPort(firebaseHost, FIREBASE_DEFAULT_PORT);\n if (parsed) {\n targets.push({\n name: \"firebase auth emulator\",\n host: parsed.host,\n port: parsed.port,\n timeoutMs: FIREBASE_TIMEOUT_MS,\n });\n }\n }\n\n return targets;\n}\n\nfunction defaultProbe(target: SidecarTarget): Promise<boolean> {\n return new Promise((resolve) => {\n let settled = false;\n const socket = net.createConnection({ host: target.host, port: target.port });\n const done = (ok: boolean) => {\n if (settled) return;\n settled = true;\n socket.destroy();\n resolve(ok);\n };\n socket.once(\"connect\", () => done(true));\n socket.once(\"error\", () => done(false));\n socket.setTimeout(DEFAULT_PROBE_TIMEOUT_MS, () => done(false));\n });\n}\n\nconst delay = (ms: number): Promise<void> =>\n new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n\nasync function waitForTarget(\n target: SidecarTarget,\n opts: {\n onLog: (message: string) => void;\n timeoutMs?: number;\n pollIntervalMs: number;\n probe: (target: SidecarTarget) => Promise<boolean>;\n },\n): Promise<void> {\n const { onLog, pollIntervalMs, probe } = opts;\n const timeoutMs = opts.timeoutMs ?? target.timeoutMs ?? FALLBACK_TIMEOUT_MS;\n const deadline = Date.now() + timeoutMs;\n onLog(`Waiting for ${target.name} on ${target.host}:${target.port}...`);\n\n while (true) {\n if (await probe(target)) {\n onLog(`${target.name} is ready`);\n return;\n }\n if (Date.now() >= deadline) {\n onLog(\n `WARNING: ${target.name} not ready after ${Math.round(timeoutMs / 1000)}s, continuing anyway`,\n );\n return;\n }\n await delay(pollIntervalMs);\n }\n}\n\n/**\n * Block until every configured sidecar is reachable (or its per-target deadline\n * elapses). Resolves immediately when no sidecar env vars are set. Never throws —\n * a timed-out sidecar logs a warning and is treated as \"continue anyway\".\n */\nexport async function waitForSidecars(opts: WaitForSidecarsOptions = {}): Promise<void> {\n const {\n env = process.env,\n onLog = () => {},\n timeoutMs,\n pollIntervalMs = DEFAULT_POLL_INTERVAL_MS,\n probe = defaultProbe,\n } = opts;\n\n const targets = resolveSidecarTargets(env);\n if (targets.length === 0) return;\n\n await Promise.all(\n targets.map((target) => waitForTarget(target, { onLog, timeoutMs, pollIntervalMs, probe })),\n );\n}\n","// Defense-in-depth startup check. The authoritative guarantee that a session is\n// bound to the right task lives server-side (requireTaskAuth + the Postgres\n// partial-unique index on active CodespaceSessions). This check exists so that\n// if those invariants ever regress, a human sees a loud WARN immediately\n// instead of the symptoms SEC-9 produced (multiple agents silently clobbering\n// the same branch).\nexport interface SessionIdentityLogger {\n warn(message: string, data?: Record<string, unknown>): void;\n info?(message: string, data?: Record<string, unknown>): void;\n}\n\nexport interface CheckSessionTaskIdentityParams {\n sessionId: string | undefined;\n taskId: string;\n fetchSessionTaskId: (sessionId: string) => Promise<string>;\n logger: SessionIdentityLogger;\n}\n\nexport async function checkSessionTaskIdentity(\n params: CheckSessionTaskIdentityParams,\n): Promise<\"match\" | \"mismatch\" | \"skipped\" | \"error\"> {\n const { sessionId, taskId, fetchSessionTaskId, logger } = params;\n if (!sessionId || sessionId === taskId) return \"skipped\";\n let sessionTaskId: string;\n try {\n sessionTaskId = await fetchSessionTaskId(sessionId);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.warn(\"Could not verify session/task identity — continuing (defense-in-depth only)\", {\n sessionId,\n taskId,\n error: message,\n });\n return \"error\";\n }\n if (sessionTaskId !== taskId) {\n logger.warn(\n \"!!! CONVEYOR_SESSION_ID is bound to a different task than CONVEYOR_TASK_ID — server-side guards should still block mutations, but this indicates a misconfiguration or replayed token.\",\n { sessionId, envTaskId: taskId, sessionTaskId },\n );\n return \"mismatch\";\n }\n return \"match\";\n}\n"],"mappings":"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","names":["logger"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/setup/sidecars.ts","../src/utils/session-identity.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { SessionRunner } from \"./runner/session-runner.js\";\nimport type { AgentRunnerStatus, RunnerMode } from \"@project/shared\";\nimport { createServiceLogger } from \"./utils/logger.js\";\nimport {\n applyBootstrapToEnv,\n buildSessionPreviewPorts,\n fetchBootstrap,\n loadConveyorConfig,\n loadForwardPorts,\n runSetupCommand,\n runStartCommand,\n waitForSidecars,\n} from \"./setup/index.js\";\nimport { checkSessionTaskIdentity } from \"./utils/session-identity.js\";\n\n// Handle --version flag before any other initialization\nif (process.argv.includes(\"--version\")) {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(__dirname, \"..\", \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n process.stdout.write(pkg.version + \"\\n\");\n process.exit(0);\n}\n\nconst logger = createServiceLogger(\"CLI\");\n\nasync function bootstrapFromCodespace(apiUrl: string, instanceName: string): Promise<void> {\n const bootstrapToken = process.env.CONVEYOR_BOOTSTRAP_TOKEN;\n const apiUrlFromEnv = Boolean(process.env.CONVEYOR_API_URL);\n logger.info(\"Bootstrapping from codespace\", {\n codespace: instanceName,\n apiUrl,\n apiUrlFromEnv,\n bootstrapTokenPresent: Boolean(bootstrapToken),\n });\n const result = await fetchBootstrap({\n apiUrl,\n instanceName,\n bootstrapToken,\n });\n if (!result.ok) {\n logger.error(\"Bootstrap failed after retries\", {\n reason: result.reason,\n attempts: result.attempts,\n status: result.status,\n detail: result.detail,\n apiUrl,\n apiUrlFromEnv,\n bootstrapTokenPresent: Boolean(bootstrapToken),\n hint: apiUrlFromEnv\n ? \"Verify the codespace was created by this Conveyor deployment and that the bootstrap token is current.\"\n : \"CONVEYOR_API_URL was not set as a codespace secret — agent fell back to the built-in default. Re-create the codespace, or push CONVEYOR_API_URL via project settings.\",\n });\n process.exit(1);\n }\n applyBootstrapToEnv(result.config);\n logger.info(\"Bootstrap complete\", {\n taskId: result.config.taskId,\n attempts: result.attempts,\n });\n}\n\n// Helper to detect expected abort errors from SDK cleanup\nfunction isExpectedAbortError(error: Error | NodeJS.ErrnoException): boolean {\n const message = error.message || \"\";\n const hasAbortMessage = /operation aborted/i.test(message) || /abort/i.test(message);\n const hasAbortCode = !(\"code\" in error) || error.code === undefined || error.code === \"ABORT_ERR\";\n return hasAbortMessage && hasAbortCode;\n}\n\nprocess.on(\"uncaughtException\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EPIPE\") return;\n\n if (isExpectedAbortError(err)) {\n logger.info(\"Ignored expected abort after shutdown\", { error: err.message, code: err.code });\n return;\n }\n\n logger.error(\"Uncaught exception\", { error: err.message, code: err.code });\n process.exit(1);\n});\n\nprocess.on(\"unhandledRejection\", (reason: unknown) => {\n const err = reason instanceof Error ? reason : new Error(String(reason));\n\n if (isExpectedAbortError(err)) {\n logger.info(\"Ignored expected abort rejection after shutdown\", { error: err.message });\n return;\n }\n\n logger.error(\"Unhandled rejection\", { error: err.message });\n process.exit(1);\n});\n\nconst DEFAULT_CONVEYOR_API_URL = \"https://api.conveyor.rallycryapp.com\";\nlet conveyorApiUrl = process.env.CONVEYOR_API_URL || DEFAULT_CONVEYOR_API_URL;\n\n// Step 1: Codespace bootstrap\nconst INSTANCE_NAME = process.env.CODESPACE_NAME || process.env.CLAUDESPACE_NAME;\nif (INSTANCE_NAME && !process.env.CONVEYOR_TASK_TOKEN) {\n if (!conveyorApiUrl) {\n logger.error(\"Could not resolve CONVEYOR_API_URL for codespace bootstrap\");\n process.exit(1);\n }\n await bootstrapFromCodespace(conveyorApiUrl, INSTANCE_NAME);\n conveyorApiUrl = process.env.CONVEYOR_API_URL ?? conveyorApiUrl;\n}\n\n// Step 2: Read env vars (bootstrap may have set them)\nconst CONVEYOR_TASK_TOKEN = process.env.CONVEYOR_TASK_TOKEN;\nconst CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;\nconst CONVEYOR_WORKSPACE = process.env.CONVEYOR_WORKSPACE ?? process.cwd();\nconst CONVEYOR_MODE = (process.env.CONVEYOR_MODE ?? \"task\") as RunnerMode;\nconst CONVEYOR_AGENT_MODE = process.env.CONVEYOR_AGENT_MODE || undefined;\nconst CONVEYOR_IS_AUTO = CONVEYOR_AGENT_MODE\n ? CONVEYOR_AGENT_MODE === \"auto\"\n : process.env.CONVEYOR_IS_AUTO === \"true\";\n\nif (!CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {\n logger.error(\"Missing required environment variables\");\n logger.error(\" CONVEYOR_TASK_TOKEN - JWT token for task authentication\");\n logger.error(\" CONVEYOR_TASK_ID - ID of the task to execute\");\n logger.error(\"\");\n logger.error(\"CONVEYOR_API_URL is provided via codespace secret or bootstrap.\");\n logger.error(\"\");\n logger.error(\"Optional:\");\n logger.error(\" CONVEYOR_MODE - Runner mode: 'task' (default) or 'pm'\");\n logger.error(\" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)\");\n process.exit(1);\n}\n\nif (CONVEYOR_MODE !== \"task\" && CONVEYOR_MODE !== \"pm\" && CONVEYOR_MODE !== \"code-review\") {\n logger.error(\"Invalid CONVEYOR_MODE\", {\n mode: CONVEYOR_MODE,\n expected: [\"task\", \"pm\", \"code-review\"],\n });\n process.exit(1);\n}\n\nlogger.info(\"Starting agent\", { mode: CONVEYOR_MODE });\n\n// Claudespace pods: longer idle timeout to stay alive for incoming messages.\n// Non-claudespace environments (local, workspace, GitHub Codespaces) have\n// persistent state and don't need the periodic WIP commit safety net, so\n// disable the git flush timer for them.\nconst lifecycleOverrides = process.env.CLAUDESPACE_NAME\n ? { idleTimeoutMs: 60 * 60 * 1000 }\n : { gitFlushIntervalMs: 0 };\n\nconst runner = new SessionRunner(\n {\n connection: {\n apiUrl: conveyorApiUrl ?? \"\",\n taskToken: CONVEYOR_TASK_TOKEN,\n // CONVEYOR_SESSION_ID is the CodespaceSession ID for BaseService ACL.\n // Falls back to CONVEYOR_TASK_ID for backward compat (codespace bootstrap sets only task ID).\n sessionId: process.env.CONVEYOR_SESSION_ID ?? CONVEYOR_TASK_ID,\n runnerMode: CONVEYOR_MODE,\n },\n runnerMode: CONVEYOR_MODE,\n isAuto: CONVEYOR_IS_AUTO,\n workspaceDir: CONVEYOR_WORKSPACE,\n agentMode: CONVEYOR_AGENT_MODE as import(\"@project/shared\").AgentMode | undefined,\n lifecycle: lifecycleOverrides,\n },\n {\n onStatusChange: (status: AgentRunnerStatus) => {\n logger.info(\"Status changed\", { status });\n },\n onEvent: (event: Record<string, unknown>) => {\n const detail =\n (event.message as string) ?? (event.content as string) ?? (event.summary as string) ?? \"\";\n if (detail) {\n logger.info(detail, { eventType: event.type as string });\n }\n },\n },\n);\n\nconst shutdownAgent = (signal: \"SIGTERM\" | \"SIGINT\") => {\n logger.info(`Received ${signal}, flushing git and stopping agent`);\n // Flush WIP commit + push BEFORE stop() tears down the connection, since\n // the token-refresh RPC needs a live socket. Then stop the runner.\n void (async () => {\n try {\n await runner.flushGitOnShutdown();\n } finally {\n runner.stop();\n }\n })();\n setTimeout(() => {\n logger.warn(`Forcing exit after ${signal} timeout`);\n process.exit(1);\n }, 45_000).unref();\n};\n\nprocess.on(\"SIGTERM\", () => shutdownAgent(\"SIGTERM\"));\nprocess.on(\"SIGINT\", () => shutdownAgent(\"SIGINT\"));\n\n// Connect first so setup/start output is forwarded to the API\nawait runner.connect();\n\n// Defense-in-depth: warn loudly if CONVEYOR_SESSION_ID decodes to a different\n// task than CONVEYOR_TASK_ID. Authoritative checks are server-side\n// (requireTaskAuth + partial-unique index on active CodespaceSessions). This\n// is a visibility net in case those regress — see SEC-9 postmortem in\n// .claude/rules/agent-codespace.md.\nvoid checkSessionTaskIdentity({\n sessionId: process.env.CONVEYOR_SESSION_ID,\n taskId: CONVEYOR_TASK_ID,\n fetchSessionTaskId: async (sessionId) => {\n const ctx = await runner.connection.call(\"getTaskContext\", { sessionId });\n return ctx.id;\n },\n logger,\n});\n\n// Run setup + start commands in the background so the agent can start\n// fetching context and thinking immediately. The dev environment will be\n// ready by the time the agent needs to actually execute anything in it.\n// Start command still runs after setup (install must finish before `bun\n// run dev` works), but both are decoupled from runner.run().\n//\n// INVARIANT: failures inside this IIFE are NON-FATAL. Any throw or non-zero\n// exit from setup/start must surface as a chat event, never as process.exit.\n// The agent continues so the user can still interact with it and debug.\nconst conveyorConfig = loadConveyorConfig();\nif (conveyorConfig) {\n void (async () => {\n const logOutput = (stream: \"stdout\" | \"stderr\", data: string) => {\n runner.connection.sendEvent({ type: \"setup_output\", stream, data });\n (stream === \"stderr\" ? process.stderr : process.stdout).write(data);\n };\n\n // Gate setup/start on sidecar readiness. This wait used to live in the pod\n // entrypoint AHEAD of the agent launch, blocking the thinking loop on\n // postgres/firebase boot it never needed. It now runs here — inside the\n // background IIFE, in parallel with runner.run() — so it only delays\n // setup/start (which genuinely need a warm postgres), not the agent.\n await waitForSidecars({\n onLog: (message) => logOutput(\"stdout\", `[sidecars] ${message}\\n`),\n });\n\n if (conveyorConfig.setupCommand) {\n logger.info(\"Running setup command (background)\", {\n command: conveyorConfig.setupCommand,\n });\n try {\n await runSetupCommand(conveyorConfig.setupCommand, CONVEYOR_WORKSPACE, logOutput);\n logger.info(\"Setup command completed\");\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Setup command failed\";\n logger.error(\"Setup command failed\", { error: msg });\n runner.connection.sendEvent({ type: \"setup_error\", message: msg });\n }\n }\n\n let startCommandRunning = false;\n if (conveyorConfig.startCommand) {\n logger.info(\"Running start command\", { command: conveyorConfig.startCommand });\n const child = runStartCommand(\n conveyorConfig.startCommand,\n CONVEYOR_WORKSPACE,\n (stream, data) => {\n runner.connection.sendEvent({ type: \"start_command_output\", stream, data });\n (stream === \"stderr\" ? process.stderr : process.stdout).write(data);\n },\n );\n startCommandRunning = true;\n child.on(\"exit\", (code, signal) => {\n logger.info(\"Start command exited\", { code, signal });\n runner.connection.sendEvent({\n type: \"start_command_exited\",\n code,\n signal,\n message: `start command exited${code === null ? \"\" : ` with code ${code}`}${signal ? ` (signal: ${signal})` : \"\"}`,\n });\n // Surface non-zero exits as a loud chat message too, so users know\n // their dev server crashed and the agent may hit tool-use failures.\n if (code !== null && code !== 0) {\n runner.connection.sendEvent({\n type: \"start_command_error\",\n message: `start command exited with code ${code}${signal ? ` (signal: ${signal})` : \"\"}`,\n });\n }\n });\n child.on(\"error\", (err) => {\n logger.error(\"Start command error\", { error: err.message });\n runner.connection.sendEvent({ type: \"start_command_error\", message: err.message });\n });\n }\n\n const forwardPorts = await loadForwardPorts(CONVEYOR_WORKSPACE);\n const previewPorts = buildSessionPreviewPorts(forwardPorts);\n runner.connection.sendEvent({\n type: \"setup_complete\",\n startCommandRunning,\n previewPort: conveyorConfig.previewPort,\n ...(previewPorts.length > 0 ? { previewPorts } : {}),\n });\n })();\n}\n\n// Start the main agent lifecycle immediately in parallel with setup\n// (context fetch, mode resolution, core loop).\nrunner\n .run()\n .then(() => {\n // Exit with code 0 for clean shutdown (entrypoint won't restart),\n // code 1 for errors (entrypoint will restart).\n process.exit(runner.finalState === \"error\" ? 1 : 0);\n })\n .catch((error: unknown) => {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(\"Agent runner failed\", { error: msg });\n process.exit(1);\n });\n","import net from \"node:net\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\n/**\n * Sidecar readiness gate.\n *\n * Previously the pod entrypoint blocked on postgres/firebase coming up BEFORE it\n * launched the agent, so the agent's thinking loop paid for up to ~60s of\n * sidecar boot it never needed. That wait now lives here and runs inside the\n * agent's background setup IIFE — it gates only `setupCommand`/`startCommand`\n * (which genuinely need a warm postgres), never the agent loop.\n *\n * Semantics deliberately match the old entrypoint: best-effort, NON-FATAL on\n * timeout (log a warning and continue), and a no-op when no sidecar env vars are\n * present. Per-target timeouts mirror what the entrypoint learned the hard way —\n * the firebase auth emulator cold-boots slowly and doesn't bind 9099 until ~50s\n * after its container starts, so it gets 60s while postgres gets 30s.\n */\n\nexport interface SidecarTarget {\n /** Human label for logs (e.g. \"postgres\"). */\n name: string;\n host: string;\n port: number;\n /** Per-target readiness deadline in ms (overridden by an explicit opts.timeoutMs). */\n timeoutMs?: number;\n}\n\nexport interface WaitForSidecarsOptions {\n /** Env to read targets from. Defaults to `process.env`. */\n env?: NodeJS.ProcessEnv;\n /** Progress sink (one line per message, no trailing newline). */\n onLog?: (message: string) => void;\n /** Force a single deadline for every target, overriding per-target defaults. */\n timeoutMs?: number;\n /** Delay between probe attempts in ms. */\n pollIntervalMs?: number;\n /** TCP probe seam — returns true once the target accepts a connection. */\n probe?: (target: SidecarTarget) => Promise<boolean>;\n}\n\nconst POSTGRES_TIMEOUT_MS = 30_000;\nconst FIREBASE_TIMEOUT_MS = 60_000;\nconst FALLBACK_TIMEOUT_MS = 30_000;\nconst DEFAULT_POLL_INTERVAL_MS = 1_000;\nconst DEFAULT_PROBE_TIMEOUT_MS = 2_000;\n\nconst POSTGRES_DEFAULT_PORT = 5432;\nconst FIREBASE_DEFAULT_PORT = 9099;\n\nasync function startLazySidecars(\n env: NodeJS.ProcessEnv,\n onLog: (message: string) => void,\n): Promise<void> {\n const markerPath = env.CONVEYOR_SIDECAR_START_FILE;\n if (!markerPath) return;\n\n try {\n await mkdir(dirname(markerPath), { recursive: true });\n await writeFile(markerPath, \"start\\n\", \"utf8\");\n onLog(\"Started lazy sidecars\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n onLog(`WARNING: failed to start lazy sidecars: ${message}`);\n }\n}\n\nfunction parseHostPort(value: string, defaultPort: number): { host: string; port: number } | null {\n const trimmed = value.trim().replace(/^[a-z]+:\\/\\//i, \"\");\n if (!trimmed) return null;\n const idx = trimmed.lastIndexOf(\":\");\n if (idx === -1) {\n return { host: trimmed, port: defaultPort };\n }\n const host = trimmed.slice(0, idx) || \"localhost\";\n const port = Number(trimmed.slice(idx + 1));\n return { host, port: Number.isFinite(port) ? port : defaultPort };\n}\n\n/**\n * Resolve the sidecar targets the agent should wait for from env. Mirrors the\n * entrypoint's conditions: postgres when `DATABASE_URL` is set, firebase auth\n * emulator when `FIREBASE_AUTH_EMULATOR_HOST` is set.\n */\nexport function resolveSidecarTargets(env: NodeJS.ProcessEnv = process.env): SidecarTarget[] {\n const targets: SidecarTarget[] = [];\n\n const databaseUrl = env.DATABASE_URL;\n if (databaseUrl) {\n try {\n const url = new URL(databaseUrl);\n const host = url.hostname || \"localhost\";\n const port = url.port ? Number(url.port) : POSTGRES_DEFAULT_PORT;\n if (Number.isFinite(port)) {\n targets.push({ name: \"postgres\", host, port, timeoutMs: POSTGRES_TIMEOUT_MS });\n }\n } catch {\n // Unparseable DATABASE_URL — skip rather than crash the setup path.\n }\n }\n\n const firebaseHost = env.FIREBASE_AUTH_EMULATOR_HOST;\n if (firebaseHost) {\n const parsed = parseHostPort(firebaseHost, FIREBASE_DEFAULT_PORT);\n if (parsed) {\n targets.push({\n name: \"firebase auth emulator\",\n host: parsed.host,\n port: parsed.port,\n timeoutMs: FIREBASE_TIMEOUT_MS,\n });\n }\n }\n\n return targets;\n}\n\nfunction defaultProbe(target: SidecarTarget): Promise<boolean> {\n return new Promise((resolve) => {\n let settled = false;\n const socket = net.createConnection({ host: target.host, port: target.port });\n const done = (ok: boolean) => {\n if (settled) return;\n settled = true;\n socket.destroy();\n resolve(ok);\n };\n socket.once(\"connect\", () => done(true));\n socket.once(\"error\", () => done(false));\n socket.setTimeout(DEFAULT_PROBE_TIMEOUT_MS, () => done(false));\n });\n}\n\nconst delay = (ms: number): Promise<void> =>\n new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n\nasync function waitForTarget(\n target: SidecarTarget,\n opts: {\n onLog: (message: string) => void;\n timeoutMs?: number;\n pollIntervalMs: number;\n probe: (target: SidecarTarget) => Promise<boolean>;\n },\n): Promise<void> {\n const { onLog, pollIntervalMs, probe } = opts;\n const timeoutMs = opts.timeoutMs ?? target.timeoutMs ?? FALLBACK_TIMEOUT_MS;\n const deadline = Date.now() + timeoutMs;\n onLog(`Waiting for ${target.name} on ${target.host}:${target.port}...`);\n\n while (true) {\n if (await probe(target)) {\n onLog(`${target.name} is ready`);\n return;\n }\n if (Date.now() >= deadline) {\n onLog(\n `WARNING: ${target.name} not ready after ${Math.round(timeoutMs / 1000)}s, continuing anyway`,\n );\n return;\n }\n await delay(pollIntervalMs);\n }\n}\n\n/**\n * Block until every configured sidecar is reachable (or its per-target deadline\n * elapses). Resolves immediately when no sidecar env vars are set. Never throws —\n * a timed-out sidecar logs a warning and is treated as \"continue anyway\".\n */\nexport async function waitForSidecars(opts: WaitForSidecarsOptions = {}): Promise<void> {\n const {\n env = process.env,\n onLog = () => {},\n timeoutMs,\n pollIntervalMs = DEFAULT_POLL_INTERVAL_MS,\n probe = defaultProbe,\n } = opts;\n\n await startLazySidecars(env, onLog);\n\n const targets = resolveSidecarTargets(env);\n if (targets.length === 0) return;\n\n await Promise.all(\n targets.map((target) => waitForTarget(target, { onLog, timeoutMs, pollIntervalMs, probe })),\n );\n}\n","// Defense-in-depth startup check. The authoritative guarantee that a session is\n// bound to the right task lives server-side (requireTaskAuth + the Postgres\n// partial-unique index on active CodespaceSessions). This check exists so that\n// if those invariants ever regress, a human sees a loud WARN immediately\n// instead of the symptoms SEC-9 produced (multiple agents silently clobbering\n// the same branch).\nexport interface SessionIdentityLogger {\n warn(message: string, data?: Record<string, unknown>): void;\n info?(message: string, data?: Record<string, unknown>): void;\n}\n\nexport interface CheckSessionTaskIdentityParams {\n sessionId: string | undefined;\n taskId: string;\n fetchSessionTaskId: (sessionId: string) => Promise<string>;\n logger: SessionIdentityLogger;\n}\n\nexport async function checkSessionTaskIdentity(\n params: CheckSessionTaskIdentityParams,\n): Promise<\"match\" | \"mismatch\" | \"skipped\" | \"error\"> {\n const { sessionId, taskId, fetchSessionTaskId, logger } = params;\n if (!sessionId || sessionId === taskId) return \"skipped\";\n let sessionTaskId: string;\n try {\n sessionTaskId = await fetchSessionTaskId(sessionId);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.warn(\"Could not verify session/task identity — continuing (defense-in-depth only)\", {\n sessionId,\n taskId,\n error: message,\n });\n return \"error\";\n }\n if (sessionTaskId !== taskId) {\n logger.warn(\n \"!!! CONVEYOR_SESSION_ID is bound to a different task than CONVEYOR_TASK_ID — server-side guards should still block mutations, but this indicates a misconfiguration or replayed token.\",\n { sessionId, envTaskId: taskId, sessionTaskId },\n );\n return \"mismatch\";\n }\n return \"match\";\n}\n"],"mappings":"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","names":["dirname","logger","dirname"]}