codeam-cli 2.32.10 → 2.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/index.js +1386 -559
  3. package/package.json +2 -1
package/dist/index.js CHANGED
@@ -498,7 +498,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
498
498
  // package.json
499
499
  var package_default = {
500
500
  name: "codeam-cli",
501
- version: "2.32.10",
501
+ version: "2.34.0",
502
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.",
503
503
  type: "commonjs",
504
504
  main: "dist/index.js",
@@ -569,6 +569,7 @@ var package_default = {
569
569
  },
570
570
  dependencies: {
571
571
  "@agentclientprotocol/claude-agent-acp": "^0.42.0",
572
+ "@beads/bd": "1.0.5",
572
573
  "@agentclientprotocol/codex-acp": "^0.0.45",
573
574
  "@agentclientprotocol/sdk": "^0.25.0",
574
575
  "@clack/prompts": "^1.2.0",
@@ -707,8 +708,8 @@ async function requestCode(pluginId) {
707
708
  });
708
709
  let timer;
709
710
  const timeoutSentinel = /* @__PURE__ */ Symbol("request-code-timeout");
710
- const timeoutPromise = new Promise((resolve6) => {
711
- timer = setTimeout(() => resolve6(timeoutSentinel), REQUEST_CODE_TIMEOUT_MS);
711
+ const timeoutPromise = new Promise((resolve7) => {
712
+ timer = setTimeout(() => resolve7(timeoutSentinel), REQUEST_CODE_TIMEOUT_MS);
712
713
  });
713
714
  const result = await Promise.race([post2, timeoutPromise]);
714
715
  clearTimeout(timer);
@@ -851,8 +852,30 @@ async function postPreviewEvent(input) {
851
852
  };
852
853
  }
853
854
  }
855
+ async function postBeadsProvisioning(input) {
856
+ try {
857
+ await _transport.postJsonAuthed(
858
+ `${API_BASE}/api/beads/provisioning`,
859
+ {
860
+ sessionId: input.sessionId,
861
+ pluginId: input.pluginId,
862
+ status: input.status,
863
+ ...input.projectKey ? { projectKey: input.projectKey } : {}
864
+ },
865
+ input.pluginAuthToken
866
+ );
867
+ return { ok: true };
868
+ } catch (err) {
869
+ const e = err;
870
+ return {
871
+ ok: false,
872
+ status: typeof e.statusCode === "number" ? e.statusCode : 0,
873
+ message: e.message || "unknown"
874
+ };
875
+ }
876
+ }
854
877
  async function _postJsonAuthed(url, body, pluginAuthToken) {
855
- return new Promise((resolve6, reject) => {
878
+ return new Promise((resolve7, reject) => {
856
879
  const data = JSON.stringify(body);
857
880
  const u2 = new URL(url);
858
881
  const transport = u2.protocol === "https:" ? https : http;
@@ -884,9 +907,9 @@ async function _postJsonAuthed(url, body, pluginAuthToken) {
884
907
  return;
885
908
  }
886
909
  try {
887
- resolve6(JSON.parse(responseBody));
910
+ resolve7(JSON.parse(responseBody));
888
911
  } catch {
889
- resolve6(null);
912
+ resolve7(null);
890
913
  }
891
914
  });
892
915
  }
@@ -911,7 +934,7 @@ function makeHttpError(statusCode, retryAfterHeader, responseBody) {
911
934
  return err;
912
935
  }
913
936
  async function _postJson(url, body) {
914
- return new Promise((resolve6, reject) => {
937
+ return new Promise((resolve7, reject) => {
915
938
  const data = JSON.stringify(body);
916
939
  const u2 = new URL(url);
917
940
  const transport = u2.protocol === "https:" ? https : http;
@@ -940,9 +963,9 @@ async function _postJson(url, body) {
940
963
  return;
941
964
  }
942
965
  try {
943
- resolve6(JSON.parse(body2));
966
+ resolve7(JSON.parse(body2));
944
967
  } catch {
945
- resolve6(null);
968
+ resolve7(null);
946
969
  }
947
970
  });
948
971
  }
@@ -957,7 +980,7 @@ async function _postJson(url, body) {
957
980
  });
958
981
  }
959
982
  async function _getJson(url) {
960
- return new Promise((resolve6, reject) => {
983
+ return new Promise((resolve7, reject) => {
961
984
  const u2 = new URL(url);
962
985
  const transport = u2.protocol === "https:" ? https : http;
963
986
  const req = transport.request(
@@ -981,9 +1004,9 @@ async function _getJson(url) {
981
1004
  return;
982
1005
  }
983
1006
  try {
984
- resolve6(JSON.parse(body));
1007
+ resolve7(JSON.parse(body));
985
1008
  } catch {
986
- resolve6(null);
1009
+ resolve7(null);
987
1010
  }
988
1011
  });
989
1012
  }
@@ -1161,8 +1184,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
1161
1184
  return decodedFile;
1162
1185
  };
1163
1186
  }
1164
- function normalizeWindowsPath(path46) {
1165
- return path46.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1187
+ function normalizeWindowsPath(path50) {
1188
+ return path50.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1166
1189
  }
1167
1190
 
1168
1191
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -3642,15 +3665,15 @@ async function addSourceContext(frames) {
3642
3665
  LRU_FILE_CONTENTS_CACHE.reduce();
3643
3666
  return frames;
3644
3667
  }
3645
- function getContextLinesFromFile(path46, ranges, output) {
3646
- return new Promise((resolve6) => {
3647
- const stream = (0, import_node_fs.createReadStream)(path46);
3668
+ function getContextLinesFromFile(path50, ranges, output) {
3669
+ return new Promise((resolve7) => {
3670
+ const stream = (0, import_node_fs.createReadStream)(path50);
3648
3671
  const lineReaded = (0, import_node_readline.createInterface)({
3649
3672
  input: stream
3650
3673
  });
3651
3674
  function destroyStreamAndResolve() {
3652
3675
  stream.destroy();
3653
- resolve6();
3676
+ resolve7();
3654
3677
  }
3655
3678
  let lineNumber = 0;
3656
3679
  let currentRangeIndex = 0;
@@ -3659,7 +3682,7 @@ function getContextLinesFromFile(path46, ranges, output) {
3659
3682
  let rangeStart = range[0];
3660
3683
  let rangeEnd = range[1];
3661
3684
  function onStreamError() {
3662
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path46, 1);
3685
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path50, 1);
3663
3686
  lineReaded.close();
3664
3687
  lineReaded.removeAllListeners();
3665
3688
  destroyStreamAndResolve();
@@ -3720,8 +3743,8 @@ function clearLineContext(frame) {
3720
3743
  delete frame.context_line;
3721
3744
  delete frame.post_context;
3722
3745
  }
3723
- function shouldSkipContextLinesForFile(path46) {
3724
- return path46.startsWith("node:") || path46.endsWith(".min.js") || path46.endsWith(".min.cjs") || path46.endsWith(".min.mjs") || path46.startsWith("data:");
3746
+ function shouldSkipContextLinesForFile(path50) {
3747
+ return path50.startsWith("node:") || path50.endsWith(".min.js") || path50.endsWith(".min.cjs") || path50.endsWith(".min.mjs") || path50.startsWith("data:");
3725
3748
  }
3726
3749
  function shouldSkipContextLinesForFrame(frame) {
3727
3750
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -4937,9 +4960,9 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
4937
4960
  if (!waitUntil) return;
4938
4961
  if (this.disabled || this.optedOut) return;
4939
4962
  if (!this._waitUntilCycle) {
4940
- let resolve6;
4963
+ let resolve7;
4941
4964
  const promise = new Promise((r) => {
4942
- resolve6 = r;
4965
+ resolve7 = r;
4943
4966
  });
4944
4967
  try {
4945
4968
  waitUntil(promise);
@@ -4947,7 +4970,7 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
4947
4970
  return;
4948
4971
  }
4949
4972
  this._waitUntilCycle = {
4950
- resolve: resolve6,
4973
+ resolve: resolve7,
4951
4974
  startedAt: Date.now(),
4952
4975
  timer: void 0
4953
4976
  };
@@ -4971,12 +4994,12 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
4971
4994
  return cycle?.resolve;
4972
4995
  }
4973
4996
  async resolveWaitUntilFlush() {
4974
- const resolve6 = this._consumeWaitUntilCycle();
4997
+ const resolve7 = this._consumeWaitUntilCycle();
4975
4998
  try {
4976
4999
  await super.flush();
4977
5000
  } catch {
4978
5001
  } finally {
4979
- resolve6?.();
5002
+ resolve7?.();
4980
5003
  }
4981
5004
  }
4982
5005
  getPersistedProperty(key) {
@@ -5068,15 +5091,15 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
5068
5091
  async waitForLocalEvaluationReady(timeoutMs = THIRTY_SECONDS) {
5069
5092
  if (this.isLocalEvaluationReady()) return true;
5070
5093
  if (void 0 === this.featureFlagsPoller) return false;
5071
- return new Promise((resolve6) => {
5094
+ return new Promise((resolve7) => {
5072
5095
  const timeout = setTimeout(() => {
5073
5096
  cleanup();
5074
- resolve6(false);
5097
+ resolve7(false);
5075
5098
  }, timeoutMs);
5076
5099
  const cleanup = this._events.on("localEvaluationFlagsLoaded", (count) => {
5077
5100
  clearTimeout(timeout);
5078
5101
  cleanup();
5079
- resolve6(count > 0);
5102
+ resolve7(count > 0);
5080
5103
  });
5081
5104
  });
5082
5105
  }
@@ -5513,13 +5536,13 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
5513
5536
  this.context?.enter(data, options);
5514
5537
  }
5515
5538
  async _shutdown(shutdownTimeoutMs) {
5516
- const resolve6 = this._consumeWaitUntilCycle();
5539
+ const resolve7 = this._consumeWaitUntilCycle();
5517
5540
  await this.featureFlagsPoller?.stopPoller(shutdownTimeoutMs);
5518
5541
  this.errorTracking.shutdown();
5519
5542
  try {
5520
5543
  return await super._shutdown(shutdownTimeoutMs);
5521
5544
  } finally {
5522
- resolve6?.();
5545
+ resolve7?.();
5523
5546
  }
5524
5547
  }
5525
5548
  async _requestRemoteConfigPayload(flagKey) {
@@ -5875,7 +5898,7 @@ function readAnonId() {
5875
5898
  }
5876
5899
  function superProperties() {
5877
5900
  return {
5878
- cliVersion: true ? "2.32.10" : "0.0.0-dev",
5901
+ cliVersion: true ? "2.34.0" : "0.0.0-dev",
5879
5902
  nodeVersion: process.version,
5880
5903
  platform: process.platform,
5881
5904
  arch: process.arch,
@@ -7217,10 +7240,10 @@ function buildForPlatform(platform2) {
7217
7240
  var import_node_crypto4 = require("crypto");
7218
7241
 
7219
7242
  // src/agents/claude/resolver.ts
7220
- function buildClaudeLaunch(extraArgs = [], os29 = createOsStrategy()) {
7221
- const found = os29.findInPath("claude") ?? os29.findInPath("claude-code");
7243
+ function buildClaudeLaunch(extraArgs = [], os30 = createOsStrategy()) {
7244
+ const found = os30.findInPath("claude") ?? os30.findInPath("claude-code");
7222
7245
  if (!found) return null;
7223
- return os29.buildLaunch(found, extraArgs);
7246
+ return os30.buildLaunch(found, extraArgs);
7224
7247
  }
7225
7248
 
7226
7249
  // src/agents/claude/installer.ts
@@ -9176,15 +9199,15 @@ function runInstaller() {
9176
9199
  "-Command",
9177
9200
  "irm https://claude.ai/install.ps1 | iex"
9178
9201
  ] : ["-c", "curl -fsSL https://claude.ai/install.sh | bash"];
9179
- return new Promise((resolve6) => {
9202
+ return new Promise((resolve7) => {
9180
9203
  const proc = (0, import_child_process4.spawn)(cmd, args2, { stdio: "inherit" });
9181
9204
  proc.on("error", (err) => {
9182
9205
  console.error(`
9183
9206
  \u2717 Installer failed to launch: ${err.message}`);
9184
- resolve6(false);
9207
+ resolve7(false);
9185
9208
  });
9186
9209
  proc.on("exit", (code) => {
9187
- resolve6(code === 0);
9210
+ resolve7(code === 0);
9188
9211
  });
9189
9212
  });
9190
9213
  }
@@ -9361,17 +9384,17 @@ function parseUsageOutput(raw) {
9361
9384
  return { percent, resetAt };
9362
9385
  }
9363
9386
  async function fetchClaudeQuota() {
9364
- return new Promise((resolve6) => {
9387
+ return new Promise((resolve7) => {
9365
9388
  const claudeCmd = findInPath("claude") ? "claude" : "claude-code";
9366
9389
  if (!claudeCmd) {
9367
- resolve6(null);
9390
+ resolve7(null);
9368
9391
  return;
9369
9392
  }
9370
9393
  const helperPath = path11.join(os10.tmpdir(), "codeam-quota-helper.py");
9371
9394
  fs8.writeFileSync(helperPath, HELPER_SCRIPT, { mode: 420 });
9372
9395
  const python = findInPath("python3") ?? findInPath("python");
9373
9396
  if (!python) {
9374
- resolve6(null);
9397
+ resolve7(null);
9375
9398
  return;
9376
9399
  }
9377
9400
  const proc = (0, import_child_process5.spawn)(python, [helperPath, claudeCmd, "--tools", ""], {
@@ -9398,13 +9421,13 @@ async function fetchClaudeQuota() {
9398
9421
  fs8.unlinkSync(helperPath);
9399
9422
  } catch {
9400
9423
  }
9401
- resolve6(result);
9424
+ resolve7(result);
9402
9425
  }, 5e3);
9403
9426
  }, 8e3);
9404
9427
  setTimeout(() => {
9405
9428
  if (!resolved) {
9406
9429
  resolved = true;
9407
- resolve6(null);
9430
+ resolve7(null);
9408
9431
  }
9409
9432
  try {
9410
9433
  proc.kill();
@@ -9435,12 +9458,12 @@ function killActiveSpawnAndCaptureChildren() {
9435
9458
  }
9436
9459
  async function spawnAndCapture(cmd, args2, opts = {}) {
9437
9460
  const timeoutMs = opts.timeoutMs ?? 6e4;
9438
- return new Promise((resolve6) => {
9461
+ return new Promise((resolve7) => {
9439
9462
  let settled = false;
9440
9463
  const settle = (value) => {
9441
9464
  if (settled) return;
9442
9465
  settled = true;
9443
- resolve6(value);
9466
+ resolve7(value);
9444
9467
  };
9445
9468
  let child;
9446
9469
  try {
@@ -9947,13 +9970,13 @@ function detectStartupBanner(lines) {
9947
9970
  while (artStart > 0 && BANNER_ART_RE.test(lines[artStart - 1])) artStart--;
9948
9971
  if (metaIdx - artStart < 2) return null;
9949
9972
  const pathLine = (lines[metaIdx + 1] ?? "").trim();
9950
- const path46 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9973
+ const path50 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9951
9974
  return {
9952
9975
  title: "",
9953
9976
  subtitle: lines[metaIdx].trim(),
9954
- path: path46,
9977
+ path: path50,
9955
9978
  startIdx: artStart,
9956
- endIdx: metaIdx + (path46 ? 1 : 0)
9979
+ endIdx: metaIdx + (path50 ? 1 : 0)
9957
9980
  };
9958
9981
  }
9959
9982
 
@@ -9963,8 +9986,8 @@ var ClaudeRuntimeStrategy = class {
9963
9986
  meta = getAgent("claude");
9964
9987
  mode = "interactive";
9965
9988
  os;
9966
- constructor(os29) {
9967
- this.os = os29;
9989
+ constructor(os30) {
9990
+ this.os = os30;
9968
9991
  }
9969
9992
  /**
9970
9993
  * Claude Code's react-ink TUI enables bracketed-paste mode at
@@ -10972,8 +10995,8 @@ function codexCredentialLocator() {
10972
10995
  function codexLoginLauncher() {
10973
10996
  return {
10974
10997
  async ensureInstalled() {
10975
- const os29 = createOsStrategy();
10976
- return os29.findInPath("codex") !== null;
10998
+ const os30 = createOsStrategy();
10999
+ return os30.findInPath("codex") !== null;
10977
11000
  },
10978
11001
  launch() {
10979
11002
  return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
@@ -10996,8 +11019,8 @@ var CodexRuntimeStrategy = class {
10996
11019
  meta = getAgent("codex");
10997
11020
  mode = "interactive";
10998
11021
  os;
10999
- constructor(os29) {
11000
- this.os = os29;
11022
+ constructor(os30) {
11023
+ this.os = os30;
11001
11024
  }
11002
11025
  async prepareLaunch() {
11003
11026
  let binary = this.os.findInPath("codex");
@@ -11103,16 +11126,16 @@ var CodexRuntimeStrategy = class {
11103
11126
  });
11104
11127
  }
11105
11128
  };
11106
- function resolveNpm(os29) {
11107
- return os29.id === "win32" ? "npm.cmd" : "npm";
11129
+ function resolveNpm(os30) {
11130
+ return os30.id === "win32" ? "npm.cmd" : "npm";
11108
11131
  }
11109
- async function installCodexViaNpm(os29) {
11110
- return new Promise((resolve6, reject) => {
11111
- const proc = (0, import_node_child_process4.spawn)(resolveNpm(os29), ["install", "-g", "@openai/codex"], {
11132
+ async function installCodexViaNpm(os30) {
11133
+ return new Promise((resolve7, reject) => {
11134
+ const proc = (0, import_node_child_process4.spawn)(resolveNpm(os30), ["install", "-g", "@openai/codex"], {
11112
11135
  stdio: "inherit"
11113
11136
  });
11114
11137
  proc.on("close", (code) => {
11115
- if (code === 0) resolve6();
11138
+ if (code === 0) resolve7();
11116
11139
  else reject(new Error(`npm install -g @openai/codex exited ${code}`));
11117
11140
  });
11118
11141
  proc.on("error", (err) => {
@@ -11125,16 +11148,16 @@ async function installCodexViaNpm(os29) {
11125
11148
  });
11126
11149
  });
11127
11150
  }
11128
- function augmentNpmGlobalBin(os29) {
11151
+ function augmentNpmGlobalBin(os30) {
11129
11152
  try {
11130
- const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os29), ["prefix", "-g"], {
11153
+ const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os30), ["prefix", "-g"], {
11131
11154
  stdio: ["ignore", "pipe", "ignore"]
11132
11155
  });
11133
11156
  if (result.status !== 0) return;
11134
11157
  const prefix = result.stdout.toString().trim();
11135
11158
  if (!prefix) return;
11136
- const binDir = os29.id === "win32" ? prefix : path17.join(prefix, "bin");
11137
- os29.augmentPath([binDir]);
11159
+ const binDir = os30.id === "win32" ? prefix : path17.join(prefix, "bin");
11160
+ os30.augmentPath([binDir]);
11138
11161
  } catch {
11139
11162
  }
11140
11163
  }
@@ -11218,25 +11241,25 @@ var import_node_child_process7 = require("child_process");
11218
11241
  // src/agents/coderabbit/installer.ts
11219
11242
  var import_node_child_process5 = require("child_process");
11220
11243
  var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
11221
- async function ensureCoderabbitInstalled(os29) {
11222
- if (os29.findInPath("coderabbit")) return true;
11223
- if (os29.id === "win32") {
11244
+ async function ensureCoderabbitInstalled(os30) {
11245
+ if (os30.findInPath("coderabbit")) return true;
11246
+ if (os30.id === "win32") {
11224
11247
  console.error(
11225
11248
  "\n \u2717 CodeRabbit on Windows requires WSL.\n Install the CLI inside your WSL distribution\n (curl -fsSL https://cli.coderabbit.ai/install.sh | sh)\n then re-run `codeam link coderabbit` from WSL.\n"
11226
11249
  );
11227
11250
  return false;
11228
11251
  }
11229
11252
  console.log("\n CodeRabbit CLI not found \u2014 installing via the official script\u2026\n");
11230
- const ok = await new Promise((resolve6) => {
11253
+ const ok = await new Promise((resolve7) => {
11231
11254
  const proc = (0, import_node_child_process5.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL} | sh`], {
11232
11255
  stdio: "inherit"
11233
11256
  });
11234
- proc.on("close", (code) => resolve6(code === 0));
11235
- proc.on("error", () => resolve6(false));
11257
+ proc.on("close", (code) => resolve7(code === 0));
11258
+ proc.on("error", () => resolve7(false));
11236
11259
  });
11237
11260
  if (!ok) return false;
11238
- os29.augmentPath([`${os29.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
11239
- return os29.findInPath("coderabbit") !== null;
11261
+ os30.augmentPath([`${os30.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
11262
+ return os30.findInPath("coderabbit") !== null;
11240
11263
  }
11241
11264
 
11242
11265
  // src/agents/coderabbit/link.ts
@@ -11263,10 +11286,10 @@ function coderabbitCredentialLocator() {
11263
11286
  extract: extractLocalCoderabbitToken
11264
11287
  };
11265
11288
  }
11266
- function coderabbitLoginLauncher(os29) {
11289
+ function coderabbitLoginLauncher(os30) {
11267
11290
  return {
11268
11291
  async ensureInstalled() {
11269
- return ensureCoderabbitInstalled(os29);
11292
+ return ensureCoderabbitInstalled(os30);
11270
11293
  },
11271
11294
  launch() {
11272
11295
  return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
@@ -11289,11 +11312,11 @@ function parseReview(stdout) {
11289
11312
  for (const line of lines) {
11290
11313
  const m = line.match(HUNK_LINE_RE);
11291
11314
  if (!m) continue;
11292
- const [, path46, lineNo, sevToken, message] = m;
11293
- if (!path46 || !lineNo || !message) continue;
11315
+ const [, path50, lineNo, sevToken, message] = m;
11316
+ if (!path50 || !lineNo || !message) continue;
11294
11317
  const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
11295
11318
  hunks.push({
11296
- path: path46.trim(),
11319
+ path: path50.trim(),
11297
11320
  line: Number(lineNo),
11298
11321
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
11299
11322
  message: cleanedMessage
@@ -11312,8 +11335,8 @@ var CoderabbitRuntimeStrategy = class {
11312
11335
  meta = getAgent("coderabbit");
11313
11336
  mode = "batch";
11314
11337
  os;
11315
- constructor(os29) {
11316
- this.os = os29;
11338
+ constructor(os30) {
11339
+ this.os = os30;
11317
11340
  }
11318
11341
  getDefaultArgs() {
11319
11342
  return ["review"];
@@ -11351,7 +11374,7 @@ var CoderabbitRuntimeStrategy = class {
11351
11374
  }
11352
11375
  async runOneShot(input) {
11353
11376
  const launch = await this.prepareInvocation(input);
11354
- return new Promise((resolve6, reject) => {
11377
+ return new Promise((resolve7, reject) => {
11355
11378
  const stdoutBuf = [];
11356
11379
  const stderrBuf = [];
11357
11380
  const proc = (0, import_node_child_process7.spawn)(launch.cmd, launch.args, {
@@ -11362,7 +11385,7 @@ var CoderabbitRuntimeStrategy = class {
11362
11385
  proc.stderr?.on("data", (b) => stderrBuf.push(b));
11363
11386
  proc.on("error", (err) => reject(err));
11364
11387
  proc.on("close", (code) => {
11365
- resolve6(
11388
+ resolve7(
11366
11389
  this.parseOutput({
11367
11390
  exitCode: code ?? 0,
11368
11391
  stdout: Buffer.concat(stdoutBuf).toString("utf8"),
@@ -11428,10 +11451,10 @@ function cursorCredentialLocator() {
11428
11451
  extract: extractLocalCursorToken
11429
11452
  };
11430
11453
  }
11431
- function cursorLoginLauncher(os29) {
11454
+ function cursorLoginLauncher(os30) {
11432
11455
  return {
11433
11456
  async ensureInstalled() {
11434
- if (os29.findInPath("cursor-agent")) return true;
11457
+ if (os30.findInPath("cursor-agent")) return true;
11435
11458
  console.error(
11436
11459
  "\n \u2717 cursor-agent binary not on PATH.\n Install Cursor (https://cursor.com/) and ensure the CLI\n plugin is enabled, then re-run `codeam link cursor`.\n"
11437
11460
  );
@@ -11493,8 +11516,8 @@ var CursorRuntimeStrategy = class {
11493
11516
  meta = getAgent("cursor");
11494
11517
  mode = "interactive";
11495
11518
  os;
11496
- constructor(os29) {
11497
- this.os = os29;
11519
+ constructor(os30) {
11520
+ this.os = os30;
11498
11521
  }
11499
11522
  async prepareLaunch() {
11500
11523
  const binary = this.os.findInPath("cursor-agent");
@@ -11614,10 +11637,10 @@ function aiderCredentialLocator() {
11614
11637
  extract: extractLocalAiderToken
11615
11638
  };
11616
11639
  }
11617
- function aiderLoginLauncher(os29) {
11640
+ function aiderLoginLauncher(os30) {
11618
11641
  return {
11619
11642
  async ensureInstalled() {
11620
- if (os29.findInPath("aider")) return true;
11643
+ if (os30.findInPath("aider")) return true;
11621
11644
  console.error(
11622
11645
  "\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
11623
11646
  );
@@ -11627,7 +11650,7 @@ function aiderLoginLauncher(os29) {
11627
11650
  console.error(
11628
11651
  "\n Aider has no interactive login flow.\n Set ANTHROPIC_API_KEY or OPENAI_API_KEY in your shell,\n or re-run `codeam link aider --api-key=<your-key>`.\n"
11629
11652
  );
11630
- return (0, import_node_child_process9.spawn)(os29.id === "win32" ? "cmd.exe" : "sh", os29.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
11653
+ return (0, import_node_child_process9.spawn)(os30.id === "win32" ? "cmd.exe" : "sh", os30.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
11631
11654
  stdio: "ignore"
11632
11655
  });
11633
11656
  }
@@ -11699,8 +11722,8 @@ var AiderRuntimeStrategy = class {
11699
11722
  meta = getAgent("aider");
11700
11723
  mode = "interactive";
11701
11724
  os;
11702
- constructor(os29) {
11703
- this.os = os29;
11725
+ constructor(os30) {
11726
+ this.os = os30;
11704
11727
  }
11705
11728
  async prepareLaunch() {
11706
11729
  const binary = this.os.findInPath("aider");
@@ -11829,8 +11852,8 @@ function geminiCredentialLocator() {
11829
11852
  function geminiLoginLauncher() {
11830
11853
  return {
11831
11854
  async ensureInstalled() {
11832
- const os29 = createOsStrategy();
11833
- return os29.findInPath("gemini") !== null;
11855
+ const os30 = createOsStrategy();
11856
+ return os30.findInPath("gemini") !== null;
11834
11857
  },
11835
11858
  launch() {
11836
11859
  return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
@@ -11863,8 +11886,8 @@ var GeminiRuntimeStrategy = class {
11863
11886
  meta = getAgent("gemini");
11864
11887
  mode = "interactive";
11865
11888
  os;
11866
- constructor(os29) {
11867
- this.os = os29;
11889
+ constructor(os30) {
11890
+ this.os = os30;
11868
11891
  }
11869
11892
  async prepareLaunch() {
11870
11893
  const binary = this.os.findInPath("gemini");
@@ -11964,18 +11987,18 @@ var GeminiRuntimeStrategy = class {
11964
11987
 
11965
11988
  // src/agents/registry.ts
11966
11989
  var runtimeBuilders = {
11967
- claude: (os29) => new ClaudeRuntimeStrategy(os29),
11968
- codex: (os29) => new CodexRuntimeStrategy(os29),
11969
- coderabbit: (os29) => new CoderabbitRuntimeStrategy(os29),
11970
- cursor: (os29) => new CursorRuntimeStrategy(os29),
11971
- aider: (os29) => new AiderRuntimeStrategy(os29),
11972
- gemini: (os29) => new GeminiRuntimeStrategy(os29)
11990
+ claude: (os30) => new ClaudeRuntimeStrategy(os30),
11991
+ codex: (os30) => new CodexRuntimeStrategy(os30),
11992
+ coderabbit: (os30) => new CoderabbitRuntimeStrategy(os30),
11993
+ cursor: (os30) => new CursorRuntimeStrategy(os30),
11994
+ aider: (os30) => new AiderRuntimeStrategy(os30),
11995
+ gemini: (os30) => new GeminiRuntimeStrategy(os30)
11973
11996
  };
11974
11997
  var deployBuilders = {
11975
11998
  claude: () => new ClaudeDeployStrategy(),
11976
11999
  codex: () => new CodexDeployStrategy()
11977
12000
  };
11978
- function createAgentStrategy(agent, os29 = createOsStrategy()) {
12001
+ function createAgentStrategy(agent, os30 = createOsStrategy()) {
11979
12002
  if (!AGENT_REGISTRY[agent]?.enabled) {
11980
12003
  throw new Error(
11981
12004
  `Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
@@ -11985,10 +12008,10 @@ function createAgentStrategy(agent, os29 = createOsStrategy()) {
11985
12008
  if (!build) {
11986
12009
  throw new Error(`No runtime strategy registered for agent "${agent}"`);
11987
12010
  }
11988
- return build(os29);
12011
+ return build(os30);
11989
12012
  }
11990
- function createInteractiveAgentStrategy(agent, os29 = createOsStrategy()) {
11991
- const s = createAgentStrategy(agent, os29);
12013
+ function createInteractiveAgentStrategy(agent, os30 = createOsStrategy()) {
12014
+ const s = createAgentStrategy(agent, os30);
11992
12015
  if (s.mode !== "interactive") {
11993
12016
  throw new Error(
11994
12017
  `Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
@@ -14268,8 +14291,8 @@ var Connection = class {
14268
14291
  this.requestHandler = requestHandler;
14269
14292
  this.notificationHandler = notificationHandler;
14270
14293
  this.stream = stream;
14271
- this.closedPromise = new Promise((resolve6) => {
14272
- this.abortController.signal.addEventListener("abort", () => resolve6());
14294
+ this.closedPromise = new Promise((resolve7) => {
14295
+ this.abortController.signal.addEventListener("abort", () => resolve7());
14273
14296
  });
14274
14297
  void this.receive();
14275
14298
  }
@@ -14439,11 +14462,11 @@ var Connection = class {
14439
14462
  return rejectedPromise(this.closedReason());
14440
14463
  }
14441
14464
  const id = this.nextRequestId++;
14442
- const responsePromise = new Promise((resolve6, reject) => {
14465
+ const responsePromise = new Promise((resolve7, reject) => {
14443
14466
  this.pendingResponses.set(id, {
14444
14467
  resolve: (response) => {
14445
14468
  try {
14446
- resolve6(mapResponse ? mapResponse(response) : response);
14469
+ resolve7(mapResponse ? mapResponse(response) : response);
14447
14470
  } catch (error) {
14448
14471
  reject(error);
14449
14472
  }
@@ -14764,17 +14787,17 @@ var AcpClient = class {
14764
14787
  this.sessionId = null;
14765
14788
  try {
14766
14789
  child.kill("SIGTERM");
14767
- const grace = new Promise((resolve6) => {
14790
+ const grace = new Promise((resolve7) => {
14768
14791
  const t2 = setTimeout(() => {
14769
14792
  try {
14770
14793
  child.kill("SIGKILL");
14771
14794
  } catch {
14772
14795
  }
14773
- resolve6();
14796
+ resolve7();
14774
14797
  }, 2e3);
14775
14798
  child.once("exit", () => {
14776
14799
  clearTimeout(t2);
14777
- resolve6();
14800
+ resolve7();
14778
14801
  });
14779
14802
  });
14780
14803
  await grace;
@@ -14912,7 +14935,7 @@ var _transport2 = {
14912
14935
  get: _get
14913
14936
  };
14914
14937
  function _post(url, headers, payload) {
14915
- return new Promise((resolve6, reject) => {
14938
+ return new Promise((resolve7, reject) => {
14916
14939
  let settled = false;
14917
14940
  const u2 = new URL(url);
14918
14941
  const lib = u2.protocol === "https:" ? https3 : http3;
@@ -14937,7 +14960,7 @@ function _post(url, headers, payload) {
14937
14960
  res.on("end", () => {
14938
14961
  if (settled) return;
14939
14962
  settled = true;
14940
- resolve6({ statusCode: res.statusCode ?? 0, body });
14963
+ resolve7({ statusCode: res.statusCode ?? 0, body });
14941
14964
  });
14942
14965
  }
14943
14966
  );
@@ -14954,7 +14977,7 @@ function _post(url, headers, payload) {
14954
14977
  });
14955
14978
  }
14956
14979
  function _get(url, headers) {
14957
- return new Promise((resolve6, reject) => {
14980
+ return new Promise((resolve7, reject) => {
14958
14981
  let settled = false;
14959
14982
  const u2 = new URL(url);
14960
14983
  const lib = u2.protocol === "https:" ? https3 : http3;
@@ -14978,7 +15001,7 @@ function _get(url, headers) {
14978
15001
  res.on("end", () => {
14979
15002
  if (settled) return;
14980
15003
  settled = true;
14981
- resolve6({ statusCode: res.statusCode ?? 0, body });
15004
+ resolve7({ statusCode: res.statusCode ?? 0, body });
14982
15005
  });
14983
15006
  }
14984
15007
  );
@@ -15687,11 +15710,11 @@ function extractSelectPrompt(text) {
15687
15710
  }
15688
15711
 
15689
15712
  // src/commands/start/handlers.ts
15690
- var fs29 = __toESM(require("fs"));
15691
- var os24 = __toESM(require("os"));
15692
- var path35 = __toESM(require("path"));
15713
+ var fs32 = __toESM(require("fs"));
15714
+ var os25 = __toESM(require("os"));
15715
+ var path39 = __toESM(require("path"));
15693
15716
  var import_crypto3 = require("crypto");
15694
- var import_child_process12 = require("child_process");
15717
+ var import_child_process15 = require("child_process");
15695
15718
 
15696
15719
  // src/lib/payload.ts
15697
15720
  var import_zod = require("zod");
@@ -16344,12 +16367,12 @@ async function applyFileReview(workingDir, filePath, action) {
16344
16367
  return { ok: true, action, filePath, repoRoot };
16345
16368
  }
16346
16369
  function runGit(cwd, args2) {
16347
- return new Promise((resolve6) => {
16370
+ return new Promise((resolve7) => {
16348
16371
  let proc;
16349
16372
  try {
16350
16373
  proc = (0, import_child_process10.spawn)("git", args2, { cwd, env: process.env });
16351
16374
  } catch (err) {
16352
- resolve6({ ok: false, code: -1, stdout: "", stderr: err.message });
16375
+ resolve7({ ok: false, code: -1, stdout: "", stderr: err.message });
16353
16376
  return;
16354
16377
  }
16355
16378
  let stdout = "";
@@ -16362,11 +16385,11 @@ function runGit(cwd, args2) {
16362
16385
  });
16363
16386
  proc.on(
16364
16387
  "error",
16365
- (err) => resolve6({ ok: false, code: -1, stdout, stderr: stderr + err.message })
16388
+ (err) => resolve7({ ok: false, code: -1, stdout, stderr: stderr + err.message })
16366
16389
  );
16367
16390
  proc.on(
16368
16391
  "close",
16369
- (code) => resolve6({ ok: code === 0, code: code ?? -1, stdout, stderr })
16392
+ (code) => resolve7({ ok: code === 0, code: code ?? -1, stdout, stderr })
16370
16393
  );
16371
16394
  });
16372
16395
  }
@@ -16625,7 +16648,7 @@ async function link(args2 = []) {
16625
16648
  waitSpin.start(waitMsg());
16626
16649
  const countdown = setInterval(() => waitSpin.message(waitMsg()), 1e3);
16627
16650
  countdown.unref?.();
16628
- const paired = await new Promise((resolve6, reject) => {
16651
+ const paired = await new Promise((resolve7, reject) => {
16629
16652
  let stopPoll = null;
16630
16653
  const sigint = () => {
16631
16654
  clearInterval(countdown);
@@ -16638,7 +16661,7 @@ async function link(args2 = []) {
16638
16661
  process.removeListener("SIGINT", sigint);
16639
16662
  clearInterval(countdown);
16640
16663
  waitSpin.stop("Paired");
16641
- resolve6(info);
16664
+ resolve7(info);
16642
16665
  },
16643
16666
  () => {
16644
16667
  clearInterval(countdown);
@@ -16773,14 +16796,14 @@ async function captureFreshCredentials(ctx) {
16773
16796
  }
16774
16797
  };
16775
16798
  try {
16776
- const token = await new Promise((resolve6, reject) => {
16799
+ const token = await new Promise((resolve7, reject) => {
16777
16800
  let settled = false;
16778
16801
  const tryExtract = async () => {
16779
16802
  if (settled) return;
16780
16803
  const t2 = await ctx.locator.extract();
16781
16804
  if (t2 && !settled) {
16782
16805
  settled = true;
16783
- resolve6(t2);
16806
+ resolve7(t2);
16784
16807
  }
16785
16808
  };
16786
16809
  watcher.on("add", () => void tryExtract());
@@ -17178,167 +17201,938 @@ function activePreviewSessionIds() {
17178
17201
  return Array.from(activePreviews.keys());
17179
17202
  }
17180
17203
 
17181
- // src/commands/start/handlers.ts
17182
- var pendingAttachmentFiles = /* @__PURE__ */ new Set();
17183
- function cleanupAttachmentTempFiles() {
17184
- for (const p2 of pendingAttachmentFiles) {
17185
- try {
17186
- fs29.unlinkSync(p2);
17187
- } catch {
17188
- }
17189
- }
17190
- pendingAttachmentFiles.clear();
17204
+ // src/beads/bd-adapter.ts
17205
+ var import_child_process12 = require("child_process");
17206
+ var fs29 = __toESM(require("fs"));
17207
+ var os24 = __toESM(require("os"));
17208
+ var path35 = __toESM(require("path"));
17209
+ var BD_PACKAGE = "@beads/bd";
17210
+ function resolveBundledBdBinary() {
17211
+ return _resolveSeam.resolveBundled();
17191
17212
  }
17192
- function saveFilesTemp(files) {
17193
- return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
17194
- const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
17195
- const tmpPath = path35.join(os24.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
17196
- fs29.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
17197
- pendingAttachmentFiles.add(tmpPath);
17198
- return tmpPath;
17199
- });
17213
+ function _defaultResolveBundled() {
17214
+ let pkgJsonPath;
17215
+ try {
17216
+ pkgJsonPath = require.resolve(`${BD_PACKAGE}/package.json`);
17217
+ } catch {
17218
+ return null;
17219
+ }
17220
+ const binDir = path35.join(path35.dirname(pkgJsonPath), "bin");
17221
+ const binaryName = process.platform === "win32" ? "bd.exe" : "bd";
17222
+ const binaryPath = path35.join(binDir, binaryName);
17223
+ try {
17224
+ fs29.accessSync(binaryPath, fs29.constants.F_OK);
17225
+ return binaryPath;
17226
+ } catch {
17227
+ return null;
17228
+ }
17200
17229
  }
17201
- function dispatchPrompt(ctx, prompt) {
17202
- ctx.outputSvc.newTurn();
17203
- ctx.agent.sendCommand(prompt);
17230
+ function resolveBdOnPath() {
17231
+ return _resolveSeam.resolveOnPath();
17204
17232
  }
17205
- var startTask = (ctx, _cmd, parsed) => {
17206
- const { prompt, files } = parsed;
17207
- const effectivePrompt = prompt ?? "";
17208
- if (files && files.length > 0) {
17209
- const paths = saveFilesTemp(files);
17210
- const atRefs = paths.map((p2) => `@${p2}`).join(" ");
17211
- ctx.outputSvc.newTurn();
17212
- ctx.agent.sendCommand(`${atRefs} ${effectivePrompt}`.trim());
17213
- setTimeout(() => {
17214
- for (const p2 of paths) {
17215
- try {
17216
- fs29.unlinkSync(p2);
17217
- } catch {
17218
- }
17219
- pendingAttachmentFiles.delete(p2);
17233
+ function _defaultResolveOnPath() {
17234
+ const dirs = (process.env.PATH ?? "").split(path35.delimiter).filter(Boolean);
17235
+ const candidates = process.platform === "win32" ? ["bd.exe", "bd.cmd", "bd"] : ["bd"];
17236
+ for (const dir of dirs) {
17237
+ for (const candidate of candidates) {
17238
+ const full = path35.join(dir, candidate);
17239
+ try {
17240
+ fs29.accessSync(full, fs29.constants.F_OK);
17241
+ return full;
17242
+ } catch {
17220
17243
  }
17221
- }, 12e4);
17222
- } else if (effectivePrompt) {
17223
- dispatchPrompt(ctx, effectivePrompt);
17244
+ }
17224
17245
  }
17246
+ return null;
17247
+ }
17248
+ var _resolveSeam = {
17249
+ resolveBundled: _defaultResolveBundled,
17250
+ resolveOnPath: _defaultResolveOnPath
17225
17251
  };
17226
- var provideInput = (ctx, _cmd, parsed) => {
17227
- if (parsed.input) dispatchPrompt(ctx, parsed.input);
17228
- };
17229
- var selectOption = (ctx, _cmd, parsed) => {
17230
- const index = parsed.index ?? 0;
17231
- const from = parsed.from ?? 0;
17232
- ctx.outputSvc.newTurn();
17233
- ctx.agent.selectOption(index, from);
17234
- };
17235
- var escapeKey = (ctx) => {
17236
- ctx.outputSvc.newTurn();
17237
- ctx.agent.sendEscape();
17238
- };
17239
- var stopTask = (ctx) => {
17240
- ctx.agent.interrupt();
17241
- };
17242
- var resumeSession = async (ctx, _cmd, parsed) => {
17243
- const { id, auto } = parsed;
17244
- if (!id) return;
17245
- ctx.historySvc.setCurrentConversationId(id);
17246
- await ctx.historySvc.loadConversation(id);
17247
- await ctx.outputSvc.newTurnResume(id);
17248
- ctx.agent.restart(id, auto ?? false);
17249
- };
17250
- var getContext = async (ctx, cmd) => {
17251
- const usage = ctx.historySvc.getCurrentUsage();
17252
- const monthlyCost = ctx.historySvc.getMonthlyEstimatedCost();
17253
- const rateLimitReset = ctx.historySvc.getRateLimitReset();
17254
- const quotaPercent = ctx.historySvc.getQuotaPercent();
17255
- const base = usage ? { ...usage, monthlyCost } : { used: 0, total: 2e5, percent: 0, model: null, outputTokens: 0, cacheReadTokens: 0, monthlyCost, error: "No usage data found" };
17256
- const result = {
17257
- ...base,
17258
- ...rateLimitReset ? { rateLimitReset } : {},
17259
- ...quotaPercent !== null ? { quotaPercent } : {}
17260
- };
17261
- await ctx.relay.sendResult(cmd.id, "completed", result);
17252
+ var _spawnSeam = {
17253
+ run: _defaultSpawn
17262
17254
  };
17263
- var getConversation = async (ctx, cmd) => {
17264
- let currentId = ctx.historySvc.getCurrentConversationId();
17265
- if (!currentId) {
17266
- ctx.historySvc.detectCurrentConversation();
17267
- currentId = ctx.historySvc.getCurrentConversationId();
17255
+ function _defaultSpawn(binaryPath, args2, opts) {
17256
+ return new Promise((resolve7) => {
17257
+ let proc;
17258
+ try {
17259
+ proc = (0, import_child_process12.spawn)(binaryPath, args2, { cwd: opts.cwd, env: opts.env });
17260
+ } catch (err) {
17261
+ resolve7({ code: -1, stdout: "", stderr: err.message });
17262
+ return;
17263
+ }
17264
+ let stdout = "";
17265
+ let stderr = "";
17266
+ proc.stdout?.on("data", (c2) => {
17267
+ stdout += c2.toString();
17268
+ });
17269
+ proc.stderr?.on("data", (c2) => {
17270
+ stderr += c2.toString();
17271
+ });
17272
+ proc.on("error", (err) => resolve7({ code: -1, stdout, stderr: err.message }));
17273
+ proc.on("close", (code) => resolve7({ code: code ?? -1, stdout, stderr }));
17274
+ });
17275
+ }
17276
+ var BdAdapter = class {
17277
+ constructor(opts = {}) {
17278
+ this.opts = opts;
17279
+ this.resolved = opts.binaryPath ?? null;
17268
17280
  }
17269
- if (!currentId) {
17270
- await ctx.relay.sendResult(cmd.id, "completed", { conversationId: null });
17271
- return;
17281
+ opts;
17282
+ resolved;
17283
+ /**
17284
+ * Resolve the bd binary lazily, caching the result. Order:
17285
+ * bundled @beads/bd → PATH. Returns null when neither is available — the
17286
+ * caller offers the consented installer (`install-bd.ts`).
17287
+ */
17288
+ resolveBinary() {
17289
+ if (this.resolved) return this.resolved;
17290
+ const bundled = resolveBundledBdBinary();
17291
+ if (bundled) {
17292
+ this.resolved = bundled;
17293
+ return bundled;
17294
+ }
17295
+ const onPath = resolveBdOnPath();
17296
+ if (onPath) {
17297
+ this.resolved = onPath;
17298
+ return onPath;
17299
+ }
17300
+ return null;
17272
17301
  }
17273
- try {
17274
- await ctx.historySvc.loadConversation(currentId);
17275
- await ctx.relay.sendResult(cmd.id, "completed", { conversationId: currentId });
17276
- } catch {
17277
- await ctx.relay.sendResult(cmd.id, "failed", {});
17302
+ /** True when a bd binary is resolvable without installing. */
17303
+ isAvailable() {
17304
+ return this.resolveBinary() !== null;
17278
17305
  }
17279
- };
17280
- var listModels = async (ctx, cmd) => {
17281
- const models = await ctx.runtime.listModels();
17282
- await ctx.relay.sendResult(cmd.id, "completed", { models });
17283
- };
17284
- var changeModel = async (ctx, cmd) => {
17285
- const params = cmd.payload;
17286
- if (typeof params.modelId !== "string" || !params.modelId) {
17287
- await ctx.relay.sendResult(cmd.id, "failed", { error: "modelId required" });
17288
- return;
17306
+ /**
17307
+ * Run an arbitrary bd subcommand against the home brain. `BEADS_DIR` is set
17308
+ * to the configured `beadsDir` (tests) or `~/.beads` (the verified embedded
17309
+ * home brain) so every command resolves to the same single graph regardless
17310
+ * of the process cwd. Returns the raw result; callers decide how to interpret
17311
+ * exit codes note bd exits 0 even for some error states (e.g. "no beads
17312
+ * database found"), so JSON-parsing callers must also inspect the payload.
17313
+ */
17314
+ async run(args2) {
17315
+ const binary = this.resolveBinary();
17316
+ if (!binary) {
17317
+ return { code: -1, stdout: "", stderr: "bd binary not resolved" };
17318
+ }
17319
+ const env = { ...process.env };
17320
+ env.BEADS_DIR = this.opts.beadsDir ?? defaultBeadsHomeDir();
17321
+ log.trace("beads", `bd ${args2.join(" ")} (BEADS_DIR=${env.BEADS_DIR})`);
17322
+ return _spawnSeam.run(binary, args2, { cwd: this.opts.cwd, env });
17289
17323
  }
17290
- const instr = ctx.runtime.changeModelInstruction(params.modelId);
17291
- if (instr.type === "pty") {
17292
- if (!instr.ptyInput) {
17293
- await ctx.relay.sendResult(cmd.id, "failed", { error: "no pty input for this agent" });
17294
- return;
17324
+ /**
17325
+ * `bd ready --json` → typed issue array. `bd list --json` shares the shape,
17326
+ * so `listIssues` reuses the same parser. Bad JSON / non-zero exit → [].
17327
+ */
17328
+ async readyIssues(projectKey) {
17329
+ const res = await this.run(["ready", "--json"]);
17330
+ return parseIssues(res, projectKey);
17331
+ }
17332
+ async listIssues(projectKey) {
17333
+ const res = await this.run(["list", "--json"]);
17334
+ return parseIssues(res, projectKey);
17335
+ }
17336
+ /** `bd status --json` → summary block, or null on failure. */
17337
+ async statusSummary() {
17338
+ const res = await this.run(["status", "--json"]);
17339
+ if (res.code !== 0) return null;
17340
+ try {
17341
+ const parsed = JSON.parse(res.stdout);
17342
+ return parsed.summary ?? null;
17343
+ } catch {
17344
+ return null;
17295
17345
  }
17296
- ctx.agent.sendRawPtyInput(instr.ptyInput);
17297
- } else if (instr.type === "restart") {
17298
- await ctx.relay.sendResult(cmd.id, "failed", { error: "restart-mode change_model not supported in Phase 1" });
17299
- return;
17300
17346
  }
17301
- await ctx.relay.sendResult(cmd.id, "completed", {});
17302
- };
17303
- var summarize = async (ctx, cmd) => {
17304
- const params = cmd.payload;
17305
- const mode = params.mode === "auto" ? "auto" : "normal";
17306
- const instr = ctx.runtime.summarizeInstruction(mode);
17307
- ctx.agent.sendRawPtyInput(instr.ptyInput);
17308
- await ctx.relay.sendResult(cmd.id, "completed", {});
17309
17347
  };
17310
- var setKeepAlive = async (ctx, cmd) => {
17311
- const enabled = !!cmd.payload.enabled;
17312
- ctx.setKeepAlive(enabled);
17348
+ var VALID_STATUS = /* @__PURE__ */ new Set([
17349
+ "open",
17350
+ "in_progress",
17351
+ "blocked",
17352
+ "closed"
17353
+ ]);
17354
+ function parseIssues(res, projectKey) {
17355
+ if (res.code !== 0) return [];
17356
+ let parsed;
17313
17357
  try {
17314
- await ctx.relay.sendResult(
17315
- cmd.id,
17316
- "success",
17317
- {
17318
- enabled,
17319
- applied: enabled && ctx.keepAliveCtx.inCodespace,
17320
- runtime: ctx.keepAliveCtx.inCodespace ? "github-codespaces" : "local"
17321
- }
17322
- );
17358
+ parsed = JSON.parse(res.stdout);
17323
17359
  } catch {
17360
+ return [];
17324
17361
  }
17325
- };
17326
- var sessionTerminated = async (ctx, cmd) => {
17327
- showInfo("Session was deleted from the app \u2014 exiting.");
17328
- try {
17329
- await ctx.relay.sendResult(cmd.id, "success", { ok: true });
17330
- } catch {
17362
+ if (!Array.isArray(parsed)) return [];
17363
+ const out2 = [];
17364
+ for (const row of parsed) {
17365
+ const issue = coerceIssue(row, projectKey);
17366
+ if (issue) out2.push(issue);
17331
17367
  }
17332
- try {
17333
- removeSession(ctx.sessionId);
17334
- } catch {
17368
+ return out2;
17369
+ }
17370
+ function coerceIssue(row, projectKey) {
17371
+ if (typeof row !== "object" || row === null) return null;
17372
+ const r = row;
17373
+ if (typeof r.id !== "string" || typeof r.title !== "string") return null;
17374
+ const status2 = typeof r.status === "string" && VALID_STATUS.has(r.status) ? r.status : "open";
17375
+ return {
17376
+ id: r.id,
17377
+ title: r.title,
17378
+ status: status2,
17379
+ priority: typeof r.priority === "number" ? r.priority : null,
17380
+ issue_type: typeof r.issue_type === "string" ? r.issue_type : "task",
17381
+ owner: typeof r.owner === "string" && r.owner.length > 0 ? r.owner : null,
17382
+ created_at: typeof r.created_at === "string" ? r.created_at : "",
17383
+ updated_at: typeof r.updated_at === "string" ? r.updated_at : "",
17384
+ dependency_count: typeof r.dependency_count === "number" ? r.dependency_count : void 0,
17385
+ dependent_count: typeof r.dependent_count === "number" ? r.dependent_count : void 0,
17386
+ comment_count: typeof r.comment_count === "number" ? r.comment_count : void 0,
17387
+ projectKey
17388
+ };
17389
+ }
17390
+ function defaultBeadsHomeDir() {
17391
+ return path35.join(os24.homedir(), ".beads");
17392
+ }
17393
+
17394
+ // src/beads/provisioner.ts
17395
+ var fs30 = __toESM(require("fs"));
17396
+ var path36 = __toESM(require("path"));
17397
+
17398
+ // src/beads/install-bd.ts
17399
+ var import_child_process13 = require("child_process");
17400
+ var INSTALL_SH_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh";
17401
+ var INSTALL_PS1_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/install.ps1";
17402
+ function resolveInstallStrategy(platform2) {
17403
+ if (platform2 === "win32") {
17404
+ return {
17405
+ command: "powershell.exe",
17406
+ args: [
17407
+ "-NoProfile",
17408
+ "-NonInteractive",
17409
+ "-ExecutionPolicy",
17410
+ "Bypass",
17411
+ "-Command",
17412
+ `irm ${INSTALL_PS1_URL} | iex`
17413
+ ],
17414
+ description: `PowerShell: irm ${INSTALL_PS1_URL} | iex (requires Go 1.24+ and Git for Windows on PATH)`
17415
+ };
17416
+ }
17417
+ return {
17418
+ command: "bash",
17419
+ args: ["-c", `curl -fsSL ${INSTALL_SH_URL} | bash`],
17420
+ description: `curl -fsSL ${INSTALL_SH_URL} | bash`
17421
+ };
17422
+ }
17423
+ var _installSpawnSeam = {
17424
+ run: _defaultInstallSpawn
17425
+ };
17426
+ function _defaultInstallSpawn(strategy) {
17427
+ return new Promise((resolve7) => {
17428
+ let proc;
17429
+ try {
17430
+ proc = (0, import_child_process13.spawn)(strategy.command, strategy.args, { env: process.env });
17431
+ } catch (err) {
17432
+ resolve7({ ok: false, code: -1, stderr: err.message });
17433
+ return;
17434
+ }
17435
+ let stderr = "";
17436
+ proc.stderr?.on("data", (c2) => {
17437
+ stderr += c2.toString();
17438
+ });
17439
+ proc.on("error", (err) => resolve7({ ok: false, code: -1, stderr: err.message }));
17440
+ proc.on(
17441
+ "close",
17442
+ (code) => resolve7({ ok: code === 0, code: code ?? -1, stderr })
17443
+ );
17444
+ });
17445
+ }
17446
+ async function installBd(platform2 = process.platform) {
17447
+ const strategy = resolveInstallStrategy(platform2);
17448
+ log.info("beads", `installing bd via ${strategy.description}`);
17449
+ const result = await _installSpawnSeam.run(strategy);
17450
+ if (!result.ok) {
17451
+ log.warn(
17452
+ "beads",
17453
+ `bd install failed (code=${result.code}): ${result.stderr.slice(0, 200)}`
17454
+ );
17335
17455
  }
17456
+ return result;
17457
+ }
17458
+
17459
+ // src/beads/provisioner.ts
17460
+ var AGENT_SETUP_RECIPE = {
17461
+ claude: "claude",
17462
+ codex: "codex",
17463
+ copilot: "copilot",
17464
+ cursor: "cursor",
17465
+ aider: "aider",
17466
+ gemini: "gemini",
17467
+ coderabbit: null
17468
+ };
17469
+ var _provisionSeam = {
17470
+ install: installBd,
17471
+ homeBrainInitialized
17472
+ };
17473
+ function homeBrainInitialized(beadsDir) {
17336
17474
  try {
17337
- ctx.agent.kill();
17475
+ return fs30.statSync(path36.join(beadsDir, "embeddeddolt")).isDirectory();
17338
17476
  } catch {
17477
+ return false;
17339
17478
  }
17340
- try {
17341
- const proc = (0, import_child_process12.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
17479
+ }
17480
+ async function provisionBeads(opts = {}) {
17481
+ const bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
17482
+ const beadsDir = opts.beadsDir ?? defaultBeadsHomeDir();
17483
+ const result = {
17484
+ bdAvailable: false,
17485
+ initialized: false,
17486
+ exportEnabled: false,
17487
+ agentsWired: []
17488
+ };
17489
+ if (!bd.isAvailable()) {
17490
+ log.info("beads", "bd binary missing \u2014 running OS installer fallback");
17491
+ const install = await _provisionSeam.install();
17492
+ if (!install.ok) {
17493
+ log.warn("beads", `bd install failed (code=${install.code}) \u2014 beads disabled this run`);
17494
+ return result;
17495
+ }
17496
+ }
17497
+ if (!bd.isAvailable()) {
17498
+ log.warn("beads", "bd still unavailable after install \u2014 beads disabled this run");
17499
+ return result;
17500
+ }
17501
+ result.bdAvailable = true;
17502
+ if (_provisionSeam.homeBrainInitialized(beadsDir)) {
17503
+ log.trace("beads", `home brain already initialized at ${beadsDir}`);
17504
+ result.initialized = true;
17505
+ } else {
17506
+ log.info("beads", `initializing home brain at ${beadsDir}`);
17507
+ const init = await bd.run(["init", "--skip-agents", "--skip-hooks", "--non-interactive"]);
17508
+ if (init.code !== 0) {
17509
+ log.warn("beads", `bd init failed (code=${init.code}): ${init.stderr.slice(0, 200)}`);
17510
+ return result;
17511
+ }
17512
+ result.initialized = true;
17513
+ }
17514
+ const exp = await bd.run(["config", "set", "export.auto", "true"]);
17515
+ result.exportEnabled = exp.code === 0;
17516
+ result.agentsWired = await setupAgents(bd, opts.agents ?? []);
17517
+ log.info(
17518
+ "beads",
17519
+ `provision done initialized=${result.initialized} export=${result.exportEnabled} agentsWired=[${result.agentsWired.join(",")}]`
17520
+ );
17521
+ return result;
17522
+ }
17523
+ async function setupAgents(bd, agents) {
17524
+ const wired = [];
17525
+ for (const recipe of dedupeRecipes(agents)) {
17526
+ try {
17527
+ const check = await bd.run(["setup", recipe, "--global", "--check"]);
17528
+ if (check.code === 0) {
17529
+ log.trace("beads", `bd setup ${recipe} --global already installed \u2014 skipping`);
17530
+ wired.push(recipe);
17531
+ continue;
17532
+ }
17533
+ log.info("beads", `wiring agent natively: bd setup ${recipe} --global`);
17534
+ const setup = await bd.run(["setup", recipe, "--global"]);
17535
+ if (setup.code === 0) {
17536
+ wired.push(recipe);
17537
+ } else {
17538
+ log.warn(
17539
+ "beads",
17540
+ `bd setup ${recipe} --global failed (code=${setup.code}): ${setup.stderr.slice(0, 200)} \u2014 non-fatal, agent runs without native bd wiring`
17541
+ );
17542
+ }
17543
+ } catch (err) {
17544
+ log.warn("beads", `bd setup ${recipe} --global threw (non-fatal)`, err);
17545
+ }
17546
+ }
17547
+ return wired;
17548
+ }
17549
+ function dedupeRecipes(agents) {
17550
+ const seen = /* @__PURE__ */ new Set();
17551
+ for (const agent of agents) {
17552
+ const recipe = AGENT_SETUP_RECIPE[agent];
17553
+ if (recipe) seen.add(recipe);
17554
+ }
17555
+ return [...seen];
17556
+ }
17557
+
17558
+ // src/beads/watcher.ts
17559
+ var crypto3 = __toESM(require("crypto"));
17560
+ var path38 = __toESM(require("path"));
17561
+
17562
+ // src/beads/project-key.ts
17563
+ var import_child_process14 = require("child_process");
17564
+ var crypto2 = __toESM(require("crypto"));
17565
+ var fs31 = __toESM(require("fs"));
17566
+ var path37 = __toESM(require("path"));
17567
+ function normalizeOrigin(raw) {
17568
+ const trimmed = raw.trim();
17569
+ if (!trimmed) return null;
17570
+ let host;
17571
+ let pathPart;
17572
+ const scpLike = /^[^/@]+@([^:]+):(.+)$/.exec(trimmed);
17573
+ if (scpLike && !trimmed.includes("://")) {
17574
+ host = scpLike[1];
17575
+ pathPart = scpLike[2];
17576
+ } else {
17577
+ let url;
17578
+ try {
17579
+ url = new URL(trimmed);
17580
+ } catch {
17581
+ return null;
17582
+ }
17583
+ host = url.hostname;
17584
+ pathPart = url.pathname;
17585
+ }
17586
+ host = host.toLowerCase();
17587
+ pathPart = pathPart.replace(/^\/+/, "").replace(/\.git$/i, "").replace(/\/+$/, "");
17588
+ if (!host || !pathPart) return null;
17589
+ return `${host}/${pathPart}`;
17590
+ }
17591
+ function findRepoRoot(cwd) {
17592
+ let dir = path37.resolve(cwd);
17593
+ const seen = /* @__PURE__ */ new Set();
17594
+ for (let i = 0; i < 256; i++) {
17595
+ if (seen.has(dir)) return null;
17596
+ seen.add(dir);
17597
+ try {
17598
+ const stat3 = fs31.statSync(path37.join(dir, ".git"), { throwIfNoEntry: false });
17599
+ if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
17600
+ } catch {
17601
+ }
17602
+ const parent = path37.dirname(dir);
17603
+ if (parent === dir) return null;
17604
+ dir = parent;
17605
+ }
17606
+ return null;
17607
+ }
17608
+ var _execSeam2 = {
17609
+ exec: (file, args2, opts) => {
17610
+ const out2 = (0, import_child_process14.execFileSync)(file, args2, opts);
17611
+ return typeof out2 === "string" ? out2 : out2.toString("utf8");
17612
+ },
17613
+ realpath: (p2) => fs31.realpathSync(p2)
17614
+ };
17615
+ function readOrigin(cwd) {
17616
+ try {
17617
+ const raw = _execSeam2.exec("git", ["remote", "get-url", "origin"], {
17618
+ cwd,
17619
+ timeout: 1e3,
17620
+ stdio: ["ignore", "pipe", "ignore"],
17621
+ encoding: "utf8"
17622
+ });
17623
+ return raw.trim() || null;
17624
+ } catch {
17625
+ return null;
17626
+ }
17627
+ }
17628
+ function deriveProjectIdentity(cwd = process.cwd()) {
17629
+ const repoRoot = findRepoRoot(cwd) ?? cwd;
17630
+ const origin = readOrigin(repoRoot);
17631
+ const normalized = origin ? normalizeOrigin(origin) : null;
17632
+ if (normalized) {
17633
+ const label = normalized.split("/").pop() || normalized;
17634
+ return { projectKey: normalized, projectLabel: label };
17635
+ }
17636
+ let real = repoRoot;
17637
+ try {
17638
+ real = _execSeam2.realpath(repoRoot);
17639
+ } catch {
17640
+ }
17641
+ const hash = crypto2.createHash("sha256").update(real).digest("hex");
17642
+ return { projectKey: `path:${hash}`, projectLabel: path37.basename(real) || "project" };
17643
+ }
17644
+
17645
+ // src/services/file-watcher/transport.ts
17646
+ var http5 = __toESM(require("http"));
17647
+ var https5 = __toESM(require("https"));
17648
+ var _transport3 = {
17649
+ post: _post2
17650
+ };
17651
+ function _post2(url, headers, payload) {
17652
+ return new Promise((resolve7, reject) => {
17653
+ let settled = false;
17654
+ const u2 = new URL(url);
17655
+ const lib = u2.protocol === "https:" ? https5 : http5;
17656
+ const req = lib.request(
17657
+ {
17658
+ hostname: u2.hostname,
17659
+ port: u2.port || (u2.protocol === "https:" ? 443 : 80),
17660
+ path: u2.pathname + u2.search,
17661
+ method: "POST",
17662
+ headers: {
17663
+ ...headers,
17664
+ ...vercelBypassHeader(),
17665
+ "Content-Length": Buffer.byteLength(payload)
17666
+ },
17667
+ timeout: 8e3
17668
+ },
17669
+ (res) => {
17670
+ let body = "";
17671
+ res.on("data", (c2) => {
17672
+ body += c2.toString();
17673
+ });
17674
+ res.on("end", () => {
17675
+ if (settled) return;
17676
+ settled = true;
17677
+ resolve7({ statusCode: res.statusCode ?? 0, body });
17678
+ });
17679
+ }
17680
+ );
17681
+ req.on("error", (err) => {
17682
+ if (settled) return;
17683
+ settled = true;
17684
+ reject(err);
17685
+ });
17686
+ req.on("timeout", () => {
17687
+ req.destroy();
17688
+ });
17689
+ req.write(payload);
17690
+ req.end();
17691
+ });
17692
+ }
17693
+
17694
+ // src/beads/watcher.ts
17695
+ var API_BASE4 = resolveApiBaseUrl();
17696
+ var DEBOUNCE_MS = 400;
17697
+ var _chokidarSeam = {
17698
+ load: () => {
17699
+ try {
17700
+ return require("chokidar");
17701
+ } catch {
17702
+ return null;
17703
+ }
17704
+ }
17705
+ };
17706
+ var BeadsWatcher = class {
17707
+ constructor(opts) {
17708
+ this.opts = opts;
17709
+ this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
17710
+ this.feedPath = opts.feedPath ?? path38.join(defaultBeadsHomeDir(), "issues.jsonl");
17711
+ this.apiBase = opts.apiBaseUrl ?? API_BASE4;
17712
+ }
17713
+ opts;
17714
+ watcher = null;
17715
+ debounceTimer = null;
17716
+ stopped = false;
17717
+ lastPushedHash = null;
17718
+ bd;
17719
+ feedPath;
17720
+ apiBase;
17721
+ /** Start tailing the change feed. Idempotent (second call is a no-op). */
17722
+ start() {
17723
+ if (this.watcher || this.stopped) return;
17724
+ const chokidar2 = _chokidarSeam.load();
17725
+ if (!chokidar2) {
17726
+ log.warn("beads", "chokidar unavailable \u2014 beads watcher disabled");
17727
+ return;
17728
+ }
17729
+ const watcher = chokidar2.watch(this.feedPath, {
17730
+ ignoreInitial: false,
17731
+ // push the current state once on start
17732
+ persistent: true,
17733
+ awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 100 }
17734
+ });
17735
+ watcher.on("add", () => this.scheduleSync());
17736
+ watcher.on("change", () => this.scheduleSync());
17737
+ watcher.on(
17738
+ "error",
17739
+ (err) => log.warn("beads", `feed watcher error \u2014 continuing: ${err}`)
17740
+ );
17741
+ this.watcher = watcher;
17742
+ log.info("beads", `watching ${this.feedPath} for session=${this.opts.sessionId.slice(0, 8)}`);
17743
+ }
17744
+ async stop() {
17745
+ if (this.stopped) return;
17746
+ this.stopped = true;
17747
+ if (this.debounceTimer) {
17748
+ clearTimeout(this.debounceTimer);
17749
+ this.debounceTimer = null;
17750
+ }
17751
+ if (this.watcher) {
17752
+ try {
17753
+ await this.watcher.close();
17754
+ } catch (err) {
17755
+ log.warn("beads", "error closing feed watcher", err);
17756
+ }
17757
+ this.watcher = null;
17758
+ }
17759
+ }
17760
+ /**
17761
+ * Debounce the filesystem event. Each fresh write resets the timer so a
17762
+ * burst of bd mutations coalesces into one snapshot push. NOT polling — the
17763
+ * timer only fires off the back of a real fs event.
17764
+ */
17765
+ scheduleSync() {
17766
+ if (this.stopped) return;
17767
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
17768
+ this.debounceTimer = setTimeout(() => {
17769
+ this.debounceTimer = null;
17770
+ void this.syncNow();
17771
+ }, DEBOUNCE_MS);
17772
+ }
17773
+ /** Visible for tests — pump a synthetic feed event through debounce → push. */
17774
+ /* @internal */
17775
+ _emitForTest() {
17776
+ this.scheduleSync();
17777
+ }
17778
+ /**
17779
+ * Build the full snapshot from bd and push it. Diffs against the last
17780
+ * pushed content hash so an identical rewrite is a no-op.
17781
+ */
17782
+ async syncNow() {
17783
+ if (this.stopped) return;
17784
+ const { projectKey, projectLabel } = deriveProjectIdentity(this.opts.cwd);
17785
+ const [issues, summary] = await Promise.all([
17786
+ this.bd.listIssues(projectKey),
17787
+ this.bd.statusSummary()
17788
+ ]);
17789
+ const payload = {
17790
+ sessionId: this.opts.sessionId,
17791
+ pluginId: this.opts.pluginId,
17792
+ projectKey,
17793
+ projectLabel,
17794
+ fullSnapshot: true,
17795
+ issues,
17796
+ memories: [],
17797
+ ...summary ? { summary } : {}
17798
+ };
17799
+ const body = JSON.stringify(payload);
17800
+ const hash = crypto3.createHash("sha256").update(body).digest("hex");
17801
+ if (hash === this.lastPushedHash) {
17802
+ log.trace("beads", "snapshot unchanged \u2014 skipping push");
17803
+ return;
17804
+ }
17805
+ try {
17806
+ const res = await _transport3.post(`${this.apiBase}/api/beads/ingest`, this.headers(), body);
17807
+ if (res.statusCode >= 200 && res.statusCode < 300) {
17808
+ this.lastPushedHash = hash;
17809
+ log.trace("beads", `pushed ${issues.length} issue(s) project=${projectLabel}`);
17810
+ } else if (res.statusCode === 404 || res.statusCode === 410) {
17811
+ log.warn("beads", `session dead (status=${res.statusCode}) \u2014 stopping watcher`);
17812
+ this.stopped = true;
17813
+ } else {
17814
+ log.warn("beads", `ingest failed status=${res.statusCode} body=${res.body.slice(0, 200)}`);
17815
+ }
17816
+ } catch (err) {
17817
+ log.warn("beads", "ingest POST error", err);
17818
+ }
17819
+ }
17820
+ headers() {
17821
+ return {
17822
+ "Content-Type": "application/json",
17823
+ "X-Codeam-Protocol-Version": "2.0.0",
17824
+ "X-Plugin-Auth-Token": this.opts.pluginAuthToken
17825
+ };
17826
+ }
17827
+ };
17828
+
17829
+ // src/beads/apply-actions.ts
17830
+ function buildBdArgs(action) {
17831
+ switch (action.kind) {
17832
+ case "claim": {
17833
+ if (!action.issueId) return null;
17834
+ const args2 = ["update", action.issueId, "--claim"];
17835
+ if (action.owner) args2.push("--owner", action.owner);
17836
+ return args2;
17837
+ }
17838
+ case "close": {
17839
+ if (!action.issueId) return null;
17840
+ const args2 = ["close", action.issueId];
17841
+ if (action.reason) args2.push("--reason", action.reason);
17842
+ return args2;
17843
+ }
17844
+ case "create": {
17845
+ const title = action.text?.trim();
17846
+ if (!title) return null;
17847
+ return ["create", title];
17848
+ }
17849
+ case "remember": {
17850
+ const body = action.text?.trim();
17851
+ if (!body) return null;
17852
+ return ["remember", body];
17853
+ }
17854
+ default:
17855
+ return null;
17856
+ }
17857
+ }
17858
+ async function applyBeadsAction(action, deps) {
17859
+ const args2 = buildBdArgs(action);
17860
+ if (!args2) {
17861
+ log.warn("beads", `malformed beads action: kind=${action.kind}`);
17862
+ return { ok: false, action: action.kind, code: -1, error: "malformed action" };
17863
+ }
17864
+ if (!deps.adapter.isAvailable()) {
17865
+ return { ok: false, action: action.kind, code: -1, error: "bd unavailable" };
17866
+ }
17867
+ const res = await deps.adapter.run(args2);
17868
+ if (res.code !== 0) {
17869
+ log.warn("beads", `bd ${args2.join(" ")} failed (code=${res.code}): ${res.stderr.slice(0, 200)}`);
17870
+ return { ok: false, action: action.kind, code: res.code, error: res.stderr };
17871
+ }
17872
+ log.info("beads", `applied action ${action.kind}${action.issueId ? ` (${action.issueId})` : ""}`);
17873
+ try {
17874
+ await deps.onApplied();
17875
+ } catch (err) {
17876
+ log.warn("beads", "post-action push failed (state still applied locally)", err);
17877
+ }
17878
+ return { ok: true, action: action.kind, code: 0 };
17879
+ }
17880
+
17881
+ // src/beads/index.ts
17882
+ async function startBeads(opts) {
17883
+ const adapter = new BdAdapter({ cwd: opts.cwd });
17884
+ const provision = await provisionBeads({ cwd: opts.cwd, adapter, agents: opts.agents });
17885
+ if (!provision.bdAvailable || !provision.initialized) {
17886
+ log.warn("beads", "home brain not provisioned \u2014 watcher not started this run");
17887
+ return null;
17888
+ }
17889
+ const watcher = new BeadsWatcher({
17890
+ sessionId: opts.sessionId,
17891
+ pluginId: opts.pluginId,
17892
+ pluginAuthToken: opts.pluginAuthToken,
17893
+ cwd: opts.cwd,
17894
+ adapter
17895
+ });
17896
+ watcher.start();
17897
+ void watcher.syncNow();
17898
+ return { watcher, adapter };
17899
+ }
17900
+ async function handleBeadsActionCommand(action, started) {
17901
+ await applyBeadsAction(action, {
17902
+ adapter: started.adapter,
17903
+ onApplied: () => started.watcher.syncNow()
17904
+ });
17905
+ }
17906
+
17907
+ // src/beads/wiring.ts
17908
+ function beadsKilled() {
17909
+ const v = process.env.CODEAM_BEADS_DISABLED;
17910
+ return !!v && v !== "0" && v.toLowerCase() !== "false";
17911
+ }
17912
+ async function provisionBeadsForStart(ctx) {
17913
+ if (beadsKilled()) {
17914
+ log.trace("beads", "CODEAM_BEADS_DISABLED set \u2014 beads off this run");
17915
+ return null;
17916
+ }
17917
+ if (!ctx.pluginAuthToken) {
17918
+ log.trace("beads", "no pluginAuthToken \u2014 beads off");
17919
+ return null;
17920
+ }
17921
+ const pluginAuthToken = ctx.pluginAuthToken;
17922
+ let started = null;
17923
+ try {
17924
+ started = await startBeads({
17925
+ sessionId: ctx.sessionId,
17926
+ pluginId: ctx.pluginId,
17927
+ pluginAuthToken,
17928
+ cwd: ctx.cwd,
17929
+ agents: ctx.agents
17930
+ });
17931
+ } catch (err) {
17932
+ log.warn("beads", "provisionBeadsForStart failed (non-fatal)", err);
17933
+ started = null;
17934
+ }
17935
+ const { projectKey } = deriveProjectIdentity(ctx.cwd);
17936
+ void postBeadsProvisioning({
17937
+ sessionId: ctx.sessionId,
17938
+ pluginId: ctx.pluginId,
17939
+ pluginAuthToken,
17940
+ status: started ? "ready" : "failed",
17941
+ projectKey
17942
+ }).then((res) => {
17943
+ if (!res.ok) {
17944
+ log.trace("beads", `provisioning signal POST non-ok (status=${res.status}) \u2014 ignoring`);
17945
+ }
17946
+ });
17947
+ return started;
17948
+ }
17949
+ var ACTION_KINDS = /* @__PURE__ */ new Set([
17950
+ "claim",
17951
+ "close",
17952
+ "create",
17953
+ "remember"
17954
+ ]);
17955
+ function isBeadsActionKind(v) {
17956
+ return typeof v === "string" && ACTION_KINDS.has(v);
17957
+ }
17958
+ function strOrUndefined(v) {
17959
+ return typeof v === "string" ? v : void 0;
17960
+ }
17961
+ function beadsActionFromPayload(payload) {
17962
+ const { action, args: args2 } = payload;
17963
+ if (!isBeadsActionKind(action)) return null;
17964
+ const a = args2 && typeof args2 === "object" ? args2 : {};
17965
+ return {
17966
+ kind: action,
17967
+ issueId: strOrUndefined(a.issueId),
17968
+ text: strOrUndefined(a.text),
17969
+ reason: strOrUndefined(a.reason),
17970
+ owner: strOrUndefined(a.owner),
17971
+ projectKey: strOrUndefined(a.projectKey)
17972
+ };
17973
+ }
17974
+
17975
+ // src/commands/start/handlers.ts
17976
+ var pendingAttachmentFiles = /* @__PURE__ */ new Set();
17977
+ function cleanupAttachmentTempFiles() {
17978
+ for (const p2 of pendingAttachmentFiles) {
17979
+ try {
17980
+ fs32.unlinkSync(p2);
17981
+ } catch {
17982
+ }
17983
+ }
17984
+ pendingAttachmentFiles.clear();
17985
+ }
17986
+ function saveFilesTemp(files) {
17987
+ return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
17988
+ const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
17989
+ const tmpPath = path39.join(os25.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
17990
+ fs32.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
17991
+ pendingAttachmentFiles.add(tmpPath);
17992
+ return tmpPath;
17993
+ });
17994
+ }
17995
+ function dispatchPrompt(ctx, prompt) {
17996
+ ctx.outputSvc.newTurn();
17997
+ ctx.agent.sendCommand(prompt);
17998
+ }
17999
+ var startTask = (ctx, _cmd, parsed) => {
18000
+ const { prompt, files } = parsed;
18001
+ const effectivePrompt = prompt ?? "";
18002
+ if (files && files.length > 0) {
18003
+ const paths = saveFilesTemp(files);
18004
+ const atRefs = paths.map((p2) => `@${p2}`).join(" ");
18005
+ ctx.outputSvc.newTurn();
18006
+ ctx.agent.sendCommand(`${atRefs} ${effectivePrompt}`.trim());
18007
+ setTimeout(() => {
18008
+ for (const p2 of paths) {
18009
+ try {
18010
+ fs32.unlinkSync(p2);
18011
+ } catch {
18012
+ }
18013
+ pendingAttachmentFiles.delete(p2);
18014
+ }
18015
+ }, 12e4);
18016
+ } else if (effectivePrompt) {
18017
+ dispatchPrompt(ctx, effectivePrompt);
18018
+ }
18019
+ };
18020
+ var provideInput = (ctx, _cmd, parsed) => {
18021
+ if (parsed.input) dispatchPrompt(ctx, parsed.input);
18022
+ };
18023
+ var selectOption = (ctx, _cmd, parsed) => {
18024
+ const index = parsed.index ?? 0;
18025
+ const from = parsed.from ?? 0;
18026
+ ctx.outputSvc.newTurn();
18027
+ ctx.agent.selectOption(index, from);
18028
+ };
18029
+ var escapeKey = (ctx) => {
18030
+ ctx.outputSvc.newTurn();
18031
+ ctx.agent.sendEscape();
18032
+ };
18033
+ var stopTask = (ctx) => {
18034
+ ctx.agent.interrupt();
18035
+ };
18036
+ var resumeSession = async (ctx, _cmd, parsed) => {
18037
+ const { id, auto } = parsed;
18038
+ if (!id) return;
18039
+ ctx.historySvc.setCurrentConversationId(id);
18040
+ await ctx.historySvc.loadConversation(id);
18041
+ await ctx.outputSvc.newTurnResume(id);
18042
+ ctx.agent.restart(id, auto ?? false);
18043
+ };
18044
+ var getContext = async (ctx, cmd) => {
18045
+ const usage = ctx.historySvc.getCurrentUsage();
18046
+ const monthlyCost = ctx.historySvc.getMonthlyEstimatedCost();
18047
+ const rateLimitReset = ctx.historySvc.getRateLimitReset();
18048
+ const quotaPercent = ctx.historySvc.getQuotaPercent();
18049
+ const base = usage ? { ...usage, monthlyCost } : { used: 0, total: 2e5, percent: 0, model: null, outputTokens: 0, cacheReadTokens: 0, monthlyCost, error: "No usage data found" };
18050
+ const result = {
18051
+ ...base,
18052
+ ...rateLimitReset ? { rateLimitReset } : {},
18053
+ ...quotaPercent !== null ? { quotaPercent } : {}
18054
+ };
18055
+ await ctx.relay.sendResult(cmd.id, "completed", result);
18056
+ };
18057
+ var getConversation = async (ctx, cmd) => {
18058
+ let currentId = ctx.historySvc.getCurrentConversationId();
18059
+ if (!currentId) {
18060
+ ctx.historySvc.detectCurrentConversation();
18061
+ currentId = ctx.historySvc.getCurrentConversationId();
18062
+ }
18063
+ if (!currentId) {
18064
+ await ctx.relay.sendResult(cmd.id, "completed", { conversationId: null });
18065
+ return;
18066
+ }
18067
+ try {
18068
+ await ctx.historySvc.loadConversation(currentId);
18069
+ await ctx.relay.sendResult(cmd.id, "completed", { conversationId: currentId });
18070
+ } catch {
18071
+ await ctx.relay.sendResult(cmd.id, "failed", {});
18072
+ }
18073
+ };
18074
+ var listModels = async (ctx, cmd) => {
18075
+ const models = await ctx.runtime.listModels();
18076
+ await ctx.relay.sendResult(cmd.id, "completed", { models });
18077
+ };
18078
+ var changeModel = async (ctx, cmd) => {
18079
+ const params = cmd.payload;
18080
+ if (typeof params.modelId !== "string" || !params.modelId) {
18081
+ await ctx.relay.sendResult(cmd.id, "failed", { error: "modelId required" });
18082
+ return;
18083
+ }
18084
+ const instr = ctx.runtime.changeModelInstruction(params.modelId);
18085
+ if (instr.type === "pty") {
18086
+ if (!instr.ptyInput) {
18087
+ await ctx.relay.sendResult(cmd.id, "failed", { error: "no pty input for this agent" });
18088
+ return;
18089
+ }
18090
+ ctx.agent.sendRawPtyInput(instr.ptyInput);
18091
+ } else if (instr.type === "restart") {
18092
+ await ctx.relay.sendResult(cmd.id, "failed", { error: "restart-mode change_model not supported in Phase 1" });
18093
+ return;
18094
+ }
18095
+ await ctx.relay.sendResult(cmd.id, "completed", {});
18096
+ };
18097
+ var summarize = async (ctx, cmd) => {
18098
+ const params = cmd.payload;
18099
+ const mode = params.mode === "auto" ? "auto" : "normal";
18100
+ const instr = ctx.runtime.summarizeInstruction(mode);
18101
+ ctx.agent.sendRawPtyInput(instr.ptyInput);
18102
+ await ctx.relay.sendResult(cmd.id, "completed", {});
18103
+ };
18104
+ var setKeepAlive = async (ctx, cmd) => {
18105
+ const enabled = !!cmd.payload.enabled;
18106
+ ctx.setKeepAlive(enabled);
18107
+ try {
18108
+ await ctx.relay.sendResult(
18109
+ cmd.id,
18110
+ "success",
18111
+ {
18112
+ enabled,
18113
+ applied: enabled && ctx.keepAliveCtx.inCodespace,
18114
+ runtime: ctx.keepAliveCtx.inCodespace ? "github-codespaces" : "local"
18115
+ }
18116
+ );
18117
+ } catch {
18118
+ }
18119
+ };
18120
+ var sessionTerminated = async (ctx, cmd) => {
18121
+ showInfo("Session was deleted from the app \u2014 exiting.");
18122
+ try {
18123
+ await ctx.relay.sendResult(cmd.id, "success", { ok: true });
18124
+ } catch {
18125
+ }
18126
+ try {
18127
+ removeSession(ctx.sessionId);
18128
+ } catch {
18129
+ }
18130
+ try {
18131
+ ctx.agent.kill();
18132
+ } catch {
18133
+ }
18134
+ try {
18135
+ const proc = (0, import_child_process15.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
17342
18136
  detached: true,
17343
18137
  stdio: "ignore"
17344
18138
  });
@@ -17360,7 +18154,7 @@ var shutdownSession = async (ctx, cmd) => {
17360
18154
  }
17361
18155
  if (ctx.keepAliveCtx.inCodespace && ctx.keepAliveCtx.codespaceName) {
17362
18156
  try {
17363
- const stopProc = (0, import_child_process12.spawn)(
18157
+ const stopProc = (0, import_child_process15.spawn)(
17364
18158
  "bash",
17365
18159
  ["-lc", `sleep 1; gh codespace stop -c ${JSON.stringify(ctx.keepAliveCtx.codespaceName)} >/dev/null 2>&1 || true`],
17366
18160
  { detached: true, stdio: "ignore" }
@@ -17370,7 +18164,7 @@ var shutdownSession = async (ctx, cmd) => {
17370
18164
  }
17371
18165
  }
17372
18166
  try {
17373
- const proc = (0, import_child_process12.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
18167
+ const proc = (0, import_child_process15.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
17374
18168
  detached: true,
17375
18169
  stdio: "ignore"
17376
18170
  });
@@ -17786,8 +18580,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
17786
18580
  if (args2.length === 0) return detection;
17787
18581
  const binName = args2[0];
17788
18582
  if (binName.startsWith("-")) return detection;
17789
- const binPath = path35.join(cwd, "node_modules", ".bin", binName);
17790
- if (!fs29.existsSync(binPath)) return detection;
18583
+ const binPath = path39.join(cwd, "node_modules", ".bin", binName);
18584
+ if (!fs32.existsSync(binPath)) return detection;
17791
18585
  return {
17792
18586
  ...detection,
17793
18587
  command: binPath,
@@ -17877,7 +18671,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
17877
18671
  "BOOT_SEQUENCE",
17878
18672
  `${spawnable.command} ${spawnable.args.join(" ")}`
17879
18673
  );
17880
- const devServer = (0, import_child_process12.spawn)(spawnable.command, spawnable.args, {
18674
+ const devServer = (0, import_child_process15.spawn)(spawnable.command, spawnable.args, {
17881
18675
  cwd: process.cwd(),
17882
18676
  env: { ...process.env, ...spawnable.env ?? {} },
17883
18677
  stdio: ["ignore", "pipe", "pipe"]
@@ -18003,7 +18797,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
18003
18797
  });
18004
18798
  return;
18005
18799
  }
18006
- tunnel = (0, import_child_process12.spawn)(bin, ["tunnel", "--url", `http://localhost:${detection.port}`], {
18800
+ tunnel = (0, import_child_process15.spawn)(bin, ["tunnel", "--url", `http://localhost:${detection.port}`], {
18007
18801
  stdio: ["ignore", "pipe", "pipe"]
18008
18802
  });
18009
18803
  let parsedUrl = null;
@@ -18100,8 +18894,8 @@ var previewStopH = (ctx) => {
18100
18894
  })();
18101
18895
  };
18102
18896
  function runOnce(cmd, args2, cwd, env) {
18103
- return new Promise((resolve6) => {
18104
- const child = (0, import_child_process12.spawn)(cmd, args2, {
18897
+ return new Promise((resolve7) => {
18898
+ const child = (0, import_child_process15.spawn)(cmd, args2, {
18105
18899
  cwd,
18106
18900
  env: { ...process.env, ...env ?? {} },
18107
18901
  stdio: ["ignore", "pipe", "pipe"]
@@ -18114,8 +18908,8 @@ function runOnce(cmd, args2, cwd, env) {
18114
18908
  };
18115
18909
  child.stdout?.on("data", onChunk);
18116
18910
  child.stderr?.on("data", onChunk);
18117
- child.once("exit", (code) => resolve6(code));
18118
- child.once("error", () => resolve6(-1));
18911
+ child.once("exit", (code) => resolve7(code));
18912
+ child.once("error", () => resolve7(-1));
18119
18913
  });
18120
18914
  }
18121
18915
  var savePreviewConfigH = (_ctx, _cmd, parsed) => {
@@ -18169,6 +18963,23 @@ var handlers = {
18169
18963
  save_preview_config: savePreviewConfigH
18170
18964
  };
18171
18965
  async function dispatchCommand(ctx, cmd) {
18966
+ if (cmd.type === "beads_action") {
18967
+ if (!ctx.beads) {
18968
+ log.trace("beads", "beads_action received but beads not running this session \u2014 dropping");
18969
+ return;
18970
+ }
18971
+ const action = beadsActionFromPayload(cmd.payload);
18972
+ if (!action) {
18973
+ log.warn("beads", "malformed beads_action payload \u2014 dropping");
18974
+ return;
18975
+ }
18976
+ try {
18977
+ await handleBeadsActionCommand(action, ctx.beads);
18978
+ } catch (err) {
18979
+ log.warn("beads", "handleBeadsActionCommand failed (non-fatal)", err);
18980
+ }
18981
+ return;
18982
+ }
18172
18983
  const parsed = parsePayload2(startCommandSchema, cmd.payload);
18173
18984
  if (!parsed) {
18174
18985
  showInfo(`Ignoring malformed ${cmd.type} payload.`);
@@ -18180,10 +18991,10 @@ async function dispatchCommand(ctx, cmd) {
18180
18991
  }
18181
18992
 
18182
18993
  // src/services/file-watcher.service.ts
18183
- var import_child_process13 = require("child_process");
18184
- var fs30 = __toESM(require("fs"));
18185
- var os25 = __toESM(require("os"));
18186
- var path36 = __toESM(require("path"));
18994
+ var import_child_process16 = require("child_process");
18995
+ var fs33 = __toESM(require("fs"));
18996
+ var os26 = __toESM(require("os"));
18997
+ var path40 = __toESM(require("path"));
18187
18998
  var import_ignore = __toESM(require("ignore"));
18188
18999
 
18189
19000
  // src/services/file-watcher/diff-parser.ts
@@ -18272,58 +19083,9 @@ function isIgnoredFilePath(filePath) {
18272
19083
  return IGNORED_PATH_PATTERN.test(filePath);
18273
19084
  }
18274
19085
 
18275
- // src/services/file-watcher/transport.ts
18276
- var http5 = __toESM(require("http"));
18277
- var https5 = __toESM(require("https"));
18278
- var _transport3 = {
18279
- post: _post2
18280
- };
18281
- function _post2(url, headers, payload) {
18282
- return new Promise((resolve6, reject) => {
18283
- let settled = false;
18284
- const u2 = new URL(url);
18285
- const lib = u2.protocol === "https:" ? https5 : http5;
18286
- const req = lib.request(
18287
- {
18288
- hostname: u2.hostname,
18289
- port: u2.port || (u2.protocol === "https:" ? 443 : 80),
18290
- path: u2.pathname + u2.search,
18291
- method: "POST",
18292
- headers: {
18293
- ...headers,
18294
- ...vercelBypassHeader(),
18295
- "Content-Length": Buffer.byteLength(payload)
18296
- },
18297
- timeout: 8e3
18298
- },
18299
- (res) => {
18300
- let body = "";
18301
- res.on("data", (c2) => {
18302
- body += c2.toString();
18303
- });
18304
- res.on("end", () => {
18305
- if (settled) return;
18306
- settled = true;
18307
- resolve6({ statusCode: res.statusCode ?? 0, body });
18308
- });
18309
- }
18310
- );
18311
- req.on("error", (err) => {
18312
- if (settled) return;
18313
- settled = true;
18314
- reject(err);
18315
- });
18316
- req.on("timeout", () => {
18317
- req.destroy();
18318
- });
18319
- req.write(payload);
18320
- req.end();
18321
- });
18322
- }
18323
-
18324
19086
  // src/services/file-watcher.service.ts
18325
- var API_BASE4 = resolveApiBaseUrl();
18326
- var DEBOUNCE_MS = 250;
19087
+ var API_BASE5 = resolveApiBaseUrl();
19088
+ var DEBOUNCE_MS2 = 250;
18327
19089
  var COALESCE_WINDOW_MS = 250;
18328
19090
  var COALESCE_MAX_HOLD_MS = 2e3;
18329
19091
  var MAX_RETRIES = 2;
@@ -18342,10 +19104,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
18342
19104
  /[\\/]Start Menu([\\/]|$)/i,
18343
19105
  /[\\/]Templates([\\/]|$)/i
18344
19106
  ];
18345
- function isUnsafeWindowsWatchRoot(dir, homedir21) {
19107
+ function isUnsafeWindowsWatchRoot(dir, homedir22) {
18346
19108
  const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
18347
19109
  const cwd = norm(dir);
18348
- const home = norm(homedir21);
19110
+ const home = norm(homedir22);
18349
19111
  if (cwd === home) return true;
18350
19112
  if (/^[a-z]:$/.test(cwd)) return true;
18351
19113
  const sysRoots = [
@@ -18359,7 +19121,7 @@ function isUnsafeWindowsWatchRoot(dir, homedir21) {
18359
19121
  }
18360
19122
  return false;
18361
19123
  }
18362
- var _chokidarSeam = {
19124
+ var _chokidarSeam2 = {
18363
19125
  load: () => {
18364
19126
  try {
18365
19127
  return require("chokidar");
@@ -18375,18 +19137,18 @@ var _findGitRootSeam = {
18375
19137
  resolve: _defaultFindGitRoot
18376
19138
  };
18377
19139
  function _defaultFindGitRoot(startDir) {
18378
- let dir = path36.resolve(startDir);
19140
+ let dir = path40.resolve(startDir);
18379
19141
  const seen = /* @__PURE__ */ new Set();
18380
19142
  for (let i = 0; i < 256; i++) {
18381
19143
  if (seen.has(dir)) return null;
18382
19144
  seen.add(dir);
18383
19145
  try {
18384
- const gitPath = path36.join(dir, ".git");
18385
- const stat3 = fs30.statSync(gitPath, { throwIfNoEntry: false });
19146
+ const gitPath = path40.join(dir, ".git");
19147
+ const stat3 = fs33.statSync(gitPath, { throwIfNoEntry: false });
18386
19148
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
18387
19149
  } catch {
18388
19150
  }
18389
- const parent = path36.dirname(dir);
19151
+ const parent = path40.dirname(dir);
18390
19152
  if (parent === dir) return null;
18391
19153
  dir = parent;
18392
19154
  }
@@ -18395,7 +19157,7 @@ function _defaultFindGitRoot(startDir) {
18395
19157
  var FileWatcherService = class {
18396
19158
  constructor(opts) {
18397
19159
  this.opts = opts;
18398
- this.apiBase = opts.apiBaseUrl ?? API_BASE4;
19160
+ this.apiBase = opts.apiBaseUrl ?? API_BASE5;
18399
19161
  }
18400
19162
  opts;
18401
19163
  watcher = null;
@@ -18444,14 +19206,14 @@ var FileWatcherService = class {
18444
19206
  throw new Error("FileWatcherService has already been stopped \u2014 re-instantiate to restart.");
18445
19207
  }
18446
19208
  const isWin = process.platform === "win32";
18447
- if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os25.homedir())) {
19209
+ if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os26.homedir())) {
18448
19210
  log.warn(
18449
19211
  "fileWatcher",
18450
19212
  `refusing to watch ${this.opts.workingDir} \u2014 looks like a Windows user-profile or system path. Run codeam from your project folder to enable file change emission.`
18451
19213
  );
18452
19214
  return;
18453
19215
  }
18454
- const chokidar2 = _chokidarSeam.load();
19216
+ const chokidar2 = _chokidarSeam2.load();
18455
19217
  if (!chokidar2) {
18456
19218
  log.warn(
18457
19219
  "fileWatcher",
@@ -18570,7 +19332,7 @@ var FileWatcherService = class {
18570
19332
  const timer = setTimeout(() => {
18571
19333
  this.pending.delete(absPath);
18572
19334
  this.enqueueForCoalesce(absPath, changeType);
18573
- }, DEBOUNCE_MS);
19335
+ }, DEBOUNCE_MS2);
18574
19336
  this.pending.set(absPath, {
18575
19337
  lastEventAt: Date.now(),
18576
19338
  timer,
@@ -18631,7 +19393,7 @@ var FileWatcherService = class {
18631
19393
  }
18632
19394
  async emitForFile(absPath, changeType) {
18633
19395
  if (this.stopped) return;
18634
- const fileDir = path36.dirname(absPath);
19396
+ const fileDir = path40.dirname(absPath);
18635
19397
  let gitRoot = this.gitRootByDir.get(fileDir);
18636
19398
  if (gitRoot === void 0) {
18637
19399
  gitRoot = findGitRoot2(fileDir);
@@ -18644,19 +19406,19 @@ var FileWatcherService = class {
18644
19406
  );
18645
19407
  return;
18646
19408
  }
18647
- const relPathInRepo = path36.relative(gitRoot, absPath);
19409
+ const relPathInRepo = path40.relative(gitRoot, absPath);
18648
19410
  if (!relPathInRepo || relPathInRepo.startsWith("..")) return;
18649
19411
  const matcher = this.getGitIgnoreMatcher(gitRoot);
18650
19412
  if (matcher && matcher.ignores(relPathInRepo)) {
18651
19413
  log.trace(
18652
19414
  "fileWatcher",
18653
- `${relPathInRepo} ignored by ${path36.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
19415
+ `${relPathInRepo} ignored by ${path40.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
18654
19416
  );
18655
19417
  return;
18656
19418
  }
18657
19419
  this.opts.onRepoDirty?.(gitRoot);
18658
- const repoPath = path36.relative(this.opts.workingDir, gitRoot);
18659
- const repoName = path36.basename(gitRoot);
19420
+ const repoPath = path40.relative(this.opts.workingDir, gitRoot);
19421
+ const repoName = path40.basename(gitRoot);
18660
19422
  let diffText = "";
18661
19423
  let fileStatus = "modified";
18662
19424
  if (changeType === "unlink") {
@@ -18831,7 +19593,7 @@ var FileWatcherService = class {
18831
19593
  collectGitignoreFiles(repoRoot, dir, matcher) {
18832
19594
  let entries;
18833
19595
  try {
18834
- entries = fs30.readdirSync(dir, { withFileTypes: true });
19596
+ entries = fs33.readdirSync(dir, { withFileTypes: true });
18835
19597
  } catch {
18836
19598
  return;
18837
19599
  }
@@ -18840,16 +19602,16 @@ var FileWatcherService = class {
18840
19602
  );
18841
19603
  if (gitignoreEntry) {
18842
19604
  try {
18843
- const body = fs30.readFileSync(path36.join(dir, ".gitignore"), "utf8");
18844
- const rel = path36.relative(repoRoot, dir).replace(/\\/g, "/");
19605
+ const body = fs33.readFileSync(path40.join(dir, ".gitignore"), "utf8");
19606
+ const rel = path40.relative(repoRoot, dir).replace(/\\/g, "/");
18845
19607
  const prefixed = body.split(/\r?\n/).map((line) => {
18846
19608
  const trimmed = line.trim();
18847
19609
  if (!trimmed || trimmed.startsWith("#")) return line;
18848
19610
  if (!rel) return line;
18849
19611
  if (trimmed.startsWith("!")) {
18850
- return "!" + path36.posix.join(rel, trimmed.slice(1));
19612
+ return "!" + path40.posix.join(rel, trimmed.slice(1));
18851
19613
  }
18852
- return path36.posix.join(rel, trimmed);
19614
+ return path40.posix.join(rel, trimmed);
18853
19615
  }).join("\n");
18854
19616
  matcher.add(prefixed);
18855
19617
  } catch {
@@ -18858,7 +19620,7 @@ var FileWatcherService = class {
18858
19620
  for (const entry of entries) {
18859
19621
  if (!entry.isDirectory()) continue;
18860
19622
  if (entry.name === ".git") continue;
18861
- const childAbs = path36.join(dir, entry.name);
19623
+ const childAbs = path40.join(dir, entry.name);
18862
19624
  if (isIgnoredFilePath(childAbs)) continue;
18863
19625
  this.collectGitignoreFiles(repoRoot, childAbs, matcher);
18864
19626
  }
@@ -18992,12 +19754,12 @@ var _gitSeam = {
18992
19754
  run: _runGitImpl
18993
19755
  };
18994
19756
  async function _runGitImpl(cwd, args2, opts = {}) {
18995
- return new Promise((resolve6) => {
19757
+ return new Promise((resolve7) => {
18996
19758
  let proc;
18997
19759
  try {
18998
- proc = (0, import_child_process13.spawn)("git", args2, { cwd, env: process.env });
19760
+ proc = (0, import_child_process16.spawn)("git", args2, { cwd, env: process.env });
18999
19761
  } catch {
19000
- resolve6(null);
19762
+ resolve7(null);
19001
19763
  return;
19002
19764
  }
19003
19765
  let stdout = "";
@@ -19008,13 +19770,13 @@ async function _runGitImpl(cwd, args2, opts = {}) {
19008
19770
  proc.stderr?.on("data", (c2) => {
19009
19771
  stderr += c2.toString();
19010
19772
  });
19011
- proc.on("error", () => resolve6(null));
19773
+ proc.on("error", () => resolve7(null));
19012
19774
  proc.on("close", (code) => {
19013
19775
  if (code === 0 || opts.allowNonZeroExit) {
19014
- resolve6(stdout);
19776
+ resolve7(stdout);
19015
19777
  } else {
19016
19778
  log.trace("fileWatcher", `git ${args2.join(" ")} exited ${code} stderr=${stderr.slice(0, 200)}`);
19017
- resolve6(null);
19779
+ resolve7(null);
19018
19780
  }
19019
19781
  });
19020
19782
  });
@@ -19027,8 +19789,8 @@ function _runGit(cwd, args2, opts = {}) {
19027
19789
  var import_crypto4 = require("crypto");
19028
19790
 
19029
19791
  // src/services/turn-files/git-changeset.ts
19030
- var import_child_process14 = require("child_process");
19031
- var path37 = __toESM(require("path"));
19792
+ var import_child_process17 = require("child_process");
19793
+ var path41 = __toESM(require("path"));
19032
19794
  async function collectRepoChangeset(opts) {
19033
19795
  const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
19034
19796
  if (status2 === null) return null;
@@ -19108,12 +19870,12 @@ function runGit3(cwd, args2) {
19108
19870
  return _runGitImpl2.run(cwd, args2);
19109
19871
  }
19110
19872
  function defaultRunGit(cwd, args2) {
19111
- return new Promise((resolve6) => {
19873
+ return new Promise((resolve7) => {
19112
19874
  let proc;
19113
19875
  try {
19114
- proc = (0, import_child_process14.spawn)("git", args2, { cwd, env: process.env });
19876
+ proc = (0, import_child_process17.spawn)("git", args2, { cwd, env: process.env });
19115
19877
  } catch {
19116
- resolve6(null);
19878
+ resolve7(null);
19117
19879
  return;
19118
19880
  }
19119
19881
  let stdout = "";
@@ -19124,22 +19886,22 @@ function defaultRunGit(cwd, args2) {
19124
19886
  proc.stderr?.on("data", (c2) => {
19125
19887
  stderr += c2.toString();
19126
19888
  });
19127
- proc.on("error", () => resolve6(null));
19889
+ proc.on("error", () => resolve7(null));
19128
19890
  proc.on("close", (code) => {
19129
19891
  if (code === 0) {
19130
- resolve6(stdout);
19892
+ resolve7(stdout);
19131
19893
  } else {
19132
19894
  log.trace(
19133
19895
  "turnFiles",
19134
19896
  `git ${args2.join(" ")} exited ${code} stderr=${stderr.slice(0, 200)}`
19135
19897
  );
19136
- resolve6(null);
19898
+ resolve7(null);
19137
19899
  }
19138
19900
  });
19139
19901
  });
19140
19902
  }
19141
19903
  async function discoverRepos(workingDir, maxDepth = 4) {
19142
- const fs36 = await import("fs/promises");
19904
+ const fs39 = await import("fs/promises");
19143
19905
  const out2 = [];
19144
19906
  await walk(workingDir, 0);
19145
19907
  return out2;
@@ -19147,7 +19909,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
19147
19909
  if (depth > maxDepth) return;
19148
19910
  let entries = [];
19149
19911
  try {
19150
- const dirents = await fs36.readdir(dir, { withFileTypes: true });
19912
+ const dirents = await fs39.readdir(dir, { withFileTypes: true });
19151
19913
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
19152
19914
  } catch {
19153
19915
  return;
@@ -19158,8 +19920,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
19158
19920
  if (hasGit) {
19159
19921
  out2.push({
19160
19922
  repoRoot: dir,
19161
- repoPath: path37.relative(workingDir, dir),
19162
- repoName: path37.basename(dir)
19923
+ repoPath: path41.relative(workingDir, dir),
19924
+ repoName: path41.basename(dir)
19163
19925
  });
19164
19926
  return;
19165
19927
  }
@@ -19167,14 +19929,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
19167
19929
  if (!entry.isDirectory) continue;
19168
19930
  if (entry.name === "node_modules") continue;
19169
19931
  if (entry.name === "dist" || entry.name === "build") continue;
19170
- await walk(path37.join(dir, entry.name), depth + 1);
19932
+ await walk(path41.join(dir, entry.name), depth + 1);
19171
19933
  }
19172
19934
  }
19173
19935
  }
19174
19936
 
19175
19937
  // src/services/turn-files/files-outbox.ts
19176
- var fs31 = __toESM(require("fs/promises"));
19177
- var path38 = __toESM(require("path"));
19938
+ var fs34 = __toESM(require("fs/promises"));
19939
+ var path42 = __toESM(require("path"));
19178
19940
  var import_os7 = require("os");
19179
19941
  var HOME_OUTBOX_DIR = ".codeam/outbox";
19180
19942
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -19207,16 +19969,16 @@ var FilesOutbox = class {
19207
19969
  backoffIndex = 0;
19208
19970
  stopped = false;
19209
19971
  constructor(opts) {
19210
- const base = opts.baseDir ?? path38.join(homeDir(), HOME_OUTBOX_DIR);
19211
- this.filePath = path38.join(base, `${opts.sessionId}.jsonl`);
19972
+ const base = opts.baseDir ?? path42.join(homeDir(), HOME_OUTBOX_DIR);
19973
+ this.filePath = path42.join(base, `${opts.sessionId}.jsonl`);
19212
19974
  this.post = opts.post;
19213
19975
  this.autoSchedule = opts.autoSchedule !== false;
19214
19976
  }
19215
19977
  /** Persist the entry to disk and trigger a flush. Returns once the
19216
19978
  * line is durable on disk (not once the POST succeeds). */
19217
19979
  async enqueue(entry) {
19218
- await fs31.mkdir(path38.dirname(this.filePath), { recursive: true });
19219
- await fs31.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
19980
+ await fs34.mkdir(path42.dirname(this.filePath), { recursive: true });
19981
+ await fs34.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
19220
19982
  this.backoffIndex = 0;
19221
19983
  if (this.autoSchedule) this.scheduleFlush(0);
19222
19984
  }
@@ -19305,7 +20067,7 @@ var FilesOutbox = class {
19305
20067
  async readAll() {
19306
20068
  let raw = "";
19307
20069
  try {
19308
- raw = await fs31.readFile(this.filePath, "utf8");
20070
+ raw = await fs34.readFile(this.filePath, "utf8");
19309
20071
  } catch {
19310
20072
  return [];
19311
20073
  }
@@ -19329,12 +20091,12 @@ var FilesOutbox = class {
19329
20091
  async rewrite(entries) {
19330
20092
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
19331
20093
  if (entries.length === 0) {
19332
- await fs31.unlink(this.filePath).catch(() => void 0);
20094
+ await fs34.unlink(this.filePath).catch(() => void 0);
19333
20095
  return;
19334
20096
  }
19335
20097
  const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
19336
- await fs31.writeFile(tmpPath, payload, "utf8");
19337
- await fs31.rename(tmpPath, this.filePath);
20098
+ await fs34.writeFile(tmpPath, payload, "utf8");
20099
+ await fs34.rename(tmpPath, this.filePath);
19338
20100
  }
19339
20101
  };
19340
20102
  function applyJitter(ms) {
@@ -19346,13 +20108,13 @@ function homeDir() {
19346
20108
  }
19347
20109
 
19348
20110
  // src/services/turn-files/turn-file-aggregator.ts
19349
- var API_BASE5 = resolveApiBaseUrl();
20111
+ var API_BASE6 = resolveApiBaseUrl();
19350
20112
  var ENDPOINT = "/api/files/batch";
19351
20113
  var MAX_BATCH_SIZE = 1e3;
19352
20114
  var TurnFileAggregator = class {
19353
20115
  constructor(opts) {
19354
20116
  this.opts = opts;
19355
- this.apiBase = opts.apiBaseUrl ?? API_BASE5;
20117
+ this.apiBase = opts.apiBaseUrl ?? API_BASE6;
19356
20118
  this.outbox = new FilesOutbox({
19357
20119
  sessionId: opts.sessionId,
19358
20120
  baseDir: opts.outboxDir,
@@ -19544,7 +20306,7 @@ var StreamingState = class {
19544
20306
  * default-reject. Caller is the SDK's `onRequestPermission`.
19545
20307
  */
19546
20308
  registerPermission(args2) {
19547
- return new Promise((resolve6) => {
20309
+ return new Promise((resolve7) => {
19548
20310
  const timeoutTimer = setTimeout(() => {
19549
20311
  if (this.pending?.kind === "permission" && this.pending.questionId === args2.questionId) {
19550
20312
  log.warn(
@@ -19552,7 +20314,7 @@ var StreamingState = class {
19552
20314
  `permission ${args2.questionId.slice(0, 8)} TTL expired \u2014 auto-cancel`
19553
20315
  );
19554
20316
  this.pending = null;
19555
- resolve6({ outcome: { outcome: "cancelled" } });
20317
+ resolve7({ outcome: { outcome: "cancelled" } });
19556
20318
  }
19557
20319
  }, PERMISSION_TIMEOUT_MS);
19558
20320
  this.pending = {
@@ -19560,7 +20322,7 @@ var StreamingState = class {
19560
20322
  questionId: args2.questionId,
19561
20323
  labels: args2.labels,
19562
20324
  optionIdByLabel: args2.optionIdByLabel,
19563
- resolve: resolve6,
20325
+ resolve: resolve7,
19564
20326
  timeoutTimer
19565
20327
  };
19566
20328
  });
@@ -19592,14 +20354,14 @@ var StreamingState = class {
19592
20354
  const label = this.pending.labels[index];
19593
20355
  const optionId = label ? this.pending.optionIdByLabel[label] : void 0;
19594
20356
  clearTimeout(this.pending.timeoutTimer);
19595
- const resolve6 = this.pending.resolve;
20357
+ const resolve7 = this.pending.resolve;
19596
20358
  this.pending = null;
19597
20359
  if (!optionId) {
19598
20360
  log.warn("acpRunner", `select_option index=${index} out of bounds \u2014 cancel`);
19599
- resolve6({ outcome: { outcome: "cancelled" } });
20361
+ resolve7({ outcome: { outcome: "cancelled" } });
19600
20362
  return { kind: "resolved" };
19601
20363
  }
19602
- resolve6({ outcome: { outcome: "selected", optionId } });
20364
+ resolve7({ outcome: { outcome: "selected", optionId } });
19603
20365
  return { kind: "resolved" };
19604
20366
  }
19605
20367
  const text = this.pending.options[index];
@@ -19955,6 +20717,7 @@ async function runAcpSession(opts) {
19955
20717
  }).catch((err) => {
19956
20718
  log.warn("acpRunner", `fileWatcher.start failed: ${describeError(err)}`);
19957
20719
  });
20720
+ const getBeads = opts.getBeads ?? (() => null);
19958
20721
  const relay = new CommandRelayService(
19959
20722
  opts.pluginId,
19960
20723
  async (cmd) => {
@@ -19968,7 +20731,8 @@ async function runAcpSession(opts) {
19968
20731
  opts,
19969
20732
  history,
19970
20733
  initialize.agentCapabilities,
19971
- turnFiles
20734
+ turnFiles,
20735
+ getBeads
19972
20736
  );
19973
20737
  },
19974
20738
  { id: opts.agent, name: opts.agent, displayName: opts.agent }
@@ -19989,8 +20753,24 @@ async function runAcpSession(opts) {
19989
20753
  await new Promise(() => {
19990
20754
  });
19991
20755
  }
19992
- async function handleCommand(cmd, client2, relay, acpSessionId, models, streaming, opts, history, agentCaps, turnFiles) {
20756
+ async function handleCommand(cmd, client2, relay, acpSessionId, models, streaming, opts, history, agentCaps, turnFiles, getBeads) {
19993
20757
  switch (cmd.type) {
20758
+ case "beads_action": {
20759
+ const beads = getBeads();
20760
+ const action = beadsActionFromPayload(cmd.payload);
20761
+ if (!beads || !action) {
20762
+ await relay.sendResult(cmd.id, "completed", { applied: false });
20763
+ return;
20764
+ }
20765
+ try {
20766
+ await handleBeadsActionCommand(action, beads);
20767
+ await relay.sendResult(cmd.id, "completed", { applied: true });
20768
+ } catch (err) {
20769
+ log.warn("acpRunner", `beads_action failed (non-fatal): ${describeError(err)}`);
20770
+ await relay.sendResult(cmd.id, "failed", { error: describeError(err) });
20771
+ }
20772
+ return;
20773
+ }
19994
20774
  case "start_task": {
19995
20775
  const payload = cmd.payload;
19996
20776
  const blocks = buildAcpPromptBlocks(payload ?? {});
@@ -20349,11 +21129,11 @@ var ChromeStepTracker = class {
20349
21129
  // src/services/output/chunk-emitter.ts
20350
21130
  var https6 = __toESM(require("https"));
20351
21131
  var http6 = __toESM(require("http"));
20352
- var API_BASE6 = resolveApiBaseUrl();
21132
+ var API_BASE7 = resolveApiBaseUrl();
20353
21133
  async function refreshAuthToken(sessionId, pluginId) {
20354
21134
  try {
20355
21135
  const { statusCode, body } = await _transport4.post(
20356
- `${API_BASE6}/api/pairing/reconnect`,
21136
+ `${API_BASE7}/api/pairing/reconnect`,
20357
21137
  {
20358
21138
  "Content-Type": "application/json",
20359
21139
  "X-Codeam-Protocol-Version": PROTOCOL_VERSION,
@@ -20394,7 +21174,7 @@ var ChunkEmitter = class {
20394
21174
  }
20395
21175
  }
20396
21176
  opts;
20397
- url = `${API_BASE6}/api/commands/output`;
21177
+ url = `${API_BASE7}/api/commands/output`;
20398
21178
  headers;
20399
21179
  /**
20400
21180
  * Send a chunk. `body` is the chunk fields minus `sessionId` /
@@ -20415,14 +21195,14 @@ var ChunkEmitter = class {
20415
21195
  "chunkEmitter",
20416
21196
  `send type=${body.type ?? "(clear)"} bytes=${payload.length} done=${body.done === true}`
20417
21197
  );
20418
- return new Promise((resolve6) => {
21198
+ return new Promise((resolve7) => {
20419
21199
  const attempt = (attemptsLeft) => {
20420
21200
  _transport4.post(this.url, this.headers, payload).then(({ statusCode, body: resBody }) => {
20421
21201
  const tookMs = Date.now() - t0;
20422
21202
  if (statusCode === 410 || statusCode === 404 && /SESSION_NOT_FOUND|SESSION_GONE/.test(resBody)) {
20423
21203
  process.stderr.write("[codeam] session was deleted/disconnected \u2014 stopping output stream.\n");
20424
21204
  log.info("chunkEmitter", `dead status=${statusCode} took=${tookMs}ms`);
20425
- resolve6({ dead: true });
21205
+ resolve7({ dead: true });
20426
21206
  return;
20427
21207
  }
20428
21208
  if (statusCode === 401) {
@@ -20438,7 +21218,7 @@ var ChunkEmitter = class {
20438
21218
  return;
20439
21219
  }
20440
21220
  }
20441
- resolve6({ dead: false });
21221
+ resolve7({ dead: false });
20442
21222
  })();
20443
21223
  return;
20444
21224
  }
@@ -20449,7 +21229,7 @@ var ChunkEmitter = class {
20449
21229
  } else {
20450
21230
  log.info("chunkEmitter", `ok status=${statusCode} took=${tookMs}ms`);
20451
21231
  }
20452
- resolve6({ dead: false });
21232
+ resolve7({ dead: false });
20453
21233
  }).catch((err) => {
20454
21234
  log.warn(
20455
21235
  "chunkEmitter",
@@ -20460,7 +21240,7 @@ var ChunkEmitter = class {
20460
21240
  const delay = 200 * (maxRetries - attemptsLeft + 1);
20461
21241
  setTimeout(() => attempt(attemptsLeft - 1), delay);
20462
21242
  } else {
20463
- resolve6({ dead: false });
21243
+ resolve7({ dead: false });
20464
21244
  }
20465
21245
  });
20466
21246
  };
@@ -20472,7 +21252,7 @@ var _transport4 = {
20472
21252
  post: _post3
20473
21253
  };
20474
21254
  function _post3(url, headers, payload) {
20475
- return new Promise((resolve6, reject) => {
21255
+ return new Promise((resolve7, reject) => {
20476
21256
  let settled = false;
20477
21257
  const u2 = new URL(url);
20478
21258
  const transport = u2.protocol === "https:" ? https6 : http6;
@@ -20496,7 +21276,7 @@ function _post3(url, headers, payload) {
20496
21276
  res.on("end", () => {
20497
21277
  if (settled) return;
20498
21278
  settled = true;
20499
- resolve6({ statusCode: res.statusCode ?? 0, body: resData });
21279
+ resolve7({ statusCode: res.statusCode ?? 0, body: resData });
20500
21280
  });
20501
21281
  }
20502
21282
  );
@@ -21070,9 +21850,9 @@ var OutputService = class _OutputService {
21070
21850
  };
21071
21851
 
21072
21852
  // src/services/history.service.ts
21073
- var fs32 = __toESM(require("fs"));
21074
- var path39 = __toESM(require("path"));
21075
- var os26 = __toESM(require("os"));
21853
+ var fs35 = __toESM(require("fs"));
21854
+ var path43 = __toESM(require("path"));
21855
+ var os27 = __toESM(require("os"));
21076
21856
  var https7 = __toESM(require("https"));
21077
21857
  var http7 = __toESM(require("http"));
21078
21858
  var import_zod2 = require("zod");
@@ -21086,7 +21866,7 @@ var historyRecordSchema = import_zod2.z.object({
21086
21866
  content: import_zod2.z.union([import_zod2.z.string(), import_zod2.z.array(import_zod2.z.unknown())]).optional()
21087
21867
  }).passthrough().optional()
21088
21868
  }).passthrough();
21089
- var API_BASE7 = resolveApiBaseUrl();
21869
+ var API_BASE8 = resolveApiBaseUrl();
21090
21870
  function extractText3(content) {
21091
21871
  if (typeof content === "string") return content;
21092
21872
  if (Array.isArray(content)) {
@@ -21099,7 +21879,7 @@ function parseJsonl(filePath) {
21099
21879
  const messages = [];
21100
21880
  let raw;
21101
21881
  try {
21102
- raw = fs32.readFileSync(filePath, "utf8");
21882
+ raw = fs35.readFileSync(filePath, "utf8");
21103
21883
  } catch (err) {
21104
21884
  if (err.code !== "ENOENT") {
21105
21885
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -21136,9 +21916,9 @@ function parseJsonl(filePath) {
21136
21916
  return messages;
21137
21917
  }
21138
21918
  function post(endpoint, body) {
21139
- return new Promise((resolve6) => {
21919
+ return new Promise((resolve7) => {
21140
21920
  const payload = JSON.stringify(body);
21141
- const u2 = new URL(`${API_BASE7}${endpoint}`);
21921
+ const u2 = new URL(`${API_BASE8}${endpoint}`);
21142
21922
  const transport = u2.protocol === "https:" ? https7 : http7;
21143
21923
  const req = transport.request(
21144
21924
  {
@@ -21157,17 +21937,17 @@ function post(endpoint, body) {
21157
21937
  res.resume();
21158
21938
  const ok = res.statusCode !== void 0 && res.statusCode >= 200 && res.statusCode < 300;
21159
21939
  if (!ok) log.warn("history:post", `${endpoint} \u2192 HTTP ${res.statusCode}`);
21160
- resolve6(ok);
21940
+ resolve7(ok);
21161
21941
  }
21162
21942
  );
21163
21943
  req.on("error", (err) => {
21164
21944
  log.warn("history:post", `${endpoint} network error`, err);
21165
- resolve6(false);
21945
+ resolve7(false);
21166
21946
  });
21167
21947
  req.on("timeout", () => {
21168
21948
  log.warn("history:post", `${endpoint} timeout after 15s`);
21169
21949
  req.destroy();
21170
- resolve6(false);
21950
+ resolve7(false);
21171
21951
  });
21172
21952
  req.write(payload);
21173
21953
  req.end();
@@ -21234,7 +22014,7 @@ var HistoryService = class _HistoryService {
21234
22014
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
21235
22015
  }
21236
22016
  get projectDir() {
21237
- return this.runtime.resolveHistoryDir(this.cwd) ?? path39.join(os26.homedir(), ".claude", "projects", encodeCwd(this.cwd));
22017
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path43.join(os27.homedir(), ".claude", "projects", encodeCwd(this.cwd));
21238
22018
  }
21239
22019
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
21240
22020
  setCurrentConversationId(id) {
@@ -21246,7 +22026,7 @@ var HistoryService = class _HistoryService {
21246
22026
  /** Return the current message count in the active conversation. */
21247
22027
  getCurrentMessageCount() {
21248
22028
  if (!this.currentConversationId) return 0;
21249
- const filePath = path39.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22029
+ const filePath = path43.join(this.projectDir, `${this.currentConversationId}.jsonl`);
21250
22030
  return parseJsonl(filePath).length;
21251
22031
  }
21252
22032
  /**
@@ -21257,7 +22037,7 @@ var HistoryService = class _HistoryService {
21257
22037
  const deadline = Date.now() + timeoutMs;
21258
22038
  while (Date.now() < deadline) {
21259
22039
  if (!this.currentConversationId) return null;
21260
- const filePath = path39.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22040
+ const filePath = path43.join(this.projectDir, `${this.currentConversationId}.jsonl`);
21261
22041
  const messages = parseJsonl(filePath);
21262
22042
  if (messages.length > previousCount) {
21263
22043
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -21283,16 +22063,16 @@ var HistoryService = class _HistoryService {
21283
22063
  const dir = this.projectDir;
21284
22064
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
21285
22065
  try {
21286
- const files = fs32.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
22066
+ const files = fs35.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
21287
22067
  try {
21288
- const stat3 = fs32.statSync(path39.join(dir, e.name));
22068
+ const stat3 = fs35.statSync(path43.join(dir, e.name));
21289
22069
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
21290
22070
  } catch {
21291
22071
  return { name: e.name, mtime: 0, birthtime: 0 };
21292
22072
  }
21293
22073
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
21294
22074
  if (files.length > 0) {
21295
- this.currentConversationId = path39.basename(files[0].name, ".jsonl");
22075
+ this.currentConversationId = path43.basename(files[0].name, ".jsonl");
21296
22076
  }
21297
22077
  } catch {
21298
22078
  }
@@ -21326,13 +22106,13 @@ var HistoryService = class _HistoryService {
21326
22106
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
21327
22107
  let entries;
21328
22108
  try {
21329
- entries = fs32.readdirSync(dir, { withFileTypes: true });
22109
+ entries = fs35.readdirSync(dir, { withFileTypes: true });
21330
22110
  } catch {
21331
22111
  return null;
21332
22112
  }
21333
22113
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
21334
22114
  try {
21335
- const stat3 = fs32.statSync(path39.join(dir, e.name));
22115
+ const stat3 = fs35.statSync(path43.join(dir, e.name));
21336
22116
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
21337
22117
  } catch {
21338
22118
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -21341,12 +22121,12 @@ var HistoryService = class _HistoryService {
21341
22121
  if (files.length === 0) return null;
21342
22122
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
21343
22123
  if (!files.some((f) => f.name === targetFile)) return null;
21344
- return this.extractUsageFromFile(path39.join(dir, targetFile));
22124
+ return this.extractUsageFromFile(path43.join(dir, targetFile));
21345
22125
  }
21346
22126
  extractUsageFromFile(filePath) {
21347
22127
  let raw;
21348
22128
  try {
21349
- raw = fs32.readFileSync(filePath, "utf8");
22129
+ raw = fs35.readFileSync(filePath, "utf8");
21350
22130
  } catch {
21351
22131
  return null;
21352
22132
  }
@@ -21391,9 +22171,9 @@ var HistoryService = class _HistoryService {
21391
22171
  let totalCost = 0;
21392
22172
  let files;
21393
22173
  try {
21394
- files = fs32.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
22174
+ files = fs35.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
21395
22175
  try {
21396
- return fs32.statSync(path39.join(projectDir, f)).mtimeMs >= monthStartMs;
22176
+ return fs35.statSync(path43.join(projectDir, f)).mtimeMs >= monthStartMs;
21397
22177
  } catch {
21398
22178
  return false;
21399
22179
  }
@@ -21404,7 +22184,7 @@ var HistoryService = class _HistoryService {
21404
22184
  for (const file of files) {
21405
22185
  let raw;
21406
22186
  try {
21407
- raw = fs32.readFileSync(path39.join(projectDir, file), "utf8");
22187
+ raw = fs35.readFileSync(path43.join(projectDir, file), "utf8");
21408
22188
  } catch {
21409
22189
  continue;
21410
22190
  }
@@ -21468,7 +22248,7 @@ var HistoryService = class _HistoryService {
21468
22248
  * showing an empty conversation.
21469
22249
  */
21470
22250
  async loadConversation(sessionId) {
21471
- const filePath = path39.join(this.projectDir, `${sessionId}.jsonl`);
22251
+ const filePath = path43.join(this.projectDir, `${sessionId}.jsonl`);
21472
22252
  const messages = parseJsonl(filePath);
21473
22253
  if (messages.length === 0) return;
21474
22254
  const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
@@ -21522,7 +22302,7 @@ var HistoryService = class _HistoryService {
21522
22302
  if (!this.currentConversationId) return 0;
21523
22303
  }
21524
22304
  const sessionId = this.currentConversationId;
21525
- const filePath = path39.join(this.projectDir, `${sessionId}.jsonl`);
22305
+ const filePath = path43.join(this.projectDir, `${sessionId}.jsonl`);
21526
22306
  const messages = parseJsonl(filePath);
21527
22307
  if (messages.length === 0) return 0;
21528
22308
  const marker = this.lastUploadedUuid.get(sessionId);
@@ -21587,7 +22367,7 @@ var RepoDirtyTracker = class {
21587
22367
 
21588
22368
  // src/services/streaming-emitter.service.ts
21589
22369
  var import_crypto5 = require("crypto");
21590
- var API_BASE8 = resolveApiBaseUrl();
22370
+ var API_BASE9 = resolveApiBaseUrl();
21591
22371
  var TICK_MS = 50;
21592
22372
  var ANSWER_POLL_MS = 1500;
21593
22373
  var SELECTOR_STABLE_MS = 800;
@@ -21598,7 +22378,7 @@ var TAIL_KEEP_BYTES2 = 1.5 * 1024 * 1024;
21598
22378
  var StreamingEmitterService = class {
21599
22379
  constructor(opts) {
21600
22380
  this.opts = opts;
21601
- this.apiBase = opts.apiBaseUrl ?? API_BASE8;
22381
+ this.apiBase = opts.apiBaseUrl ?? API_BASE9;
21602
22382
  this.headers = {
21603
22383
  "Content-Type": "application/json",
21604
22384
  "X-Codeam-Protocol-Version": "2.0.0",
@@ -21948,13 +22728,13 @@ function fetchQuotaUsage(runtime, historySvc) {
21948
22728
  }
21949
22729
 
21950
22730
  // src/commands/start/keep-alive.ts
21951
- var import_child_process15 = require("child_process");
22731
+ var import_child_process18 = require("child_process");
21952
22732
  function buildKeepAlive(ctx) {
21953
22733
  let timer = null;
21954
22734
  async function setIdleTimeout(minutes) {
21955
22735
  if (!ctx.inCodespace || !ctx.codespaceName) return;
21956
- await new Promise((resolve6) => {
21957
- const proc = (0, import_child_process15.spawn)(
22736
+ await new Promise((resolve7) => {
22737
+ const proc = (0, import_child_process18.spawn)(
21958
22738
  "gh",
21959
22739
  [
21960
22740
  "api",
@@ -21967,8 +22747,8 @@ function buildKeepAlive(ctx) {
21967
22747
  { stdio: "ignore", detached: true }
21968
22748
  );
21969
22749
  proc.unref();
21970
- proc.on("exit", () => resolve6());
21971
- proc.on("error", () => resolve6());
22750
+ proc.on("exit", () => resolve7());
22751
+ proc.on("error", () => resolve7());
21972
22752
  });
21973
22753
  }
21974
22754
  return {
@@ -22044,6 +22824,20 @@ async function start(requestedAgent) {
22044
22824
  "pluginAuth",
22045
22825
  `boot triple sessionId=${session.id} pluginId=${pluginId} tokenLen=${tokenForLog.length} tokenHead=${tokenForLog.slice(0, 12)} tokenTail=${tokenForLog.slice(-8)} mintedEqualsCached=${refreshed === session.pluginAuthToken}`
22046
22826
  );
22827
+ let beads = null;
22828
+ const getBeads = () => beads;
22829
+ const beadsReady = provisionBeadsForStart({
22830
+ sessionId: session.id,
22831
+ pluginId,
22832
+ pluginAuthToken: session.pluginAuthToken ?? void 0,
22833
+ cwd,
22834
+ // Wire this session's agent natively via `bd setup <recipe> --global` so
22835
+ // the agent actually uses bd (D12 — REVISED). Covers BOTH ACP and PTY.
22836
+ agents: [session.agent]
22837
+ }).then((started) => {
22838
+ beads = started;
22839
+ return started;
22840
+ });
22047
22841
  const acpDisabled = process.env.CODEAM_ACP_DISABLED === "1";
22048
22842
  if (!acpDisabled && session.pluginAuthToken) {
22049
22843
  const adapter = getAcpAdapter(session.agent);
@@ -22054,7 +22848,8 @@ async function start(requestedAgent) {
22054
22848
  pluginId,
22055
22849
  pluginAuthToken: session.pluginAuthToken,
22056
22850
  adapter,
22057
- cwd
22851
+ cwd,
22852
+ getBeads
22058
22853
  });
22059
22854
  return;
22060
22855
  }
@@ -22132,6 +22927,7 @@ async function start(requestedAgent) {
22132
22927
  relay.stop();
22133
22928
  void fileWatcher?.stop();
22134
22929
  turnFiles?.stop();
22930
+ void beads?.watcher.stop();
22135
22931
  void streamingEmitter?.stop();
22136
22932
  closeAllTerminals();
22137
22933
  cleanupAttachmentTempFiles();
@@ -22165,6 +22961,9 @@ async function start(requestedAgent) {
22165
22961
  await dispatchCommand(ctx, cmd);
22166
22962
  }, runtime.meta);
22167
22963
  ctx.relay = relay;
22964
+ void beadsReady.then((started) => {
22965
+ ctx.beads = started;
22966
+ });
22168
22967
  registerTerminalHandlers({
22169
22968
  onData: ({ sessionId, data }) => {
22170
22969
  void outputSvc.sendTerminalChunk(sessionId, data);
@@ -22181,6 +22980,7 @@ async function start(requestedAgent) {
22181
22980
  outputSvc.dispose();
22182
22981
  relay.stop();
22183
22982
  void fileWatcher?.stop();
22983
+ void beads?.watcher.stop();
22184
22984
  void streamingEmitter?.stop();
22185
22985
  closeAllTerminals();
22186
22986
  cleanupAttachmentTempFiles();
@@ -22319,7 +23119,7 @@ async function pair(args2 = []) {
22319
23119
  waitSpin.message(waitMessage());
22320
23120
  }, 1e3);
22321
23121
  countdownInterval.unref?.();
22322
- await new Promise((resolve6) => {
23122
+ await new Promise((resolve7) => {
22323
23123
  let stopPolling = null;
22324
23124
  function sigintHandler() {
22325
23125
  clearInterval(countdownInterval);
@@ -22367,7 +23167,7 @@ async function pair(args2 = []) {
22367
23167
  pluginAuthToken: info.pluginAuthToken
22368
23168
  });
22369
23169
  }
22370
- resolve6();
23170
+ resolve7();
22371
23171
  },
22372
23172
  () => {
22373
23173
  clearInterval(countdownInterval);
@@ -22419,8 +23219,8 @@ async function autoLinkAfterPair(opts) {
22419
23219
  }
22420
23220
 
22421
23221
  // src/commands/pair-auto.ts
22422
- var fs33 = __toESM(require("fs"));
22423
- var os27 = __toESM(require("os"));
23222
+ var fs36 = __toESM(require("fs"));
23223
+ var os28 = __toESM(require("os"));
22424
23224
  var import_crypto7 = require("crypto");
22425
23225
 
22426
23226
  // src/commands/start-infra-only.ts
@@ -22480,6 +23280,15 @@ async function startInfraOnly(agentId) {
22480
23280
  pluginId,
22481
23281
  pluginAuthToken: session.pluginAuthToken
22482
23282
  }) : null;
23283
+ let beads = null;
23284
+ void provisionBeadsForStart({
23285
+ sessionId: session.id,
23286
+ pluginId,
23287
+ pluginAuthToken: session.pluginAuthToken ?? void 0,
23288
+ cwd
23289
+ }).then((started) => {
23290
+ beads = started;
23291
+ });
22483
23292
  let relayRef = null;
22484
23293
  const ctx = {
22485
23294
  // Agent-touching fields are not used by any of the commands
@@ -22501,6 +23310,23 @@ async function startInfraOnly(agentId) {
22501
23310
  const relay = new CommandRelayService(
22502
23311
  pluginId,
22503
23312
  async (cmd) => {
23313
+ if (cmd.type === "beads_action") {
23314
+ if (!beads) {
23315
+ log.trace("infra-only", "beads_action received but beads not running \u2014 dropping");
23316
+ return;
23317
+ }
23318
+ const action = beadsActionFromPayload(cmd.payload);
23319
+ if (!action) {
23320
+ log.warn("infra-only", "malformed beads_action payload \u2014 dropping");
23321
+ return;
23322
+ }
23323
+ try {
23324
+ await handleBeadsActionCommand(action, beads);
23325
+ } catch (err) {
23326
+ log.warn("infra-only", "handleBeadsActionCommand failed (non-fatal)", err);
23327
+ }
23328
+ return;
23329
+ }
22504
23330
  if (!INFRA_ONLY_COMMAND_TYPES.has(cmd.type)) {
22505
23331
  log.trace("infra-only", `dropping agent-only command type=${cmd.type}`);
22506
23332
  return;
@@ -22561,6 +23387,7 @@ async function startInfraOnly(agentId) {
22561
23387
  } catch {
22562
23388
  }
22563
23389
  void fileWatcher?.stop();
23390
+ void beads?.watcher.stop();
22564
23391
  closeAllTerminals();
22565
23392
  cleanupAttachmentTempFiles();
22566
23393
  process.exit(0);
@@ -22573,7 +23400,7 @@ async function startInfraOnly(agentId) {
22573
23400
  }
22574
23401
 
22575
23402
  // src/commands/pair-auto.ts
22576
- var API_BASE9 = resolveApiBaseUrl();
23403
+ var API_BASE10 = resolveApiBaseUrl();
22577
23404
  function fail(msg) {
22578
23405
  console.error(`
22579
23406
  ${msg}
@@ -22588,12 +23415,12 @@ function readTokenFromArgs(args2) {
22588
23415
  }
22589
23416
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
22590
23417
  if (fileFlag) {
22591
- const path46 = fileFlag.slice("--token-file=".length);
23418
+ const path50 = fileFlag.slice("--token-file=".length);
22592
23419
  try {
22593
- const content = fs33.readFileSync(path46, "utf8").trim();
22594
- if (content.length === 0) fail(`--token-file ${path46} is empty`);
23420
+ const content = fs36.readFileSync(path50, "utf8").trim();
23421
+ if (content.length === 0) fail(`--token-file ${path50} is empty`);
22595
23422
  try {
22596
- fs33.unlinkSync(path46);
23423
+ fs36.unlinkSync(path50);
22597
23424
  } catch {
22598
23425
  }
22599
23426
  return content;
@@ -22613,13 +23440,13 @@ function networkError(msg, cause) {
22613
23440
  return err;
22614
23441
  }
22615
23442
  async function claimOnce(token, pluginId) {
22616
- const url = `${API_BASE9}/api/pairing/claim-auto-token`;
23443
+ const url = `${API_BASE10}/api/pairing/claim-auto-token`;
22617
23444
  const body = {
22618
23445
  token,
22619
23446
  pluginId,
22620
23447
  ideName: "codeam-cli (codespace)",
22621
23448
  ideVersion: process.env.npm_package_version ?? "unknown",
22622
- hostname: os27.hostname(),
23449
+ hostname: os28.hostname(),
22623
23450
  codespaceName: process.env.CODESPACE_NAME ?? "",
22624
23451
  // Current git branch of the codespace's working directory, so the
22625
23452
  // backend can populate `PairedSession.branch` for the codespace pair.
@@ -22816,7 +23643,7 @@ function status() {
22816
23643
 
22817
23644
  // src/commands/logout.ts
22818
23645
  var import_picocolors7 = __toESM(require("picocolors"));
22819
- var API_BASE10 = resolveApiBaseUrl();
23646
+ var API_BASE11 = resolveApiBaseUrl();
22820
23647
  async function notifyBackendOffline() {
22821
23648
  const cfg = loadCliConfig();
22822
23649
  const pluginIds = /* @__PURE__ */ new Set([
@@ -22828,7 +23655,7 @@ async function notifyBackendOffline() {
22828
23655
  try {
22829
23656
  await Promise.all(
22830
23657
  Array.from(pluginIds).map(
22831
- (pluginId) => _postJson(`${API_BASE10}/api/plugin/heartbeat`, {
23658
+ (pluginId) => _postJson(`${API_BASE11}/api/plugin/heartbeat`, {
22832
23659
  pluginId,
22833
23660
  online: false
22834
23661
  }).catch((err) => {
@@ -22856,11 +23683,11 @@ async function logout() {
22856
23683
  var import_picocolors10 = __toESM(require("picocolors"));
22857
23684
 
22858
23685
  // src/services/providers/github-codespaces.ts
22859
- var import_child_process16 = require("child_process");
23686
+ var import_child_process19 = require("child_process");
22860
23687
  var import_util4 = require("util");
22861
23688
  var import_picocolors8 = __toESM(require("picocolors"));
22862
- var path40 = __toESM(require("path"));
22863
- var execFileP5 = (0, import_util4.promisify)(import_child_process16.execFile);
23689
+ var path44 = __toESM(require("path"));
23690
+ var execFileP5 = (0, import_util4.promisify)(import_child_process19.execFile);
22864
23691
  var MAX_BUFFER = 8 * 1024 * 1024;
22865
23692
  function resetStdinForChild() {
22866
23693
  if (process.stdin.isTTY) {
@@ -22903,12 +23730,12 @@ var GitHubCodespacesProvider = class {
22903
23730
  }
22904
23731
  if (!isAuthed) {
22905
23732
  resetStdinForChild();
22906
- await new Promise((resolve6, reject) => {
22907
- const proc = (0, import_child_process16.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
23733
+ await new Promise((resolve7, reject) => {
23734
+ const proc = (0, import_child_process19.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
22908
23735
  stdio: "inherit"
22909
23736
  });
22910
23737
  proc.on("exit", (code) => {
22911
- if (code === 0) resolve6();
23738
+ if (code === 0) resolve7();
22912
23739
  else reject(new Error("gh auth login failed."));
22913
23740
  });
22914
23741
  proc.on("error", reject);
@@ -22937,13 +23764,13 @@ var GitHubCodespacesProvider = class {
22937
23764
  }
22938
23765
  wt(noteLines.join("\n"), "One more permission needed");
22939
23766
  resetStdinForChild();
22940
- const refreshCode = await new Promise((resolve6, reject) => {
22941
- const proc = (0, import_child_process16.spawn)(
23767
+ const refreshCode = await new Promise((resolve7, reject) => {
23768
+ const proc = (0, import_child_process19.spawn)(
22942
23769
  "gh",
22943
23770
  ["auth", "refresh", "-h", "github.com", "-s", "codespace"],
22944
23771
  { stdio: "inherit" }
22945
23772
  );
22946
- proc.on("exit", (code) => resolve6(code ?? 1));
23773
+ proc.on("exit", (code) => resolve7(code ?? 1));
22947
23774
  proc.on("error", reject);
22948
23775
  });
22949
23776
  if (refreshCode !== 0) {
@@ -23087,10 +23914,10 @@ var GitHubCodespacesProvider = class {
23087
23914
  if (q(proceed) || !proceed) return;
23088
23915
  O2.step(`Installing gh via ${installCmd.describe}\u2026`);
23089
23916
  resetStdinForChild();
23090
- const ok = await new Promise((resolve6) => {
23091
- const proc = (0, import_child_process16.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
23092
- proc.on("exit", (code) => resolve6(code === 0));
23093
- proc.on("error", () => resolve6(false));
23917
+ const ok = await new Promise((resolve7) => {
23918
+ const proc = (0, import_child_process19.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
23919
+ proc.on("exit", (code) => resolve7(code === 0));
23920
+ proc.on("error", () => resolve7(false));
23094
23921
  });
23095
23922
  if (ok) O2.success("gh installed");
23096
23923
  else O2.error("gh install failed");
@@ -23114,14 +23941,14 @@ var GitHubCodespacesProvider = class {
23114
23941
  "Expanding GitHub scopes"
23115
23942
  );
23116
23943
  resetStdinForChild();
23117
- await new Promise((resolve6, reject) => {
23118
- const proc = (0, import_child_process16.spawn)(
23944
+ await new Promise((resolve7, reject) => {
23945
+ const proc = (0, import_child_process19.spawn)(
23119
23946
  "gh",
23120
23947
  ["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
23121
23948
  { stdio: "inherit" }
23122
23949
  );
23123
23950
  proc.on("exit", (code) => {
23124
- if (code === 0) resolve6();
23951
+ if (code === 0) resolve7();
23125
23952
  else reject(new Error(
23126
23953
  "gh auth refresh failed. Re-run `gh auth refresh -h github.com -s repo,read:org` manually."
23127
23954
  ));
@@ -23292,13 +24119,13 @@ var GitHubCodespacesProvider = class {
23292
24119
  }
23293
24120
  async streamCommand(workspaceId, command2) {
23294
24121
  resetStdinForChild();
23295
- return new Promise((resolve6, reject) => {
23296
- const proc = (0, import_child_process16.spawn)(
24122
+ return new Promise((resolve7, reject) => {
24123
+ const proc = (0, import_child_process19.spawn)(
23297
24124
  "gh",
23298
24125
  ["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
23299
24126
  { stdio: "inherit" }
23300
24127
  );
23301
- proc.on("exit", (code) => resolve6({ code: code ?? 0 }));
24128
+ proc.on("exit", (code) => resolve7({ code: code ?? 0 }));
23302
24129
  proc.on("error", reject);
23303
24130
  });
23304
24131
  }
@@ -23319,12 +24146,12 @@ var GitHubCodespacesProvider = class {
23319
24146
  "--",
23320
24147
  `mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
23321
24148
  ];
23322
- await new Promise((resolve6, reject) => {
23323
- const tar = (0, import_child_process16.spawn)("tar", tarArgs, {
24149
+ await new Promise((resolve7, reject) => {
24150
+ const tar = (0, import_child_process19.spawn)("tar", tarArgs, {
23324
24151
  stdio: ["ignore", "pipe", "pipe"],
23325
24152
  env: tarEnv
23326
24153
  });
23327
- const ssh = (0, import_child_process16.spawn)("gh", sshArgs, {
24154
+ const ssh = (0, import_child_process19.spawn)("gh", sshArgs, {
23328
24155
  stdio: [tar.stdout, "pipe", "pipe"]
23329
24156
  });
23330
24157
  let tarErr = "";
@@ -23339,7 +24166,7 @@ var GitHubCodespacesProvider = class {
23339
24166
  ssh.on("error", reject);
23340
24167
  ssh.on("exit", (code) => {
23341
24168
  if (code === 0) {
23342
- resolve6();
24169
+ resolve7();
23343
24170
  } else {
23344
24171
  const reason = (sshErr || tarErr || `exit ${code}`).trim().slice(0, 500);
23345
24172
  reject(new Error(`Remote tar failed: ${reason}`));
@@ -23348,7 +24175,7 @@ var GitHubCodespacesProvider = class {
23348
24175
  });
23349
24176
  }
23350
24177
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
23351
- const remoteDir = path40.posix.dirname(remotePath);
24178
+ const remoteDir = path44.posix.dirname(remotePath);
23352
24179
  const parts = [
23353
24180
  `mkdir -p ${shellQuote(remoteDir)}`,
23354
24181
  `cat > ${shellQuote(remotePath)}`
@@ -23357,8 +24184,8 @@ var GitHubCodespacesProvider = class {
23357
24184
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote(remotePath)}`);
23358
24185
  }
23359
24186
  const cmd = parts.join(" && ");
23360
- await new Promise((resolve6, reject) => {
23361
- const proc = (0, import_child_process16.spawn)(
24187
+ await new Promise((resolve7, reject) => {
24188
+ const proc = (0, import_child_process19.spawn)(
23362
24189
  "gh",
23363
24190
  ["codespace", "ssh", "-c", workspaceId, "--", cmd],
23364
24191
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -23369,7 +24196,7 @@ var GitHubCodespacesProvider = class {
23369
24196
  });
23370
24197
  proc.on("error", reject);
23371
24198
  proc.on("exit", (code) => {
23372
- if (code === 0) resolve6();
24199
+ if (code === 0) resolve7();
23373
24200
  else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
23374
24201
  });
23375
24202
  proc.stdin?.write(contents);
@@ -23416,11 +24243,11 @@ function shellQuote(s) {
23416
24243
  }
23417
24244
 
23418
24245
  // src/services/providers/gitpod.ts
23419
- var import_child_process17 = require("child_process");
24246
+ var import_child_process20 = require("child_process");
23420
24247
  var import_util5 = require("util");
23421
- var path41 = __toESM(require("path"));
24248
+ var path45 = __toESM(require("path"));
23422
24249
  var import_picocolors9 = __toESM(require("picocolors"));
23423
- var execFileP6 = (0, import_util5.promisify)(import_child_process17.execFile);
24250
+ var execFileP6 = (0, import_util5.promisify)(import_child_process20.execFile);
23424
24251
  var MAX_BUFFER2 = 8 * 1024 * 1024;
23425
24252
  function resetStdinForChild2() {
23426
24253
  if (process.stdin.isTTY) {
@@ -23459,10 +24286,10 @@ var GitpodProvider = class {
23459
24286
  "Authenticating Gitpod"
23460
24287
  );
23461
24288
  resetStdinForChild2();
23462
- await new Promise((resolve6, reject) => {
23463
- const proc = (0, import_child_process17.spawn)("gitpod", ["login"], { stdio: "inherit" });
24289
+ await new Promise((resolve7, reject) => {
24290
+ const proc = (0, import_child_process20.spawn)("gitpod", ["login"], { stdio: "inherit" });
23464
24291
  proc.on("exit", (code) => {
23465
- if (code === 0) resolve6();
24292
+ if (code === 0) resolve7();
23466
24293
  else reject(new Error("gitpod login failed."));
23467
24294
  });
23468
24295
  proc.on("error", reject);
@@ -23611,13 +24438,13 @@ var GitpodProvider = class {
23611
24438
  }
23612
24439
  async streamCommand(workspaceId, command2) {
23613
24440
  resetStdinForChild2();
23614
- return new Promise((resolve6, reject) => {
23615
- const proc = (0, import_child_process17.spawn)(
24441
+ return new Promise((resolve7, reject) => {
24442
+ const proc = (0, import_child_process20.spawn)(
23616
24443
  "gitpod",
23617
24444
  ["workspace", "ssh", workspaceId, "--", "-tt", command2],
23618
24445
  { stdio: "inherit" }
23619
24446
  );
23620
- proc.on("exit", (code) => resolve6({ code: code ?? 0 }));
24447
+ proc.on("exit", (code) => resolve7({ code: code ?? 0 }));
23621
24448
  proc.on("error", reject);
23622
24449
  });
23623
24450
  }
@@ -23631,12 +24458,12 @@ var GitpodProvider = class {
23631
24458
  tarArgs.push(".");
23632
24459
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
23633
24460
  const remoteCmd = `mkdir -p ${shellQuote2(remoteDir)} && tar -xzf - -C ${shellQuote2(remoteDir)}`;
23634
- await new Promise((resolve6, reject) => {
23635
- const tar = (0, import_child_process17.spawn)("tar", tarArgs, {
24461
+ await new Promise((resolve7, reject) => {
24462
+ const tar = (0, import_child_process20.spawn)("tar", tarArgs, {
23636
24463
  stdio: ["ignore", "pipe", "pipe"],
23637
24464
  env: tarEnv
23638
24465
  });
23639
- const ssh = (0, import_child_process17.spawn)(
24466
+ const ssh = (0, import_child_process20.spawn)(
23640
24467
  "gitpod",
23641
24468
  ["workspace", "ssh", workspaceId, "--", remoteCmd],
23642
24469
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -23652,13 +24479,13 @@ var GitpodProvider = class {
23652
24479
  tar.on("error", reject);
23653
24480
  ssh.on("error", reject);
23654
24481
  ssh.on("exit", (code) => {
23655
- if (code === 0) resolve6();
24482
+ if (code === 0) resolve7();
23656
24483
  else reject(new Error(`Remote tar failed: ${(sshErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
23657
24484
  });
23658
24485
  });
23659
24486
  }
23660
24487
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
23661
- const remoteDir = path41.posix.dirname(remotePath);
24488
+ const remoteDir = path45.posix.dirname(remotePath);
23662
24489
  const parts = [
23663
24490
  `mkdir -p ${shellQuote2(remoteDir)}`,
23664
24491
  `cat > ${shellQuote2(remotePath)}`
@@ -23667,8 +24494,8 @@ var GitpodProvider = class {
23667
24494
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote2(remotePath)}`);
23668
24495
  }
23669
24496
  const cmd = parts.join(" && ");
23670
- await new Promise((resolve6, reject) => {
23671
- const proc = (0, import_child_process17.spawn)(
24497
+ await new Promise((resolve7, reject) => {
24498
+ const proc = (0, import_child_process20.spawn)(
23672
24499
  "gitpod",
23673
24500
  ["workspace", "ssh", workspaceId, "--", cmd],
23674
24501
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -23679,7 +24506,7 @@ var GitpodProvider = class {
23679
24506
  });
23680
24507
  proc.on("error", reject);
23681
24508
  proc.on("exit", (code) => {
23682
- if (code === 0) resolve6();
24509
+ if (code === 0) resolve7();
23683
24510
  else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
23684
24511
  });
23685
24512
  proc.stdin?.write(contents);
@@ -23692,10 +24519,10 @@ function shellQuote2(s) {
23692
24519
  }
23693
24520
 
23694
24521
  // src/services/providers/gitlab-workspaces.ts
23695
- var import_child_process18 = require("child_process");
24522
+ var import_child_process21 = require("child_process");
23696
24523
  var import_util6 = require("util");
23697
- var path42 = __toESM(require("path"));
23698
- var execFileP7 = (0, import_util6.promisify)(import_child_process18.execFile);
24524
+ var path46 = __toESM(require("path"));
24525
+ var execFileP7 = (0, import_util6.promisify)(import_child_process21.execFile);
23699
24526
  var MAX_BUFFER3 = 8 * 1024 * 1024;
23700
24527
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
23701
24528
  function resetStdinForChild3() {
@@ -23736,14 +24563,14 @@ var GitLabWorkspacesProvider = class {
23736
24563
  "Authenticating GitLab"
23737
24564
  );
23738
24565
  resetStdinForChild3();
23739
- await new Promise((resolve6, reject) => {
23740
- const proc = (0, import_child_process18.spawn)(
24566
+ await new Promise((resolve7, reject) => {
24567
+ const proc = (0, import_child_process21.spawn)(
23741
24568
  "glab",
23742
24569
  ["auth", "login", "--scopes", "api,read_user,read_repository"],
23743
24570
  { stdio: "inherit" }
23744
24571
  );
23745
24572
  proc.on("exit", (code) => {
23746
- if (code === 0) resolve6();
24573
+ if (code === 0) resolve7();
23747
24574
  else reject(new Error("glab auth login failed."));
23748
24575
  });
23749
24576
  proc.on("error", reject);
@@ -23908,13 +24735,13 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
23908
24735
  async streamCommand(workspaceId, command2) {
23909
24736
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
23910
24737
  resetStdinForChild3();
23911
- return new Promise((resolve6, reject) => {
23912
- const proc = (0, import_child_process18.spawn)(
24738
+ return new Promise((resolve7, reject) => {
24739
+ const proc = (0, import_child_process21.spawn)(
23913
24740
  "ssh",
23914
24741
  ["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
23915
24742
  { stdio: "inherit" }
23916
24743
  );
23917
- proc.on("exit", (code) => resolve6({ code: code ?? 0 }));
24744
+ proc.on("exit", (code) => resolve7({ code: code ?? 0 }));
23918
24745
  proc.on("error", reject);
23919
24746
  });
23920
24747
  }
@@ -23929,9 +24756,9 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
23929
24756
  tarArgs.push(".");
23930
24757
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
23931
24758
  const remoteCmd = `mkdir -p ${shellQuote3(remoteDir)} && tar -xzf - -C ${shellQuote3(remoteDir)}`;
23932
- await new Promise((resolve6, reject) => {
23933
- const tar = (0, import_child_process18.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
23934
- const ssh = (0, import_child_process18.spawn)(
24759
+ await new Promise((resolve7, reject) => {
24760
+ const tar = (0, import_child_process21.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
24761
+ const ssh = (0, import_child_process21.spawn)(
23935
24762
  "ssh",
23936
24763
  ["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, remoteCmd],
23937
24764
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -23947,21 +24774,21 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
23947
24774
  tar.on("error", reject);
23948
24775
  ssh.on("error", reject);
23949
24776
  ssh.on("exit", (code) => {
23950
- if (code === 0) resolve6();
24777
+ if (code === 0) resolve7();
23951
24778
  else reject(new Error(`Remote tar failed: ${(sshErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
23952
24779
  });
23953
24780
  });
23954
24781
  }
23955
24782
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
23956
24783
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
23957
- const remoteDir = path42.posix.dirname(remotePath);
24784
+ const remoteDir = path46.posix.dirname(remotePath);
23958
24785
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
23959
24786
  if (options.mode != null) {
23960
24787
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
23961
24788
  }
23962
24789
  const cmd = parts.join(" && ");
23963
- await new Promise((resolve6, reject) => {
23964
- const proc = (0, import_child_process18.spawn)(
24790
+ await new Promise((resolve7, reject) => {
24791
+ const proc = (0, import_child_process21.spawn)(
23965
24792
  "ssh",
23966
24793
  ["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
23967
24794
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -23972,7 +24799,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
23972
24799
  });
23973
24800
  proc.on("error", reject);
23974
24801
  proc.on("exit", (code) => {
23975
- if (code === 0) resolve6();
24802
+ if (code === 0) resolve7();
23976
24803
  else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
23977
24804
  });
23978
24805
  proc.stdin?.write(contents);
@@ -24020,10 +24847,10 @@ function shellQuote3(s) {
24020
24847
  }
24021
24848
 
24022
24849
  // src/services/providers/railway.ts
24023
- var import_child_process19 = require("child_process");
24850
+ var import_child_process22 = require("child_process");
24024
24851
  var import_util7 = require("util");
24025
- var path43 = __toESM(require("path"));
24026
- var execFileP8 = (0, import_util7.promisify)(import_child_process19.execFile);
24852
+ var path47 = __toESM(require("path"));
24853
+ var execFileP8 = (0, import_util7.promisify)(import_child_process22.execFile);
24027
24854
  var MAX_BUFFER4 = 8 * 1024 * 1024;
24028
24855
  function resetStdinForChild4() {
24029
24856
  if (process.stdin.isTTY) {
@@ -24063,10 +24890,10 @@ var RailwayProvider = class {
24063
24890
  "Authenticating Railway"
24064
24891
  );
24065
24892
  resetStdinForChild4();
24066
- await new Promise((resolve6, reject) => {
24067
- const proc = (0, import_child_process19.spawn)("railway", ["login"], { stdio: "inherit" });
24893
+ await new Promise((resolve7, reject) => {
24894
+ const proc = (0, import_child_process22.spawn)("railway", ["login"], { stdio: "inherit" });
24068
24895
  proc.on("exit", (code) => {
24069
- if (code === 0) resolve6();
24896
+ if (code === 0) resolve7();
24070
24897
  else reject(new Error("railway login failed."));
24071
24898
  });
24072
24899
  proc.on("error", reject);
@@ -24206,13 +25033,13 @@ var RailwayProvider = class {
24206
25033
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
24207
25034
  }
24208
25035
  resetStdinForChild4();
24209
- return new Promise((resolve6, reject) => {
24210
- const proc = (0, import_child_process19.spawn)(
25036
+ return new Promise((resolve7, reject) => {
25037
+ const proc = (0, import_child_process22.spawn)(
24211
25038
  "railway",
24212
25039
  ["shell", "--project", projectId, "--service", serviceId, "--command", command2],
24213
25040
  { stdio: "inherit" }
24214
25041
  );
24215
- proc.on("exit", (code) => resolve6({ code: code ?? 0 }));
25042
+ proc.on("exit", (code) => resolve7({ code: code ?? 0 }));
24216
25043
  proc.on("error", reject);
24217
25044
  });
24218
25045
  }
@@ -24230,9 +25057,9 @@ var RailwayProvider = class {
24230
25057
  tarArgs.push(".");
24231
25058
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
24232
25059
  const remoteCmd = `mkdir -p ${shellQuote4(remoteDir)} && tar -xzf - -C ${shellQuote4(remoteDir)}`;
24233
- await new Promise((resolve6, reject) => {
24234
- const tar = (0, import_child_process19.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
24235
- const sh = (0, import_child_process19.spawn)(
25060
+ await new Promise((resolve7, reject) => {
25061
+ const tar = (0, import_child_process22.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
25062
+ const sh = (0, import_child_process22.spawn)(
24236
25063
  "railway",
24237
25064
  ["shell", "--project", projectId, "--service", serviceId, "--command", remoteCmd],
24238
25065
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -24248,7 +25075,7 @@ var RailwayProvider = class {
24248
25075
  tar.on("error", reject);
24249
25076
  sh.on("error", reject);
24250
25077
  sh.on("exit", (code) => {
24251
- if (code === 0) resolve6();
25078
+ if (code === 0) resolve7();
24252
25079
  else reject(new Error(`Remote tar failed: ${(shErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
24253
25080
  });
24254
25081
  });
@@ -24258,14 +25085,14 @@ var RailwayProvider = class {
24258
25085
  if (!projectId || !serviceId) {
24259
25086
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
24260
25087
  }
24261
- const remoteDir = path43.posix.dirname(remotePath);
25088
+ const remoteDir = path47.posix.dirname(remotePath);
24262
25089
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
24263
25090
  if (options.mode != null) {
24264
25091
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
24265
25092
  }
24266
25093
  const cmd = parts.join(" && ");
24267
- await new Promise((resolve6, reject) => {
24268
- const proc = (0, import_child_process19.spawn)(
25094
+ await new Promise((resolve7, reject) => {
25095
+ const proc = (0, import_child_process22.spawn)(
24269
25096
  "railway",
24270
25097
  ["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
24271
25098
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -24276,7 +25103,7 @@ var RailwayProvider = class {
24276
25103
  });
24277
25104
  proc.on("error", reject);
24278
25105
  proc.on("exit", (code) => {
24279
- if (code === 0) resolve6();
25106
+ if (code === 0) resolve7();
24280
25107
  else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
24281
25108
  });
24282
25109
  proc.stdin?.write(contents);
@@ -24801,8 +25628,8 @@ async function stopWorkspaceFromLocal(target) {
24801
25628
  var import_node_dns = require("dns");
24802
25629
  var import_node_util4 = require("util");
24803
25630
  var import_node_crypto8 = require("crypto");
24804
- var fs34 = __toESM(require("fs"));
24805
- var path44 = __toESM(require("path"));
25631
+ var fs37 = __toESM(require("fs"));
25632
+ var path48 = __toESM(require("path"));
24806
25633
  var import_picocolors12 = __toESM(require("picocolors"));
24807
25634
  var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
24808
25635
  async function checkDns(apiBase) {
@@ -24858,13 +25685,13 @@ async function checkHealth(apiBase) {
24858
25685
  }
24859
25686
  }
24860
25687
  function checkConfigDir() {
24861
- const dir = path44.join(require("os").homedir(), ".codeam");
25688
+ const dir = path48.join(require("os").homedir(), ".codeam");
24862
25689
  try {
24863
- fs34.mkdirSync(dir, { recursive: true, mode: 448 });
24864
- const probe = path44.join(dir, ".doctor-probe");
24865
- fs34.writeFileSync(probe, "ok", { mode: 384 });
24866
- const read = fs34.readFileSync(probe, "utf8");
24867
- fs34.unlinkSync(probe);
25690
+ fs37.mkdirSync(dir, { recursive: true, mode: 448 });
25691
+ const probe = path48.join(dir, ".doctor-probe");
25692
+ fs37.writeFileSync(probe, "ok", { mode: 384 });
25693
+ const read = fs37.readFileSync(probe, "utf8");
25694
+ fs37.unlinkSync(probe);
24868
25695
  if (read !== "ok") throw new Error("write/read round-trip mismatch");
24869
25696
  return {
24870
25697
  id: "config-dir",
@@ -24904,9 +25731,9 @@ function checkSessions() {
24904
25731
  }
24905
25732
  }
24906
25733
  function checkAgentBinaries() {
24907
- const os29 = createOsStrategy();
25734
+ const os30 = createOsStrategy();
24908
25735
  return getEnabledAgents().map((meta) => {
24909
- const found = os29.findInPath(meta.binaryName);
25736
+ const found = os30.findInPath(meta.binaryName);
24910
25737
  return {
24911
25738
  id: `agent-${meta.id}`,
24912
25739
  label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
@@ -24928,7 +25755,7 @@ function checkNodePty() {
24928
25755
  detail: "not required on this platform"
24929
25756
  };
24930
25757
  }
24931
- const vendoredPath = path44.join(__dirname, "vendor", "node-pty");
25758
+ const vendoredPath = path48.join(__dirname, "vendor", "node-pty");
24932
25759
  for (const target of [vendoredPath, "node-pty"]) {
24933
25760
  try {
24934
25761
  require(target);
@@ -24970,7 +25797,7 @@ function checkChokidar() {
24970
25797
  }
24971
25798
  async function doctor(args2 = []) {
24972
25799
  const json = args2.includes("--json");
24973
- const cliVersion = true ? "2.32.10" : "0.0.0-dev";
25800
+ const cliVersion = true ? "2.34.0" : "0.0.0-dev";
24974
25801
  const apiBase = resolveApiBaseUrl();
24975
25802
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
24976
25803
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -25169,7 +25996,7 @@ async function completion(args2) {
25169
25996
  // src/commands/version.ts
25170
25997
  var import_picocolors13 = __toESM(require("picocolors"));
25171
25998
  function version2() {
25172
- const v = true ? "2.32.10" : "unknown";
25999
+ const v = true ? "2.34.0" : "unknown";
25173
26000
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
25174
26001
  }
25175
26002
 
@@ -25297,9 +26124,9 @@ function tryShowSubcommandHelp(cmd, args2) {
25297
26124
  var _subcommandHelpKeys = Object.keys(HELPS);
25298
26125
 
25299
26126
  // src/lib/updateNotifier.ts
25300
- var fs35 = __toESM(require("fs"));
25301
- var os28 = __toESM(require("os"));
25302
- var path45 = __toESM(require("path"));
26127
+ var fs38 = __toESM(require("fs"));
26128
+ var os29 = __toESM(require("os"));
26129
+ var path49 = __toESM(require("path"));
25303
26130
  var https8 = __toESM(require("https"));
25304
26131
  var import_node_child_process12 = require("child_process");
25305
26132
  var import_picocolors16 = __toESM(require("picocolors"));
@@ -25308,12 +26135,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
25308
26135
  var TTL_MS = 24 * 60 * 60 * 1e3;
25309
26136
  var REQUEST_TIMEOUT_MS = 1500;
25310
26137
  function cachePath() {
25311
- const dir = path45.join(os28.homedir(), ".codeam");
25312
- return path45.join(dir, "update-check.json");
26138
+ const dir = path49.join(os29.homedir(), ".codeam");
26139
+ return path49.join(dir, "update-check.json");
25313
26140
  }
25314
26141
  function readCache() {
25315
26142
  try {
25316
- const raw = fs35.readFileSync(cachePath(), "utf8");
26143
+ const raw = fs38.readFileSync(cachePath(), "utf8");
25317
26144
  const parsed = JSON.parse(raw);
25318
26145
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
25319
26146
  return parsed;
@@ -25324,10 +26151,10 @@ function readCache() {
25324
26151
  function writeCache(cache) {
25325
26152
  try {
25326
26153
  const file = cachePath();
25327
- fs35.mkdirSync(path45.dirname(file), { recursive: true });
26154
+ fs38.mkdirSync(path49.dirname(file), { recursive: true });
25328
26155
  const tmp = `${file}.${process.pid}.tmp`;
25329
- fs35.writeFileSync(tmp, JSON.stringify(cache));
25330
- fs35.renameSync(tmp, file);
26156
+ fs38.writeFileSync(tmp, JSON.stringify(cache));
26157
+ fs38.renameSync(tmp, file);
25331
26158
  } catch {
25332
26159
  }
25333
26160
  }
@@ -25345,14 +26172,14 @@ function compareSemver(a, b) {
25345
26172
  return 0;
25346
26173
  }
25347
26174
  function fetchLatest() {
25348
- return new Promise((resolve6) => {
26175
+ return new Promise((resolve7) => {
25349
26176
  const req = https8.get(
25350
26177
  REGISTRY_URL,
25351
26178
  { headers: { Accept: "application/json" }, timeout: REQUEST_TIMEOUT_MS },
25352
26179
  (res) => {
25353
26180
  if (res.statusCode !== 200) {
25354
26181
  res.resume();
25355
- resolve6(null);
26182
+ resolve7(null);
25356
26183
  return;
25357
26184
  }
25358
26185
  let buf = "";
@@ -25364,21 +26191,21 @@ function fetchLatest() {
25364
26191
  try {
25365
26192
  const json = JSON.parse(buf);
25366
26193
  if (typeof json.version === "string") {
25367
- resolve6(json.version);
26194
+ resolve7(json.version);
25368
26195
  } else {
25369
- resolve6(null);
26196
+ resolve7(null);
25370
26197
  }
25371
26198
  } catch {
25372
- resolve6(null);
26199
+ resolve7(null);
25373
26200
  }
25374
26201
  });
25375
26202
  }
25376
26203
  );
25377
26204
  req.on("timeout", () => {
25378
26205
  req.destroy();
25379
- resolve6(null);
26206
+ resolve7(null);
25380
26207
  });
25381
- req.on("error", () => resolve6(null));
26208
+ req.on("error", () => resolve7(null));
25382
26209
  });
25383
26210
  }
25384
26211
  function notifyIfStale(currentVersion, latest) {
@@ -25401,8 +26228,8 @@ function isLinkedInstall() {
25401
26228
  timeout: 2e3
25402
26229
  }).trim();
25403
26230
  if (!root) return false;
25404
- const pkgPath = path45.join(root, PKG_NAME);
25405
- return fs35.lstatSync(pkgPath).isSymbolicLink();
26231
+ const pkgPath = path49.join(root, PKG_NAME);
26232
+ return fs38.lstatSync(pkgPath).isSymbolicLink();
25406
26233
  } catch {
25407
26234
  return false;
25408
26235
  }
@@ -25438,7 +26265,7 @@ function maybeAutoUpdate(currentVersion, latest) {
25438
26265
  return;
25439
26266
  }
25440
26267
  try {
25441
- fs35.unlinkSync(cachePath());
26268
+ fs38.unlinkSync(cachePath());
25442
26269
  } catch {
25443
26270
  }
25444
26271
  process.stderr.write(` ${import_picocolors16.default.green("\u2713")} Updated. Resuming session...
@@ -25455,7 +26282,7 @@ function checkForUpdates() {
25455
26282
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
25456
26283
  if (process.env.CI) return;
25457
26284
  if (!process.stdout.isTTY) return;
25458
- const current = true ? "2.32.10" : null;
26285
+ const current = true ? "2.34.0" : null;
25459
26286
  if (!current) return;
25460
26287
  const cache = readCache();
25461
26288
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;