codeam-cli 2.56.0 → 2.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/index.js +482 -585
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -610,10 +610,167 @@ OUTPUT JSON ONLY. NO MARKDOWN. NO COMMENTARY.
610
610
  `.trim();
611
611
 
612
612
  // src/config.ts
613
+ var fs3 = __toESM(require("fs"));
614
+ var os2 = __toESM(require("os"));
615
+ var path2 = __toESM(require("path"));
616
+ var crypto = __toESM(require("crypto"));
617
+
618
+ // src/lib/quiet.ts
619
+ var fs2 = __toESM(require("fs"));
620
+
621
+ // src/services/logger.ts
613
622
  var fs = __toESM(require("fs"));
614
623
  var os = __toESM(require("os"));
615
624
  var path = __toESM(require("path"));
616
- var crypto = __toESM(require("crypto"));
625
+ var LEVELS = { silent: 0, error: 1, warn: 2, info: 3, debug: 4, trace: 5 };
626
+ var MAX_LOG_BYTES = 5 * 1024 * 1024;
627
+ var MAX_ARCHIVES = 5;
628
+ function currentLevel() {
629
+ if (process.env.CODEAM_DEBUG === "1") return LEVELS.trace;
630
+ const raw = (process.env.CODEAM_LOG ?? "error").toLowerCase();
631
+ return LEVELS[raw] ?? LEVELS.error;
632
+ }
633
+ var verboseFileEnabled = process.env.CODEAM_DEBUG === "1" || process.env.CODEAM_LOG === "debug" || process.env.CODEAM_LOG === "trace";
634
+ var jsonMode = process.env.CODEAM_LOG_JSON === "1";
635
+ function resolveLogDir() {
636
+ if (process.platform === "linux") {
637
+ const xdgState = process.env.XDG_STATE_HOME;
638
+ if (xdgState && xdgState.length > 0) return path.join(xdgState, "codeam");
639
+ }
640
+ if (process.platform === "win32") {
641
+ const local = process.env.LOCALAPPDATA;
642
+ if (local && local.length > 0) return path.join(local, "codeam", "Logs");
643
+ }
644
+ return path.join(os.homedir(), ".codeam");
645
+ }
646
+ var LOG_DIR = resolveLogDir();
647
+ var debugFilePath = path.join(LOG_DIR, `debug-${process.pid}.log`);
648
+ var fileInitialized = false;
649
+ function maybeRotate() {
650
+ try {
651
+ const st3 = fs.statSync(debugFilePath);
652
+ if (st3.size < MAX_LOG_BYTES) return;
653
+ } catch {
654
+ return;
655
+ }
656
+ const archivePath = (n) => n === 0 ? `${debugFilePath}.old` : `${debugFilePath}.${n}`;
657
+ for (let i = MAX_ARCHIVES - 1; i >= 0; i--) {
658
+ const src = archivePath(i);
659
+ const dst = archivePath(i + 1);
660
+ try {
661
+ fs.renameSync(src, dst);
662
+ } catch {
663
+ }
664
+ }
665
+ try {
666
+ fs.unlinkSync(archivePath(MAX_ARCHIVES));
667
+ } catch {
668
+ }
669
+ try {
670
+ fs.renameSync(debugFilePath, archivePath(0));
671
+ } catch {
672
+ }
673
+ fileInitialized = false;
674
+ }
675
+ function appendToFile(line) {
676
+ try {
677
+ if (!fileInitialized) {
678
+ fs.mkdirSync(path.dirname(debugFilePath), { recursive: true, mode: 448 });
679
+ const header = jsonMode ? `${JSON.stringify({
680
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
681
+ level: "info",
682
+ tag: "logger",
683
+ msg: `debug log started`,
684
+ ctx: {
685
+ pid: process.pid,
686
+ platform: process.platform,
687
+ node: process.version,
688
+ cwd: process.cwd(),
689
+ dir: LOG_DIR
690
+ }
691
+ })}
692
+ ` : `=== codeam debug log \u2014 pid ${process.pid} \u2014 ${(/* @__PURE__ */ new Date()).toISOString()} ===
693
+ platform=${process.platform} node=${process.version} cwd=${process.cwd()} dir=${LOG_DIR}
694
+
695
+ `;
696
+ const tmp = `${debugFilePath}.${process.pid}.tmp`;
697
+ fs.writeFileSync(tmp, header);
698
+ fs.renameSync(tmp, debugFilePath);
699
+ fileInitialized = true;
700
+ }
701
+ fs.appendFileSync(debugFilePath, line);
702
+ maybeRotate();
703
+ } catch {
704
+ }
705
+ }
706
+ function formatEntry(level, tag, msg, err) {
707
+ const detail = err instanceof Error ? `: ${err.message}` : err !== void 0 ? `: ${String(err)}` : "";
708
+ const text = `[codeam:${level}] ${tag} \u2014 ${msg}${detail}
709
+ `;
710
+ const entry = {
711
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
712
+ level,
713
+ tag,
714
+ msg
715
+ };
716
+ if (err !== void 0) {
717
+ entry.ctx = err instanceof Error ? { errorName: err.name, errorMessage: err.message } : { error: String(err) };
718
+ }
719
+ return { text, json: `${JSON.stringify(entry)}
720
+ ` };
721
+ }
722
+ function emit(level, tag, msg, err) {
723
+ const { text, json } = formatEntry(level, tag, msg, err);
724
+ if (LEVELS[level] <= LEVELS.info || verboseFileEnabled) {
725
+ appendToFile(jsonMode ? json : `${(/* @__PURE__ */ new Date()).toISOString()} ${text}`);
726
+ }
727
+ if (LEVELS[level] <= currentLevel()) {
728
+ process.stderr.write(jsonMode ? json : text);
729
+ }
730
+ }
731
+ var log = {
732
+ error: (tag, msg, err) => emit("error", tag, msg, err),
733
+ warn: (tag, msg, err) => emit("warn", tag, msg, err),
734
+ info: (tag, msg, err) => emit("info", tag, msg, err),
735
+ debug: (tag, msg, err) => emit("debug", tag, msg, err),
736
+ /**
737
+ * Verbose pipeline breadcrumb. Only fires when CODEAM_LOG=trace or
738
+ * CODEAM_DEBUG=1, so call sites can be liberal — they have zero
739
+ * cost in normal runs.
740
+ */
741
+ trace: (tag, msg, err) => emit("trace", tag, msg, err)
742
+ };
743
+
744
+ // src/lib/quiet.ts
745
+ var TAG = "quiet";
746
+ function quiet(fn) {
747
+ try {
748
+ fn();
749
+ } catch (err) {
750
+ log.debug(TAG, "ignored sync error", err);
751
+ }
752
+ }
753
+ function rmIfExistsQuiet(path68) {
754
+ try {
755
+ fs2.rmSync(path68, { force: true });
756
+ } catch (err) {
757
+ log.debug(TAG, `rmIfExists failed for ${path68}`, err);
758
+ }
759
+ }
760
+ function killQuiet(target, signal = "SIGTERM") {
761
+ if (target === void 0 || target === null) return;
762
+ try {
763
+ if (typeof target === "number") {
764
+ process.kill(target, signal);
765
+ } else {
766
+ target.kill(signal);
767
+ }
768
+ } catch (err) {
769
+ log.debug(TAG, "kill failed", err);
770
+ }
771
+ }
772
+
773
+ // src/config.ts
617
774
  var EMPTY_CONFIG = () => ({
618
775
  pluginId: crypto.randomUUID(),
619
776
  activeSessionId: null,
@@ -623,11 +780,11 @@ function migrateSession(s) {
623
780
  return { ...s, agent: s.agent ?? "claude" };
624
781
  }
625
782
  function makeConfig(baseDir) {
626
- const dir = path.join(baseDir ?? os.homedir(), ".codeam");
627
- const file = path.join(dir, "config.json");
783
+ const dir = path2.join(baseDir ?? os2.homedir(), ".codeam");
784
+ const file = path2.join(dir, "config.json");
628
785
  function load() {
629
786
  try {
630
- const raw = JSON.parse(fs.readFileSync(file, "utf-8"));
787
+ const raw = JSON.parse(fs3.readFileSync(file, "utf-8"));
631
788
  return {
632
789
  pluginId: typeof raw.pluginId === "string" ? raw.pluginId : crypto.randomUUID(),
633
790
  activeSessionId: typeof raw.activeSessionId === "string" ? raw.activeSessionId : null,
@@ -639,19 +796,16 @@ function makeConfig(baseDir) {
639
796
  }
640
797
  }
641
798
  function save(c2) {
642
- fs.mkdirSync(dir, { recursive: true, mode: 448 });
799
+ fs3.mkdirSync(dir, { recursive: true, mode: 448 });
643
800
  const tmp = `${file}.${process.pid}.${crypto.randomBytes(4).toString("hex")}.tmp`;
644
801
  try {
645
- fs.writeFileSync(tmp, JSON.stringify(c2, null, 2), {
802
+ fs3.writeFileSync(tmp, JSON.stringify(c2, null, 2), {
646
803
  encoding: "utf-8",
647
804
  mode: 384
648
805
  });
649
- fs.renameSync(tmp, file);
806
+ fs3.renameSync(tmp, file);
650
807
  } catch (err) {
651
- try {
652
- fs.unlinkSync(tmp);
653
- } catch {
654
- }
808
+ rmIfExistsQuiet(tmp);
655
809
  throw err;
656
810
  }
657
811
  }
@@ -709,7 +863,7 @@ function makeConfig(baseDir) {
709
863
  }
710
864
  function clearAll2() {
711
865
  try {
712
- fs.unlinkSync(file);
866
+ fs3.unlinkSync(file);
713
867
  } catch {
714
868
  }
715
869
  }
@@ -730,9 +884,9 @@ var CODESPACE_ENV_KEYS = [
730
884
  ];
731
885
  function loadCodespaceEnv() {
732
886
  try {
733
- const file = path.join(os.homedir(), ".codeam", "codespace-env.json");
734
- if (!fs.existsSync(file)) return;
735
- const raw = JSON.parse(fs.readFileSync(file, "utf-8"));
887
+ const file = path2.join(os2.homedir(), ".codeam", "codespace-env.json");
888
+ if (!fs3.existsSync(file)) return;
889
+ const raw = JSON.parse(fs3.readFileSync(file, "utf-8"));
736
890
  for (const key of CODESPACE_ENV_KEYS) {
737
891
  const value = raw[key];
738
892
  if (typeof value === "string" && value.length > 0 && process.env[key] === void 0) {
@@ -746,13 +900,13 @@ var _default = makeConfig();
746
900
  var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, setDisable1mContext, clearAll, saveCliConfig, loadCliConfig } = _default;
747
901
 
748
902
  // src/commands/pair-auto.ts
749
- var fs50 = __toESM(require("fs"));
903
+ var fs51 = __toESM(require("fs"));
750
904
  var os40 = __toESM(require("os"));
751
905
  var path54 = __toESM(require("path"));
752
906
  var import_crypto4 = require("crypto");
753
907
 
754
908
  // src/services/telemetry.service.ts
755
- var fs3 = __toESM(require("fs"));
909
+ var fs4 = __toESM(require("fs"));
756
910
  var path3 = __toESM(require("path"));
757
911
  var os3 = __toESM(require("os"));
758
912
  var import_node_crypto = require("crypto");
@@ -5468,129 +5622,6 @@ var PostHog = class extends PostHogBackendClient {
5468
5622
  }
5469
5623
  };
5470
5624
 
5471
- // src/services/logger.ts
5472
- var fs2 = __toESM(require("fs"));
5473
- var os2 = __toESM(require("os"));
5474
- var path2 = __toESM(require("path"));
5475
- var LEVELS = { silent: 0, error: 1, warn: 2, info: 3, debug: 4, trace: 5 };
5476
- var MAX_LOG_BYTES = 5 * 1024 * 1024;
5477
- var MAX_ARCHIVES = 5;
5478
- function currentLevel() {
5479
- if (process.env.CODEAM_DEBUG === "1") return LEVELS.trace;
5480
- const raw = (process.env.CODEAM_LOG ?? "error").toLowerCase();
5481
- return LEVELS[raw] ?? LEVELS.error;
5482
- }
5483
- var verboseFileEnabled = process.env.CODEAM_DEBUG === "1" || process.env.CODEAM_LOG === "debug" || process.env.CODEAM_LOG === "trace";
5484
- var jsonMode = process.env.CODEAM_LOG_JSON === "1";
5485
- function resolveLogDir() {
5486
- if (process.platform === "linux") {
5487
- const xdgState = process.env.XDG_STATE_HOME;
5488
- if (xdgState && xdgState.length > 0) return path2.join(xdgState, "codeam");
5489
- }
5490
- if (process.platform === "win32") {
5491
- const local = process.env.LOCALAPPDATA;
5492
- if (local && local.length > 0) return path2.join(local, "codeam", "Logs");
5493
- }
5494
- return path2.join(os2.homedir(), ".codeam");
5495
- }
5496
- var LOG_DIR = resolveLogDir();
5497
- var debugFilePath = path2.join(LOG_DIR, `debug-${process.pid}.log`);
5498
- var fileInitialized = false;
5499
- function maybeRotate() {
5500
- try {
5501
- const st3 = fs2.statSync(debugFilePath);
5502
- if (st3.size < MAX_LOG_BYTES) return;
5503
- } catch {
5504
- return;
5505
- }
5506
- const archivePath = (n) => n === 0 ? `${debugFilePath}.old` : `${debugFilePath}.${n}`;
5507
- for (let i = MAX_ARCHIVES - 1; i >= 0; i--) {
5508
- const src = archivePath(i);
5509
- const dst = archivePath(i + 1);
5510
- try {
5511
- fs2.renameSync(src, dst);
5512
- } catch {
5513
- }
5514
- }
5515
- try {
5516
- fs2.unlinkSync(archivePath(MAX_ARCHIVES));
5517
- } catch {
5518
- }
5519
- try {
5520
- fs2.renameSync(debugFilePath, archivePath(0));
5521
- } catch {
5522
- }
5523
- fileInitialized = false;
5524
- }
5525
- function appendToFile(line) {
5526
- try {
5527
- if (!fileInitialized) {
5528
- fs2.mkdirSync(path2.dirname(debugFilePath), { recursive: true, mode: 448 });
5529
- const header = jsonMode ? `${JSON.stringify({
5530
- ts: (/* @__PURE__ */ new Date()).toISOString(),
5531
- level: "info",
5532
- tag: "logger",
5533
- msg: `debug log started`,
5534
- ctx: {
5535
- pid: process.pid,
5536
- platform: process.platform,
5537
- node: process.version,
5538
- cwd: process.cwd(),
5539
- dir: LOG_DIR
5540
- }
5541
- })}
5542
- ` : `=== codeam debug log \u2014 pid ${process.pid} \u2014 ${(/* @__PURE__ */ new Date()).toISOString()} ===
5543
- platform=${process.platform} node=${process.version} cwd=${process.cwd()} dir=${LOG_DIR}
5544
-
5545
- `;
5546
- const tmp = `${debugFilePath}.${process.pid}.tmp`;
5547
- fs2.writeFileSync(tmp, header);
5548
- fs2.renameSync(tmp, debugFilePath);
5549
- fileInitialized = true;
5550
- }
5551
- fs2.appendFileSync(debugFilePath, line);
5552
- maybeRotate();
5553
- } catch {
5554
- }
5555
- }
5556
- function formatEntry(level, tag, msg, err) {
5557
- const detail = err instanceof Error ? `: ${err.message}` : err !== void 0 ? `: ${String(err)}` : "";
5558
- const text = `[codeam:${level}] ${tag} \u2014 ${msg}${detail}
5559
- `;
5560
- const entry = {
5561
- ts: (/* @__PURE__ */ new Date()).toISOString(),
5562
- level,
5563
- tag,
5564
- msg
5565
- };
5566
- if (err !== void 0) {
5567
- entry.ctx = err instanceof Error ? { errorName: err.name, errorMessage: err.message } : { error: String(err) };
5568
- }
5569
- return { text, json: `${JSON.stringify(entry)}
5570
- ` };
5571
- }
5572
- function emit(level, tag, msg, err) {
5573
- const { text, json } = formatEntry(level, tag, msg, err);
5574
- if (LEVELS[level] <= LEVELS.info || verboseFileEnabled) {
5575
- appendToFile(jsonMode ? json : `${(/* @__PURE__ */ new Date()).toISOString()} ${text}`);
5576
- }
5577
- if (LEVELS[level] <= currentLevel()) {
5578
- process.stderr.write(jsonMode ? json : text);
5579
- }
5580
- }
5581
- var log = {
5582
- error: (tag, msg, err) => emit("error", tag, msg, err),
5583
- warn: (tag, msg, err) => emit("warn", tag, msg, err),
5584
- info: (tag, msg, err) => emit("info", tag, msg, err),
5585
- debug: (tag, msg, err) => emit("debug", tag, msg, err),
5586
- /**
5587
- * Verbose pipeline breadcrumb. Only fires when CODEAM_LOG=trace or
5588
- * CODEAM_DEBUG=1, so call sites can be liberal — they have zero
5589
- * cost in normal runs.
5590
- */
5591
- trace: (tag, msg, err) => emit("trace", tag, msg, err)
5592
- };
5593
-
5594
5625
  // src/services/telemetry.service.ts
5595
5626
  var ANON_FILE = path3.join(os3.homedir(), ".codeam", "anon.json");
5596
5627
  var client = null;
@@ -5605,23 +5636,23 @@ function isOptedOut() {
5605
5636
  }
5606
5637
  function readAnonId() {
5607
5638
  try {
5608
- if (fs3.existsSync(ANON_FILE)) {
5609
- const raw = JSON.parse(fs3.readFileSync(ANON_FILE, "utf8"));
5639
+ if (fs4.existsSync(ANON_FILE)) {
5640
+ const raw = JSON.parse(fs4.readFileSync(ANON_FILE, "utf8"));
5610
5641
  if (typeof raw.id === "string" && raw.id.length > 0) return raw.id;
5611
5642
  }
5612
5643
  } catch {
5613
5644
  }
5614
5645
  const id = `anon-${(0, import_node_crypto.randomUUID)()}`;
5615
5646
  try {
5616
- fs3.mkdirSync(path3.dirname(ANON_FILE), { recursive: true, mode: 448 });
5617
- fs3.writeFileSync(ANON_FILE, JSON.stringify({ id }), { mode: 384 });
5647
+ fs4.mkdirSync(path3.dirname(ANON_FILE), { recursive: true, mode: 448 });
5648
+ fs4.writeFileSync(ANON_FILE, JSON.stringify({ id }), { mode: 384 });
5618
5649
  } catch {
5619
5650
  }
5620
5651
  return id;
5621
5652
  }
5622
5653
  function superProperties() {
5623
5654
  return {
5624
- cliVersion: true ? "2.56.0" : "0.0.0-dev",
5655
+ cliVersion: true ? "2.58.0" : "0.0.0-dev",
5625
5656
  nodeVersion: process.version,
5626
5657
  platform: process.platform,
5627
5658
  arch: process.arch,
@@ -5724,9 +5755,9 @@ function maybePrintFirstRunBanner() {
5724
5755
  if (isOptedOut()) return;
5725
5756
  const marker = path3.join(os3.homedir(), ".codeam", ".telemetry-notice");
5726
5757
  try {
5727
- if (fs3.existsSync(marker)) return;
5728
- fs3.mkdirSync(path3.dirname(marker), { recursive: true, mode: 448 });
5729
- fs3.writeFileSync(marker, (/* @__PURE__ */ new Date()).toISOString());
5758
+ if (fs4.existsSync(marker)) return;
5759
+ fs4.mkdirSync(path3.dirname(marker), { recursive: true, mode: 448 });
5760
+ fs4.writeFileSync(marker, (/* @__PURE__ */ new Date()).toISOString());
5730
5761
  } catch {
5731
5762
  }
5732
5763
  process.stderr.write(
@@ -5802,7 +5833,7 @@ var os4 = __toESM(require("os"));
5802
5833
  // package.json
5803
5834
  var package_default = {
5804
5835
  name: "codeam-cli",
5805
- version: "2.56.0",
5836
+ version: "2.58.0",
5806
5837
  description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
5807
5838
  type: "commonjs",
5808
5839
  main: "dist/index.js",
@@ -6331,7 +6362,7 @@ function computePollDelay({ baseMs, failures }) {
6331
6362
  }
6332
6363
 
6333
6364
  // src/services/headroom/proxy-supervisor.ts
6334
- var fs5 = __toESM(require("fs"));
6365
+ var fs6 = __toESM(require("fs"));
6335
6366
  var os6 = __toESM(require("os"));
6336
6367
  var path5 = __toESM(require("path"));
6337
6368
 
@@ -6348,7 +6379,7 @@ function buildBudgetProxyArgs(env) {
6348
6379
 
6349
6380
  // src/services/headroom/proxy-pid.ts
6350
6381
  var import_node_child_process = require("child_process");
6351
- var fs4 = __toESM(require("fs"));
6382
+ var fs5 = __toESM(require("fs"));
6352
6383
  var os5 = __toESM(require("os"));
6353
6384
  var path4 = __toESM(require("path"));
6354
6385
  function headroomProxyPidfilePath() {
@@ -6358,15 +6389,15 @@ function writeHeadroomProxyPidfile(pid) {
6358
6389
  if (!pid) return;
6359
6390
  try {
6360
6391
  const file = headroomProxyPidfilePath();
6361
- fs4.mkdirSync(path4.dirname(file), { recursive: true, mode: 448 });
6362
- fs4.writeFileSync(file, `${pid}
6392
+ fs5.mkdirSync(path4.dirname(file), { recursive: true, mode: 448 });
6393
+ fs5.writeFileSync(file, `${pid}
6363
6394
  `, { encoding: "utf8", mode: 384 });
6364
6395
  } catch {
6365
6396
  }
6366
6397
  }
6367
6398
  function readHeadroomProxyPidfile() {
6368
6399
  try {
6369
- const pid = Number(fs4.readFileSync(headroomProxyPidfilePath(), "utf8").trim());
6400
+ const pid = Number(fs5.readFileSync(headroomProxyPidfilePath(), "utf8").trim());
6370
6401
  return Number.isInteger(pid) && pid > 0 ? pid : null;
6371
6402
  } catch {
6372
6403
  return null;
@@ -6398,7 +6429,7 @@ function killHeadroomProxy() {
6398
6429
  try {
6399
6430
  process.kill(pid, "SIGTERM");
6400
6431
  try {
6401
- fs4.rmSync(headroomProxyPidfilePath(), { force: true });
6432
+ fs5.rmSync(headroomProxyPidfilePath(), { force: true });
6402
6433
  } catch {
6403
6434
  }
6404
6435
  return;
@@ -6407,7 +6438,7 @@ function killHeadroomProxy() {
6407
6438
  }
6408
6439
  if (pid !== null) {
6409
6440
  try {
6410
- fs4.rmSync(headroomProxyPidfilePath(), { force: true });
6441
+ fs5.rmSync(headroomProxyPidfilePath(), { force: true });
6411
6442
  } catch {
6412
6443
  }
6413
6444
  }
@@ -6458,13 +6489,13 @@ function isHeadroomConfiguredReal(homeDir2 = os6.homedir()) {
6458
6489
  if (process.env.HEADROOM_ENABLED === "1") return true;
6459
6490
  const csEnv = path5.join(homeDir2, ".codeam", "codespace-env.json");
6460
6491
  try {
6461
- const j2 = JSON.parse(fs5.readFileSync(csEnv, "utf8"));
6492
+ const j2 = JSON.parse(fs6.readFileSync(csEnv, "utf8"));
6462
6493
  if (j2.HEADROOM_ENABLED === "1" || j2.HEADROOM_ENABLED === 1) return true;
6463
6494
  } catch {
6464
6495
  }
6465
6496
  const settings = path5.join(homeDir2, ".claude", "settings.json");
6466
6497
  try {
6467
- if (fs5.readFileSync(settings, "utf8").includes("127.0.0.1:8787")) return true;
6498
+ if (fs6.readFileSync(settings, "utf8").includes("127.0.0.1:8787")) return true;
6468
6499
  } catch {
6469
6500
  }
6470
6501
  return false;
@@ -6850,7 +6881,7 @@ var CommandRelayService = class {
6850
6881
  // fresh + clear the "CLI update available" banner after a self-update
6851
6882
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
6852
6883
  // pair/reconnect). Older backends ignore the extra field.
6853
- ..."2.56.0" ? { ideVersion: "2.56.0" } : {}
6884
+ ..."2.58.0" ? { ideVersion: "2.58.0" } : {}
6854
6885
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
6855
6886
  }
6856
6887
  /**
@@ -6916,7 +6947,7 @@ var CommandRelayService = class {
6916
6947
 
6917
6948
  // src/services/file-watcher.service.ts
6918
6949
  var import_child_process3 = require("child_process");
6919
- var fs6 = __toESM(require("fs"));
6950
+ var fs7 = __toESM(require("fs"));
6920
6951
  var os7 = __toESM(require("os"));
6921
6952
  var path6 = __toESM(require("path"));
6922
6953
  var import_ignore = __toESM(require("ignore"));
@@ -7117,7 +7148,7 @@ function _defaultFindGitRoot(startDir) {
7117
7148
  seen.add(dir);
7118
7149
  try {
7119
7150
  const gitPath = path6.join(dir, ".git");
7120
- const stat3 = fs6.statSync(gitPath, { throwIfNoEntry: false });
7151
+ const stat3 = fs7.statSync(gitPath, { throwIfNoEntry: false });
7121
7152
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
7122
7153
  } catch {
7123
7154
  }
@@ -7566,7 +7597,7 @@ var FileWatcherService = class {
7566
7597
  collectGitignoreFiles(repoRoot, dir, matcher) {
7567
7598
  let entries;
7568
7599
  try {
7569
- entries = fs6.readdirSync(dir, { withFileTypes: true });
7600
+ entries = fs7.readdirSync(dir, { withFileTypes: true });
7570
7601
  } catch {
7571
7602
  return;
7572
7603
  }
@@ -7575,7 +7606,7 @@ var FileWatcherService = class {
7575
7606
  );
7576
7607
  if (gitignoreEntry) {
7577
7608
  try {
7578
- const body = fs6.readFileSync(path6.join(dir, ".gitignore"), "utf8");
7609
+ const body = fs7.readFileSync(path6.join(dir, ".gitignore"), "utf8");
7579
7610
  const rel = path6.relative(repoRoot, dir).replace(/\\/g, "/");
7580
7611
  const prefixed = body.split(/\r?\n/).map((line) => {
7581
7612
  const trimmed = line.trim();
@@ -8224,7 +8255,7 @@ function closeAllTerminals() {
8224
8255
  }
8225
8256
 
8226
8257
  // src/commands/start/handlers.ts
8227
- var fs49 = __toESM(require("fs"));
8258
+ var fs50 = __toESM(require("fs"));
8228
8259
  var os39 = __toESM(require("os"));
8229
8260
  var path53 = __toESM(require("path"));
8230
8261
  var import_crypto3 = require("crypto");
@@ -8378,7 +8409,7 @@ function parsePayload2(schema, raw) {
8378
8409
  }
8379
8410
 
8380
8411
  // src/services/file-ops.service.ts
8381
- var fs7 = __toESM(require("fs/promises"));
8412
+ var fs8 = __toESM(require("fs/promises"));
8382
8413
  var path8 = __toESM(require("path"));
8383
8414
  var MAX_FILE_BYTES = 5 * 1024 * 1024;
8384
8415
  var MAX_WALK_DEPTH = 6;
@@ -8419,7 +8450,7 @@ function isUnder(parent, candidate) {
8419
8450
  }
8420
8451
  async function isExistingFile(absPath) {
8421
8452
  try {
8422
- const stat3 = await fs7.stat(absPath);
8453
+ const stat3 = await fs8.stat(absPath);
8423
8454
  return stat3.isFile();
8424
8455
  } catch {
8425
8456
  return false;
@@ -8432,7 +8463,7 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
8432
8463
  ctx.visited++;
8433
8464
  let entries = [];
8434
8465
  try {
8435
- entries = await fs7.readdir(dir, { withFileTypes: true });
8466
+ entries = await fs8.readdir(dir, { withFileTypes: true });
8436
8467
  } catch {
8437
8468
  return;
8438
8469
  }
@@ -8493,11 +8524,11 @@ async function readProjectFile(rawPath) {
8493
8524
  if (!abs) {
8494
8525
  return { error: `File not found in the project tree: ${rawPath}` };
8495
8526
  }
8496
- const stat3 = await fs7.stat(abs);
8527
+ const stat3 = await fs8.stat(abs);
8497
8528
  if (stat3.size > MAX_FILE_BYTES) {
8498
8529
  return { error: `File too large (${(stat3.size / 1024 / 1024).toFixed(1)} MB > ${MAX_FILE_BYTES / 1024 / 1024} MB).` };
8499
8530
  }
8500
- const buf = await fs7.readFile(abs);
8531
+ const buf = await fs8.readFile(abs);
8501
8532
  if (looksBinary(buf)) {
8502
8533
  return { error: "Binary file \u2014 refusing to open in a code editor." };
8503
8534
  }
@@ -8516,8 +8547,8 @@ async function writeProjectFile(rawPath, content) {
8516
8547
  if (Buffer.byteLength(content, "utf-8") > MAX_FILE_BYTES) {
8517
8548
  return { error: "Content too large." };
8518
8549
  }
8519
- await fs7.mkdir(path8.dirname(abs), { recursive: true });
8520
- await fs7.writeFile(abs, content, "utf-8");
8550
+ await fs8.mkdir(path8.dirname(abs), { recursive: true });
8551
+ await fs8.writeFile(abs, content, "utf-8");
8521
8552
  return { ok: true };
8522
8553
  } catch (e) {
8523
8554
  const msg = e instanceof Error ? e.message : "Write failed";
@@ -8528,7 +8559,7 @@ async function writeProjectFile(rawPath, content) {
8528
8559
  // src/services/project-ops.service.ts
8529
8560
  var import_child_process5 = require("child_process");
8530
8561
  var import_util = require("util");
8531
- var fs8 = __toESM(require("fs/promises"));
8562
+ var fs9 = __toESM(require("fs/promises"));
8532
8563
  var path9 = __toESM(require("path"));
8533
8564
  var execFileP = (0, import_util.promisify)(import_child_process5.execFile);
8534
8565
  var PROJECT_IGNORE = /* @__PURE__ */ new Set([
@@ -8577,7 +8608,7 @@ async function listProjectFiles(opts = {}) {
8577
8608
  }
8578
8609
  let entries = [];
8579
8610
  try {
8580
- entries = await fs8.readdir(dir, { withFileTypes: true });
8611
+ entries = await fs9.readdir(dir, { withFileTypes: true });
8581
8612
  } catch {
8582
8613
  return;
8583
8614
  }
@@ -8598,7 +8629,7 @@ async function listProjectFiles(opts = {}) {
8598
8629
  }
8599
8630
  let size = 0;
8600
8631
  try {
8601
- const st3 = await fs8.stat(full);
8632
+ const st3 = await fs9.stat(full);
8602
8633
  size = st3.size;
8603
8634
  } catch {
8604
8635
  }
@@ -8701,7 +8732,7 @@ async function gitStatus(cwd) {
8701
8732
  try {
8702
8733
  const gitDir = (await git(["rev-parse", "--git-dir"], root)).stdout.trim();
8703
8734
  const mergeHead = path9.isAbsolute(gitDir) ? path9.join(gitDir, "MERGE_HEAD") : path9.join(root, gitDir, "MERGE_HEAD");
8704
- await fs8.access(mergeHead);
8735
+ await fs9.access(mergeHead);
8705
8736
  hasMergeInProgress = true;
8706
8737
  } catch {
8707
8738
  }
@@ -8847,7 +8878,7 @@ async function jsSearchFiles(opts, cwd, cap) {
8847
8878
  }
8848
8879
  let content = "";
8849
8880
  try {
8850
- content = await fs8.readFile(path9.join(cwd, f.path), "utf8");
8881
+ content = await fs9.readFile(path9.join(cwd, f.path), "utf8");
8851
8882
  } catch {
8852
8883
  continue;
8853
8884
  }
@@ -8924,7 +8955,7 @@ function formatRemaining(expiresAt) {
8924
8955
 
8925
8956
  // src/services/apply-file-review.service.ts
8926
8957
  var import_child_process6 = require("child_process");
8927
- var fs9 = __toESM(require("fs"));
8958
+ var fs10 = __toESM(require("fs"));
8928
8959
  var path10 = __toESM(require("path"));
8929
8960
  async function applyFileReview(workingDir, filePath, action) {
8930
8961
  if (filePath.includes("..") || path10.isAbsolute(filePath)) {
@@ -8995,7 +9026,7 @@ function findGitRoot2(startDir) {
8995
9026
  if (seen.has(dir)) return null;
8996
9027
  seen.add(dir);
8997
9028
  try {
8998
- const stat3 = fs9.statSync(path10.join(dir, ".git"), { throwIfNoEntry: false });
9029
+ const stat3 = fs10.statSync(path10.join(dir, ".git"), { throwIfNoEntry: false });
8999
9030
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
9000
9031
  } catch {
9001
9032
  }
@@ -9008,7 +9039,7 @@ function findGitRoot2(startDir) {
9008
9039
 
9009
9040
  // src/commands/link.ts
9010
9041
  var import_node_crypto5 = require("crypto");
9011
- var fs27 = __toESM(require("fs"));
9042
+ var fs28 = __toESM(require("fs"));
9012
9043
  var path32 = __toESM(require("path"));
9013
9044
  var import_chokidar = __toESM(require("chokidar"));
9014
9045
  var import_picocolors2 = __toESM(require("picocolors"));
@@ -11064,7 +11095,7 @@ function parseFrame(frame, dispatch) {
11064
11095
  }
11065
11096
 
11066
11097
  // src/os/posix.ts
11067
- var fs11 = __toESM(require("fs"));
11098
+ var fs12 = __toESM(require("fs"));
11068
11099
  var os9 = __toESM(require("os"));
11069
11100
  var path13 = __toESM(require("path"));
11070
11101
  var import_node_crypto2 = require("crypto");
@@ -11089,7 +11120,7 @@ function findInPathFor(name, opts) {
11089
11120
 
11090
11121
  // src/services/pty/unix.strategy.ts
11091
11122
  var import_child_process7 = require("child_process");
11092
- var fs10 = __toESM(require("fs"));
11123
+ var fs11 = __toESM(require("fs"));
11093
11124
  var os8 = __toESM(require("os"));
11094
11125
  var path12 = __toESM(require("path"));
11095
11126
 
@@ -11174,7 +11205,7 @@ var UnixPtyStrategy = class {
11174
11205
  const cols = process.stdout.columns || 220;
11175
11206
  const rows = process.stdout.rows || 50;
11176
11207
  this.helperPath = path12.join(os8.tmpdir(), "codeam-pty-helper.py");
11177
- fs10.writeFileSync(this.helperPath, PYTHON_PTY_HELPER, { mode: 420 });
11208
+ fs11.writeFileSync(this.helperPath, PYTHON_PTY_HELPER, { mode: 420 });
11178
11209
  this.proc = (0, import_child_process7.spawn)(python, [this.helperPath, cmd, ...args2], {
11179
11210
  stdio: ["pipe", "pipe", "inherit"],
11180
11211
  cwd,
@@ -11302,10 +11333,7 @@ var UnixPtyStrategy = class {
11302
11333
  };
11303
11334
  removeTempFile() {
11304
11335
  if (this.helperPath) {
11305
- try {
11306
- fs10.unlinkSync(this.helperPath);
11307
- } catch {
11308
- }
11336
+ rmIfExistsQuiet(this.helperPath);
11309
11337
  this.helperPath = null;
11310
11338
  }
11311
11339
  }
@@ -11326,8 +11354,8 @@ var PosixOsStrategy = class {
11326
11354
  findInPath(name) {
11327
11355
  return findInPathFor(name, {
11328
11356
  candidates: () => [name],
11329
- accessFlag: fs11.constants.X_OK,
11330
- accessSync: fs11.accessSync
11357
+ accessFlag: fs12.constants.X_OK,
11358
+ accessSync: fs12.accessSync
11331
11359
  });
11332
11360
  }
11333
11361
  augmentPath(dirs) {
@@ -11355,7 +11383,7 @@ var LinuxOsStrategy = class extends PosixOsStrategy {
11355
11383
  };
11356
11384
 
11357
11385
  // src/os/win32.ts
11358
- var fs12 = __toESM(require("fs"));
11386
+ var fs13 = __toESM(require("fs"));
11359
11387
  var os10 = __toESM(require("os"));
11360
11388
  var path15 = __toESM(require("path"));
11361
11389
  var import_node_crypto3 = require("crypto");
@@ -11566,8 +11594,8 @@ var Win32OsStrategy = class {
11566
11594
  // IS the executability check. X_OK on Windows is a no-op alias
11567
11595
  // for F_OK at the libuv layer anyway, but F_OK makes intent
11568
11596
  // explicit.
11569
- accessFlag: fs12.constants.F_OK,
11570
- accessSync: fs12.accessSync
11597
+ accessFlag: fs13.constants.F_OK,
11598
+ accessSync: fs13.accessSync
11571
11599
  });
11572
11600
  }
11573
11601
  augmentPath(dirs) {
@@ -11751,7 +11779,7 @@ var import_node_child_process3 = require("child_process");
11751
11779
 
11752
11780
  // src/agents/claude/local-token.ts
11753
11781
  var import_node_child_process2 = require("child_process");
11754
- var fs13 = __toESM(require("fs"));
11782
+ var fs14 = __toESM(require("fs"));
11755
11783
  var os12 = __toESM(require("os"));
11756
11784
  var path17 = __toESM(require("path"));
11757
11785
  var import_node_util3 = require("util");
@@ -11772,8 +11800,8 @@ function claudeCredentialsPaths() {
11772
11800
  async function extractLocalClaudeToken() {
11773
11801
  const agentState = readClaudeAgentState();
11774
11802
  for (const flat of claudeCredentialsPaths()) {
11775
- if (!fs13.existsSync(flat)) continue;
11776
- const credential = fs13.readFileSync(flat, "utf8").trim();
11803
+ if (!fs14.existsSync(flat)) continue;
11804
+ const credential = fs14.readFileSync(flat, "utf8").trim();
11777
11805
  if (credential.length > 0) {
11778
11806
  return { method: "oauth", credential, source: "flat-file", agentState };
11779
11807
  }
@@ -11800,8 +11828,8 @@ function readClaudeAgentState() {
11800
11828
  const STATE_MAX_BYTES = 256 * 1024;
11801
11829
  const candidate = path17.join(os12.homedir(), ".claude.json");
11802
11830
  try {
11803
- if (!fs13.existsSync(candidate)) return void 0;
11804
- const buf = fs13.readFileSync(candidate);
11831
+ if (!fs14.existsSync(candidate)) return void 0;
11832
+ const buf = fs14.readFileSync(candidate);
11805
11833
  if (buf.length === 0 || buf.length > STATE_MAX_BYTES) return void 0;
11806
11834
  const text = buf.toString("utf8").trim();
11807
11835
  return text.length > 0 ? text : void 0;
@@ -11888,7 +11916,7 @@ function claudeLoginLauncher() {
11888
11916
  }
11889
11917
 
11890
11918
  // src/agents/claude/quota.ts
11891
- var fs14 = __toESM(require("fs"));
11919
+ var fs15 = __toESM(require("fs"));
11892
11920
  var os13 = __toESM(require("os"));
11893
11921
  var path18 = __toESM(require("path"));
11894
11922
  var import_child_process10 = require("child_process");
@@ -11954,7 +11982,7 @@ async function fetchClaudeQuota() {
11954
11982
  return;
11955
11983
  }
11956
11984
  const helperPath = path18.join(os13.tmpdir(), "codeam-quota-helper.py");
11957
- fs14.writeFileSync(helperPath, HELPER_SCRIPT, { mode: 420 });
11985
+ fs15.writeFileSync(helperPath, HELPER_SCRIPT, { mode: 420 });
11958
11986
  const python = findInPath("python3") ?? findInPath("python");
11959
11987
  if (!python) {
11960
11988
  resolve7(null);
@@ -11981,7 +12009,7 @@ async function fetchClaudeQuota() {
11981
12009
  } catch {
11982
12010
  }
11983
12011
  try {
11984
- fs14.unlinkSync(helperPath);
12012
+ fs15.unlinkSync(helperPath);
11985
12013
  } catch {
11986
12014
  }
11987
12015
  resolve7(result);
@@ -12005,17 +12033,11 @@ var import_child_process11 = require("child_process");
12005
12033
  var activeChildren = /* @__PURE__ */ new Set();
12006
12034
  function killActiveSpawnAndCaptureChildren() {
12007
12035
  for (const child of activeChildren) {
12008
- try {
12009
- child.kill("SIGTERM");
12010
- } catch {
12011
- }
12036
+ killQuiet(child);
12012
12037
  }
12013
12038
  setTimeout(() => {
12014
12039
  for (const child of activeChildren) {
12015
- try {
12016
- child.kill("SIGKILL");
12017
- } catch {
12018
- }
12040
+ killQuiet(child, "SIGKILL");
12019
12041
  }
12020
12042
  }, 250).unref?.();
12021
12043
  }
@@ -12048,10 +12070,7 @@ async function spawnAndCapture(cmd, args2, opts = {}) {
12048
12070
  opts.onStderr?.(chunk.toString("utf8"));
12049
12071
  });
12050
12072
  const timer = setTimeout(() => {
12051
- try {
12052
- child.kill("SIGKILL");
12053
- } catch {
12054
- }
12073
+ killQuiet(child, "SIGKILL");
12055
12074
  settle(null);
12056
12075
  }, timeoutMs);
12057
12076
  timer.unref();
@@ -12074,7 +12093,7 @@ async function spawnAndCapture(cmd, args2, opts = {}) {
12074
12093
  }
12075
12094
 
12076
12095
  // src/agents/claude/history.ts
12077
- var fs15 = __toESM(require("fs"));
12096
+ var fs16 = __toESM(require("fs"));
12078
12097
  var path19 = __toESM(require("path"));
12079
12098
  var os14 = __toESM(require("os"));
12080
12099
  function encodeCwd(cwd) {
@@ -12083,9 +12102,9 @@ function encodeCwd(cwd) {
12083
12102
  function resolveHistoryDir(cwd, projectsRoot) {
12084
12103
  const root = projectsRoot ?? path19.join(os14.homedir(), ".claude", "projects");
12085
12104
  const primary = path19.join(root, encodeCwd(cwd));
12086
- if (fs15.existsSync(primary)) return primary;
12105
+ if (fs16.existsSync(primary)) return primary;
12087
12106
  try {
12088
- const entries = fs15.readdirSync(root, { withFileTypes: true });
12107
+ const entries = fs16.readdirSync(root, { withFileTypes: true });
12089
12108
  const wanted = encodeCwd(cwd);
12090
12109
  for (const e of entries) {
12091
12110
  if (!e.isDirectory()) continue;
@@ -12103,13 +12122,13 @@ function getCurrentUsage(historyDir, bootTimeMs = 0) {
12103
12122
  const cutoff = bootTimeMs > 0 ? bootTimeMs - GRACE_MS : 0;
12104
12123
  let entries;
12105
12124
  try {
12106
- entries = fs15.readdirSync(historyDir, { withFileTypes: true });
12125
+ entries = fs16.readdirSync(historyDir, { withFileTypes: true });
12107
12126
  } catch {
12108
12127
  return null;
12109
12128
  }
12110
12129
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
12111
12130
  try {
12112
- const stat3 = fs15.statSync(path19.join(historyDir, e.name));
12131
+ const stat3 = fs16.statSync(path19.join(historyDir, e.name));
12113
12132
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
12114
12133
  } catch {
12115
12134
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -12119,7 +12138,7 @@ function getCurrentUsage(historyDir, bootTimeMs = 0) {
12119
12138
  const filePath = path19.join(historyDir, files[0].name);
12120
12139
  let raw;
12121
12140
  try {
12122
- raw = fs15.readFileSync(filePath, "utf8");
12141
+ raw = fs16.readFileSync(filePath, "utf8");
12123
12142
  } catch {
12124
12143
  return null;
12125
12144
  }
@@ -12164,7 +12183,7 @@ function parseHistoryFile(filePath) {
12164
12183
  const out2 = [];
12165
12184
  let raw;
12166
12185
  try {
12167
- raw = fs15.readFileSync(filePath, "utf8");
12186
+ raw = fs16.readFileSync(filePath, "utf8");
12168
12187
  } catch {
12169
12188
  return out2;
12170
12189
  }
@@ -12209,7 +12228,7 @@ function listResumableSessions(cwd) {
12209
12228
  if (!dir) return [];
12210
12229
  let entries;
12211
12230
  try {
12212
- entries = fs15.readdirSync(dir, { withFileTypes: true });
12231
+ entries = fs16.readdirSync(dir, { withFileTypes: true });
12213
12232
  } catch {
12214
12233
  return [];
12215
12234
  }
@@ -12220,12 +12239,12 @@ function listResumableSessions(cwd) {
12220
12239
  const filePath = path19.join(dir, entry.name);
12221
12240
  let timestamp = Date.now();
12222
12241
  try {
12223
- timestamp = fs15.statSync(filePath).mtimeMs;
12242
+ timestamp = fs16.statSync(filePath).mtimeMs;
12224
12243
  } catch {
12225
12244
  }
12226
12245
  let summary = "";
12227
12246
  try {
12228
- const raw = fs15.readFileSync(filePath, "utf8");
12247
+ const raw = fs16.readFileSync(filePath, "utf8");
12229
12248
  for (const line of raw.split("\n")) {
12230
12249
  if (!line.trim()) continue;
12231
12250
  try {
@@ -12388,13 +12407,13 @@ var ClaudeRuntimeStrategy = class {
12388
12407
  };
12389
12408
 
12390
12409
  // src/agents/claude/deploy.ts
12391
- var fs17 = __toESM(require("fs"));
12410
+ var fs18 = __toESM(require("fs"));
12392
12411
  var os16 = __toESM(require("os"));
12393
12412
  var path21 = __toESM(require("path"));
12394
12413
 
12395
12414
  // src/agents/claude/credentials.ts
12396
12415
  var import_child_process12 = require("child_process");
12397
- var fs16 = __toESM(require("fs"));
12416
+ var fs17 = __toESM(require("fs"));
12398
12417
  var os15 = __toESM(require("os"));
12399
12418
  var path20 = __toESM(require("path"));
12400
12419
  var import_util2 = require("util");
@@ -12402,7 +12421,7 @@ var execFileP3 = (0, import_util2.promisify)(import_child_process12.execFile);
12402
12421
  async function detectLocalClaudeCredentials() {
12403
12422
  const localClaudeDir = path20.join(os15.homedir(), ".claude");
12404
12423
  const flat = path20.join(localClaudeDir, ".credentials.json");
12405
- if (fs16.existsSync(flat)) {
12424
+ if (fs17.existsSync(flat)) {
12406
12425
  return { source: "flat-file", description: "~/.claude/.credentials.json" };
12407
12426
  }
12408
12427
  if (os15.platform() === "darwin") {
@@ -12422,7 +12441,7 @@ async function detectLocalClaudeCredentials() {
12422
12441
  async function bridgeClaudeCredentials(provider, workspaceId) {
12423
12442
  const localClaudeDir = path20.join(os15.homedir(), ".claude");
12424
12443
  const fileBased = path20.join(localClaudeDir, ".credentials.json");
12425
- if (fs16.existsSync(fileBased)) {
12444
+ if (fs17.existsSync(fileBased)) {
12426
12445
  return { source: "flat-file", description: "~/.claude/.credentials.json" };
12427
12446
  }
12428
12447
  if (process.platform === "darwin") {
@@ -12515,7 +12534,7 @@ var ClaudeDeployStrategy = class {
12515
12534
  }
12516
12535
  claudeStep.stop("\u2713 Claude CLI installed");
12517
12536
  const localClaudeDir = path21.join(os16.homedir(), ".claude");
12518
- const haveLocalClaude = fs17.existsSync(localClaudeDir) && fs17.statSync(localClaudeDir).isDirectory();
12537
+ const haveLocalClaude = fs18.existsSync(localClaudeDir) && fs18.statSync(localClaudeDir).isDirectory();
12519
12538
  if (haveLocalClaude) {
12520
12539
  const copyStep = fe();
12521
12540
  copyStep.start("Copying local Claude config to workspace\u2026");
@@ -12570,9 +12589,9 @@ var ClaudeDeployStrategy = class {
12570
12589
  }
12571
12590
  if (opts.bridged !== "none") {
12572
12591
  const localClaudeJson = path21.join(os16.homedir(), ".claude.json");
12573
- if (fs17.existsSync(localClaudeJson)) {
12592
+ if (fs18.existsSync(localClaudeJson)) {
12574
12593
  try {
12575
- const contents = fs17.readFileSync(localClaudeJson);
12594
+ const contents = fs18.readFileSync(localClaudeJson);
12576
12595
  await provider.uploadFile(
12577
12596
  workspaceId,
12578
12597
  "/home/codespace/.claude.json",
@@ -12865,7 +12884,7 @@ function getCurrentUsage2(historyDir) {
12865
12884
  var import_node_child_process4 = require("child_process");
12866
12885
 
12867
12886
  // src/agents/codex/local-token.ts
12868
- var fs19 = __toESM(require("fs"));
12887
+ var fs20 = __toESM(require("fs"));
12869
12888
  var os18 = __toESM(require("os"));
12870
12889
  var path23 = __toESM(require("path"));
12871
12890
  function codexCredentialsPath() {
@@ -12873,8 +12892,8 @@ function codexCredentialsPath() {
12873
12892
  }
12874
12893
  async function extractLocalCodexToken() {
12875
12894
  const file = codexCredentialsPath();
12876
- if (!fs19.existsSync(file)) return null;
12877
- const credential = fs19.readFileSync(file, "utf8").trim();
12895
+ if (!fs20.existsSync(file)) return null;
12896
+ const credential = fs20.readFileSync(file, "utf8").trim();
12878
12897
  if (credential.length === 0) return null;
12879
12898
  return { method: "oauth", credential, source: "flat-file" };
12880
12899
  }
@@ -13195,7 +13214,7 @@ async function ensureCoderabbitInstalled(os46) {
13195
13214
 
13196
13215
  // src/agents/coderabbit/link.ts
13197
13216
  var import_node_child_process7 = require("child_process");
13198
- var fs21 = __toESM(require("fs"));
13217
+ var fs22 = __toESM(require("fs"));
13199
13218
  var os20 = __toESM(require("os"));
13200
13219
  var path26 = __toESM(require("path"));
13201
13220
 
@@ -13210,8 +13229,8 @@ function authPath() {
13210
13229
  }
13211
13230
  async function extractLocalCoderabbitToken() {
13212
13231
  const file = authPath();
13213
- if (!fs21.existsSync(file)) return null;
13214
- const credential = fs21.readFileSync(file, "utf8").trim();
13232
+ if (!fs22.existsSync(file)) return null;
13233
+ const credential = fs22.readFileSync(file, "utf8").trim();
13215
13234
  if (credential.length === 0) return null;
13216
13235
  return { method: "oauth", credential, source: "flat-file" };
13217
13236
  }
@@ -13343,12 +13362,12 @@ var CoderabbitRuntimeStrategy = class {
13343
13362
  };
13344
13363
 
13345
13364
  // src/agents/cursor/history.ts
13346
- var fs22 = __toESM(require("fs"));
13365
+ var fs23 = __toESM(require("fs"));
13347
13366
  var os21 = __toESM(require("os"));
13348
13367
  var path27 = __toESM(require("path"));
13349
13368
  var HISTORY_ROOT = path27.join(os21.homedir(), ".cursor", "projects");
13350
13369
  function resolveHistoryDir3(cwd) {
13351
- if (!fs22.existsSync(HISTORY_ROOT)) return null;
13370
+ if (!fs23.existsSync(HISTORY_ROOT)) return null;
13352
13371
  void cwd;
13353
13372
  return HISTORY_ROOT;
13354
13373
  }
@@ -13363,7 +13382,7 @@ function getCurrentUsage3(_historyDir) {
13363
13382
  var import_node_child_process9 = require("child_process");
13364
13383
 
13365
13384
  // src/agents/cursor/local-token.ts
13366
- var fs23 = __toESM(require("fs"));
13385
+ var fs24 = __toESM(require("fs"));
13367
13386
  var os22 = __toESM(require("os"));
13368
13387
  var path28 = __toESM(require("path"));
13369
13388
  function cursorCredentialsPath() {
@@ -13371,8 +13390,8 @@ function cursorCredentialsPath() {
13371
13390
  }
13372
13391
  async function extractLocalCursorToken() {
13373
13392
  const file = cursorCredentialsPath();
13374
- if (!fs23.existsSync(file)) return null;
13375
- const credential = fs23.readFileSync(file, "utf8").trim();
13393
+ if (!fs24.existsSync(file)) return null;
13394
+ const credential = fs24.readFileSync(file, "utf8").trim();
13376
13395
  if (credential.length === 0) return null;
13377
13396
  return { method: "oauth", credential, source: "flat-file" };
13378
13397
  }
@@ -13536,12 +13555,12 @@ var CursorRuntimeStrategy = class {
13536
13555
  };
13537
13556
 
13538
13557
  // src/agents/aider/history.ts
13539
- var fs24 = __toESM(require("fs"));
13558
+ var fs25 = __toESM(require("fs"));
13540
13559
  var path29 = __toESM(require("path"));
13541
13560
  var AIDER_HISTORY_FILE = ".aider.chat.history.md";
13542
13561
  function resolveHistoryDir4(cwd) {
13543
13562
  const candidate = path29.join(cwd, AIDER_HISTORY_FILE);
13544
- return fs24.existsSync(candidate) ? cwd : null;
13563
+ return fs25.existsSync(candidate) ? cwd : null;
13545
13564
  }
13546
13565
  function parseHistoryFile4(_filePath) {
13547
13566
  return [];
@@ -13554,7 +13573,7 @@ function getCurrentUsage4(_historyDir) {
13554
13573
  var import_node_child_process10 = require("child_process");
13555
13574
 
13556
13575
  // src/agents/aider/local-token.ts
13557
- var fs25 = __toESM(require("fs"));
13576
+ var fs26 = __toESM(require("fs"));
13558
13577
  var os23 = __toESM(require("os"));
13559
13578
  var path30 = __toESM(require("path"));
13560
13579
  var AIDER_CONF_FILE = path30.join(os23.homedir(), ".aider.conf.yml");
@@ -13572,8 +13591,8 @@ async function extractLocalAiderToken() {
13572
13591
  return { method: "api_key", credential: value.trim(), source: "flat-file" };
13573
13592
  }
13574
13593
  }
13575
- if (fs25.existsSync(AIDER_CONF_FILE)) {
13576
- const conf = fs25.readFileSync(AIDER_CONF_FILE, "utf8");
13594
+ if (fs26.existsSync(AIDER_CONF_FILE)) {
13595
+ const conf = fs26.readFileSync(AIDER_CONF_FILE, "utf8");
13577
13596
  const match = conf.match(/^api-key:\s*['"]?([^'"\n]+)['"]?\s*$/m);
13578
13597
  if (match) {
13579
13598
  return { method: "api_key", credential: match[1].trim(), source: "flat-file" };
@@ -13753,7 +13772,7 @@ var AiderRuntimeStrategy = class {
13753
13772
  var import_node_child_process11 = require("child_process");
13754
13773
 
13755
13774
  // src/agents/gemini/local-token.ts
13756
- var fs26 = __toESM(require("fs"));
13775
+ var fs27 = __toESM(require("fs"));
13757
13776
  var os24 = __toESM(require("os"));
13758
13777
  var path31 = __toESM(require("path"));
13759
13778
  function geminiCredentialsPath() {
@@ -13764,8 +13783,8 @@ function geminiCredentialsPaths() {
13764
13783
  }
13765
13784
  async function extractLocalGeminiToken() {
13766
13785
  const file = geminiCredentialsPath();
13767
- if (!fs26.existsSync(file)) return null;
13768
- const credential = fs26.readFileSync(file, "utf8").trim();
13786
+ if (!fs27.existsSync(file)) return null;
13787
+ const credential = fs27.readFileSync(file, "utf8").trim();
13769
13788
  if (credential.length === 0) return null;
13770
13789
  return { method: "oauth", credential, source: "flat-file" };
13771
13790
  }
@@ -14025,7 +14044,7 @@ function parseLinkArgs(args2) {
14025
14044
  if (apiKeyFileArg) {
14026
14045
  const filePath = apiKeyFileArg.slice("--api-key-file=".length);
14027
14046
  try {
14028
- apiKey = fs27.readFileSync(path32.resolve(filePath), "utf8").trim();
14047
+ apiKey = fs28.readFileSync(path32.resolve(filePath), "utf8").trim();
14029
14048
  } catch (err) {
14030
14049
  throw new Error(`Could not read --api-key-file ${filePath}: ${err.message}`);
14031
14050
  }
@@ -14152,7 +14171,7 @@ async function link(args2 = []) {
14152
14171
  return;
14153
14172
  }
14154
14173
  if (parsed.tokenFile) {
14155
- const credential = fs27.readFileSync(path32.resolve(parsed.tokenFile), "utf8").trim();
14174
+ const credential = fs28.readFileSync(path32.resolve(parsed.tokenFile), "utf8").trim();
14156
14175
  if (!credential) {
14157
14176
  showError(`--token-file ${parsed.tokenFile} is empty.`);
14158
14177
  process.exit(1);
@@ -14252,10 +14271,7 @@ async function captureFreshCredentials(ctx) {
14252
14271
  void watcher.close();
14253
14272
  if (keychainPoll) clearInterval(keychainPoll);
14254
14273
  if (child && !child.killed) {
14255
- try {
14256
- child.kill("SIGTERM");
14257
- } catch {
14258
- }
14274
+ killQuiet(child, "SIGTERM");
14259
14275
  }
14260
14276
  };
14261
14277
  try {
@@ -14374,15 +14390,15 @@ async function linkDryRunPreflight(ctx) {
14374
14390
  // src/commands/host-agent.ts
14375
14391
  var import_node_child_process19 = require("child_process");
14376
14392
  var os32 = __toESM(require("os"));
14377
- var fs37 = __toESM(require("fs"));
14393
+ var fs38 = __toESM(require("fs"));
14378
14394
  var path40 = __toESM(require("path"));
14379
14395
 
14380
14396
  // src/commands/host/host-client.ts
14381
- var fs29 = __toESM(require("fs"));
14397
+ var fs30 = __toESM(require("fs"));
14382
14398
  var os26 = __toESM(require("os"));
14383
14399
  var path33 = __toESM(require("path"));
14384
14400
 
14385
- // src/util/restrict-to-owner.ts
14401
+ // src/lib/restrict-to-owner.ts
14386
14402
  var import_node_fs5 = __toESM(require("fs"));
14387
14403
  var import_node_os3 = __toESM(require("os"));
14388
14404
  var import_node_child_process12 = require("child_process");
@@ -14474,7 +14490,7 @@ function collectOsInfo() {
14474
14490
  }
14475
14491
  function loadHostIdentity() {
14476
14492
  try {
14477
- const raw = fs29.readFileSync(hostIdentityPath(), "utf8");
14493
+ const raw = fs30.readFileSync(hostIdentityPath(), "utf8");
14478
14494
  const parsed = JSON.parse(raw);
14479
14495
  if (typeof parsed === "object" && parsed !== null && typeof parsed.hostId === "string" && typeof parsed.hostToken === "string" && typeof parsed.controlPluginId === "string") {
14480
14496
  const p2 = parsed;
@@ -14487,8 +14503,8 @@ function loadHostIdentity() {
14487
14503
  }
14488
14504
  function saveHostIdentity(identity) {
14489
14505
  const file = hostIdentityPath();
14490
- fs29.mkdirSync(path33.dirname(file), { recursive: true, mode: 448 });
14491
- fs29.writeFileSync(file, JSON.stringify(identity, null, 2), {
14506
+ fs30.mkdirSync(path33.dirname(file), { recursive: true, mode: 448 });
14507
+ fs30.writeFileSync(file, JSON.stringify(identity, null, 2), {
14492
14508
  encoding: "utf8",
14493
14509
  mode: 384
14494
14510
  });
@@ -14533,7 +14549,7 @@ function isTerminalEnrollError(err) {
14533
14549
  }
14534
14550
  function deleteHostIdentity() {
14535
14551
  try {
14536
- fs29.rmSync(hostIdentityPath(), { force: true });
14552
+ fs30.rmSync(hostIdentityPath(), { force: true });
14537
14553
  } catch {
14538
14554
  }
14539
14555
  }
@@ -14656,7 +14672,7 @@ async function reportDeployProgress(auth, deployId, step, message, sessionId) {
14656
14672
  }
14657
14673
 
14658
14674
  // src/commands/host/workspace.ts
14659
- var fs30 = __toESM(require("fs"));
14675
+ var fs31 = __toESM(require("fs"));
14660
14676
  var os27 = __toESM(require("os"));
14661
14677
  var path34 = __toESM(require("path"));
14662
14678
  var import_node_child_process13 = require("child_process");
@@ -14720,7 +14736,7 @@ async function configureGitCredentials(dest, repoRef, cloneToken) {
14720
14736
  const gh = githubOwnerRepo(repoRef.trim());
14721
14737
  if (!gh || !cloneToken) return;
14722
14738
  const credFile = path34.join(dest, ".git", "codeam-credentials");
14723
- fs30.writeFileSync(credFile, `https://x-access-token:${cloneToken}@github.com
14739
+ fs31.writeFileSync(credFile, `https://x-access-token:${cloneToken}@github.com
14724
14740
  `, { mode: 384 });
14725
14741
  restrictToOwner(credFile);
14726
14742
  const env = nonInteractiveGitEnv();
@@ -14761,17 +14777,17 @@ function maskToken(text, cloneToken) {
14761
14777
  }
14762
14778
  async function prepareWorkspace(repoOrPath, deployId, cloneToken) {
14763
14779
  if (isAbsolutePathTarget(repoOrPath)) {
14764
- if (!fs30.existsSync(repoOrPath)) {
14780
+ if (!fs31.existsSync(repoOrPath)) {
14765
14781
  throw new Error(`deploy target path does not exist: ${repoOrPath}`);
14766
14782
  }
14767
14783
  return repoOrPath;
14768
14784
  }
14769
14785
  const dest = path34.join(selfHostedWorkspaceRoot(), deployId);
14770
- if (fs30.existsSync(path34.join(dest, ".git"))) {
14786
+ if (fs31.existsSync(path34.join(dest, ".git"))) {
14771
14787
  if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken);
14772
14788
  return dest;
14773
14789
  }
14774
- fs30.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
14790
+ fs31.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
14775
14791
  const cloneUrl = repoCloneUrl(repoOrPath, cloneToken);
14776
14792
  try {
14777
14793
  await execFileP4("git", ["clone", "--depth", "1", cloneUrl, dest], {
@@ -14788,7 +14804,7 @@ async function prepareWorkspace(repoOrPath, deployId, cloneToken) {
14788
14804
  }
14789
14805
 
14790
14806
  // src/commands/host/agent-provisioning.ts
14791
- var fs31 = __toESM(require("fs"));
14807
+ var fs32 = __toESM(require("fs"));
14792
14808
  var os28 = __toESM(require("os"));
14793
14809
  var path35 = __toESM(require("path"));
14794
14810
  var PUBLIC_TO_INTERNAL_AGENT = {
@@ -14805,16 +14821,16 @@ function toInternalAgentId(publicAgentId) {
14805
14821
  return PUBLIC_TO_INTERNAL_AGENT[publicAgentId] ?? null;
14806
14822
  }
14807
14823
  function ensureDir(dir) {
14808
- fs31.mkdirSync(dir, { recursive: true, mode: 448 });
14824
+ fs32.mkdirSync(dir, { recursive: true, mode: 448 });
14809
14825
  }
14810
14826
  function writeFile0600(filePath, contents) {
14811
14827
  ensureDir(path35.dirname(filePath));
14812
- fs31.writeFileSync(filePath, contents, { encoding: "utf8", mode: 384 });
14828
+ fs32.writeFileSync(filePath, contents, { encoding: "utf8", mode: 384 });
14813
14829
  restrictToOwner(filePath);
14814
14830
  }
14815
14831
  function rmIfExists(filePath) {
14816
14832
  try {
14817
- fs31.rmSync(filePath, { force: true });
14833
+ fs32.rmSync(filePath, { force: true });
14818
14834
  } catch {
14819
14835
  }
14820
14836
  }
@@ -14833,7 +14849,7 @@ var claudeProvisioner = {
14833
14849
  rmIfExists(credentialsJson);
14834
14850
  }
14835
14851
  const claudeJson = path35.join(home, ".claude.json");
14836
- if (!fs31.existsSync(claudeJson)) {
14852
+ if (!fs32.existsSync(claudeJson)) {
14837
14853
  writeFile0600(
14838
14854
  claudeJson,
14839
14855
  JSON.stringify({ hasCompletedOnboarding: true, customApiKeyResponses: { approved: [] } })
@@ -14916,7 +14932,7 @@ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os28.homedir(
14916
14932
 
14917
14933
  // src/commands/host/git-tooling.ts
14918
14934
  var import_node_child_process14 = require("child_process");
14919
- var fs32 = __toESM(require("fs"));
14935
+ var fs33 = __toESM(require("fs"));
14920
14936
  var os29 = __toESM(require("os"));
14921
14937
  var path36 = __toESM(require("path"));
14922
14938
  function codeamBinDir() {
@@ -14952,7 +14968,7 @@ async function download(url, dest) {
14952
14968
  const res = await fetch(url, { headers: { "User-Agent": "codeam-cli" } });
14953
14969
  if (!res.ok || !res.body) return false;
14954
14970
  const buf = Buffer.from(await res.arrayBuffer());
14955
- fs32.writeFileSync(dest, buf);
14971
+ fs33.writeFileSync(dest, buf);
14956
14972
  return true;
14957
14973
  } catch {
14958
14974
  return false;
@@ -14975,7 +14991,7 @@ async function ensureGhCli(runner, token, deps = {}) {
14975
14991
  const version3 = await resolveVersionFn(token);
14976
14992
  const asset = `gh_${version3}_${osToken}_${arch2}`;
14977
14993
  const url = `https://github.com/cli/cli/releases/download/v${version3}/${asset}.${ext}`;
14978
- const tmpRoot = fs32.mkdtempSync(path36.join(os29.tmpdir(), "codeam-gh-"));
14994
+ const tmpRoot = fs33.mkdtempSync(path36.join(os29.tmpdir(), "codeam-gh-"));
14979
14995
  const archive = path36.join(tmpRoot, `${asset}.${ext}`);
14980
14996
  if (!await downloadFn(url, archive)) {
14981
14997
  log.warn("host-agent", "gh download failed \u2014 skipping (git pull/push still work via the credential helper)");
@@ -14987,15 +15003,15 @@ async function ensureGhCli(runner, token, deps = {}) {
14987
15003
  return null;
14988
15004
  }
14989
15005
  const extractedBin = path36.join(tmpRoot, asset, "bin", binaryName);
14990
- if (!fs32.existsSync(extractedBin)) {
15006
+ if (!fs33.existsSync(extractedBin)) {
14991
15007
  log.warn("host-agent", "gh binary not found in the extracted archive \u2014 skipping");
14992
15008
  return null;
14993
15009
  }
14994
15010
  const binDir = codeamBinDir();
14995
- fs32.mkdirSync(binDir, { recursive: true });
15011
+ fs33.mkdirSync(binDir, { recursive: true });
14996
15012
  const target = path36.join(binDir, binaryName);
14997
- fs32.copyFileSync(extractedBin, target);
14998
- fs32.chmodSync(target, 493);
15013
+ fs33.copyFileSync(extractedBin, target);
15014
+ fs33.chmodSync(target, 493);
14999
15015
  log.info("host-agent", `gh installed to ${target} (v${version3})`);
15000
15016
  return target;
15001
15017
  } catch (e) {
@@ -15056,10 +15072,7 @@ var defaultGitToolingRunner = {
15056
15072
  let timer;
15057
15073
  if (opts.timeoutMs !== void 0) {
15058
15074
  timer = setTimeout(() => {
15059
- try {
15060
- child.kill("SIGTERM");
15061
- } catch {
15062
- }
15075
+ killQuiet(child);
15063
15076
  done(null);
15064
15077
  }, opts.timeoutMs);
15065
15078
  }
@@ -15237,10 +15250,7 @@ var defaultHeadroomRunner = {
15237
15250
  "host-agent",
15238
15251
  `headroom[${cmd}] timed out after ${timeoutMs / 1e3}s \u2014 aborting`
15239
15252
  );
15240
- try {
15241
- child.kill("SIGTERM");
15242
- } catch {
15243
- }
15253
+ killQuiet(child);
15244
15254
  done(null);
15245
15255
  }, timeoutMs);
15246
15256
  }
@@ -15488,11 +15498,11 @@ async function ensureModernPython(runner) {
15488
15498
  }
15489
15499
 
15490
15500
  // src/commands/host/headroom-bootstrap.ts
15491
- var fs34 = __toESM(require("fs"));
15501
+ var fs35 = __toESM(require("fs"));
15492
15502
  var path38 = __toESM(require("path"));
15493
15503
 
15494
15504
  // src/commands/host/headroom-config.ts
15495
- var fs33 = __toESM(require("fs"));
15505
+ var fs34 = __toESM(require("fs"));
15496
15506
  var os30 = __toESM(require("os"));
15497
15507
  var path37 = __toESM(require("path"));
15498
15508
  function headroomConfigPath() {
@@ -15501,10 +15511,10 @@ function headroomConfigPath() {
15501
15511
  function persistHeadroomConfig(config) {
15502
15512
  try {
15503
15513
  const file = headroomConfigPath();
15504
- fs33.mkdirSync(path37.dirname(file), { recursive: true, mode: 448 });
15514
+ fs34.mkdirSync(path37.dirname(file), { recursive: true, mode: 448 });
15505
15515
  const tmp = `${file}.tmp-${process.pid}`;
15506
- fs33.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
15507
- fs33.renameSync(tmp, file);
15516
+ fs34.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
15517
+ fs34.renameSync(tmp, file);
15508
15518
  restrictToOwner(file);
15509
15519
  } catch (err) {
15510
15520
  log.warn(
@@ -15524,11 +15534,11 @@ function backupAgentHeadroomConfig(kind) {
15524
15534
  const src = agentSettingsPath(kind);
15525
15535
  if (!src) return;
15526
15536
  try {
15527
- if (!fs33.existsSync(src)) return;
15537
+ if (!fs34.existsSync(src)) return;
15528
15538
  const dest = path37.join(os30.homedir(), ".codeam", `headroom-backup-${kind}.json`);
15529
- fs33.mkdirSync(path37.dirname(dest), { recursive: true, mode: 448 });
15530
- fs33.copyFileSync(src, dest);
15531
- fs33.chmodSync(dest, 384);
15539
+ fs34.mkdirSync(path37.dirname(dest), { recursive: true, mode: 448 });
15540
+ fs34.copyFileSync(src, dest);
15541
+ fs34.chmodSync(dest, 384);
15532
15542
  log.info("host-agent", `headroom config backup: ${src} \u2192 ${dest}`);
15533
15543
  } catch (err) {
15534
15544
  log.warn(
@@ -15541,11 +15551,11 @@ function restoreAgentHeadroomConfig(kind) {
15541
15551
  const dest = agentSettingsPath(kind);
15542
15552
  if (!dest) return false;
15543
15553
  const src = path37.join(os30.homedir(), ".codeam", `headroom-backup-${kind}.json`);
15544
- if (!fs33.existsSync(src)) return false;
15554
+ if (!fs34.existsSync(src)) return false;
15545
15555
  try {
15546
- fs33.mkdirSync(path37.dirname(dest), { recursive: true, mode: 448 });
15547
- fs33.copyFileSync(src, dest);
15548
- fs33.chmodSync(dest, 384);
15556
+ fs34.mkdirSync(path37.dirname(dest), { recursive: true, mode: 448 });
15557
+ fs34.copyFileSync(src, dest);
15558
+ fs34.chmodSync(dest, 384);
15549
15559
  log.info("host-agent", `headroom config restored: ${src} \u2192 ${dest}`);
15550
15560
  return true;
15551
15561
  } catch (err) {
@@ -15558,7 +15568,7 @@ function restoreAgentHeadroomConfig(kind) {
15558
15568
  }
15559
15569
  function readHeadroomChildEnv() {
15560
15570
  try {
15561
- const raw = fs33.readFileSync(headroomConfigPath(), "utf8");
15571
+ const raw = fs34.readFileSync(headroomConfigPath(), "utf8");
15562
15572
  const parsed = JSON.parse(raw);
15563
15573
  if (typeof parsed !== "object" || parsed === null) return {};
15564
15574
  const o = parsed;
@@ -15610,21 +15620,21 @@ function bundledClaudeBinDir() {
15610
15620
  const atAnthropic = path38.join(nm, "@anthropic-ai");
15611
15621
  let entries;
15612
15622
  try {
15613
- entries = fs34.readdirSync(atAnthropic);
15623
+ entries = fs35.readdirSync(atAnthropic);
15614
15624
  } catch {
15615
15625
  continue;
15616
15626
  }
15617
15627
  for (const entry of entries) {
15618
15628
  if (!entry.startsWith("claude-agent-sdk-")) continue;
15619
15629
  const bin = path38.join(atAnthropic, entry, "claude");
15620
- if (fs34.existsSync(bin)) return path38.dirname(bin);
15630
+ if (fs35.existsSync(bin)) return path38.dirname(bin);
15621
15631
  }
15622
15632
  }
15623
15633
  return null;
15624
15634
  }
15625
15635
  async function getFreeDiskBytes(dir) {
15626
15636
  try {
15627
- const s = await fs34.promises.statfs(dir);
15637
+ const s = await fs35.promises.statfs(dir);
15628
15638
  return s.bsize * s.bavail;
15629
15639
  } catch {
15630
15640
  return null;
@@ -15721,7 +15731,7 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
15721
15731
  var import_node_child_process17 = require("child_process");
15722
15732
 
15723
15733
  // src/lib/updateNotifier.ts
15724
- var fs35 = __toESM(require("fs"));
15734
+ var fs36 = __toESM(require("fs"));
15725
15735
  var os31 = __toESM(require("os"));
15726
15736
  var path39 = __toESM(require("path"));
15727
15737
  var https6 = __toESM(require("https"));
@@ -15737,7 +15747,7 @@ function cachePath() {
15737
15747
  }
15738
15748
  function readCache() {
15739
15749
  try {
15740
- const raw = fs35.readFileSync(cachePath(), "utf8");
15750
+ const raw = fs36.readFileSync(cachePath(), "utf8");
15741
15751
  const parsed = JSON.parse(raw);
15742
15752
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
15743
15753
  return parsed;
@@ -15748,10 +15758,10 @@ function readCache() {
15748
15758
  function writeCache(cache) {
15749
15759
  try {
15750
15760
  const file = cachePath();
15751
- fs35.mkdirSync(path39.dirname(file), { recursive: true });
15761
+ fs36.mkdirSync(path39.dirname(file), { recursive: true });
15752
15762
  const tmp = `${file}.${process.pid}.tmp`;
15753
- fs35.writeFileSync(tmp, JSON.stringify(cache));
15754
- fs35.renameSync(tmp, file);
15763
+ fs36.writeFileSync(tmp, JSON.stringify(cache));
15764
+ fs36.renameSync(tmp, file);
15755
15765
  } catch {
15756
15766
  }
15757
15767
  }
@@ -15826,7 +15836,7 @@ function isLinkedInstall() {
15826
15836
  }).trim();
15827
15837
  if (!root) return false;
15828
15838
  const pkgPath = path39.join(root, PKG_NAME);
15829
- return fs35.lstatSync(pkgPath).isSymbolicLink();
15839
+ return fs36.lstatSync(pkgPath).isSymbolicLink();
15830
15840
  } catch {
15831
15841
  return false;
15832
15842
  }
@@ -15862,7 +15872,7 @@ function maybeAutoUpdate(currentVersion, latest) {
15862
15872
  return;
15863
15873
  }
15864
15874
  try {
15865
- fs35.unlinkSync(cachePath());
15875
+ fs36.unlinkSync(cachePath());
15866
15876
  } catch {
15867
15877
  }
15868
15878
  process.stderr.write(` ${import_picocolors3.default.green("\u2713")} Updated. Resuming session...
@@ -15878,7 +15888,7 @@ async function autoUpgradeBeforeCriticalCommand() {
15878
15888
  if (process.env.NODE_ENV === "test") return;
15879
15889
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
15880
15890
  if (process.env.CI) return;
15881
- const current = true ? "2.56.0" : null;
15891
+ const current = true ? "2.58.0" : null;
15882
15892
  if (!current) return;
15883
15893
  const cache = readCache();
15884
15894
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -15895,7 +15905,7 @@ function checkForUpdates() {
15895
15905
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
15896
15906
  if (process.env.CI) return;
15897
15907
  if (!process.stdout.isTTY) return;
15898
- const current = true ? "2.56.0" : null;
15908
+ const current = true ? "2.58.0" : null;
15899
15909
  if (!current) return;
15900
15910
  const cache = readCache();
15901
15911
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -15915,7 +15925,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
15915
15925
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
15916
15926
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
15917
15927
  function currentCliVersion() {
15918
- return true ? "2.56.0" : null;
15928
+ return true ? "2.58.0" : null;
15919
15929
  }
15920
15930
  function runCmd(cmd, args2, timeoutMs) {
15921
15931
  return new Promise((resolve7) => {
@@ -15982,7 +15992,7 @@ async function runSelfUpdate() {
15982
15992
 
15983
15993
  // src/commands/host/teardown.ts
15984
15994
  var import_node_child_process18 = require("child_process");
15985
- var fs36 = __toESM(require("fs"));
15995
+ var fs37 = __toESM(require("fs"));
15986
15996
  var defaultDisableService = () => {
15987
15997
  try {
15988
15998
  (0, import_node_child_process18.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
@@ -15991,7 +16001,7 @@ var defaultDisableService = () => {
15991
16001
  };
15992
16002
  var defaultTeardownHeadroom = () => {
15993
16003
  try {
15994
- const kind = JSON.parse(fs36.readFileSync(headroomConfigPath(), "utf8")).agent;
16004
+ const kind = JSON.parse(fs37.readFileSync(headroomConfigPath(), "utf8")).agent;
15995
16005
  if (kind) {
15996
16006
  (0, import_node_child_process18.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
15997
16007
  }
@@ -16059,8 +16069,8 @@ function maybeResumeLocalHeadroomReporter(ctx) {
16059
16069
  if (process.env["HEADROOM_ENABLED"] === "1") return null;
16060
16070
  try {
16061
16071
  const file = headroomConfigPath();
16062
- if (!fs37.existsSync(file)) return null;
16063
- const cfg = JSON.parse(fs37.readFileSync(file, "utf8"));
16072
+ if (!fs38.existsSync(file)) return null;
16073
+ const cfg = JSON.parse(fs38.readFileSync(file, "utf8"));
16064
16074
  if (!cfg?.enabled) return null;
16065
16075
  const agent = cfg.agent ?? "claude";
16066
16076
  const ingestUrl = `${resolveApiBaseUrl()}/api/sessions/${ctx.sessionId}/headroom-savings`;
@@ -16269,10 +16279,7 @@ var HostAgentSupervisor = class {
16269
16279
  }
16270
16280
  this.relay?.stop();
16271
16281
  for (const child of this.children.values()) {
16272
- try {
16273
- child.proc.kill("SIGTERM");
16274
- } catch {
16275
- }
16282
+ killQuiet(child.proc);
16276
16283
  }
16277
16284
  this.children.clear();
16278
16285
  }
@@ -16470,7 +16477,7 @@ var HostAgentSupervisor = class {
16470
16477
  };
16471
16478
  const houseConfigDir = path40.join(os32.homedir(), ".codeam", "house-claude");
16472
16479
  try {
16473
- fs37.mkdirSync(houseConfigDir, { recursive: true, mode: 448 });
16480
+ fs38.mkdirSync(houseConfigDir, { recursive: true, mode: 448 });
16474
16481
  } catch {
16475
16482
  }
16476
16483
  childEnv.CLAUDE_CONFIG_DIR = houseConfigDir;
@@ -16817,7 +16824,7 @@ async function configureHeadroom(action, ctx, deps) {
16817
16824
  }
16818
16825
 
16819
16826
  // src/services/headroom/budget-relaunch.ts
16820
- var fs38 = __toESM(require("fs"));
16827
+ var fs39 = __toESM(require("fs"));
16821
16828
  var os33 = __toESM(require("os"));
16822
16829
  var path41 = __toESM(require("path"));
16823
16830
  var import_child_process13 = require("child_process");
@@ -16894,8 +16901,8 @@ async function applyBudgetToHeadroom(budget, deps) {
16894
16901
  }
16895
16902
  function writeManifestReal(manifestPath, manifest) {
16896
16903
  const tmp = manifestPath + ".codeam.tmp";
16897
- fs38.writeFileSync(tmp, JSON.stringify(manifest, null, 2) + "\n", { mode: 384 });
16898
- fs38.renameSync(tmp, manifestPath);
16904
+ fs39.writeFileSync(tmp, JSON.stringify(manifest, null, 2) + "\n", { mode: 384 });
16905
+ fs39.renameSync(tmp, manifestPath);
16899
16906
  }
16900
16907
  function restartDeploymentReal(profile) {
16901
16908
  try {
@@ -16928,8 +16935,8 @@ function makeRealApplyBudgetDeps() {
16928
16935
  const homeDir2 = os33.homedir();
16929
16936
  return {
16930
16937
  findDeployments: () => findHeadroomDeployments(homeDir2, {
16931
- readDir: (dir) => fs38.readdirSync(dir),
16932
- readJson: (filePath) => JSON.parse(fs38.readFileSync(filePath, "utf8"))
16938
+ readDir: (dir) => fs39.readdirSync(dir),
16939
+ readJson: (filePath) => JSON.parse(fs39.readFileSync(filePath, "utf8"))
16933
16940
  }),
16934
16941
  writeManifest: writeManifestReal,
16935
16942
  restartDeployment: restartDeploymentReal,
@@ -17284,10 +17291,7 @@ function runSetupCommand(cmd, args2, cwd, env, opts) {
17284
17291
  if (settled) return;
17285
17292
  settled = true;
17286
17293
  log.info("preview", `${tag}: timed out after ${opts.timeoutMs}ms \u2014 killing`);
17287
- try {
17288
- child.kill("SIGTERM");
17289
- } catch {
17290
- }
17294
+ killQuiet(child);
17291
17295
  resolve7({ status: "timeout", code: null });
17292
17296
  }, opts.timeoutMs);
17293
17297
  child.once("exit", (code) => {
@@ -17612,7 +17616,7 @@ function activePreviewSessionIds() {
17612
17616
 
17613
17617
  // src/services/preview/start-orchestrator.ts
17614
17618
  var import_child_process17 = require("child_process");
17615
- var fs43 = __toESM(require("fs"));
17619
+ var fs44 = __toESM(require("fs"));
17616
17620
  var path46 = __toESM(require("path"));
17617
17621
  var import_which2 = __toESM(require("which"));
17618
17622
  var INSTALL_TIMEOUT_MS = 5 * 6e4;
@@ -17681,7 +17685,7 @@ function normalizeDetectionForSpawn(detection, cwd) {
17681
17685
  const binName = args2[0];
17682
17686
  if (binName.startsWith("-")) return detection;
17683
17687
  const binPath = path46.join(cwd, "node_modules", ".bin", binName);
17684
- if (!fs43.existsSync(binPath)) return detection;
17688
+ if (!fs44.existsSync(binPath)) return detection;
17685
17689
  return {
17686
17690
  ...detection,
17687
17691
  command: binPath,
@@ -17983,10 +17987,7 @@ async function establishTunnel(ctx, dev) {
17983
17987
  "preview",
17984
17988
  "named tunnel did not register within 45s \u2014 falling back to quick tunnel"
17985
17989
  );
17986
- try {
17987
- candidate.kill("SIGTERM");
17988
- } catch {
17989
- }
17990
+ killQuiet(candidate);
17990
17991
  }
17991
17992
  } catch (e) {
17992
17993
  log.info(
@@ -18018,10 +18019,7 @@ async function establishTunnel(ctx, dev) {
18018
18019
  parsedUrl = outcome.url;
18019
18020
  } else {
18020
18021
  lastTunnelErr = outcome.sawUrl ? "cloudflared did not register a tunnel connection within 45s" : "cloudflared did not emit a URL within 45s";
18021
- try {
18022
- candidate.kill("SIGTERM");
18023
- } catch {
18024
- }
18022
+ killQuiet(candidate);
18025
18023
  }
18026
18024
  }
18027
18025
  if (!parsedUrl) {
@@ -18037,7 +18035,7 @@ async function establishTunnel(ctx, dev) {
18037
18035
 
18038
18036
  // src/beads/bd-adapter.ts
18039
18037
  var import_child_process18 = require("child_process");
18040
- var fs44 = __toESM(require("fs"));
18038
+ var fs45 = __toESM(require("fs"));
18041
18039
  var os35 = __toESM(require("os"));
18042
18040
  var path47 = __toESM(require("path"));
18043
18041
  var BD_PACKAGE = "@beads/bd";
@@ -18055,7 +18053,7 @@ function _defaultResolveBundled() {
18055
18053
  const binaryName = process.platform === "win32" ? "bd.exe" : "bd";
18056
18054
  const binaryPath = path47.join(binDir, binaryName);
18057
18055
  try {
18058
- fs44.accessSync(binaryPath, fs44.constants.F_OK);
18056
+ fs45.accessSync(binaryPath, fs45.constants.F_OK);
18059
18057
  return binaryPath;
18060
18058
  } catch {
18061
18059
  return null;
@@ -18071,7 +18069,7 @@ function _defaultResolveOnPath() {
18071
18069
  for (const candidate of candidates) {
18072
18070
  const full = path47.join(dir, candidate);
18073
18071
  try {
18074
- fs44.accessSync(full, fs44.constants.F_OK);
18072
+ fs45.accessSync(full, fs45.constants.F_OK);
18075
18073
  return full;
18076
18074
  } catch {
18077
18075
  }
@@ -18248,7 +18246,7 @@ function coerceIssue(row, projectKey) {
18248
18246
 
18249
18247
  // src/beads/provisioner.ts
18250
18248
  var import_child_process22 = require("child_process");
18251
- var fs47 = __toESM(require("fs"));
18249
+ var fs48 = __toESM(require("fs"));
18252
18250
  var os37 = __toESM(require("os"));
18253
18251
  var path50 = __toESM(require("path"));
18254
18252
 
@@ -18315,7 +18313,7 @@ async function installBd(platform3 = process.platform) {
18315
18313
 
18316
18314
  // src/beads/install-dolt.ts
18317
18315
  var import_child_process20 = require("child_process");
18318
- var fs45 = __toESM(require("fs"));
18316
+ var fs46 = __toESM(require("fs"));
18319
18317
  var os36 = __toESM(require("os"));
18320
18318
  var path48 = __toESM(require("path"));
18321
18319
  var DOLT_INSTALL_SH_URL = "https://github.com/dolthub/dolt/releases/latest/download/install.sh";
@@ -18413,7 +18411,7 @@ var _doltPathSeam = {
18413
18411
  },
18414
18412
  exists: (p2) => {
18415
18413
  try {
18416
- fs45.accessSync(p2, fs45.constants.F_OK);
18414
+ fs46.accessSync(p2, fs46.constants.F_OK);
18417
18415
  return true;
18418
18416
  } catch {
18419
18417
  return false;
@@ -18576,7 +18574,7 @@ async function ensureSharedServer(adapter, options = {}) {
18576
18574
  // src/beads/project-key.ts
18577
18575
  var import_child_process21 = require("child_process");
18578
18576
  var crypto2 = __toESM(require("crypto"));
18579
- var fs46 = __toESM(require("fs"));
18577
+ var fs47 = __toESM(require("fs"));
18580
18578
  var path49 = __toESM(require("path"));
18581
18579
  function normalizeOrigin(raw) {
18582
18580
  const trimmed = raw.trim();
@@ -18609,7 +18607,7 @@ function findRepoRoot(cwd) {
18609
18607
  if (seen.has(dir)) return null;
18610
18608
  seen.add(dir);
18611
18609
  try {
18612
- const stat3 = fs46.statSync(path49.join(dir, ".git"), { throwIfNoEntry: false });
18610
+ const stat3 = fs47.statSync(path49.join(dir, ".git"), { throwIfNoEntry: false });
18613
18611
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
18614
18612
  } catch {
18615
18613
  }
@@ -18624,7 +18622,7 @@ var _execSeam2 = {
18624
18622
  const out2 = (0, import_child_process21.execFileSync)(file, args2, opts);
18625
18623
  return typeof out2 === "string" ? out2 : out2.toString("utf8");
18626
18624
  },
18627
- realpath: (p2) => fs46.realpathSync(p2)
18625
+ realpath: (p2) => fs47.realpathSync(p2)
18628
18626
  };
18629
18627
  function readOrigin(cwd) {
18630
18628
  try {
@@ -18698,14 +18696,14 @@ var _linkSeam = {
18698
18696
  homedir: () => os37.homedir(),
18699
18697
  isWritableDir: (dir) => {
18700
18698
  try {
18701
- fs47.accessSync(dir, fs47.constants.W_OK);
18699
+ fs48.accessSync(dir, fs48.constants.W_OK);
18702
18700
  return true;
18703
18701
  } catch {
18704
18702
  return false;
18705
18703
  }
18706
18704
  },
18707
18705
  ensureDir: (dir) => {
18708
- fs47.mkdirSync(dir, { recursive: true });
18706
+ fs48.mkdirSync(dir, { recursive: true });
18709
18707
  },
18710
18708
  /**
18711
18709
  * A directory to symlink `bd` into so the AGENT's shell + Claude Code's
@@ -18745,7 +18743,7 @@ var _linkSeam = {
18745
18743
  const entry = process.argv[1];
18746
18744
  if (entry) {
18747
18745
  try {
18748
- candidates.push(path50.dirname(fs47.realpathSync(entry)));
18746
+ candidates.push(path50.dirname(fs48.realpathSync(entry)));
18749
18747
  } catch {
18750
18748
  candidates.push(path50.dirname(entry));
18751
18749
  }
@@ -18759,13 +18757,13 @@ var _linkSeam = {
18759
18757
  /** Current symlink target at `linkPath`, or null when absent / not a link. */
18760
18758
  readlink: (linkPath) => {
18761
18759
  try {
18762
- return fs47.readlinkSync(linkPath);
18760
+ return fs48.readlinkSync(linkPath);
18763
18761
  } catch {
18764
18762
  return null;
18765
18763
  }
18766
18764
  },
18767
- unlink: (linkPath) => fs47.unlinkSync(linkPath),
18768
- symlink: (target, linkPath) => fs47.symlinkSync(target, linkPath)
18765
+ unlink: (linkPath) => fs48.unlinkSync(linkPath),
18766
+ symlink: (target, linkPath) => fs48.symlinkSync(target, linkPath)
18769
18767
  };
18770
18768
  function linkBdOntoPath(binaryPath) {
18771
18769
  if (_linkSeam.platform() === "win32") return;
@@ -19401,10 +19399,7 @@ async function configureBeads(action, ctx, deps) {
19401
19399
  var pendingAttachmentFiles = /* @__PURE__ */ new Set();
19402
19400
  function cleanupAttachmentTempFiles() {
19403
19401
  for (const p2 of pendingAttachmentFiles) {
19404
- try {
19405
- fs49.unlinkSync(p2);
19406
- } catch {
19407
- }
19402
+ rmIfExistsQuiet(p2);
19408
19403
  }
19409
19404
  pendingAttachmentFiles.clear();
19410
19405
  }
@@ -19412,7 +19407,7 @@ function saveFilesTemp(files) {
19412
19407
  return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
19413
19408
  const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
19414
19409
  const tmpPath = path53.join(os39.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
19415
- fs49.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
19410
+ fs50.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
19416
19411
  pendingAttachmentFiles.add(tmpPath);
19417
19412
  return tmpPath;
19418
19413
  });
@@ -19431,10 +19426,7 @@ var startTask = (ctx, _cmd, parsed) => {
19431
19426
  ctx.agent.sendCommand(`${atRefs} ${effectivePrompt}`.trim());
19432
19427
  setTimeout(() => {
19433
19428
  for (const p2 of paths) {
19434
- try {
19435
- fs49.unlinkSync(p2);
19436
- } catch {
19437
- }
19429
+ rmIfExistsQuiet(p2);
19438
19430
  pendingAttachmentFiles.delete(p2);
19439
19431
  }
19440
19432
  }, 12e4);
@@ -19552,10 +19544,7 @@ var sessionTerminated = async (ctx, cmd) => {
19552
19544
  removeSession(ctx.sessionId);
19553
19545
  } catch {
19554
19546
  }
19555
- try {
19556
- ctx.agent.kill();
19557
- } catch {
19558
- }
19547
+ quiet(() => ctx.agent.kill());
19559
19548
  try {
19560
19549
  const proc = (0, import_child_process23.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
19561
19550
  detached: true,
@@ -19573,10 +19562,7 @@ var shutdownSession = async (ctx, cmd) => {
19573
19562
  await ctx.relay.sendResult(cmd.id, "success", { ok: true });
19574
19563
  } catch {
19575
19564
  }
19576
- try {
19577
- ctx.agent.kill();
19578
- } catch {
19579
- }
19565
+ quiet(() => ctx.agent.kill());
19580
19566
  if (ctx.keepAliveCtx.inCodespace && ctx.keepAliveCtx.codespaceName) {
19581
19567
  try {
19582
19568
  const stopProc = (0, import_child_process23.spawn)(
@@ -19635,7 +19621,7 @@ var listFiles = async (ctx, cmd, parsed) => {
19635
19621
  var envReadH = async (ctx, cmd) => {
19636
19622
  const envPath = path53.join(process.cwd(), ".env");
19637
19623
  try {
19638
- const raw = await fs49.promises.readFile(envPath, "utf8");
19624
+ const raw = await fs50.promises.readFile(envPath, "utf8");
19639
19625
  await ctx.relay.sendResult(cmd.id, "completed", {
19640
19626
  exists: true,
19641
19627
  vars: parseDotenv(raw)
@@ -19669,11 +19655,11 @@ var envWriteH = async (ctx, cmd, parsed) => {
19669
19655
  const envPath = path53.join(process.cwd(), ".env");
19670
19656
  const tmpPath = path53.join(process.cwd(), ".env.codeam.tmp");
19671
19657
  try {
19672
- await fs49.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
19673
- await fs49.promises.rename(tmpPath, envPath);
19658
+ await fs50.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
19659
+ await fs50.promises.rename(tmpPath, envPath);
19674
19660
  await ctx.relay.sendResult(cmd.id, "completed", { ok: true, count: vars.length });
19675
19661
  } catch (err) {
19676
- await fs49.promises.rm(tmpPath, { force: true }).catch(() => void 0);
19662
+ await fs50.promises.rm(tmpPath, { force: true }).catch(() => void 0);
19677
19663
  await ctx.relay.sendResult(cmd.id, "failed", { error: err.message });
19678
19664
  }
19679
19665
  };
@@ -19691,7 +19677,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
19691
19677
  let configuredAgent = rawAgentId;
19692
19678
  if (!configuredAgent) {
19693
19679
  try {
19694
- const raw = JSON.parse(fs49.readFileSync(headroomConfigPath(), "utf8"));
19680
+ const raw = JSON.parse(fs50.readFileSync(headroomConfigPath(), "utf8"));
19695
19681
  configuredAgent = raw.agent ?? "";
19696
19682
  } catch {
19697
19683
  }
@@ -19725,7 +19711,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
19725
19711
  persist: persistHeadroomConfig,
19726
19712
  readEnabled: () => {
19727
19713
  try {
19728
- const raw = JSON.parse(fs49.readFileSync(headroomConfigPath(), "utf8"));
19714
+ const raw = JSON.parse(fs50.readFileSync(headroomConfigPath(), "utf8"));
19729
19715
  return raw.enabled === true;
19730
19716
  } catch {
19731
19717
  return false;
@@ -19814,7 +19800,7 @@ var headroomBudgetH = async (ctx, cmd) => {
19814
19800
  }
19815
19801
  let headroomActive = false;
19816
19802
  try {
19817
- const raw = JSON.parse(fs49.readFileSync(headroomConfigPath(), "utf8"));
19803
+ const raw = JSON.parse(fs50.readFileSync(headroomConfigPath(), "utf8"));
19818
19804
  headroomActive = raw.enabled === true;
19819
19805
  } catch {
19820
19806
  }
@@ -19824,7 +19810,7 @@ var headroomBudgetH = async (ctx, cmd) => {
19824
19810
  }
19825
19811
  let existingConfig = { enabled: true };
19826
19812
  try {
19827
- existingConfig = JSON.parse(fs49.readFileSync(headroomConfigPath(), "utf8"));
19813
+ existingConfig = JSON.parse(fs50.readFileSync(headroomConfigPath(), "utf8"));
19828
19814
  } catch {
19829
19815
  }
19830
19816
  if (payload.budgetEnabled && payload.budgetUsd != null) {
@@ -19942,7 +19928,7 @@ var CLI_UPDATE_MAX_ATTEMPTS = 3;
19942
19928
  function buildNpmInstallInvocation(opts) {
19943
19929
  const entryScript = opts?.entryScript ?? process.argv[1] ?? "";
19944
19930
  const execPath = opts?.execPath ?? process.execPath;
19945
- const exists2 = opts?.existsSync ?? fs49.existsSync;
19931
+ const exists2 = opts?.existsSync ?? fs50.existsSync;
19946
19932
  const normalized = entryScript.split(path53.sep).join("/");
19947
19933
  const marker = "/lib/node_modules/codeam-cli/";
19948
19934
  const markerIdx = normalized.indexOf(marker);
@@ -20790,12 +20776,9 @@ function readTokenFromArgs(args2) {
20790
20776
  if (fileFlag) {
20791
20777
  const path68 = fileFlag.slice("--token-file=".length);
20792
20778
  try {
20793
- const content = fs50.readFileSync(path68, "utf8").trim();
20779
+ const content = fs51.readFileSync(path68, "utf8").trim();
20794
20780
  if (content.length === 0) fail(`--token-file ${path68} is empty`);
20795
- try {
20796
- fs50.unlinkSync(path68);
20797
- } catch {
20798
- }
20781
+ rmIfExistsQuiet(path68);
20799
20782
  return content;
20800
20783
  } catch (err) {
20801
20784
  fail(`Could not read --token-file: ${err.message}`);
@@ -20890,7 +20873,7 @@ function isLivePairAuto(pid) {
20890
20873
  if (e.code !== "EPERM") return false;
20891
20874
  }
20892
20875
  try {
20893
- return fs50.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
20876
+ return fs51.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
20894
20877
  } catch {
20895
20878
  return true;
20896
20879
  }
@@ -20905,19 +20888,19 @@ function daemonLockPath(sessionId) {
20905
20888
  function acquireDaemonLock(sessionId) {
20906
20889
  const lockPath = daemonLockPath(sessionId);
20907
20890
  try {
20908
- fs50.mkdirSync(path54.dirname(lockPath), { recursive: true });
20891
+ fs51.mkdirSync(path54.dirname(lockPath), { recursive: true });
20909
20892
  try {
20910
- fs50.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
20893
+ fs51.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
20911
20894
  } catch (e) {
20912
20895
  if (e.code !== "EEXIST") throw e;
20913
- const holder = Number(fs50.readFileSync(lockPath, "utf8").trim());
20896
+ const holder = Number(fs51.readFileSync(lockPath, "utf8").trim());
20914
20897
  if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
20915
- fs50.writeFileSync(lockPath, String(process.pid));
20898
+ fs51.writeFileSync(lockPath, String(process.pid));
20916
20899
  }
20917
20900
  const release3 = () => {
20918
20901
  try {
20919
- if (fs50.existsSync(lockPath) && Number(fs50.readFileSync(lockPath, "utf8").trim()) === process.pid) {
20920
- fs50.unlinkSync(lockPath);
20902
+ if (fs51.existsSync(lockPath) && Number(fs51.readFileSync(lockPath, "utf8").trim()) === process.pid) {
20903
+ fs51.unlinkSync(lockPath);
20921
20904
  }
20922
20905
  } catch {
20923
20906
  }
@@ -20939,19 +20922,19 @@ function acquireDaemonLock(sessionId) {
20939
20922
  function acquireSingletonLock() {
20940
20923
  const lockPath = pairAutoLockPath();
20941
20924
  try {
20942
- fs50.mkdirSync(path54.dirname(lockPath), { recursive: true });
20925
+ fs51.mkdirSync(path54.dirname(lockPath), { recursive: true });
20943
20926
  try {
20944
- fs50.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
20927
+ fs51.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
20945
20928
  } catch (e) {
20946
20929
  if (e.code !== "EEXIST") throw e;
20947
- const holder = Number(fs50.readFileSync(lockPath, "utf8").trim());
20930
+ const holder = Number(fs51.readFileSync(lockPath, "utf8").trim());
20948
20931
  if (isLivePairAuto(holder)) return false;
20949
- fs50.writeFileSync(lockPath, String(process.pid));
20932
+ fs51.writeFileSync(lockPath, String(process.pid));
20950
20933
  }
20951
20934
  process.once("exit", () => {
20952
20935
  try {
20953
- if (fs50.existsSync(lockPath) && Number(fs50.readFileSync(lockPath, "utf8").trim()) === process.pid) {
20954
- fs50.unlinkSync(lockPath);
20936
+ if (fs51.existsSync(lockPath) && Number(fs51.readFileSync(lockPath, "utf8").trim()) === process.pid) {
20937
+ fs51.unlinkSync(lockPath);
20955
20938
  }
20956
20939
  } catch {
20957
20940
  }
@@ -21630,7 +21613,7 @@ function requiresAcp(agent) {
21630
21613
  var import_node_crypto7 = require("crypto");
21631
21614
 
21632
21615
  // src/services/history.service.ts
21633
- var fs52 = __toESM(require("fs"));
21616
+ var fs53 = __toESM(require("fs"));
21634
21617
  var path57 = __toESM(require("path"));
21635
21618
  var os41 = __toESM(require("os"));
21636
21619
  var https7 = __toESM(require("https"));
@@ -21659,7 +21642,7 @@ function parseJsonl(filePath) {
21659
21642
  const messages = [];
21660
21643
  let raw;
21661
21644
  try {
21662
- raw = fs52.readFileSync(filePath, "utf8");
21645
+ raw = fs53.readFileSync(filePath, "utf8");
21663
21646
  } catch (err) {
21664
21647
  if (err.code !== "ENOENT") {
21665
21648
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -21849,9 +21832,9 @@ var HistoryService = class _HistoryService {
21849
21832
  const dir = this.projectDir;
21850
21833
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
21851
21834
  try {
21852
- const files = fs52.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
21835
+ const files = fs53.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
21853
21836
  try {
21854
- const stat3 = fs52.statSync(path57.join(dir, e.name));
21837
+ const stat3 = fs53.statSync(path57.join(dir, e.name));
21855
21838
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
21856
21839
  } catch {
21857
21840
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -21892,13 +21875,13 @@ var HistoryService = class _HistoryService {
21892
21875
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
21893
21876
  let entries;
21894
21877
  try {
21895
- entries = fs52.readdirSync(dir, { withFileTypes: true });
21878
+ entries = fs53.readdirSync(dir, { withFileTypes: true });
21896
21879
  } catch {
21897
21880
  return null;
21898
21881
  }
21899
21882
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
21900
21883
  try {
21901
- const stat3 = fs52.statSync(path57.join(dir, e.name));
21884
+ const stat3 = fs53.statSync(path57.join(dir, e.name));
21902
21885
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
21903
21886
  } catch {
21904
21887
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -21912,7 +21895,7 @@ var HistoryService = class _HistoryService {
21912
21895
  extractUsageFromFile(filePath) {
21913
21896
  let raw;
21914
21897
  try {
21915
- raw = fs52.readFileSync(filePath, "utf8");
21898
+ raw = fs53.readFileSync(filePath, "utf8");
21916
21899
  } catch {
21917
21900
  return null;
21918
21901
  }
@@ -21957,9 +21940,9 @@ var HistoryService = class _HistoryService {
21957
21940
  let totalCost = 0;
21958
21941
  let files;
21959
21942
  try {
21960
- files = fs52.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
21943
+ files = fs53.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
21961
21944
  try {
21962
- return fs52.statSync(path57.join(projectDir, f)).mtimeMs >= monthStartMs;
21945
+ return fs53.statSync(path57.join(projectDir, f)).mtimeMs >= monthStartMs;
21963
21946
  } catch {
21964
21947
  return false;
21965
21948
  }
@@ -21970,7 +21953,7 @@ var HistoryService = class _HistoryService {
21970
21953
  for (const file of files) {
21971
21954
  let raw;
21972
21955
  try {
21973
- raw = fs52.readFileSync(path57.join(projectDir, file), "utf8");
21956
+ raw = fs53.readFileSync(path57.join(projectDir, file), "utf8");
21974
21957
  } catch {
21975
21958
  continue;
21976
21959
  }
@@ -22139,7 +22122,7 @@ var HistoryService = class _HistoryService {
22139
22122
  if (!filePath) return false;
22140
22123
  let mtimeMs;
22141
22124
  try {
22142
- mtimeMs = fs52.statSync(filePath).mtimeMs;
22125
+ mtimeMs = fs53.statSync(filePath).mtimeMs;
22143
22126
  } catch {
22144
22127
  return false;
22145
22128
  }
@@ -22208,7 +22191,7 @@ var HistoryService = class _HistoryService {
22208
22191
 
22209
22192
  // src/agents/acp/client.ts
22210
22193
  var import_node_child_process21 = require("child_process");
22211
- var fs53 = __toESM(require("fs/promises"));
22194
+ var fs54 = __toESM(require("fs/promises"));
22212
22195
  var fsSync = __toESM(require("fs"));
22213
22196
  var os42 = __toESM(require("os"));
22214
22197
  var path58 = __toESM(require("path"));
@@ -24987,10 +24970,7 @@ var AcpClient = class {
24987
24970
  child.kill("SIGTERM");
24988
24971
  const grace = new Promise((resolve7) => {
24989
24972
  const t2 = setTimeout(() => {
24990
- try {
24991
- child.kill("SIGKILL");
24992
- } catch {
24993
- }
24973
+ killQuiet(child, "SIGKILL");
24994
24974
  resolve7();
24995
24975
  }, 2e3);
24996
24976
  child.once("exit", () => {
@@ -25044,7 +25024,7 @@ var AcpClient = class {
25044
25024
  },
25045
25025
  readTextFile: async (params) => {
25046
25026
  try {
25047
- const content = await fs53.readFile(params.path, "utf8");
25027
+ const content = await fs54.readFile(params.path, "utf8");
25048
25028
  return applyLineRange(content, params.line ?? null, params.limit ?? null);
25049
25029
  } catch (err) {
25050
25030
  const code = err.code;
@@ -25064,7 +25044,7 @@ var AcpClient = class {
25064
25044
  },
25065
25045
  writeTextFile: async (params) => {
25066
25046
  try {
25067
- await fs53.writeFile(params.path, params.content, "utf8");
25047
+ await fs54.writeFile(params.path, params.content, "utf8");
25068
25048
  return {};
25069
25049
  } catch (err) {
25070
25050
  const code = err.code;
@@ -25478,67 +25458,6 @@ var AcpPublisher = class {
25478
25458
  }
25479
25459
  };
25480
25460
 
25481
- // src/agents/acp/oneMContextRecovery.ts
25482
- var ONE_M_CONTEXT_CREDITS_RE = /usage credits required for 1m context/i;
25483
- function looksLike1mContextCreditsError(text) {
25484
- return ONE_M_CONTEXT_CREDITS_RE.test(text);
25485
- }
25486
- var ONE_M_DISABLE_OPTION = "Disable 1M context and continue";
25487
- function shouldOfferOneMRecovery(opts) {
25488
- return looksLike1mContextCreditsError(opts.detail) || looksLike1mContextCreditsError(opts.recentStderr) || looksLike1mContextCreditsError(opts.finalText);
25489
- }
25490
- function oneMRecoverySelectPrompt() {
25491
- return {
25492
- question: "\u26A0\uFE0F This agent's Anthropic account needs usage credits for 1M context. You can disable 1M context (uses standard 200K context) and continue.",
25493
- options: [ONE_M_DISABLE_OPTION]
25494
- };
25495
- }
25496
- function createOneMRecovery(deps) {
25497
- let pending = null;
25498
- const sp = oneMRecoverySelectPrompt();
25499
- return {
25500
- offer: async (commandId, blocks) => {
25501
- pending = { blocks };
25502
- await deps.publishText(sp.question);
25503
- await deps.publishSelectPrompt(sp.question, sp.options);
25504
- await deps.publishAwaitingAnswer(sp.question, sp.options);
25505
- deps.appendAgentReply(sp.question);
25506
- deps.flushHistory();
25507
- deps.log?.(`1M-context credits gate \u2014 recovery offered id=${commandId.slice(0, 8)}`);
25508
- await deps.sendResult(commandId, "failed", {
25509
- error: "1M context requires usage credits \u2014 recovery offered"
25510
- });
25511
- },
25512
- tryRecover: async (commandId) => {
25513
- if (!pending) return false;
25514
- const blocks = pending.blocks;
25515
- pending = null;
25516
- deps.log?.("1M-context recovery \u2192 disable + reconnect + rerun");
25517
- await deps.reconnectWith1mDisabled();
25518
- await deps.beginTurn();
25519
- try {
25520
- const reply = await deps.promptAgent(blocks);
25521
- const finalText = deps.getCurrentText();
25522
- await deps.closeTurn();
25523
- deps.appendAgentReply(finalText);
25524
- deps.flushHistory();
25525
- await deps.sendResult(commandId, "completed", { stopReason: reply.stopReason });
25526
- } catch (err) {
25527
- await deps.recoverFromFailedTurn();
25528
- const d3 = deps.describeError(err);
25529
- const b = deps.failureBubbleFor(d3);
25530
- if (b) {
25531
- await deps.publishText(b);
25532
- deps.appendAgentReply(b);
25533
- deps.flushHistory();
25534
- }
25535
- await deps.sendResult(commandId, "failed", { error: d3 });
25536
- }
25537
- return true;
25538
- }
25539
- };
25540
- }
25541
-
25542
25461
  // src/agents/acp/budgetRecovery.ts
25543
25462
  var BUDGET_EXCEEDED_RE = /budget exceeded for (\w+) period/i;
25544
25463
  function looksLikeBudgetExceeded(text) {
@@ -25663,15 +25582,15 @@ function commonPrefixLength(a, b) {
25663
25582
 
25664
25583
  // src/agents/acp/onboarding.ts
25665
25584
  var import_child_process26 = require("child_process");
25666
- var fs54 = __toESM(require("fs"));
25585
+ var fs55 = __toESM(require("fs"));
25667
25586
  var os43 = __toESM(require("os"));
25668
25587
  var path59 = __toESM(require("path"));
25669
25588
  var _onboardingSeam = {
25670
25589
  markerPath: (sessionId) => path59.join(os43.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
25671
- exists: (p2) => fs54.existsSync(p2),
25590
+ exists: (p2) => fs55.existsSync(p2),
25672
25591
  write: (p2) => {
25673
- fs54.mkdirSync(path59.dirname(p2), { recursive: true });
25674
- fs54.writeFileSync(p2, "");
25592
+ fs55.mkdirSync(path59.dirname(p2), { recursive: true });
25593
+ fs55.writeFileSync(p2, "");
25675
25594
  },
25676
25595
  disabled: () => {
25677
25596
  const v = process.env.CODEAM_ONBOARDING_DISABLED;
@@ -25960,7 +25879,7 @@ var import_crypto5 = require("crypto");
25960
25879
 
25961
25880
  // src/services/turn-files/git-changeset.ts
25962
25881
  var import_child_process27 = require("child_process");
25963
- var fs55 = __toESM(require("fs/promises"));
25882
+ var fs56 = __toESM(require("fs/promises"));
25964
25883
  var path60 = __toESM(require("path"));
25965
25884
  async function collectRepoChangeset(opts) {
25966
25885
  const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
@@ -26010,7 +25929,7 @@ function readUntrackedLineCount(absPath) {
26010
25929
  }
26011
25930
  async function defaultReadUntrackedLineCount(absPath) {
26012
25931
  try {
26013
- const content = await fs55.readFile(absPath, "utf8");
25932
+ const content = await fs56.readFile(absPath, "utf8");
26014
25933
  let count = 0;
26015
25934
  let pos = -1;
26016
25935
  while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
@@ -26102,7 +26021,7 @@ function defaultRunGit(cwd, args2) {
26102
26021
  });
26103
26022
  }
26104
26023
  async function discoverRepos(workingDir, maxDepth = 4) {
26105
- const fs59 = await import("fs/promises");
26024
+ const fs60 = await import("fs/promises");
26106
26025
  const out2 = [];
26107
26026
  await walk(workingDir, 0);
26108
26027
  return out2;
@@ -26110,7 +26029,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
26110
26029
  if (depth > maxDepth) return;
26111
26030
  let entries = [];
26112
26031
  try {
26113
- const dirents = await fs59.readdir(dir, { withFileTypes: true });
26032
+ const dirents = await fs60.readdir(dir, { withFileTypes: true });
26114
26033
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
26115
26034
  } catch {
26116
26035
  return;
@@ -26136,7 +26055,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
26136
26055
  }
26137
26056
 
26138
26057
  // src/services/turn-files/files-outbox.ts
26139
- var fs56 = __toESM(require("fs/promises"));
26058
+ var fs57 = __toESM(require("fs/promises"));
26140
26059
  var path61 = __toESM(require("path"));
26141
26060
  var import_os7 = require("os");
26142
26061
  var HOME_OUTBOX_DIR = ".codeam/outbox";
@@ -26178,8 +26097,8 @@ var FilesOutbox = class {
26178
26097
  /** Persist the entry to disk and trigger a flush. Returns once the
26179
26098
  * line is durable on disk (not once the POST succeeds). */
26180
26099
  async enqueue(entry) {
26181
- await fs56.mkdir(path61.dirname(this.filePath), { recursive: true });
26182
- await fs56.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
26100
+ await fs57.mkdir(path61.dirname(this.filePath), { recursive: true });
26101
+ await fs57.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
26183
26102
  this.backoffIndex = 0;
26184
26103
  if (this.autoSchedule) this.scheduleFlush(0);
26185
26104
  }
@@ -26268,7 +26187,7 @@ var FilesOutbox = class {
26268
26187
  async readAll() {
26269
26188
  let raw = "";
26270
26189
  try {
26271
- raw = await fs56.readFile(this.filePath, "utf8");
26190
+ raw = await fs57.readFile(this.filePath, "utf8");
26272
26191
  } catch {
26273
26192
  return [];
26274
26193
  }
@@ -26292,12 +26211,12 @@ var FilesOutbox = class {
26292
26211
  async rewrite(entries) {
26293
26212
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
26294
26213
  if (entries.length === 0) {
26295
- await fs56.unlink(this.filePath).catch(() => void 0);
26214
+ await fs57.unlink(this.filePath).catch(() => void 0);
26296
26215
  return;
26297
26216
  }
26298
26217
  const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
26299
- await fs56.writeFile(tmpPath, payload, "utf8");
26300
- await fs56.rename(tmpPath, this.filePath);
26218
+ await fs57.writeFile(tmpPath, payload, "utf8");
26219
+ await fs57.rename(tmpPath, this.filePath);
26301
26220
  }
26302
26221
  };
26303
26222
  function applyJitter(ms) {
@@ -26506,6 +26425,50 @@ function withTimeout(p2, ms) {
26506
26425
  });
26507
26426
  }
26508
26427
 
26428
+ // src/agents/acp/oneMContextRecovery.ts
26429
+ var ONE_M_CONTEXT_CREDITS_RE = /usage credits required for 1m context/i;
26430
+ function looksLike1mContextCreditsError(text) {
26431
+ return ONE_M_CONTEXT_CREDITS_RE.test(text);
26432
+ }
26433
+ function shouldOfferOneMRecovery(opts) {
26434
+ return looksLike1mContextCreditsError(opts.detail) || looksLike1mContextCreditsError(opts.recentStderr) || looksLike1mContextCreditsError(opts.finalText);
26435
+ }
26436
+
26437
+ // src/agents/acp/agent-hooks.ts
26438
+ function replyIsCursorUpgradeRequired(finalText) {
26439
+ const t2 = finalText.trim().toLowerCase();
26440
+ if (t2.length === 0 || t2.length > 200) return false;
26441
+ return t2.includes("upgrade your plan to continue") || t2.includes("upgrade your plan") && t2.includes("continue");
26442
+ }
26443
+ function isGeminiIneligibleTier(haystack) {
26444
+ return /IneligibleTierError|UNSUPPORTED_CLIENT|no longer supported for Gemini Code Assist|not eligible for Gemini Code Assist/i.test(
26445
+ haystack
26446
+ );
26447
+ }
26448
+ var ACP_AGENT_HOOKS = {
26449
+ claude: {
26450
+ statusPage: { vendor: "Anthropic", url: "https://status.anthropic.com" }
26451
+ },
26452
+ codex: {
26453
+ statusPage: { vendor: "OpenAI", url: "https://status.openai.com" },
26454
+ startupExtraEnv: ({ autoApprovePermissions }) => autoApprovePermissions ? { INITIAL_AGENT_MODE: "agent-full-access" } : {}
26455
+ },
26456
+ gemini: {
26457
+ statusPage: { vendor: "Google", url: "https://status.cloud.google.com" },
26458
+ classifyStartupFailure: (haystack) => isGeminiIneligibleTier(haystack) ? "ineligible_tier" : null
26459
+ },
26460
+ copilot: {
26461
+ statusPage: { vendor: "GitHub", url: "https://www.githubstatus.com" }
26462
+ },
26463
+ cursor: {
26464
+ statusPage: { vendor: "Cursor", url: "https://status.cursor.com" },
26465
+ classifyCompletedReply: (finalText) => replyIsCursorUpgradeRequired(finalText) ? "upgrade_required" : null
26466
+ }
26467
+ };
26468
+ function agentHooks(agent) {
26469
+ return ACP_AGENT_HOOKS[agent];
26470
+ }
26471
+
26509
26472
  // src/agents/acp/failure-messages.ts
26510
26473
  function describeError(err) {
26511
26474
  if (err instanceof Error) return err.message;
@@ -26520,11 +26483,6 @@ function replyIsAuthFailure(finalText) {
26520
26483
  return t2.length > 0 && t2.length <= 200 && looksLikeAuthFailure(t2);
26521
26484
  }
26522
26485
  var AUTH_FAILURE_MESSAGE = "\u{1F512} **Authentication failed \u2014 your agent credentials are invalid or expired (API 401).**\n\nTap [Re-authenticate this agent](codeam://reauth) to renew your credentials in Profile \u203A Agents, then send your message again.";
26523
- function replyIsCursorUpgradeRequired(finalText) {
26524
- const t2 = finalText.trim().toLowerCase();
26525
- if (t2.length === 0 || t2.length > 200) return false;
26526
- return t2.includes("upgrade your plan to continue") || t2.includes("upgrade your plan") && t2.includes("continue");
26527
- }
26528
26486
  var CURSOR_UPGRADE_MESSAGE = "\u26A1 **Cursor needs a paid plan to run the agent.**\n\nThe headless Cursor Agent requires Cursor **Pro** \u2014 your Free plan\u2019s included usage does NOT cover Agent runs, even with quota left. This is your Cursor account (not CodeAgent). Upgrade, then send your message again:\n\n[Upgrade to Cursor Pro \u2192](https://cursor.com/dashboard)";
26529
26487
  var ONE_M_CREDITS_MESSAGE = "\u{1F504} **Reconnect your Claude subscription to continue.**\n\nClaude requested 1M-context but your account doesn\u2019t have the usage credits for it on this credential. Reconnecting refreshes your subscription so the agent can keep going \u2014 disabling 1M context won\u2019t fix a credits gate.\n\nTap [Reconnect this agent](codeam://reauth) to reconnect your Claude subscription in Profile \u203A Agents, then send your message again.";
26530
26488
  var TURN_FAILURE_MESSAGE = "\u26A0\uFE0F **The agent hit an error and couldn\u2019t finish this turn.** Please send your message again.";
@@ -26534,17 +26492,8 @@ function looksLikeProviderOutage(text) {
26534
26492
  }
26535
26493
  function agentStatusPage(agent) {
26536
26494
  const a = (agent ?? "").toLowerCase();
26537
- if (a.includes("claude") || a.includes("anthropic"))
26538
- return { vendor: "Anthropic", url: "https://status.anthropic.com" };
26539
- if (a.includes("codex") || a.includes("openai"))
26540
- return { vendor: "OpenAI", url: "https://status.openai.com" };
26541
- if (a.includes("gemini") || a.includes("google"))
26542
- return { vendor: "Google", url: "https://status.cloud.google.com" };
26543
- if (a.includes("copilot"))
26544
- return { vendor: "GitHub", url: "https://www.githubstatus.com" };
26545
- if (a.includes("cursor"))
26546
- return { vendor: "Cursor", url: "https://status.cursor.com" };
26547
- return null;
26495
+ const id = a.includes("claude") || a.includes("anthropic") ? "claude" : a.includes("codex") || a.includes("openai") ? "codex" : a.includes("gemini") || a.includes("google") ? "gemini" : a.includes("copilot") ? "copilot" : a.includes("cursor") ? "cursor" : null;
26496
+ return id ? agentHooks(id)?.statusPage ?? null : null;
26548
26497
  }
26549
26498
  function providerOutageMessage(agent) {
26550
26499
  const info = agentStatusPage(agent);
@@ -26555,15 +26504,10 @@ The agent provider returned an overload/outage error, so this turn couldn\u2019t
26555
26504
 
26556
26505
  Follow the status here: [${info.url}](${info.url})` : "");
26557
26506
  }
26558
- function isGeminiIneligibleTier(haystack) {
26559
- return /IneligibleTierError|UNSUPPORTED_CLIENT|no longer supported for Gemini Code Assist|not eligible for Gemini Code Assist/i.test(
26560
- haystack
26561
- );
26562
- }
26563
26507
  function startupFailureMessage(agent, detail, recentStderr) {
26564
26508
  const haystack = `${detail}
26565
26509
  ${recentStderr}`;
26566
- if (agent === "gemini" && isGeminiIneligibleTier(haystack)) {
26510
+ if (agentHooks(agent)?.classifyStartupFailure?.(haystack) === "ineligible_tier") {
26567
26511
  return [
26568
26512
  "\u26A0\uFE0F **Gemini couldn't start \u2014 your Google account isn't eligible.**",
26569
26513
  "",
@@ -26750,19 +26694,13 @@ async function handleGetConversation(args2) {
26750
26694
  }
26751
26695
  function buildLegacyContextForACP(opts, relay, runtime) {
26752
26696
  return {
26753
- outputSvc: null,
26754
- agent: null,
26755
- historySvc: null,
26756
26697
  runtime,
26757
26698
  relay,
26758
- setKeepAlive: null,
26759
- keepAliveCtx: null,
26760
26699
  pluginId: opts.pluginId,
26761
26700
  sessionId: opts.sessionId,
26762
26701
  // The running ACP agent (claude/codex/gemini/cursor). REQUIRED: headroom_configure
26763
26702
  // resolves the agent from ctx.agentId; without it the enable gate sees '' and
26764
- // returns {supported:false} for a real Claude session (the `as unknown` cast
26765
- // below previously hid this missing field from the type checker).
26703
+ // returns {supported:false} for a real Claude session.
26766
26704
  agentId: opts.agent,
26767
26705
  pluginAuthToken: opts.pluginAuthToken
26768
26706
  };
@@ -26820,7 +26758,7 @@ async function startTaskH(ctx) {
26820
26758
  try {
26821
26759
  const reply = await client2.prompt(blocks);
26822
26760
  const finalText = streaming.getCurrentText();
26823
- if (opts.agent === "cursor" && replyIsCursorUpgradeRequired(finalText)) {
26761
+ if (agentHooks(opts.agent)?.classifyCompletedReply?.(finalText) === "upgrade_required") {
26824
26762
  await streaming.closeWithBubble(CURSOR_UPGRADE_MESSAGE);
26825
26763
  history.appendAgentReply(CURSOR_UPGRADE_MESSAGE);
26826
26764
  void history.flush();
@@ -26989,8 +26927,7 @@ async function ackEmptyH(ctx) {
26989
26927
  return;
26990
26928
  }
26991
26929
  async function selectOptionH(ctx) {
26992
- const { cmd, client: client2, relay, streaming, history, oneMRecovery, budgetRecovery } = ctx;
26993
- if (await oneMRecovery.tryRecover(cmd.id)) return;
26930
+ const { cmd, client: client2, relay, streaming, history, budgetRecovery } = ctx;
26994
26931
  const payload = cmd.payload;
26995
26932
  const index = typeof payload?.index === "number" ? payload.index : 0;
26996
26933
  const offset = typeof payload?.from === "number" ? payload.from : 0;
@@ -27710,9 +27647,12 @@ function buildRelaunchProxyEnv(baseEnv) {
27710
27647
  function computeAdapterExtraEnv(params) {
27711
27648
  const env = {};
27712
27649
  if (params.disable1mContext) env.CLAUDE_CODE_DISABLE_1M_CONTEXT = "1";
27713
- if (params.agent === "codex" && params.autoApprovePermissions) {
27714
- env.INITIAL_AGENT_MODE = "agent-full-access";
27715
- }
27650
+ Object.assign(
27651
+ env,
27652
+ agentHooks(params.agent)?.startupExtraEnv?.({
27653
+ autoApprovePermissions: params.autoApprovePermissions
27654
+ }) ?? {}
27655
+ );
27716
27656
  return env;
27717
27657
  }
27718
27658
  async function runAcpSession(opts) {
@@ -27818,48 +27758,7 @@ async function runAcpSession(opts) {
27818
27758
  })();
27819
27759
  }
27820
27760
  };
27821
- let client2 = new AcpClient(clientOptions);
27822
- const reconnectWith1mDisabled = async () => {
27823
- setDisable1mContext(opts.pluginId, true);
27824
- try {
27825
- await client2.stop();
27826
- } catch {
27827
- }
27828
- client2 = new AcpClient({
27829
- ...clientOptions,
27830
- extraEnv: { ...extraEnv, CLAUDE_CODE_DISABLE_1M_CONTEXT: "1" }
27831
- });
27832
- await client2.start();
27833
- };
27834
- const oneMRecovery = createOneMRecovery({
27835
- publishText: (text) => publisher.publishOutput({ type: "text", content: text, done: true }),
27836
- publishSelectPrompt: (question, options) => publisher.publishOutput({
27837
- type: "select_prompt",
27838
- content: question,
27839
- options,
27840
- optionDescriptions: options.map(() => ""),
27841
- currentIndex: 0,
27842
- done: true
27843
- }),
27844
- // The button driver — mobile renders the tappable option from this
27845
- // awaiting-answer event; the user's tap returns as a `select_option`
27846
- // command, caught at the top of the select_option case by tryRecover.
27847
- publishAwaitingAnswer: (prompt, options) => publisher.publishAwaitingAnswer({ questionId: (0, import_node_crypto7.randomUUID)(), prompt, options }),
27848
- sendResult: (commandId, status2, result) => relay.sendResult(commandId, status2, result),
27849
- appendAgentReply: (text) => history.appendAgentReply(text),
27850
- flushHistory: () => void history.flush(),
27851
- beginTurn: () => streaming.beginTurn(),
27852
- getCurrentText: () => streaming.getCurrentText(),
27853
- closeTurn: async () => {
27854
- await streaming.closeTurnWithInteractiveDetection();
27855
- },
27856
- recoverFromFailedTurn: () => recoverFromFailedTurn(client2, streaming),
27857
- reconnectWith1mDisabled,
27858
- promptAgent: (blocks) => client2.prompt(blocks),
27859
- failureBubbleFor: (detail) => failureBubble({ detail, recentStderr: recentStderr.join("\n"), hadText: false, agent: opts.agent }),
27860
- describeError,
27861
- log: (msg) => log.info("acpRunner", msg)
27862
- });
27761
+ const client2 = new AcpClient(clientOptions);
27863
27762
  let _budgetReachedPosted = false;
27864
27763
  const relaunchProxyWithoutBudget = async () => {
27865
27764
  const { spawn: spawn38 } = await import("child_process");
@@ -28013,7 +27912,6 @@ async function runAcpSession(opts) {
28013
27912
  getBeads,
28014
27913
  publisher,
28015
27914
  recentStderr,
28016
- oneMRecovery,
28017
27915
  budgetRecovery,
28018
27916
  { get: () => _budgetReachedPosted, set: (v) => {
28019
27917
  _budgetReachedPosted = v;
@@ -28052,7 +27950,7 @@ async function runAcpSession(opts) {
28052
27950
  await new Promise(() => {
28053
27951
  });
28054
27952
  }
28055
- async function handleCommand(cmd, client2, relay, acpSessionId, models, streaming, opts, history, jsonlHistory, agentCaps, turnFiles, getBeads, publisher, recentStderr, oneMRecovery, budgetRecovery, budgetReachedFlag) {
27953
+ async function handleCommand(cmd, client2, relay, acpSessionId, models, streaming, opts, history, jsonlHistory, agentCaps, turnFiles, getBeads, publisher, recentStderr, budgetRecovery, budgetReachedFlag) {
28056
27954
  await dispatchAcpCommand({
28057
27955
  cmd,
28058
27956
  client: client2,
@@ -28068,7 +27966,6 @@ async function handleCommand(cmd, client2, relay, acpSessionId, models, streamin
28068
27966
  getBeads,
28069
27967
  publisher,
28070
27968
  recentStderr,
28071
- oneMRecovery,
28072
27969
  budgetRecovery,
28073
27970
  budgetReachedFlag
28074
27971
  });
@@ -29079,7 +28976,7 @@ function fetchQuotaUsage(runtime, historySvc) {
29079
28976
  }
29080
28977
 
29081
28978
  // src/agents/claude/onboarding.ts
29082
- var fs57 = __toESM(require("fs"));
28979
+ var fs58 = __toESM(require("fs"));
29083
28980
  var os44 = __toESM(require("os"));
29084
28981
  var path62 = __toESM(require("path"));
29085
28982
  function ensureClaudeOnboarded() {
@@ -29087,7 +28984,7 @@ function ensureClaudeOnboarded() {
29087
28984
  const file = path62.join(os44.homedir(), ".claude.json");
29088
28985
  let config = {};
29089
28986
  try {
29090
- config = JSON.parse(fs57.readFileSync(file, "utf8"));
28987
+ config = JSON.parse(fs58.readFileSync(file, "utf8"));
29091
28988
  } catch {
29092
28989
  }
29093
28990
  if (config.hasCompletedOnboarding === true && typeof config.theme === "string") {
@@ -29098,8 +28995,8 @@ function ensureClaudeOnboarded() {
29098
28995
  if (typeof config.lastOnboardingVersion !== "string") {
29099
28996
  config.lastOnboardingVersion = "2.1.177";
29100
28997
  }
29101
- fs57.mkdirSync(path62.dirname(file), { recursive: true });
29102
- fs57.writeFileSync(file, JSON.stringify(config, null, 2));
28998
+ fs58.mkdirSync(path62.dirname(file), { recursive: true });
28999
+ fs58.writeFileSync(file, JSON.stringify(config, null, 2));
29103
29000
  log.info("claude", "pre-completed Claude onboarding (skip first-run theme picker)");
29104
29001
  } catch (err) {
29105
29002
  log.warn("claude", `ensureClaudeOnboarded failed (non-fatal): ${err.message}`);
@@ -29429,7 +29326,7 @@ async function start(requestedAgent) {
29429
29326
  var import_crypto7 = require("crypto");
29430
29327
  var import_picocolors5 = __toESM(require("picocolors"));
29431
29328
 
29432
- // src/utils/agent-prompt.ts
29329
+ // src/lib/agent-prompt.ts
29433
29330
  function parseAgentFlag(args2) {
29434
29331
  const flag = args2.find((a) => a.startsWith("--agent="));
29435
29332
  if (!flag) return null;
@@ -31801,7 +31698,7 @@ async function invite() {
31801
31698
  var import_node_dns = require("dns");
31802
31699
  var import_node_util5 = require("util");
31803
31700
  var import_node_crypto8 = require("crypto");
31804
- var fs58 = __toESM(require("fs"));
31701
+ var fs59 = __toESM(require("fs"));
31805
31702
  var path67 = __toESM(require("path"));
31806
31703
  var import_picocolors14 = __toESM(require("picocolors"));
31807
31704
  var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
@@ -31860,11 +31757,11 @@ async function checkHealth(apiBase2) {
31860
31757
  function checkConfigDir() {
31861
31758
  const dir = path67.join(require("os").homedir(), ".codeam");
31862
31759
  try {
31863
- fs58.mkdirSync(dir, { recursive: true, mode: 448 });
31760
+ fs59.mkdirSync(dir, { recursive: true, mode: 448 });
31864
31761
  const probe = path67.join(dir, ".doctor-probe");
31865
- fs58.writeFileSync(probe, "ok", { mode: 384 });
31866
- const read2 = fs58.readFileSync(probe, "utf8");
31867
- fs58.unlinkSync(probe);
31762
+ fs59.writeFileSync(probe, "ok", { mode: 384 });
31763
+ const read2 = fs59.readFileSync(probe, "utf8");
31764
+ fs59.unlinkSync(probe);
31868
31765
  if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
31869
31766
  return {
31870
31767
  id: "config-dir",
@@ -31970,7 +31867,7 @@ function checkChokidar() {
31970
31867
  }
31971
31868
  async function doctor(args2 = []) {
31972
31869
  const json = args2.includes("--json");
31973
- const cliVersion = true ? "2.56.0" : "0.0.0-dev";
31870
+ const cliVersion = true ? "2.58.0" : "0.0.0-dev";
31974
31871
  const apiBase2 = resolveApiBaseUrl();
31975
31872
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
31976
31873
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -32169,7 +32066,7 @@ async function completion(args2) {
32169
32066
  // src/commands/version.ts
32170
32067
  var import_picocolors15 = __toESM(require("picocolors"));
32171
32068
  function version2() {
32172
- const v = true ? "2.56.0" : "unknown";
32069
+ const v = true ? "2.58.0" : "unknown";
32173
32070
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
32174
32071
  }
32175
32072