codeam-cli 2.32.10 → 2.33.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 +6 -0
  2. package/dist/index.js +1180 -424
  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.33.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);
@@ -852,7 +853,7 @@ async function postPreviewEvent(input) {
852
853
  }
853
854
  }
854
855
  async function _postJsonAuthed(url, body, pluginAuthToken) {
855
- return new Promise((resolve6, reject) => {
856
+ return new Promise((resolve7, reject) => {
856
857
  const data = JSON.stringify(body);
857
858
  const u2 = new URL(url);
858
859
  const transport = u2.protocol === "https:" ? https : http;
@@ -884,9 +885,9 @@ async function _postJsonAuthed(url, body, pluginAuthToken) {
884
885
  return;
885
886
  }
886
887
  try {
887
- resolve6(JSON.parse(responseBody));
888
+ resolve7(JSON.parse(responseBody));
888
889
  } catch {
889
- resolve6(null);
890
+ resolve7(null);
890
891
  }
891
892
  });
892
893
  }
@@ -911,7 +912,7 @@ function makeHttpError(statusCode, retryAfterHeader, responseBody) {
911
912
  return err;
912
913
  }
913
914
  async function _postJson(url, body) {
914
- return new Promise((resolve6, reject) => {
915
+ return new Promise((resolve7, reject) => {
915
916
  const data = JSON.stringify(body);
916
917
  const u2 = new URL(url);
917
918
  const transport = u2.protocol === "https:" ? https : http;
@@ -940,9 +941,9 @@ async function _postJson(url, body) {
940
941
  return;
941
942
  }
942
943
  try {
943
- resolve6(JSON.parse(body2));
944
+ resolve7(JSON.parse(body2));
944
945
  } catch {
945
- resolve6(null);
946
+ resolve7(null);
946
947
  }
947
948
  });
948
949
  }
@@ -957,7 +958,7 @@ async function _postJson(url, body) {
957
958
  });
958
959
  }
959
960
  async function _getJson(url) {
960
- return new Promise((resolve6, reject) => {
961
+ return new Promise((resolve7, reject) => {
961
962
  const u2 = new URL(url);
962
963
  const transport = u2.protocol === "https:" ? https : http;
963
964
  const req = transport.request(
@@ -981,9 +982,9 @@ async function _getJson(url) {
981
982
  return;
982
983
  }
983
984
  try {
984
- resolve6(JSON.parse(body));
985
+ resolve7(JSON.parse(body));
985
986
  } catch {
986
- resolve6(null);
987
+ resolve7(null);
987
988
  }
988
989
  });
989
990
  }
@@ -1161,8 +1162,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
1161
1162
  return decodedFile;
1162
1163
  };
1163
1164
  }
1164
- function normalizeWindowsPath(path46) {
1165
- return path46.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1165
+ function normalizeWindowsPath(path49) {
1166
+ return path49.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1166
1167
  }
1167
1168
 
1168
1169
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -3642,15 +3643,15 @@ async function addSourceContext(frames) {
3642
3643
  LRU_FILE_CONTENTS_CACHE.reduce();
3643
3644
  return frames;
3644
3645
  }
3645
- function getContextLinesFromFile(path46, ranges, output) {
3646
- return new Promise((resolve6) => {
3647
- const stream = (0, import_node_fs.createReadStream)(path46);
3646
+ function getContextLinesFromFile(path49, ranges, output) {
3647
+ return new Promise((resolve7) => {
3648
+ const stream = (0, import_node_fs.createReadStream)(path49);
3648
3649
  const lineReaded = (0, import_node_readline.createInterface)({
3649
3650
  input: stream
3650
3651
  });
3651
3652
  function destroyStreamAndResolve() {
3652
3653
  stream.destroy();
3653
- resolve6();
3654
+ resolve7();
3654
3655
  }
3655
3656
  let lineNumber = 0;
3656
3657
  let currentRangeIndex = 0;
@@ -3659,7 +3660,7 @@ function getContextLinesFromFile(path46, ranges, output) {
3659
3660
  let rangeStart = range[0];
3660
3661
  let rangeEnd = range[1];
3661
3662
  function onStreamError() {
3662
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path46, 1);
3663
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path49, 1);
3663
3664
  lineReaded.close();
3664
3665
  lineReaded.removeAllListeners();
3665
3666
  destroyStreamAndResolve();
@@ -3720,8 +3721,8 @@ function clearLineContext(frame) {
3720
3721
  delete frame.context_line;
3721
3722
  delete frame.post_context;
3722
3723
  }
3723
- function shouldSkipContextLinesForFile(path46) {
3724
- return path46.startsWith("node:") || path46.endsWith(".min.js") || path46.endsWith(".min.cjs") || path46.endsWith(".min.mjs") || path46.startsWith("data:");
3724
+ function shouldSkipContextLinesForFile(path49) {
3725
+ return path49.startsWith("node:") || path49.endsWith(".min.js") || path49.endsWith(".min.cjs") || path49.endsWith(".min.mjs") || path49.startsWith("data:");
3725
3726
  }
3726
3727
  function shouldSkipContextLinesForFrame(frame) {
3727
3728
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -4937,9 +4938,9 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
4937
4938
  if (!waitUntil) return;
4938
4939
  if (this.disabled || this.optedOut) return;
4939
4940
  if (!this._waitUntilCycle) {
4940
- let resolve6;
4941
+ let resolve7;
4941
4942
  const promise = new Promise((r) => {
4942
- resolve6 = r;
4943
+ resolve7 = r;
4943
4944
  });
4944
4945
  try {
4945
4946
  waitUntil(promise);
@@ -4947,7 +4948,7 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
4947
4948
  return;
4948
4949
  }
4949
4950
  this._waitUntilCycle = {
4950
- resolve: resolve6,
4951
+ resolve: resolve7,
4951
4952
  startedAt: Date.now(),
4952
4953
  timer: void 0
4953
4954
  };
@@ -4971,12 +4972,12 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
4971
4972
  return cycle?.resolve;
4972
4973
  }
4973
4974
  async resolveWaitUntilFlush() {
4974
- const resolve6 = this._consumeWaitUntilCycle();
4975
+ const resolve7 = this._consumeWaitUntilCycle();
4975
4976
  try {
4976
4977
  await super.flush();
4977
4978
  } catch {
4978
4979
  } finally {
4979
- resolve6?.();
4980
+ resolve7?.();
4980
4981
  }
4981
4982
  }
4982
4983
  getPersistedProperty(key) {
@@ -5068,15 +5069,15 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
5068
5069
  async waitForLocalEvaluationReady(timeoutMs = THIRTY_SECONDS) {
5069
5070
  if (this.isLocalEvaluationReady()) return true;
5070
5071
  if (void 0 === this.featureFlagsPoller) return false;
5071
- return new Promise((resolve6) => {
5072
+ return new Promise((resolve7) => {
5072
5073
  const timeout = setTimeout(() => {
5073
5074
  cleanup();
5074
- resolve6(false);
5075
+ resolve7(false);
5075
5076
  }, timeoutMs);
5076
5077
  const cleanup = this._events.on("localEvaluationFlagsLoaded", (count) => {
5077
5078
  clearTimeout(timeout);
5078
5079
  cleanup();
5079
- resolve6(count > 0);
5080
+ resolve7(count > 0);
5080
5081
  });
5081
5082
  });
5082
5083
  }
@@ -5513,13 +5514,13 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
5513
5514
  this.context?.enter(data, options);
5514
5515
  }
5515
5516
  async _shutdown(shutdownTimeoutMs) {
5516
- const resolve6 = this._consumeWaitUntilCycle();
5517
+ const resolve7 = this._consumeWaitUntilCycle();
5517
5518
  await this.featureFlagsPoller?.stopPoller(shutdownTimeoutMs);
5518
5519
  this.errorTracking.shutdown();
5519
5520
  try {
5520
5521
  return await super._shutdown(shutdownTimeoutMs);
5521
5522
  } finally {
5522
- resolve6?.();
5523
+ resolve7?.();
5523
5524
  }
5524
5525
  }
5525
5526
  async _requestRemoteConfigPayload(flagKey) {
@@ -5875,7 +5876,7 @@ function readAnonId() {
5875
5876
  }
5876
5877
  function superProperties() {
5877
5878
  return {
5878
- cliVersion: true ? "2.32.10" : "0.0.0-dev",
5879
+ cliVersion: true ? "2.33.0" : "0.0.0-dev",
5879
5880
  nodeVersion: process.version,
5880
5881
  platform: process.platform,
5881
5882
  arch: process.arch,
@@ -7217,10 +7218,10 @@ function buildForPlatform(platform2) {
7217
7218
  var import_node_crypto4 = require("crypto");
7218
7219
 
7219
7220
  // src/agents/claude/resolver.ts
7220
- function buildClaudeLaunch(extraArgs = [], os29 = createOsStrategy()) {
7221
- const found = os29.findInPath("claude") ?? os29.findInPath("claude-code");
7221
+ function buildClaudeLaunch(extraArgs = [], os30 = createOsStrategy()) {
7222
+ const found = os30.findInPath("claude") ?? os30.findInPath("claude-code");
7222
7223
  if (!found) return null;
7223
- return os29.buildLaunch(found, extraArgs);
7224
+ return os30.buildLaunch(found, extraArgs);
7224
7225
  }
7225
7226
 
7226
7227
  // src/agents/claude/installer.ts
@@ -9176,15 +9177,15 @@ function runInstaller() {
9176
9177
  "-Command",
9177
9178
  "irm https://claude.ai/install.ps1 | iex"
9178
9179
  ] : ["-c", "curl -fsSL https://claude.ai/install.sh | bash"];
9179
- return new Promise((resolve6) => {
9180
+ return new Promise((resolve7) => {
9180
9181
  const proc = (0, import_child_process4.spawn)(cmd, args2, { stdio: "inherit" });
9181
9182
  proc.on("error", (err) => {
9182
9183
  console.error(`
9183
9184
  \u2717 Installer failed to launch: ${err.message}`);
9184
- resolve6(false);
9185
+ resolve7(false);
9185
9186
  });
9186
9187
  proc.on("exit", (code) => {
9187
- resolve6(code === 0);
9188
+ resolve7(code === 0);
9188
9189
  });
9189
9190
  });
9190
9191
  }
@@ -9361,17 +9362,17 @@ function parseUsageOutput(raw) {
9361
9362
  return { percent, resetAt };
9362
9363
  }
9363
9364
  async function fetchClaudeQuota() {
9364
- return new Promise((resolve6) => {
9365
+ return new Promise((resolve7) => {
9365
9366
  const claudeCmd = findInPath("claude") ? "claude" : "claude-code";
9366
9367
  if (!claudeCmd) {
9367
- resolve6(null);
9368
+ resolve7(null);
9368
9369
  return;
9369
9370
  }
9370
9371
  const helperPath = path11.join(os10.tmpdir(), "codeam-quota-helper.py");
9371
9372
  fs8.writeFileSync(helperPath, HELPER_SCRIPT, { mode: 420 });
9372
9373
  const python = findInPath("python3") ?? findInPath("python");
9373
9374
  if (!python) {
9374
- resolve6(null);
9375
+ resolve7(null);
9375
9376
  return;
9376
9377
  }
9377
9378
  const proc = (0, import_child_process5.spawn)(python, [helperPath, claudeCmd, "--tools", ""], {
@@ -9398,13 +9399,13 @@ async function fetchClaudeQuota() {
9398
9399
  fs8.unlinkSync(helperPath);
9399
9400
  } catch {
9400
9401
  }
9401
- resolve6(result);
9402
+ resolve7(result);
9402
9403
  }, 5e3);
9403
9404
  }, 8e3);
9404
9405
  setTimeout(() => {
9405
9406
  if (!resolved) {
9406
9407
  resolved = true;
9407
- resolve6(null);
9408
+ resolve7(null);
9408
9409
  }
9409
9410
  try {
9410
9411
  proc.kill();
@@ -9435,12 +9436,12 @@ function killActiveSpawnAndCaptureChildren() {
9435
9436
  }
9436
9437
  async function spawnAndCapture(cmd, args2, opts = {}) {
9437
9438
  const timeoutMs = opts.timeoutMs ?? 6e4;
9438
- return new Promise((resolve6) => {
9439
+ return new Promise((resolve7) => {
9439
9440
  let settled = false;
9440
9441
  const settle = (value) => {
9441
9442
  if (settled) return;
9442
9443
  settled = true;
9443
- resolve6(value);
9444
+ resolve7(value);
9444
9445
  };
9445
9446
  let child;
9446
9447
  try {
@@ -9947,13 +9948,13 @@ function detectStartupBanner(lines) {
9947
9948
  while (artStart > 0 && BANNER_ART_RE.test(lines[artStart - 1])) artStart--;
9948
9949
  if (metaIdx - artStart < 2) return null;
9949
9950
  const pathLine = (lines[metaIdx + 1] ?? "").trim();
9950
- const path46 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9951
+ const path49 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9951
9952
  return {
9952
9953
  title: "",
9953
9954
  subtitle: lines[metaIdx].trim(),
9954
- path: path46,
9955
+ path: path49,
9955
9956
  startIdx: artStart,
9956
- endIdx: metaIdx + (path46 ? 1 : 0)
9957
+ endIdx: metaIdx + (path49 ? 1 : 0)
9957
9958
  };
9958
9959
  }
9959
9960
 
@@ -9963,8 +9964,8 @@ var ClaudeRuntimeStrategy = class {
9963
9964
  meta = getAgent("claude");
9964
9965
  mode = "interactive";
9965
9966
  os;
9966
- constructor(os29) {
9967
- this.os = os29;
9967
+ constructor(os30) {
9968
+ this.os = os30;
9968
9969
  }
9969
9970
  /**
9970
9971
  * Claude Code's react-ink TUI enables bracketed-paste mode at
@@ -10972,8 +10973,8 @@ function codexCredentialLocator() {
10972
10973
  function codexLoginLauncher() {
10973
10974
  return {
10974
10975
  async ensureInstalled() {
10975
- const os29 = createOsStrategy();
10976
- return os29.findInPath("codex") !== null;
10976
+ const os30 = createOsStrategy();
10977
+ return os30.findInPath("codex") !== null;
10977
10978
  },
10978
10979
  launch() {
10979
10980
  return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
@@ -10996,8 +10997,8 @@ var CodexRuntimeStrategy = class {
10996
10997
  meta = getAgent("codex");
10997
10998
  mode = "interactive";
10998
10999
  os;
10999
- constructor(os29) {
11000
- this.os = os29;
11000
+ constructor(os30) {
11001
+ this.os = os30;
11001
11002
  }
11002
11003
  async prepareLaunch() {
11003
11004
  let binary = this.os.findInPath("codex");
@@ -11103,16 +11104,16 @@ var CodexRuntimeStrategy = class {
11103
11104
  });
11104
11105
  }
11105
11106
  };
11106
- function resolveNpm(os29) {
11107
- return os29.id === "win32" ? "npm.cmd" : "npm";
11107
+ function resolveNpm(os30) {
11108
+ return os30.id === "win32" ? "npm.cmd" : "npm";
11108
11109
  }
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"], {
11110
+ async function installCodexViaNpm(os30) {
11111
+ return new Promise((resolve7, reject) => {
11112
+ const proc = (0, import_node_child_process4.spawn)(resolveNpm(os30), ["install", "-g", "@openai/codex"], {
11112
11113
  stdio: "inherit"
11113
11114
  });
11114
11115
  proc.on("close", (code) => {
11115
- if (code === 0) resolve6();
11116
+ if (code === 0) resolve7();
11116
11117
  else reject(new Error(`npm install -g @openai/codex exited ${code}`));
11117
11118
  });
11118
11119
  proc.on("error", (err) => {
@@ -11125,16 +11126,16 @@ async function installCodexViaNpm(os29) {
11125
11126
  });
11126
11127
  });
11127
11128
  }
11128
- function augmentNpmGlobalBin(os29) {
11129
+ function augmentNpmGlobalBin(os30) {
11129
11130
  try {
11130
- const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os29), ["prefix", "-g"], {
11131
+ const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os30), ["prefix", "-g"], {
11131
11132
  stdio: ["ignore", "pipe", "ignore"]
11132
11133
  });
11133
11134
  if (result.status !== 0) return;
11134
11135
  const prefix = result.stdout.toString().trim();
11135
11136
  if (!prefix) return;
11136
- const binDir = os29.id === "win32" ? prefix : path17.join(prefix, "bin");
11137
- os29.augmentPath([binDir]);
11137
+ const binDir = os30.id === "win32" ? prefix : path17.join(prefix, "bin");
11138
+ os30.augmentPath([binDir]);
11138
11139
  } catch {
11139
11140
  }
11140
11141
  }
@@ -11218,25 +11219,25 @@ var import_node_child_process7 = require("child_process");
11218
11219
  // src/agents/coderabbit/installer.ts
11219
11220
  var import_node_child_process5 = require("child_process");
11220
11221
  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") {
11222
+ async function ensureCoderabbitInstalled(os30) {
11223
+ if (os30.findInPath("coderabbit")) return true;
11224
+ if (os30.id === "win32") {
11224
11225
  console.error(
11225
11226
  "\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
11227
  );
11227
11228
  return false;
11228
11229
  }
11229
11230
  console.log("\n CodeRabbit CLI not found \u2014 installing via the official script\u2026\n");
11230
- const ok = await new Promise((resolve6) => {
11231
+ const ok = await new Promise((resolve7) => {
11231
11232
  const proc = (0, import_node_child_process5.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL} | sh`], {
11232
11233
  stdio: "inherit"
11233
11234
  });
11234
- proc.on("close", (code) => resolve6(code === 0));
11235
- proc.on("error", () => resolve6(false));
11235
+ proc.on("close", (code) => resolve7(code === 0));
11236
+ proc.on("error", () => resolve7(false));
11236
11237
  });
11237
11238
  if (!ok) return false;
11238
- os29.augmentPath([`${os29.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
11239
- return os29.findInPath("coderabbit") !== null;
11239
+ os30.augmentPath([`${os30.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
11240
+ return os30.findInPath("coderabbit") !== null;
11240
11241
  }
11241
11242
 
11242
11243
  // src/agents/coderabbit/link.ts
@@ -11263,10 +11264,10 @@ function coderabbitCredentialLocator() {
11263
11264
  extract: extractLocalCoderabbitToken
11264
11265
  };
11265
11266
  }
11266
- function coderabbitLoginLauncher(os29) {
11267
+ function coderabbitLoginLauncher(os30) {
11267
11268
  return {
11268
11269
  async ensureInstalled() {
11269
- return ensureCoderabbitInstalled(os29);
11270
+ return ensureCoderabbitInstalled(os30);
11270
11271
  },
11271
11272
  launch() {
11272
11273
  return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
@@ -11289,11 +11290,11 @@ function parseReview(stdout) {
11289
11290
  for (const line of lines) {
11290
11291
  const m = line.match(HUNK_LINE_RE);
11291
11292
  if (!m) continue;
11292
- const [, path46, lineNo, sevToken, message] = m;
11293
- if (!path46 || !lineNo || !message) continue;
11293
+ const [, path49, lineNo, sevToken, message] = m;
11294
+ if (!path49 || !lineNo || !message) continue;
11294
11295
  const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
11295
11296
  hunks.push({
11296
- path: path46.trim(),
11297
+ path: path49.trim(),
11297
11298
  line: Number(lineNo),
11298
11299
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
11299
11300
  message: cleanedMessage
@@ -11312,8 +11313,8 @@ var CoderabbitRuntimeStrategy = class {
11312
11313
  meta = getAgent("coderabbit");
11313
11314
  mode = "batch";
11314
11315
  os;
11315
- constructor(os29) {
11316
- this.os = os29;
11316
+ constructor(os30) {
11317
+ this.os = os30;
11317
11318
  }
11318
11319
  getDefaultArgs() {
11319
11320
  return ["review"];
@@ -11351,7 +11352,7 @@ var CoderabbitRuntimeStrategy = class {
11351
11352
  }
11352
11353
  async runOneShot(input) {
11353
11354
  const launch = await this.prepareInvocation(input);
11354
- return new Promise((resolve6, reject) => {
11355
+ return new Promise((resolve7, reject) => {
11355
11356
  const stdoutBuf = [];
11356
11357
  const stderrBuf = [];
11357
11358
  const proc = (0, import_node_child_process7.spawn)(launch.cmd, launch.args, {
@@ -11362,7 +11363,7 @@ var CoderabbitRuntimeStrategy = class {
11362
11363
  proc.stderr?.on("data", (b) => stderrBuf.push(b));
11363
11364
  proc.on("error", (err) => reject(err));
11364
11365
  proc.on("close", (code) => {
11365
- resolve6(
11366
+ resolve7(
11366
11367
  this.parseOutput({
11367
11368
  exitCode: code ?? 0,
11368
11369
  stdout: Buffer.concat(stdoutBuf).toString("utf8"),
@@ -11428,10 +11429,10 @@ function cursorCredentialLocator() {
11428
11429
  extract: extractLocalCursorToken
11429
11430
  };
11430
11431
  }
11431
- function cursorLoginLauncher(os29) {
11432
+ function cursorLoginLauncher(os30) {
11432
11433
  return {
11433
11434
  async ensureInstalled() {
11434
- if (os29.findInPath("cursor-agent")) return true;
11435
+ if (os30.findInPath("cursor-agent")) return true;
11435
11436
  console.error(
11436
11437
  "\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
11438
  );
@@ -11493,8 +11494,8 @@ var CursorRuntimeStrategy = class {
11493
11494
  meta = getAgent("cursor");
11494
11495
  mode = "interactive";
11495
11496
  os;
11496
- constructor(os29) {
11497
- this.os = os29;
11497
+ constructor(os30) {
11498
+ this.os = os30;
11498
11499
  }
11499
11500
  async prepareLaunch() {
11500
11501
  const binary = this.os.findInPath("cursor-agent");
@@ -11614,10 +11615,10 @@ function aiderCredentialLocator() {
11614
11615
  extract: extractLocalAiderToken
11615
11616
  };
11616
11617
  }
11617
- function aiderLoginLauncher(os29) {
11618
+ function aiderLoginLauncher(os30) {
11618
11619
  return {
11619
11620
  async ensureInstalled() {
11620
- if (os29.findInPath("aider")) return true;
11621
+ if (os30.findInPath("aider")) return true;
11621
11622
  console.error(
11622
11623
  "\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
11623
11624
  );
@@ -11627,7 +11628,7 @@ function aiderLoginLauncher(os29) {
11627
11628
  console.error(
11628
11629
  "\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
11630
  );
11630
- return (0, import_node_child_process9.spawn)(os29.id === "win32" ? "cmd.exe" : "sh", os29.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
11631
+ return (0, import_node_child_process9.spawn)(os30.id === "win32" ? "cmd.exe" : "sh", os30.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
11631
11632
  stdio: "ignore"
11632
11633
  });
11633
11634
  }
@@ -11699,8 +11700,8 @@ var AiderRuntimeStrategy = class {
11699
11700
  meta = getAgent("aider");
11700
11701
  mode = "interactive";
11701
11702
  os;
11702
- constructor(os29) {
11703
- this.os = os29;
11703
+ constructor(os30) {
11704
+ this.os = os30;
11704
11705
  }
11705
11706
  async prepareLaunch() {
11706
11707
  const binary = this.os.findInPath("aider");
@@ -11829,8 +11830,8 @@ function geminiCredentialLocator() {
11829
11830
  function geminiLoginLauncher() {
11830
11831
  return {
11831
11832
  async ensureInstalled() {
11832
- const os29 = createOsStrategy();
11833
- return os29.findInPath("gemini") !== null;
11833
+ const os30 = createOsStrategy();
11834
+ return os30.findInPath("gemini") !== null;
11834
11835
  },
11835
11836
  launch() {
11836
11837
  return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
@@ -11863,8 +11864,8 @@ var GeminiRuntimeStrategy = class {
11863
11864
  meta = getAgent("gemini");
11864
11865
  mode = "interactive";
11865
11866
  os;
11866
- constructor(os29) {
11867
- this.os = os29;
11867
+ constructor(os30) {
11868
+ this.os = os30;
11868
11869
  }
11869
11870
  async prepareLaunch() {
11870
11871
  const binary = this.os.findInPath("gemini");
@@ -11964,18 +11965,18 @@ var GeminiRuntimeStrategy = class {
11964
11965
 
11965
11966
  // src/agents/registry.ts
11966
11967
  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)
11968
+ claude: (os30) => new ClaudeRuntimeStrategy(os30),
11969
+ codex: (os30) => new CodexRuntimeStrategy(os30),
11970
+ coderabbit: (os30) => new CoderabbitRuntimeStrategy(os30),
11971
+ cursor: (os30) => new CursorRuntimeStrategy(os30),
11972
+ aider: (os30) => new AiderRuntimeStrategy(os30),
11973
+ gemini: (os30) => new GeminiRuntimeStrategy(os30)
11973
11974
  };
11974
11975
  var deployBuilders = {
11975
11976
  claude: () => new ClaudeDeployStrategy(),
11976
11977
  codex: () => new CodexDeployStrategy()
11977
11978
  };
11978
- function createAgentStrategy(agent, os29 = createOsStrategy()) {
11979
+ function createAgentStrategy(agent, os30 = createOsStrategy()) {
11979
11980
  if (!AGENT_REGISTRY[agent]?.enabled) {
11980
11981
  throw new Error(
11981
11982
  `Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
@@ -11985,10 +11986,10 @@ function createAgentStrategy(agent, os29 = createOsStrategy()) {
11985
11986
  if (!build) {
11986
11987
  throw new Error(`No runtime strategy registered for agent "${agent}"`);
11987
11988
  }
11988
- return build(os29);
11989
+ return build(os30);
11989
11990
  }
11990
- function createInteractiveAgentStrategy(agent, os29 = createOsStrategy()) {
11991
- const s = createAgentStrategy(agent, os29);
11991
+ function createInteractiveAgentStrategy(agent, os30 = createOsStrategy()) {
11992
+ const s = createAgentStrategy(agent, os30);
11992
11993
  if (s.mode !== "interactive") {
11993
11994
  throw new Error(
11994
11995
  `Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
@@ -14268,8 +14269,8 @@ var Connection = class {
14268
14269
  this.requestHandler = requestHandler;
14269
14270
  this.notificationHandler = notificationHandler;
14270
14271
  this.stream = stream;
14271
- this.closedPromise = new Promise((resolve6) => {
14272
- this.abortController.signal.addEventListener("abort", () => resolve6());
14272
+ this.closedPromise = new Promise((resolve7) => {
14273
+ this.abortController.signal.addEventListener("abort", () => resolve7());
14273
14274
  });
14274
14275
  void this.receive();
14275
14276
  }
@@ -14439,11 +14440,11 @@ var Connection = class {
14439
14440
  return rejectedPromise(this.closedReason());
14440
14441
  }
14441
14442
  const id = this.nextRequestId++;
14442
- const responsePromise = new Promise((resolve6, reject) => {
14443
+ const responsePromise = new Promise((resolve7, reject) => {
14443
14444
  this.pendingResponses.set(id, {
14444
14445
  resolve: (response) => {
14445
14446
  try {
14446
- resolve6(mapResponse ? mapResponse(response) : response);
14447
+ resolve7(mapResponse ? mapResponse(response) : response);
14447
14448
  } catch (error) {
14448
14449
  reject(error);
14449
14450
  }
@@ -14764,17 +14765,17 @@ var AcpClient = class {
14764
14765
  this.sessionId = null;
14765
14766
  try {
14766
14767
  child.kill("SIGTERM");
14767
- const grace = new Promise((resolve6) => {
14768
+ const grace = new Promise((resolve7) => {
14768
14769
  const t2 = setTimeout(() => {
14769
14770
  try {
14770
14771
  child.kill("SIGKILL");
14771
14772
  } catch {
14772
14773
  }
14773
- resolve6();
14774
+ resolve7();
14774
14775
  }, 2e3);
14775
14776
  child.once("exit", () => {
14776
14777
  clearTimeout(t2);
14777
- resolve6();
14778
+ resolve7();
14778
14779
  });
14779
14780
  });
14780
14781
  await grace;
@@ -14912,7 +14913,7 @@ var _transport2 = {
14912
14913
  get: _get
14913
14914
  };
14914
14915
  function _post(url, headers, payload) {
14915
- return new Promise((resolve6, reject) => {
14916
+ return new Promise((resolve7, reject) => {
14916
14917
  let settled = false;
14917
14918
  const u2 = new URL(url);
14918
14919
  const lib = u2.protocol === "https:" ? https3 : http3;
@@ -14937,7 +14938,7 @@ function _post(url, headers, payload) {
14937
14938
  res.on("end", () => {
14938
14939
  if (settled) return;
14939
14940
  settled = true;
14940
- resolve6({ statusCode: res.statusCode ?? 0, body });
14941
+ resolve7({ statusCode: res.statusCode ?? 0, body });
14941
14942
  });
14942
14943
  }
14943
14944
  );
@@ -14954,7 +14955,7 @@ function _post(url, headers, payload) {
14954
14955
  });
14955
14956
  }
14956
14957
  function _get(url, headers) {
14957
- return new Promise((resolve6, reject) => {
14958
+ return new Promise((resolve7, reject) => {
14958
14959
  let settled = false;
14959
14960
  const u2 = new URL(url);
14960
14961
  const lib = u2.protocol === "https:" ? https3 : http3;
@@ -14978,7 +14979,7 @@ function _get(url, headers) {
14978
14979
  res.on("end", () => {
14979
14980
  if (settled) return;
14980
14981
  settled = true;
14981
- resolve6({ statusCode: res.statusCode ?? 0, body });
14982
+ resolve7({ statusCode: res.statusCode ?? 0, body });
14982
14983
  });
14983
14984
  }
14984
14985
  );
@@ -15687,11 +15688,11 @@ function extractSelectPrompt(text) {
15687
15688
  }
15688
15689
 
15689
15690
  // src/commands/start/handlers.ts
15690
- var fs29 = __toESM(require("fs"));
15691
- var os24 = __toESM(require("os"));
15692
- var path35 = __toESM(require("path"));
15691
+ var fs31 = __toESM(require("fs"));
15692
+ var os25 = __toESM(require("os"));
15693
+ var path38 = __toESM(require("path"));
15693
15694
  var import_crypto3 = require("crypto");
15694
- var import_child_process12 = require("child_process");
15695
+ var import_child_process15 = require("child_process");
15695
15696
 
15696
15697
  // src/lib/payload.ts
15697
15698
  var import_zod = require("zod");
@@ -16344,12 +16345,12 @@ async function applyFileReview(workingDir, filePath, action) {
16344
16345
  return { ok: true, action, filePath, repoRoot };
16345
16346
  }
16346
16347
  function runGit(cwd, args2) {
16347
- return new Promise((resolve6) => {
16348
+ return new Promise((resolve7) => {
16348
16349
  let proc;
16349
16350
  try {
16350
16351
  proc = (0, import_child_process10.spawn)("git", args2, { cwd, env: process.env });
16351
16352
  } catch (err) {
16352
- resolve6({ ok: false, code: -1, stdout: "", stderr: err.message });
16353
+ resolve7({ ok: false, code: -1, stdout: "", stderr: err.message });
16353
16354
  return;
16354
16355
  }
16355
16356
  let stdout = "";
@@ -16362,11 +16363,11 @@ function runGit(cwd, args2) {
16362
16363
  });
16363
16364
  proc.on(
16364
16365
  "error",
16365
- (err) => resolve6({ ok: false, code: -1, stdout, stderr: stderr + err.message })
16366
+ (err) => resolve7({ ok: false, code: -1, stdout, stderr: stderr + err.message })
16366
16367
  );
16367
16368
  proc.on(
16368
16369
  "close",
16369
- (code) => resolve6({ ok: code === 0, code: code ?? -1, stdout, stderr })
16370
+ (code) => resolve7({ ok: code === 0, code: code ?? -1, stdout, stderr })
16370
16371
  );
16371
16372
  });
16372
16373
  }
@@ -16625,7 +16626,7 @@ async function link(args2 = []) {
16625
16626
  waitSpin.start(waitMsg());
16626
16627
  const countdown = setInterval(() => waitSpin.message(waitMsg()), 1e3);
16627
16628
  countdown.unref?.();
16628
- const paired = await new Promise((resolve6, reject) => {
16629
+ const paired = await new Promise((resolve7, reject) => {
16629
16630
  let stopPoll = null;
16630
16631
  const sigint = () => {
16631
16632
  clearInterval(countdown);
@@ -16638,7 +16639,7 @@ async function link(args2 = []) {
16638
16639
  process.removeListener("SIGINT", sigint);
16639
16640
  clearInterval(countdown);
16640
16641
  waitSpin.stop("Paired");
16641
- resolve6(info);
16642
+ resolve7(info);
16642
16643
  },
16643
16644
  () => {
16644
16645
  clearInterval(countdown);
@@ -16773,14 +16774,14 @@ async function captureFreshCredentials(ctx) {
16773
16774
  }
16774
16775
  };
16775
16776
  try {
16776
- const token = await new Promise((resolve6, reject) => {
16777
+ const token = await new Promise((resolve7, reject) => {
16777
16778
  let settled = false;
16778
16779
  const tryExtract = async () => {
16779
16780
  if (settled) return;
16780
16781
  const t2 = await ctx.locator.extract();
16781
16782
  if (t2 && !settled) {
16782
16783
  settled = true;
16783
- resolve6(t2);
16784
+ resolve7(t2);
16784
16785
  }
16785
16786
  };
16786
16787
  watcher.on("add", () => void tryExtract());
@@ -17178,12 +17179,758 @@ function activePreviewSessionIds() {
17178
17179
  return Array.from(activePreviews.keys());
17179
17180
  }
17180
17181
 
17182
+ // src/beads/bd-adapter.ts
17183
+ var import_child_process12 = require("child_process");
17184
+ var fs29 = __toESM(require("fs"));
17185
+ var os24 = __toESM(require("os"));
17186
+ var path35 = __toESM(require("path"));
17187
+ var BD_PACKAGE = "@beads/bd";
17188
+ function resolveBundledBdBinary() {
17189
+ return _resolveSeam.resolveBundled();
17190
+ }
17191
+ function _defaultResolveBundled() {
17192
+ let pkgJsonPath;
17193
+ try {
17194
+ pkgJsonPath = require.resolve(`${BD_PACKAGE}/package.json`);
17195
+ } catch {
17196
+ return null;
17197
+ }
17198
+ const binDir = path35.join(path35.dirname(pkgJsonPath), "bin");
17199
+ const binaryName = process.platform === "win32" ? "bd.exe" : "bd";
17200
+ const binaryPath = path35.join(binDir, binaryName);
17201
+ try {
17202
+ fs29.accessSync(binaryPath, fs29.constants.F_OK);
17203
+ return binaryPath;
17204
+ } catch {
17205
+ return null;
17206
+ }
17207
+ }
17208
+ function resolveBdOnPath() {
17209
+ return _resolveSeam.resolveOnPath();
17210
+ }
17211
+ function _defaultResolveOnPath() {
17212
+ const dirs = (process.env.PATH ?? "").split(path35.delimiter).filter(Boolean);
17213
+ const candidates = process.platform === "win32" ? ["bd.exe", "bd.cmd", "bd"] : ["bd"];
17214
+ for (const dir of dirs) {
17215
+ for (const candidate of candidates) {
17216
+ const full = path35.join(dir, candidate);
17217
+ try {
17218
+ fs29.accessSync(full, fs29.constants.F_OK);
17219
+ return full;
17220
+ } catch {
17221
+ }
17222
+ }
17223
+ }
17224
+ return null;
17225
+ }
17226
+ var _resolveSeam = {
17227
+ resolveBundled: _defaultResolveBundled,
17228
+ resolveOnPath: _defaultResolveOnPath
17229
+ };
17230
+ var _spawnSeam = {
17231
+ run: _defaultSpawn
17232
+ };
17233
+ function _defaultSpawn(binaryPath, args2, opts) {
17234
+ return new Promise((resolve7) => {
17235
+ let proc;
17236
+ try {
17237
+ proc = (0, import_child_process12.spawn)(binaryPath, args2, { cwd: opts.cwd, env: opts.env });
17238
+ } catch (err) {
17239
+ resolve7({ code: -1, stdout: "", stderr: err.message });
17240
+ return;
17241
+ }
17242
+ let stdout = "";
17243
+ let stderr = "";
17244
+ proc.stdout?.on("data", (c2) => {
17245
+ stdout += c2.toString();
17246
+ });
17247
+ proc.stderr?.on("data", (c2) => {
17248
+ stderr += c2.toString();
17249
+ });
17250
+ proc.on("error", (err) => resolve7({ code: -1, stdout, stderr: err.message }));
17251
+ proc.on("close", (code) => resolve7({ code: code ?? -1, stdout, stderr }));
17252
+ });
17253
+ }
17254
+ var BdAdapter = class {
17255
+ constructor(opts = {}) {
17256
+ this.opts = opts;
17257
+ this.resolved = opts.binaryPath ?? null;
17258
+ }
17259
+ opts;
17260
+ resolved;
17261
+ /**
17262
+ * Resolve the bd binary lazily, caching the result. Order:
17263
+ * bundled @beads/bd → PATH. Returns null when neither is available — the
17264
+ * caller offers the consented installer (`install-bd.ts`).
17265
+ */
17266
+ resolveBinary() {
17267
+ if (this.resolved) return this.resolved;
17268
+ const bundled = resolveBundledBdBinary();
17269
+ if (bundled) {
17270
+ this.resolved = bundled;
17271
+ return bundled;
17272
+ }
17273
+ const onPath = resolveBdOnPath();
17274
+ if (onPath) {
17275
+ this.resolved = onPath;
17276
+ return onPath;
17277
+ }
17278
+ return null;
17279
+ }
17280
+ /** True when a bd binary is resolvable without installing. */
17281
+ isAvailable() {
17282
+ return this.resolveBinary() !== null;
17283
+ }
17284
+ /**
17285
+ * Run an arbitrary bd subcommand. Always injects `--global` (the home brain)
17286
+ * unless a `beadsDir` override is set, in which case `BEADS_DIR` redirects bd
17287
+ * to that dir instead (tests). Returns the raw result; callers decide how to
17288
+ * interpret exit codes (e.g. `bd setup --check` uses 0/nonzero).
17289
+ */
17290
+ async run(args2) {
17291
+ const binary = this.resolveBinary();
17292
+ if (!binary) {
17293
+ return { code: -1, stdout: "", stderr: "bd binary not resolved" };
17294
+ }
17295
+ const env = { ...process.env };
17296
+ const finalArgs = [...args2];
17297
+ if (this.opts.beadsDir) {
17298
+ env.BEADS_DIR = this.opts.beadsDir;
17299
+ } else if (!finalArgs.includes("--global")) {
17300
+ finalArgs.push("--global");
17301
+ }
17302
+ log.trace("beads", `bd ${finalArgs.join(" ")}`);
17303
+ return _spawnSeam.run(binary, finalArgs, { cwd: this.opts.cwd, env });
17304
+ }
17305
+ /**
17306
+ * `bd ready --json` → typed issue array. `bd list --json` shares the shape,
17307
+ * so `listIssues` reuses the same parser. Bad JSON / non-zero exit → [].
17308
+ */
17309
+ async readyIssues(projectKey) {
17310
+ const res = await this.run(["ready", "--json"]);
17311
+ return parseIssues(res, projectKey);
17312
+ }
17313
+ async listIssues(projectKey) {
17314
+ const res = await this.run(["list", "--json"]);
17315
+ return parseIssues(res, projectKey);
17316
+ }
17317
+ /** `bd status --json` → summary block, or null on failure. */
17318
+ async statusSummary() {
17319
+ const res = await this.run(["status", "--json"]);
17320
+ if (res.code !== 0) return null;
17321
+ try {
17322
+ const parsed = JSON.parse(res.stdout);
17323
+ return parsed.summary ?? null;
17324
+ } catch {
17325
+ return null;
17326
+ }
17327
+ }
17328
+ };
17329
+ var VALID_STATUS = /* @__PURE__ */ new Set([
17330
+ "open",
17331
+ "in_progress",
17332
+ "blocked",
17333
+ "closed"
17334
+ ]);
17335
+ function parseIssues(res, projectKey) {
17336
+ if (res.code !== 0) return [];
17337
+ let parsed;
17338
+ try {
17339
+ parsed = JSON.parse(res.stdout);
17340
+ } catch {
17341
+ return [];
17342
+ }
17343
+ if (!Array.isArray(parsed)) return [];
17344
+ const out2 = [];
17345
+ for (const row of parsed) {
17346
+ const issue = coerceIssue(row, projectKey);
17347
+ if (issue) out2.push(issue);
17348
+ }
17349
+ return out2;
17350
+ }
17351
+ function coerceIssue(row, projectKey) {
17352
+ if (typeof row !== "object" || row === null) return null;
17353
+ const r = row;
17354
+ if (typeof r.id !== "string" || typeof r.title !== "string") return null;
17355
+ const status2 = typeof r.status === "string" && VALID_STATUS.has(r.status) ? r.status : "open";
17356
+ return {
17357
+ id: r.id,
17358
+ title: r.title,
17359
+ status: status2,
17360
+ priority: typeof r.priority === "number" ? r.priority : null,
17361
+ issue_type: typeof r.issue_type === "string" ? r.issue_type : "task",
17362
+ owner: typeof r.owner === "string" && r.owner.length > 0 ? r.owner : null,
17363
+ created_at: typeof r.created_at === "string" ? r.created_at : "",
17364
+ updated_at: typeof r.updated_at === "string" ? r.updated_at : "",
17365
+ dependency_count: typeof r.dependency_count === "number" ? r.dependency_count : void 0,
17366
+ dependent_count: typeof r.dependent_count === "number" ? r.dependent_count : void 0,
17367
+ comment_count: typeof r.comment_count === "number" ? r.comment_count : void 0,
17368
+ projectKey
17369
+ };
17370
+ }
17371
+ function defaultBeadsHomeDir() {
17372
+ return path35.join(os24.homedir(), ".beads");
17373
+ }
17374
+
17375
+ // src/beads/bootstrap.ts
17376
+ var SETUP_RECIPE = {
17377
+ claude: "claude",
17378
+ codex: "codex",
17379
+ cursor: "cursor",
17380
+ gemini: "gemini",
17381
+ aider: "aider",
17382
+ copilot: "copilot"
17383
+ };
17384
+ async function bootstrapBeads(opts) {
17385
+ const bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
17386
+ const result = {
17387
+ bdAvailable: false,
17388
+ serverUp: false,
17389
+ agentsConfigured: [],
17390
+ exportEnabled: false
17391
+ };
17392
+ if (!bd.isAvailable()) {
17393
+ log.warn("beads", "bd binary unavailable \u2014 skipping bootstrap");
17394
+ return result;
17395
+ }
17396
+ result.bdAvailable = true;
17397
+ result.serverUp = await ensureServer(bd);
17398
+ if (!result.serverUp) {
17399
+ log.warn("beads", "dolt sql-server not up after start \u2014 skipping wiring this run");
17400
+ return result;
17401
+ }
17402
+ for (const agent of opts.agents) {
17403
+ const recipe = SETUP_RECIPE[agent];
17404
+ if (!recipe) {
17405
+ log.trace("beads", `no bd setup recipe for agent ${agent} \u2014 skipping`);
17406
+ continue;
17407
+ }
17408
+ const applied = await ensureRecipe(bd, recipe);
17409
+ if (applied) result.agentsConfigured.push(agent);
17410
+ }
17411
+ result.exportEnabled = await ensureAutoExport(bd);
17412
+ log.info(
17413
+ "beads",
17414
+ `bootstrap done server=${result.serverUp} agents=[${result.agentsConfigured.join(",")}] export=${result.exportEnabled}`
17415
+ );
17416
+ return result;
17417
+ }
17418
+ async function ensureServer(bd) {
17419
+ const status2 = await bd.run(["dolt", "status"]);
17420
+ if (status2.code === 0) {
17421
+ log.trace("beads", "dolt sql-server already running");
17422
+ return true;
17423
+ }
17424
+ log.info("beads", "dolt sql-server down \u2014 starting detached");
17425
+ const start2 = await bd.run(["dolt", "start"]);
17426
+ if (start2.code !== 0) {
17427
+ log.warn("beads", `bd dolt start failed (code=${start2.code}): ${start2.stderr.slice(0, 200)}`);
17428
+ return false;
17429
+ }
17430
+ const recheck = await bd.run(["dolt", "status"]);
17431
+ return recheck.code === 0;
17432
+ }
17433
+ async function ensureRecipe(bd, recipe) {
17434
+ const check = await bd.run(["setup", recipe, "--check"]);
17435
+ if (check.code === 0) {
17436
+ log.trace("beads", `recipe ${recipe} already configured`);
17437
+ return false;
17438
+ }
17439
+ const setup = await bd.run(["setup", recipe]);
17440
+ if (setup.code !== 0) {
17441
+ log.warn("beads", `bd setup ${recipe} failed (code=${setup.code})`);
17442
+ return false;
17443
+ }
17444
+ log.info("beads", `configured agent recipe: ${recipe}`);
17445
+ return true;
17446
+ }
17447
+ async function ensureAutoExport(bd) {
17448
+ const res = await bd.run(["config", "set", "export.jsonl", "true"]);
17449
+ return res.code === 0;
17450
+ }
17451
+
17452
+ // src/beads/watcher.ts
17453
+ var crypto3 = __toESM(require("crypto"));
17454
+ var path37 = __toESM(require("path"));
17455
+
17456
+ // src/beads/project-key.ts
17457
+ var import_child_process13 = require("child_process");
17458
+ var crypto2 = __toESM(require("crypto"));
17459
+ var fs30 = __toESM(require("fs"));
17460
+ var path36 = __toESM(require("path"));
17461
+ function normalizeOrigin(raw) {
17462
+ const trimmed = raw.trim();
17463
+ if (!trimmed) return null;
17464
+ let host;
17465
+ let pathPart;
17466
+ const scpLike = /^[^/@]+@([^:]+):(.+)$/.exec(trimmed);
17467
+ if (scpLike && !trimmed.includes("://")) {
17468
+ host = scpLike[1];
17469
+ pathPart = scpLike[2];
17470
+ } else {
17471
+ let url;
17472
+ try {
17473
+ url = new URL(trimmed);
17474
+ } catch {
17475
+ return null;
17476
+ }
17477
+ host = url.hostname;
17478
+ pathPart = url.pathname;
17479
+ }
17480
+ host = host.toLowerCase();
17481
+ pathPart = pathPart.replace(/^\/+/, "").replace(/\.git$/i, "").replace(/\/+$/, "");
17482
+ if (!host || !pathPart) return null;
17483
+ return `${host}/${pathPart}`;
17484
+ }
17485
+ function findRepoRoot(cwd) {
17486
+ let dir = path36.resolve(cwd);
17487
+ const seen = /* @__PURE__ */ new Set();
17488
+ for (let i = 0; i < 256; i++) {
17489
+ if (seen.has(dir)) return null;
17490
+ seen.add(dir);
17491
+ try {
17492
+ const stat3 = fs30.statSync(path36.join(dir, ".git"), { throwIfNoEntry: false });
17493
+ if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
17494
+ } catch {
17495
+ }
17496
+ const parent = path36.dirname(dir);
17497
+ if (parent === dir) return null;
17498
+ dir = parent;
17499
+ }
17500
+ return null;
17501
+ }
17502
+ var _execSeam2 = {
17503
+ exec: (file, args2, opts) => {
17504
+ const out2 = (0, import_child_process13.execFileSync)(file, args2, opts);
17505
+ return typeof out2 === "string" ? out2 : out2.toString("utf8");
17506
+ },
17507
+ realpath: (p2) => fs30.realpathSync(p2)
17508
+ };
17509
+ function readOrigin(cwd) {
17510
+ try {
17511
+ const raw = _execSeam2.exec("git", ["remote", "get-url", "origin"], {
17512
+ cwd,
17513
+ timeout: 1e3,
17514
+ stdio: ["ignore", "pipe", "ignore"],
17515
+ encoding: "utf8"
17516
+ });
17517
+ return raw.trim() || null;
17518
+ } catch {
17519
+ return null;
17520
+ }
17521
+ }
17522
+ function deriveProjectIdentity(cwd = process.cwd()) {
17523
+ const repoRoot = findRepoRoot(cwd) ?? cwd;
17524
+ const origin = readOrigin(repoRoot);
17525
+ const normalized = origin ? normalizeOrigin(origin) : null;
17526
+ if (normalized) {
17527
+ const label = normalized.split("/").pop() || normalized;
17528
+ return { projectKey: normalized, projectLabel: label };
17529
+ }
17530
+ let real = repoRoot;
17531
+ try {
17532
+ real = _execSeam2.realpath(repoRoot);
17533
+ } catch {
17534
+ }
17535
+ const hash = crypto2.createHash("sha256").update(real).digest("hex");
17536
+ return { projectKey: `path:${hash}`, projectLabel: path36.basename(real) || "project" };
17537
+ }
17538
+
17539
+ // src/services/file-watcher/transport.ts
17540
+ var http5 = __toESM(require("http"));
17541
+ var https5 = __toESM(require("https"));
17542
+ var _transport3 = {
17543
+ post: _post2
17544
+ };
17545
+ function _post2(url, headers, payload) {
17546
+ return new Promise((resolve7, reject) => {
17547
+ let settled = false;
17548
+ const u2 = new URL(url);
17549
+ const lib = u2.protocol === "https:" ? https5 : http5;
17550
+ const req = lib.request(
17551
+ {
17552
+ hostname: u2.hostname,
17553
+ port: u2.port || (u2.protocol === "https:" ? 443 : 80),
17554
+ path: u2.pathname + u2.search,
17555
+ method: "POST",
17556
+ headers: {
17557
+ ...headers,
17558
+ ...vercelBypassHeader(),
17559
+ "Content-Length": Buffer.byteLength(payload)
17560
+ },
17561
+ timeout: 8e3
17562
+ },
17563
+ (res) => {
17564
+ let body = "";
17565
+ res.on("data", (c2) => {
17566
+ body += c2.toString();
17567
+ });
17568
+ res.on("end", () => {
17569
+ if (settled) return;
17570
+ settled = true;
17571
+ resolve7({ statusCode: res.statusCode ?? 0, body });
17572
+ });
17573
+ }
17574
+ );
17575
+ req.on("error", (err) => {
17576
+ if (settled) return;
17577
+ settled = true;
17578
+ reject(err);
17579
+ });
17580
+ req.on("timeout", () => {
17581
+ req.destroy();
17582
+ });
17583
+ req.write(payload);
17584
+ req.end();
17585
+ });
17586
+ }
17587
+
17588
+ // src/beads/watcher.ts
17589
+ var API_BASE4 = resolveApiBaseUrl();
17590
+ var DEBOUNCE_MS = 400;
17591
+ var _chokidarSeam = {
17592
+ load: () => {
17593
+ try {
17594
+ return require("chokidar");
17595
+ } catch {
17596
+ return null;
17597
+ }
17598
+ }
17599
+ };
17600
+ var BeadsWatcher = class {
17601
+ constructor(opts) {
17602
+ this.opts = opts;
17603
+ this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
17604
+ this.feedPath = opts.feedPath ?? path37.join(defaultBeadsHomeDir(), "issues.jsonl");
17605
+ this.apiBase = opts.apiBaseUrl ?? API_BASE4;
17606
+ }
17607
+ opts;
17608
+ watcher = null;
17609
+ debounceTimer = null;
17610
+ stopped = false;
17611
+ lastPushedHash = null;
17612
+ bd;
17613
+ feedPath;
17614
+ apiBase;
17615
+ /** Start tailing the change feed. Idempotent (second call is a no-op). */
17616
+ start() {
17617
+ if (this.watcher || this.stopped) return;
17618
+ const chokidar2 = _chokidarSeam.load();
17619
+ if (!chokidar2) {
17620
+ log.warn("beads", "chokidar unavailable \u2014 beads watcher disabled");
17621
+ return;
17622
+ }
17623
+ const watcher = chokidar2.watch(this.feedPath, {
17624
+ ignoreInitial: false,
17625
+ // push the current state once on start
17626
+ persistent: true,
17627
+ awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 100 }
17628
+ });
17629
+ watcher.on("add", () => this.scheduleSync());
17630
+ watcher.on("change", () => this.scheduleSync());
17631
+ watcher.on(
17632
+ "error",
17633
+ (err) => log.warn("beads", `feed watcher error \u2014 continuing: ${err}`)
17634
+ );
17635
+ this.watcher = watcher;
17636
+ log.info("beads", `watching ${this.feedPath} for session=${this.opts.sessionId.slice(0, 8)}`);
17637
+ }
17638
+ async stop() {
17639
+ if (this.stopped) return;
17640
+ this.stopped = true;
17641
+ if (this.debounceTimer) {
17642
+ clearTimeout(this.debounceTimer);
17643
+ this.debounceTimer = null;
17644
+ }
17645
+ if (this.watcher) {
17646
+ try {
17647
+ await this.watcher.close();
17648
+ } catch (err) {
17649
+ log.warn("beads", "error closing feed watcher", err);
17650
+ }
17651
+ this.watcher = null;
17652
+ }
17653
+ }
17654
+ /**
17655
+ * Debounce the filesystem event. Each fresh write resets the timer so a
17656
+ * burst of bd mutations coalesces into one snapshot push. NOT polling — the
17657
+ * timer only fires off the back of a real fs event.
17658
+ */
17659
+ scheduleSync() {
17660
+ if (this.stopped) return;
17661
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
17662
+ this.debounceTimer = setTimeout(() => {
17663
+ this.debounceTimer = null;
17664
+ void this.syncNow();
17665
+ }, DEBOUNCE_MS);
17666
+ }
17667
+ /** Visible for tests — pump a synthetic feed event through debounce → push. */
17668
+ /* @internal */
17669
+ _emitForTest() {
17670
+ this.scheduleSync();
17671
+ }
17672
+ /**
17673
+ * Build the full snapshot from bd and push it. Diffs against the last
17674
+ * pushed content hash so an identical rewrite is a no-op.
17675
+ */
17676
+ async syncNow() {
17677
+ if (this.stopped) return;
17678
+ const { projectKey, projectLabel } = deriveProjectIdentity(this.opts.cwd);
17679
+ const [issues, summary] = await Promise.all([
17680
+ this.bd.listIssues(projectKey),
17681
+ this.bd.statusSummary()
17682
+ ]);
17683
+ const payload = {
17684
+ sessionId: this.opts.sessionId,
17685
+ pluginId: this.opts.pluginId,
17686
+ projectKey,
17687
+ projectLabel,
17688
+ fullSnapshot: true,
17689
+ issues,
17690
+ memories: [],
17691
+ ...summary ? { summary } : {}
17692
+ };
17693
+ const body = JSON.stringify(payload);
17694
+ const hash = crypto3.createHash("sha256").update(body).digest("hex");
17695
+ if (hash === this.lastPushedHash) {
17696
+ log.trace("beads", "snapshot unchanged \u2014 skipping push");
17697
+ return;
17698
+ }
17699
+ try {
17700
+ const res = await _transport3.post(`${this.apiBase}/api/beads/ingest`, this.headers(), body);
17701
+ if (res.statusCode >= 200 && res.statusCode < 300) {
17702
+ this.lastPushedHash = hash;
17703
+ log.trace("beads", `pushed ${issues.length} issue(s) project=${projectLabel}`);
17704
+ } else if (res.statusCode === 404 || res.statusCode === 410) {
17705
+ log.warn("beads", `session dead (status=${res.statusCode}) \u2014 stopping watcher`);
17706
+ this.stopped = true;
17707
+ } else {
17708
+ log.warn("beads", `ingest failed status=${res.statusCode} body=${res.body.slice(0, 200)}`);
17709
+ }
17710
+ } catch (err) {
17711
+ log.warn("beads", "ingest POST error", err);
17712
+ }
17713
+ }
17714
+ headers() {
17715
+ return {
17716
+ "Content-Type": "application/json",
17717
+ "X-Codeam-Protocol-Version": "2.0.0",
17718
+ "X-Plugin-Auth-Token": this.opts.pluginAuthToken
17719
+ };
17720
+ }
17721
+ };
17722
+
17723
+ // src/beads/apply-actions.ts
17724
+ function buildBdArgs(action) {
17725
+ switch (action.kind) {
17726
+ case "claim": {
17727
+ if (!action.issueId) return null;
17728
+ const args2 = ["update", action.issueId, "--claim"];
17729
+ if (action.owner) args2.push("--owner", action.owner);
17730
+ return args2;
17731
+ }
17732
+ case "close": {
17733
+ if (!action.issueId) return null;
17734
+ const args2 = ["close", action.issueId];
17735
+ if (action.reason) args2.push("--reason", action.reason);
17736
+ return args2;
17737
+ }
17738
+ case "create": {
17739
+ const title = action.text?.trim();
17740
+ if (!title) return null;
17741
+ return ["create", title];
17742
+ }
17743
+ case "remember": {
17744
+ const body = action.text?.trim();
17745
+ if (!body) return null;
17746
+ return ["remember", body];
17747
+ }
17748
+ default:
17749
+ return null;
17750
+ }
17751
+ }
17752
+ async function applyBeadsAction(action, deps) {
17753
+ const args2 = buildBdArgs(action);
17754
+ if (!args2) {
17755
+ log.warn("beads", `malformed beads action: kind=${action.kind}`);
17756
+ return { ok: false, action: action.kind, code: -1, error: "malformed action" };
17757
+ }
17758
+ if (!deps.adapter.isAvailable()) {
17759
+ return { ok: false, action: action.kind, code: -1, error: "bd unavailable" };
17760
+ }
17761
+ const res = await deps.adapter.run(args2);
17762
+ if (res.code !== 0) {
17763
+ log.warn("beads", `bd ${args2.join(" ")} failed (code=${res.code}): ${res.stderr.slice(0, 200)}`);
17764
+ return { ok: false, action: action.kind, code: res.code, error: res.stderr };
17765
+ }
17766
+ log.info("beads", `applied action ${action.kind}${action.issueId ? ` (${action.issueId})` : ""}`);
17767
+ try {
17768
+ await deps.onApplied();
17769
+ } catch (err) {
17770
+ log.warn("beads", "post-action push failed (state still applied locally)", err);
17771
+ }
17772
+ return { ok: true, action: action.kind, code: 0 };
17773
+ }
17774
+
17775
+ // src/beads/install-bd.ts
17776
+ var import_child_process14 = require("child_process");
17777
+ var INSTALL_SH_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh";
17778
+ var INSTALL_PS1_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/install.ps1";
17779
+ function resolveInstallStrategy(platform2) {
17780
+ if (platform2 === "win32") {
17781
+ return {
17782
+ command: "powershell.exe",
17783
+ args: [
17784
+ "-NoProfile",
17785
+ "-NonInteractive",
17786
+ "-ExecutionPolicy",
17787
+ "Bypass",
17788
+ "-Command",
17789
+ `irm ${INSTALL_PS1_URL} | iex`
17790
+ ],
17791
+ description: `PowerShell: irm ${INSTALL_PS1_URL} | iex (requires Go 1.24+ and Git for Windows on PATH)`
17792
+ };
17793
+ }
17794
+ return {
17795
+ command: "bash",
17796
+ args: ["-c", `curl -fsSL ${INSTALL_SH_URL} | bash`],
17797
+ description: `curl -fsSL ${INSTALL_SH_URL} | bash`
17798
+ };
17799
+ }
17800
+ var _installSpawnSeam = {
17801
+ run: _defaultInstallSpawn
17802
+ };
17803
+ function _defaultInstallSpawn(strategy) {
17804
+ return new Promise((resolve7) => {
17805
+ let proc;
17806
+ try {
17807
+ proc = (0, import_child_process14.spawn)(strategy.command, strategy.args, { env: process.env });
17808
+ } catch (err) {
17809
+ resolve7({ ok: false, code: -1, stderr: err.message });
17810
+ return;
17811
+ }
17812
+ let stderr = "";
17813
+ proc.stderr?.on("data", (c2) => {
17814
+ stderr += c2.toString();
17815
+ });
17816
+ proc.on("error", (err) => resolve7({ ok: false, code: -1, stderr: err.message }));
17817
+ proc.on(
17818
+ "close",
17819
+ (code) => resolve7({ ok: code === 0, code: code ?? -1, stderr })
17820
+ );
17821
+ });
17822
+ }
17823
+ async function installBd(platform2 = process.platform) {
17824
+ const strategy = resolveInstallStrategy(platform2);
17825
+ log.info("beads", `installing bd via ${strategy.description}`);
17826
+ const result = await _installSpawnSeam.run(strategy);
17827
+ if (!result.ok) {
17828
+ log.warn(
17829
+ "beads",
17830
+ `bd install failed (code=${result.code}): ${result.stderr.slice(0, 200)}`
17831
+ );
17832
+ }
17833
+ return result;
17834
+ }
17835
+
17836
+ // src/beads/index.ts
17837
+ async function maybeStartBeads(opts) {
17838
+ if (!opts.enabled) {
17839
+ log.trace("beads", "beads flag off \u2014 skipping");
17840
+ return null;
17841
+ }
17842
+ const adapter = new BdAdapter({ cwd: opts.cwd });
17843
+ if (!adapter.isAvailable() && opts.allowInstall) {
17844
+ log.info("beads", "bd not found \u2014 running OS installer");
17845
+ await installBd();
17846
+ }
17847
+ if (!adapter.isAvailable()) {
17848
+ log.warn("beads", "bd unavailable \u2014 beads disabled for this session");
17849
+ return null;
17850
+ }
17851
+ const boot = await bootstrapBeads({ cwd: opts.cwd, agents: opts.agents, adapter });
17852
+ if (!boot.serverUp) {
17853
+ log.warn("beads", "beads server not up \u2014 watcher not started this run");
17854
+ return null;
17855
+ }
17856
+ const watcher = new BeadsWatcher({
17857
+ sessionId: opts.sessionId,
17858
+ pluginId: opts.pluginId,
17859
+ pluginAuthToken: opts.pluginAuthToken,
17860
+ cwd: opts.cwd,
17861
+ adapter
17862
+ });
17863
+ watcher.start();
17864
+ void watcher.syncNow();
17865
+ return { watcher, adapter };
17866
+ }
17867
+ async function handleBeadsActionCommand(action, started) {
17868
+ await applyBeadsAction(action, {
17869
+ adapter: started.adapter,
17870
+ onApplied: () => started.watcher.syncNow()
17871
+ });
17872
+ }
17873
+
17874
+ // src/beads/wiring.ts
17875
+ function beadsKilled() {
17876
+ const v = process.env.CODEAM_BEADS_DISABLED;
17877
+ return !!v && v !== "0" && v.toLowerCase() !== "false";
17878
+ }
17879
+ async function startBeadsForSession(ctx) {
17880
+ if (beadsKilled()) {
17881
+ log.trace("beads", "CODEAM_BEADS_DISABLED set \u2014 beads off for this session");
17882
+ return null;
17883
+ }
17884
+ if (!ctx.pluginAuthToken) {
17885
+ log.trace("beads", "no pluginAuthToken on session \u2014 beads off");
17886
+ return null;
17887
+ }
17888
+ try {
17889
+ return await maybeStartBeads({
17890
+ enabled: true,
17891
+ sessionId: ctx.sessionId,
17892
+ pluginId: ctx.pluginId,
17893
+ pluginAuthToken: ctx.pluginAuthToken,
17894
+ agents: ctx.agents,
17895
+ cwd: ctx.cwd
17896
+ });
17897
+ } catch (err) {
17898
+ log.warn("beads", "startBeadsForSession failed (non-fatal)", err);
17899
+ return null;
17900
+ }
17901
+ }
17902
+ var ACTION_KINDS = /* @__PURE__ */ new Set([
17903
+ "claim",
17904
+ "close",
17905
+ "create",
17906
+ "remember"
17907
+ ]);
17908
+ function isBeadsActionKind(v) {
17909
+ return typeof v === "string" && ACTION_KINDS.has(v);
17910
+ }
17911
+ function strOrUndefined(v) {
17912
+ return typeof v === "string" ? v : void 0;
17913
+ }
17914
+ function beadsActionFromPayload(payload) {
17915
+ const { action, args: args2 } = payload;
17916
+ if (!isBeadsActionKind(action)) return null;
17917
+ const a = args2 && typeof args2 === "object" ? args2 : {};
17918
+ return {
17919
+ kind: action,
17920
+ issueId: strOrUndefined(a.issueId),
17921
+ text: strOrUndefined(a.text),
17922
+ reason: strOrUndefined(a.reason),
17923
+ owner: strOrUndefined(a.owner),
17924
+ projectKey: strOrUndefined(a.projectKey)
17925
+ };
17926
+ }
17927
+
17181
17928
  // src/commands/start/handlers.ts
17182
17929
  var pendingAttachmentFiles = /* @__PURE__ */ new Set();
17183
17930
  function cleanupAttachmentTempFiles() {
17184
17931
  for (const p2 of pendingAttachmentFiles) {
17185
17932
  try {
17186
- fs29.unlinkSync(p2);
17933
+ fs31.unlinkSync(p2);
17187
17934
  } catch {
17188
17935
  }
17189
17936
  }
@@ -17192,8 +17939,8 @@ function cleanupAttachmentTempFiles() {
17192
17939
  function saveFilesTemp(files) {
17193
17940
  return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
17194
17941
  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"));
17942
+ const tmpPath = path38.join(os25.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
17943
+ fs31.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
17197
17944
  pendingAttachmentFiles.add(tmpPath);
17198
17945
  return tmpPath;
17199
17946
  });
@@ -17213,7 +17960,7 @@ var startTask = (ctx, _cmd, parsed) => {
17213
17960
  setTimeout(() => {
17214
17961
  for (const p2 of paths) {
17215
17962
  try {
17216
- fs29.unlinkSync(p2);
17963
+ fs31.unlinkSync(p2);
17217
17964
  } catch {
17218
17965
  }
17219
17966
  pendingAttachmentFiles.delete(p2);
@@ -17338,7 +18085,7 @@ var sessionTerminated = async (ctx, cmd) => {
17338
18085
  } catch {
17339
18086
  }
17340
18087
  try {
17341
- const proc = (0, import_child_process12.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
18088
+ const proc = (0, import_child_process15.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
17342
18089
  detached: true,
17343
18090
  stdio: "ignore"
17344
18091
  });
@@ -17360,7 +18107,7 @@ var shutdownSession = async (ctx, cmd) => {
17360
18107
  }
17361
18108
  if (ctx.keepAliveCtx.inCodespace && ctx.keepAliveCtx.codespaceName) {
17362
18109
  try {
17363
- const stopProc = (0, import_child_process12.spawn)(
18110
+ const stopProc = (0, import_child_process15.spawn)(
17364
18111
  "bash",
17365
18112
  ["-lc", `sleep 1; gh codespace stop -c ${JSON.stringify(ctx.keepAliveCtx.codespaceName)} >/dev/null 2>&1 || true`],
17366
18113
  { detached: true, stdio: "ignore" }
@@ -17370,7 +18117,7 @@ var shutdownSession = async (ctx, cmd) => {
17370
18117
  }
17371
18118
  }
17372
18119
  try {
17373
- const proc = (0, import_child_process12.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
18120
+ const proc = (0, import_child_process15.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
17374
18121
  detached: true,
17375
18122
  stdio: "ignore"
17376
18123
  });
@@ -17786,8 +18533,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
17786
18533
  if (args2.length === 0) return detection;
17787
18534
  const binName = args2[0];
17788
18535
  if (binName.startsWith("-")) return detection;
17789
- const binPath = path35.join(cwd, "node_modules", ".bin", binName);
17790
- if (!fs29.existsSync(binPath)) return detection;
18536
+ const binPath = path38.join(cwd, "node_modules", ".bin", binName);
18537
+ if (!fs31.existsSync(binPath)) return detection;
17791
18538
  return {
17792
18539
  ...detection,
17793
18540
  command: binPath,
@@ -17877,7 +18624,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
17877
18624
  "BOOT_SEQUENCE",
17878
18625
  `${spawnable.command} ${spawnable.args.join(" ")}`
17879
18626
  );
17880
- const devServer = (0, import_child_process12.spawn)(spawnable.command, spawnable.args, {
18627
+ const devServer = (0, import_child_process15.spawn)(spawnable.command, spawnable.args, {
17881
18628
  cwd: process.cwd(),
17882
18629
  env: { ...process.env, ...spawnable.env ?? {} },
17883
18630
  stdio: ["ignore", "pipe", "pipe"]
@@ -18003,7 +18750,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
18003
18750
  });
18004
18751
  return;
18005
18752
  }
18006
- tunnel = (0, import_child_process12.spawn)(bin, ["tunnel", "--url", `http://localhost:${detection.port}`], {
18753
+ tunnel = (0, import_child_process15.spawn)(bin, ["tunnel", "--url", `http://localhost:${detection.port}`], {
18007
18754
  stdio: ["ignore", "pipe", "pipe"]
18008
18755
  });
18009
18756
  let parsedUrl = null;
@@ -18100,8 +18847,8 @@ var previewStopH = (ctx) => {
18100
18847
  })();
18101
18848
  };
18102
18849
  function runOnce(cmd, args2, cwd, env) {
18103
- return new Promise((resolve6) => {
18104
- const child = (0, import_child_process12.spawn)(cmd, args2, {
18850
+ return new Promise((resolve7) => {
18851
+ const child = (0, import_child_process15.spawn)(cmd, args2, {
18105
18852
  cwd,
18106
18853
  env: { ...process.env, ...env ?? {} },
18107
18854
  stdio: ["ignore", "pipe", "pipe"]
@@ -18114,8 +18861,8 @@ function runOnce(cmd, args2, cwd, env) {
18114
18861
  };
18115
18862
  child.stdout?.on("data", onChunk);
18116
18863
  child.stderr?.on("data", onChunk);
18117
- child.once("exit", (code) => resolve6(code));
18118
- child.once("error", () => resolve6(-1));
18864
+ child.once("exit", (code) => resolve7(code));
18865
+ child.once("error", () => resolve7(-1));
18119
18866
  });
18120
18867
  }
18121
18868
  var savePreviewConfigH = (_ctx, _cmd, parsed) => {
@@ -18169,6 +18916,23 @@ var handlers = {
18169
18916
  save_preview_config: savePreviewConfigH
18170
18917
  };
18171
18918
  async function dispatchCommand(ctx, cmd) {
18919
+ if (cmd.type === "beads_action") {
18920
+ if (!ctx.beads) {
18921
+ log.trace("beads", "beads_action received but beads not running this session \u2014 dropping");
18922
+ return;
18923
+ }
18924
+ const action = beadsActionFromPayload(cmd.payload);
18925
+ if (!action) {
18926
+ log.warn("beads", "malformed beads_action payload \u2014 dropping");
18927
+ return;
18928
+ }
18929
+ try {
18930
+ await handleBeadsActionCommand(action, ctx.beads);
18931
+ } catch (err) {
18932
+ log.warn("beads", "handleBeadsActionCommand failed (non-fatal)", err);
18933
+ }
18934
+ return;
18935
+ }
18172
18936
  const parsed = parsePayload2(startCommandSchema, cmd.payload);
18173
18937
  if (!parsed) {
18174
18938
  showInfo(`Ignoring malformed ${cmd.type} payload.`);
@@ -18180,10 +18944,10 @@ async function dispatchCommand(ctx, cmd) {
18180
18944
  }
18181
18945
 
18182
18946
  // 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"));
18947
+ var import_child_process16 = require("child_process");
18948
+ var fs32 = __toESM(require("fs"));
18949
+ var os26 = __toESM(require("os"));
18950
+ var path39 = __toESM(require("path"));
18187
18951
  var import_ignore = __toESM(require("ignore"));
18188
18952
 
18189
18953
  // src/services/file-watcher/diff-parser.ts
@@ -18272,58 +19036,9 @@ function isIgnoredFilePath(filePath) {
18272
19036
  return IGNORED_PATH_PATTERN.test(filePath);
18273
19037
  }
18274
19038
 
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
19039
  // src/services/file-watcher.service.ts
18325
- var API_BASE4 = resolveApiBaseUrl();
18326
- var DEBOUNCE_MS = 250;
19040
+ var API_BASE5 = resolveApiBaseUrl();
19041
+ var DEBOUNCE_MS2 = 250;
18327
19042
  var COALESCE_WINDOW_MS = 250;
18328
19043
  var COALESCE_MAX_HOLD_MS = 2e3;
18329
19044
  var MAX_RETRIES = 2;
@@ -18342,10 +19057,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
18342
19057
  /[\\/]Start Menu([\\/]|$)/i,
18343
19058
  /[\\/]Templates([\\/]|$)/i
18344
19059
  ];
18345
- function isUnsafeWindowsWatchRoot(dir, homedir21) {
19060
+ function isUnsafeWindowsWatchRoot(dir, homedir22) {
18346
19061
  const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
18347
19062
  const cwd = norm(dir);
18348
- const home = norm(homedir21);
19063
+ const home = norm(homedir22);
18349
19064
  if (cwd === home) return true;
18350
19065
  if (/^[a-z]:$/.test(cwd)) return true;
18351
19066
  const sysRoots = [
@@ -18359,7 +19074,7 @@ function isUnsafeWindowsWatchRoot(dir, homedir21) {
18359
19074
  }
18360
19075
  return false;
18361
19076
  }
18362
- var _chokidarSeam = {
19077
+ var _chokidarSeam2 = {
18363
19078
  load: () => {
18364
19079
  try {
18365
19080
  return require("chokidar");
@@ -18375,18 +19090,18 @@ var _findGitRootSeam = {
18375
19090
  resolve: _defaultFindGitRoot
18376
19091
  };
18377
19092
  function _defaultFindGitRoot(startDir) {
18378
- let dir = path36.resolve(startDir);
19093
+ let dir = path39.resolve(startDir);
18379
19094
  const seen = /* @__PURE__ */ new Set();
18380
19095
  for (let i = 0; i < 256; i++) {
18381
19096
  if (seen.has(dir)) return null;
18382
19097
  seen.add(dir);
18383
19098
  try {
18384
- const gitPath = path36.join(dir, ".git");
18385
- const stat3 = fs30.statSync(gitPath, { throwIfNoEntry: false });
19099
+ const gitPath = path39.join(dir, ".git");
19100
+ const stat3 = fs32.statSync(gitPath, { throwIfNoEntry: false });
18386
19101
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
18387
19102
  } catch {
18388
19103
  }
18389
- const parent = path36.dirname(dir);
19104
+ const parent = path39.dirname(dir);
18390
19105
  if (parent === dir) return null;
18391
19106
  dir = parent;
18392
19107
  }
@@ -18395,7 +19110,7 @@ function _defaultFindGitRoot(startDir) {
18395
19110
  var FileWatcherService = class {
18396
19111
  constructor(opts) {
18397
19112
  this.opts = opts;
18398
- this.apiBase = opts.apiBaseUrl ?? API_BASE4;
19113
+ this.apiBase = opts.apiBaseUrl ?? API_BASE5;
18399
19114
  }
18400
19115
  opts;
18401
19116
  watcher = null;
@@ -18444,14 +19159,14 @@ var FileWatcherService = class {
18444
19159
  throw new Error("FileWatcherService has already been stopped \u2014 re-instantiate to restart.");
18445
19160
  }
18446
19161
  const isWin = process.platform === "win32";
18447
- if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os25.homedir())) {
19162
+ if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os26.homedir())) {
18448
19163
  log.warn(
18449
19164
  "fileWatcher",
18450
19165
  `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
19166
  );
18452
19167
  return;
18453
19168
  }
18454
- const chokidar2 = _chokidarSeam.load();
19169
+ const chokidar2 = _chokidarSeam2.load();
18455
19170
  if (!chokidar2) {
18456
19171
  log.warn(
18457
19172
  "fileWatcher",
@@ -18570,7 +19285,7 @@ var FileWatcherService = class {
18570
19285
  const timer = setTimeout(() => {
18571
19286
  this.pending.delete(absPath);
18572
19287
  this.enqueueForCoalesce(absPath, changeType);
18573
- }, DEBOUNCE_MS);
19288
+ }, DEBOUNCE_MS2);
18574
19289
  this.pending.set(absPath, {
18575
19290
  lastEventAt: Date.now(),
18576
19291
  timer,
@@ -18631,7 +19346,7 @@ var FileWatcherService = class {
18631
19346
  }
18632
19347
  async emitForFile(absPath, changeType) {
18633
19348
  if (this.stopped) return;
18634
- const fileDir = path36.dirname(absPath);
19349
+ const fileDir = path39.dirname(absPath);
18635
19350
  let gitRoot = this.gitRootByDir.get(fileDir);
18636
19351
  if (gitRoot === void 0) {
18637
19352
  gitRoot = findGitRoot2(fileDir);
@@ -18644,19 +19359,19 @@ var FileWatcherService = class {
18644
19359
  );
18645
19360
  return;
18646
19361
  }
18647
- const relPathInRepo = path36.relative(gitRoot, absPath);
19362
+ const relPathInRepo = path39.relative(gitRoot, absPath);
18648
19363
  if (!relPathInRepo || relPathInRepo.startsWith("..")) return;
18649
19364
  const matcher = this.getGitIgnoreMatcher(gitRoot);
18650
19365
  if (matcher && matcher.ignores(relPathInRepo)) {
18651
19366
  log.trace(
18652
19367
  "fileWatcher",
18653
- `${relPathInRepo} ignored by ${path36.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
19368
+ `${relPathInRepo} ignored by ${path39.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
18654
19369
  );
18655
19370
  return;
18656
19371
  }
18657
19372
  this.opts.onRepoDirty?.(gitRoot);
18658
- const repoPath = path36.relative(this.opts.workingDir, gitRoot);
18659
- const repoName = path36.basename(gitRoot);
19373
+ const repoPath = path39.relative(this.opts.workingDir, gitRoot);
19374
+ const repoName = path39.basename(gitRoot);
18660
19375
  let diffText = "";
18661
19376
  let fileStatus = "modified";
18662
19377
  if (changeType === "unlink") {
@@ -18831,7 +19546,7 @@ var FileWatcherService = class {
18831
19546
  collectGitignoreFiles(repoRoot, dir, matcher) {
18832
19547
  let entries;
18833
19548
  try {
18834
- entries = fs30.readdirSync(dir, { withFileTypes: true });
19549
+ entries = fs32.readdirSync(dir, { withFileTypes: true });
18835
19550
  } catch {
18836
19551
  return;
18837
19552
  }
@@ -18840,16 +19555,16 @@ var FileWatcherService = class {
18840
19555
  );
18841
19556
  if (gitignoreEntry) {
18842
19557
  try {
18843
- const body = fs30.readFileSync(path36.join(dir, ".gitignore"), "utf8");
18844
- const rel = path36.relative(repoRoot, dir).replace(/\\/g, "/");
19558
+ const body = fs32.readFileSync(path39.join(dir, ".gitignore"), "utf8");
19559
+ const rel = path39.relative(repoRoot, dir).replace(/\\/g, "/");
18845
19560
  const prefixed = body.split(/\r?\n/).map((line) => {
18846
19561
  const trimmed = line.trim();
18847
19562
  if (!trimmed || trimmed.startsWith("#")) return line;
18848
19563
  if (!rel) return line;
18849
19564
  if (trimmed.startsWith("!")) {
18850
- return "!" + path36.posix.join(rel, trimmed.slice(1));
19565
+ return "!" + path39.posix.join(rel, trimmed.slice(1));
18851
19566
  }
18852
- return path36.posix.join(rel, trimmed);
19567
+ return path39.posix.join(rel, trimmed);
18853
19568
  }).join("\n");
18854
19569
  matcher.add(prefixed);
18855
19570
  } catch {
@@ -18858,7 +19573,7 @@ var FileWatcherService = class {
18858
19573
  for (const entry of entries) {
18859
19574
  if (!entry.isDirectory()) continue;
18860
19575
  if (entry.name === ".git") continue;
18861
- const childAbs = path36.join(dir, entry.name);
19576
+ const childAbs = path39.join(dir, entry.name);
18862
19577
  if (isIgnoredFilePath(childAbs)) continue;
18863
19578
  this.collectGitignoreFiles(repoRoot, childAbs, matcher);
18864
19579
  }
@@ -18992,12 +19707,12 @@ var _gitSeam = {
18992
19707
  run: _runGitImpl
18993
19708
  };
18994
19709
  async function _runGitImpl(cwd, args2, opts = {}) {
18995
- return new Promise((resolve6) => {
19710
+ return new Promise((resolve7) => {
18996
19711
  let proc;
18997
19712
  try {
18998
- proc = (0, import_child_process13.spawn)("git", args2, { cwd, env: process.env });
19713
+ proc = (0, import_child_process16.spawn)("git", args2, { cwd, env: process.env });
18999
19714
  } catch {
19000
- resolve6(null);
19715
+ resolve7(null);
19001
19716
  return;
19002
19717
  }
19003
19718
  let stdout = "";
@@ -19008,13 +19723,13 @@ async function _runGitImpl(cwd, args2, opts = {}) {
19008
19723
  proc.stderr?.on("data", (c2) => {
19009
19724
  stderr += c2.toString();
19010
19725
  });
19011
- proc.on("error", () => resolve6(null));
19726
+ proc.on("error", () => resolve7(null));
19012
19727
  proc.on("close", (code) => {
19013
19728
  if (code === 0 || opts.allowNonZeroExit) {
19014
- resolve6(stdout);
19729
+ resolve7(stdout);
19015
19730
  } else {
19016
19731
  log.trace("fileWatcher", `git ${args2.join(" ")} exited ${code} stderr=${stderr.slice(0, 200)}`);
19017
- resolve6(null);
19732
+ resolve7(null);
19018
19733
  }
19019
19734
  });
19020
19735
  });
@@ -19027,8 +19742,8 @@ function _runGit(cwd, args2, opts = {}) {
19027
19742
  var import_crypto4 = require("crypto");
19028
19743
 
19029
19744
  // src/services/turn-files/git-changeset.ts
19030
- var import_child_process14 = require("child_process");
19031
- var path37 = __toESM(require("path"));
19745
+ var import_child_process17 = require("child_process");
19746
+ var path40 = __toESM(require("path"));
19032
19747
  async function collectRepoChangeset(opts) {
19033
19748
  const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
19034
19749
  if (status2 === null) return null;
@@ -19108,12 +19823,12 @@ function runGit3(cwd, args2) {
19108
19823
  return _runGitImpl2.run(cwd, args2);
19109
19824
  }
19110
19825
  function defaultRunGit(cwd, args2) {
19111
- return new Promise((resolve6) => {
19826
+ return new Promise((resolve7) => {
19112
19827
  let proc;
19113
19828
  try {
19114
- proc = (0, import_child_process14.spawn)("git", args2, { cwd, env: process.env });
19829
+ proc = (0, import_child_process17.spawn)("git", args2, { cwd, env: process.env });
19115
19830
  } catch {
19116
- resolve6(null);
19831
+ resolve7(null);
19117
19832
  return;
19118
19833
  }
19119
19834
  let stdout = "";
@@ -19124,22 +19839,22 @@ function defaultRunGit(cwd, args2) {
19124
19839
  proc.stderr?.on("data", (c2) => {
19125
19840
  stderr += c2.toString();
19126
19841
  });
19127
- proc.on("error", () => resolve6(null));
19842
+ proc.on("error", () => resolve7(null));
19128
19843
  proc.on("close", (code) => {
19129
19844
  if (code === 0) {
19130
- resolve6(stdout);
19845
+ resolve7(stdout);
19131
19846
  } else {
19132
19847
  log.trace(
19133
19848
  "turnFiles",
19134
19849
  `git ${args2.join(" ")} exited ${code} stderr=${stderr.slice(0, 200)}`
19135
19850
  );
19136
- resolve6(null);
19851
+ resolve7(null);
19137
19852
  }
19138
19853
  });
19139
19854
  });
19140
19855
  }
19141
19856
  async function discoverRepos(workingDir, maxDepth = 4) {
19142
- const fs36 = await import("fs/promises");
19857
+ const fs38 = await import("fs/promises");
19143
19858
  const out2 = [];
19144
19859
  await walk(workingDir, 0);
19145
19860
  return out2;
@@ -19147,7 +19862,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
19147
19862
  if (depth > maxDepth) return;
19148
19863
  let entries = [];
19149
19864
  try {
19150
- const dirents = await fs36.readdir(dir, { withFileTypes: true });
19865
+ const dirents = await fs38.readdir(dir, { withFileTypes: true });
19151
19866
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
19152
19867
  } catch {
19153
19868
  return;
@@ -19158,8 +19873,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
19158
19873
  if (hasGit) {
19159
19874
  out2.push({
19160
19875
  repoRoot: dir,
19161
- repoPath: path37.relative(workingDir, dir),
19162
- repoName: path37.basename(dir)
19876
+ repoPath: path40.relative(workingDir, dir),
19877
+ repoName: path40.basename(dir)
19163
19878
  });
19164
19879
  return;
19165
19880
  }
@@ -19167,14 +19882,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
19167
19882
  if (!entry.isDirectory) continue;
19168
19883
  if (entry.name === "node_modules") continue;
19169
19884
  if (entry.name === "dist" || entry.name === "build") continue;
19170
- await walk(path37.join(dir, entry.name), depth + 1);
19885
+ await walk(path40.join(dir, entry.name), depth + 1);
19171
19886
  }
19172
19887
  }
19173
19888
  }
19174
19889
 
19175
19890
  // src/services/turn-files/files-outbox.ts
19176
- var fs31 = __toESM(require("fs/promises"));
19177
- var path38 = __toESM(require("path"));
19891
+ var fs33 = __toESM(require("fs/promises"));
19892
+ var path41 = __toESM(require("path"));
19178
19893
  var import_os7 = require("os");
19179
19894
  var HOME_OUTBOX_DIR = ".codeam/outbox";
19180
19895
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -19207,16 +19922,16 @@ var FilesOutbox = class {
19207
19922
  backoffIndex = 0;
19208
19923
  stopped = false;
19209
19924
  constructor(opts) {
19210
- const base = opts.baseDir ?? path38.join(homeDir(), HOME_OUTBOX_DIR);
19211
- this.filePath = path38.join(base, `${opts.sessionId}.jsonl`);
19925
+ const base = opts.baseDir ?? path41.join(homeDir(), HOME_OUTBOX_DIR);
19926
+ this.filePath = path41.join(base, `${opts.sessionId}.jsonl`);
19212
19927
  this.post = opts.post;
19213
19928
  this.autoSchedule = opts.autoSchedule !== false;
19214
19929
  }
19215
19930
  /** Persist the entry to disk and trigger a flush. Returns once the
19216
19931
  * line is durable on disk (not once the POST succeeds). */
19217
19932
  async enqueue(entry) {
19218
- await fs31.mkdir(path38.dirname(this.filePath), { recursive: true });
19219
- await fs31.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
19933
+ await fs33.mkdir(path41.dirname(this.filePath), { recursive: true });
19934
+ await fs33.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
19220
19935
  this.backoffIndex = 0;
19221
19936
  if (this.autoSchedule) this.scheduleFlush(0);
19222
19937
  }
@@ -19305,7 +20020,7 @@ var FilesOutbox = class {
19305
20020
  async readAll() {
19306
20021
  let raw = "";
19307
20022
  try {
19308
- raw = await fs31.readFile(this.filePath, "utf8");
20023
+ raw = await fs33.readFile(this.filePath, "utf8");
19309
20024
  } catch {
19310
20025
  return [];
19311
20026
  }
@@ -19329,12 +20044,12 @@ var FilesOutbox = class {
19329
20044
  async rewrite(entries) {
19330
20045
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
19331
20046
  if (entries.length === 0) {
19332
- await fs31.unlink(this.filePath).catch(() => void 0);
20047
+ await fs33.unlink(this.filePath).catch(() => void 0);
19333
20048
  return;
19334
20049
  }
19335
20050
  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);
20051
+ await fs33.writeFile(tmpPath, payload, "utf8");
20052
+ await fs33.rename(tmpPath, this.filePath);
19338
20053
  }
19339
20054
  };
19340
20055
  function applyJitter(ms) {
@@ -19346,13 +20061,13 @@ function homeDir() {
19346
20061
  }
19347
20062
 
19348
20063
  // src/services/turn-files/turn-file-aggregator.ts
19349
- var API_BASE5 = resolveApiBaseUrl();
20064
+ var API_BASE6 = resolveApiBaseUrl();
19350
20065
  var ENDPOINT = "/api/files/batch";
19351
20066
  var MAX_BATCH_SIZE = 1e3;
19352
20067
  var TurnFileAggregator = class {
19353
20068
  constructor(opts) {
19354
20069
  this.opts = opts;
19355
- this.apiBase = opts.apiBaseUrl ?? API_BASE5;
20070
+ this.apiBase = opts.apiBaseUrl ?? API_BASE6;
19356
20071
  this.outbox = new FilesOutbox({
19357
20072
  sessionId: opts.sessionId,
19358
20073
  baseDir: opts.outboxDir,
@@ -19544,7 +20259,7 @@ var StreamingState = class {
19544
20259
  * default-reject. Caller is the SDK's `onRequestPermission`.
19545
20260
  */
19546
20261
  registerPermission(args2) {
19547
- return new Promise((resolve6) => {
20262
+ return new Promise((resolve7) => {
19548
20263
  const timeoutTimer = setTimeout(() => {
19549
20264
  if (this.pending?.kind === "permission" && this.pending.questionId === args2.questionId) {
19550
20265
  log.warn(
@@ -19552,7 +20267,7 @@ var StreamingState = class {
19552
20267
  `permission ${args2.questionId.slice(0, 8)} TTL expired \u2014 auto-cancel`
19553
20268
  );
19554
20269
  this.pending = null;
19555
- resolve6({ outcome: { outcome: "cancelled" } });
20270
+ resolve7({ outcome: { outcome: "cancelled" } });
19556
20271
  }
19557
20272
  }, PERMISSION_TIMEOUT_MS);
19558
20273
  this.pending = {
@@ -19560,7 +20275,7 @@ var StreamingState = class {
19560
20275
  questionId: args2.questionId,
19561
20276
  labels: args2.labels,
19562
20277
  optionIdByLabel: args2.optionIdByLabel,
19563
- resolve: resolve6,
20278
+ resolve: resolve7,
19564
20279
  timeoutTimer
19565
20280
  };
19566
20281
  });
@@ -19592,14 +20307,14 @@ var StreamingState = class {
19592
20307
  const label = this.pending.labels[index];
19593
20308
  const optionId = label ? this.pending.optionIdByLabel[label] : void 0;
19594
20309
  clearTimeout(this.pending.timeoutTimer);
19595
- const resolve6 = this.pending.resolve;
20310
+ const resolve7 = this.pending.resolve;
19596
20311
  this.pending = null;
19597
20312
  if (!optionId) {
19598
20313
  log.warn("acpRunner", `select_option index=${index} out of bounds \u2014 cancel`);
19599
- resolve6({ outcome: { outcome: "cancelled" } });
20314
+ resolve7({ outcome: { outcome: "cancelled" } });
19600
20315
  return { kind: "resolved" };
19601
20316
  }
19602
- resolve6({ outcome: { outcome: "selected", optionId } });
20317
+ resolve7({ outcome: { outcome: "selected", optionId } });
19603
20318
  return { kind: "resolved" };
19604
20319
  }
19605
20320
  const text = this.pending.options[index];
@@ -19955,6 +20670,16 @@ async function runAcpSession(opts) {
19955
20670
  }).catch((err) => {
19956
20671
  log.warn("acpRunner", `fileWatcher.start failed: ${describeError(err)}`);
19957
20672
  });
20673
+ let beads = null;
20674
+ void startBeadsForSession({
20675
+ sessionId: opts.sessionId,
20676
+ pluginId: opts.pluginId,
20677
+ pluginAuthToken: opts.pluginAuthToken,
20678
+ agents: [opts.agent],
20679
+ cwd: opts.cwd
20680
+ }).then((started) => {
20681
+ beads = started;
20682
+ });
19958
20683
  const relay = new CommandRelayService(
19959
20684
  opts.pluginId,
19960
20685
  async (cmd) => {
@@ -19968,7 +20693,8 @@ async function runAcpSession(opts) {
19968
20693
  opts,
19969
20694
  history,
19970
20695
  initialize.agentCapabilities,
19971
- turnFiles
20696
+ turnFiles,
20697
+ () => beads
19972
20698
  );
19973
20699
  },
19974
20700
  { id: opts.agent, name: opts.agent, displayName: opts.agent }
@@ -19979,6 +20705,7 @@ async function runAcpSession(opts) {
19979
20705
  relay.stop();
19980
20706
  void fileWatcher.stop();
19981
20707
  turnFiles.stop();
20708
+ void beads?.watcher.stop();
19982
20709
  closeAllTerminals();
19983
20710
  await client2.stop();
19984
20711
  process.exit(0);
@@ -19989,8 +20716,24 @@ async function runAcpSession(opts) {
19989
20716
  await new Promise(() => {
19990
20717
  });
19991
20718
  }
19992
- async function handleCommand(cmd, client2, relay, acpSessionId, models, streaming, opts, history, agentCaps, turnFiles) {
20719
+ async function handleCommand(cmd, client2, relay, acpSessionId, models, streaming, opts, history, agentCaps, turnFiles, getBeads) {
19993
20720
  switch (cmd.type) {
20721
+ case "beads_action": {
20722
+ const beads = getBeads();
20723
+ const action = beadsActionFromPayload(cmd.payload);
20724
+ if (!beads || !action) {
20725
+ await relay.sendResult(cmd.id, "completed", { applied: false });
20726
+ return;
20727
+ }
20728
+ try {
20729
+ await handleBeadsActionCommand(action, beads);
20730
+ await relay.sendResult(cmd.id, "completed", { applied: true });
20731
+ } catch (err) {
20732
+ log.warn("acpRunner", `beads_action failed (non-fatal): ${describeError(err)}`);
20733
+ await relay.sendResult(cmd.id, "failed", { error: describeError(err) });
20734
+ }
20735
+ return;
20736
+ }
19994
20737
  case "start_task": {
19995
20738
  const payload = cmd.payload;
19996
20739
  const blocks = buildAcpPromptBlocks(payload ?? {});
@@ -20349,11 +21092,11 @@ var ChromeStepTracker = class {
20349
21092
  // src/services/output/chunk-emitter.ts
20350
21093
  var https6 = __toESM(require("https"));
20351
21094
  var http6 = __toESM(require("http"));
20352
- var API_BASE6 = resolveApiBaseUrl();
21095
+ var API_BASE7 = resolveApiBaseUrl();
20353
21096
  async function refreshAuthToken(sessionId, pluginId) {
20354
21097
  try {
20355
21098
  const { statusCode, body } = await _transport4.post(
20356
- `${API_BASE6}/api/pairing/reconnect`,
21099
+ `${API_BASE7}/api/pairing/reconnect`,
20357
21100
  {
20358
21101
  "Content-Type": "application/json",
20359
21102
  "X-Codeam-Protocol-Version": PROTOCOL_VERSION,
@@ -20394,7 +21137,7 @@ var ChunkEmitter = class {
20394
21137
  }
20395
21138
  }
20396
21139
  opts;
20397
- url = `${API_BASE6}/api/commands/output`;
21140
+ url = `${API_BASE7}/api/commands/output`;
20398
21141
  headers;
20399
21142
  /**
20400
21143
  * Send a chunk. `body` is the chunk fields minus `sessionId` /
@@ -20415,14 +21158,14 @@ var ChunkEmitter = class {
20415
21158
  "chunkEmitter",
20416
21159
  `send type=${body.type ?? "(clear)"} bytes=${payload.length} done=${body.done === true}`
20417
21160
  );
20418
- return new Promise((resolve6) => {
21161
+ return new Promise((resolve7) => {
20419
21162
  const attempt = (attemptsLeft) => {
20420
21163
  _transport4.post(this.url, this.headers, payload).then(({ statusCode, body: resBody }) => {
20421
21164
  const tookMs = Date.now() - t0;
20422
21165
  if (statusCode === 410 || statusCode === 404 && /SESSION_NOT_FOUND|SESSION_GONE/.test(resBody)) {
20423
21166
  process.stderr.write("[codeam] session was deleted/disconnected \u2014 stopping output stream.\n");
20424
21167
  log.info("chunkEmitter", `dead status=${statusCode} took=${tookMs}ms`);
20425
- resolve6({ dead: true });
21168
+ resolve7({ dead: true });
20426
21169
  return;
20427
21170
  }
20428
21171
  if (statusCode === 401) {
@@ -20438,7 +21181,7 @@ var ChunkEmitter = class {
20438
21181
  return;
20439
21182
  }
20440
21183
  }
20441
- resolve6({ dead: false });
21184
+ resolve7({ dead: false });
20442
21185
  })();
20443
21186
  return;
20444
21187
  }
@@ -20449,7 +21192,7 @@ var ChunkEmitter = class {
20449
21192
  } else {
20450
21193
  log.info("chunkEmitter", `ok status=${statusCode} took=${tookMs}ms`);
20451
21194
  }
20452
- resolve6({ dead: false });
21195
+ resolve7({ dead: false });
20453
21196
  }).catch((err) => {
20454
21197
  log.warn(
20455
21198
  "chunkEmitter",
@@ -20460,7 +21203,7 @@ var ChunkEmitter = class {
20460
21203
  const delay = 200 * (maxRetries - attemptsLeft + 1);
20461
21204
  setTimeout(() => attempt(attemptsLeft - 1), delay);
20462
21205
  } else {
20463
- resolve6({ dead: false });
21206
+ resolve7({ dead: false });
20464
21207
  }
20465
21208
  });
20466
21209
  };
@@ -20472,7 +21215,7 @@ var _transport4 = {
20472
21215
  post: _post3
20473
21216
  };
20474
21217
  function _post3(url, headers, payload) {
20475
- return new Promise((resolve6, reject) => {
21218
+ return new Promise((resolve7, reject) => {
20476
21219
  let settled = false;
20477
21220
  const u2 = new URL(url);
20478
21221
  const transport = u2.protocol === "https:" ? https6 : http6;
@@ -20496,7 +21239,7 @@ function _post3(url, headers, payload) {
20496
21239
  res.on("end", () => {
20497
21240
  if (settled) return;
20498
21241
  settled = true;
20499
- resolve6({ statusCode: res.statusCode ?? 0, body: resData });
21242
+ resolve7({ statusCode: res.statusCode ?? 0, body: resData });
20500
21243
  });
20501
21244
  }
20502
21245
  );
@@ -21070,9 +21813,9 @@ var OutputService = class _OutputService {
21070
21813
  };
21071
21814
 
21072
21815
  // src/services/history.service.ts
21073
- var fs32 = __toESM(require("fs"));
21074
- var path39 = __toESM(require("path"));
21075
- var os26 = __toESM(require("os"));
21816
+ var fs34 = __toESM(require("fs"));
21817
+ var path42 = __toESM(require("path"));
21818
+ var os27 = __toESM(require("os"));
21076
21819
  var https7 = __toESM(require("https"));
21077
21820
  var http7 = __toESM(require("http"));
21078
21821
  var import_zod2 = require("zod");
@@ -21086,7 +21829,7 @@ var historyRecordSchema = import_zod2.z.object({
21086
21829
  content: import_zod2.z.union([import_zod2.z.string(), import_zod2.z.array(import_zod2.z.unknown())]).optional()
21087
21830
  }).passthrough().optional()
21088
21831
  }).passthrough();
21089
- var API_BASE7 = resolveApiBaseUrl();
21832
+ var API_BASE8 = resolveApiBaseUrl();
21090
21833
  function extractText3(content) {
21091
21834
  if (typeof content === "string") return content;
21092
21835
  if (Array.isArray(content)) {
@@ -21099,7 +21842,7 @@ function parseJsonl(filePath) {
21099
21842
  const messages = [];
21100
21843
  let raw;
21101
21844
  try {
21102
- raw = fs32.readFileSync(filePath, "utf8");
21845
+ raw = fs34.readFileSync(filePath, "utf8");
21103
21846
  } catch (err) {
21104
21847
  if (err.code !== "ENOENT") {
21105
21848
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -21136,9 +21879,9 @@ function parseJsonl(filePath) {
21136
21879
  return messages;
21137
21880
  }
21138
21881
  function post(endpoint, body) {
21139
- return new Promise((resolve6) => {
21882
+ return new Promise((resolve7) => {
21140
21883
  const payload = JSON.stringify(body);
21141
- const u2 = new URL(`${API_BASE7}${endpoint}`);
21884
+ const u2 = new URL(`${API_BASE8}${endpoint}`);
21142
21885
  const transport = u2.protocol === "https:" ? https7 : http7;
21143
21886
  const req = transport.request(
21144
21887
  {
@@ -21157,17 +21900,17 @@ function post(endpoint, body) {
21157
21900
  res.resume();
21158
21901
  const ok = res.statusCode !== void 0 && res.statusCode >= 200 && res.statusCode < 300;
21159
21902
  if (!ok) log.warn("history:post", `${endpoint} \u2192 HTTP ${res.statusCode}`);
21160
- resolve6(ok);
21903
+ resolve7(ok);
21161
21904
  }
21162
21905
  );
21163
21906
  req.on("error", (err) => {
21164
21907
  log.warn("history:post", `${endpoint} network error`, err);
21165
- resolve6(false);
21908
+ resolve7(false);
21166
21909
  });
21167
21910
  req.on("timeout", () => {
21168
21911
  log.warn("history:post", `${endpoint} timeout after 15s`);
21169
21912
  req.destroy();
21170
- resolve6(false);
21913
+ resolve7(false);
21171
21914
  });
21172
21915
  req.write(payload);
21173
21916
  req.end();
@@ -21234,7 +21977,7 @@ var HistoryService = class _HistoryService {
21234
21977
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
21235
21978
  }
21236
21979
  get projectDir() {
21237
- return this.runtime.resolveHistoryDir(this.cwd) ?? path39.join(os26.homedir(), ".claude", "projects", encodeCwd(this.cwd));
21980
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path42.join(os27.homedir(), ".claude", "projects", encodeCwd(this.cwd));
21238
21981
  }
21239
21982
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
21240
21983
  setCurrentConversationId(id) {
@@ -21246,7 +21989,7 @@ var HistoryService = class _HistoryService {
21246
21989
  /** Return the current message count in the active conversation. */
21247
21990
  getCurrentMessageCount() {
21248
21991
  if (!this.currentConversationId) return 0;
21249
- const filePath = path39.join(this.projectDir, `${this.currentConversationId}.jsonl`);
21992
+ const filePath = path42.join(this.projectDir, `${this.currentConversationId}.jsonl`);
21250
21993
  return parseJsonl(filePath).length;
21251
21994
  }
21252
21995
  /**
@@ -21257,7 +22000,7 @@ var HistoryService = class _HistoryService {
21257
22000
  const deadline = Date.now() + timeoutMs;
21258
22001
  while (Date.now() < deadline) {
21259
22002
  if (!this.currentConversationId) return null;
21260
- const filePath = path39.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22003
+ const filePath = path42.join(this.projectDir, `${this.currentConversationId}.jsonl`);
21261
22004
  const messages = parseJsonl(filePath);
21262
22005
  if (messages.length > previousCount) {
21263
22006
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -21283,16 +22026,16 @@ var HistoryService = class _HistoryService {
21283
22026
  const dir = this.projectDir;
21284
22027
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
21285
22028
  try {
21286
- const files = fs32.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
22029
+ const files = fs34.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
21287
22030
  try {
21288
- const stat3 = fs32.statSync(path39.join(dir, e.name));
22031
+ const stat3 = fs34.statSync(path42.join(dir, e.name));
21289
22032
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
21290
22033
  } catch {
21291
22034
  return { name: e.name, mtime: 0, birthtime: 0 };
21292
22035
  }
21293
22036
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
21294
22037
  if (files.length > 0) {
21295
- this.currentConversationId = path39.basename(files[0].name, ".jsonl");
22038
+ this.currentConversationId = path42.basename(files[0].name, ".jsonl");
21296
22039
  }
21297
22040
  } catch {
21298
22041
  }
@@ -21326,13 +22069,13 @@ var HistoryService = class _HistoryService {
21326
22069
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
21327
22070
  let entries;
21328
22071
  try {
21329
- entries = fs32.readdirSync(dir, { withFileTypes: true });
22072
+ entries = fs34.readdirSync(dir, { withFileTypes: true });
21330
22073
  } catch {
21331
22074
  return null;
21332
22075
  }
21333
22076
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
21334
22077
  try {
21335
- const stat3 = fs32.statSync(path39.join(dir, e.name));
22078
+ const stat3 = fs34.statSync(path42.join(dir, e.name));
21336
22079
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
21337
22080
  } catch {
21338
22081
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -21341,12 +22084,12 @@ var HistoryService = class _HistoryService {
21341
22084
  if (files.length === 0) return null;
21342
22085
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
21343
22086
  if (!files.some((f) => f.name === targetFile)) return null;
21344
- return this.extractUsageFromFile(path39.join(dir, targetFile));
22087
+ return this.extractUsageFromFile(path42.join(dir, targetFile));
21345
22088
  }
21346
22089
  extractUsageFromFile(filePath) {
21347
22090
  let raw;
21348
22091
  try {
21349
- raw = fs32.readFileSync(filePath, "utf8");
22092
+ raw = fs34.readFileSync(filePath, "utf8");
21350
22093
  } catch {
21351
22094
  return null;
21352
22095
  }
@@ -21391,9 +22134,9 @@ var HistoryService = class _HistoryService {
21391
22134
  let totalCost = 0;
21392
22135
  let files;
21393
22136
  try {
21394
- files = fs32.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
22137
+ files = fs34.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
21395
22138
  try {
21396
- return fs32.statSync(path39.join(projectDir, f)).mtimeMs >= monthStartMs;
22139
+ return fs34.statSync(path42.join(projectDir, f)).mtimeMs >= monthStartMs;
21397
22140
  } catch {
21398
22141
  return false;
21399
22142
  }
@@ -21404,7 +22147,7 @@ var HistoryService = class _HistoryService {
21404
22147
  for (const file of files) {
21405
22148
  let raw;
21406
22149
  try {
21407
- raw = fs32.readFileSync(path39.join(projectDir, file), "utf8");
22150
+ raw = fs34.readFileSync(path42.join(projectDir, file), "utf8");
21408
22151
  } catch {
21409
22152
  continue;
21410
22153
  }
@@ -21468,7 +22211,7 @@ var HistoryService = class _HistoryService {
21468
22211
  * showing an empty conversation.
21469
22212
  */
21470
22213
  async loadConversation(sessionId) {
21471
- const filePath = path39.join(this.projectDir, `${sessionId}.jsonl`);
22214
+ const filePath = path42.join(this.projectDir, `${sessionId}.jsonl`);
21472
22215
  const messages = parseJsonl(filePath);
21473
22216
  if (messages.length === 0) return;
21474
22217
  const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
@@ -21522,7 +22265,7 @@ var HistoryService = class _HistoryService {
21522
22265
  if (!this.currentConversationId) return 0;
21523
22266
  }
21524
22267
  const sessionId = this.currentConversationId;
21525
- const filePath = path39.join(this.projectDir, `${sessionId}.jsonl`);
22268
+ const filePath = path42.join(this.projectDir, `${sessionId}.jsonl`);
21526
22269
  const messages = parseJsonl(filePath);
21527
22270
  if (messages.length === 0) return 0;
21528
22271
  const marker = this.lastUploadedUuid.get(sessionId);
@@ -21587,7 +22330,7 @@ var RepoDirtyTracker = class {
21587
22330
 
21588
22331
  // src/services/streaming-emitter.service.ts
21589
22332
  var import_crypto5 = require("crypto");
21590
- var API_BASE8 = resolveApiBaseUrl();
22333
+ var API_BASE9 = resolveApiBaseUrl();
21591
22334
  var TICK_MS = 50;
21592
22335
  var ANSWER_POLL_MS = 1500;
21593
22336
  var SELECTOR_STABLE_MS = 800;
@@ -21598,7 +22341,7 @@ var TAIL_KEEP_BYTES2 = 1.5 * 1024 * 1024;
21598
22341
  var StreamingEmitterService = class {
21599
22342
  constructor(opts) {
21600
22343
  this.opts = opts;
21601
- this.apiBase = opts.apiBaseUrl ?? API_BASE8;
22344
+ this.apiBase = opts.apiBaseUrl ?? API_BASE9;
21602
22345
  this.headers = {
21603
22346
  "Content-Type": "application/json",
21604
22347
  "X-Codeam-Protocol-Version": "2.0.0",
@@ -21948,13 +22691,13 @@ function fetchQuotaUsage(runtime, historySvc) {
21948
22691
  }
21949
22692
 
21950
22693
  // src/commands/start/keep-alive.ts
21951
- var import_child_process15 = require("child_process");
22694
+ var import_child_process18 = require("child_process");
21952
22695
  function buildKeepAlive(ctx) {
21953
22696
  let timer = null;
21954
22697
  async function setIdleTimeout(minutes) {
21955
22698
  if (!ctx.inCodespace || !ctx.codespaceName) return;
21956
- await new Promise((resolve6) => {
21957
- const proc = (0, import_child_process15.spawn)(
22699
+ await new Promise((resolve7) => {
22700
+ const proc = (0, import_child_process18.spawn)(
21958
22701
  "gh",
21959
22702
  [
21960
22703
  "api",
@@ -21967,8 +22710,8 @@ function buildKeepAlive(ctx) {
21967
22710
  { stdio: "ignore", detached: true }
21968
22711
  );
21969
22712
  proc.unref();
21970
- proc.on("exit", () => resolve6());
21971
- proc.on("error", () => resolve6());
22713
+ proc.on("exit", () => resolve7());
22714
+ proc.on("error", () => resolve7());
21972
22715
  });
21973
22716
  }
21974
22717
  return {
@@ -22116,6 +22859,7 @@ async function start(requestedAgent) {
22116
22859
  dirtyTracker: dirtyTracker ?? void 0
22117
22860
  }) : null;
22118
22861
  let streamingEmitter = null;
22862
+ let beads = null;
22119
22863
  const agent = new AgentService(
22120
22864
  runtime,
22121
22865
  {
@@ -22132,6 +22876,7 @@ async function start(requestedAgent) {
22132
22876
  relay.stop();
22133
22877
  void fileWatcher?.stop();
22134
22878
  turnFiles?.stop();
22879
+ void beads?.watcher.stop();
22135
22880
  void streamingEmitter?.stop();
22136
22881
  closeAllTerminals();
22137
22882
  cleanupAttachmentTempFiles();
@@ -22165,6 +22910,16 @@ async function start(requestedAgent) {
22165
22910
  await dispatchCommand(ctx, cmd);
22166
22911
  }, runtime.meta);
22167
22912
  ctx.relay = relay;
22913
+ void startBeadsForSession({
22914
+ sessionId: session.id,
22915
+ pluginId,
22916
+ pluginAuthToken: session.pluginAuthToken ?? void 0,
22917
+ agents: [session.agent],
22918
+ cwd
22919
+ }).then((started) => {
22920
+ beads = started;
22921
+ ctx.beads = started;
22922
+ });
22168
22923
  registerTerminalHandlers({
22169
22924
  onData: ({ sessionId, data }) => {
22170
22925
  void outputSvc.sendTerminalChunk(sessionId, data);
@@ -22181,6 +22936,7 @@ async function start(requestedAgent) {
22181
22936
  outputSvc.dispose();
22182
22937
  relay.stop();
22183
22938
  void fileWatcher?.stop();
22939
+ void beads?.watcher.stop();
22184
22940
  void streamingEmitter?.stop();
22185
22941
  closeAllTerminals();
22186
22942
  cleanupAttachmentTempFiles();
@@ -22319,7 +23075,7 @@ async function pair(args2 = []) {
22319
23075
  waitSpin.message(waitMessage());
22320
23076
  }, 1e3);
22321
23077
  countdownInterval.unref?.();
22322
- await new Promise((resolve6) => {
23078
+ await new Promise((resolve7) => {
22323
23079
  let stopPolling = null;
22324
23080
  function sigintHandler() {
22325
23081
  clearInterval(countdownInterval);
@@ -22367,7 +23123,7 @@ async function pair(args2 = []) {
22367
23123
  pluginAuthToken: info.pluginAuthToken
22368
23124
  });
22369
23125
  }
22370
- resolve6();
23126
+ resolve7();
22371
23127
  },
22372
23128
  () => {
22373
23129
  clearInterval(countdownInterval);
@@ -22419,8 +23175,8 @@ async function autoLinkAfterPair(opts) {
22419
23175
  }
22420
23176
 
22421
23177
  // src/commands/pair-auto.ts
22422
- var fs33 = __toESM(require("fs"));
22423
- var os27 = __toESM(require("os"));
23178
+ var fs35 = __toESM(require("fs"));
23179
+ var os28 = __toESM(require("os"));
22424
23180
  var import_crypto7 = require("crypto");
22425
23181
 
22426
23182
  // src/commands/start-infra-only.ts
@@ -22573,7 +23329,7 @@ async function startInfraOnly(agentId) {
22573
23329
  }
22574
23330
 
22575
23331
  // src/commands/pair-auto.ts
22576
- var API_BASE9 = resolveApiBaseUrl();
23332
+ var API_BASE10 = resolveApiBaseUrl();
22577
23333
  function fail(msg) {
22578
23334
  console.error(`
22579
23335
  ${msg}
@@ -22588,12 +23344,12 @@ function readTokenFromArgs(args2) {
22588
23344
  }
22589
23345
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
22590
23346
  if (fileFlag) {
22591
- const path46 = fileFlag.slice("--token-file=".length);
23347
+ const path49 = fileFlag.slice("--token-file=".length);
22592
23348
  try {
22593
- const content = fs33.readFileSync(path46, "utf8").trim();
22594
- if (content.length === 0) fail(`--token-file ${path46} is empty`);
23349
+ const content = fs35.readFileSync(path49, "utf8").trim();
23350
+ if (content.length === 0) fail(`--token-file ${path49} is empty`);
22595
23351
  try {
22596
- fs33.unlinkSync(path46);
23352
+ fs35.unlinkSync(path49);
22597
23353
  } catch {
22598
23354
  }
22599
23355
  return content;
@@ -22613,13 +23369,13 @@ function networkError(msg, cause) {
22613
23369
  return err;
22614
23370
  }
22615
23371
  async function claimOnce(token, pluginId) {
22616
- const url = `${API_BASE9}/api/pairing/claim-auto-token`;
23372
+ const url = `${API_BASE10}/api/pairing/claim-auto-token`;
22617
23373
  const body = {
22618
23374
  token,
22619
23375
  pluginId,
22620
23376
  ideName: "codeam-cli (codespace)",
22621
23377
  ideVersion: process.env.npm_package_version ?? "unknown",
22622
- hostname: os27.hostname(),
23378
+ hostname: os28.hostname(),
22623
23379
  codespaceName: process.env.CODESPACE_NAME ?? "",
22624
23380
  // Current git branch of the codespace's working directory, so the
22625
23381
  // backend can populate `PairedSession.branch` for the codespace pair.
@@ -22816,7 +23572,7 @@ function status() {
22816
23572
 
22817
23573
  // src/commands/logout.ts
22818
23574
  var import_picocolors7 = __toESM(require("picocolors"));
22819
- var API_BASE10 = resolveApiBaseUrl();
23575
+ var API_BASE11 = resolveApiBaseUrl();
22820
23576
  async function notifyBackendOffline() {
22821
23577
  const cfg = loadCliConfig();
22822
23578
  const pluginIds = /* @__PURE__ */ new Set([
@@ -22828,7 +23584,7 @@ async function notifyBackendOffline() {
22828
23584
  try {
22829
23585
  await Promise.all(
22830
23586
  Array.from(pluginIds).map(
22831
- (pluginId) => _postJson(`${API_BASE10}/api/plugin/heartbeat`, {
23587
+ (pluginId) => _postJson(`${API_BASE11}/api/plugin/heartbeat`, {
22832
23588
  pluginId,
22833
23589
  online: false
22834
23590
  }).catch((err) => {
@@ -22856,11 +23612,11 @@ async function logout() {
22856
23612
  var import_picocolors10 = __toESM(require("picocolors"));
22857
23613
 
22858
23614
  // src/services/providers/github-codespaces.ts
22859
- var import_child_process16 = require("child_process");
23615
+ var import_child_process19 = require("child_process");
22860
23616
  var import_util4 = require("util");
22861
23617
  var import_picocolors8 = __toESM(require("picocolors"));
22862
- var path40 = __toESM(require("path"));
22863
- var execFileP5 = (0, import_util4.promisify)(import_child_process16.execFile);
23618
+ var path43 = __toESM(require("path"));
23619
+ var execFileP5 = (0, import_util4.promisify)(import_child_process19.execFile);
22864
23620
  var MAX_BUFFER = 8 * 1024 * 1024;
22865
23621
  function resetStdinForChild() {
22866
23622
  if (process.stdin.isTTY) {
@@ -22903,12 +23659,12 @@ var GitHubCodespacesProvider = class {
22903
23659
  }
22904
23660
  if (!isAuthed) {
22905
23661
  resetStdinForChild();
22906
- await new Promise((resolve6, reject) => {
22907
- const proc = (0, import_child_process16.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
23662
+ await new Promise((resolve7, reject) => {
23663
+ const proc = (0, import_child_process19.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
22908
23664
  stdio: "inherit"
22909
23665
  });
22910
23666
  proc.on("exit", (code) => {
22911
- if (code === 0) resolve6();
23667
+ if (code === 0) resolve7();
22912
23668
  else reject(new Error("gh auth login failed."));
22913
23669
  });
22914
23670
  proc.on("error", reject);
@@ -22937,13 +23693,13 @@ var GitHubCodespacesProvider = class {
22937
23693
  }
22938
23694
  wt(noteLines.join("\n"), "One more permission needed");
22939
23695
  resetStdinForChild();
22940
- const refreshCode = await new Promise((resolve6, reject) => {
22941
- const proc = (0, import_child_process16.spawn)(
23696
+ const refreshCode = await new Promise((resolve7, reject) => {
23697
+ const proc = (0, import_child_process19.spawn)(
22942
23698
  "gh",
22943
23699
  ["auth", "refresh", "-h", "github.com", "-s", "codespace"],
22944
23700
  { stdio: "inherit" }
22945
23701
  );
22946
- proc.on("exit", (code) => resolve6(code ?? 1));
23702
+ proc.on("exit", (code) => resolve7(code ?? 1));
22947
23703
  proc.on("error", reject);
22948
23704
  });
22949
23705
  if (refreshCode !== 0) {
@@ -23087,10 +23843,10 @@ var GitHubCodespacesProvider = class {
23087
23843
  if (q(proceed) || !proceed) return;
23088
23844
  O2.step(`Installing gh via ${installCmd.describe}\u2026`);
23089
23845
  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));
23846
+ const ok = await new Promise((resolve7) => {
23847
+ const proc = (0, import_child_process19.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
23848
+ proc.on("exit", (code) => resolve7(code === 0));
23849
+ proc.on("error", () => resolve7(false));
23094
23850
  });
23095
23851
  if (ok) O2.success("gh installed");
23096
23852
  else O2.error("gh install failed");
@@ -23114,14 +23870,14 @@ var GitHubCodespacesProvider = class {
23114
23870
  "Expanding GitHub scopes"
23115
23871
  );
23116
23872
  resetStdinForChild();
23117
- await new Promise((resolve6, reject) => {
23118
- const proc = (0, import_child_process16.spawn)(
23873
+ await new Promise((resolve7, reject) => {
23874
+ const proc = (0, import_child_process19.spawn)(
23119
23875
  "gh",
23120
23876
  ["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
23121
23877
  { stdio: "inherit" }
23122
23878
  );
23123
23879
  proc.on("exit", (code) => {
23124
- if (code === 0) resolve6();
23880
+ if (code === 0) resolve7();
23125
23881
  else reject(new Error(
23126
23882
  "gh auth refresh failed. Re-run `gh auth refresh -h github.com -s repo,read:org` manually."
23127
23883
  ));
@@ -23292,13 +24048,13 @@ var GitHubCodespacesProvider = class {
23292
24048
  }
23293
24049
  async streamCommand(workspaceId, command2) {
23294
24050
  resetStdinForChild();
23295
- return new Promise((resolve6, reject) => {
23296
- const proc = (0, import_child_process16.spawn)(
24051
+ return new Promise((resolve7, reject) => {
24052
+ const proc = (0, import_child_process19.spawn)(
23297
24053
  "gh",
23298
24054
  ["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
23299
24055
  { stdio: "inherit" }
23300
24056
  );
23301
- proc.on("exit", (code) => resolve6({ code: code ?? 0 }));
24057
+ proc.on("exit", (code) => resolve7({ code: code ?? 0 }));
23302
24058
  proc.on("error", reject);
23303
24059
  });
23304
24060
  }
@@ -23319,12 +24075,12 @@ var GitHubCodespacesProvider = class {
23319
24075
  "--",
23320
24076
  `mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
23321
24077
  ];
23322
- await new Promise((resolve6, reject) => {
23323
- const tar = (0, import_child_process16.spawn)("tar", tarArgs, {
24078
+ await new Promise((resolve7, reject) => {
24079
+ const tar = (0, import_child_process19.spawn)("tar", tarArgs, {
23324
24080
  stdio: ["ignore", "pipe", "pipe"],
23325
24081
  env: tarEnv
23326
24082
  });
23327
- const ssh = (0, import_child_process16.spawn)("gh", sshArgs, {
24083
+ const ssh = (0, import_child_process19.spawn)("gh", sshArgs, {
23328
24084
  stdio: [tar.stdout, "pipe", "pipe"]
23329
24085
  });
23330
24086
  let tarErr = "";
@@ -23339,7 +24095,7 @@ var GitHubCodespacesProvider = class {
23339
24095
  ssh.on("error", reject);
23340
24096
  ssh.on("exit", (code) => {
23341
24097
  if (code === 0) {
23342
- resolve6();
24098
+ resolve7();
23343
24099
  } else {
23344
24100
  const reason = (sshErr || tarErr || `exit ${code}`).trim().slice(0, 500);
23345
24101
  reject(new Error(`Remote tar failed: ${reason}`));
@@ -23348,7 +24104,7 @@ var GitHubCodespacesProvider = class {
23348
24104
  });
23349
24105
  }
23350
24106
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
23351
- const remoteDir = path40.posix.dirname(remotePath);
24107
+ const remoteDir = path43.posix.dirname(remotePath);
23352
24108
  const parts = [
23353
24109
  `mkdir -p ${shellQuote(remoteDir)}`,
23354
24110
  `cat > ${shellQuote(remotePath)}`
@@ -23357,8 +24113,8 @@ var GitHubCodespacesProvider = class {
23357
24113
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote(remotePath)}`);
23358
24114
  }
23359
24115
  const cmd = parts.join(" && ");
23360
- await new Promise((resolve6, reject) => {
23361
- const proc = (0, import_child_process16.spawn)(
24116
+ await new Promise((resolve7, reject) => {
24117
+ const proc = (0, import_child_process19.spawn)(
23362
24118
  "gh",
23363
24119
  ["codespace", "ssh", "-c", workspaceId, "--", cmd],
23364
24120
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -23369,7 +24125,7 @@ var GitHubCodespacesProvider = class {
23369
24125
  });
23370
24126
  proc.on("error", reject);
23371
24127
  proc.on("exit", (code) => {
23372
- if (code === 0) resolve6();
24128
+ if (code === 0) resolve7();
23373
24129
  else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
23374
24130
  });
23375
24131
  proc.stdin?.write(contents);
@@ -23416,11 +24172,11 @@ function shellQuote(s) {
23416
24172
  }
23417
24173
 
23418
24174
  // src/services/providers/gitpod.ts
23419
- var import_child_process17 = require("child_process");
24175
+ var import_child_process20 = require("child_process");
23420
24176
  var import_util5 = require("util");
23421
- var path41 = __toESM(require("path"));
24177
+ var path44 = __toESM(require("path"));
23422
24178
  var import_picocolors9 = __toESM(require("picocolors"));
23423
- var execFileP6 = (0, import_util5.promisify)(import_child_process17.execFile);
24179
+ var execFileP6 = (0, import_util5.promisify)(import_child_process20.execFile);
23424
24180
  var MAX_BUFFER2 = 8 * 1024 * 1024;
23425
24181
  function resetStdinForChild2() {
23426
24182
  if (process.stdin.isTTY) {
@@ -23459,10 +24215,10 @@ var GitpodProvider = class {
23459
24215
  "Authenticating Gitpod"
23460
24216
  );
23461
24217
  resetStdinForChild2();
23462
- await new Promise((resolve6, reject) => {
23463
- const proc = (0, import_child_process17.spawn)("gitpod", ["login"], { stdio: "inherit" });
24218
+ await new Promise((resolve7, reject) => {
24219
+ const proc = (0, import_child_process20.spawn)("gitpod", ["login"], { stdio: "inherit" });
23464
24220
  proc.on("exit", (code) => {
23465
- if (code === 0) resolve6();
24221
+ if (code === 0) resolve7();
23466
24222
  else reject(new Error("gitpod login failed."));
23467
24223
  });
23468
24224
  proc.on("error", reject);
@@ -23611,13 +24367,13 @@ var GitpodProvider = class {
23611
24367
  }
23612
24368
  async streamCommand(workspaceId, command2) {
23613
24369
  resetStdinForChild2();
23614
- return new Promise((resolve6, reject) => {
23615
- const proc = (0, import_child_process17.spawn)(
24370
+ return new Promise((resolve7, reject) => {
24371
+ const proc = (0, import_child_process20.spawn)(
23616
24372
  "gitpod",
23617
24373
  ["workspace", "ssh", workspaceId, "--", "-tt", command2],
23618
24374
  { stdio: "inherit" }
23619
24375
  );
23620
- proc.on("exit", (code) => resolve6({ code: code ?? 0 }));
24376
+ proc.on("exit", (code) => resolve7({ code: code ?? 0 }));
23621
24377
  proc.on("error", reject);
23622
24378
  });
23623
24379
  }
@@ -23631,12 +24387,12 @@ var GitpodProvider = class {
23631
24387
  tarArgs.push(".");
23632
24388
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
23633
24389
  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, {
24390
+ await new Promise((resolve7, reject) => {
24391
+ const tar = (0, import_child_process20.spawn)("tar", tarArgs, {
23636
24392
  stdio: ["ignore", "pipe", "pipe"],
23637
24393
  env: tarEnv
23638
24394
  });
23639
- const ssh = (0, import_child_process17.spawn)(
24395
+ const ssh = (0, import_child_process20.spawn)(
23640
24396
  "gitpod",
23641
24397
  ["workspace", "ssh", workspaceId, "--", remoteCmd],
23642
24398
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -23652,13 +24408,13 @@ var GitpodProvider = class {
23652
24408
  tar.on("error", reject);
23653
24409
  ssh.on("error", reject);
23654
24410
  ssh.on("exit", (code) => {
23655
- if (code === 0) resolve6();
24411
+ if (code === 0) resolve7();
23656
24412
  else reject(new Error(`Remote tar failed: ${(sshErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
23657
24413
  });
23658
24414
  });
23659
24415
  }
23660
24416
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
23661
- const remoteDir = path41.posix.dirname(remotePath);
24417
+ const remoteDir = path44.posix.dirname(remotePath);
23662
24418
  const parts = [
23663
24419
  `mkdir -p ${shellQuote2(remoteDir)}`,
23664
24420
  `cat > ${shellQuote2(remotePath)}`
@@ -23667,8 +24423,8 @@ var GitpodProvider = class {
23667
24423
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote2(remotePath)}`);
23668
24424
  }
23669
24425
  const cmd = parts.join(" && ");
23670
- await new Promise((resolve6, reject) => {
23671
- const proc = (0, import_child_process17.spawn)(
24426
+ await new Promise((resolve7, reject) => {
24427
+ const proc = (0, import_child_process20.spawn)(
23672
24428
  "gitpod",
23673
24429
  ["workspace", "ssh", workspaceId, "--", cmd],
23674
24430
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -23679,7 +24435,7 @@ var GitpodProvider = class {
23679
24435
  });
23680
24436
  proc.on("error", reject);
23681
24437
  proc.on("exit", (code) => {
23682
- if (code === 0) resolve6();
24438
+ if (code === 0) resolve7();
23683
24439
  else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
23684
24440
  });
23685
24441
  proc.stdin?.write(contents);
@@ -23692,10 +24448,10 @@ function shellQuote2(s) {
23692
24448
  }
23693
24449
 
23694
24450
  // src/services/providers/gitlab-workspaces.ts
23695
- var import_child_process18 = require("child_process");
24451
+ var import_child_process21 = require("child_process");
23696
24452
  var import_util6 = require("util");
23697
- var path42 = __toESM(require("path"));
23698
- var execFileP7 = (0, import_util6.promisify)(import_child_process18.execFile);
24453
+ var path45 = __toESM(require("path"));
24454
+ var execFileP7 = (0, import_util6.promisify)(import_child_process21.execFile);
23699
24455
  var MAX_BUFFER3 = 8 * 1024 * 1024;
23700
24456
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
23701
24457
  function resetStdinForChild3() {
@@ -23736,14 +24492,14 @@ var GitLabWorkspacesProvider = class {
23736
24492
  "Authenticating GitLab"
23737
24493
  );
23738
24494
  resetStdinForChild3();
23739
- await new Promise((resolve6, reject) => {
23740
- const proc = (0, import_child_process18.spawn)(
24495
+ await new Promise((resolve7, reject) => {
24496
+ const proc = (0, import_child_process21.spawn)(
23741
24497
  "glab",
23742
24498
  ["auth", "login", "--scopes", "api,read_user,read_repository"],
23743
24499
  { stdio: "inherit" }
23744
24500
  );
23745
24501
  proc.on("exit", (code) => {
23746
- if (code === 0) resolve6();
24502
+ if (code === 0) resolve7();
23747
24503
  else reject(new Error("glab auth login failed."));
23748
24504
  });
23749
24505
  proc.on("error", reject);
@@ -23908,13 +24664,13 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
23908
24664
  async streamCommand(workspaceId, command2) {
23909
24665
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
23910
24666
  resetStdinForChild3();
23911
- return new Promise((resolve6, reject) => {
23912
- const proc = (0, import_child_process18.spawn)(
24667
+ return new Promise((resolve7, reject) => {
24668
+ const proc = (0, import_child_process21.spawn)(
23913
24669
  "ssh",
23914
24670
  ["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
23915
24671
  { stdio: "inherit" }
23916
24672
  );
23917
- proc.on("exit", (code) => resolve6({ code: code ?? 0 }));
24673
+ proc.on("exit", (code) => resolve7({ code: code ?? 0 }));
23918
24674
  proc.on("error", reject);
23919
24675
  });
23920
24676
  }
@@ -23929,9 +24685,9 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
23929
24685
  tarArgs.push(".");
23930
24686
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
23931
24687
  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)(
24688
+ await new Promise((resolve7, reject) => {
24689
+ const tar = (0, import_child_process21.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
24690
+ const ssh = (0, import_child_process21.spawn)(
23935
24691
  "ssh",
23936
24692
  ["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, remoteCmd],
23937
24693
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -23947,21 +24703,21 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
23947
24703
  tar.on("error", reject);
23948
24704
  ssh.on("error", reject);
23949
24705
  ssh.on("exit", (code) => {
23950
- if (code === 0) resolve6();
24706
+ if (code === 0) resolve7();
23951
24707
  else reject(new Error(`Remote tar failed: ${(sshErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
23952
24708
  });
23953
24709
  });
23954
24710
  }
23955
24711
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
23956
24712
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
23957
- const remoteDir = path42.posix.dirname(remotePath);
24713
+ const remoteDir = path45.posix.dirname(remotePath);
23958
24714
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
23959
24715
  if (options.mode != null) {
23960
24716
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
23961
24717
  }
23962
24718
  const cmd = parts.join(" && ");
23963
- await new Promise((resolve6, reject) => {
23964
- const proc = (0, import_child_process18.spawn)(
24719
+ await new Promise((resolve7, reject) => {
24720
+ const proc = (0, import_child_process21.spawn)(
23965
24721
  "ssh",
23966
24722
  ["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
23967
24723
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -23972,7 +24728,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
23972
24728
  });
23973
24729
  proc.on("error", reject);
23974
24730
  proc.on("exit", (code) => {
23975
- if (code === 0) resolve6();
24731
+ if (code === 0) resolve7();
23976
24732
  else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
23977
24733
  });
23978
24734
  proc.stdin?.write(contents);
@@ -24020,10 +24776,10 @@ function shellQuote3(s) {
24020
24776
  }
24021
24777
 
24022
24778
  // src/services/providers/railway.ts
24023
- var import_child_process19 = require("child_process");
24779
+ var import_child_process22 = require("child_process");
24024
24780
  var import_util7 = require("util");
24025
- var path43 = __toESM(require("path"));
24026
- var execFileP8 = (0, import_util7.promisify)(import_child_process19.execFile);
24781
+ var path46 = __toESM(require("path"));
24782
+ var execFileP8 = (0, import_util7.promisify)(import_child_process22.execFile);
24027
24783
  var MAX_BUFFER4 = 8 * 1024 * 1024;
24028
24784
  function resetStdinForChild4() {
24029
24785
  if (process.stdin.isTTY) {
@@ -24063,10 +24819,10 @@ var RailwayProvider = class {
24063
24819
  "Authenticating Railway"
24064
24820
  );
24065
24821
  resetStdinForChild4();
24066
- await new Promise((resolve6, reject) => {
24067
- const proc = (0, import_child_process19.spawn)("railway", ["login"], { stdio: "inherit" });
24822
+ await new Promise((resolve7, reject) => {
24823
+ const proc = (0, import_child_process22.spawn)("railway", ["login"], { stdio: "inherit" });
24068
24824
  proc.on("exit", (code) => {
24069
- if (code === 0) resolve6();
24825
+ if (code === 0) resolve7();
24070
24826
  else reject(new Error("railway login failed."));
24071
24827
  });
24072
24828
  proc.on("error", reject);
@@ -24206,13 +24962,13 @@ var RailwayProvider = class {
24206
24962
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
24207
24963
  }
24208
24964
  resetStdinForChild4();
24209
- return new Promise((resolve6, reject) => {
24210
- const proc = (0, import_child_process19.spawn)(
24965
+ return new Promise((resolve7, reject) => {
24966
+ const proc = (0, import_child_process22.spawn)(
24211
24967
  "railway",
24212
24968
  ["shell", "--project", projectId, "--service", serviceId, "--command", command2],
24213
24969
  { stdio: "inherit" }
24214
24970
  );
24215
- proc.on("exit", (code) => resolve6({ code: code ?? 0 }));
24971
+ proc.on("exit", (code) => resolve7({ code: code ?? 0 }));
24216
24972
  proc.on("error", reject);
24217
24973
  });
24218
24974
  }
@@ -24230,9 +24986,9 @@ var RailwayProvider = class {
24230
24986
  tarArgs.push(".");
24231
24987
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
24232
24988
  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)(
24989
+ await new Promise((resolve7, reject) => {
24990
+ const tar = (0, import_child_process22.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
24991
+ const sh = (0, import_child_process22.spawn)(
24236
24992
  "railway",
24237
24993
  ["shell", "--project", projectId, "--service", serviceId, "--command", remoteCmd],
24238
24994
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -24248,7 +25004,7 @@ var RailwayProvider = class {
24248
25004
  tar.on("error", reject);
24249
25005
  sh.on("error", reject);
24250
25006
  sh.on("exit", (code) => {
24251
- if (code === 0) resolve6();
25007
+ if (code === 0) resolve7();
24252
25008
  else reject(new Error(`Remote tar failed: ${(shErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
24253
25009
  });
24254
25010
  });
@@ -24258,14 +25014,14 @@ var RailwayProvider = class {
24258
25014
  if (!projectId || !serviceId) {
24259
25015
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
24260
25016
  }
24261
- const remoteDir = path43.posix.dirname(remotePath);
25017
+ const remoteDir = path46.posix.dirname(remotePath);
24262
25018
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
24263
25019
  if (options.mode != null) {
24264
25020
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
24265
25021
  }
24266
25022
  const cmd = parts.join(" && ");
24267
- await new Promise((resolve6, reject) => {
24268
- const proc = (0, import_child_process19.spawn)(
25023
+ await new Promise((resolve7, reject) => {
25024
+ const proc = (0, import_child_process22.spawn)(
24269
25025
  "railway",
24270
25026
  ["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
24271
25027
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -24276,7 +25032,7 @@ var RailwayProvider = class {
24276
25032
  });
24277
25033
  proc.on("error", reject);
24278
25034
  proc.on("exit", (code) => {
24279
- if (code === 0) resolve6();
25035
+ if (code === 0) resolve7();
24280
25036
  else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
24281
25037
  });
24282
25038
  proc.stdin?.write(contents);
@@ -24801,8 +25557,8 @@ async function stopWorkspaceFromLocal(target) {
24801
25557
  var import_node_dns = require("dns");
24802
25558
  var import_node_util4 = require("util");
24803
25559
  var import_node_crypto8 = require("crypto");
24804
- var fs34 = __toESM(require("fs"));
24805
- var path44 = __toESM(require("path"));
25560
+ var fs36 = __toESM(require("fs"));
25561
+ var path47 = __toESM(require("path"));
24806
25562
  var import_picocolors12 = __toESM(require("picocolors"));
24807
25563
  var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
24808
25564
  async function checkDns(apiBase) {
@@ -24858,13 +25614,13 @@ async function checkHealth(apiBase) {
24858
25614
  }
24859
25615
  }
24860
25616
  function checkConfigDir() {
24861
- const dir = path44.join(require("os").homedir(), ".codeam");
25617
+ const dir = path47.join(require("os").homedir(), ".codeam");
24862
25618
  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);
25619
+ fs36.mkdirSync(dir, { recursive: true, mode: 448 });
25620
+ const probe = path47.join(dir, ".doctor-probe");
25621
+ fs36.writeFileSync(probe, "ok", { mode: 384 });
25622
+ const read = fs36.readFileSync(probe, "utf8");
25623
+ fs36.unlinkSync(probe);
24868
25624
  if (read !== "ok") throw new Error("write/read round-trip mismatch");
24869
25625
  return {
24870
25626
  id: "config-dir",
@@ -24904,9 +25660,9 @@ function checkSessions() {
24904
25660
  }
24905
25661
  }
24906
25662
  function checkAgentBinaries() {
24907
- const os29 = createOsStrategy();
25663
+ const os30 = createOsStrategy();
24908
25664
  return getEnabledAgents().map((meta) => {
24909
- const found = os29.findInPath(meta.binaryName);
25665
+ const found = os30.findInPath(meta.binaryName);
24910
25666
  return {
24911
25667
  id: `agent-${meta.id}`,
24912
25668
  label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
@@ -24928,7 +25684,7 @@ function checkNodePty() {
24928
25684
  detail: "not required on this platform"
24929
25685
  };
24930
25686
  }
24931
- const vendoredPath = path44.join(__dirname, "vendor", "node-pty");
25687
+ const vendoredPath = path47.join(__dirname, "vendor", "node-pty");
24932
25688
  for (const target of [vendoredPath, "node-pty"]) {
24933
25689
  try {
24934
25690
  require(target);
@@ -24970,7 +25726,7 @@ function checkChokidar() {
24970
25726
  }
24971
25727
  async function doctor(args2 = []) {
24972
25728
  const json = args2.includes("--json");
24973
- const cliVersion = true ? "2.32.10" : "0.0.0-dev";
25729
+ const cliVersion = true ? "2.33.0" : "0.0.0-dev";
24974
25730
  const apiBase = resolveApiBaseUrl();
24975
25731
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
24976
25732
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -25169,7 +25925,7 @@ async function completion(args2) {
25169
25925
  // src/commands/version.ts
25170
25926
  var import_picocolors13 = __toESM(require("picocolors"));
25171
25927
  function version2() {
25172
- const v = true ? "2.32.10" : "unknown";
25928
+ const v = true ? "2.33.0" : "unknown";
25173
25929
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
25174
25930
  }
25175
25931
 
@@ -25297,9 +26053,9 @@ function tryShowSubcommandHelp(cmd, args2) {
25297
26053
  var _subcommandHelpKeys = Object.keys(HELPS);
25298
26054
 
25299
26055
  // src/lib/updateNotifier.ts
25300
- var fs35 = __toESM(require("fs"));
25301
- var os28 = __toESM(require("os"));
25302
- var path45 = __toESM(require("path"));
26056
+ var fs37 = __toESM(require("fs"));
26057
+ var os29 = __toESM(require("os"));
26058
+ var path48 = __toESM(require("path"));
25303
26059
  var https8 = __toESM(require("https"));
25304
26060
  var import_node_child_process12 = require("child_process");
25305
26061
  var import_picocolors16 = __toESM(require("picocolors"));
@@ -25308,12 +26064,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
25308
26064
  var TTL_MS = 24 * 60 * 60 * 1e3;
25309
26065
  var REQUEST_TIMEOUT_MS = 1500;
25310
26066
  function cachePath() {
25311
- const dir = path45.join(os28.homedir(), ".codeam");
25312
- return path45.join(dir, "update-check.json");
26067
+ const dir = path48.join(os29.homedir(), ".codeam");
26068
+ return path48.join(dir, "update-check.json");
25313
26069
  }
25314
26070
  function readCache() {
25315
26071
  try {
25316
- const raw = fs35.readFileSync(cachePath(), "utf8");
26072
+ const raw = fs37.readFileSync(cachePath(), "utf8");
25317
26073
  const parsed = JSON.parse(raw);
25318
26074
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
25319
26075
  return parsed;
@@ -25324,10 +26080,10 @@ function readCache() {
25324
26080
  function writeCache(cache) {
25325
26081
  try {
25326
26082
  const file = cachePath();
25327
- fs35.mkdirSync(path45.dirname(file), { recursive: true });
26083
+ fs37.mkdirSync(path48.dirname(file), { recursive: true });
25328
26084
  const tmp = `${file}.${process.pid}.tmp`;
25329
- fs35.writeFileSync(tmp, JSON.stringify(cache));
25330
- fs35.renameSync(tmp, file);
26085
+ fs37.writeFileSync(tmp, JSON.stringify(cache));
26086
+ fs37.renameSync(tmp, file);
25331
26087
  } catch {
25332
26088
  }
25333
26089
  }
@@ -25345,14 +26101,14 @@ function compareSemver(a, b) {
25345
26101
  return 0;
25346
26102
  }
25347
26103
  function fetchLatest() {
25348
- return new Promise((resolve6) => {
26104
+ return new Promise((resolve7) => {
25349
26105
  const req = https8.get(
25350
26106
  REGISTRY_URL,
25351
26107
  { headers: { Accept: "application/json" }, timeout: REQUEST_TIMEOUT_MS },
25352
26108
  (res) => {
25353
26109
  if (res.statusCode !== 200) {
25354
26110
  res.resume();
25355
- resolve6(null);
26111
+ resolve7(null);
25356
26112
  return;
25357
26113
  }
25358
26114
  let buf = "";
@@ -25364,21 +26120,21 @@ function fetchLatest() {
25364
26120
  try {
25365
26121
  const json = JSON.parse(buf);
25366
26122
  if (typeof json.version === "string") {
25367
- resolve6(json.version);
26123
+ resolve7(json.version);
25368
26124
  } else {
25369
- resolve6(null);
26125
+ resolve7(null);
25370
26126
  }
25371
26127
  } catch {
25372
- resolve6(null);
26128
+ resolve7(null);
25373
26129
  }
25374
26130
  });
25375
26131
  }
25376
26132
  );
25377
26133
  req.on("timeout", () => {
25378
26134
  req.destroy();
25379
- resolve6(null);
26135
+ resolve7(null);
25380
26136
  });
25381
- req.on("error", () => resolve6(null));
26137
+ req.on("error", () => resolve7(null));
25382
26138
  });
25383
26139
  }
25384
26140
  function notifyIfStale(currentVersion, latest) {
@@ -25401,8 +26157,8 @@ function isLinkedInstall() {
25401
26157
  timeout: 2e3
25402
26158
  }).trim();
25403
26159
  if (!root) return false;
25404
- const pkgPath = path45.join(root, PKG_NAME);
25405
- return fs35.lstatSync(pkgPath).isSymbolicLink();
26160
+ const pkgPath = path48.join(root, PKG_NAME);
26161
+ return fs37.lstatSync(pkgPath).isSymbolicLink();
25406
26162
  } catch {
25407
26163
  return false;
25408
26164
  }
@@ -25438,7 +26194,7 @@ function maybeAutoUpdate(currentVersion, latest) {
25438
26194
  return;
25439
26195
  }
25440
26196
  try {
25441
- fs35.unlinkSync(cachePath());
26197
+ fs37.unlinkSync(cachePath());
25442
26198
  } catch {
25443
26199
  }
25444
26200
  process.stderr.write(` ${import_picocolors16.default.green("\u2713")} Updated. Resuming session...
@@ -25455,7 +26211,7 @@ function checkForUpdates() {
25455
26211
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
25456
26212
  if (process.env.CI) return;
25457
26213
  if (!process.stdout.isTTY) return;
25458
- const current = true ? "2.32.10" : null;
26214
+ const current = true ? "2.33.0" : null;
25459
26215
  if (!current) return;
25460
26216
  const cache = readCache();
25461
26217
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;