codeam-cli 2.27.0 → 2.27.2

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 +6 -0
  2. package/dist/index.js +1054 -438
  3. package/package.json +5 -1
package/dist/index.js CHANGED
@@ -300,6 +300,18 @@ var AGENT_REGISTRY = {
300
300
  // this via the existing --api-key escape hatch in commands/link.ts.
301
301
  supportedAuthKinds: ["api_key"],
302
302
  preferredAuthKind: "api_key"
303
+ },
304
+ gemini: {
305
+ id: "gemini",
306
+ displayName: "Gemini CLI",
307
+ binaryName: "gemini",
308
+ enabled: true,
309
+ // Gemini speaks ACP natively via `gemini --acp` — pairing flows
310
+ // through the ACP runtime, not a PTY parser. Auth is the user's
311
+ // existing `gemini auth login` (OAuth) or GEMINI_API_KEY env var,
312
+ // both managed by the gemini binary itself.
313
+ supportedAuthKinds: ["api_key"],
314
+ preferredAuthKind: "api_key"
303
315
  }
304
316
  };
305
317
  function getEnabledAgents() {
@@ -311,7 +323,7 @@ function getAgent(id) {
311
323
  return meta;
312
324
  }
313
325
  function isKnownAgentId(id) {
314
- return id === "claude" || id === "codex" || id === "copilot" || id === "coderabbit" || id === "cursor" || id === "aider";
326
+ return id === "claude" || id === "codex" || id === "copilot" || id === "coderabbit" || id === "cursor" || id === "aider" || id === "gemini";
315
327
  }
316
328
 
317
329
  // ../../packages/shared/src/api-url.ts
@@ -486,7 +498,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
486
498
  // package.json
487
499
  var package_default = {
488
500
  name: "codeam-cli",
489
- version: "2.27.0",
501
+ version: "2.27.2",
490
502
  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.",
491
503
  type: "commonjs",
492
504
  main: "dist/index.js",
@@ -556,8 +568,12 @@ var package_default = {
556
568
  node: ">=18.0.0"
557
569
  },
558
570
  dependencies: {
571
+ "@agentclientprotocol/claude-agent-acp": "^0.42.0",
572
+ "@agentclientprotocol/codex-acp": "^0.0.45",
573
+ "@agentclientprotocol/sdk": "^0.25.0",
559
574
  "@clack/prompts": "^1.2.0",
560
575
  chokidar: "^3.6.0",
576
+ "cursor-agent-acp": "^0.1.1",
561
577
  picocolors: "^1.1.0",
562
578
  "qrcode-terminal": "^0.12.0",
563
579
  which: "^5.0.0",
@@ -853,7 +869,7 @@ async function postPreviewEvent(input) {
853
869
  }
854
870
  }
855
871
  async function _postJsonAuthed(url, body, pluginAuthToken) {
856
- return new Promise((resolve5, reject) => {
872
+ return new Promise((resolve6, reject) => {
857
873
  const data = JSON.stringify(body);
858
874
  const u2 = new URL(url);
859
875
  const transport = u2.protocol === "https:" ? https : http;
@@ -874,8 +890,8 @@ async function _postJsonAuthed(url, body, pluginAuthToken) {
874
890
  (res) => {
875
891
  res.on("error", reject);
876
892
  let responseBody = "";
877
- res.on("data", (chunk) => {
878
- responseBody += chunk.toString();
893
+ res.on("data", (chunk2) => {
894
+ responseBody += chunk2.toString();
879
895
  });
880
896
  res.on("end", () => {
881
897
  if (res.statusCode && res.statusCode >= 400) {
@@ -885,9 +901,9 @@ async function _postJsonAuthed(url, body, pluginAuthToken) {
885
901
  return;
886
902
  }
887
903
  try {
888
- resolve5(JSON.parse(responseBody));
904
+ resolve6(JSON.parse(responseBody));
889
905
  } catch {
890
- resolve5(null);
906
+ resolve6(null);
891
907
  }
892
908
  });
893
909
  }
@@ -902,7 +918,7 @@ async function _postJsonAuthed(url, body, pluginAuthToken) {
902
918
  });
903
919
  }
904
920
  async function _postJson(url, body) {
905
- return new Promise((resolve5, reject) => {
921
+ return new Promise((resolve6, reject) => {
906
922
  const data = JSON.stringify(body);
907
923
  const u2 = new URL(url);
908
924
  const transport = u2.protocol === "https:" ? https : http;
@@ -922,8 +938,8 @@ async function _postJson(url, body) {
922
938
  (res) => {
923
939
  res.on("error", reject);
924
940
  let body2 = "";
925
- res.on("data", (chunk) => {
926
- body2 += chunk.toString();
941
+ res.on("data", (chunk2) => {
942
+ body2 += chunk2.toString();
927
943
  });
928
944
  res.on("end", () => {
929
945
  if (res.statusCode && res.statusCode >= 400) {
@@ -931,9 +947,9 @@ async function _postJson(url, body) {
931
947
  return;
932
948
  }
933
949
  try {
934
- resolve5(JSON.parse(body2));
950
+ resolve6(JSON.parse(body2));
935
951
  } catch {
936
- resolve5(null);
952
+ resolve6(null);
937
953
  }
938
954
  });
939
955
  }
@@ -948,7 +964,7 @@ async function _postJson(url, body) {
948
964
  });
949
965
  }
950
966
  async function _getJson(url) {
951
- return new Promise((resolve5, reject) => {
967
+ return new Promise((resolve6, reject) => {
952
968
  const u2 = new URL(url);
953
969
  const transport = u2.protocol === "https:" ? https : http;
954
970
  const req = transport.request(
@@ -963,8 +979,8 @@ async function _getJson(url) {
963
979
  (res) => {
964
980
  res.on("error", reject);
965
981
  let body = "";
966
- res.on("data", (chunk) => {
967
- body += chunk.toString();
982
+ res.on("data", (chunk2) => {
983
+ body += chunk2.toString();
968
984
  });
969
985
  res.on("end", () => {
970
986
  if (res.statusCode && res.statusCode >= 400) {
@@ -972,9 +988,9 @@ async function _getJson(url) {
972
988
  return;
973
989
  }
974
990
  try {
975
- resolve5(JSON.parse(body));
991
+ resolve6(JSON.parse(body));
976
992
  } catch {
977
- resolve5(null);
993
+ resolve6(null);
978
994
  }
979
995
  });
980
996
  }
@@ -1144,8 +1160,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
1144
1160
  return decodedFile;
1145
1161
  };
1146
1162
  }
1147
- function normalizeWindowsPath(path43) {
1148
- return path43.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1163
+ function normalizeWindowsPath(path44) {
1164
+ return path44.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1149
1165
  }
1150
1166
 
1151
1167
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -3625,15 +3641,15 @@ async function addSourceContext(frames) {
3625
3641
  LRU_FILE_CONTENTS_CACHE.reduce();
3626
3642
  return frames;
3627
3643
  }
3628
- function getContextLinesFromFile(path43, ranges, output) {
3629
- return new Promise((resolve5) => {
3630
- const stream = (0, import_node_fs.createReadStream)(path43);
3644
+ function getContextLinesFromFile(path44, ranges, output) {
3645
+ return new Promise((resolve6) => {
3646
+ const stream = (0, import_node_fs.createReadStream)(path44);
3631
3647
  const lineReaded = (0, import_node_readline.createInterface)({
3632
3648
  input: stream
3633
3649
  });
3634
3650
  function destroyStreamAndResolve() {
3635
3651
  stream.destroy();
3636
- resolve5();
3652
+ resolve6();
3637
3653
  }
3638
3654
  let lineNumber = 0;
3639
3655
  let currentRangeIndex = 0;
@@ -3642,7 +3658,7 @@ function getContextLinesFromFile(path43, ranges, output) {
3642
3658
  let rangeStart = range[0];
3643
3659
  let rangeEnd = range[1];
3644
3660
  function onStreamError() {
3645
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path43, 1);
3661
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path44, 1);
3646
3662
  lineReaded.close();
3647
3663
  lineReaded.removeAllListeners();
3648
3664
  destroyStreamAndResolve();
@@ -3703,8 +3719,8 @@ function clearLineContext(frame) {
3703
3719
  delete frame.context_line;
3704
3720
  delete frame.post_context;
3705
3721
  }
3706
- function shouldSkipContextLinesForFile(path43) {
3707
- return path43.startsWith("node:") || path43.endsWith(".min.js") || path43.endsWith(".min.cjs") || path43.endsWith(".min.mjs") || path43.startsWith("data:");
3722
+ function shouldSkipContextLinesForFile(path44) {
3723
+ return path44.startsWith("node:") || path44.endsWith(".min.js") || path44.endsWith(".min.cjs") || path44.endsWith(".min.mjs") || path44.startsWith("data:");
3708
3724
  }
3709
3725
  function shouldSkipContextLinesForFrame(frame) {
3710
3726
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -4920,9 +4936,9 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
4920
4936
  if (!waitUntil) return;
4921
4937
  if (this.disabled || this.optedOut) return;
4922
4938
  if (!this._waitUntilCycle) {
4923
- let resolve5;
4939
+ let resolve6;
4924
4940
  const promise = new Promise((r) => {
4925
- resolve5 = r;
4941
+ resolve6 = r;
4926
4942
  });
4927
4943
  try {
4928
4944
  waitUntil(promise);
@@ -4930,7 +4946,7 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
4930
4946
  return;
4931
4947
  }
4932
4948
  this._waitUntilCycle = {
4933
- resolve: resolve5,
4949
+ resolve: resolve6,
4934
4950
  startedAt: Date.now(),
4935
4951
  timer: void 0
4936
4952
  };
@@ -4954,12 +4970,12 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
4954
4970
  return cycle?.resolve;
4955
4971
  }
4956
4972
  async resolveWaitUntilFlush() {
4957
- const resolve5 = this._consumeWaitUntilCycle();
4973
+ const resolve6 = this._consumeWaitUntilCycle();
4958
4974
  try {
4959
4975
  await super.flush();
4960
4976
  } catch {
4961
4977
  } finally {
4962
- resolve5?.();
4978
+ resolve6?.();
4963
4979
  }
4964
4980
  }
4965
4981
  getPersistedProperty(key) {
@@ -5051,15 +5067,15 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
5051
5067
  async waitForLocalEvaluationReady(timeoutMs = THIRTY_SECONDS) {
5052
5068
  if (this.isLocalEvaluationReady()) return true;
5053
5069
  if (void 0 === this.featureFlagsPoller) return false;
5054
- return new Promise((resolve5) => {
5070
+ return new Promise((resolve6) => {
5055
5071
  const timeout = setTimeout(() => {
5056
5072
  cleanup();
5057
- resolve5(false);
5073
+ resolve6(false);
5058
5074
  }, timeoutMs);
5059
5075
  const cleanup = this._events.on("localEvaluationFlagsLoaded", (count) => {
5060
5076
  clearTimeout(timeout);
5061
5077
  cleanup();
5062
- resolve5(count > 0);
5078
+ resolve6(count > 0);
5063
5079
  });
5064
5080
  });
5065
5081
  }
@@ -5496,13 +5512,13 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
5496
5512
  this.context?.enter(data, options);
5497
5513
  }
5498
5514
  async _shutdown(shutdownTimeoutMs) {
5499
- const resolve5 = this._consumeWaitUntilCycle();
5515
+ const resolve6 = this._consumeWaitUntilCycle();
5500
5516
  await this.featureFlagsPoller?.stopPoller(shutdownTimeoutMs);
5501
5517
  this.errorTracking.shutdown();
5502
5518
  try {
5503
5519
  return await super._shutdown(shutdownTimeoutMs);
5504
5520
  } finally {
5505
- resolve5?.();
5521
+ resolve6?.();
5506
5522
  }
5507
5523
  }
5508
5524
  async _requestRemoteConfigPayload(flagKey) {
@@ -5858,7 +5874,7 @@ function readAnonId() {
5858
5874
  }
5859
5875
  function superProperties() {
5860
5876
  return {
5861
- cliVersion: true ? "2.27.0" : "0.0.0-dev",
5877
+ cliVersion: true ? "2.27.2" : "0.0.0-dev",
5862
5878
  nodeVersion: process.version,
5863
5879
  platform: process.platform,
5864
5880
  arch: process.arch,
@@ -6065,9 +6081,9 @@ var CommandRelayService = class {
6065
6081
  this.armSseWatchdog();
6066
6082
  let buffer = "";
6067
6083
  res.setEncoding("utf8");
6068
- res.on("data", (chunk) => {
6084
+ res.on("data", (chunk2) => {
6069
6085
  this.sseLastByteAt = Date.now();
6070
- buffer += chunk;
6086
+ buffer += chunk2;
6071
6087
  let frameEnd;
6072
6088
  while ((frameEnd = buffer.indexOf("\n\n")) !== -1) {
6073
6089
  const frame = buffer.slice(0, frameEnd);
@@ -6736,9 +6752,9 @@ var UnixPtyStrategy = class {
6736
6752
  );
6737
6753
  process.exit(1);
6738
6754
  });
6739
- this.proc.stdout?.on("data", (chunk) => {
6740
- process.stdout.write(chunk);
6741
- this.opts.onData(chunk.toString("utf8"));
6755
+ this.proc.stdout?.on("data", (chunk2) => {
6756
+ process.stdout.write(chunk2);
6757
+ this.opts.onData(chunk2.toString("utf8"));
6742
6758
  });
6743
6759
  if (process.stdin.isTTY) process.stdin.setRawMode(true);
6744
6760
  process.stdin.resume();
@@ -6830,8 +6846,8 @@ var UnixPtyStrategy = class {
6830
6846
  }
6831
6847
  }
6832
6848
  }
6833
- stdinHandler = (chunk) => {
6834
- this.proc?.stdin?.write(chunk);
6849
+ stdinHandler = (chunk2) => {
6850
+ this.proc?.stdin?.write(chunk2);
6835
6851
  };
6836
6852
  handleResize = () => {
6837
6853
  if (this.proc?.pid) {
@@ -7017,8 +7033,8 @@ var WindowsConPtyStrategy = class _WindowsConPtyStrategy {
7017
7033
  }
7018
7034
  this.pty = null;
7019
7035
  }
7020
- stdinHandler = (chunk) => {
7021
- this.pty?.write(chunk.toString("utf8"));
7036
+ stdinHandler = (chunk2) => {
7037
+ this.pty?.write(chunk2.toString("utf8"));
7022
7038
  };
7023
7039
  };
7024
7040
 
@@ -7051,9 +7067,9 @@ var WindowsPtyStrategy = class {
7051
7067
  );
7052
7068
  process.exit(1);
7053
7069
  });
7054
- this.proc.stdout?.on("data", (chunk) => {
7055
- process.stdout.write(chunk);
7056
- this.opts.onData(chunk.toString("utf8"));
7070
+ this.proc.stdout?.on("data", (chunk2) => {
7071
+ process.stdout.write(chunk2);
7072
+ this.opts.onData(chunk2.toString("utf8"));
7057
7073
  });
7058
7074
  this.proc.stdin?.write("");
7059
7075
  if (process.stdin.isTTY) process.stdin.setRawMode(true);
@@ -7080,8 +7096,8 @@ var WindowsPtyStrategy = class {
7080
7096
  }
7081
7097
  }
7082
7098
  }
7083
- stdinHandler = (chunk) => {
7084
- this.proc?.stdin?.write(chunk);
7099
+ stdinHandler = (chunk2) => {
7100
+ this.proc?.stdin?.write(chunk2);
7085
7101
  };
7086
7102
  };
7087
7103
 
@@ -9159,15 +9175,15 @@ function runInstaller() {
9159
9175
  "-Command",
9160
9176
  "irm https://claude.ai/install.ps1 | iex"
9161
9177
  ] : ["-c", "curl -fsSL https://claude.ai/install.sh | bash"];
9162
- return new Promise((resolve5) => {
9178
+ return new Promise((resolve6) => {
9163
9179
  const proc = (0, import_child_process4.spawn)(cmd, args2, { stdio: "inherit" });
9164
9180
  proc.on("error", (err) => {
9165
9181
  console.error(`
9166
9182
  \u2717 Installer failed to launch: ${err.message}`);
9167
- resolve5(false);
9183
+ resolve6(false);
9168
9184
  });
9169
9185
  proc.on("exit", (code) => {
9170
- resolve5(code === 0);
9186
+ resolve6(code === 0);
9171
9187
  });
9172
9188
  });
9173
9189
  }
@@ -9344,17 +9360,17 @@ function parseUsageOutput(raw) {
9344
9360
  return { percent, resetAt };
9345
9361
  }
9346
9362
  async function fetchClaudeQuota() {
9347
- return new Promise((resolve5) => {
9363
+ return new Promise((resolve6) => {
9348
9364
  const claudeCmd = findInPath("claude") ? "claude" : "claude-code";
9349
9365
  if (!claudeCmd) {
9350
- resolve5(null);
9366
+ resolve6(null);
9351
9367
  return;
9352
9368
  }
9353
9369
  const helperPath = path11.join(os10.tmpdir(), "codeam-quota-helper.py");
9354
9370
  fs8.writeFileSync(helperPath, HELPER_SCRIPT, { mode: 420 });
9355
9371
  const python = findInPath("python3") ?? findInPath("python");
9356
9372
  if (!python) {
9357
- resolve5(null);
9373
+ resolve6(null);
9358
9374
  return;
9359
9375
  }
9360
9376
  const proc = (0, import_child_process5.spawn)(python, [helperPath, claudeCmd, "--tools", ""], {
@@ -9364,8 +9380,8 @@ async function fetchClaudeQuota() {
9364
9380
  });
9365
9381
  let output = "";
9366
9382
  let resolved = false;
9367
- proc.stdout?.on("data", (chunk) => {
9368
- output += chunk.toString("utf8");
9383
+ proc.stdout?.on("data", (chunk2) => {
9384
+ output += chunk2.toString("utf8");
9369
9385
  });
9370
9386
  setTimeout(() => {
9371
9387
  proc.stdin?.write("/usage\r");
@@ -9381,13 +9397,13 @@ async function fetchClaudeQuota() {
9381
9397
  fs8.unlinkSync(helperPath);
9382
9398
  } catch {
9383
9399
  }
9384
- resolve5(result);
9400
+ resolve6(result);
9385
9401
  }, 5e3);
9386
9402
  }, 8e3);
9387
9403
  setTimeout(() => {
9388
9404
  if (!resolved) {
9389
9405
  resolved = true;
9390
- resolve5(null);
9406
+ resolve6(null);
9391
9407
  }
9392
9408
  try {
9393
9409
  proc.kill();
@@ -9418,12 +9434,12 @@ function killActiveSpawnAndCaptureChildren() {
9418
9434
  }
9419
9435
  async function spawnAndCapture(cmd, args2, opts = {}) {
9420
9436
  const timeoutMs = opts.timeoutMs ?? 6e4;
9421
- return new Promise((resolve5) => {
9437
+ return new Promise((resolve6) => {
9422
9438
  let settled = false;
9423
9439
  const settle = (value) => {
9424
9440
  if (settled) return;
9425
9441
  settled = true;
9426
- resolve5(value);
9442
+ resolve6(value);
9427
9443
  };
9428
9444
  let child;
9429
9445
  try {
@@ -9438,11 +9454,11 @@ async function spawnAndCapture(cmd, args2, opts = {}) {
9438
9454
  }
9439
9455
  activeChildren.add(child);
9440
9456
  let stdout = "";
9441
- child.stdout?.on("data", (chunk) => {
9442
- stdout += chunk.toString("utf8");
9457
+ child.stdout?.on("data", (chunk2) => {
9458
+ stdout += chunk2.toString("utf8");
9443
9459
  });
9444
- child.stderr?.on("data", (chunk) => {
9445
- opts.onStderr?.(chunk.toString("utf8"));
9460
+ child.stderr?.on("data", (chunk2) => {
9461
+ opts.onStderr?.(chunk2.toString("utf8"));
9446
9462
  });
9447
9463
  const timer = setTimeout(() => {
9448
9464
  try {
@@ -9930,13 +9946,13 @@ function detectStartupBanner(lines) {
9930
9946
  while (artStart > 0 && BANNER_ART_RE.test(lines[artStart - 1])) artStart--;
9931
9947
  if (metaIdx - artStart < 2) return null;
9932
9948
  const pathLine = (lines[metaIdx + 1] ?? "").trim();
9933
- const path43 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9949
+ const path44 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9934
9950
  return {
9935
9951
  title: "",
9936
9952
  subtitle: lines[metaIdx].trim(),
9937
- path: path43,
9953
+ path: path44,
9938
9954
  startIdx: artStart,
9939
- endIdx: metaIdx + (path43 ? 1 : 0)
9955
+ endIdx: metaIdx + (path44 ? 1 : 0)
9940
9956
  };
9941
9957
  }
9942
9958
 
@@ -11090,12 +11106,12 @@ function resolveNpm(os27) {
11090
11106
  return os27.id === "win32" ? "npm.cmd" : "npm";
11091
11107
  }
11092
11108
  async function installCodexViaNpm(os27) {
11093
- return new Promise((resolve5, reject) => {
11109
+ return new Promise((resolve6, reject) => {
11094
11110
  const proc = (0, import_node_child_process4.spawn)(resolveNpm(os27), ["install", "-g", "@openai/codex"], {
11095
11111
  stdio: "inherit"
11096
11112
  });
11097
11113
  proc.on("close", (code) => {
11098
- if (code === 0) resolve5();
11114
+ if (code === 0) resolve6();
11099
11115
  else reject(new Error(`npm install -g @openai/codex exited ${code}`));
11100
11116
  });
11101
11117
  proc.on("error", (err) => {
@@ -11210,12 +11226,12 @@ async function ensureCoderabbitInstalled(os27) {
11210
11226
  return false;
11211
11227
  }
11212
11228
  console.log("\n CodeRabbit CLI not found \u2014 installing via the official script\u2026\n");
11213
- const ok = await new Promise((resolve5) => {
11229
+ const ok = await new Promise((resolve6) => {
11214
11230
  const proc = (0, import_node_child_process5.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL} | sh`], {
11215
11231
  stdio: "inherit"
11216
11232
  });
11217
- proc.on("close", (code) => resolve5(code === 0));
11218
- proc.on("error", () => resolve5(false));
11233
+ proc.on("close", (code) => resolve6(code === 0));
11234
+ proc.on("error", () => resolve6(false));
11219
11235
  });
11220
11236
  if (!ok) return false;
11221
11237
  os27.augmentPath([`${os27.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
@@ -11272,11 +11288,11 @@ function parseReview(stdout) {
11272
11288
  for (const line of lines) {
11273
11289
  const m = line.match(HUNK_LINE_RE);
11274
11290
  if (!m) continue;
11275
- const [, path43, lineNo, sevToken, message] = m;
11276
- if (!path43 || !lineNo || !message) continue;
11291
+ const [, path44, lineNo, sevToken, message] = m;
11292
+ if (!path44 || !lineNo || !message) continue;
11277
11293
  const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
11278
11294
  hunks.push({
11279
- path: path43.trim(),
11295
+ path: path44.trim(),
11280
11296
  line: Number(lineNo),
11281
11297
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
11282
11298
  message: cleanedMessage
@@ -11334,7 +11350,7 @@ var CoderabbitRuntimeStrategy = class {
11334
11350
  }
11335
11351
  async runOneShot(input) {
11336
11352
  const launch = await this.prepareInvocation(input);
11337
- return new Promise((resolve5, reject) => {
11353
+ return new Promise((resolve6, reject) => {
11338
11354
  const stdoutBuf = [];
11339
11355
  const stderrBuf = [];
11340
11356
  const proc = (0, import_node_child_process7.spawn)(launch.cmd, launch.args, {
@@ -11345,7 +11361,7 @@ var CoderabbitRuntimeStrategy = class {
11345
11361
  proc.stderr?.on("data", (b) => stderrBuf.push(b));
11346
11362
  proc.on("error", (err) => reject(err));
11347
11363
  proc.on("close", (code) => {
11348
- resolve5(
11364
+ resolve6(
11349
11365
  this.parseOutput({
11350
11366
  exitCode: code ?? 0,
11351
11367
  stdout: Buffer.concat(stdoutBuf).toString("utf8"),
@@ -11795,6 +11811,681 @@ function createDeployStrategy(agent) {
11795
11811
  return build();
11796
11812
  }
11797
11813
 
11814
+ // src/agents/acp/adapters.ts
11815
+ var path24 = __toESM(require("path"));
11816
+ var require_ = require;
11817
+ function resolveBin(pkgName, binName) {
11818
+ try {
11819
+ const manifestPath = require_.resolve(`${pkgName}/package.json`);
11820
+ const manifest = require_(`${pkgName}/package.json`);
11821
+ const pkgDir = path24.dirname(manifestPath);
11822
+ const bin = manifest.bin;
11823
+ if (!bin) return null;
11824
+ if (typeof bin === "string") return path24.resolve(pkgDir, bin);
11825
+ const target = binName ?? Object.keys(bin)[0];
11826
+ if (!target || !bin[target]) return null;
11827
+ return path24.resolve(pkgDir, bin[target]);
11828
+ } catch {
11829
+ return null;
11830
+ }
11831
+ }
11832
+ var REGISTRY = {
11833
+ claude: () => {
11834
+ const bin = resolveBin("@agentclientprotocol/claude-agent-acp", "claude-agent-acp");
11835
+ if (!bin) return null;
11836
+ return {
11837
+ command: process.execPath,
11838
+ args: [bin],
11839
+ requiresAgentBinary: "claude"
11840
+ };
11841
+ },
11842
+ codex: () => {
11843
+ const bin = resolveBin("@agentclientprotocol/codex-acp", "codex-acp");
11844
+ if (!bin) return null;
11845
+ return {
11846
+ command: process.execPath,
11847
+ args: [bin],
11848
+ requiresAgentBinary: "codex"
11849
+ };
11850
+ },
11851
+ cursor: () => {
11852
+ const bin = resolveBin("cursor-agent-acp", "cursor-agent-acp");
11853
+ if (!bin) return null;
11854
+ return {
11855
+ command: process.execPath,
11856
+ args: [bin],
11857
+ requiresAgentBinary: "cursor-agent"
11858
+ };
11859
+ },
11860
+ // Gemini speaks ACP natively via `gemini --acp` — no npm adapter
11861
+ // package, just the user-installed `gemini` binary on PATH. Same
11862
+ // {@link AdapterSpec} shape; the only difference is `command` is
11863
+ // resolved from PATH at spawn time instead of being absolute.
11864
+ gemini: () => ({
11865
+ command: "gemini",
11866
+ args: ["--acp"],
11867
+ requiresAgentBinary: "gemini"
11868
+ })
11869
+ };
11870
+ function getAcpAdapter(agent) {
11871
+ const factory = REGISTRY[agent];
11872
+ return factory ? factory() : null;
11873
+ }
11874
+
11875
+ // src/agents/acp/runner.ts
11876
+ var import_node_crypto6 = require("crypto");
11877
+
11878
+ // src/agents/acp/client.ts
11879
+ var import_node_child_process10 = require("child_process");
11880
+ var fs20 = __toESM(require("fs/promises"));
11881
+ var import_node_stream = require("stream");
11882
+ var import_sdk = require("@agentclientprotocol/sdk");
11883
+ var PROTOCOL_VERSION2 = 1;
11884
+ var CLIENT_CAPABILITIES = {
11885
+ fs: { readTextFile: true, writeTextFile: true },
11886
+ terminal: false
11887
+ };
11888
+ var AcpClient = class {
11889
+ constructor(opts) {
11890
+ this.opts = opts;
11891
+ }
11892
+ opts;
11893
+ child = null;
11894
+ connection = null;
11895
+ stopping = false;
11896
+ sessionId = null;
11897
+ /**
11898
+ * Spawn the adapter + perform the initial handshake (initialize
11899
+ * → newSession). Returns the ACP-assigned sessionId so the
11900
+ * caller can route subsequent prompts.
11901
+ */
11902
+ async start() {
11903
+ if (this.child) throw new Error("AcpClient already started");
11904
+ const { adapter, cwd } = this.opts;
11905
+ const child = (0, import_node_child_process10.spawn)(adapter.command, adapter.args, {
11906
+ cwd,
11907
+ env: process.env,
11908
+ stdio: ["pipe", "pipe", "pipe"]
11909
+ });
11910
+ this.child = child;
11911
+ child.stderr?.setEncoding("utf8");
11912
+ child.stderr?.on("data", (chunk2) => {
11913
+ for (const line of chunk2.split(/\r?\n/)) {
11914
+ const trimmed = line.trim();
11915
+ if (trimmed) this.opts.onStderr?.(trimmed);
11916
+ }
11917
+ });
11918
+ child.on("exit", (code, signal) => {
11919
+ if (this.stopping) return;
11920
+ log.warn("acpClient", `adapter exited unexpectedly code=${code} signal=${signal}`);
11921
+ this.opts.onUnexpectedExit?.(code, signal);
11922
+ });
11923
+ if (!child.stdin || !child.stdout) {
11924
+ throw new Error("Spawned ACP adapter is missing stdio handles");
11925
+ }
11926
+ const input = import_node_stream.Readable.toWeb(child.stdout);
11927
+ const output = import_node_stream.Writable.toWeb(child.stdin);
11928
+ const stream = (0, import_sdk.ndJsonStream)(output, input);
11929
+ this.connection = new import_sdk.ClientSideConnection(
11930
+ (_agent) => this.buildClient(),
11931
+ stream
11932
+ );
11933
+ const initialize = await this.connection.initialize({
11934
+ protocolVersion: PROTOCOL_VERSION2,
11935
+ clientCapabilities: CLIENT_CAPABILITIES
11936
+ });
11937
+ const newSession = await this.connection.newSession({
11938
+ cwd,
11939
+ mcpServers: []
11940
+ });
11941
+ this.sessionId = newSession.sessionId;
11942
+ return { sessionId: newSession.sessionId, initialize };
11943
+ }
11944
+ /**
11945
+ * Send a user prompt to the active session. Returns the
11946
+ * {@link PromptResponse} which carries the agent's stop reason
11947
+ * once the turn finishes. Session/update notifications keep
11948
+ * arriving on `onSessionUpdate` while the turn streams.
11949
+ */
11950
+ async prompt(text) {
11951
+ if (!this.connection || !this.sessionId) {
11952
+ throw new Error("AcpClient.prompt called before start()");
11953
+ }
11954
+ return this.connection.prompt({
11955
+ sessionId: this.sessionId,
11956
+ prompt: [{ type: "text", text }]
11957
+ });
11958
+ }
11959
+ /**
11960
+ * Cancel the in-flight prompt turn. Notification — no response.
11961
+ * Safe to call when nothing is in flight (the adapter no-ops).
11962
+ */
11963
+ async cancel() {
11964
+ if (!this.connection || !this.sessionId) return;
11965
+ await this.connection.cancel({ sessionId: this.sessionId });
11966
+ }
11967
+ /**
11968
+ * Kill the adapter process and tear down the connection. Safe
11969
+ * to call multiple times. Suppresses the unexpected-exit
11970
+ * callback for this teardown.
11971
+ */
11972
+ async stop() {
11973
+ this.stopping = true;
11974
+ const child = this.child;
11975
+ if (!child) return;
11976
+ this.child = null;
11977
+ this.connection = null;
11978
+ this.sessionId = null;
11979
+ try {
11980
+ child.kill("SIGTERM");
11981
+ const grace = new Promise((resolve6) => {
11982
+ const t2 = setTimeout(() => {
11983
+ try {
11984
+ child.kill("SIGKILL");
11985
+ } catch {
11986
+ }
11987
+ resolve6();
11988
+ }, 2e3);
11989
+ child.once("exit", () => {
11990
+ clearTimeout(t2);
11991
+ resolve6();
11992
+ });
11993
+ });
11994
+ await grace;
11995
+ } catch (err) {
11996
+ log.trace("acpClient", "stop teardown error", err);
11997
+ }
11998
+ }
11999
+ // ─── Client surface (what the agent calls into) ───────────────────
12000
+ buildClient() {
12001
+ return {
12002
+ sessionUpdate: async (params) => {
12003
+ this.opts.onSessionUpdate(params);
12004
+ },
12005
+ requestPermission: (params) => {
12006
+ return this.opts.onRequestPermission(params);
12007
+ },
12008
+ readTextFile: async (params) => {
12009
+ const content = await fs20.readFile(params.path, "utf8");
12010
+ return applyLineRange(content, params.line ?? null, params.limit ?? null);
12011
+ },
12012
+ writeTextFile: async (params) => {
12013
+ await fs20.writeFile(params.path, params.content, "utf8");
12014
+ return {};
12015
+ },
12016
+ // Terminal capability is declared `false` above so adapters
12017
+ // shouldn't call these; provide explicit "not implemented"
12018
+ // stubs so a misbehaving adapter gets a clean error instead
12019
+ // of a hung promise.
12020
+ createTerminal: async () => {
12021
+ throw new Error("terminal capability not implemented in this client (Phase 1)");
12022
+ },
12023
+ terminalOutput: async () => {
12024
+ throw new Error("terminal capability not implemented in this client (Phase 1)");
12025
+ },
12026
+ releaseTerminal: async () => {
12027
+ throw new Error("terminal capability not implemented in this client (Phase 1)");
12028
+ },
12029
+ waitForTerminalExit: async () => {
12030
+ throw new Error("terminal capability not implemented in this client (Phase 1)");
12031
+ },
12032
+ killTerminal: async () => {
12033
+ throw new Error("terminal capability not implemented in this client (Phase 1)");
12034
+ }
12035
+ };
12036
+ }
12037
+ };
12038
+ function applyLineRange(content, line, limit) {
12039
+ if (line === null && limit === null) return { content };
12040
+ const lines = content.split("\n");
12041
+ const start2 = Math.max(0, (line ?? 1) - 1);
12042
+ const end = limit !== null ? start2 + limit : lines.length;
12043
+ return { content: lines.slice(start2, end).join("\n") };
12044
+ }
12045
+
12046
+ // src/services/streaming/transport.ts
12047
+ var http3 = __toESM(require("http"));
12048
+ var https3 = __toESM(require("https"));
12049
+ var _transport2 = {
12050
+ post: _post,
12051
+ get: _get
12052
+ };
12053
+ function _post(url, headers, payload) {
12054
+ return new Promise((resolve6, reject) => {
12055
+ let settled = false;
12056
+ const u2 = new URL(url);
12057
+ const lib = u2.protocol === "https:" ? https3 : http3;
12058
+ const req = lib.request(
12059
+ {
12060
+ hostname: u2.hostname,
12061
+ port: u2.port || (u2.protocol === "https:" ? 443 : 80),
12062
+ path: u2.pathname + u2.search,
12063
+ method: "POST",
12064
+ headers: {
12065
+ ...headers,
12066
+ ...vercelBypassHeader(),
12067
+ "Content-Length": Buffer.byteLength(payload)
12068
+ },
12069
+ timeout: 8e3
12070
+ },
12071
+ (res) => {
12072
+ let body = "";
12073
+ res.on("data", (c2) => {
12074
+ body += c2.toString();
12075
+ });
12076
+ res.on("end", () => {
12077
+ if (settled) return;
12078
+ settled = true;
12079
+ resolve6({ statusCode: res.statusCode ?? 0, body });
12080
+ });
12081
+ }
12082
+ );
12083
+ req.on("error", (err) => {
12084
+ if (settled) return;
12085
+ settled = true;
12086
+ reject(err);
12087
+ });
12088
+ req.on("timeout", () => {
12089
+ req.destroy();
12090
+ });
12091
+ req.write(payload);
12092
+ req.end();
12093
+ });
12094
+ }
12095
+ function _get(url, headers) {
12096
+ return new Promise((resolve6, reject) => {
12097
+ let settled = false;
12098
+ const u2 = new URL(url);
12099
+ const lib = u2.protocol === "https:" ? https3 : http3;
12100
+ const req = lib.request(
12101
+ {
12102
+ hostname: u2.hostname,
12103
+ port: u2.port || (u2.protocol === "https:" ? 443 : 80),
12104
+ path: u2.pathname + u2.search,
12105
+ method: "GET",
12106
+ headers: {
12107
+ ...headers,
12108
+ ...vercelBypassHeader()
12109
+ },
12110
+ timeout: 8e3
12111
+ },
12112
+ (res) => {
12113
+ let body = "";
12114
+ res.on("data", (c2) => {
12115
+ body += c2.toString();
12116
+ });
12117
+ res.on("end", () => {
12118
+ if (settled) return;
12119
+ settled = true;
12120
+ resolve6({ statusCode: res.statusCode ?? 0, body });
12121
+ });
12122
+ }
12123
+ );
12124
+ req.on("error", (err) => {
12125
+ if (settled) return;
12126
+ settled = true;
12127
+ reject(err);
12128
+ });
12129
+ req.on("timeout", () => {
12130
+ req.destroy();
12131
+ });
12132
+ req.end();
12133
+ });
12134
+ }
12135
+
12136
+ // src/agents/acp/publisher.ts
12137
+ var AcpPublisher = class {
12138
+ constructor(opts) {
12139
+ this.opts = opts;
12140
+ this.apiBase = opts.apiBaseUrl ?? resolveApiBaseUrl();
12141
+ this.headers = {
12142
+ "Content-Type": "application/json",
12143
+ "X-Codeam-Protocol-Version": "2.0.0",
12144
+ "X-Plugin-Auth-Token": opts.pluginAuthToken
12145
+ };
12146
+ }
12147
+ opts;
12148
+ apiBase;
12149
+ headers;
12150
+ /**
12151
+ * Fire-and-forget chunk POST. The backend's per-user SSE bus
12152
+ * forwards each chunk to mobile/landing within ~20 ms (PRO) /
12153
+ * ~80 ms (FREE). Errors are logged but never thrown — a missed
12154
+ * chunk shouldn't bring down the whole session.
12155
+ */
12156
+ async publishChunk(event) {
12157
+ const url = `${this.apiBase}/api/sessions/${encodeURIComponent(this.opts.sessionId)}/streaming-chunk`;
12158
+ try {
12159
+ const { statusCode, body } = await _transport2.post(
12160
+ url,
12161
+ this.headers,
12162
+ JSON.stringify(event)
12163
+ );
12164
+ if (statusCode < 200 || statusCode >= 300) {
12165
+ log.warn("acpPublisher", `chunk status=${statusCode} body=${body.slice(0, 200)}`);
12166
+ }
12167
+ } catch (err) {
12168
+ log.trace("acpPublisher", "chunk post failed", err);
12169
+ }
12170
+ }
12171
+ /**
12172
+ * Publish an awaiting-answer event so the mobile renders the
12173
+ * pending-prompt sheet. The CLI follows up with
12174
+ * {@link pollPendingAnswer} until the user replies (or the
12175
+ * 5 min Redis TTL expires upstream).
12176
+ */
12177
+ async publishAwaitingAnswer(event) {
12178
+ const url = `${this.apiBase}/api/sessions/${encodeURIComponent(this.opts.sessionId)}/awaiting-answer`;
12179
+ try {
12180
+ const { statusCode, body } = await _transport2.post(
12181
+ url,
12182
+ this.headers,
12183
+ JSON.stringify(event)
12184
+ );
12185
+ if (statusCode < 200 || statusCode >= 300) {
12186
+ log.warn("acpPublisher", `awaiting-answer status=${statusCode} body=${body.slice(0, 200)}`);
12187
+ }
12188
+ } catch (err) {
12189
+ log.trace("acpPublisher", "awaiting-answer post failed", err);
12190
+ }
12191
+ }
12192
+ /**
12193
+ * Drain the pending-answer endpoint. Returns the resolved answer
12194
+ * when the user has replied, `null` otherwise. The caller polls
12195
+ * this on a 1.5 s cadence (same as the legacy emitter) until a
12196
+ * non-null result lands.
12197
+ */
12198
+ async pollPendingAnswer(questionId) {
12199
+ const url = `${this.apiBase}/api/sessions/${encodeURIComponent(this.opts.sessionId)}/pending-answer?questionId=${encodeURIComponent(questionId)}&pluginId=${encodeURIComponent(this.opts.pluginId)}`;
12200
+ try {
12201
+ const { statusCode, body } = await _transport2.get(url, this.headers);
12202
+ if (statusCode === 204 || statusCode === 404) return null;
12203
+ if (statusCode < 200 || statusCode >= 300) {
12204
+ log.warn("acpPublisher", `pending-answer status=${statusCode} body=${body.slice(0, 200)}`);
12205
+ return null;
12206
+ }
12207
+ return parsePendingAnswerResponse(body, questionId);
12208
+ } catch (err) {
12209
+ log.trace("acpPublisher", "pending-answer poll failed", err);
12210
+ return null;
12211
+ }
12212
+ }
12213
+ };
12214
+ function parsePendingAnswerResponse(body, questionId) {
12215
+ if (!body) return null;
12216
+ let parsed;
12217
+ try {
12218
+ parsed = JSON.parse(body);
12219
+ } catch {
12220
+ return null;
12221
+ }
12222
+ if (typeof parsed !== "object" || parsed === null) return null;
12223
+ const root = parsed;
12224
+ const candidate = root.data && typeof root.data === "object" ? root.data : root;
12225
+ const qid = candidate.questionId;
12226
+ const answer = candidate.answer;
12227
+ const optionIndex = candidate.optionIndex;
12228
+ if (typeof qid !== "string" || qid !== questionId) return null;
12229
+ if (typeof answer !== "string") return null;
12230
+ const result = { questionId: qid, answer };
12231
+ if (typeof optionIndex === "number" && Number.isInteger(optionIndex)) {
12232
+ result.optionIndex = optionIndex;
12233
+ }
12234
+ return result;
12235
+ }
12236
+
12237
+ // src/agents/acp/mappers.ts
12238
+ var import_node_crypto5 = require("crypto");
12239
+ function mapSessionUpdate(notification) {
12240
+ const update = notification.update;
12241
+ switch (update.sessionUpdate) {
12242
+ case "agent_message_chunk": {
12243
+ const text = extractText2(update.content);
12244
+ if (!text) return [];
12245
+ return [chunk(messageChunkId(update.messageId), "text", text)];
12246
+ }
12247
+ case "agent_thought_chunk": {
12248
+ const text = extractText2(update.content);
12249
+ if (!text) return [];
12250
+ return [chunk(messageChunkId(update.messageId), "thinking", text)];
12251
+ }
12252
+ case "tool_call": {
12253
+ const summary = describeToolCall(update);
12254
+ if (!summary) return [];
12255
+ return [chunk(update.toolCallId, "tool_use", summary)];
12256
+ }
12257
+ case "tool_call_update": {
12258
+ if (update.status !== "completed" && update.status !== "failed") {
12259
+ return [];
12260
+ }
12261
+ const body = describeToolCallUpdate(update);
12262
+ if (!body) return [];
12263
+ const prefix = update.status === "failed" ? "[failed] " : "";
12264
+ return [chunk(update.toolCallId, "tool_result", prefix + body)];
12265
+ }
12266
+ case "user_message_chunk":
12267
+ return [];
12268
+ case "plan":
12269
+ case "plan_update":
12270
+ case "plan_removed":
12271
+ case "available_commands_update":
12272
+ case "current_mode_update":
12273
+ case "config_option_update":
12274
+ case "session_info_update":
12275
+ case "usage_update":
12276
+ return [];
12277
+ default:
12278
+ return [];
12279
+ }
12280
+ }
12281
+ function mapPermissionRequest(request) {
12282
+ const prompt = describeToolCall(request.toolCall) ?? "The agent requested permission to continue.";
12283
+ const optionIdByLabel = {};
12284
+ const kindByLabel = {};
12285
+ const labels = [];
12286
+ for (const opt of request.options) {
12287
+ const label = opt.name?.trim() || humanizeKind(opt.kind);
12288
+ if (label in optionIdByLabel) continue;
12289
+ optionIdByLabel[label] = opt.optionId;
12290
+ kindByLabel[label] = opt.kind;
12291
+ labels.push(label);
12292
+ }
12293
+ return {
12294
+ event: {
12295
+ questionId: (0, import_node_crypto5.randomUUID)(),
12296
+ prompt,
12297
+ options: labels.length > 0 ? labels : void 0
12298
+ },
12299
+ optionIdByLabel,
12300
+ kindByLabel
12301
+ };
12302
+ }
12303
+ function chunk(chunkId, kind, content) {
12304
+ return { chunkId, kind, content, isFinal: true };
12305
+ }
12306
+ function messageChunkId(messageId) {
12307
+ if (typeof messageId === "string" && messageId.length > 0) return messageId;
12308
+ return (0, import_node_crypto5.randomUUID)();
12309
+ }
12310
+ function extractText2(content) {
12311
+ if (!content || typeof content !== "object") return null;
12312
+ if ("type" in content && content.type === "text") {
12313
+ const t2 = content.text;
12314
+ return typeof t2 === "string" && t2.length > 0 ? t2 : null;
12315
+ }
12316
+ return null;
12317
+ }
12318
+ function describeToolCall(call) {
12319
+ const title = call.title?.trim();
12320
+ const kind = call.kind?.trim();
12321
+ if (title && title.length > 0) return title;
12322
+ if (kind && kind.length > 0) return kind;
12323
+ if (call.rawInput && typeof call.rawInput === "object") {
12324
+ try {
12325
+ const summary = JSON.stringify(call.rawInput);
12326
+ if (summary.length > 240) return `${summary.slice(0, 240)}\u2026`;
12327
+ return summary;
12328
+ } catch {
12329
+ return null;
12330
+ }
12331
+ }
12332
+ return null;
12333
+ }
12334
+ function describeToolCallUpdate(update) {
12335
+ const parts = [];
12336
+ if (Array.isArray(update.content)) {
12337
+ for (const item of update.content) {
12338
+ if (!item || typeof item !== "object") continue;
12339
+ if (item.type === "content" && item.content) {
12340
+ const text = extractText2(item.content);
12341
+ if (text) parts.push(text);
12342
+ } else if (item.type === "diff") {
12343
+ const p2 = item.path;
12344
+ parts.push(p2 ? `diff: ${p2}` : "diff");
12345
+ } else if (item.type === "terminal") {
12346
+ const id = item.terminalId;
12347
+ parts.push(id ? `terminal: ${id}` : "terminal");
12348
+ }
12349
+ }
12350
+ }
12351
+ if (parts.length > 0) return parts.join("\n");
12352
+ const title = update.title?.trim();
12353
+ return title && title.length > 0 ? title : null;
12354
+ }
12355
+ function humanizeKind(kind) {
12356
+ switch (kind) {
12357
+ case "allow_once":
12358
+ return "Allow once";
12359
+ case "allow_always":
12360
+ return "Always allow";
12361
+ case "reject_once":
12362
+ return "Reject";
12363
+ case "reject_always":
12364
+ return "Always reject";
12365
+ default:
12366
+ return kind;
12367
+ }
12368
+ }
12369
+
12370
+ // src/agents/acp/runner.ts
12371
+ var ANSWER_POLL_MS = 1500;
12372
+ var PERMISSION_TIMEOUT_MS = 5 * 60 * 1e3;
12373
+ async function runAcpSession(opts) {
12374
+ const publisher = new AcpPublisher({
12375
+ sessionId: opts.sessionId,
12376
+ pluginId: opts.pluginId,
12377
+ pluginAuthToken: opts.pluginAuthToken
12378
+ });
12379
+ const client2 = new AcpClient({
12380
+ adapter: opts.adapter,
12381
+ cwd: opts.cwd,
12382
+ onSessionUpdate: (notification) => {
12383
+ const chunks = mapSessionUpdate(notification);
12384
+ for (const chunk2 of chunks) {
12385
+ void publisher.publishChunk(chunk2);
12386
+ }
12387
+ },
12388
+ onRequestPermission: async (request) => {
12389
+ const { event, optionIdByLabel } = mapPermissionRequest(request);
12390
+ await publisher.publishAwaitingAnswer(event);
12391
+ const answer = await waitForAnswer(publisher, event.questionId);
12392
+ if (!answer) {
12393
+ return { outcome: { outcome: "cancelled" } };
12394
+ }
12395
+ const optionId = optionIdByLabel[answer.answer];
12396
+ if (!optionId) {
12397
+ log.warn(
12398
+ "acpRunner",
12399
+ `pending-answer label not in option map; reply="${answer.answer.slice(0, 80)}"`
12400
+ );
12401
+ return { outcome: { outcome: "cancelled" } };
12402
+ }
12403
+ return { outcome: { outcome: "selected", optionId } };
12404
+ },
12405
+ onStderr: (line) => {
12406
+ log.trace("acpAdapter", line);
12407
+ },
12408
+ onUnexpectedExit: (code, signal) => {
12409
+ log.warn("acpRunner", `adapter died code=${code} signal=${signal}; shutting down session`);
12410
+ void publisher.publishChunk({
12411
+ chunkId: (0, import_node_crypto6.randomUUID)(),
12412
+ kind: "text",
12413
+ content: `Agent adapter exited unexpectedly (code=${code ?? "null"} signal=${signal ?? "null"}).`,
12414
+ isFinal: true
12415
+ });
12416
+ process.exit(1);
12417
+ }
12418
+ });
12419
+ showInfo(`Starting ${opts.agent} via ACP adapter (${opts.adapter.requiresAgentBinary})\u2026`);
12420
+ const { sessionId: acpSessionId, initialize } = await client2.start();
12421
+ log.trace(
12422
+ "acpRunner",
12423
+ `adapter handshake ok protocolVersion=${initialize.protocolVersion} sessionId=${acpSessionId.slice(0, 8)}`
12424
+ );
12425
+ const relay = new CommandRelayService(
12426
+ opts.pluginId,
12427
+ async (cmd) => {
12428
+ await handleCommand(cmd, client2);
12429
+ },
12430
+ { id: opts.agent, name: opts.agent, displayName: opts.agent }
12431
+ );
12432
+ relay.start();
12433
+ const shutdown = async (signal) => {
12434
+ showInfo(`Shutting down ACP session (${signal})\u2026`);
12435
+ relay.stop();
12436
+ await client2.stop();
12437
+ process.exit(0);
12438
+ };
12439
+ process.once("SIGINT", () => void shutdown("SIGINT"));
12440
+ process.once("SIGTERM", () => void shutdown("SIGTERM"));
12441
+ process.once("SIGHUP", () => void shutdown("SIGHUP"));
12442
+ await new Promise(() => {
12443
+ });
12444
+ }
12445
+ async function handleCommand(cmd, client2) {
12446
+ switch (cmd.type) {
12447
+ case "start_task": {
12448
+ const payload = cmd.payload;
12449
+ const prompt = payload?.prompt?.trim();
12450
+ if (!prompt) {
12451
+ log.warn("acpRunner", "start_task with empty prompt; ignoring");
12452
+ return;
12453
+ }
12454
+ try {
12455
+ await client2.prompt(prompt);
12456
+ } catch (err) {
12457
+ log.warn("acpRunner", `prompt failed: ${describeError(err)}`);
12458
+ }
12459
+ return;
12460
+ }
12461
+ case "stop_task":
12462
+ case "escape_key": {
12463
+ try {
12464
+ await client2.cancel();
12465
+ } catch (err) {
12466
+ log.warn("acpRunner", `cancel failed: ${describeError(err)}`);
12467
+ }
12468
+ return;
12469
+ }
12470
+ default:
12471
+ log.trace("acpRunner", `command type "${cmd.type}" not supported in Phase 1 ACP mode`);
12472
+ return;
12473
+ }
12474
+ }
12475
+ async function waitForAnswer(publisher, questionId) {
12476
+ const deadline = Date.now() + PERMISSION_TIMEOUT_MS;
12477
+ while (Date.now() < deadline) {
12478
+ const reply = await publisher.pollPendingAnswer(questionId);
12479
+ if (reply) return { answer: reply.answer };
12480
+ await new Promise((r) => setTimeout(r, ANSWER_POLL_MS));
12481
+ }
12482
+ return null;
12483
+ }
12484
+ function describeError(err) {
12485
+ if (err instanceof Error) return err.message;
12486
+ return String(err);
12487
+ }
12488
+
11798
12489
  // src/services/output/chrome-tracker.ts
11799
12490
  var ChromeStepTracker = class {
11800
12491
  history = [];
@@ -11841,12 +12532,12 @@ var ChromeStepTracker = class {
11841
12532
  };
11842
12533
 
11843
12534
  // src/services/output/chunk-emitter.ts
11844
- var https3 = __toESM(require("https"));
11845
- var http3 = __toESM(require("http"));
12535
+ var https4 = __toESM(require("https"));
12536
+ var http4 = __toESM(require("http"));
11846
12537
  var API_BASE3 = resolveApiBaseUrl();
11847
12538
  async function refreshAuthToken(sessionId, pluginId) {
11848
12539
  try {
11849
- const { statusCode, body } = await _transport2.post(
12540
+ const { statusCode, body } = await _transport3.post(
11850
12541
  `${API_BASE3}/api/pairing/reconnect`,
11851
12542
  {
11852
12543
  "Content-Type": "application/json",
@@ -11909,14 +12600,14 @@ var ChunkEmitter = class {
11909
12600
  "chunkEmitter",
11910
12601
  `send type=${body.type ?? "(clear)"} bytes=${payload.length} done=${body.done === true}`
11911
12602
  );
11912
- return new Promise((resolve5) => {
12603
+ return new Promise((resolve6) => {
11913
12604
  const attempt = (attemptsLeft) => {
11914
- _transport2.post(this.url, this.headers, payload).then(({ statusCode, body: resBody }) => {
12605
+ _transport3.post(this.url, this.headers, payload).then(({ statusCode, body: resBody }) => {
11915
12606
  const tookMs = Date.now() - t0;
11916
12607
  if (statusCode === 410 || statusCode === 404 && /SESSION_NOT_FOUND|SESSION_GONE/.test(resBody)) {
11917
12608
  process.stderr.write("[codeam] session was deleted/disconnected \u2014 stopping output stream.\n");
11918
12609
  log.info("chunkEmitter", `dead status=${statusCode} took=${tookMs}ms`);
11919
- resolve5({ dead: true });
12610
+ resolve6({ dead: true });
11920
12611
  return;
11921
12612
  }
11922
12613
  if (statusCode === 401) {
@@ -11932,7 +12623,7 @@ var ChunkEmitter = class {
11932
12623
  return;
11933
12624
  }
11934
12625
  }
11935
- resolve5({ dead: false });
12626
+ resolve6({ dead: false });
11936
12627
  })();
11937
12628
  return;
11938
12629
  }
@@ -11943,7 +12634,7 @@ var ChunkEmitter = class {
11943
12634
  } else {
11944
12635
  log.info("chunkEmitter", `ok status=${statusCode} took=${tookMs}ms`);
11945
12636
  }
11946
- resolve5({ dead: false });
12637
+ resolve6({ dead: false });
11947
12638
  }).catch((err) => {
11948
12639
  log.warn(
11949
12640
  "chunkEmitter",
@@ -11954,7 +12645,7 @@ var ChunkEmitter = class {
11954
12645
  const delay = 200 * (maxRetries - attemptsLeft + 1);
11955
12646
  setTimeout(() => attempt(attemptsLeft - 1), delay);
11956
12647
  } else {
11957
- resolve5({ dead: false });
12648
+ resolve6({ dead: false });
11958
12649
  }
11959
12650
  });
11960
12651
  };
@@ -11962,14 +12653,14 @@ var ChunkEmitter = class {
11962
12653
  });
11963
12654
  }
11964
12655
  };
11965
- var _transport2 = {
11966
- post: _post
12656
+ var _transport3 = {
12657
+ post: _post2
11967
12658
  };
11968
- function _post(url, headers, payload) {
11969
- return new Promise((resolve5, reject) => {
12659
+ function _post2(url, headers, payload) {
12660
+ return new Promise((resolve6, reject) => {
11970
12661
  let settled = false;
11971
12662
  const u2 = new URL(url);
11972
- const transport = u2.protocol === "https:" ? https3 : http3;
12663
+ const transport = u2.protocol === "https:" ? https4 : http4;
11973
12664
  const req = transport.request(
11974
12665
  {
11975
12666
  hostname: u2.hostname,
@@ -11990,7 +12681,7 @@ function _post(url, headers, payload) {
11990
12681
  res.on("end", () => {
11991
12682
  if (settled) return;
11992
12683
  settled = true;
11993
- resolve5({ statusCode: res.statusCode ?? 0, body: resData });
12684
+ resolve6({ statusCode: res.statusCode ?? 0, body: resData });
11994
12685
  });
11995
12686
  }
11996
12687
  );
@@ -12564,11 +13255,11 @@ var OutputService = class _OutputService {
12564
13255
  };
12565
13256
 
12566
13257
  // src/services/history.service.ts
12567
- var fs20 = __toESM(require("fs"));
12568
- var path24 = __toESM(require("path"));
13258
+ var fs21 = __toESM(require("fs"));
13259
+ var path25 = __toESM(require("path"));
12569
13260
  var os21 = __toESM(require("os"));
12570
- var https4 = __toESM(require("https"));
12571
- var http4 = __toESM(require("http"));
13261
+ var https5 = __toESM(require("https"));
13262
+ var http5 = __toESM(require("http"));
12572
13263
  var import_zod = require("zod");
12573
13264
  var historyRecordSchema = import_zod.z.object({
12574
13265
  type: import_zod.z.string().optional(),
@@ -12581,7 +13272,7 @@ var historyRecordSchema = import_zod.z.object({
12581
13272
  }).passthrough().optional()
12582
13273
  }).passthrough();
12583
13274
  var API_BASE4 = resolveApiBaseUrl();
12584
- function extractText2(content) {
13275
+ function extractText3(content) {
12585
13276
  if (typeof content === "string") return content;
12586
13277
  if (Array.isArray(content)) {
12587
13278
  return content.filter((b) => b["type"] === "text").map((b) => b["text"]).join("\n");
@@ -12593,7 +13284,7 @@ function parseJsonl(filePath) {
12593
13284
  const messages = [];
12594
13285
  let raw;
12595
13286
  try {
12596
- raw = fs20.readFileSync(filePath, "utf8");
13287
+ raw = fs21.readFileSync(filePath, "utf8");
12597
13288
  } catch (err) {
12598
13289
  if (err.code !== "ENOENT") {
12599
13290
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -12620,20 +13311,20 @@ function parseJsonl(filePath) {
12620
13311
  const uuid = record.uuid ?? `${Date.now()}-${Math.random()}`;
12621
13312
  const msg = record.message;
12622
13313
  if (record.type === "user" && msg) {
12623
- const text = extractText2(msg.content).trim();
13314
+ const text = extractText3(msg.content).trim();
12624
13315
  if (text) messages.push({ id: uuid, role: "user", text, timestamp });
12625
13316
  } else if (record.type === "assistant" && msg) {
12626
- const text = extractText2(msg.content).trim();
13317
+ const text = extractText3(msg.content).trim();
12627
13318
  if (text) messages.push({ id: uuid, role: "agent", text, timestamp });
12628
13319
  }
12629
13320
  }
12630
13321
  return messages;
12631
13322
  }
12632
13323
  function post(endpoint, body) {
12633
- return new Promise((resolve5) => {
13324
+ return new Promise((resolve6) => {
12634
13325
  const payload = JSON.stringify(body);
12635
13326
  const u2 = new URL(`${API_BASE4}${endpoint}`);
12636
- const transport = u2.protocol === "https:" ? https4 : http4;
13327
+ const transport = u2.protocol === "https:" ? https5 : http5;
12637
13328
  const req = transport.request(
12638
13329
  {
12639
13330
  hostname: u2.hostname,
@@ -12651,17 +13342,17 @@ function post(endpoint, body) {
12651
13342
  res.resume();
12652
13343
  const ok = res.statusCode !== void 0 && res.statusCode >= 200 && res.statusCode < 300;
12653
13344
  if (!ok) log.warn("history:post", `${endpoint} \u2192 HTTP ${res.statusCode}`);
12654
- resolve5(ok);
13345
+ resolve6(ok);
12655
13346
  }
12656
13347
  );
12657
13348
  req.on("error", (err) => {
12658
13349
  log.warn("history:post", `${endpoint} network error`, err);
12659
- resolve5(false);
13350
+ resolve6(false);
12660
13351
  });
12661
13352
  req.on("timeout", () => {
12662
13353
  log.warn("history:post", `${endpoint} timeout after 15s`);
12663
13354
  req.destroy();
12664
- resolve5(false);
13355
+ resolve6(false);
12665
13356
  });
12666
13357
  req.write(payload);
12667
13358
  req.end();
@@ -12728,7 +13419,7 @@ var HistoryService = class _HistoryService {
12728
13419
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
12729
13420
  }
12730
13421
  get projectDir() {
12731
- return this.runtime.resolveHistoryDir(this.cwd) ?? path24.join(os21.homedir(), ".claude", "projects", encodeCwd(this.cwd));
13422
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path25.join(os21.homedir(), ".claude", "projects", encodeCwd(this.cwd));
12732
13423
  }
12733
13424
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
12734
13425
  setCurrentConversationId(id) {
@@ -12740,7 +13431,7 @@ var HistoryService = class _HistoryService {
12740
13431
  /** Return the current message count in the active conversation. */
12741
13432
  getCurrentMessageCount() {
12742
13433
  if (!this.currentConversationId) return 0;
12743
- const filePath = path24.join(this.projectDir, `${this.currentConversationId}.jsonl`);
13434
+ const filePath = path25.join(this.projectDir, `${this.currentConversationId}.jsonl`);
12744
13435
  return parseJsonl(filePath).length;
12745
13436
  }
12746
13437
  /**
@@ -12751,7 +13442,7 @@ var HistoryService = class _HistoryService {
12751
13442
  const deadline = Date.now() + timeoutMs;
12752
13443
  while (Date.now() < deadline) {
12753
13444
  if (!this.currentConversationId) return null;
12754
- const filePath = path24.join(this.projectDir, `${this.currentConversationId}.jsonl`);
13445
+ const filePath = path25.join(this.projectDir, `${this.currentConversationId}.jsonl`);
12755
13446
  const messages = parseJsonl(filePath);
12756
13447
  if (messages.length > previousCount) {
12757
13448
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -12777,16 +13468,16 @@ var HistoryService = class _HistoryService {
12777
13468
  const dir = this.projectDir;
12778
13469
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
12779
13470
  try {
12780
- const files = fs20.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
13471
+ const files = fs21.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
12781
13472
  try {
12782
- const stat3 = fs20.statSync(path24.join(dir, e.name));
13473
+ const stat3 = fs21.statSync(path25.join(dir, e.name));
12783
13474
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
12784
13475
  } catch {
12785
13476
  return { name: e.name, mtime: 0, birthtime: 0 };
12786
13477
  }
12787
13478
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
12788
13479
  if (files.length > 0) {
12789
- this.currentConversationId = path24.basename(files[0].name, ".jsonl");
13480
+ this.currentConversationId = path25.basename(files[0].name, ".jsonl");
12790
13481
  }
12791
13482
  } catch {
12792
13483
  }
@@ -12820,13 +13511,13 @@ var HistoryService = class _HistoryService {
12820
13511
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
12821
13512
  let entries;
12822
13513
  try {
12823
- entries = fs20.readdirSync(dir, { withFileTypes: true });
13514
+ entries = fs21.readdirSync(dir, { withFileTypes: true });
12824
13515
  } catch {
12825
13516
  return null;
12826
13517
  }
12827
13518
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
12828
13519
  try {
12829
- const stat3 = fs20.statSync(path24.join(dir, e.name));
13520
+ const stat3 = fs21.statSync(path25.join(dir, e.name));
12830
13521
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
12831
13522
  } catch {
12832
13523
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -12835,12 +13526,12 @@ var HistoryService = class _HistoryService {
12835
13526
  if (files.length === 0) return null;
12836
13527
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
12837
13528
  if (!files.some((f) => f.name === targetFile)) return null;
12838
- return this.extractUsageFromFile(path24.join(dir, targetFile));
13529
+ return this.extractUsageFromFile(path25.join(dir, targetFile));
12839
13530
  }
12840
13531
  extractUsageFromFile(filePath) {
12841
13532
  let raw;
12842
13533
  try {
12843
- raw = fs20.readFileSync(filePath, "utf8");
13534
+ raw = fs21.readFileSync(filePath, "utf8");
12844
13535
  } catch {
12845
13536
  return null;
12846
13537
  }
@@ -12885,9 +13576,9 @@ var HistoryService = class _HistoryService {
12885
13576
  let totalCost = 0;
12886
13577
  let files;
12887
13578
  try {
12888
- files = fs20.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
13579
+ files = fs21.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
12889
13580
  try {
12890
- return fs20.statSync(path24.join(projectDir, f)).mtimeMs >= monthStartMs;
13581
+ return fs21.statSync(path25.join(projectDir, f)).mtimeMs >= monthStartMs;
12891
13582
  } catch {
12892
13583
  return false;
12893
13584
  }
@@ -12898,7 +13589,7 @@ var HistoryService = class _HistoryService {
12898
13589
  for (const file of files) {
12899
13590
  let raw;
12900
13591
  try {
12901
- raw = fs20.readFileSync(path24.join(projectDir, file), "utf8");
13592
+ raw = fs21.readFileSync(path25.join(projectDir, file), "utf8");
12902
13593
  } catch {
12903
13594
  continue;
12904
13595
  }
@@ -12962,7 +13653,7 @@ var HistoryService = class _HistoryService {
12962
13653
  * showing an empty conversation.
12963
13654
  */
12964
13655
  async loadConversation(sessionId) {
12965
- const filePath = path24.join(this.projectDir, `${sessionId}.jsonl`);
13656
+ const filePath = path25.join(this.projectDir, `${sessionId}.jsonl`);
12966
13657
  const messages = parseJsonl(filePath);
12967
13658
  if (messages.length === 0) return;
12968
13659
  const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
@@ -13016,7 +13707,7 @@ var HistoryService = class _HistoryService {
13016
13707
  if (!this.currentConversationId) return 0;
13017
13708
  }
13018
13709
  const sessionId = this.currentConversationId;
13019
- const filePath = path24.join(this.projectDir, `${sessionId}.jsonl`);
13710
+ const filePath = path25.join(this.projectDir, `${sessionId}.jsonl`);
13020
13711
  const messages = parseJsonl(filePath);
13021
13712
  if (messages.length === 0) return 0;
13022
13713
  const marker = this.lastUploadedUuid.get(sessionId);
@@ -13047,9 +13738,9 @@ var HistoryService = class _HistoryService {
13047
13738
 
13048
13739
  // src/services/file-watcher.service.ts
13049
13740
  var import_child_process8 = require("child_process");
13050
- var fs21 = __toESM(require("fs"));
13741
+ var fs22 = __toESM(require("fs"));
13051
13742
  var os22 = __toESM(require("os"));
13052
- var path25 = __toESM(require("path"));
13743
+ var path26 = __toESM(require("path"));
13053
13744
 
13054
13745
  // src/services/file-watcher/diff-parser.ts
13055
13746
  var HUNK_HEADER_RE = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
@@ -13138,16 +13829,16 @@ function isIgnoredFilePath(filePath) {
13138
13829
  }
13139
13830
 
13140
13831
  // src/services/file-watcher/transport.ts
13141
- var http5 = __toESM(require("http"));
13142
- var https5 = __toESM(require("https"));
13143
- var _transport3 = {
13144
- post: _post2
13832
+ var http6 = __toESM(require("http"));
13833
+ var https6 = __toESM(require("https"));
13834
+ var _transport4 = {
13835
+ post: _post3
13145
13836
  };
13146
- function _post2(url, headers, payload) {
13147
- return new Promise((resolve5, reject) => {
13837
+ function _post3(url, headers, payload) {
13838
+ return new Promise((resolve6, reject) => {
13148
13839
  let settled = false;
13149
13840
  const u2 = new URL(url);
13150
- const lib = u2.protocol === "https:" ? https5 : http5;
13841
+ const lib = u2.protocol === "https:" ? https6 : http6;
13151
13842
  const req = lib.request(
13152
13843
  {
13153
13844
  hostname: u2.hostname,
@@ -13169,7 +13860,7 @@ function _post2(url, headers, payload) {
13169
13860
  res.on("end", () => {
13170
13861
  if (settled) return;
13171
13862
  settled = true;
13172
- resolve5({ statusCode: res.statusCode ?? 0, body });
13863
+ resolve6({ statusCode: res.statusCode ?? 0, body });
13173
13864
  });
13174
13865
  }
13175
13866
  );
@@ -13240,18 +13931,18 @@ var _findGitRootSeam = {
13240
13931
  resolve: _defaultFindGitRoot
13241
13932
  };
13242
13933
  function _defaultFindGitRoot(startDir) {
13243
- let dir = path25.resolve(startDir);
13934
+ let dir = path26.resolve(startDir);
13244
13935
  const seen = /* @__PURE__ */ new Set();
13245
13936
  for (let i = 0; i < 256; i++) {
13246
13937
  if (seen.has(dir)) return null;
13247
13938
  seen.add(dir);
13248
13939
  try {
13249
- const gitPath = path25.join(dir, ".git");
13250
- const stat3 = fs21.statSync(gitPath, { throwIfNoEntry: false });
13940
+ const gitPath = path26.join(dir, ".git");
13941
+ const stat3 = fs22.statSync(gitPath, { throwIfNoEntry: false });
13251
13942
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
13252
13943
  } catch {
13253
13944
  }
13254
- const parent = path25.dirname(dir);
13945
+ const parent = path26.dirname(dir);
13255
13946
  if (parent === dir) return null;
13256
13947
  dir = parent;
13257
13948
  }
@@ -13485,7 +14176,7 @@ var FileWatcherService = class {
13485
14176
  }
13486
14177
  async emitForFile(absPath, changeType) {
13487
14178
  if (this.stopped) return;
13488
- const fileDir = path25.dirname(absPath);
14179
+ const fileDir = path26.dirname(absPath);
13489
14180
  let gitRoot = this.gitRootByDir.get(fileDir);
13490
14181
  if (gitRoot === void 0) {
13491
14182
  gitRoot = findGitRoot(fileDir);
@@ -13499,10 +14190,10 @@ var FileWatcherService = class {
13499
14190
  return;
13500
14191
  }
13501
14192
  this.opts.onRepoDirty?.(gitRoot);
13502
- const relPathInRepo = path25.relative(gitRoot, absPath);
14193
+ const relPathInRepo = path26.relative(gitRoot, absPath);
13503
14194
  if (!relPathInRepo || relPathInRepo.startsWith("..")) return;
13504
- const repoPath = path25.relative(this.opts.workingDir, gitRoot);
13505
- const repoName = path25.basename(gitRoot);
14195
+ const repoPath = path26.relative(this.opts.workingDir, gitRoot);
14196
+ const repoName = path26.basename(gitRoot);
13506
14197
  let diffText = "";
13507
14198
  let fileStatus = "modified";
13508
14199
  if (changeType === "unlink") {
@@ -13646,7 +14337,7 @@ var FileWatcherService = class {
13646
14337
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt += 1) {
13647
14338
  if (this.stopped) return;
13648
14339
  try {
13649
- const { statusCode, body: resBody } = await _transport3.post(url, headers, payload);
14340
+ const { statusCode, body: resBody } = await _transport4.post(url, headers, payload);
13650
14341
  if (statusCode >= 200 && statusCode < 300) {
13651
14342
  log.trace(
13652
14343
  "fileWatcher",
@@ -13765,12 +14456,12 @@ var _gitSeam = {
13765
14456
  run: _runGitImpl
13766
14457
  };
13767
14458
  async function _runGitImpl(cwd, args2, opts = {}) {
13768
- return new Promise((resolve5) => {
14459
+ return new Promise((resolve6) => {
13769
14460
  let proc;
13770
14461
  try {
13771
14462
  proc = (0, import_child_process8.spawn)("git", args2, { cwd, env: process.env });
13772
14463
  } catch {
13773
- resolve5(null);
14464
+ resolve6(null);
13774
14465
  return;
13775
14466
  }
13776
14467
  let stdout = "";
@@ -13781,13 +14472,13 @@ async function _runGitImpl(cwd, args2, opts = {}) {
13781
14472
  proc.stderr?.on("data", (c2) => {
13782
14473
  stderr += c2.toString();
13783
14474
  });
13784
- proc.on("error", () => resolve5(null));
14475
+ proc.on("error", () => resolve6(null));
13785
14476
  proc.on("close", (code) => {
13786
14477
  if (code === 0 || opts.allowNonZeroExit) {
13787
- resolve5(stdout);
14478
+ resolve6(stdout);
13788
14479
  } else {
13789
14480
  log.trace("fileWatcher", `git ${args2.join(" ")} exited ${code} stderr=${stderr.slice(0, 200)}`);
13790
- resolve5(null);
14481
+ resolve6(null);
13791
14482
  }
13792
14483
  });
13793
14484
  });
@@ -13801,7 +14492,7 @@ var import_crypto2 = require("crypto");
13801
14492
 
13802
14493
  // src/services/turn-files/git-changeset.ts
13803
14494
  var import_child_process9 = require("child_process");
13804
- var path26 = __toESM(require("path"));
14495
+ var path27 = __toESM(require("path"));
13805
14496
  async function collectRepoChangeset(opts) {
13806
14497
  const status2 = await runGit2(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
13807
14498
  if (status2 === null) return null;
@@ -13881,12 +14572,12 @@ function runGit2(cwd, args2) {
13881
14572
  return _runGitImpl2.run(cwd, args2);
13882
14573
  }
13883
14574
  function defaultRunGit(cwd, args2) {
13884
- return new Promise((resolve5) => {
14575
+ return new Promise((resolve6) => {
13885
14576
  let proc;
13886
14577
  try {
13887
14578
  proc = (0, import_child_process9.spawn)("git", args2, { cwd, env: process.env });
13888
14579
  } catch {
13889
- resolve5(null);
14580
+ resolve6(null);
13890
14581
  return;
13891
14582
  }
13892
14583
  let stdout = "";
@@ -13897,22 +14588,22 @@ function defaultRunGit(cwd, args2) {
13897
14588
  proc.stderr?.on("data", (c2) => {
13898
14589
  stderr += c2.toString();
13899
14590
  });
13900
- proc.on("error", () => resolve5(null));
14591
+ proc.on("error", () => resolve6(null));
13901
14592
  proc.on("close", (code) => {
13902
14593
  if (code === 0) {
13903
- resolve5(stdout);
14594
+ resolve6(stdout);
13904
14595
  } else {
13905
14596
  log.trace(
13906
14597
  "turnFiles",
13907
14598
  `git ${args2.join(" ")} exited ${code} stderr=${stderr.slice(0, 200)}`
13908
14599
  );
13909
- resolve5(null);
14600
+ resolve6(null);
13910
14601
  }
13911
14602
  });
13912
14603
  });
13913
14604
  }
13914
14605
  async function discoverRepos(workingDir, maxDepth = 4) {
13915
- const fs34 = await import("fs/promises");
14606
+ const fs35 = await import("fs/promises");
13916
14607
  const out2 = [];
13917
14608
  await walk(workingDir, 0);
13918
14609
  return out2;
@@ -13920,7 +14611,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
13920
14611
  if (depth > maxDepth) return;
13921
14612
  let entries = [];
13922
14613
  try {
13923
- const dirents = await fs34.readdir(dir, { withFileTypes: true });
14614
+ const dirents = await fs35.readdir(dir, { withFileTypes: true });
13924
14615
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
13925
14616
  } catch {
13926
14617
  return;
@@ -13931,8 +14622,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
13931
14622
  if (hasGit) {
13932
14623
  out2.push({
13933
14624
  repoRoot: dir,
13934
- repoPath: path26.relative(workingDir, dir),
13935
- repoName: path26.basename(dir)
14625
+ repoPath: path27.relative(workingDir, dir),
14626
+ repoName: path27.basename(dir)
13936
14627
  });
13937
14628
  return;
13938
14629
  }
@@ -13940,14 +14631,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
13940
14631
  if (!entry.isDirectory) continue;
13941
14632
  if (entry.name === "node_modules") continue;
13942
14633
  if (entry.name === "dist" || entry.name === "build") continue;
13943
- await walk(path26.join(dir, entry.name), depth + 1);
14634
+ await walk(path27.join(dir, entry.name), depth + 1);
13944
14635
  }
13945
14636
  }
13946
14637
  }
13947
14638
 
13948
14639
  // src/services/turn-files/files-outbox.ts
13949
- var fs22 = __toESM(require("fs/promises"));
13950
- var path27 = __toESM(require("path"));
14640
+ var fs23 = __toESM(require("fs/promises"));
14641
+ var path28 = __toESM(require("path"));
13951
14642
  var import_os6 = require("os");
13952
14643
  var HOME_OUTBOX_DIR = ".codeam/outbox";
13953
14644
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -13980,16 +14671,16 @@ var FilesOutbox = class {
13980
14671
  backoffIndex = 0;
13981
14672
  stopped = false;
13982
14673
  constructor(opts) {
13983
- const base = opts.baseDir ?? path27.join(homeDir(), HOME_OUTBOX_DIR);
13984
- this.filePath = path27.join(base, `${opts.sessionId}.jsonl`);
14674
+ const base = opts.baseDir ?? path28.join(homeDir(), HOME_OUTBOX_DIR);
14675
+ this.filePath = path28.join(base, `${opts.sessionId}.jsonl`);
13985
14676
  this.post = opts.post;
13986
14677
  this.autoSchedule = opts.autoSchedule !== false;
13987
14678
  }
13988
14679
  /** Persist the entry to disk and trigger a flush. Returns once the
13989
14680
  * line is durable on disk (not once the POST succeeds). */
13990
14681
  async enqueue(entry) {
13991
- await fs22.mkdir(path27.dirname(this.filePath), { recursive: true });
13992
- await fs22.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
14682
+ await fs23.mkdir(path28.dirname(this.filePath), { recursive: true });
14683
+ await fs23.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
13993
14684
  this.backoffIndex = 0;
13994
14685
  if (this.autoSchedule) this.scheduleFlush(0);
13995
14686
  }
@@ -14078,7 +14769,7 @@ var FilesOutbox = class {
14078
14769
  async readAll() {
14079
14770
  let raw = "";
14080
14771
  try {
14081
- raw = await fs22.readFile(this.filePath, "utf8");
14772
+ raw = await fs23.readFile(this.filePath, "utf8");
14082
14773
  } catch {
14083
14774
  return [];
14084
14775
  }
@@ -14102,12 +14793,12 @@ var FilesOutbox = class {
14102
14793
  async rewrite(entries) {
14103
14794
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
14104
14795
  if (entries.length === 0) {
14105
- await fs22.unlink(this.filePath).catch(() => void 0);
14796
+ await fs23.unlink(this.filePath).catch(() => void 0);
14106
14797
  return;
14107
14798
  }
14108
14799
  const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
14109
- await fs22.writeFile(tmpPath, payload, "utf8");
14110
- await fs22.rename(tmpPath, this.filePath);
14800
+ await fs23.writeFile(tmpPath, payload, "utf8");
14801
+ await fs23.rename(tmpPath, this.filePath);
14111
14802
  }
14112
14803
  };
14113
14804
  function applyJitter(ms) {
@@ -14222,13 +14913,13 @@ var TurnFileAggregator = class {
14222
14913
  return;
14223
14914
  }
14224
14915
  const chunks = chunkArray(novel, MAX_BATCH_SIZE);
14225
- for (const chunk of chunks) {
14916
+ for (const chunk2 of chunks) {
14226
14917
  const entry = {
14227
14918
  turnId: (0, import_crypto2.randomUUID)(),
14228
14919
  sessionId: this.opts.sessionId,
14229
14920
  pluginId: this.opts.pluginId,
14230
14921
  enqueuedAt: Date.now(),
14231
- files: chunk
14922
+ files: chunk2
14232
14923
  };
14233
14924
  await this.outbox.enqueue(entry);
14234
14925
  }
@@ -14267,7 +14958,7 @@ var TurnFileAggregator = class {
14267
14958
  files: entry.files
14268
14959
  });
14269
14960
  try {
14270
- const res = await _transport3.post(url, headers, body);
14961
+ const res = await _transport4.post(url, headers, body);
14271
14962
  return { ok: res.statusCode >= 200 && res.statusCode < 300, statusCode: res.statusCode };
14272
14963
  } catch (err) {
14273
14964
  log.trace(
@@ -14326,101 +15017,9 @@ var RepoDirtyTracker = class {
14326
15017
 
14327
15018
  // src/services/streaming-emitter.service.ts
14328
15019
  var import_crypto3 = require("crypto");
14329
-
14330
- // src/services/streaming/transport.ts
14331
- var http6 = __toESM(require("http"));
14332
- var https6 = __toESM(require("https"));
14333
- var _transport4 = {
14334
- post: _post3,
14335
- get: _get
14336
- };
14337
- function _post3(url, headers, payload) {
14338
- return new Promise((resolve5, reject) => {
14339
- let settled = false;
14340
- const u2 = new URL(url);
14341
- const lib = u2.protocol === "https:" ? https6 : http6;
14342
- const req = lib.request(
14343
- {
14344
- hostname: u2.hostname,
14345
- port: u2.port || (u2.protocol === "https:" ? 443 : 80),
14346
- path: u2.pathname + u2.search,
14347
- method: "POST",
14348
- headers: {
14349
- ...headers,
14350
- ...vercelBypassHeader(),
14351
- "Content-Length": Buffer.byteLength(payload)
14352
- },
14353
- timeout: 8e3
14354
- },
14355
- (res) => {
14356
- let body = "";
14357
- res.on("data", (c2) => {
14358
- body += c2.toString();
14359
- });
14360
- res.on("end", () => {
14361
- if (settled) return;
14362
- settled = true;
14363
- resolve5({ statusCode: res.statusCode ?? 0, body });
14364
- });
14365
- }
14366
- );
14367
- req.on("error", (err) => {
14368
- if (settled) return;
14369
- settled = true;
14370
- reject(err);
14371
- });
14372
- req.on("timeout", () => {
14373
- req.destroy();
14374
- });
14375
- req.write(payload);
14376
- req.end();
14377
- });
14378
- }
14379
- function _get(url, headers) {
14380
- return new Promise((resolve5, reject) => {
14381
- let settled = false;
14382
- const u2 = new URL(url);
14383
- const lib = u2.protocol === "https:" ? https6 : http6;
14384
- const req = lib.request(
14385
- {
14386
- hostname: u2.hostname,
14387
- port: u2.port || (u2.protocol === "https:" ? 443 : 80),
14388
- path: u2.pathname + u2.search,
14389
- method: "GET",
14390
- headers: {
14391
- ...headers,
14392
- ...vercelBypassHeader()
14393
- },
14394
- timeout: 8e3
14395
- },
14396
- (res) => {
14397
- let body = "";
14398
- res.on("data", (c2) => {
14399
- body += c2.toString();
14400
- });
14401
- res.on("end", () => {
14402
- if (settled) return;
14403
- settled = true;
14404
- resolve5({ statusCode: res.statusCode ?? 0, body });
14405
- });
14406
- }
14407
- );
14408
- req.on("error", (err) => {
14409
- if (settled) return;
14410
- settled = true;
14411
- reject(err);
14412
- });
14413
- req.on("timeout", () => {
14414
- req.destroy();
14415
- });
14416
- req.end();
14417
- });
14418
- }
14419
-
14420
- // src/services/streaming-emitter.service.ts
14421
15020
  var API_BASE7 = resolveApiBaseUrl();
14422
15021
  var TICK_MS = 50;
14423
- var ANSWER_POLL_MS = 1500;
15022
+ var ANSWER_POLL_MS2 = 1500;
14424
15023
  var SELECTOR_STABLE_MS = 800;
14425
15024
  var MAX_RETRIES2 = 1;
14426
15025
  var RETRY_BACKOFF_MS2 = 200;
@@ -14460,7 +15059,7 @@ var StreamingEmitterService = class {
14460
15059
  this.tickTimer = setInterval(() => this.tick(), TICK_MS);
14461
15060
  this.answerPollTimer = setInterval(() => {
14462
15061
  void this.pollPendingAnswer();
14463
- }, ANSWER_POLL_MS);
15062
+ }, ANSWER_POLL_MS2);
14464
15063
  log.trace("streamingEmitter", `started session=${this.opts.sessionId.slice(0, 8)}`);
14465
15064
  }
14466
15065
  /**
@@ -14481,11 +15080,11 @@ var StreamingEmitterService = class {
14481
15080
  }
14482
15081
  if (this.activeChunk) {
14483
15082
  const finalContent = this.activeChunk.currentContent;
14484
- const chunk = this.activeChunk;
15083
+ const chunk2 = this.activeChunk;
14485
15084
  this.activeChunk = null;
14486
15085
  await this.postChunk({
14487
- chunkId: chunk.chunkId,
14488
- kind: chunk.kind,
15086
+ chunkId: chunk2.chunkId,
15087
+ kind: chunk2.kind,
14489
15088
  content: finalContent,
14490
15089
  isFinal: true
14491
15090
  });
@@ -14557,17 +15156,17 @@ var StreamingEmitterService = class {
14557
15156
  this.maybeFlushActive(false);
14558
15157
  }
14559
15158
  maybeFlushActive(force) {
14560
- const chunk = this.activeChunk;
14561
- if (!chunk) return;
15159
+ const chunk2 = this.activeChunk;
15160
+ if (!chunk2) return;
14562
15161
  const now = Date.now();
14563
- if (!force && now - chunk.lastEmitAt < TICK_MS) return;
14564
- if (chunk.currentContent === chunk.emittedContent) return;
14565
- chunk.emittedContent = chunk.currentContent;
14566
- chunk.lastEmitAt = now;
15162
+ if (!force && now - chunk2.lastEmitAt < TICK_MS) return;
15163
+ if (chunk2.currentContent === chunk2.emittedContent) return;
15164
+ chunk2.emittedContent = chunk2.currentContent;
15165
+ chunk2.lastEmitAt = now;
14567
15166
  void this.postChunk({
14568
- chunkId: chunk.chunkId,
14569
- kind: chunk.kind,
14570
- content: chunk.currentContent,
15167
+ chunkId: chunk2.chunkId,
15168
+ kind: chunk2.kind,
15169
+ content: chunk2.currentContent,
14571
15170
  isFinal: false
14572
15171
  });
14573
15172
  }
@@ -14634,7 +15233,7 @@ var StreamingEmitterService = class {
14634
15233
  if (!this.pendingAnswer) return;
14635
15234
  const questionId = this.pendingAnswer.questionId;
14636
15235
  try {
14637
- const { statusCode, body } = await _transport4.get(
15236
+ const { statusCode, body } = await _transport2.get(
14638
15237
  `${this.apiBase}/api/sessions/${encodeURIComponent(this.opts.sessionId)}/pending-answer?questionId=${encodeURIComponent(questionId)}&pluginId=${encodeURIComponent(this.opts.pluginId)}`,
14639
15238
  this.headers
14640
15239
  );
@@ -14645,7 +15244,7 @@ var StreamingEmitterService = class {
14645
15244
  log.warn("streamingEmitter", `pending-answer status=${statusCode} body=${body.slice(0, 200)}`);
14646
15245
  return;
14647
15246
  }
14648
- const parsed = parsePendingAnswerResponse(body);
15247
+ const parsed = parsePendingAnswerResponse2(body);
14649
15248
  if (!parsed || parsed.questionId !== questionId) return;
14650
15249
  const pending = this.pendingAnswer;
14651
15250
  this.pendingAnswer = null;
@@ -14695,7 +15294,7 @@ var StreamingEmitterService = class {
14695
15294
  });
14696
15295
  for (let attempt = 0; attempt <= MAX_RETRIES2; attempt += 1) {
14697
15296
  try {
14698
- const { statusCode, body: resBody } = await _transport4.post(url, this.headers, payload);
15297
+ const { statusCode, body: resBody } = await _transport2.post(url, this.headers, payload);
14699
15298
  if (statusCode >= 200 && statusCode < 300) {
14700
15299
  log.trace("streamingEmitter", `post ok url=${url} status=${statusCode}`);
14701
15300
  return;
@@ -14742,7 +15341,7 @@ function classifyLine(line, parseChrome, runtime) {
14742
15341
  if (filtered.length === 0) return null;
14743
15342
  return "text";
14744
15343
  }
14745
- function parsePendingAnswerResponse(body) {
15344
+ function parsePendingAnswerResponse2(body) {
14746
15345
  if (!body) return null;
14747
15346
  let parsed;
14748
15347
  try {
@@ -14784,7 +15383,7 @@ function buildKeepAlive(ctx) {
14784
15383
  let timer = null;
14785
15384
  async function setIdleTimeout(minutes) {
14786
15385
  if (!ctx.inCodespace || !ctx.codespaceName) return;
14787
- await new Promise((resolve5) => {
15386
+ await new Promise((resolve6) => {
14788
15387
  const proc = (0, import_child_process10.spawn)(
14789
15388
  "gh",
14790
15389
  [
@@ -14798,8 +15397,8 @@ function buildKeepAlive(ctx) {
14798
15397
  { stdio: "ignore", detached: true }
14799
15398
  );
14800
15399
  proc.unref();
14801
- proc.on("exit", () => resolve5());
14802
- proc.on("error", () => resolve5());
15400
+ proc.on("exit", () => resolve6());
15401
+ proc.on("error", () => resolve6());
14803
15402
  });
14804
15403
  }
14805
15404
  return {
@@ -14822,9 +15421,9 @@ function buildKeepAlive(ctx) {
14822
15421
  }
14823
15422
 
14824
15423
  // src/commands/start/handlers.ts
14825
- var fs30 = __toESM(require("fs"));
15424
+ var fs31 = __toESM(require("fs"));
14826
15425
  var os24 = __toESM(require("os"));
14827
- var path36 = __toESM(require("path"));
15426
+ var path37 = __toESM(require("path"));
14828
15427
  var import_crypto5 = require("crypto");
14829
15428
  var import_child_process15 = require("child_process");
14830
15429
 
@@ -14948,8 +15547,8 @@ function parsePayload2(schema, raw) {
14948
15547
  }
14949
15548
 
14950
15549
  // src/services/file-ops.service.ts
14951
- var fs23 = __toESM(require("fs/promises"));
14952
- var path28 = __toESM(require("path"));
15550
+ var fs24 = __toESM(require("fs/promises"));
15551
+ var path29 = __toESM(require("path"));
14953
15552
  var MAX_FILE_BYTES = 5 * 1024 * 1024;
14954
15553
  var MAX_WALK_DEPTH = 6;
14955
15554
  var MAX_VISITED_DIRS = 5e3;
@@ -14984,12 +15583,12 @@ var SUBDIR_IGNORE = /* @__PURE__ */ new Set([
14984
15583
  "__pycache__"
14985
15584
  ]);
14986
15585
  function isUnder(parent, candidate) {
14987
- const rel = path28.relative(parent, candidate);
14988
- return rel === "" || !rel.startsWith("..") && !path28.isAbsolute(rel);
15586
+ const rel = path29.relative(parent, candidate);
15587
+ return rel === "" || !rel.startsWith("..") && !path29.isAbsolute(rel);
14989
15588
  }
14990
15589
  async function isExistingFile(absPath) {
14991
15590
  try {
14992
- const stat3 = await fs23.stat(absPath);
15591
+ const stat3 = await fs24.stat(absPath);
14993
15592
  return stat3.isFile();
14994
15593
  } catch {
14995
15594
  return false;
@@ -15002,13 +15601,13 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
15002
15601
  ctx.visited++;
15003
15602
  let entries = [];
15004
15603
  try {
15005
- entries = await fs23.readdir(dir, { withFileTypes: true });
15604
+ entries = await fs24.readdir(dir, { withFileTypes: true });
15006
15605
  } catch {
15007
15606
  return;
15008
15607
  }
15009
15608
  for (const e of entries) {
15010
15609
  if (!e.isFile()) continue;
15011
- const full = path28.join(dir, e.name);
15610
+ const full = path29.join(dir, e.name);
15012
15611
  if (needleVariants.some((needle) => full.endsWith(needle))) {
15013
15612
  ctx.matches.push(full);
15014
15613
  if (ctx.matches.length >= ctx.cap) return;
@@ -15018,21 +15617,21 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
15018
15617
  if (!e.isDirectory()) continue;
15019
15618
  if (SUBDIR_IGNORE.has(e.name)) continue;
15020
15619
  if (e.name.startsWith(".") && SUBDIR_IGNORE.has(e.name)) continue;
15021
- await walkForSuffix(path28.join(dir, e.name), needleVariants, depth + 1, ctx);
15620
+ await walkForSuffix(path29.join(dir, e.name), needleVariants, depth + 1, ctx);
15022
15621
  if (ctx.matches.length >= ctx.cap) return;
15023
15622
  }
15024
15623
  }
15025
15624
  async function findFile(rawPath) {
15026
15625
  const cwd = process.cwd();
15027
- if (path28.isAbsolute(rawPath)) {
15028
- const abs = path28.normalize(rawPath);
15626
+ if (path29.isAbsolute(rawPath)) {
15627
+ const abs = path29.normalize(rawPath);
15029
15628
  if (isUnder(cwd, abs) && await isExistingFile(abs)) return abs;
15030
15629
  }
15031
- const direct = path28.resolve(cwd, rawPath);
15630
+ const direct = path29.resolve(cwd, rawPath);
15032
15631
  if (isUnder(cwd, direct) && await isExistingFile(direct)) return direct;
15033
- const normalized = path28.normalize(rawPath).replace(/^[./\\]+/, "");
15632
+ const normalized = path29.normalize(rawPath).replace(/^[./\\]+/, "");
15034
15633
  const needles = [
15035
- `${path28.sep}${normalized}`,
15634
+ `${path29.sep}${normalized}`,
15036
15635
  `/${normalized}`
15037
15636
  ].filter((v, i, a) => a.indexOf(v) === i);
15038
15637
  const ctx = { visited: 0, matches: [], cap: 16 };
@@ -15046,7 +15645,7 @@ async function findWriteTarget(rawPath) {
15046
15645
  const found = await findFile(rawPath);
15047
15646
  if (found) return found;
15048
15647
  const cwd = process.cwd();
15049
- const fallback = path28.isAbsolute(rawPath) ? path28.normalize(rawPath) : path28.resolve(cwd, rawPath);
15648
+ const fallback = path29.isAbsolute(rawPath) ? path29.normalize(rawPath) : path29.resolve(cwd, rawPath);
15050
15649
  if (!isUnder(cwd, fallback)) return null;
15051
15650
  return fallback;
15052
15651
  }
@@ -15063,11 +15662,11 @@ async function readProjectFile(rawPath) {
15063
15662
  if (!abs) {
15064
15663
  return { error: `File not found in the project tree: ${rawPath}` };
15065
15664
  }
15066
- const stat3 = await fs23.stat(abs);
15665
+ const stat3 = await fs24.stat(abs);
15067
15666
  if (stat3.size > MAX_FILE_BYTES) {
15068
15667
  return { error: `File too large (${(stat3.size / 1024 / 1024).toFixed(1)} MB > ${MAX_FILE_BYTES / 1024 / 1024} MB).` };
15069
15668
  }
15070
- const buf = await fs23.readFile(abs);
15669
+ const buf = await fs24.readFile(abs);
15071
15670
  if (looksBinary(buf)) {
15072
15671
  return { error: "Binary file \u2014 refusing to open in a code editor." };
15073
15672
  }
@@ -15086,8 +15685,8 @@ async function writeProjectFile(rawPath, content) {
15086
15685
  if (Buffer.byteLength(content, "utf-8") > MAX_FILE_BYTES) {
15087
15686
  return { error: "Content too large." };
15088
15687
  }
15089
- await fs23.mkdir(path28.dirname(abs), { recursive: true });
15090
- await fs23.writeFile(abs, content, "utf-8");
15688
+ await fs24.mkdir(path29.dirname(abs), { recursive: true });
15689
+ await fs24.writeFile(abs, content, "utf-8");
15091
15690
  return { ok: true };
15092
15691
  } catch (e) {
15093
15692
  const msg = e instanceof Error ? e.message : "Write failed";
@@ -15098,8 +15697,8 @@ async function writeProjectFile(rawPath, content) {
15098
15697
  // src/services/project-ops.service.ts
15099
15698
  var import_child_process11 = require("child_process");
15100
15699
  var import_util2 = require("util");
15101
- var fs24 = __toESM(require("fs/promises"));
15102
- var path29 = __toESM(require("path"));
15700
+ var fs25 = __toESM(require("fs/promises"));
15701
+ var path30 = __toESM(require("path"));
15103
15702
  var execFileP3 = (0, import_util2.promisify)(import_child_process11.execFile);
15104
15703
  var PROJECT_IGNORE = /* @__PURE__ */ new Set([
15105
15704
  "node_modules",
@@ -15147,7 +15746,7 @@ async function listProjectFiles(opts = {}) {
15147
15746
  }
15148
15747
  let entries = [];
15149
15748
  try {
15150
- entries = await fs24.readdir(dir, { withFileTypes: true });
15749
+ entries = await fs25.readdir(dir, { withFileTypes: true });
15151
15750
  } catch {
15152
15751
  return;
15153
15752
  }
@@ -15157,18 +15756,18 @@ async function listProjectFiles(opts = {}) {
15157
15756
  return;
15158
15757
  }
15159
15758
  if (PROJECT_IGNORE.has(e.name)) continue;
15160
- const full = path29.join(dir, e.name);
15759
+ const full = path30.join(dir, e.name);
15161
15760
  if (e.isDirectory()) {
15162
15761
  if (depth >= 12) continue;
15163
15762
  await walk(full, depth + 1);
15164
15763
  } else if (e.isFile()) {
15165
- const rel = path29.relative(root, full);
15764
+ const rel = path30.relative(root, full);
15166
15765
  if (q2 && !rel.toLowerCase().includes(q2) && !e.name.toLowerCase().includes(q2)) {
15167
15766
  continue;
15168
15767
  }
15169
15768
  let size = 0;
15170
15769
  try {
15171
- const st3 = await fs24.stat(full);
15770
+ const st3 = await fs25.stat(full);
15172
15771
  size = st3.size;
15173
15772
  } catch {
15174
15773
  }
@@ -15270,8 +15869,8 @@ async function gitStatus(cwd) {
15270
15869
  let hasMergeInProgress = false;
15271
15870
  try {
15272
15871
  const gitDir = (await git(["rev-parse", "--git-dir"], root)).stdout.trim();
15273
- const mergeHead = path29.isAbsolute(gitDir) ? path29.join(gitDir, "MERGE_HEAD") : path29.join(root, gitDir, "MERGE_HEAD");
15274
- await fs24.access(mergeHead);
15872
+ const mergeHead = path30.isAbsolute(gitDir) ? path30.join(gitDir, "MERGE_HEAD") : path30.join(root, gitDir, "MERGE_HEAD");
15873
+ await fs25.access(mergeHead);
15275
15874
  hasMergeInProgress = true;
15276
15875
  } catch {
15277
15876
  }
@@ -15417,7 +16016,7 @@ async function jsSearchFiles(opts, cwd, cap) {
15417
16016
  }
15418
16017
  let content = "";
15419
16018
  try {
15420
- content = await fs24.readFile(path29.join(cwd, f.path), "utf8");
16019
+ content = await fs25.readFile(path30.join(cwd, f.path), "utf8");
15421
16020
  } catch {
15422
16021
  continue;
15423
16022
  }
@@ -15698,14 +16297,14 @@ function closeAllTerminals() {
15698
16297
 
15699
16298
  // src/services/apply-file-review.service.ts
15700
16299
  var import_child_process13 = require("child_process");
15701
- var fs25 = __toESM(require("fs"));
15702
- var path31 = __toESM(require("path"));
16300
+ var fs26 = __toESM(require("fs"));
16301
+ var path32 = __toESM(require("path"));
15703
16302
  async function applyFileReview(workingDir, filePath, action) {
15704
- if (filePath.includes("..") || path31.isAbsolute(filePath)) {
16303
+ if (filePath.includes("..") || path32.isAbsolute(filePath)) {
15705
16304
  return { ok: false, action, filePath, error: "invalid file path" };
15706
16305
  }
15707
- const absFile = path31.resolve(workingDir, filePath);
15708
- const repoRoot = findGitRoot2(path31.dirname(absFile));
16306
+ const absFile = path32.resolve(workingDir, filePath);
16307
+ const repoRoot = findGitRoot2(path32.dirname(absFile));
15709
16308
  if (!repoRoot) {
15710
16309
  return {
15711
16310
  ok: false,
@@ -15714,7 +16313,7 @@ async function applyFileReview(workingDir, filePath, action) {
15714
16313
  error: `no enclosing git repo for ${filePath}`
15715
16314
  };
15716
16315
  }
15717
- const relInRepo = path31.relative(repoRoot, absFile);
16316
+ const relInRepo = path32.relative(repoRoot, absFile);
15718
16317
  if (!relInRepo || relInRepo.startsWith("..")) {
15719
16318
  return { ok: false, action, filePath, error: "path escapes repo root" };
15720
16319
  }
@@ -15736,12 +16335,12 @@ async function applyFileReview(workingDir, filePath, action) {
15736
16335
  return { ok: true, action, filePath, repoRoot };
15737
16336
  }
15738
16337
  function runGit3(cwd, args2) {
15739
- return new Promise((resolve5) => {
16338
+ return new Promise((resolve6) => {
15740
16339
  let proc;
15741
16340
  try {
15742
16341
  proc = (0, import_child_process13.spawn)("git", args2, { cwd, env: process.env });
15743
16342
  } catch (err) {
15744
- resolve5({ ok: false, code: -1, stdout: "", stderr: err.message });
16343
+ resolve6({ ok: false, code: -1, stdout: "", stderr: err.message });
15745
16344
  return;
15746
16345
  }
15747
16346
  let stdout = "";
@@ -15754,26 +16353,26 @@ function runGit3(cwd, args2) {
15754
16353
  });
15755
16354
  proc.on(
15756
16355
  "error",
15757
- (err) => resolve5({ ok: false, code: -1, stdout, stderr: stderr + err.message })
16356
+ (err) => resolve6({ ok: false, code: -1, stdout, stderr: stderr + err.message })
15758
16357
  );
15759
16358
  proc.on(
15760
16359
  "close",
15761
- (code) => resolve5({ ok: code === 0, code: code ?? -1, stdout, stderr })
16360
+ (code) => resolve6({ ok: code === 0, code: code ?? -1, stdout, stderr })
15762
16361
  );
15763
16362
  });
15764
16363
  }
15765
16364
  function findGitRoot2(startDir) {
15766
- let dir = path31.resolve(startDir);
16365
+ let dir = path32.resolve(startDir);
15767
16366
  const seen = /* @__PURE__ */ new Set();
15768
16367
  for (let i = 0; i < 256; i++) {
15769
16368
  if (seen.has(dir)) return null;
15770
16369
  seen.add(dir);
15771
16370
  try {
15772
- const stat3 = fs25.statSync(path31.join(dir, ".git"), { throwIfNoEntry: false });
16371
+ const stat3 = fs26.statSync(path32.join(dir, ".git"), { throwIfNoEntry: false });
15773
16372
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
15774
16373
  } catch {
15775
16374
  }
15776
- const parent = path31.dirname(dir);
16375
+ const parent = path32.dirname(dir);
15777
16376
  if (parent === dir) return null;
15778
16377
  dir = parent;
15779
16378
  }
@@ -15781,9 +16380,9 @@ function findGitRoot2(startDir) {
15781
16380
  }
15782
16381
 
15783
16382
  // src/commands/link.ts
15784
- var import_node_crypto5 = require("crypto");
15785
- var fs26 = __toESM(require("fs"));
15786
- var path32 = __toESM(require("path"));
16383
+ var import_node_crypto7 = require("crypto");
16384
+ var fs27 = __toESM(require("fs"));
16385
+ var path33 = __toESM(require("path"));
15787
16386
  var import_chokidar = __toESM(require("chokidar"));
15788
16387
  var import_picocolors2 = __toESM(require("picocolors"));
15789
16388
 
@@ -15843,7 +16442,7 @@ function parseLinkArgs(args2) {
15843
16442
  if (apiKeyFileArg) {
15844
16443
  const filePath = apiKeyFileArg.slice("--api-key-file=".length);
15845
16444
  try {
15846
- apiKey = fs26.readFileSync(path32.resolve(filePath), "utf8").trim();
16445
+ apiKey = fs27.readFileSync(path33.resolve(filePath), "utf8").trim();
15847
16446
  } catch (err) {
15848
16447
  throw new Error(`Could not read --api-key-file ${filePath}: ${err.message}`);
15849
16448
  }
@@ -15870,7 +16469,7 @@ async function link(args2 = []) {
15870
16469
  await linkDryRunPreflight(ctx);
15871
16470
  return;
15872
16471
  }
15873
- const pluginId = (0, import_node_crypto5.randomUUID)();
16472
+ const pluginId = (0, import_node_crypto7.randomUUID)();
15874
16473
  const spin = dist_exports.spinner();
15875
16474
  spin.start("Requesting pairing code...");
15876
16475
  const pairing = await requestCode(pluginId);
@@ -15888,7 +16487,7 @@ async function link(args2 = []) {
15888
16487
  waitSpin.start(waitMsg());
15889
16488
  const countdown = setInterval(() => waitSpin.message(waitMsg()), 1e3);
15890
16489
  countdown.unref?.();
15891
- const paired = await new Promise((resolve5, reject) => {
16490
+ const paired = await new Promise((resolve6, reject) => {
15892
16491
  let stopPoll = null;
15893
16492
  const sigint = () => {
15894
16493
  clearInterval(countdown);
@@ -15901,7 +16500,7 @@ async function link(args2 = []) {
15901
16500
  process.removeListener("SIGINT", sigint);
15902
16501
  clearInterval(countdown);
15903
16502
  waitSpin.stop("Paired");
15904
- resolve5(info);
16503
+ resolve6(info);
15905
16504
  },
15906
16505
  () => {
15907
16506
  clearInterval(countdown);
@@ -15937,7 +16536,7 @@ async function link(args2 = []) {
15937
16536
  return;
15938
16537
  }
15939
16538
  if (parsed.tokenFile) {
15940
- const credential = fs26.readFileSync(path32.resolve(parsed.tokenFile), "utf8").trim();
16539
+ const credential = fs27.readFileSync(path33.resolve(parsed.tokenFile), "utf8").trim();
15941
16540
  if (!credential) {
15942
16541
  showError(`--token-file ${parsed.tokenFile} is empty.`);
15943
16542
  process.exit(1);
@@ -16036,14 +16635,14 @@ async function captureFreshCredentials(ctx) {
16036
16635
  }
16037
16636
  };
16038
16637
  try {
16039
- const token = await new Promise((resolve5, reject) => {
16638
+ const token = await new Promise((resolve6, reject) => {
16040
16639
  let settled = false;
16041
16640
  const tryExtract = async () => {
16042
16641
  if (settled) return;
16043
16642
  const t2 = await ctx.locator.extract();
16044
16643
  if (t2 && !settled) {
16045
16644
  settled = true;
16046
- resolve5(t2);
16645
+ resolve6(t2);
16047
16646
  }
16048
16647
  };
16049
16648
  watcher.on("add", () => void tryExtract());
@@ -16447,7 +17046,7 @@ var pendingAttachmentFiles = /* @__PURE__ */ new Set();
16447
17046
  function cleanupAttachmentTempFiles() {
16448
17047
  for (const p2 of pendingAttachmentFiles) {
16449
17048
  try {
16450
- fs30.unlinkSync(p2);
17049
+ fs31.unlinkSync(p2);
16451
17050
  } catch {
16452
17051
  }
16453
17052
  }
@@ -16456,8 +17055,8 @@ function cleanupAttachmentTempFiles() {
16456
17055
  function saveFilesTemp(files) {
16457
17056
  return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
16458
17057
  const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
16459
- const tmpPath = path36.join(os24.tmpdir(), `codeam-${(0, import_crypto5.randomUUID)()}-${safeName}`);
16460
- fs30.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
17058
+ const tmpPath = path37.join(os24.tmpdir(), `codeam-${(0, import_crypto5.randomUUID)()}-${safeName}`);
17059
+ fs31.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
16461
17060
  pendingAttachmentFiles.add(tmpPath);
16462
17061
  return tmpPath;
16463
17062
  });
@@ -16477,7 +17076,7 @@ var startTask = (ctx, _cmd, parsed) => {
16477
17076
  setTimeout(() => {
16478
17077
  for (const p2 of paths) {
16479
17078
  try {
16480
- fs30.unlinkSync(p2);
17079
+ fs31.unlinkSync(p2);
16481
17080
  } catch {
16482
17081
  }
16483
17082
  pendingAttachmentFiles.delete(p2);
@@ -16645,7 +17244,7 @@ var shutdownSession = async (ctx, cmd) => {
16645
17244
  ctx.relay.stop();
16646
17245
  process.exit(0);
16647
17246
  };
16648
- var readFile4 = async (ctx, cmd, parsed) => {
17247
+ var readFile5 = async (ctx, cmd, parsed) => {
16649
17248
  if (!parsed.path) {
16650
17249
  await ctx.relay.sendResult(cmd.id, "failed", { error: "Missing path" });
16651
17250
  return;
@@ -16653,7 +17252,7 @@ var readFile4 = async (ctx, cmd, parsed) => {
16653
17252
  const result = await readProjectFile(parsed.path);
16654
17253
  await ctx.relay.sendResult(cmd.id, "completed", result);
16655
17254
  };
16656
- var writeFile3 = async (ctx, cmd, parsed) => {
17255
+ var writeFile4 = async (ctx, cmd, parsed) => {
16657
17256
  if (!parsed.path || typeof parsed.content !== "string") {
16658
17257
  await ctx.relay.sendResult(cmd.id, "failed", { error: "Missing path or content" });
16659
17258
  return;
@@ -17104,8 +17703,8 @@ var previewStartH = (ctx, _cmd, parsed) => {
17104
17703
  let readyMatched = false;
17105
17704
  let expoUrl = null;
17106
17705
  const readyRe = new RegExp(detection.ready_pattern);
17107
- const onChunk = (chunk) => {
17108
- const s = chunk.toString();
17706
+ const onChunk = (chunk2) => {
17707
+ const s = chunk2.toString();
17109
17708
  if (!readyMatched && readyRe.test(s)) readyMatched = true;
17110
17709
  if (!expoUrl && detection.framework === "Expo") expoUrl = parseExpoUrl(s);
17111
17710
  };
@@ -17228,8 +17827,8 @@ var previewStartH = (ctx, _cmd, parsed) => {
17228
17827
  stdio: ["ignore", "pipe", "pipe"]
17229
17828
  });
17230
17829
  let parsedUrl = null;
17231
- const onTunnelChunk = (chunk) => {
17232
- const s = chunk.toString();
17830
+ const onTunnelChunk = (chunk2) => {
17831
+ const s = chunk2.toString();
17233
17832
  if (!parsedUrl) parsedUrl = parseCloudflaredUrl(s);
17234
17833
  const trimmed = s.replace(/\n+$/g, "");
17235
17834
  if (trimmed.length > 0) log.info("preview", `cloudflared: ${trimmed}`);
@@ -17321,22 +17920,22 @@ var previewStopH = (ctx) => {
17321
17920
  })();
17322
17921
  };
17323
17922
  function runOnce(cmd, args2, cwd, env) {
17324
- return new Promise((resolve5) => {
17923
+ return new Promise((resolve6) => {
17325
17924
  const child = (0, import_child_process15.spawn)(cmd, args2, {
17326
17925
  cwd,
17327
17926
  env: { ...process.env, ...env ?? {} },
17328
17927
  stdio: ["ignore", "pipe", "pipe"]
17329
17928
  });
17330
17929
  const tag = `setup:${cmd}`;
17331
- const onChunk = (chunk) => {
17332
- const text = chunk.toString().replace(/\n+$/g, "");
17930
+ const onChunk = (chunk2) => {
17931
+ const text = chunk2.toString().replace(/\n+$/g, "");
17333
17932
  if (text.length === 0) return;
17334
17933
  log.info("preview", `${tag}: ${text}`);
17335
17934
  };
17336
17935
  child.stdout?.on("data", onChunk);
17337
17936
  child.stderr?.on("data", onChunk);
17338
- child.once("exit", (code) => resolve5(code));
17339
- child.once("error", () => resolve5(-1));
17937
+ child.once("exit", (code) => resolve6(code));
17938
+ child.once("error", () => resolve6(-1));
17340
17939
  });
17341
17940
  }
17342
17941
  var savePreviewConfigH = (_ctx, _cmd, parsed) => {
@@ -17364,8 +17963,8 @@ var handlers = {
17364
17963
  set_keep_alive: setKeepAlive,
17365
17964
  session_terminated: sessionTerminated,
17366
17965
  shutdown_session: shutdownSession,
17367
- read_file: readFile4,
17368
- write_file: writeFile3,
17966
+ read_file: readFile5,
17967
+ write_file: writeFile4,
17369
17968
  list_files: listFiles,
17370
17969
  search_files: searchFilesH,
17371
17970
  terminal_open: terminalOpenH,
@@ -17441,6 +18040,23 @@ async function start(requestedAgent) {
17441
18040
  requestedAgent: requestedAgent ?? null
17442
18041
  });
17443
18042
  const cwd = process.cwd();
18043
+ if (process.env.CODEAM_ACP_ENABLED === "1" && session.pluginAuthToken) {
18044
+ const adapter = getAcpAdapter(session.agent);
18045
+ if (adapter) {
18046
+ await runAcpSession({
18047
+ agent: session.agent,
18048
+ sessionId: session.id,
18049
+ pluginId,
18050
+ pluginAuthToken: session.pluginAuthToken,
18051
+ adapter,
18052
+ cwd
18053
+ });
18054
+ return;
18055
+ }
18056
+ showInfo(
18057
+ `CODEAM_ACP_ENABLED is set but no ACP adapter is registered for "${session.agent}" \u2014 falling back to PTY runtime.`
18058
+ );
18059
+ }
17444
18060
  const runtime = createRuntimeStrategy(session.agent);
17445
18061
  const historySvc = new HistoryService(runtime, pluginId, cwd);
17446
18062
  const keepAliveCtx = {
@@ -17688,7 +18304,7 @@ async function pair(args2 = []) {
17688
18304
  waitSpin.message(waitMessage());
17689
18305
  }, 1e3);
17690
18306
  countdownInterval.unref?.();
17691
- await new Promise((resolve5) => {
18307
+ await new Promise((resolve6) => {
17692
18308
  let stopPolling = null;
17693
18309
  function sigintHandler() {
17694
18310
  clearInterval(countdownInterval);
@@ -17736,7 +18352,7 @@ async function pair(args2 = []) {
17736
18352
  pluginAuthToken: info.pluginAuthToken
17737
18353
  });
17738
18354
  }
17739
- resolve5();
18355
+ resolve6();
17740
18356
  },
17741
18357
  () => {
17742
18358
  clearInterval(countdownInterval);
@@ -17788,7 +18404,7 @@ async function autoLinkAfterPair(opts) {
17788
18404
  }
17789
18405
 
17790
18406
  // src/commands/pair-auto.ts
17791
- var fs31 = __toESM(require("fs"));
18407
+ var fs32 = __toESM(require("fs"));
17792
18408
  var os25 = __toESM(require("os"));
17793
18409
  var import_crypto7 = require("crypto");
17794
18410
 
@@ -17957,12 +18573,12 @@ function readTokenFromArgs(args2) {
17957
18573
  }
17958
18574
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
17959
18575
  if (fileFlag) {
17960
- const path43 = fileFlag.slice("--token-file=".length);
18576
+ const path44 = fileFlag.slice("--token-file=".length);
17961
18577
  try {
17962
- const content = fs31.readFileSync(path43, "utf8").trim();
17963
- if (content.length === 0) fail(`--token-file ${path43} is empty`);
18578
+ const content = fs32.readFileSync(path44, "utf8").trim();
18579
+ if (content.length === 0) fail(`--token-file ${path44} is empty`);
17964
18580
  try {
17965
- fs31.unlinkSync(path43);
18581
+ fs32.unlinkSync(path44);
17966
18582
  } catch {
17967
18583
  }
17968
18584
  return content;
@@ -18228,7 +18844,7 @@ var import_picocolors10 = __toESM(require("picocolors"));
18228
18844
  var import_child_process16 = require("child_process");
18229
18845
  var import_util4 = require("util");
18230
18846
  var import_picocolors8 = __toESM(require("picocolors"));
18231
- var path37 = __toESM(require("path"));
18847
+ var path38 = __toESM(require("path"));
18232
18848
  var execFileP5 = (0, import_util4.promisify)(import_child_process16.execFile);
18233
18849
  var MAX_BUFFER = 8 * 1024 * 1024;
18234
18850
  function resetStdinForChild() {
@@ -18272,12 +18888,12 @@ var GitHubCodespacesProvider = class {
18272
18888
  }
18273
18889
  if (!isAuthed) {
18274
18890
  resetStdinForChild();
18275
- await new Promise((resolve5, reject) => {
18891
+ await new Promise((resolve6, reject) => {
18276
18892
  const proc = (0, import_child_process16.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
18277
18893
  stdio: "inherit"
18278
18894
  });
18279
18895
  proc.on("exit", (code) => {
18280
- if (code === 0) resolve5();
18896
+ if (code === 0) resolve6();
18281
18897
  else reject(new Error("gh auth login failed."));
18282
18898
  });
18283
18899
  proc.on("error", reject);
@@ -18306,13 +18922,13 @@ var GitHubCodespacesProvider = class {
18306
18922
  }
18307
18923
  wt(noteLines.join("\n"), "One more permission needed");
18308
18924
  resetStdinForChild();
18309
- const refreshCode = await new Promise((resolve5, reject) => {
18925
+ const refreshCode = await new Promise((resolve6, reject) => {
18310
18926
  const proc = (0, import_child_process16.spawn)(
18311
18927
  "gh",
18312
18928
  ["auth", "refresh", "-h", "github.com", "-s", "codespace"],
18313
18929
  { stdio: "inherit" }
18314
18930
  );
18315
- proc.on("exit", (code) => resolve5(code ?? 1));
18931
+ proc.on("exit", (code) => resolve6(code ?? 1));
18316
18932
  proc.on("error", reject);
18317
18933
  });
18318
18934
  if (refreshCode !== 0) {
@@ -18456,10 +19072,10 @@ var GitHubCodespacesProvider = class {
18456
19072
  if (q(proceed) || !proceed) return;
18457
19073
  O2.step(`Installing gh via ${installCmd.describe}\u2026`);
18458
19074
  resetStdinForChild();
18459
- const ok = await new Promise((resolve5) => {
19075
+ const ok = await new Promise((resolve6) => {
18460
19076
  const proc = (0, import_child_process16.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
18461
- proc.on("exit", (code) => resolve5(code === 0));
18462
- proc.on("error", () => resolve5(false));
19077
+ proc.on("exit", (code) => resolve6(code === 0));
19078
+ proc.on("error", () => resolve6(false));
18463
19079
  });
18464
19080
  if (ok) O2.success("gh installed");
18465
19081
  else O2.error("gh install failed");
@@ -18483,14 +19099,14 @@ var GitHubCodespacesProvider = class {
18483
19099
  "Expanding GitHub scopes"
18484
19100
  );
18485
19101
  resetStdinForChild();
18486
- await new Promise((resolve5, reject) => {
19102
+ await new Promise((resolve6, reject) => {
18487
19103
  const proc = (0, import_child_process16.spawn)(
18488
19104
  "gh",
18489
19105
  ["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
18490
19106
  { stdio: "inherit" }
18491
19107
  );
18492
19108
  proc.on("exit", (code) => {
18493
- if (code === 0) resolve5();
19109
+ if (code === 0) resolve6();
18494
19110
  else reject(new Error(
18495
19111
  "gh auth refresh failed. Re-run `gh auth refresh -h github.com -s repo,read:org` manually."
18496
19112
  ));
@@ -18661,13 +19277,13 @@ var GitHubCodespacesProvider = class {
18661
19277
  }
18662
19278
  async streamCommand(workspaceId, command2) {
18663
19279
  resetStdinForChild();
18664
- return new Promise((resolve5, reject) => {
19280
+ return new Promise((resolve6, reject) => {
18665
19281
  const proc = (0, import_child_process16.spawn)(
18666
19282
  "gh",
18667
19283
  ["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
18668
19284
  { stdio: "inherit" }
18669
19285
  );
18670
- proc.on("exit", (code) => resolve5({ code: code ?? 0 }));
19286
+ proc.on("exit", (code) => resolve6({ code: code ?? 0 }));
18671
19287
  proc.on("error", reject);
18672
19288
  });
18673
19289
  }
@@ -18688,7 +19304,7 @@ var GitHubCodespacesProvider = class {
18688
19304
  "--",
18689
19305
  `mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
18690
19306
  ];
18691
- await new Promise((resolve5, reject) => {
19307
+ await new Promise((resolve6, reject) => {
18692
19308
  const tar = (0, import_child_process16.spawn)("tar", tarArgs, {
18693
19309
  stdio: ["ignore", "pipe", "pipe"],
18694
19310
  env: tarEnv
@@ -18708,7 +19324,7 @@ var GitHubCodespacesProvider = class {
18708
19324
  ssh.on("error", reject);
18709
19325
  ssh.on("exit", (code) => {
18710
19326
  if (code === 0) {
18711
- resolve5();
19327
+ resolve6();
18712
19328
  } else {
18713
19329
  const reason = (sshErr || tarErr || `exit ${code}`).trim().slice(0, 500);
18714
19330
  reject(new Error(`Remote tar failed: ${reason}`));
@@ -18717,7 +19333,7 @@ var GitHubCodespacesProvider = class {
18717
19333
  });
18718
19334
  }
18719
19335
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
18720
- const remoteDir = path37.posix.dirname(remotePath);
19336
+ const remoteDir = path38.posix.dirname(remotePath);
18721
19337
  const parts = [
18722
19338
  `mkdir -p ${shellQuote(remoteDir)}`,
18723
19339
  `cat > ${shellQuote(remotePath)}`
@@ -18726,7 +19342,7 @@ var GitHubCodespacesProvider = class {
18726
19342
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote(remotePath)}`);
18727
19343
  }
18728
19344
  const cmd = parts.join(" && ");
18729
- await new Promise((resolve5, reject) => {
19345
+ await new Promise((resolve6, reject) => {
18730
19346
  const proc = (0, import_child_process16.spawn)(
18731
19347
  "gh",
18732
19348
  ["codespace", "ssh", "-c", workspaceId, "--", cmd],
@@ -18738,7 +19354,7 @@ var GitHubCodespacesProvider = class {
18738
19354
  });
18739
19355
  proc.on("error", reject);
18740
19356
  proc.on("exit", (code) => {
18741
- if (code === 0) resolve5();
19357
+ if (code === 0) resolve6();
18742
19358
  else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
18743
19359
  });
18744
19360
  proc.stdin?.write(contents);
@@ -18787,7 +19403,7 @@ function shellQuote(s) {
18787
19403
  // src/services/providers/gitpod.ts
18788
19404
  var import_child_process17 = require("child_process");
18789
19405
  var import_util5 = require("util");
18790
- var path38 = __toESM(require("path"));
19406
+ var path39 = __toESM(require("path"));
18791
19407
  var import_picocolors9 = __toESM(require("picocolors"));
18792
19408
  var execFileP6 = (0, import_util5.promisify)(import_child_process17.execFile);
18793
19409
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -18828,10 +19444,10 @@ var GitpodProvider = class {
18828
19444
  "Authenticating Gitpod"
18829
19445
  );
18830
19446
  resetStdinForChild2();
18831
- await new Promise((resolve5, reject) => {
19447
+ await new Promise((resolve6, reject) => {
18832
19448
  const proc = (0, import_child_process17.spawn)("gitpod", ["login"], { stdio: "inherit" });
18833
19449
  proc.on("exit", (code) => {
18834
- if (code === 0) resolve5();
19450
+ if (code === 0) resolve6();
18835
19451
  else reject(new Error("gitpod login failed."));
18836
19452
  });
18837
19453
  proc.on("error", reject);
@@ -18980,13 +19596,13 @@ var GitpodProvider = class {
18980
19596
  }
18981
19597
  async streamCommand(workspaceId, command2) {
18982
19598
  resetStdinForChild2();
18983
- return new Promise((resolve5, reject) => {
19599
+ return new Promise((resolve6, reject) => {
18984
19600
  const proc = (0, import_child_process17.spawn)(
18985
19601
  "gitpod",
18986
19602
  ["workspace", "ssh", workspaceId, "--", "-tt", command2],
18987
19603
  { stdio: "inherit" }
18988
19604
  );
18989
- proc.on("exit", (code) => resolve5({ code: code ?? 0 }));
19605
+ proc.on("exit", (code) => resolve6({ code: code ?? 0 }));
18990
19606
  proc.on("error", reject);
18991
19607
  });
18992
19608
  }
@@ -19000,7 +19616,7 @@ var GitpodProvider = class {
19000
19616
  tarArgs.push(".");
19001
19617
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
19002
19618
  const remoteCmd = `mkdir -p ${shellQuote2(remoteDir)} && tar -xzf - -C ${shellQuote2(remoteDir)}`;
19003
- await new Promise((resolve5, reject) => {
19619
+ await new Promise((resolve6, reject) => {
19004
19620
  const tar = (0, import_child_process17.spawn)("tar", tarArgs, {
19005
19621
  stdio: ["ignore", "pipe", "pipe"],
19006
19622
  env: tarEnv
@@ -19021,13 +19637,13 @@ var GitpodProvider = class {
19021
19637
  tar.on("error", reject);
19022
19638
  ssh.on("error", reject);
19023
19639
  ssh.on("exit", (code) => {
19024
- if (code === 0) resolve5();
19640
+ if (code === 0) resolve6();
19025
19641
  else reject(new Error(`Remote tar failed: ${(sshErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
19026
19642
  });
19027
19643
  });
19028
19644
  }
19029
19645
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
19030
- const remoteDir = path38.posix.dirname(remotePath);
19646
+ const remoteDir = path39.posix.dirname(remotePath);
19031
19647
  const parts = [
19032
19648
  `mkdir -p ${shellQuote2(remoteDir)}`,
19033
19649
  `cat > ${shellQuote2(remotePath)}`
@@ -19036,7 +19652,7 @@ var GitpodProvider = class {
19036
19652
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote2(remotePath)}`);
19037
19653
  }
19038
19654
  const cmd = parts.join(" && ");
19039
- await new Promise((resolve5, reject) => {
19655
+ await new Promise((resolve6, reject) => {
19040
19656
  const proc = (0, import_child_process17.spawn)(
19041
19657
  "gitpod",
19042
19658
  ["workspace", "ssh", workspaceId, "--", cmd],
@@ -19048,7 +19664,7 @@ var GitpodProvider = class {
19048
19664
  });
19049
19665
  proc.on("error", reject);
19050
19666
  proc.on("exit", (code) => {
19051
- if (code === 0) resolve5();
19667
+ if (code === 0) resolve6();
19052
19668
  else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
19053
19669
  });
19054
19670
  proc.stdin?.write(contents);
@@ -19063,7 +19679,7 @@ function shellQuote2(s) {
19063
19679
  // src/services/providers/gitlab-workspaces.ts
19064
19680
  var import_child_process18 = require("child_process");
19065
19681
  var import_util6 = require("util");
19066
- var path39 = __toESM(require("path"));
19682
+ var path40 = __toESM(require("path"));
19067
19683
  var execFileP7 = (0, import_util6.promisify)(import_child_process18.execFile);
19068
19684
  var MAX_BUFFER3 = 8 * 1024 * 1024;
19069
19685
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -19105,14 +19721,14 @@ var GitLabWorkspacesProvider = class {
19105
19721
  "Authenticating GitLab"
19106
19722
  );
19107
19723
  resetStdinForChild3();
19108
- await new Promise((resolve5, reject) => {
19724
+ await new Promise((resolve6, reject) => {
19109
19725
  const proc = (0, import_child_process18.spawn)(
19110
19726
  "glab",
19111
19727
  ["auth", "login", "--scopes", "api,read_user,read_repository"],
19112
19728
  { stdio: "inherit" }
19113
19729
  );
19114
19730
  proc.on("exit", (code) => {
19115
- if (code === 0) resolve5();
19731
+ if (code === 0) resolve6();
19116
19732
  else reject(new Error("glab auth login failed."));
19117
19733
  });
19118
19734
  proc.on("error", reject);
@@ -19277,13 +19893,13 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
19277
19893
  async streamCommand(workspaceId, command2) {
19278
19894
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
19279
19895
  resetStdinForChild3();
19280
- return new Promise((resolve5, reject) => {
19896
+ return new Promise((resolve6, reject) => {
19281
19897
  const proc = (0, import_child_process18.spawn)(
19282
19898
  "ssh",
19283
19899
  ["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
19284
19900
  { stdio: "inherit" }
19285
19901
  );
19286
- proc.on("exit", (code) => resolve5({ code: code ?? 0 }));
19902
+ proc.on("exit", (code) => resolve6({ code: code ?? 0 }));
19287
19903
  proc.on("error", reject);
19288
19904
  });
19289
19905
  }
@@ -19298,7 +19914,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
19298
19914
  tarArgs.push(".");
19299
19915
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
19300
19916
  const remoteCmd = `mkdir -p ${shellQuote3(remoteDir)} && tar -xzf - -C ${shellQuote3(remoteDir)}`;
19301
- await new Promise((resolve5, reject) => {
19917
+ await new Promise((resolve6, reject) => {
19302
19918
  const tar = (0, import_child_process18.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
19303
19919
  const ssh = (0, import_child_process18.spawn)(
19304
19920
  "ssh",
@@ -19316,20 +19932,20 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
19316
19932
  tar.on("error", reject);
19317
19933
  ssh.on("error", reject);
19318
19934
  ssh.on("exit", (code) => {
19319
- if (code === 0) resolve5();
19935
+ if (code === 0) resolve6();
19320
19936
  else reject(new Error(`Remote tar failed: ${(sshErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
19321
19937
  });
19322
19938
  });
19323
19939
  }
19324
19940
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
19325
19941
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
19326
- const remoteDir = path39.posix.dirname(remotePath);
19942
+ const remoteDir = path40.posix.dirname(remotePath);
19327
19943
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
19328
19944
  if (options.mode != null) {
19329
19945
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
19330
19946
  }
19331
19947
  const cmd = parts.join(" && ");
19332
- await new Promise((resolve5, reject) => {
19948
+ await new Promise((resolve6, reject) => {
19333
19949
  const proc = (0, import_child_process18.spawn)(
19334
19950
  "ssh",
19335
19951
  ["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
@@ -19341,7 +19957,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
19341
19957
  });
19342
19958
  proc.on("error", reject);
19343
19959
  proc.on("exit", (code) => {
19344
- if (code === 0) resolve5();
19960
+ if (code === 0) resolve6();
19345
19961
  else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
19346
19962
  });
19347
19963
  proc.stdin?.write(contents);
@@ -19391,7 +20007,7 @@ function shellQuote3(s) {
19391
20007
  // src/services/providers/railway.ts
19392
20008
  var import_child_process19 = require("child_process");
19393
20009
  var import_util7 = require("util");
19394
- var path40 = __toESM(require("path"));
20010
+ var path41 = __toESM(require("path"));
19395
20011
  var execFileP8 = (0, import_util7.promisify)(import_child_process19.execFile);
19396
20012
  var MAX_BUFFER4 = 8 * 1024 * 1024;
19397
20013
  function resetStdinForChild4() {
@@ -19432,10 +20048,10 @@ var RailwayProvider = class {
19432
20048
  "Authenticating Railway"
19433
20049
  );
19434
20050
  resetStdinForChild4();
19435
- await new Promise((resolve5, reject) => {
20051
+ await new Promise((resolve6, reject) => {
19436
20052
  const proc = (0, import_child_process19.spawn)("railway", ["login"], { stdio: "inherit" });
19437
20053
  proc.on("exit", (code) => {
19438
- if (code === 0) resolve5();
20054
+ if (code === 0) resolve6();
19439
20055
  else reject(new Error("railway login failed."));
19440
20056
  });
19441
20057
  proc.on("error", reject);
@@ -19575,13 +20191,13 @@ var RailwayProvider = class {
19575
20191
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
19576
20192
  }
19577
20193
  resetStdinForChild4();
19578
- return new Promise((resolve5, reject) => {
20194
+ return new Promise((resolve6, reject) => {
19579
20195
  const proc = (0, import_child_process19.spawn)(
19580
20196
  "railway",
19581
20197
  ["shell", "--project", projectId, "--service", serviceId, "--command", command2],
19582
20198
  { stdio: "inherit" }
19583
20199
  );
19584
- proc.on("exit", (code) => resolve5({ code: code ?? 0 }));
20200
+ proc.on("exit", (code) => resolve6({ code: code ?? 0 }));
19585
20201
  proc.on("error", reject);
19586
20202
  });
19587
20203
  }
@@ -19599,7 +20215,7 @@ var RailwayProvider = class {
19599
20215
  tarArgs.push(".");
19600
20216
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
19601
20217
  const remoteCmd = `mkdir -p ${shellQuote4(remoteDir)} && tar -xzf - -C ${shellQuote4(remoteDir)}`;
19602
- await new Promise((resolve5, reject) => {
20218
+ await new Promise((resolve6, reject) => {
19603
20219
  const tar = (0, import_child_process19.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
19604
20220
  const sh = (0, import_child_process19.spawn)(
19605
20221
  "railway",
@@ -19617,7 +20233,7 @@ var RailwayProvider = class {
19617
20233
  tar.on("error", reject);
19618
20234
  sh.on("error", reject);
19619
20235
  sh.on("exit", (code) => {
19620
- if (code === 0) resolve5();
20236
+ if (code === 0) resolve6();
19621
20237
  else reject(new Error(`Remote tar failed: ${(shErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
19622
20238
  });
19623
20239
  });
@@ -19627,13 +20243,13 @@ var RailwayProvider = class {
19627
20243
  if (!projectId || !serviceId) {
19628
20244
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
19629
20245
  }
19630
- const remoteDir = path40.posix.dirname(remotePath);
20246
+ const remoteDir = path41.posix.dirname(remotePath);
19631
20247
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
19632
20248
  if (options.mode != null) {
19633
20249
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
19634
20250
  }
19635
20251
  const cmd = parts.join(" && ");
19636
- await new Promise((resolve5, reject) => {
20252
+ await new Promise((resolve6, reject) => {
19637
20253
  const proc = (0, import_child_process19.spawn)(
19638
20254
  "railway",
19639
20255
  ["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
@@ -19645,7 +20261,7 @@ var RailwayProvider = class {
19645
20261
  });
19646
20262
  proc.on("error", reject);
19647
20263
  proc.on("exit", (code) => {
19648
- if (code === 0) resolve5();
20264
+ if (code === 0) resolve6();
19649
20265
  else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
19650
20266
  });
19651
20267
  proc.stdin?.write(contents);
@@ -20169,9 +20785,9 @@ async function stopWorkspaceFromLocal(target) {
20169
20785
  // src/commands/doctor.ts
20170
20786
  var import_node_dns = require("dns");
20171
20787
  var import_node_util4 = require("util");
20172
- var import_node_crypto6 = require("crypto");
20173
- var fs32 = __toESM(require("fs"));
20174
- var path41 = __toESM(require("path"));
20788
+ var import_node_crypto8 = require("crypto");
20789
+ var fs33 = __toESM(require("fs"));
20790
+ var path42 = __toESM(require("path"));
20175
20791
  var import_picocolors12 = __toESM(require("picocolors"));
20176
20792
  var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
20177
20793
  async function checkDns(apiBase) {
@@ -20227,13 +20843,13 @@ async function checkHealth(apiBase) {
20227
20843
  }
20228
20844
  }
20229
20845
  function checkConfigDir() {
20230
- const dir = path41.join(require("os").homedir(), ".codeam");
20846
+ const dir = path42.join(require("os").homedir(), ".codeam");
20231
20847
  try {
20232
- fs32.mkdirSync(dir, { recursive: true, mode: 448 });
20233
- const probe = path41.join(dir, ".doctor-probe");
20234
- fs32.writeFileSync(probe, "ok", { mode: 384 });
20235
- const read = fs32.readFileSync(probe, "utf8");
20236
- fs32.unlinkSync(probe);
20848
+ fs33.mkdirSync(dir, { recursive: true, mode: 448 });
20849
+ const probe = path42.join(dir, ".doctor-probe");
20850
+ fs33.writeFileSync(probe, "ok", { mode: 384 });
20851
+ const read = fs33.readFileSync(probe, "utf8");
20852
+ fs33.unlinkSync(probe);
20237
20853
  if (read !== "ok") throw new Error("write/read round-trip mismatch");
20238
20854
  return {
20239
20855
  id: "config-dir",
@@ -20297,7 +20913,7 @@ function checkNodePty() {
20297
20913
  detail: "not required on this platform"
20298
20914
  };
20299
20915
  }
20300
- const vendoredPath = path41.join(__dirname, "vendor", "node-pty");
20916
+ const vendoredPath = path42.join(__dirname, "vendor", "node-pty");
20301
20917
  for (const target of [vendoredPath, "node-pty"]) {
20302
20918
  try {
20303
20919
  require(target);
@@ -20339,9 +20955,9 @@ function checkChokidar() {
20339
20955
  }
20340
20956
  async function doctor(args2 = []) {
20341
20957
  const json = args2.includes("--json");
20342
- const cliVersion = true ? "2.27.0" : "0.0.0-dev";
20958
+ const cliVersion = true ? "2.27.2" : "0.0.0-dev";
20343
20959
  const apiBase = resolveApiBaseUrl();
20344
- const diagnosticId = (0, import_node_crypto6.randomUUID)();
20960
+ const diagnosticId = (0, import_node_crypto8.randomUUID)();
20345
20961
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
20346
20962
  const [dns, health] = await Promise.all([
20347
20963
  checkDns(apiBase),
@@ -20538,7 +21154,7 @@ async function completion(args2) {
20538
21154
  // src/commands/version.ts
20539
21155
  var import_picocolors13 = __toESM(require("picocolors"));
20540
21156
  function version2() {
20541
- const v = true ? "2.27.0" : "unknown";
21157
+ const v = true ? "2.27.2" : "unknown";
20542
21158
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
20543
21159
  }
20544
21160
 
@@ -20666,9 +21282,9 @@ function tryShowSubcommandHelp(cmd, args2) {
20666
21282
  var _subcommandHelpKeys = Object.keys(HELPS);
20667
21283
 
20668
21284
  // src/lib/updateNotifier.ts
20669
- var fs33 = __toESM(require("fs"));
21285
+ var fs34 = __toESM(require("fs"));
20670
21286
  var os26 = __toESM(require("os"));
20671
- var path42 = __toESM(require("path"));
21287
+ var path43 = __toESM(require("path"));
20672
21288
  var https7 = __toESM(require("https"));
20673
21289
  var import_picocolors16 = __toESM(require("picocolors"));
20674
21290
  var PKG_NAME = "codeam-cli";
@@ -20676,12 +21292,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
20676
21292
  var TTL_MS = 24 * 60 * 60 * 1e3;
20677
21293
  var REQUEST_TIMEOUT_MS = 1500;
20678
21294
  function cachePath() {
20679
- const dir = path42.join(os26.homedir(), ".codeam");
20680
- return path42.join(dir, "update-check.json");
21295
+ const dir = path43.join(os26.homedir(), ".codeam");
21296
+ return path43.join(dir, "update-check.json");
20681
21297
  }
20682
21298
  function readCache() {
20683
21299
  try {
20684
- const raw = fs33.readFileSync(cachePath(), "utf8");
21300
+ const raw = fs34.readFileSync(cachePath(), "utf8");
20685
21301
  const parsed = JSON.parse(raw);
20686
21302
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
20687
21303
  return parsed;
@@ -20692,10 +21308,10 @@ function readCache() {
20692
21308
  function writeCache(cache) {
20693
21309
  try {
20694
21310
  const file = cachePath();
20695
- fs33.mkdirSync(path42.dirname(file), { recursive: true });
21311
+ fs34.mkdirSync(path43.dirname(file), { recursive: true });
20696
21312
  const tmp = `${file}.${process.pid}.tmp`;
20697
- fs33.writeFileSync(tmp, JSON.stringify(cache));
20698
- fs33.renameSync(tmp, file);
21313
+ fs34.writeFileSync(tmp, JSON.stringify(cache));
21314
+ fs34.renameSync(tmp, file);
20699
21315
  } catch {
20700
21316
  }
20701
21317
  }
@@ -20713,40 +21329,40 @@ function compareSemver(a, b) {
20713
21329
  return 0;
20714
21330
  }
20715
21331
  function fetchLatest() {
20716
- return new Promise((resolve5) => {
21332
+ return new Promise((resolve6) => {
20717
21333
  const req = https7.get(
20718
21334
  REGISTRY_URL,
20719
21335
  { headers: { Accept: "application/json" }, timeout: REQUEST_TIMEOUT_MS },
20720
21336
  (res) => {
20721
21337
  if (res.statusCode !== 200) {
20722
21338
  res.resume();
20723
- resolve5(null);
21339
+ resolve6(null);
20724
21340
  return;
20725
21341
  }
20726
21342
  let buf = "";
20727
21343
  res.setEncoding("utf8");
20728
- res.on("data", (chunk) => {
20729
- buf += chunk;
21344
+ res.on("data", (chunk2) => {
21345
+ buf += chunk2;
20730
21346
  });
20731
21347
  res.on("end", () => {
20732
21348
  try {
20733
21349
  const json = JSON.parse(buf);
20734
21350
  if (typeof json.version === "string") {
20735
- resolve5(json.version);
21351
+ resolve6(json.version);
20736
21352
  } else {
20737
- resolve5(null);
21353
+ resolve6(null);
20738
21354
  }
20739
21355
  } catch {
20740
- resolve5(null);
21356
+ resolve6(null);
20741
21357
  }
20742
21358
  });
20743
21359
  }
20744
21360
  );
20745
21361
  req.on("timeout", () => {
20746
21362
  req.destroy();
20747
- resolve5(null);
21363
+ resolve6(null);
20748
21364
  });
20749
- req.on("error", () => resolve5(null));
21365
+ req.on("error", () => resolve6(null));
20750
21366
  });
20751
21367
  }
20752
21368
  function notifyIfStale(currentVersion, latest) {
@@ -20766,7 +21382,7 @@ function checkForUpdates() {
20766
21382
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
20767
21383
  if (process.env.CI) return;
20768
21384
  if (!process.stdout.isTTY) return;
20769
- const current = true ? "2.27.0" : null;
21385
+ const current = true ? "2.27.2" : null;
20770
21386
  if (!current) return;
20771
21387
  const cache = readCache();
20772
21388
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;