codeam-cli 2.39.24 → 2.39.25

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 +640 -200
  3. package/package.json +1 -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.39.24",
501
+ version: "2.39.25",
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",
@@ -1194,8 +1194,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
1194
1194
  return decodedFile;
1195
1195
  };
1196
1196
  }
1197
- function normalizeWindowsPath(path55) {
1198
- return path55.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1197
+ function normalizeWindowsPath(path58) {
1198
+ return path58.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1199
1199
  }
1200
1200
 
1201
1201
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -2347,10 +2347,10 @@ var PostHogCoreStateless = class {
2347
2347
  }
2348
2348
  async getRemoteConfig() {
2349
2349
  await this._initPromise;
2350
- let host = this.host;
2351
- if ("https://us.i.posthog.com" === host) host = "https://us-assets.i.posthog.com";
2352
- else if ("https://eu.i.posthog.com" === host) host = "https://eu-assets.i.posthog.com";
2353
- const url = `${host}/array/${this.apiKey}/config`;
2350
+ let host2 = this.host;
2351
+ if ("https://us.i.posthog.com" === host2) host2 = "https://us-assets.i.posthog.com";
2352
+ else if ("https://eu.i.posthog.com" === host2) host2 = "https://eu-assets.i.posthog.com";
2353
+ const url = `${host2}/array/${this.apiKey}/config`;
2354
2354
  const fetchOptions = {
2355
2355
  method: "GET",
2356
2356
  headers: {
@@ -3030,9 +3030,9 @@ var ErrorPropertiesBuilder = class {
3030
3030
 
3031
3031
  // ../../node_modules/@posthog/core/dist/error-tracking/parsers/base.mjs
3032
3032
  var UNKNOWN_FUNCTION = "?";
3033
- function createFrame(platform2, filename, func, lineno, colno) {
3033
+ function createFrame(platform3, filename, func, lineno, colno) {
3034
3034
  const frame = {
3035
- platform: platform2,
3035
+ platform: platform3,
3036
3036
  filename,
3037
3037
  function: "<anonymous>" === func ? UNKNOWN_FUNCTION : func,
3038
3038
  in_app: true
@@ -3059,11 +3059,11 @@ var extractSafariExtensionDetails = (func, filename) => {
3059
3059
  var chromeRegexNoFnName = /^\s*at (\S+?)(?::(\d+))(?::(\d+))\s*$/i;
3060
3060
  var chromeRegex = /^\s*at (?:(.+?\)(?: \[.+\])?|.*?) ?\((?:address at )?)?(?:async )?((?:<anonymous>|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
3061
3061
  var chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/;
3062
- var chromeStackLineParser = (line, platform2) => {
3062
+ var chromeStackLineParser = (line, platform3) => {
3063
3063
  const noFnParts = chromeRegexNoFnName.exec(line);
3064
3064
  if (noFnParts) {
3065
3065
  const [, filename, line2, col] = noFnParts;
3066
- return createFrame(platform2, filename, UNKNOWN_FUNCTION, +line2, +col);
3066
+ return createFrame(platform3, filename, UNKNOWN_FUNCTION, +line2, +col);
3067
3067
  }
3068
3068
  const parts = chromeRegex.exec(line);
3069
3069
  if (parts) {
@@ -3077,14 +3077,14 @@ var chromeStackLineParser = (line, platform2) => {
3077
3077
  }
3078
3078
  }
3079
3079
  const [func, filename] = extractSafariExtensionDetails(parts[1] || UNKNOWN_FUNCTION, parts[2]);
3080
- return createFrame(platform2, filename, func, parts[3] ? +parts[3] : void 0, parts[4] ? +parts[4] : void 0);
3080
+ return createFrame(platform3, filename, func, parts[3] ? +parts[3] : void 0, parts[4] ? +parts[4] : void 0);
3081
3081
  }
3082
3082
  };
3083
3083
 
3084
3084
  // ../../node_modules/@posthog/core/dist/error-tracking/parsers/gecko.mjs
3085
3085
  var geckoREgex = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:[-a-z]+)?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i;
3086
3086
  var geckoEvalRegex = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
3087
- var geckoStackLineParser = (line, platform2) => {
3087
+ var geckoStackLineParser = (line, platform3) => {
3088
3088
  const parts = geckoREgex.exec(line);
3089
3089
  if (parts) {
3090
3090
  const isEval = parts[3] && parts[3].indexOf(" > eval") > -1;
@@ -3100,33 +3100,33 @@ var geckoStackLineParser = (line, platform2) => {
3100
3100
  let filename = parts[3];
3101
3101
  let func = parts[1] || UNKNOWN_FUNCTION;
3102
3102
  [func, filename] = extractSafariExtensionDetails(func, filename);
3103
- return createFrame(platform2, filename, func, parts[4] ? +parts[4] : void 0, parts[5] ? +parts[5] : void 0);
3103
+ return createFrame(platform3, filename, func, parts[4] ? +parts[4] : void 0, parts[5] ? +parts[5] : void 0);
3104
3104
  }
3105
3105
  };
3106
3106
 
3107
3107
  // ../../node_modules/@posthog/core/dist/error-tracking/parsers/winjs.mjs
3108
3108
  var winjsRegex = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:[-a-z]+):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
3109
- var winjsStackLineParser = (line, platform2) => {
3109
+ var winjsStackLineParser = (line, platform3) => {
3110
3110
  const parts = winjsRegex.exec(line);
3111
- return parts ? createFrame(platform2, parts[2], parts[1] || UNKNOWN_FUNCTION, +parts[3], parts[4] ? +parts[4] : void 0) : void 0;
3111
+ return parts ? createFrame(platform3, parts[2], parts[1] || UNKNOWN_FUNCTION, +parts[3], parts[4] ? +parts[4] : void 0) : void 0;
3112
3112
  };
3113
3113
 
3114
3114
  // ../../node_modules/@posthog/core/dist/error-tracking/parsers/opera.mjs
3115
3115
  var opera10Regex = / line (\d+).*script (?:in )?(\S+)(?:: in function (\S+))?$/i;
3116
- var opera10StackLineParser = (line, platform2) => {
3116
+ var opera10StackLineParser = (line, platform3) => {
3117
3117
  const parts = opera10Regex.exec(line);
3118
- return parts ? createFrame(platform2, parts[2], parts[3] || UNKNOWN_FUNCTION, +parts[1]) : void 0;
3118
+ return parts ? createFrame(platform3, parts[2], parts[3] || UNKNOWN_FUNCTION, +parts[1]) : void 0;
3119
3119
  };
3120
3120
  var opera11Regex = / line (\d+), column (\d+)\s*(?:in (?:<anonymous function: ([^>]+)>|([^)]+))\(.*\))? in (.*):\s*$/i;
3121
- var opera11StackLineParser = (line, platform2) => {
3121
+ var opera11StackLineParser = (line, platform3) => {
3122
3122
  const parts = opera11Regex.exec(line);
3123
- return parts ? createFrame(platform2, parts[5], parts[3] || parts[4] || UNKNOWN_FUNCTION, +parts[1], +parts[2]) : void 0;
3123
+ return parts ? createFrame(platform3, parts[5], parts[3] || parts[4] || UNKNOWN_FUNCTION, +parts[1], +parts[2]) : void 0;
3124
3124
  };
3125
3125
 
3126
3126
  // ../../node_modules/@posthog/core/dist/error-tracking/parsers/node.mjs
3127
3127
  var FILENAME_MATCH = /^\s*[-]{4,}$/;
3128
3128
  var FULL_MATCH = /at (?:async )?(?:(.+?)\s+\()?(?:(.+):(\d+):(\d+)?|([^)]+))\)?/;
3129
- var nodeStackLineParser = (line, platform2) => {
3129
+ var nodeStackLineParser = (line, platform3) => {
3130
3130
  const lineMatch = line.match(FULL_MATCH);
3131
3131
  if (lineMatch) {
3132
3132
  let object;
@@ -3172,12 +3172,12 @@ var nodeStackLineParser = (line, platform2) => {
3172
3172
  lineno: _parseIntOrUndefined(lineMatch[3]),
3173
3173
  colno: _parseIntOrUndefined(lineMatch[4]),
3174
3174
  in_app: filenameIsInApp(filename || "", isNative),
3175
- platform: platform2
3175
+ platform: platform3
3176
3176
  };
3177
3177
  }
3178
3178
  if (line.match(FILENAME_MATCH)) return {
3179
3179
  filename: line,
3180
- platform: platform2
3180
+ platform: platform3
3181
3181
  };
3182
3182
  };
3183
3183
  function filenameIsInApp(filename, isNative = false) {
@@ -3207,7 +3207,7 @@ function getLastStackFrame(arr) {
3207
3207
  function createDefaultStackParser() {
3208
3208
  return createStackParser("web:javascript", chromeStackLineParser, geckoStackLineParser);
3209
3209
  }
3210
- function createStackParser(platform2, ...parsers) {
3210
+ function createStackParser(platform3, ...parsers) {
3211
3211
  return (stack, skipFirstLines = 0) => {
3212
3212
  const frames = [];
3213
3213
  const lines = stack.split("\n");
@@ -3217,7 +3217,7 @@ function createStackParser(platform2, ...parsers) {
3217
3217
  const cleanedLine = WEBPACK_ERROR_REGEXP.test(line) ? line.replace(WEBPACK_ERROR_REGEXP, "$1") : line;
3218
3218
  if (!cleanedLine.match(/\S*Error: /)) {
3219
3219
  for (const parser of parsers) {
3220
- const frame = parser(cleanedLine, platform2);
3220
+ const frame = parser(cleanedLine, platform3);
3221
3221
  if (frame) {
3222
3222
  frames.push(frame);
3223
3223
  break;
@@ -3675,9 +3675,9 @@ async function addSourceContext(frames) {
3675
3675
  LRU_FILE_CONTENTS_CACHE.reduce();
3676
3676
  return frames;
3677
3677
  }
3678
- function getContextLinesFromFile(path55, ranges, output) {
3678
+ function getContextLinesFromFile(path58, ranges, output) {
3679
3679
  return new Promise((resolve7) => {
3680
- const stream = (0, import_node_fs.createReadStream)(path55);
3680
+ const stream = (0, import_node_fs.createReadStream)(path58);
3681
3681
  const lineReaded = (0, import_node_readline.createInterface)({
3682
3682
  input: stream
3683
3683
  });
@@ -3692,7 +3692,7 @@ function getContextLinesFromFile(path55, ranges, output) {
3692
3692
  let rangeStart = range[0];
3693
3693
  let rangeEnd = range[1];
3694
3694
  function onStreamError() {
3695
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path55, 1);
3695
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path58, 1);
3696
3696
  lineReaded.close();
3697
3697
  lineReaded.removeAllListeners();
3698
3698
  destroyStreamAndResolve();
@@ -3753,8 +3753,8 @@ function clearLineContext(frame) {
3753
3753
  delete frame.context_line;
3754
3754
  delete frame.post_context;
3755
3755
  }
3756
- function shouldSkipContextLinesForFile(path55) {
3757
- return path55.startsWith("node:") || path55.endsWith(".min.js") || path55.endsWith(".min.cjs") || path55.endsWith(".min.mjs") || path55.startsWith("data:");
3756
+ function shouldSkipContextLinesForFile(path58) {
3757
+ return path58.startsWith("node:") || path58.endsWith(".min.js") || path58.endsWith(".min.cjs") || path58.endsWith(".min.mjs") || path58.startsWith("data:");
3758
3758
  }
3759
3759
  function shouldSkipContextLinesForFrame(frame) {
3760
3760
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -4109,7 +4109,7 @@ var RequiresServerEvaluation = class _RequiresServerEvaluation extends Error {
4109
4109
  }
4110
4110
  };
4111
4111
  var FeatureFlagsPoller = class {
4112
- constructor({ pollingInterval, personalApiKey, projectApiKey, timeout, host, customHeaders, ...options }) {
4112
+ constructor({ pollingInterval, personalApiKey, projectApiKey, timeout, host: host2, customHeaders, ...options }) {
4113
4113
  this.debugMode = false;
4114
4114
  this.shouldBeginExponentialBackoff = false;
4115
4115
  this.backOffCount = 0;
@@ -4122,7 +4122,7 @@ var FeatureFlagsPoller = class {
4122
4122
  this.loadedSuccessfullyOnce = false;
4123
4123
  this.timeout = timeout;
4124
4124
  this.projectApiKey = projectApiKey;
4125
- this.host = host;
4125
+ this.host = host2;
4126
4126
  this.poller = void 0;
4127
4127
  this.fetch = options.fetch || fetch;
4128
4128
  this.onError = options.onError;
@@ -5908,7 +5908,7 @@ function readAnonId() {
5908
5908
  }
5909
5909
  function superProperties() {
5910
5910
  return {
5911
- cliVersion: true ? "2.39.24" : "0.0.0-dev",
5911
+ cliVersion: true ? "2.39.25" : "0.0.0-dev",
5912
5912
  nodeVersion: process.version,
5913
5913
  platform: process.platform,
5914
5914
  arch: process.arch,
@@ -5942,10 +5942,10 @@ function initTelemetry() {
5942
5942
  log.trace("telemetry", "no PostHog API key baked into build \u2014 disabled");
5943
5943
  return false;
5944
5944
  }
5945
- const host = true ? "https://us.i.posthog.com" : "https://us.i.posthog.com";
5945
+ const host2 = true ? "https://us.i.posthog.com" : "https://us.i.posthog.com";
5946
5946
  distinctId = readAnonId();
5947
5947
  client = new PostHog(apiKey, {
5948
- host,
5948
+ host: host2,
5949
5949
  // 10s flush is generous for a CLI — most commands run < 30s
5950
5950
  // and we shutdown() before exit anyway. Per-batch size caps
5951
5951
  // memory growth on long-lived `codeam start` sessions.
@@ -5960,7 +5960,7 @@ function initTelemetry() {
5960
5960
  log.trace("telemetry", "posthog error (ignored)", err);
5961
5961
  });
5962
5962
  client.register(superProperties());
5963
- log.trace("telemetry", `posthog client initialised host=${host} distinctId=${distinctId}`);
5963
+ log.trace("telemetry", `posthog client initialised host=${host2} distinctId=${distinctId}`);
5964
5964
  return true;
5965
5965
  }
5966
5966
  function identifyUser(params) {
@@ -7287,8 +7287,8 @@ function createOsStrategy() {
7287
7287
  cached = buildForPlatform(process.platform);
7288
7288
  return cached;
7289
7289
  }
7290
- function buildForPlatform(platform2) {
7291
- switch (platform2) {
7290
+ function buildForPlatform(platform3) {
7291
+ switch (platform3) {
7292
7292
  case "darwin":
7293
7293
  return new DarwinOsStrategy();
7294
7294
  case "win32":
@@ -7302,10 +7302,10 @@ function buildForPlatform(platform2) {
7302
7302
  var import_node_crypto4 = require("crypto");
7303
7303
 
7304
7304
  // src/agents/claude/resolver.ts
7305
- function buildClaudeLaunch(extraArgs = [], os33 = createOsStrategy()) {
7306
- const found = os33.findInPath("claude") ?? os33.findInPath("claude-code");
7305
+ function buildClaudeLaunch(extraArgs = [], os36 = createOsStrategy()) {
7306
+ const found = os36.findInPath("claude") ?? os36.findInPath("claude-code");
7307
7307
  if (!found) return null;
7308
- return os33.buildLaunch(found, extraArgs);
7308
+ return os36.buildLaunch(found, extraArgs);
7309
7309
  }
7310
7310
 
7311
7311
  // src/agents/claude/installer.ts
@@ -9754,8 +9754,8 @@ var ClaudeRuntimeStrategy = class {
9754
9754
  meta = getAgent("claude");
9755
9755
  mode = "interactive";
9756
9756
  os;
9757
- constructor(os33) {
9758
- this.os = os33;
9757
+ constructor(os36) {
9758
+ this.os = os36;
9759
9759
  }
9760
9760
  /**
9761
9761
  * Claude Code's react-ink TUI enables bracketed-paste mode at
@@ -10374,8 +10374,8 @@ function codexCredentialLocator() {
10374
10374
  function codexLoginLauncher() {
10375
10375
  return {
10376
10376
  async ensureInstalled() {
10377
- const os33 = createOsStrategy();
10378
- return os33.findInPath("codex") !== null;
10377
+ const os36 = createOsStrategy();
10378
+ return os36.findInPath("codex") !== null;
10379
10379
  },
10380
10380
  launch() {
10381
10381
  return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
@@ -10398,8 +10398,8 @@ var CodexRuntimeStrategy = class {
10398
10398
  meta = getAgent("codex");
10399
10399
  mode = "interactive";
10400
10400
  os;
10401
- constructor(os33) {
10402
- this.os = os33;
10401
+ constructor(os36) {
10402
+ this.os = os36;
10403
10403
  }
10404
10404
  async prepareLaunch() {
10405
10405
  let binary = this.os.findInPath("codex");
@@ -10495,12 +10495,12 @@ var CodexRuntimeStrategy = class {
10495
10495
  });
10496
10496
  }
10497
10497
  };
10498
- function resolveNpm(os33) {
10499
- return os33.id === "win32" ? "npm.cmd" : "npm";
10498
+ function resolveNpm(os36) {
10499
+ return os36.id === "win32" ? "npm.cmd" : "npm";
10500
10500
  }
10501
- async function installCodexViaNpm(os33) {
10501
+ async function installCodexViaNpm(os36) {
10502
10502
  return new Promise((resolve7, reject) => {
10503
- const proc = (0, import_node_child_process4.spawn)(resolveNpm(os33), ["install", "-g", "@openai/codex"], {
10503
+ const proc = (0, import_node_child_process4.spawn)(resolveNpm(os36), ["install", "-g", "@openai/codex"], {
10504
10504
  stdio: "inherit"
10505
10505
  });
10506
10506
  proc.on("close", (code) => {
@@ -10517,16 +10517,16 @@ async function installCodexViaNpm(os33) {
10517
10517
  });
10518
10518
  });
10519
10519
  }
10520
- function augmentNpmGlobalBin(os33) {
10520
+ function augmentNpmGlobalBin(os36) {
10521
10521
  try {
10522
- const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os33), ["prefix", "-g"], {
10522
+ const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os36), ["prefix", "-g"], {
10523
10523
  stdio: ["ignore", "pipe", "ignore"]
10524
10524
  });
10525
10525
  if (result.status !== 0) return;
10526
10526
  const prefix = result.stdout.toString().trim();
10527
10527
  if (!prefix) return;
10528
- const binDir = os33.id === "win32" ? prefix : path17.join(prefix, "bin");
10529
- os33.augmentPath([binDir]);
10528
+ const binDir = os36.id === "win32" ? prefix : path17.join(prefix, "bin");
10529
+ os36.augmentPath([binDir]);
10530
10530
  } catch {
10531
10531
  }
10532
10532
  }
@@ -10610,9 +10610,9 @@ var import_node_child_process7 = require("child_process");
10610
10610
  // src/agents/coderabbit/installer.ts
10611
10611
  var import_node_child_process5 = require("child_process");
10612
10612
  var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
10613
- async function ensureCoderabbitInstalled(os33) {
10614
- if (os33.findInPath("coderabbit")) return true;
10615
- if (os33.id === "win32") {
10613
+ async function ensureCoderabbitInstalled(os36) {
10614
+ if (os36.findInPath("coderabbit")) return true;
10615
+ if (os36.id === "win32") {
10616
10616
  console.error(
10617
10617
  "\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"
10618
10618
  );
@@ -10627,8 +10627,8 @@ async function ensureCoderabbitInstalled(os33) {
10627
10627
  proc.on("error", () => resolve7(false));
10628
10628
  });
10629
10629
  if (!ok) return false;
10630
- os33.augmentPath([`${os33.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
10631
- return os33.findInPath("coderabbit") !== null;
10630
+ os36.augmentPath([`${os36.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
10631
+ return os36.findInPath("coderabbit") !== null;
10632
10632
  }
10633
10633
 
10634
10634
  // src/agents/coderabbit/link.ts
@@ -10655,10 +10655,10 @@ function coderabbitCredentialLocator() {
10655
10655
  extract: extractLocalCoderabbitToken
10656
10656
  };
10657
10657
  }
10658
- function coderabbitLoginLauncher(os33) {
10658
+ function coderabbitLoginLauncher(os36) {
10659
10659
  return {
10660
10660
  async ensureInstalled() {
10661
- return ensureCoderabbitInstalled(os33);
10661
+ return ensureCoderabbitInstalled(os36);
10662
10662
  },
10663
10663
  launch() {
10664
10664
  return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
@@ -10681,11 +10681,11 @@ function parseReview(stdout) {
10681
10681
  for (const line of lines) {
10682
10682
  const m = line.match(HUNK_LINE_RE);
10683
10683
  if (!m) continue;
10684
- const [, path55, lineNo, sevToken, message] = m;
10685
- if (!path55 || !lineNo || !message) continue;
10684
+ const [, path58, lineNo, sevToken, message] = m;
10685
+ if (!path58 || !lineNo || !message) continue;
10686
10686
  const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
10687
10687
  hunks.push({
10688
- path: path55.trim(),
10688
+ path: path58.trim(),
10689
10689
  line: Number(lineNo),
10690
10690
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
10691
10691
  message: cleanedMessage
@@ -10704,8 +10704,8 @@ var CoderabbitRuntimeStrategy = class {
10704
10704
  meta = getAgent("coderabbit");
10705
10705
  mode = "batch";
10706
10706
  os;
10707
- constructor(os33) {
10708
- this.os = os33;
10707
+ constructor(os36) {
10708
+ this.os = os36;
10709
10709
  }
10710
10710
  getDefaultArgs() {
10711
10711
  return ["review"];
@@ -10820,10 +10820,10 @@ function cursorCredentialLocator() {
10820
10820
  extract: extractLocalCursorToken
10821
10821
  };
10822
10822
  }
10823
- function cursorLoginLauncher(os33) {
10823
+ function cursorLoginLauncher(os36) {
10824
10824
  return {
10825
10825
  async ensureInstalled() {
10826
- if (os33.findInPath("cursor-agent")) return true;
10826
+ if (os36.findInPath("cursor-agent")) return true;
10827
10827
  console.error(
10828
10828
  "\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"
10829
10829
  );
@@ -10885,8 +10885,8 @@ var CursorRuntimeStrategy = class {
10885
10885
  meta = getAgent("cursor");
10886
10886
  mode = "interactive";
10887
10887
  os;
10888
- constructor(os33) {
10889
- this.os = os33;
10888
+ constructor(os36) {
10889
+ this.os = os36;
10890
10890
  }
10891
10891
  async prepareLaunch() {
10892
10892
  const binary = this.os.findInPath("cursor-agent");
@@ -11006,10 +11006,10 @@ function aiderCredentialLocator() {
11006
11006
  extract: extractLocalAiderToken
11007
11007
  };
11008
11008
  }
11009
- function aiderLoginLauncher(os33) {
11009
+ function aiderLoginLauncher(os36) {
11010
11010
  return {
11011
11011
  async ensureInstalled() {
11012
- if (os33.findInPath("aider")) return true;
11012
+ if (os36.findInPath("aider")) return true;
11013
11013
  console.error(
11014
11014
  "\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
11015
11015
  );
@@ -11019,7 +11019,7 @@ function aiderLoginLauncher(os33) {
11019
11019
  console.error(
11020
11020
  "\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"
11021
11021
  );
11022
- return (0, import_node_child_process9.spawn)(os33.id === "win32" ? "cmd.exe" : "sh", os33.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
11022
+ return (0, import_node_child_process9.spawn)(os36.id === "win32" ? "cmd.exe" : "sh", os36.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
11023
11023
  stdio: "ignore"
11024
11024
  });
11025
11025
  }
@@ -11091,8 +11091,8 @@ var AiderRuntimeStrategy = class {
11091
11091
  meta = getAgent("aider");
11092
11092
  mode = "interactive";
11093
11093
  os;
11094
- constructor(os33) {
11095
- this.os = os33;
11094
+ constructor(os36) {
11095
+ this.os = os36;
11096
11096
  }
11097
11097
  async prepareLaunch() {
11098
11098
  const binary = this.os.findInPath("aider");
@@ -11221,8 +11221,8 @@ function geminiCredentialLocator() {
11221
11221
  function geminiLoginLauncher() {
11222
11222
  return {
11223
11223
  async ensureInstalled() {
11224
- const os33 = createOsStrategy();
11225
- return os33.findInPath("gemini") !== null;
11224
+ const os36 = createOsStrategy();
11225
+ return os36.findInPath("gemini") !== null;
11226
11226
  },
11227
11227
  launch() {
11228
11228
  return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
@@ -11255,8 +11255,8 @@ var GeminiRuntimeStrategy = class {
11255
11255
  meta = getAgent("gemini");
11256
11256
  mode = "interactive";
11257
11257
  os;
11258
- constructor(os33) {
11259
- this.os = os33;
11258
+ constructor(os36) {
11259
+ this.os = os36;
11260
11260
  }
11261
11261
  async prepareLaunch() {
11262
11262
  const binary = this.os.findInPath("gemini");
@@ -11355,18 +11355,18 @@ var GeminiRuntimeStrategy = class {
11355
11355
 
11356
11356
  // src/agents/registry.ts
11357
11357
  var runtimeBuilders = {
11358
- claude: (os33) => new ClaudeRuntimeStrategy(os33),
11359
- codex: (os33) => new CodexRuntimeStrategy(os33),
11360
- coderabbit: (os33) => new CoderabbitRuntimeStrategy(os33),
11361
- cursor: (os33) => new CursorRuntimeStrategy(os33),
11362
- aider: (os33) => new AiderRuntimeStrategy(os33),
11363
- gemini: (os33) => new GeminiRuntimeStrategy(os33)
11358
+ claude: (os36) => new ClaudeRuntimeStrategy(os36),
11359
+ codex: (os36) => new CodexRuntimeStrategy(os36),
11360
+ coderabbit: (os36) => new CoderabbitRuntimeStrategy(os36),
11361
+ cursor: (os36) => new CursorRuntimeStrategy(os36),
11362
+ aider: (os36) => new AiderRuntimeStrategy(os36),
11363
+ gemini: (os36) => new GeminiRuntimeStrategy(os36)
11364
11364
  };
11365
11365
  var deployBuilders = {
11366
11366
  claude: () => new ClaudeDeployStrategy(),
11367
11367
  codex: () => new CodexDeployStrategy()
11368
11368
  };
11369
- function createAgentStrategy(agent, os33 = createOsStrategy()) {
11369
+ function createAgentStrategy(agent, os36 = createOsStrategy()) {
11370
11370
  if (!AGENT_REGISTRY[agent]?.enabled) {
11371
11371
  throw new Error(
11372
11372
  `Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
@@ -11376,10 +11376,10 @@ function createAgentStrategy(agent, os33 = createOsStrategy()) {
11376
11376
  if (!build) {
11377
11377
  throw new Error(`No runtime strategy registered for agent "${agent}"`);
11378
11378
  }
11379
- return build(os33);
11379
+ return build(os36);
11380
11380
  }
11381
- function createInteractiveAgentStrategy(agent, os33 = createOsStrategy()) {
11382
- const s = createAgentStrategy(agent, os33);
11381
+ function createInteractiveAgentStrategy(agent, os36 = createOsStrategy()) {
11382
+ const s = createAgentStrategy(agent, os36);
11383
11383
  if (s.mode !== "interactive") {
11384
11384
  throw new Error(
11385
11385
  `Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
@@ -16508,16 +16508,16 @@ async function downloadCloudflared(target) {
16508
16508
  );
16509
16509
  }
16510
16510
  function downloadUrlForPlatform() {
16511
- const platform2 = process.platform;
16512
- const arch = process.arch;
16511
+ const platform3 = process.platform;
16512
+ const arch2 = process.arch;
16513
16513
  const base = "https://github.com/cloudflare/cloudflared/releases/latest/download";
16514
- if (platform2 === "darwin" && arch === "arm64") return `${base}/cloudflared-darwin-arm64.tgz`;
16515
- if (platform2 === "darwin" && arch === "x64") return `${base}/cloudflared-darwin-amd64.tgz`;
16516
- if (platform2 === "linux" && arch === "x64") return `${base}/cloudflared-linux-amd64`;
16517
- if (platform2 === "linux" && arch === "arm64") return `${base}/cloudflared-linux-arm64`;
16518
- if (platform2 === "win32") return `${base}/cloudflared-windows-amd64.exe`;
16514
+ if (platform3 === "darwin" && arch2 === "arm64") return `${base}/cloudflared-darwin-arm64.tgz`;
16515
+ if (platform3 === "darwin" && arch2 === "x64") return `${base}/cloudflared-darwin-amd64.tgz`;
16516
+ if (platform3 === "linux" && arch2 === "x64") return `${base}/cloudflared-linux-amd64`;
16517
+ if (platform3 === "linux" && arch2 === "arm64") return `${base}/cloudflared-linux-arm64`;
16518
+ if (platform3 === "win32") return `${base}/cloudflared-windows-amd64.exe`;
16519
16519
  throw new Error(
16520
- `cloudflared auto-install not supported on ${platform2}/${arch}. Install manually from https://github.com/cloudflare/cloudflared/releases.`
16520
+ `cloudflared auto-install not supported on ${platform3}/${arch2}. Install manually from https://github.com/cloudflare/cloudflared/releases.`
16521
16521
  );
16522
16522
  }
16523
16523
 
@@ -16676,7 +16676,7 @@ function parseExpoUrl(stdout) {
16676
16676
 
16677
16677
  // src/services/preview/port-ready.ts
16678
16678
  var net = __toESM(require("net"));
16679
- function isPortListening(port, host = "127.0.0.1") {
16679
+ function isPortListening(port, host2 = "127.0.0.1") {
16680
16680
  return new Promise((resolve7) => {
16681
16681
  const socket = new net.Socket();
16682
16682
  const done = (result) => {
@@ -16688,7 +16688,7 @@ function isPortListening(port, host = "127.0.0.1") {
16688
16688
  socket.once("connect", () => done(true));
16689
16689
  socket.once("timeout", () => done(false));
16690
16690
  socket.once("error", () => done(false));
16691
- socket.connect(port, host);
16691
+ socket.connect(port, host2);
16692
16692
  });
16693
16693
  }
16694
16694
  async function waitForPortListening(port, opts) {
@@ -17221,8 +17221,8 @@ var path40 = __toESM(require("path"));
17221
17221
  var import_child_process14 = require("child_process");
17222
17222
  var INSTALL_SH_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh";
17223
17223
  var INSTALL_PS1_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/install.ps1";
17224
- function resolveInstallStrategy(platform2) {
17225
- if (platform2 === "win32") {
17224
+ function resolveInstallStrategy(platform3) {
17225
+ if (platform3 === "win32") {
17226
17226
  return {
17227
17227
  command: "powershell.exe",
17228
17228
  args: [
@@ -17265,8 +17265,8 @@ function _defaultInstallSpawn(strategy) {
17265
17265
  );
17266
17266
  });
17267
17267
  }
17268
- async function installBd(platform2 = process.platform) {
17269
- const strategy = resolveInstallStrategy(platform2);
17268
+ async function installBd(platform3 = process.platform) {
17269
+ const strategy = resolveInstallStrategy(platform3);
17270
17270
  log.info("beads", `installing bd via ${strategy.description}`);
17271
17271
  const result = await _installSpawnSeam.run(strategy);
17272
17272
  if (!result.ok) {
@@ -17285,8 +17285,8 @@ var os25 = __toESM(require("os"));
17285
17285
  var path38 = __toESM(require("path"));
17286
17286
  var DOLT_INSTALL_SH_URL = "https://github.com/dolthub/dolt/releases/latest/download/install.sh";
17287
17287
  var DOLT_MSI_URL = "https://github.com/dolthub/dolt/releases/latest/download/dolt-windows-amd64.msi";
17288
- function resolveDoltInstallStrategy(platform2) {
17289
- if (platform2 === "win32") {
17288
+ function resolveDoltInstallStrategy(platform3) {
17289
+ if (platform3 === "win32") {
17290
17290
  const script = [
17291
17291
  `$ErrorActionPreference='Stop';`,
17292
17292
  `$u='${DOLT_MSI_URL}';`,
@@ -17307,7 +17307,7 @@ function resolveDoltInstallStrategy(platform2) {
17307
17307
  description: "PowerShell: download official dolt MSI + silent msiexec"
17308
17308
  };
17309
17309
  }
17310
- if (platform2 === "darwin") {
17310
+ if (platform3 === "darwin") {
17311
17311
  return {
17312
17312
  command: "brew",
17313
17313
  args: ["install", "dolt"],
@@ -17321,17 +17321,17 @@ function resolveDoltInstallStrategy(platform2) {
17321
17321
  };
17322
17322
  }
17323
17323
  var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
17324
- function doltPlatformTuple(platform2, arch) {
17325
- const os33 = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "darwin" : "linux";
17326
- const a = arch === "x64" ? "amd64" : arch === "arm64" ? "arm64" : null;
17324
+ function doltPlatformTuple(platform3, arch2) {
17325
+ const os36 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
17326
+ const a = arch2 === "x64" ? "amd64" : arch2 === "arm64" ? "arm64" : null;
17327
17327
  if (!a) return null;
17328
- if (os33 === "windows" && a !== "amd64") return null;
17329
- return `${os33}-${a}`;
17328
+ if (os36 === "windows" && a !== "amd64") return null;
17329
+ return `${os36}-${a}`;
17330
17330
  }
17331
- function resolveDoltTarballStrategy(targetDir, platform2, arch) {
17332
- const tuple = doltPlatformTuple(platform2, arch);
17331
+ function resolveDoltTarballStrategy(targetDir, platform3, arch2) {
17332
+ const tuple = doltPlatformTuple(platform3, arch2);
17333
17333
  if (!tuple) return null;
17334
- if (platform2 === "win32") {
17334
+ if (platform3 === "win32") {
17335
17335
  const url2 = `${DOLT_RELEASE_BASE}/dolt-${tuple}.zip`;
17336
17336
  const script = [
17337
17337
  `$ErrorActionPreference='Stop';`,
@@ -17357,11 +17357,11 @@ function resolveDoltTarballStrategy(targetDir, platform2, arch) {
17357
17357
  description: `download dolt ${tuple} tarball \u2192 ${targetDir} (no sudo)`
17358
17358
  };
17359
17359
  }
17360
- async function installDoltToDir(targetDir, platform2 = process.platform, arch = process.arch) {
17361
- const strategy = resolveDoltTarballStrategy(targetDir, platform2, arch);
17360
+ async function installDoltToDir(targetDir, platform3 = process.platform, arch2 = process.arch) {
17361
+ const strategy = resolveDoltTarballStrategy(targetDir, platform3, arch2);
17362
17362
  if (!strategy) {
17363
- log.warn("beads", `no dolt prebuilt for ${platform2}/${arch} \u2014 cannot fall back`);
17364
- return { ok: false, code: -1, stderr: `unsupported platform ${platform2}/${arch}` };
17363
+ log.warn("beads", `no dolt prebuilt for ${platform3}/${arch2} \u2014 cannot fall back`);
17364
+ return { ok: false, code: -1, stderr: `unsupported platform ${platform3}/${arch2}` };
17365
17365
  }
17366
17366
  log.info("beads", `dolt fallback: ${strategy.description}`);
17367
17367
  const result = await _doltInstallSpawnSeam.run(strategy);
@@ -17385,13 +17385,13 @@ var _doltPathSeam = {
17385
17385
  }
17386
17386
  }
17387
17387
  };
17388
- function doltBinaryNames(platform2) {
17389
- return platform2 === "win32" ? ["dolt.exe", "dolt.cmd", "dolt"] : ["dolt"];
17388
+ function doltBinaryNames(platform3) {
17389
+ return platform3 === "win32" ? ["dolt.exe", "dolt.cmd", "dolt"] : ["dolt"];
17390
17390
  }
17391
- function knownDoltDirs(platform2) {
17392
- const P3 = platform2 === "win32" ? path38.win32 : path38.posix;
17391
+ function knownDoltDirs(platform3) {
17392
+ const P3 = platform3 === "win32" ? path38.win32 : path38.posix;
17393
17393
  const home = _doltPathSeam.homedir();
17394
- if (platform2 === "win32") {
17394
+ if (platform3 === "win32") {
17395
17395
  return [
17396
17396
  "C:\\Program Files\\Dolt\\bin",
17397
17397
  home ? P3.join(home, "AppData", "Local", "Programs", "dolt", "bin") : ""
@@ -17404,17 +17404,17 @@ function knownDoltDirs(platform2) {
17404
17404
  home ? P3.join(home, "bin") : ""
17405
17405
  ].filter(Boolean);
17406
17406
  }
17407
- function ensureDoltResolvable(platform2 = process.platform) {
17408
- const P3 = platform2 === "win32" ? path38.win32 : path38.posix;
17409
- const delim = platform2 === "win32" ? ";" : ":";
17410
- const names = doltBinaryNames(platform2);
17407
+ function ensureDoltResolvable(platform3 = process.platform) {
17408
+ const P3 = platform3 === "win32" ? path38.win32 : path38.posix;
17409
+ const delim = platform3 === "win32" ? ";" : ":";
17410
+ const names = doltBinaryNames(platform3);
17411
17411
  const pathDirs = _doltPathSeam.getPath().split(delim).filter(Boolean);
17412
17412
  for (const dir of pathDirs) {
17413
17413
  for (const n of names) {
17414
17414
  if (_doltPathSeam.exists(P3.join(dir, n))) return true;
17415
17415
  }
17416
17416
  }
17417
- for (const dir of knownDoltDirs(platform2)) {
17417
+ for (const dir of knownDoltDirs(platform3)) {
17418
17418
  for (const n of names) {
17419
17419
  if (_doltPathSeam.exists(P3.join(dir, n))) {
17420
17420
  _doltPathSeam.setPath(`${dir}${delim}${_doltPathSeam.getPath()}`);
@@ -17468,8 +17468,8 @@ function _defaultDoltInstallSpawn(strategy) {
17468
17468
  proc.on("close", (code) => finish({ ok: code === 0, code: code ?? -1, stderr }));
17469
17469
  });
17470
17470
  }
17471
- async function installDolt(platform2 = process.platform) {
17472
- const strategy = resolveDoltInstallStrategy(platform2);
17471
+ async function installDolt(platform3 = process.platform) {
17472
+ const strategy = resolveDoltInstallStrategy(platform3);
17473
17473
  log.info("beads", `installing dolt via ${strategy.description}`);
17474
17474
  const result = await _doltInstallSpawnSeam.run(strategy);
17475
17475
  if (!result.ok) {
@@ -17521,11 +17521,11 @@ var path39 = __toESM(require("path"));
17521
17521
  function normalizeOrigin(raw) {
17522
17522
  const trimmed = raw.trim();
17523
17523
  if (!trimmed) return null;
17524
- let host;
17524
+ let host2;
17525
17525
  let pathPart;
17526
17526
  const scpLike = /^[^/@]+@([^:]+):(.+)$/.exec(trimmed);
17527
17527
  if (scpLike && !trimmed.includes("://")) {
17528
- host = scpLike[1];
17528
+ host2 = scpLike[1];
17529
17529
  pathPart = scpLike[2];
17530
17530
  } else {
17531
17531
  let url;
@@ -17534,13 +17534,13 @@ function normalizeOrigin(raw) {
17534
17534
  } catch {
17535
17535
  return null;
17536
17536
  }
17537
- host = url.hostname;
17537
+ host2 = url.hostname;
17538
17538
  pathPart = url.pathname;
17539
17539
  }
17540
- host = host.toLowerCase();
17540
+ host2 = host2.toLowerCase();
17541
17541
  pathPart = pathPart.replace(/^\/+/, "").replace(/\.git$/i, "").replace(/\/+$/, "");
17542
- if (!host || !pathPart) return null;
17543
- return `${host}/${pathPart}`;
17542
+ if (!host2 || !pathPart) return null;
17543
+ return `${host2}/${pathPart}`;
17544
17544
  }
17545
17545
  function findRepoRoot(cwd) {
17546
17546
  let dir = path39.resolve(cwd);
@@ -18056,11 +18056,11 @@ var BeadsWatcher = class {
18056
18056
 
18057
18057
  // src/beads/inherit-team-memories.ts
18058
18058
  async function inheritTeamMemories(opts) {
18059
- const apiBase = opts.apiBaseUrl ?? resolveApiBaseUrl();
18059
+ const apiBase2 = opts.apiBaseUrl ?? resolveApiBaseUrl();
18060
18060
  let memories = [];
18061
18061
  try {
18062
18062
  const res = await _transport3.post(
18063
- `${apiBase}/api/beads/team-memories`,
18063
+ `${apiBase2}/api/beads/team-memories`,
18064
18064
  {
18065
18065
  "Content-Type": "application/json",
18066
18066
  "X-Codeam-Protocol-Version": "2.0.0",
@@ -19440,10 +19440,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
19440
19440
  /[\\/]Start Menu([\\/]|$)/i,
19441
19441
  /[\\/]Templates([\\/]|$)/i
19442
19442
  ];
19443
- function isUnsafeWindowsWatchRoot(dir, homedir26) {
19443
+ function isUnsafeWindowsWatchRoot(dir, homedir29) {
19444
19444
  const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
19445
19445
  const cwd = norm(dir);
19446
- const home = norm(homedir26);
19446
+ const home = norm(homedir29);
19447
19447
  if (cwd === home) return true;
19448
19448
  if (/^[a-z]:$/.test(cwd)) return true;
19449
19449
  const sysRoots = [
@@ -20237,7 +20237,7 @@ function defaultRunGit(cwd, args2) {
20237
20237
  });
20238
20238
  }
20239
20239
  async function discoverRepos(workingDir, maxDepth = 4) {
20240
- const fs43 = await import("fs/promises");
20240
+ const fs46 = await import("fs/promises");
20241
20241
  const out2 = [];
20242
20242
  await walk(workingDir, 0);
20243
20243
  return out2;
@@ -20245,7 +20245,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
20245
20245
  if (depth > maxDepth) return;
20246
20246
  let entries = [];
20247
20247
  try {
20248
- const dirents = await fs43.readdir(dir, { withFileTypes: true });
20248
+ const dirents = await fs46.readdir(dir, { withFileTypes: true });
20249
20249
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
20250
20250
  } catch {
20251
20251
  return;
@@ -23920,12 +23920,12 @@ function readTokenFromArgs(args2) {
23920
23920
  }
23921
23921
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
23922
23922
  if (fileFlag) {
23923
- const path55 = fileFlag.slice("--token-file=".length);
23923
+ const path58 = fileFlag.slice("--token-file=".length);
23924
23924
  try {
23925
- const content = fs40.readFileSync(path55, "utf8").trim();
23926
- if (content.length === 0) fail(`--token-file ${path55} is empty`);
23925
+ const content = fs40.readFileSync(path58, "utf8").trim();
23926
+ if (content.length === 0) fail(`--token-file ${path58} is empty`);
23927
23927
  try {
23928
- fs40.unlinkSync(path55);
23928
+ fs40.unlinkSync(path58);
23929
23929
  } catch {
23930
23930
  }
23931
23931
  return content;
@@ -24409,12 +24409,12 @@ var GitHubCodespacesProvider = class {
24409
24409
  * install error if it's still missing.
24410
24410
  */
24411
24411
  async tryInstallGh() {
24412
- const platform2 = process.platform;
24412
+ const platform3 = process.platform;
24413
24413
  wt(
24414
24414
  `GitHub CLI (${import_picocolors8.default.cyan("gh")}) is required for Codespaces deploys but isn't on your PATH.`,
24415
24415
  "Heads up"
24416
24416
  );
24417
- if (platform2 === "linux") {
24417
+ if (platform3 === "linux") {
24418
24418
  wt(
24419
24419
  [
24420
24420
  "On Linux, please install gh from the official guide:",
@@ -24426,7 +24426,7 @@ var GitHubCodespacesProvider = class {
24426
24426
  return;
24427
24427
  }
24428
24428
  let installCmd = null;
24429
- if (platform2 === "darwin") {
24429
+ if (platform3 === "darwin") {
24430
24430
  try {
24431
24431
  await execFileP5("brew", ["--version"], { maxBuffer: MAX_BUFFER });
24432
24432
  } catch {
@@ -24445,7 +24445,7 @@ var GitHubCodespacesProvider = class {
24445
24445
  args: ["install", "gh"],
24446
24446
  describe: "brew install gh"
24447
24447
  };
24448
- } else if (platform2 === "win32") {
24448
+ } else if (platform3 === "win32") {
24449
24449
  try {
24450
24450
  await execFileP5("winget", ["--version"], { maxBuffer: MAX_BUFFER });
24451
24451
  } catch {
@@ -26175,50 +26175,488 @@ async function probeCodeamPair(provider, workspace) {
26175
26175
  }
26176
26176
  async function stopWorkspaceFromLocal(target) {
26177
26177
  if (target.provider.id === "github-codespaces") {
26178
- const { execFile: execFile9 } = await import("child_process");
26179
- const { promisify: promisify10 } = await import("util");
26180
- const execFileP9 = promisify10(execFile9);
26181
- await execFileP9("gh", ["codespace", "stop", "-c", target.id], { maxBuffer: 8 * 1024 * 1024 });
26178
+ const { execFile: execFile10 } = await import("child_process");
26179
+ const { promisify: promisify11 } = await import("util");
26180
+ const execFileP10 = promisify11(execFile10);
26181
+ await execFileP10("gh", ["codespace", "stop", "-c", target.id], { maxBuffer: 8 * 1024 * 1024 });
26182
26182
  return;
26183
26183
  }
26184
26184
  }
26185
26185
 
26186
+ // src/commands/host/host-client.ts
26187
+ var fs41 = __toESM(require("fs"));
26188
+ var os32 = __toESM(require("os"));
26189
+ var path53 = __toESM(require("path"));
26190
+ function apiBase() {
26191
+ return process.env.CODEAM_API_URL ?? resolveApiBaseUrl();
26192
+ }
26193
+ function hostIdentityPath() {
26194
+ return path53.join(os32.homedir(), ".codeam", "host-agent.json");
26195
+ }
26196
+ function collectOsInfo() {
26197
+ return {
26198
+ distro: os32.platform(),
26199
+ arch: os32.arch(),
26200
+ kernel: os32.release(),
26201
+ nodeVersion: process.versions.node
26202
+ };
26203
+ }
26204
+ function loadHostIdentity() {
26205
+ try {
26206
+ const raw = fs41.readFileSync(hostIdentityPath(), "utf8");
26207
+ const parsed = JSON.parse(raw);
26208
+ if (typeof parsed === "object" && parsed !== null && typeof parsed.hostId === "string" && typeof parsed.hostToken === "string" && typeof parsed.controlPluginId === "string") {
26209
+ const p2 = parsed;
26210
+ return { hostId: p2.hostId, hostToken: p2.hostToken, controlPluginId: p2.controlPluginId };
26211
+ }
26212
+ return null;
26213
+ } catch {
26214
+ return null;
26215
+ }
26216
+ }
26217
+ function saveHostIdentity(identity) {
26218
+ const file = hostIdentityPath();
26219
+ fs41.mkdirSync(path53.dirname(file), { recursive: true, mode: 448 });
26220
+ fs41.writeFileSync(file, JSON.stringify(identity, null, 2), {
26221
+ encoding: "utf8",
26222
+ mode: 384
26223
+ });
26224
+ fs41.chmodSync(file, 384);
26225
+ }
26226
+ async function postJson(pathname, body) {
26227
+ const res = await fetch(`${apiBase()}${pathname}`, {
26228
+ method: "POST",
26229
+ headers: { "Content-Type": "application/json", ...vercelBypassHeader() },
26230
+ body: JSON.stringify(body)
26231
+ });
26232
+ const json = await res.json();
26233
+ if (!res.ok || !json.success) {
26234
+ const err = !json.success ? json.error : void 0;
26235
+ throw new Error(
26236
+ `${pathname} failed (${err?.code ?? `HTTP_${res.status}`}): ${err?.message ?? res.statusText}`
26237
+ );
26238
+ }
26239
+ return json.data;
26240
+ }
26241
+ async function redeemEnrollToken(token, label) {
26242
+ const data = await postJson("/api/self-hosted/redeem", {
26243
+ token,
26244
+ ...label ? { label } : {},
26245
+ osInfo: collectOsInfo()
26246
+ });
26247
+ return {
26248
+ hostId: data.hostId,
26249
+ hostToken: data.hostToken,
26250
+ controlPluginId: data.controlPluginId
26251
+ };
26252
+ }
26253
+ async function sendHostHeartbeat(identity) {
26254
+ await postJson("/api/self-hosted/heartbeat", {
26255
+ hostId: identity.hostId,
26256
+ hostToken: identity.hostToken
26257
+ });
26258
+ }
26259
+ function isSealedEnvelope(v) {
26260
+ if (typeof v !== "object" || v === null) return false;
26261
+ const o = v;
26262
+ return typeof o.ciphertext === "string" && typeof o.iv === "string" && typeof o.authTag === "string" && typeof o.keyVersion === "number";
26263
+ }
26264
+ function isAgentAuth(v) {
26265
+ if (typeof v !== "object" || v === null) return false;
26266
+ const o = v;
26267
+ return (o.kind === "oauth_token" || o.kind === "api_key") && typeof o.value === "string";
26268
+ }
26269
+ async function unsealAgentAuth(identity, sealedAgentAuth) {
26270
+ const envelope = JSON.parse(sealedAgentAuth);
26271
+ if (!isSealedEnvelope(envelope)) {
26272
+ throw new Error("sealedAgentAuth is not a valid vault envelope");
26273
+ }
26274
+ const data = await postJson(
26275
+ "/api/self-hosted/unseal-agent-auth",
26276
+ {
26277
+ hostId: identity.hostId,
26278
+ hostToken: identity.hostToken,
26279
+ sealedAgentAuth
26280
+ }
26281
+ );
26282
+ if (!isAgentAuth(data)) {
26283
+ throw new Error("unseal-agent-auth returned an unexpected shape");
26284
+ }
26285
+ return data;
26286
+ }
26287
+
26288
+ // src/commands/host.ts
26289
+ function readTokenFlag(args2) {
26290
+ const flag = args2.find((a) => a.startsWith("--token="));
26291
+ if (!flag) return void 0;
26292
+ const value = flag.slice("--token=".length).trim();
26293
+ return value.length > 0 ? value : void 0;
26294
+ }
26295
+ function readLabelFlag(args2) {
26296
+ const flag = args2.find((a) => a.startsWith("--label="));
26297
+ if (!flag) return void 0;
26298
+ const value = flag.slice("--label=".length).trim();
26299
+ return value.length > 0 ? value : void 0;
26300
+ }
26301
+ async function hostEnroll(args2) {
26302
+ const existing = loadHostIdentity();
26303
+ if (existing) {
26304
+ console.log(
26305
+ ` Already enrolled (host ${existing.hostId}). Run \`codeam host-agent\` to connect.`
26306
+ );
26307
+ return;
26308
+ }
26309
+ const token = readTokenFlag(args2);
26310
+ if (!token) {
26311
+ throw new Error(
26312
+ "codeam host enroll requires --token=<EPHEMERAL>. Copy the command from the app."
26313
+ );
26314
+ }
26315
+ const identity = await redeemEnrollToken(token, readLabelFlag(args2));
26316
+ saveHostIdentity(identity);
26317
+ console.log(
26318
+ ` Enrolled host ${identity.hostId}. Sealed credentials to ~/.codeam/host-agent.json (0600).`
26319
+ );
26320
+ console.log(" Run `codeam host-agent` (or let systemd start it) to connect.");
26321
+ }
26322
+ async function host(args2) {
26323
+ const sub = args2[0];
26324
+ if (sub === "enroll") {
26325
+ await hostEnroll(args2.slice(1));
26326
+ return;
26327
+ }
26328
+ throw new Error(
26329
+ `Unknown 'codeam host' subcommand: ${sub ?? "(none)"}. Try: codeam host enroll --token=<EPHEMERAL>`
26330
+ );
26331
+ }
26332
+
26333
+ // src/commands/host-agent.ts
26334
+ var import_node_child_process13 = require("child_process");
26335
+
26336
+ // src/commands/host/workspace.ts
26337
+ var fs42 = __toESM(require("fs"));
26338
+ var os33 = __toESM(require("os"));
26339
+ var path54 = __toESM(require("path"));
26340
+ var import_node_child_process12 = require("child_process");
26341
+ var import_node_util4 = require("util");
26342
+ var execFileP9 = (0, import_node_util4.promisify)(import_node_child_process12.execFile);
26343
+ function isAbsolutePathTarget(target) {
26344
+ return path54.isAbsolute(target);
26345
+ }
26346
+ function selfHostedWorkspaceRoot() {
26347
+ return path54.join(os33.homedir(), ".codeam", "self-hosted");
26348
+ }
26349
+ function repoCloneUrl(repoRef) {
26350
+ const trimmed = repoRef.trim();
26351
+ if (/^https?:\/\//.test(trimmed) || trimmed.startsWith("git@")) return trimmed;
26352
+ return `https://github.com/${trimmed.replace(/\.git$/, "")}.git`;
26353
+ }
26354
+ async function prepareWorkspace(repoOrPath, deployId) {
26355
+ if (isAbsolutePathTarget(repoOrPath)) {
26356
+ if (!fs42.existsSync(repoOrPath)) {
26357
+ throw new Error(`deploy target path does not exist: ${repoOrPath}`);
26358
+ }
26359
+ return repoOrPath;
26360
+ }
26361
+ const dest = path54.join(selfHostedWorkspaceRoot(), deployId);
26362
+ if (fs42.existsSync(path54.join(dest, ".git"))) {
26363
+ return dest;
26364
+ }
26365
+ fs42.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
26366
+ await execFileP9("git", ["clone", "--depth", "1", repoCloneUrl(repoOrPath), dest], {
26367
+ timeout: 12e4,
26368
+ maxBuffer: 16 * 1024 * 1024
26369
+ });
26370
+ return dest;
26371
+ }
26372
+
26373
+ // src/commands/host/agent-provisioning.ts
26374
+ var fs43 = __toESM(require("fs"));
26375
+ var os34 = __toESM(require("os"));
26376
+ var path55 = __toESM(require("path"));
26377
+ var PUBLIC_TO_INTERNAL_AGENT = {
26378
+ claude_code: "claude",
26379
+ claude: "claude",
26380
+ codex: "codex",
26381
+ copilot: "copilot",
26382
+ cursor: "cursor",
26383
+ aider: "aider",
26384
+ coderabbit: "coderabbit",
26385
+ gemini: "gemini"
26386
+ };
26387
+ function toInternalAgentId(publicAgentId) {
26388
+ return PUBLIC_TO_INTERNAL_AGENT[publicAgentId] ?? null;
26389
+ }
26390
+ function ensureDir(dir) {
26391
+ fs43.mkdirSync(dir, { recursive: true, mode: 448 });
26392
+ }
26393
+ function writeFile0600(filePath, contents) {
26394
+ ensureDir(path55.dirname(filePath));
26395
+ fs43.writeFileSync(filePath, contents, { encoding: "utf8", mode: 384 });
26396
+ fs43.chmodSync(filePath, 384);
26397
+ }
26398
+ var claudeProvisioner = {
26399
+ write(auth, home) {
26400
+ if (auth.kind === "api_key") {
26401
+ return { ANTHROPIC_API_KEY: auth.value };
26402
+ }
26403
+ writeFile0600(path55.join(home, ".claude", ".credentials.json"), auth.value);
26404
+ const claudeJson = path55.join(home, ".claude.json");
26405
+ if (!fs43.existsSync(claudeJson)) {
26406
+ writeFile0600(
26407
+ claudeJson,
26408
+ JSON.stringify({ hasCompletedOnboarding: true, customApiKeyResponses: { approved: [] } })
26409
+ );
26410
+ }
26411
+ return {};
26412
+ }
26413
+ };
26414
+ var codexProvisioner = {
26415
+ write(auth, home) {
26416
+ if (auth.kind === "api_key") {
26417
+ return { OPENAI_API_KEY: auth.value };
26418
+ }
26419
+ writeFile0600(path55.join(home, ".codex", "auth.json"), auth.value);
26420
+ return {};
26421
+ }
26422
+ };
26423
+ var PROVISIONERS = {
26424
+ claude: claudeProvisioner,
26425
+ codex: codexProvisioner
26426
+ };
26427
+ var UnsupportedAgentError = class extends Error {
26428
+ agentId;
26429
+ constructor(agentId) {
26430
+ super(`Self-hosted provisioning is not implemented for agent "${agentId}"`);
26431
+ this.name = "UnsupportedAgentError";
26432
+ this.agentId = agentId;
26433
+ }
26434
+ };
26435
+ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os34.homedir()) {
26436
+ const internal = toInternalAgentId(publicAgentId);
26437
+ if (!internal) throw new UnsupportedAgentError(publicAgentId);
26438
+ const provisioner = PROVISIONERS[internal];
26439
+ if (!provisioner) throw new UnsupportedAgentError(publicAgentId);
26440
+ return provisioner.write(auth, homeDir2);
26441
+ }
26442
+
26443
+ // src/commands/host-agent.ts
26444
+ var HEARTBEAT_INTERVAL_MS = 2e4;
26445
+ function isDeployPayload(p2) {
26446
+ return typeof p2.deployId === "string" && typeof p2.repoOrPath === "string" && typeof p2.agentId === "string" && typeof p2.sealedAgentAuth === "string" && typeof p2.autoPairToken === "string";
26447
+ }
26448
+ function isStopPayload(p2) {
26449
+ return typeof p2.sessionId === "string";
26450
+ }
26451
+ var CONTROL_AGENT_META = {
26452
+ id: "claude",
26453
+ displayName: "CodeAgent Host Agent",
26454
+ binaryName: "codeam",
26455
+ enabled: true,
26456
+ supportedAuthKinds: ["oauth_token"],
26457
+ preferredAuthKind: "oauth_token"
26458
+ };
26459
+ var defaultSpawner = (env, cwd) => (0, import_node_child_process13.spawn)(process.execPath, [process.argv[1], "pair-auto"], {
26460
+ cwd,
26461
+ env: { ...process.env, ...env },
26462
+ stdio: "ignore",
26463
+ detached: false
26464
+ });
26465
+ var HostAgentSupervisor = class {
26466
+ constructor(identity, deps = {}) {
26467
+ this.identity = identity;
26468
+ this.deps = deps;
26469
+ this.spawnChild = deps.spawnChild ?? defaultSpawner;
26470
+ this.resolveAgentAuth = deps.resolveAgentAuth ?? unsealAgentAuth;
26471
+ }
26472
+ identity;
26473
+ deps;
26474
+ children = /* @__PURE__ */ new Map();
26475
+ spawnChild;
26476
+ resolveAgentAuth;
26477
+ relay = null;
26478
+ heartbeatTimer = null;
26479
+ /** Open the control channel (reusing the relay) + start heartbeats. */
26480
+ start() {
26481
+ const make = this.deps.makeRelay ?? ((pluginId, onCommand, meta) => new CommandRelayService(pluginId, onCommand, meta));
26482
+ this.relay = make(
26483
+ this.identity.controlPluginId,
26484
+ (cmd) => this.handleCommand(cmd),
26485
+ CONTROL_AGENT_META
26486
+ );
26487
+ this.relay.start();
26488
+ void this.beat();
26489
+ this.heartbeatTimer = setInterval(() => void this.beat(), HEARTBEAT_INTERVAL_MS);
26490
+ this.heartbeatTimer.unref?.();
26491
+ log.info("host-agent", `supervisor up host=${this.identity.hostId.slice(0, 8)}`);
26492
+ }
26493
+ /** Stop the control channel + heartbeats + kill every child. */
26494
+ stop() {
26495
+ if (this.heartbeatTimer) {
26496
+ clearInterval(this.heartbeatTimer);
26497
+ this.heartbeatTimer = null;
26498
+ }
26499
+ this.relay?.stop();
26500
+ for (const child of this.children.values()) {
26501
+ try {
26502
+ child.proc.kill("SIGTERM");
26503
+ } catch {
26504
+ }
26505
+ }
26506
+ this.children.clear();
26507
+ }
26508
+ async beat() {
26509
+ try {
26510
+ await sendHostHeartbeat(this.identity);
26511
+ } catch (err) {
26512
+ log.trace("host-agent", "heartbeat failed", err);
26513
+ }
26514
+ }
26515
+ /** Number of live children — for tests + diagnostics. */
26516
+ childCount() {
26517
+ return this.children.size;
26518
+ }
26519
+ /**
26520
+ * Route a relay command. Only `self_hosted_deploy` / `self_hosted_stop`
26521
+ * are understood; anything else is ignored (the box accepts no
26522
+ * arbitrary command surface).
26523
+ */
26524
+ async handleCommand(cmd) {
26525
+ if (cmd.type === "self_hosted_deploy") {
26526
+ if (!isDeployPayload(cmd.payload)) {
26527
+ log.warn("host-agent", `ignoring malformed self_hosted_deploy id=${cmd.id}`);
26528
+ return;
26529
+ }
26530
+ await this.deploy(cmd.payload);
26531
+ return;
26532
+ }
26533
+ if (cmd.type === "self_hosted_stop") {
26534
+ if (!isStopPayload(cmd.payload)) {
26535
+ log.warn("host-agent", `ignoring malformed self_hosted_stop id=${cmd.id}`);
26536
+ return;
26537
+ }
26538
+ this.stopChild(cmd.payload.sessionId);
26539
+ return;
26540
+ }
26541
+ log.trace("host-agent", `ignoring unsupported command type=${cmd.type}`);
26542
+ }
26543
+ /**
26544
+ * Prepare the workspace, write the agent credential (same as codespace
26545
+ * provisioning), and spawn a supervised `codeam pair-auto` child.
26546
+ *
26547
+ * The child claims its session via `CODEAM_AUTO_TOKEN`; the backend's
26548
+ * claim response is what binds the sessionId on the server side. We key
26549
+ * the child by `deployId` immediately (and adopt the sessionId — which
26550
+ * for self-hosted equals the deployId-correlated session) so a
26551
+ * subsequent `self_hosted_stop` can find it.
26552
+ */
26553
+ async deploy(payload) {
26554
+ log.info(
26555
+ "host-agent",
26556
+ `deploy id=${payload.deployId.slice(0, 8)} agent=${payload.agentId} target=${payload.repoOrPath}`
26557
+ );
26558
+ const cwd = await prepareWorkspace(payload.repoOrPath, payload.deployId);
26559
+ const auth = await this.resolveAgentAuth(this.identity, payload.sealedAgentAuth);
26560
+ const credEnv = provisionAgentCredentials(payload.agentId, auth, void 0);
26561
+ const childEnv = {
26562
+ ...credEnv,
26563
+ CODEAM_AUTO_TOKEN: payload.autoPairToken
26564
+ };
26565
+ const proc = this.spawnChild(childEnv, cwd);
26566
+ const child = { deployId: payload.deployId, sessionId: payload.deployId, proc };
26567
+ this.children.set(payload.deployId, child);
26568
+ proc.once("exit", () => {
26569
+ if (this.children.get(payload.deployId)?.proc === proc) {
26570
+ this.children.delete(payload.deployId);
26571
+ }
26572
+ });
26573
+ }
26574
+ /** Kill the child matching `sessionId` (or its deployId). No-op if absent. */
26575
+ stopChild(sessionId) {
26576
+ const child = this.children.get(sessionId) ?? this.findBySessionId(sessionId);
26577
+ if (!child) {
26578
+ log.trace("host-agent", `stop: no child for sessionId=${sessionId}`);
26579
+ return;
26580
+ }
26581
+ log.info("host-agent", `stopping child deploy=${child.deployId.slice(0, 8)}`);
26582
+ try {
26583
+ child.proc.kill("SIGTERM");
26584
+ } catch {
26585
+ }
26586
+ this.children.delete(child.deployId);
26587
+ }
26588
+ findBySessionId(sessionId) {
26589
+ for (const child of this.children.values()) {
26590
+ if (child.sessionId === sessionId) return child;
26591
+ }
26592
+ return void 0;
26593
+ }
26594
+ };
26595
+ async function resolveHostIdentity(enrollToken) {
26596
+ const existing = loadHostIdentity();
26597
+ if (existing) return existing;
26598
+ if (!enrollToken) return null;
26599
+ const identity = await redeemEnrollToken(enrollToken);
26600
+ saveHostIdentity(identity);
26601
+ return identity;
26602
+ }
26603
+ async function hostAgent(args2 = []) {
26604
+ const tokenArg = args2.find((a) => a.startsWith("--token="));
26605
+ const enrollToken = (tokenArg ? tokenArg.slice("--token=".length).trim() : "") || process.env.CODEAM_ENROLL_TOKEN || void 0;
26606
+ const identity = await resolveHostIdentity(enrollToken);
26607
+ if (!identity) {
26608
+ throw new Error(
26609
+ "host-agent: no sealed host identity and no enroll token. Re-run the installer from the app (tokens expire after 15 min)."
26610
+ );
26611
+ }
26612
+ const supervisor = new HostAgentSupervisor(identity);
26613
+ supervisor.start();
26614
+ const shutdown = () => {
26615
+ supervisor.stop();
26616
+ process.exit(0);
26617
+ };
26618
+ process.once("SIGINT", shutdown);
26619
+ process.once("SIGTERM", shutdown);
26620
+ await new Promise(() => {
26621
+ });
26622
+ }
26623
+
26186
26624
  // src/commands/doctor.ts
26187
26625
  var import_node_dns = require("dns");
26188
- var import_node_util4 = require("util");
26626
+ var import_node_util5 = require("util");
26189
26627
  var import_node_crypto8 = require("crypto");
26190
- var fs41 = __toESM(require("fs"));
26191
- var path53 = __toESM(require("path"));
26628
+ var fs44 = __toESM(require("fs"));
26629
+ var path56 = __toESM(require("path"));
26192
26630
  var import_picocolors12 = __toESM(require("picocolors"));
26193
- var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
26194
- async function checkDns(apiBase) {
26195
- const host = (() => {
26631
+ var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
26632
+ async function checkDns(apiBase2) {
26633
+ const host2 = (() => {
26196
26634
  try {
26197
- return new URL(apiBase).host;
26635
+ return new URL(apiBase2).host;
26198
26636
  } catch {
26199
- return apiBase;
26637
+ return apiBase2;
26200
26638
  }
26201
26639
  })();
26202
26640
  try {
26203
- const addrs = await dnsResolveP(host);
26641
+ const addrs = await dnsResolveP(host2);
26204
26642
  return {
26205
26643
  id: "dns",
26206
- label: `DNS resolves ${host}`,
26644
+ label: `DNS resolves ${host2}`,
26207
26645
  ok: true,
26208
26646
  detail: `${addrs.length} record(s)`
26209
26647
  };
26210
26648
  } catch (err) {
26211
26649
  return {
26212
26650
  id: "dns",
26213
- label: `DNS resolves ${host}`,
26651
+ label: `DNS resolves ${host2}`,
26214
26652
  ok: false,
26215
26653
  detail: err.message,
26216
26654
  hint: "Check your network connection / DNS configuration. The backend host MUST resolve before `codeam pair` can succeed."
26217
26655
  };
26218
26656
  }
26219
26657
  }
26220
- async function checkHealth(apiBase) {
26221
- const url = `${apiBase}/health`;
26658
+ async function checkHealth(apiBase2) {
26659
+ const url = `${apiBase2}/health`;
26222
26660
  const controller = new AbortController();
26223
26661
  const timer = setTimeout(() => controller.abort(), 5e3);
26224
26662
  try {
@@ -26244,13 +26682,13 @@ async function checkHealth(apiBase) {
26244
26682
  }
26245
26683
  }
26246
26684
  function checkConfigDir() {
26247
- const dir = path53.join(require("os").homedir(), ".codeam");
26685
+ const dir = path56.join(require("os").homedir(), ".codeam");
26248
26686
  try {
26249
- fs41.mkdirSync(dir, { recursive: true, mode: 448 });
26250
- const probe = path53.join(dir, ".doctor-probe");
26251
- fs41.writeFileSync(probe, "ok", { mode: 384 });
26252
- const read = fs41.readFileSync(probe, "utf8");
26253
- fs41.unlinkSync(probe);
26687
+ fs44.mkdirSync(dir, { recursive: true, mode: 448 });
26688
+ const probe = path56.join(dir, ".doctor-probe");
26689
+ fs44.writeFileSync(probe, "ok", { mode: 384 });
26690
+ const read = fs44.readFileSync(probe, "utf8");
26691
+ fs44.unlinkSync(probe);
26254
26692
  if (read !== "ok") throw new Error("write/read round-trip mismatch");
26255
26693
  return {
26256
26694
  id: "config-dir",
@@ -26290,9 +26728,9 @@ function checkSessions() {
26290
26728
  }
26291
26729
  }
26292
26730
  function checkAgentBinaries() {
26293
- const os33 = createOsStrategy();
26731
+ const os36 = createOsStrategy();
26294
26732
  return getEnabledAgents().map((meta) => {
26295
- const found = os33.findInPath(meta.binaryName);
26733
+ const found = os36.findInPath(meta.binaryName);
26296
26734
  return {
26297
26735
  id: `agent-${meta.id}`,
26298
26736
  label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
@@ -26314,7 +26752,7 @@ function checkNodePty() {
26314
26752
  detail: "not required on this platform"
26315
26753
  };
26316
26754
  }
26317
- const vendoredPath = path53.join(__dirname, "vendor", "node-pty");
26755
+ const vendoredPath = path56.join(__dirname, "vendor", "node-pty");
26318
26756
  for (const target of [vendoredPath, "node-pty"]) {
26319
26757
  try {
26320
26758
  require(target);
@@ -26356,13 +26794,13 @@ function checkChokidar() {
26356
26794
  }
26357
26795
  async function doctor(args2 = []) {
26358
26796
  const json = args2.includes("--json");
26359
- const cliVersion = true ? "2.39.24" : "0.0.0-dev";
26360
- const apiBase = resolveApiBaseUrl();
26797
+ const cliVersion = true ? "2.39.25" : "0.0.0-dev";
26798
+ const apiBase2 = resolveApiBaseUrl();
26361
26799
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
26362
26800
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
26363
26801
  const [dns2, health] = await Promise.all([
26364
- checkDns(apiBase),
26365
- checkHealth(apiBase)
26802
+ checkDns(apiBase2),
26803
+ checkHealth(apiBase2)
26366
26804
  ]);
26367
26805
  const checks = [
26368
26806
  dns2,
@@ -26379,7 +26817,7 @@ async function doctor(args2 = []) {
26379
26817
  node: process.version,
26380
26818
  platform: process.platform,
26381
26819
  arch: process.arch,
26382
- apiBase,
26820
+ apiBase: apiBase2,
26383
26821
  checks,
26384
26822
  // Optional checks (e.g. agent-binary probes) report status but
26385
26823
  // don't gate exit code — see CheckResult.optional.
@@ -26555,7 +26993,7 @@ async function completion(args2) {
26555
26993
  // src/commands/version.ts
26556
26994
  var import_picocolors13 = __toESM(require("picocolors"));
26557
26995
  function version2() {
26558
- const v = true ? "2.39.24" : "unknown";
26996
+ const v = true ? "2.39.25" : "unknown";
26559
26997
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
26560
26998
  }
26561
26999
 
@@ -26683,23 +27121,23 @@ function tryShowSubcommandHelp(cmd, args2) {
26683
27121
  var _subcommandHelpKeys = Object.keys(HELPS);
26684
27122
 
26685
27123
  // src/lib/updateNotifier.ts
26686
- var fs42 = __toESM(require("fs"));
26687
- var os32 = __toESM(require("os"));
26688
- var path54 = __toESM(require("path"));
27124
+ var fs45 = __toESM(require("fs"));
27125
+ var os35 = __toESM(require("os"));
27126
+ var path57 = __toESM(require("path"));
26689
27127
  var https8 = __toESM(require("https"));
26690
- var import_node_child_process12 = require("child_process");
27128
+ var import_node_child_process14 = require("child_process");
26691
27129
  var import_picocolors16 = __toESM(require("picocolors"));
26692
27130
  var PKG_NAME = "codeam-cli";
26693
27131
  var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
26694
27132
  var TTL_MS = 24 * 60 * 60 * 1e3;
26695
27133
  var REQUEST_TIMEOUT_MS = 1500;
26696
27134
  function cachePath() {
26697
- const dir = path54.join(os32.homedir(), ".codeam");
26698
- return path54.join(dir, "update-check.json");
27135
+ const dir = path57.join(os35.homedir(), ".codeam");
27136
+ return path57.join(dir, "update-check.json");
26699
27137
  }
26700
27138
  function readCache() {
26701
27139
  try {
26702
- const raw = fs42.readFileSync(cachePath(), "utf8");
27140
+ const raw = fs45.readFileSync(cachePath(), "utf8");
26703
27141
  const parsed = JSON.parse(raw);
26704
27142
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
26705
27143
  return parsed;
@@ -26710,10 +27148,10 @@ function readCache() {
26710
27148
  function writeCache(cache) {
26711
27149
  try {
26712
27150
  const file = cachePath();
26713
- fs42.mkdirSync(path54.dirname(file), { recursive: true });
27151
+ fs45.mkdirSync(path57.dirname(file), { recursive: true });
26714
27152
  const tmp = `${file}.${process.pid}.tmp`;
26715
- fs42.writeFileSync(tmp, JSON.stringify(cache));
26716
- fs42.renameSync(tmp, file);
27153
+ fs45.writeFileSync(tmp, JSON.stringify(cache));
27154
+ fs45.renameSync(tmp, file);
26717
27155
  } catch {
26718
27156
  }
26719
27157
  }
@@ -26781,14 +27219,14 @@ function notifyIfStale(currentVersion, latest) {
26781
27219
  }
26782
27220
  function isLinkedInstall() {
26783
27221
  try {
26784
- const root = (0, import_node_child_process12.execSync)("npm root -g", {
27222
+ const root = (0, import_node_child_process14.execSync)("npm root -g", {
26785
27223
  encoding: "utf8",
26786
27224
  stdio: ["ignore", "pipe", "ignore"],
26787
27225
  timeout: 2e3
26788
27226
  }).trim();
26789
27227
  if (!root) return false;
26790
- const pkgPath = path54.join(root, PKG_NAME);
26791
- return fs42.lstatSync(pkgPath).isSymbolicLink();
27228
+ const pkgPath = path57.join(root, PKG_NAME);
27229
+ return fs45.lstatSync(pkgPath).isSymbolicLink();
26792
27230
  } catch {
26793
27231
  return false;
26794
27232
  }
@@ -26809,7 +27247,7 @@ function maybeAutoUpdate(currentVersion, latest) {
26809
27247
 
26810
27248
  `
26811
27249
  );
26812
- const install = (0, import_node_child_process12.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
27250
+ const install = (0, import_node_child_process14.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
26813
27251
  stdio: "inherit",
26814
27252
  env: process.env
26815
27253
  });
@@ -26824,13 +27262,13 @@ function maybeAutoUpdate(currentVersion, latest) {
26824
27262
  return;
26825
27263
  }
26826
27264
  try {
26827
- fs42.unlinkSync(cachePath());
27265
+ fs45.unlinkSync(cachePath());
26828
27266
  } catch {
26829
27267
  }
26830
27268
  process.stderr.write(` ${import_picocolors16.default.green("\u2713")} Updated. Resuming session...
26831
27269
 
26832
27270
  `);
26833
- const child = (0, import_node_child_process12.spawnSync)("codeam", process.argv.slice(2), {
27271
+ const child = (0, import_node_child_process14.spawnSync)("codeam", process.argv.slice(2), {
26834
27272
  stdio: "inherit",
26835
27273
  env: process.env
26836
27274
  });
@@ -26841,7 +27279,7 @@ function checkForUpdates() {
26841
27279
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
26842
27280
  if (process.env.CI) return;
26843
27281
  if (!process.stdout.isTTY) return;
26844
- const current = true ? "2.39.24" : null;
27282
+ const current = true ? "2.39.25" : null;
26845
27283
  if (!current) return;
26846
27284
  const cache = readCache();
26847
27285
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -26886,6 +27324,8 @@ async function main() {
26886
27324
  const commands = {
26887
27325
  "pair": () => pair(args),
26888
27326
  "pair-auto": () => pairAuto(args),
27327
+ "host-agent": () => hostAgent(args),
27328
+ "host": () => host(args),
26889
27329
  "sessions": () => sessions2(args),
26890
27330
  "status": () => status(),
26891
27331
  "logout": () => logout(),