@rallycry/conveyor-agent 10.13.3 → 10.13.9

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
@@ -14,6 +14,8 @@ import {
14
14
  awaitGitReady,
15
15
  buildPromptBytes,
16
16
  buildSessionPreviewPorts,
17
+ buildSynthesizedCredentials,
18
+ claudeJsonPath,
17
19
  cleanTerminalOutput,
18
20
  createServiceLogger,
19
21
  defineTool,
@@ -23,19 +25,21 @@ import {
23
25
  loadConveyorConfig,
24
26
  loadForwardPorts,
25
27
  loadPtySpawn,
28
+ parseUsageGauges,
26
29
  resolvePlaywrightMcpServer,
27
30
  resolveSessionStart,
28
31
  runSetupCommand,
29
32
  runStartCommand,
33
+ runUsageProbe,
30
34
  sampleKeyUsage,
31
35
  terminateProcessGroup,
32
36
  textResult
33
- } from "./chunk-P4VWWR5O.js";
37
+ } from "./chunk-PXQJ4NVO.js";
34
38
  import "./chunk-7TQO4ZF4.js";
35
39
 
36
40
  // src/cli.ts
37
41
  import { readFileSync } from "fs";
38
- import { join as join2, dirname as dirname3 } from "path";
42
+ import { join as join3, dirname as dirname3 } from "path";
39
43
  import { fileURLToPath } from "url";
40
44
 
41
45
  // src/setup/sidecars.ts
@@ -207,6 +211,34 @@ async function waitForSidecars(opts = {}) {
207
211
  );
208
212
  }
209
213
 
214
+ // src/setup/boot-milestone.ts
215
+ var REPORT_TIMEOUT_MS = 5e3;
216
+ async function reportBootMilestone(opts) {
217
+ const env = opts.env ?? process.env;
218
+ const apiUrl = env.CONVEYOR_API_URL;
219
+ const token = env.POD_BOOTSTRAP_TOKEN;
220
+ if (!apiUrl || !token) return false;
221
+ const fetchFn = opts.fetchFn ?? fetch;
222
+ const controller = new AbortController();
223
+ const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? REPORT_TIMEOUT_MS);
224
+ try {
225
+ const res = await fetchFn(`${apiUrl.replace(/\/$/, "")}/api/v3/pods/boot-milestone`, {
226
+ method: "POST",
227
+ headers: {
228
+ "content-type": "application/json",
229
+ authorization: `Bearer ${token}`
230
+ },
231
+ body: JSON.stringify({ key: opts.key }),
232
+ signal: controller.signal
233
+ });
234
+ return res.ok;
235
+ } catch {
236
+ return false;
237
+ } finally {
238
+ clearTimeout(timer);
239
+ }
240
+ }
241
+
210
242
  // src/setup/workspace-command-supervisor.ts
211
243
  var defaultWriteOutput = (stream, data) => {
212
244
  (stream === "stderr" ? process.stderr : process.stdout).write(data);
@@ -236,6 +268,7 @@ var WorkspaceCommandSupervisor = class {
236
268
  loadForwardPortsFn;
237
269
  writeOutput;
238
270
  terminateStartCommand;
271
+ reportBootMilestoneFn;
239
272
  startCommandChild = null;
240
273
  liveStartCommandChildren = /* @__PURE__ */ new Set();
241
274
  startCommandTerminations = /* @__PURE__ */ new WeakMap();
@@ -263,6 +296,9 @@ var WorkspaceCommandSupervisor = class {
263
296
  this.loadForwardPortsFn = options.loadForwardPorts ?? loadForwardPorts;
264
297
  this.writeOutput = options.writeOutput ?? defaultWriteOutput;
265
298
  this.terminateStartCommand = options.terminateStartCommand ?? terminateProcessGroup;
299
+ this.reportBootMilestoneFn = options.reportBootMilestone ?? ((key) => {
300
+ void reportBootMilestone({ key, env: this.env });
301
+ });
266
302
  }
267
303
  start() {
268
304
  if (this.started || this.stopped) return;
@@ -308,6 +344,7 @@ var WorkspaceCommandSupervisor = class {
308
344
  });
309
345
  return;
310
346
  }
347
+ if (gitState === "ready") this.reportBootMilestoneFn("git_ready");
311
348
  await this.waitForSidecarsFn({
312
349
  onLog: (message) => this.forwardSetupOutput("stdout", `[sidecars] ${message}
313
350
  `),
@@ -315,8 +352,10 @@ var WorkspaceCommandSupervisor = class {
315
352
  signal: this.abortController.signal
316
353
  });
317
354
  if (this.stopped) return;
355
+ this.reportBootMilestoneFn("sidecars_ready");
318
356
  await this.runConfiguredSetup();
319
357
  if (this.stopped) return;
358
+ this.reportBootMilestoneFn("setup_complete");
320
359
  const startCommandRunning = this.config?.startCommand ? await this.ensureStartCommandLaunched(this.config.startCommand) : false;
321
360
  if (this.stopped) return;
322
361
  const forwardPorts = await this.loadForwardPortsFn(this.workspaceDir);
@@ -469,14 +508,14 @@ var WorkspaceCommandSupervisor = class {
469
508
 
470
509
  // src/utils/session-identity.ts
471
510
  async function checkSessionTaskIdentity(params) {
472
- const { sessionId, taskId, fetchSessionTaskId, logger: logger6 } = params;
511
+ const { sessionId, taskId, fetchSessionTaskId, logger: logger7 } = params;
473
512
  if (!sessionId || sessionId === taskId) return "skipped";
474
513
  let sessionTaskId;
475
514
  try {
476
515
  sessionTaskId = await fetchSessionTaskId(sessionId);
477
516
  } catch (err) {
478
517
  const message = err instanceof Error ? err.message : String(err);
479
- logger6.warn("Could not verify session/task identity \u2014 continuing (defense-in-depth only)", {
518
+ logger7.warn("Could not verify session/task identity \u2014 continuing (defense-in-depth only)", {
480
519
  sessionId,
481
520
  taskId,
482
521
  error: message
@@ -484,7 +523,7 @@ async function checkSessionTaskIdentity(params) {
484
523
  return "error";
485
524
  }
486
525
  if (sessionTaskId !== taskId) {
487
- logger6.warn(
526
+ logger7.warn(
488
527
  "!!! CONVEYOR_SESSION_ID is bound to a different task than CONVEYOR_TASK_ID \u2014 server-side guards should still block mutations, but this indicates a misconfiguration or replayed token.",
489
528
  { sessionId, envTaskId: taskId, sessionTaskId }
490
529
  );
@@ -666,20 +705,91 @@ var ProjectSessionRunner = class {
666
705
  }
667
706
  };
668
707
 
708
+ // src/usage/multi-key-probe.ts
709
+ import { mkdtemp, writeFile as writeFile2, copyFile, rm } from "fs/promises";
710
+ import { tmpdir } from "os";
711
+ import { join } from "path";
712
+ var logger = createServiceLogger("multi-key-probe");
713
+ function gaugesToSamples(stdout) {
714
+ const { sessionUsage, weeklyUsage, sessionResetsAt, weeklyResetsAt, gauges } = parseUsageGauges(stdout);
715
+ const samples = [];
716
+ if (sessionUsage !== null) {
717
+ samples.push({
718
+ rateLimitType: "five_hour",
719
+ utilization: sessionUsage,
720
+ status: "allowed",
721
+ resetsAt: sessionResetsAt,
722
+ gauges
723
+ });
724
+ }
725
+ if (weeklyUsage !== null) {
726
+ samples.push({
727
+ rateLimitType: "seven_day",
728
+ utilization: weeklyUsage,
729
+ status: "allowed",
730
+ resetsAt: weeklyResetsAt,
731
+ gauges
732
+ });
733
+ }
734
+ return samples;
735
+ }
736
+ async function isolatedProbe(token, now) {
737
+ let dir = null;
738
+ try {
739
+ dir = await mkdtemp(join(tmpdir(), "conveyor-usage-"));
740
+ await writeFile2(join(dir, ".credentials.json"), buildSynthesizedCredentials(token, now), {
741
+ encoding: "utf8",
742
+ mode: 384
743
+ });
744
+ await copyFile(claudeJsonPath(), join(dir, ".claude.json")).catch(() => {
745
+ });
746
+ return await runUsageProbe({ env: { ...process.env, CLAUDE_CONFIG_DIR: dir } });
747
+ } catch (error) {
748
+ logger.info("isolated usage probe failed", {
749
+ error: error instanceof Error ? error.message : String(error)
750
+ });
751
+ return "";
752
+ } finally {
753
+ if (dir) await rm(dir, { recursive: true, force: true }).catch(() => {
754
+ });
755
+ }
756
+ }
757
+ async function probeKeysUsage(keys, deps = {}) {
758
+ const now = deps.now ?? Date.now;
759
+ const probeOne = deps.probeOne ?? ((token) => isolatedProbe(token, now()));
760
+ const results = [];
761
+ for (const key of keys) {
762
+ if (!key.oauthToken) continue;
763
+ try {
764
+ const stdout = await probeOne(key.oauthToken);
765
+ const samples = gaugesToSamples(stdout);
766
+ if (samples.length > 0) {
767
+ results.push({ codingAgentKeyId: key.codingAgentKeyId, samples });
768
+ }
769
+ } catch (error) {
770
+ logger.info("usage probe for key failed", {
771
+ codingAgentKeyId: key.codingAgentKeyId,
772
+ error: error instanceof Error ? error.message : String(error)
773
+ });
774
+ }
775
+ }
776
+ return results;
777
+ }
778
+
669
779
  // src/harness/pty/adapters/opencode-auth.ts
670
780
  import { promises as fs } from "fs";
671
- import { dirname as dirname2, join } from "path";
781
+ import { dirname as dirname2, join as join2 } from "path";
672
782
  import { homedir } from "os";
673
- var logger = createServiceLogger("opencode-auth");
783
+ var logger2 = createServiceLogger("opencode-auth");
674
784
  var OPENCODE_CODEX_PLUGIN = "opencode-openai-codex-auth@4.4.0";
675
785
  var PLUGIN_PACKAGE = "opencode-openai-codex-auth";
676
786
  function opencodeAuthPath(env) {
677
- const dataHome = env.XDG_DATA_HOME ?? join(env.HOME ?? homedir(), ".local", "share");
678
- return join(dataHome, "opencode", "auth.json");
787
+ const dataHome = env.XDG_DATA_HOME ?? join2(env.HOME ?? homedir(), ".local", "share");
788
+ return join2(dataHome, "opencode", "auth.json");
679
789
  }
680
790
  function opencodeConfigPath(env) {
681
- const configHome = env.XDG_CONFIG_HOME ?? join(env.HOME ?? homedir(), ".config");
682
- return join(configHome, "opencode", "opencode.json");
791
+ const configHome = env.XDG_CONFIG_HOME ?? join2(env.HOME ?? homedir(), ".config");
792
+ return join2(configHome, "opencode", "opencode.json");
683
793
  }
684
794
  function parseOauthSeed(b64) {
685
795
  if (!b64) return null;
@@ -717,7 +827,7 @@ async function ensureAuthEntry(env, seed) {
717
827
  const path = opencodeAuthPath(env);
718
828
  const store = await readJsonFile(path);
719
829
  if (!shouldSeed(store.openai, seed)) {
720
- logger.info("opencode oauth store is fresher than the seed; leaving it alone");
830
+ logger2.info("opencode oauth store is fresher than the seed; leaving it alone");
721
831
  return;
722
832
  }
723
833
  store.openai = {
@@ -727,7 +837,7 @@ async function ensureAuthEntry(env, seed) {
727
837
  expires: seed.expires
728
838
  };
729
839
  await writeJsonFile(path, store);
730
- logger.info("seeded opencode oauth store entry");
840
+ logger2.info("seeded opencode oauth store entry");
731
841
  }
732
842
  async function ensurePluginConfig(env) {
733
843
  const path = opencodeConfigPath(env);
@@ -740,7 +850,7 @@ async function ensurePluginConfig(env) {
740
850
  const kept = plugins.filter((p) => !isOurs(p));
741
851
  config.plugin = [...kept, OPENCODE_CODEX_PLUGIN];
742
852
  await writeJsonFile(path, config);
743
- logger.info("ensured opencode codex-auth plugin in config");
853
+ logger2.info("ensured opencode codex-auth plugin in config");
744
854
  }
745
855
  async function seedOpenCodeOauth(env) {
746
856
  const seed = parseOauthSeed(env.CONVEYOR_OPENCODE_OAUTH);
@@ -749,7 +859,7 @@ async function seedOpenCodeOauth(env) {
749
859
  await ensureAuthEntry(env, seed);
750
860
  await ensurePluginConfig(env);
751
861
  } catch (err) {
752
- logger.warn(
862
+ logger2.warn(
753
863
  `failed to seed opencode oauth store: ${err instanceof Error ? err.message : String(err)}`
754
864
  );
755
865
  }
@@ -1182,7 +1292,7 @@ var AdhocSessionRunner = class {
1182
1292
  }),
1183
1293
  onGitFlush: () => {
1184
1294
  },
1185
- onUsageSample: () => void this.sampleAndReportKeyUsage()
1295
+ onUsageSample: () => void this.sampleAndReportAllKeys()
1186
1296
  }
1187
1297
  );
1188
1298
  }
@@ -1202,6 +1312,7 @@ var AdhocSessionRunner = class {
1202
1312
  projectId: this.config.projectId
1203
1313
  });
1204
1314
  this.connection.onStop(() => this.requestStop());
1315
+ this.connection.onProbeUsage(() => void this.sampleAndReportAllKeys());
1205
1316
  this.lifecycle.startHeartbeat();
1206
1317
  this.lifecycle.startTokenRefresh();
1207
1318
  this.lifecycle.startUsageSample();
@@ -1289,7 +1400,44 @@ var AdhocSessionRunner = class {
1289
1400
  resolve();
1290
1401
  }
1291
1402
  }
1292
- async sampleAndReportKeyUsage() {
1403
+ /**
1404
+ * Multi-key usage refresh: ask the server for every subscription key the
1405
+ * OWNER has, probe each one's `/usage` from THIS pod (isolated per key), and
1406
+ * report each key's gauges tagged with its explicit `codingAgentKeyId`. Falls
1407
+ * back to the single-key self-sample when the owner has no probeable keys
1408
+ * (e.g. API-key-only, or all decrypts failed). Best-effort — never throws.
1409
+ */
1410
+ async sampleAndReportAllKeys() {
1411
+ if (this.stopped) return;
1412
+ let keys = [];
1413
+ try {
1414
+ const res = await this.connection.call("listKeysToProbe", {
1415
+ sessionId: this.config.connection.sessionId
1416
+ });
1417
+ keys = res?.keys ?? [];
1418
+ } catch {
1419
+ }
1420
+ if (keys.length === 0) {
1421
+ await this.sampleAndReportOwnKey();
1422
+ return;
1423
+ }
1424
+ const probed = await probeKeysUsage(keys);
1425
+ for (const { codingAgentKeyId, samples } of probed) {
1426
+ for (const sample of samples) {
1427
+ this.connection.sendEvent({
1428
+ type: "rate_limit_update",
1429
+ rateLimitType: sample.rateLimitType,
1430
+ utilization: sample.utilization,
1431
+ status: sample.status,
1432
+ resetsAt: sample.resetsAt ?? void 0,
1433
+ gauges: sample.gauges,
1434
+ codingAgentKeyId
1435
+ });
1436
+ }
1437
+ }
1438
+ }
1439
+ /** Single-key fallback: sample only the key this pod booted under. */
1440
+ async sampleAndReportOwnKey() {
1293
1441
  if (this.stopped) return;
1294
1442
  const samples = await sampleKeyUsage(process.env.CLAUDE_CODE_OAUTH_TOKEN);
1295
1443
  for (const sample of samples) {
@@ -1317,7 +1465,7 @@ var AdhocSessionRunner = class {
1317
1465
  import { spawn as nodeSpawn, execFile } from "child_process";
1318
1466
  import { promisify } from "util";
1319
1467
  var execFileAsync = promisify(execFile);
1320
- var logger2 = createServiceLogger("ReviewChild");
1468
+ var logger3 = createServiceLogger("ReviewChild");
1321
1469
  var SPAWN_FAILURE_GRACE_MS = 15e3;
1322
1470
  var KILL_WAIT_MS = 5e3;
1323
1471
  function buildReviewChildEnv(baseEnv, data) {
@@ -1346,7 +1494,7 @@ var ReviewChildSupervisor = class {
1346
1494
  childSessionId = null;
1347
1495
  /** Spawn (or replace) the review child for a `session:spawnReview` push. */
1348
1496
  async spawn(data) {
1349
- logger2.info("Spawning same-pod review child", {
1497
+ logger3.info("Spawning same-pod review child", {
1350
1498
  reviewSessionId: data.sessionId,
1351
1499
  branch: data.branch ?? void 0,
1352
1500
  prNumber: data.prNumber ?? void 0
@@ -1389,7 +1537,7 @@ var ReviewChildSupervisor = class {
1389
1537
  process.stderr.write(`[review-child] ${chunk.toString()}`);
1390
1538
  });
1391
1539
  child.on("error", (err) => {
1392
- logger2.error("Review child spawn error", { error: err.message });
1540
+ logger3.error("Review child spawn error", { error: err.message });
1393
1541
  if (this.child === child) {
1394
1542
  this.child = null;
1395
1543
  this.childSessionId = null;
@@ -1402,7 +1550,7 @@ var ReviewChildSupervisor = class {
1402
1550
  this.child = null;
1403
1551
  this.childSessionId = null;
1404
1552
  }
1405
- logger2.info("Review child exited", { code, signal, reviewSessionId: data.sessionId });
1553
+ logger3.info("Review child exited", { code, signal, reviewSessionId: data.sessionId });
1406
1554
  const withinGrace = Date.now() - spawnedAt < SPAWN_FAILURE_GRACE_MS;
1407
1555
  if (wasCurrent && withinGrace && code !== null && code !== 0) {
1408
1556
  reportOnce(`review child exited with code ${code} within startup grace`);
@@ -1420,7 +1568,7 @@ var ReviewChildSupervisor = class {
1420
1568
  this.childSessionId = null;
1421
1569
  return;
1422
1570
  }
1423
- logger2.info("Stopping review child", { reason, reviewSessionId: this.childSessionId });
1571
+ logger3.info("Stopping review child", { reason, reviewSessionId: this.childSessionId });
1424
1572
  this.child = null;
1425
1573
  this.childSessionId = null;
1426
1574
  await new Promise((resolve) => {
@@ -1462,7 +1610,7 @@ var ReviewChildSupervisor = class {
1462
1610
  timeout: 3e4
1463
1611
  });
1464
1612
  } catch (err) {
1465
- logger2.warn("Review checkout freshen skipped", {
1613
+ logger3.warn("Review checkout freshen skipped", {
1466
1614
  branch,
1467
1615
  error: err instanceof Error ? err.message : String(err)
1468
1616
  });
@@ -1472,7 +1620,7 @@ var ReviewChildSupervisor = class {
1472
1620
 
1473
1621
  // src/runner/session-child.ts
1474
1622
  import { spawn as nodeSpawn2 } from "child_process";
1475
- var logger3 = createServiceLogger("SessionChild");
1623
+ var logger4 = createServiceLogger("SessionChild");
1476
1624
  function buildSpawnedChildEnv(baseEnv, data) {
1477
1625
  const env = { ...baseEnv };
1478
1626
  env.CONVEYOR_TASK_TOKEN = data.sessionJwt;
@@ -1503,7 +1651,7 @@ var SessionChildSupervisor = class {
1503
1651
  }
1504
1652
  /** Spawn a TUI/shell child for a `session:spawnTui` push. Additive per session. */
1505
1653
  async spawn(data) {
1506
- logger3.info("Spawning same-pod session child", {
1654
+ logger4.info("Spawning same-pod session child", {
1507
1655
  spawnedSessionId: data.sessionId,
1508
1656
  mode: data.mode
1509
1657
  });
@@ -1544,7 +1692,7 @@ var SessionChildSupervisor = class {
1544
1692
  process.stderr.write(`${prefix} ${chunk.toString()}`);
1545
1693
  });
1546
1694
  child.on("error", (err) => {
1547
- logger3.error("Session child spawn error", { error: err.message });
1695
+ logger4.error("Session child spawn error", { error: err.message });
1548
1696
  if (this.children.get(data.sessionId) === child) {
1549
1697
  this.children.delete(data.sessionId);
1550
1698
  }
@@ -1553,7 +1701,7 @@ var SessionChildSupervisor = class {
1553
1701
  child.on("exit", (code, signal) => {
1554
1702
  const wasCurrent = this.children.get(data.sessionId) === child;
1555
1703
  if (wasCurrent) this.children.delete(data.sessionId);
1556
- logger3.info("Session child exited", {
1704
+ logger4.info("Session child exited", {
1557
1705
  code,
1558
1706
  signal,
1559
1707
  spawnedSessionId: data.sessionId,
@@ -1574,7 +1722,7 @@ var SessionChildSupervisor = class {
1574
1722
  const child = this.children.get(sessionId);
1575
1723
  this.children.delete(sessionId);
1576
1724
  if (!child || child.exitCode !== null || child.killed) return;
1577
- logger3.info("Stopping session child", { reason, spawnedSessionId: sessionId });
1725
+ logger4.info("Stopping session child", { reason, spawnedSessionId: sessionId });
1578
1726
  await new Promise((resolve) => {
1579
1727
  const timer = setTimeout(() => {
1580
1728
  try {
@@ -1722,7 +1870,7 @@ var ShellSessionRunner = class {
1722
1870
  };
1723
1871
 
1724
1872
  // src/runner/spawned-child-boot.ts
1725
- var logger4 = createServiceLogger("SpawnedChildBoot");
1873
+ var logger5 = createServiceLogger("SpawnedChildBoot");
1726
1874
  function createSpawnedChildRunner(inputs) {
1727
1875
  if (inputs.mode === "shell") {
1728
1876
  return new ShellSessionRunner({
@@ -1752,7 +1900,7 @@ function createSpawnedChildRunner(inputs) {
1752
1900
  },
1753
1901
  {
1754
1902
  onEvent: (event) => {
1755
- logger4.info("Spawned TUI event", { eventType: event.type });
1903
+ logger5.info("Spawned TUI event", { eventType: event.type });
1756
1904
  }
1757
1905
  }
1758
1906
  );
@@ -1761,12 +1909,12 @@ function createSpawnedChildRunner(inputs) {
1761
1909
  // src/cli.ts
1762
1910
  if (process.argv.includes("--version")) {
1763
1911
  const __dirname = dirname3(fileURLToPath(import.meta.url));
1764
- const pkgPath = join2(__dirname, "..", "package.json");
1912
+ const pkgPath = join3(__dirname, "..", "package.json");
1765
1913
  const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
1766
1914
  process.stdout.write(pkg.version + "\n");
1767
1915
  process.exit(0);
1768
1916
  }
1769
- var logger5 = createServiceLogger("CLI");
1917
+ var logger6 = createServiceLogger("CLI");
1770
1918
  var exitContext = {};
1771
1919
  var exitLogged = false;
1772
1920
  function logAgentExit(reason, opts) {
@@ -1780,12 +1928,12 @@ function logAgentExit(reason, opts) {
1780
1928
  uptimeSec: process.uptime(),
1781
1929
  identity: exitContext
1782
1930
  });
1783
- logger5[exitLogLevel(reason)]("agent_exit", payload);
1931
+ logger6[exitLogLevel(reason)]("agent_exit", payload);
1784
1932
  }
1785
1933
  async function bootstrapFromCodespace(apiUrl, instanceName) {
1786
1934
  const bootstrapToken = process.env.CONVEYOR_BOOTSTRAP_TOKEN;
1787
1935
  const apiUrlFromEnv = Boolean(process.env.CONVEYOR_API_URL);
1788
- logger5.info("Bootstrapping from codespace", {
1936
+ logger6.info("Bootstrapping from codespace", {
1789
1937
  codespace: instanceName,
1790
1938
  apiUrl,
1791
1939
  apiUrlFromEnv,
@@ -1797,7 +1945,7 @@ async function bootstrapFromCodespace(apiUrl, instanceName) {
1797
1945
  bootstrapToken
1798
1946
  });
1799
1947
  if (!result.ok) {
1800
- logger5.error("Bootstrap failed after retries", {
1948
+ logger6.error("Bootstrap failed after retries", {
1801
1949
  reason: result.reason,
1802
1950
  attempts: result.attempts,
1803
1951
  status: result.status,
@@ -1810,7 +1958,7 @@ async function bootstrapFromCodespace(apiUrl, instanceName) {
1810
1958
  process.exit(1);
1811
1959
  }
1812
1960
  applyBootstrapToEnv(result.config);
1813
- logger5.info("Bootstrap complete", {
1961
+ logger6.info("Bootstrap complete", {
1814
1962
  taskId: result.config.taskId,
1815
1963
  attempts: result.attempts
1816
1964
  });
@@ -1824,20 +1972,20 @@ function isExpectedAbortError(error) {
1824
1972
  process.on("uncaughtException", (err) => {
1825
1973
  if (err.code === "EPIPE") return;
1826
1974
  if (isExpectedAbortError(err)) {
1827
- logger5.info("Ignored expected abort after shutdown", { error: err.message, code: err.code });
1975
+ logger6.info("Ignored expected abort after shutdown", { error: err.message, code: err.code });
1828
1976
  return;
1829
1977
  }
1830
- logger5.error("Uncaught exception", { error: err.message, code: err.code });
1978
+ logger6.error("Uncaught exception", { error: err.message, code: err.code });
1831
1979
  logAgentExit("uncaught_exception", { exitCode: 1 });
1832
1980
  process.exit(1);
1833
1981
  });
1834
1982
  process.on("unhandledRejection", (reason) => {
1835
1983
  const err = reason instanceof Error ? reason : new Error(String(reason));
1836
1984
  if (isExpectedAbortError(err)) {
1837
- logger5.info("Ignored expected abort rejection after shutdown", { error: err.message });
1985
+ logger6.info("Ignored expected abort rejection after shutdown", { error: err.message });
1838
1986
  return;
1839
1987
  }
1840
- logger5.error("Unhandled rejection", { error: err.message });
1988
+ logger6.error("Unhandled rejection", { error: err.message });
1841
1989
  logAgentExit("unhandled_rejection", { exitCode: 1 });
1842
1990
  process.exit(1);
1843
1991
  });
@@ -1846,7 +1994,7 @@ var conveyorApiUrl = process.env.CONVEYOR_API_URL || DEFAULT_CONVEYOR_API_URL;
1846
1994
  var INSTANCE_NAME = process.env.CODESPACE_NAME || process.env.CLAUDESPACE_NAME;
1847
1995
  if (INSTANCE_NAME && !process.env.CONVEYOR_TASK_TOKEN) {
1848
1996
  if (!conveyorApiUrl) {
1849
- logger5.error("Could not resolve CONVEYOR_API_URL for codespace bootstrap");
1997
+ logger6.error("Could not resolve CONVEYOR_API_URL for codespace bootstrap");
1850
1998
  process.exit(1);
1851
1999
  }
1852
2000
  await bootstrapFromCodespace(conveyorApiUrl, INSTANCE_NAME);
@@ -1864,7 +2012,7 @@ exitContext.runnerMode = CONVEYOR_MODE;
1864
2012
  exitContext.sessionId = process.env.CONVEYOR_SESSION_ID ?? CONVEYOR_TASK_ID;
1865
2013
  var projectIdentity = resolveProjectRunnerIdentity(process.env);
1866
2014
  if (!CONVEYOR_TASK_ID && projectIdentity && CONVEYOR_MODE === "adhoc") {
1867
- logger5.info("Starting ad-hoc agent", { projectId: projectIdentity.projectId });
2015
+ logger6.info("Starting ad-hoc agent", { projectId: projectIdentity.projectId });
1868
2016
  const adhocRunner = new AdhocSessionRunner(
1869
2017
  {
1870
2018
  connection: {
@@ -1883,7 +2031,7 @@ if (!CONVEYOR_TASK_ID && projectIdentity && CONVEYOR_MODE === "adhoc") {
1883
2031
  },
1884
2032
  {
1885
2033
  onEvent: (event) => {
1886
- logger5.info("Ad-hoc runner event", { eventType: event.type });
2034
+ logger6.info("Ad-hoc runner event", { eventType: event.type });
1887
2035
  }
1888
2036
  }
1889
2037
  );
@@ -1901,7 +2049,7 @@ if (!CONVEYOR_TASK_ID && projectIdentity && CONVEYOR_MODE === "adhoc") {
1901
2049
  process.exit(adhocError ? 1 : 0);
1902
2050
  }
1903
2051
  if (!CONVEYOR_TASK_ID && projectIdentity) {
1904
- logger5.info("Starting project agent", { projectId: projectIdentity.projectId });
2052
+ logger6.info("Starting project agent", { projectId: projectIdentity.projectId });
1905
2053
  const projectRunner = new ProjectSessionRunner(
1906
2054
  {
1907
2055
  connection: {
@@ -1916,7 +2064,7 @@ if (!CONVEYOR_TASK_ID && projectIdentity) {
1916
2064
  },
1917
2065
  {
1918
2066
  onEvent: (event) => {
1919
- logger5.info("Project runner event", { eventType: event.type });
2067
+ logger6.info("Project runner event", { eventType: event.type });
1920
2068
  }
1921
2069
  }
1922
2070
  );
@@ -1934,22 +2082,22 @@ if (!CONVEYOR_TASK_ID && projectIdentity) {
1934
2082
  process.exit(projectError ? 1 : 0);
1935
2083
  }
1936
2084
  if (!CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {
1937
- logger5.error("Missing required environment variables");
1938
- logger5.error(" CONVEYOR_TASK_TOKEN - JWT token for task authentication");
1939
- logger5.error(" CONVEYOR_TASK_ID - ID of the task to execute");
1940
- logger5.error("");
1941
- logger5.error("CONVEYOR_API_URL is provided via codespace secret or bootstrap.");
1942
- logger5.error("");
1943
- logger5.error("Optional:");
1944
- logger5.error(" CONVEYOR_MODE - Runner mode: 'task' (default), 'pack', or 'pm'");
1945
- logger5.error(" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)");
1946
- logger5.error(
2085
+ logger6.error("Missing required environment variables");
2086
+ logger6.error(" CONVEYOR_TASK_TOKEN - JWT token for task authentication");
2087
+ logger6.error(" CONVEYOR_TASK_ID - ID of the task to execute");
2088
+ logger6.error("");
2089
+ logger6.error("CONVEYOR_API_URL is provided via codespace secret or bootstrap.");
2090
+ logger6.error("");
2091
+ logger6.error("Optional:");
2092
+ logger6.error(" CONVEYOR_MODE - Runner mode: 'task' (default), 'pack', or 'pm'");
2093
+ logger6.error(" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)");
2094
+ logger6.error(
1947
2095
  " Project pods instead require CONVEYOR_PROJECT_ID + CONVEYOR_SESSION_ID + CONVEYOR_MODE=pm"
1948
2096
  );
1949
2097
  process.exit(1);
1950
2098
  }
1951
2099
  if (CONVEYOR_MODE !== "task" && CONVEYOR_MODE !== "pm" && CONVEYOR_MODE !== "code-review" && CONVEYOR_MODE !== "adhoc" && CONVEYOR_MODE !== "pack" && CONVEYOR_MODE !== "shell") {
1952
- logger5.error("Invalid CONVEYOR_MODE", {
2100
+ logger6.error("Invalid CONVEYOR_MODE", {
1953
2101
  mode: CONVEYOR_MODE,
1954
2102
  expected: ["task", "pm", "code-review", "adhoc", "pack", "shell"]
1955
2103
  });
@@ -1958,7 +2106,7 @@ if (CONVEYOR_MODE !== "task" && CONVEYOR_MODE !== "pm" && CONVEYOR_MODE !== "cod
1958
2106
  if (CONVEYOR_MODE === "shell" || CONVEYOR_MODE === "adhoc") {
1959
2107
  const spawnedSessionId = process.env.CONVEYOR_SESSION_ID;
1960
2108
  if (!spawnedSessionId) {
1961
- logger5.error("Spawned child requires CONVEYOR_SESSION_ID", { mode: CONVEYOR_MODE });
2109
+ logger6.error("Spawned child requires CONVEYOR_SESSION_ID", { mode: CONVEYOR_MODE });
1962
2110
  process.exit(1);
1963
2111
  }
1964
2112
  exitContext.sessionId = spawnedSessionId;
@@ -1971,7 +2119,7 @@ if (CONVEYOR_MODE === "shell" || CONVEYOR_MODE === "adhoc") {
1971
2119
  workspaceDir: CONVEYOR_WORKSPACE,
1972
2120
  projectId: process.env.CONVEYOR_PROJECT_ID ?? ""
1973
2121
  });
1974
- logger5.info("Starting spawned session child", {
2122
+ logger6.info("Starting spawned session child", {
1975
2123
  mode: CONVEYOR_MODE,
1976
2124
  sessionId: spawnedSessionId
1977
2125
  });
@@ -1985,7 +2133,7 @@ if (CONVEYOR_MODE === "shell" || CONVEYOR_MODE === "adhoc") {
1985
2133
  });
1986
2134
  process.exit(childError ? 1 : 0);
1987
2135
  }
1988
- logger5.info("Starting agent", { mode: CONVEYOR_MODE });
2136
+ logger6.info("Starting agent", { mode: CONVEYOR_MODE });
1989
2137
  var lifecycleOverrides = process.env.CLAUDESPACE_NAME ? { idleTimeoutMs: 60 * 60 * 1e3 } : { gitFlushIntervalMs: 0 };
1990
2138
  var runner = new SessionRunner(
1991
2139
  {
@@ -2005,12 +2153,12 @@ var runner = new SessionRunner(
2005
2153
  },
2006
2154
  {
2007
2155
  onStatusChange: (status) => {
2008
- logger5.info("Status changed", { status });
2156
+ logger6.info("Status changed", { status });
2009
2157
  },
2010
2158
  onEvent: (event) => {
2011
2159
  const detail = event.message ?? event.content ?? event.summary ?? "";
2012
2160
  if (detail) {
2013
- logger5.info(detail, { eventType: event.type });
2161
+ logger6.info(detail, { eventType: event.type });
2014
2162
  }
2015
2163
  }
2016
2164
  }
@@ -2021,7 +2169,7 @@ var shutdownSignal;
2021
2169
  var workspaceCommandSupervisor = null;
2022
2170
  var shutdownCompletion = null;
2023
2171
  var shutdownAgent = (signal) => {
2024
- logger5.info(`Received ${signal}, flushing git and stopping agent`);
2172
+ logger6.info(`Received ${signal}, flushing git and stopping agent`);
2025
2173
  const commandShutdown = stopWorkspaceCommands(workspaceCommandSupervisor);
2026
2174
  shutdownSignal = signal;
2027
2175
  shutdownCompletion ??= (async () => {
@@ -2038,8 +2186,8 @@ var shutdownAgent = (signal) => {
2038
2186
  })();
2039
2187
  void shutdownCompletion;
2040
2188
  setTimeout(() => {
2041
- logger5.warn(`Forcing exit after ${signal} timeout`);
2042
- logger5.warn(
2189
+ logger6.warn(`Forcing exit after ${signal} timeout`);
2190
+ logger6.warn(
2043
2191
  "agent_exit",
2044
2192
  buildAgentExitLog({
2045
2193
  reason: "force_timeout",
@@ -2065,7 +2213,7 @@ workspaceCommandSupervisor = await startWorkspaceCommandsAfterConnect({
2065
2213
  })
2066
2214
  });
2067
2215
  if (!workspaceCommandSupervisor) {
2068
- logger5.info("Agent stopped before workspace commands were started");
2216
+ logger6.info("Agent stopped before workspace commands were started");
2069
2217
  if (shutdownCompletion) await shutdownCompletion;
2070
2218
  logAgentExit(shutdownSignal ? "signal" : "clean", {
2071
2219
  exitCode: 0,
@@ -2081,12 +2229,12 @@ void checkSessionTaskIdentity({
2081
2229
  const ctx = await runner.connection.call("getTaskContext", { sessionId });
2082
2230
  return ctx.id;
2083
2231
  },
2084
- logger: logger5
2232
+ logger: logger6
2085
2233
  });
2086
2234
  if (CONVEYOR_MODE === "task") {
2087
2235
  runner.connection.onSpawnReview((data) => {
2088
2236
  void reviewChildren.spawn(data).catch((err) => {
2089
- logger5.error("Review child spawn threw", {
2237
+ logger6.error("Review child spawn threw", {
2090
2238
  error: err instanceof Error ? err.message : String(err)
2091
2239
  });
2092
2240
  runner.connection.reportReviewSpawnFailure(
@@ -2099,7 +2247,7 @@ if (CONVEYOR_MODE === "task") {
2099
2247
  if (CONVEYOR_MODE === "task" || CONVEYOR_MODE === "pack") {
2100
2248
  runner.connection.onSpawnTui((data) => {
2101
2249
  void sessionChildren.spawn(data).catch((err) => {
2102
- logger5.error("Session child spawn threw", {
2250
+ logger6.error("Session child spawn threw", {
2103
2251
  error: err instanceof Error ? err.message : String(err)
2104
2252
  });
2105
2253
  runner.connection.reportSessionSpawnFailure(
@@ -2122,7 +2270,7 @@ runner.run().then(async () => {
2122
2270
  }).catch(async (error) => {
2123
2271
  await stopWorkspaceCommands(workspaceCommandSupervisor);
2124
2272
  const msg = error instanceof Error ? error.message : String(error);
2125
- logger5.error("Agent runner failed", { error: msg });
2273
+ logger6.error("Agent runner failed", { error: msg });
2126
2274
  logAgentExit("error", { exitCode: 1, finalState: runner.finalState ?? void 0 });
2127
2275
  process.exit(1);
2128
2276
  });