codeam-cli 2.39.82 → 2.39.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/index.js +532 -246
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -515,9 +515,9 @@ var _default = makeConfig();
515
515
  var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, clearAll, saveCliConfig, loadCliConfig } = _default;
516
516
 
517
517
  // src/commands/pair-auto.ts
518
- var fs40 = __toESM(require("fs"));
519
- var os33 = __toESM(require("os"));
520
- var path46 = __toESM(require("path"));
518
+ var fs41 = __toESM(require("fs"));
519
+ var os34 = __toESM(require("os"));
520
+ var path47 = __toESM(require("path"));
521
521
  var import_crypto4 = require("crypto");
522
522
 
523
523
  // src/services/telemetry.service.ts
@@ -553,8 +553,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
553
553
  return decodedFile;
554
554
  };
555
555
  }
556
- function normalizeWindowsPath(path59) {
557
- return path59.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
556
+ function normalizeWindowsPath(path60) {
557
+ return path60.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
558
558
  }
559
559
 
560
560
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -3034,9 +3034,9 @@ async function addSourceContext(frames) {
3034
3034
  LRU_FILE_CONTENTS_CACHE.reduce();
3035
3035
  return frames;
3036
3036
  }
3037
- function getContextLinesFromFile(path59, ranges, output) {
3037
+ function getContextLinesFromFile(path60, ranges, output) {
3038
3038
  return new Promise((resolve7) => {
3039
- const stream = (0, import_node_fs.createReadStream)(path59);
3039
+ const stream = (0, import_node_fs.createReadStream)(path60);
3040
3040
  const lineReaded = (0, import_node_readline.createInterface)({
3041
3041
  input: stream
3042
3042
  });
@@ -3051,7 +3051,7 @@ function getContextLinesFromFile(path59, ranges, output) {
3051
3051
  let rangeStart = range[0];
3052
3052
  let rangeEnd = range[1];
3053
3053
  function onStreamError() {
3054
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path59, 1);
3054
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path60, 1);
3055
3055
  lineReaded.close();
3056
3056
  lineReaded.removeAllListeners();
3057
3057
  destroyStreamAndResolve();
@@ -3112,8 +3112,8 @@ function clearLineContext(frame) {
3112
3112
  delete frame.context_line;
3113
3113
  delete frame.post_context;
3114
3114
  }
3115
- function shouldSkipContextLinesForFile(path59) {
3116
- return path59.startsWith("node:") || path59.endsWith(".min.js") || path59.endsWith(".min.cjs") || path59.endsWith(".min.mjs") || path59.startsWith("data:");
3115
+ function shouldSkipContextLinesForFile(path60) {
3116
+ return path60.startsWith("node:") || path60.endsWith(".min.js") || path60.endsWith(".min.cjs") || path60.endsWith(".min.mjs") || path60.startsWith("data:");
3117
3117
  }
3118
3118
  function shouldSkipContextLinesForFrame(frame) {
3119
3119
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -5390,7 +5390,7 @@ function readAnonId() {
5390
5390
  }
5391
5391
  function superProperties() {
5392
5392
  return {
5393
- cliVersion: true ? "2.39.82" : "0.0.0-dev",
5393
+ cliVersion: true ? "2.39.84" : "0.0.0-dev",
5394
5394
  nodeVersion: process.version,
5395
5395
  platform: process.platform,
5396
5396
  arch: process.arch,
@@ -5549,7 +5549,7 @@ var os4 = __toESM(require("os"));
5549
5549
  // package.json
5550
5550
  var package_default = {
5551
5551
  name: "codeam-cli",
5552
- version: "2.39.82",
5552
+ version: "2.39.84",
5553
5553
  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.",
5554
5554
  type: "commonjs",
5555
5555
  main: "dist/index.js",
@@ -6506,10 +6506,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
6506
6506
  /[\\/]Start Menu([\\/]|$)/i,
6507
6507
  /[\\/]Templates([\\/]|$)/i
6508
6508
  ];
6509
- function isUnsafeWindowsWatchRoot(dir, homedir32) {
6509
+ function isUnsafeWindowsWatchRoot(dir, homedir33) {
6510
6510
  const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
6511
6511
  const cwd = norm(dir);
6512
- const home = norm(homedir32);
6512
+ const home = norm(homedir33);
6513
6513
  if (cwd === home) return true;
6514
6514
  if (/^[a-z]:$/.test(cwd)) return true;
6515
6515
  const sysRoots = [
@@ -11048,10 +11048,10 @@ function buildForPlatform(platform3) {
11048
11048
  var import_node_crypto4 = require("crypto");
11049
11049
 
11050
11050
  // src/agents/claude/resolver.ts
11051
- function buildClaudeLaunch(extraArgs = [], os39 = createOsStrategy()) {
11052
- const found = os39.findInPath("claude") ?? os39.findInPath("claude-code");
11051
+ function buildClaudeLaunch(extraArgs = [], os40 = createOsStrategy()) {
11052
+ const found = os40.findInPath("claude") ?? os40.findInPath("claude-code");
11053
11053
  if (!found) return null;
11054
- return os39.buildLaunch(found, extraArgs);
11054
+ return os40.buildLaunch(found, extraArgs);
11055
11055
  }
11056
11056
 
11057
11057
  // src/agents/claude/installer.ts
@@ -11078,12 +11078,12 @@ function isAvailable() {
11078
11078
  }
11079
11079
  function augmentPath() {
11080
11080
  const dirs = probeInstallDirs();
11081
- const sep5 = path14.delimiter;
11081
+ const sep6 = path14.delimiter;
11082
11082
  const current = process.env.PATH ?? "";
11083
- const existing = new Set(current.split(sep5).filter(Boolean));
11083
+ const existing = new Set(current.split(sep6).filter(Boolean));
11084
11084
  const additions = dirs.filter((d3) => !existing.has(d3));
11085
11085
  if (additions.length === 0) return;
11086
- process.env.PATH = additions.join(sep5) + sep5 + current;
11086
+ process.env.PATH = additions.join(sep6) + sep6 + current;
11087
11087
  }
11088
11088
  function runInstaller() {
11089
11089
  const isWindows = process.platform === "win32";
@@ -11200,13 +11200,34 @@ function readClaudeAgentState() {
11200
11200
  }
11201
11201
 
11202
11202
  // src/agents/claude/link.ts
11203
+ function validateClaudeToken(token) {
11204
+ if (token.method !== "oauth") return { status: "unknown" };
11205
+ let oauth;
11206
+ try {
11207
+ const parsed = JSON.parse(token.credential);
11208
+ const inner = parsed.claudeAiOauth;
11209
+ oauth = inner && typeof inner === "object" ? inner : parsed;
11210
+ } catch {
11211
+ return { status: "unknown" };
11212
+ }
11213
+ const expiresAt = typeof oauth.expiresAt === "number" ? oauth.expiresAt : null;
11214
+ if (expiresAt === null) return { status: "unknown" };
11215
+ if (expiresAt >= Date.now()) return { status: "valid" };
11216
+ const hasRefresh = typeof oauth.refreshToken === "string" && oauth.refreshToken.length > 0;
11217
+ if (hasRefresh) return { status: "unknown" };
11218
+ return {
11219
+ status: "expired",
11220
+ reason: "Your local Claude session has expired with no refresh token."
11221
+ };
11222
+ }
11203
11223
  function claudeCredentialLocator() {
11204
11224
  return {
11205
11225
  publicId: "claude_code",
11206
11226
  vendor: "Anthropic",
11207
11227
  hint: "~/.claude/.credentials.json or the macOS Keychain",
11208
11228
  watchPaths: claudeCredentialsPaths,
11209
- extract: extractLocalClaudeToken
11229
+ extract: extractLocalClaudeToken,
11230
+ validate: validateClaudeToken
11210
11231
  };
11211
11232
  }
11212
11233
  function claudeLoginLauncher() {
@@ -11588,8 +11609,8 @@ var ClaudeRuntimeStrategy = class {
11588
11609
  meta = getAgent("claude");
11589
11610
  mode = "interactive";
11590
11611
  os;
11591
- constructor(os39) {
11592
- this.os = os39;
11612
+ constructor(os40) {
11613
+ this.os = os40;
11593
11614
  }
11594
11615
  /**
11595
11616
  * Claude Code's react-ink TUI enables bracketed-paste mode at
@@ -12208,8 +12229,8 @@ function codexCredentialLocator() {
12208
12229
  function codexLoginLauncher() {
12209
12230
  return {
12210
12231
  async ensureInstalled() {
12211
- const os39 = createOsStrategy();
12212
- return os39.findInPath("codex") !== null;
12232
+ const os40 = createOsStrategy();
12233
+ return os40.findInPath("codex") !== null;
12213
12234
  },
12214
12235
  launch() {
12215
12236
  return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
@@ -12232,8 +12253,8 @@ var CodexRuntimeStrategy = class {
12232
12253
  meta = getAgent("codex");
12233
12254
  mode = "interactive";
12234
12255
  os;
12235
- constructor(os39) {
12236
- this.os = os39;
12256
+ constructor(os40) {
12257
+ this.os = os40;
12237
12258
  }
12238
12259
  async prepareLaunch() {
12239
12260
  let binary = this.os.findInPath("codex");
@@ -12329,12 +12350,12 @@ var CodexRuntimeStrategy = class {
12329
12350
  });
12330
12351
  }
12331
12352
  };
12332
- function resolveNpm(os39) {
12333
- return os39.id === "win32" ? "npm.cmd" : "npm";
12353
+ function resolveNpm(os40) {
12354
+ return os40.id === "win32" ? "npm.cmd" : "npm";
12334
12355
  }
12335
- async function installCodexViaNpm(os39) {
12356
+ async function installCodexViaNpm(os40) {
12336
12357
  return new Promise((resolve7, reject) => {
12337
- const proc = (0, import_node_child_process4.spawn)(resolveNpm(os39), ["install", "-g", "@openai/codex"], {
12358
+ const proc = (0, import_node_child_process4.spawn)(resolveNpm(os40), ["install", "-g", "@openai/codex"], {
12338
12359
  stdio: "inherit"
12339
12360
  });
12340
12361
  proc.on("close", (code) => {
@@ -12351,16 +12372,16 @@ async function installCodexViaNpm(os39) {
12351
12372
  });
12352
12373
  });
12353
12374
  }
12354
- function augmentNpmGlobalBin(os39) {
12375
+ function augmentNpmGlobalBin(os40) {
12355
12376
  try {
12356
- const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os39), ["prefix", "-g"], {
12377
+ const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os40), ["prefix", "-g"], {
12357
12378
  stdio: ["ignore", "pipe", "ignore"]
12358
12379
  });
12359
12380
  if (result.status !== 0) return;
12360
12381
  const prefix = result.stdout.toString().trim();
12361
12382
  if (!prefix) return;
12362
- const binDir = os39.id === "win32" ? prefix : path22.join(prefix, "bin");
12363
- os39.augmentPath([binDir]);
12383
+ const binDir = os40.id === "win32" ? prefix : path22.join(prefix, "bin");
12384
+ os40.augmentPath([binDir]);
12364
12385
  } catch {
12365
12386
  }
12366
12387
  }
@@ -12444,9 +12465,9 @@ var import_node_child_process7 = require("child_process");
12444
12465
  // src/agents/coderabbit/installer.ts
12445
12466
  var import_node_child_process5 = require("child_process");
12446
12467
  var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
12447
- async function ensureCoderabbitInstalled(os39) {
12448
- if (os39.findInPath("coderabbit")) return true;
12449
- if (os39.id === "win32") {
12468
+ async function ensureCoderabbitInstalled(os40) {
12469
+ if (os40.findInPath("coderabbit")) return true;
12470
+ if (os40.id === "win32") {
12450
12471
  console.error(
12451
12472
  "\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"
12452
12473
  );
@@ -12461,8 +12482,8 @@ async function ensureCoderabbitInstalled(os39) {
12461
12482
  proc.on("error", () => resolve7(false));
12462
12483
  });
12463
12484
  if (!ok) return false;
12464
- os39.augmentPath([`${os39.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
12465
- return os39.findInPath("coderabbit") !== null;
12485
+ os40.augmentPath([`${os40.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
12486
+ return os40.findInPath("coderabbit") !== null;
12466
12487
  }
12467
12488
 
12468
12489
  // src/agents/coderabbit/link.ts
@@ -12470,6 +12491,13 @@ var import_node_child_process6 = require("child_process");
12470
12491
  var fs19 = __toESM(require("fs"));
12471
12492
  var os18 = __toESM(require("os"));
12472
12493
  var path24 = __toESM(require("path"));
12494
+
12495
+ // src/agents/strategy.ts
12496
+ function validateNonEmptyCredential(token) {
12497
+ return { status: token.credential.trim().length > 0 ? "valid" : "unknown" };
12498
+ }
12499
+
12500
+ // src/agents/coderabbit/link.ts
12473
12501
  function authPath() {
12474
12502
  return path24.join(os18.homedir(), ".coderabbit", "auth.json");
12475
12503
  }
@@ -12486,13 +12514,14 @@ function coderabbitCredentialLocator() {
12486
12514
  vendor: "CodeRabbit",
12487
12515
  hint: "~/.coderabbit/auth.json",
12488
12516
  watchPaths: () => [authPath()],
12489
- extract: extractLocalCoderabbitToken
12517
+ extract: extractLocalCoderabbitToken,
12518
+ validate: validateNonEmptyCredential
12490
12519
  };
12491
12520
  }
12492
- function coderabbitLoginLauncher(os39) {
12521
+ function coderabbitLoginLauncher(os40) {
12493
12522
  return {
12494
12523
  async ensureInstalled() {
12495
- return ensureCoderabbitInstalled(os39);
12524
+ return ensureCoderabbitInstalled(os40);
12496
12525
  },
12497
12526
  launch() {
12498
12527
  return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
@@ -12515,11 +12544,11 @@ function parseReview(stdout) {
12515
12544
  for (const line of lines) {
12516
12545
  const m = line.match(HUNK_LINE_RE);
12517
12546
  if (!m) continue;
12518
- const [, path59, lineNo, sevToken, message] = m;
12519
- if (!path59 || !lineNo || !message) continue;
12547
+ const [, path60, lineNo, sevToken, message] = m;
12548
+ if (!path60 || !lineNo || !message) continue;
12520
12549
  const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
12521
12550
  hunks.push({
12522
- path: path59.trim(),
12551
+ path: path60.trim(),
12523
12552
  line: Number(lineNo),
12524
12553
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
12525
12554
  message: cleanedMessage
@@ -12538,8 +12567,8 @@ var CoderabbitRuntimeStrategy = class {
12538
12567
  meta = getAgent("coderabbit");
12539
12568
  mode = "batch";
12540
12569
  os;
12541
- constructor(os39) {
12542
- this.os = os39;
12570
+ constructor(os40) {
12571
+ this.os = os40;
12543
12572
  }
12544
12573
  getDefaultArgs() {
12545
12574
  return ["review"];
@@ -12651,13 +12680,14 @@ function cursorCredentialLocator() {
12651
12680
  vendor: "Cursor",
12652
12681
  hint: "~/.cursor/auth.json",
12653
12682
  watchPaths: cursorCredentialsPaths,
12654
- extract: extractLocalCursorToken
12683
+ extract: extractLocalCursorToken,
12684
+ validate: validateNonEmptyCredential
12655
12685
  };
12656
12686
  }
12657
- function cursorLoginLauncher(os39) {
12687
+ function cursorLoginLauncher(os40) {
12658
12688
  return {
12659
12689
  async ensureInstalled() {
12660
- if (os39.findInPath("cursor-agent")) return true;
12690
+ if (os40.findInPath("cursor-agent")) return true;
12661
12691
  console.error(
12662
12692
  "\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"
12663
12693
  );
@@ -12719,8 +12749,8 @@ var CursorRuntimeStrategy = class {
12719
12749
  meta = getAgent("cursor");
12720
12750
  mode = "interactive";
12721
12751
  os;
12722
- constructor(os39) {
12723
- this.os = os39;
12752
+ constructor(os40) {
12753
+ this.os = os40;
12724
12754
  }
12725
12755
  async prepareLaunch() {
12726
12756
  const binary = this.os.findInPath("cursor-agent");
@@ -12837,13 +12867,14 @@ function aiderCredentialLocator() {
12837
12867
  vendor: "Aider",
12838
12868
  hint: "ANTHROPIC_API_KEY / OPENAI_API_KEY env var or ~/.aider.conf.yml",
12839
12869
  watchPaths: aiderCredentialsPaths,
12840
- extract: extractLocalAiderToken
12870
+ extract: extractLocalAiderToken,
12871
+ validate: validateNonEmptyCredential
12841
12872
  };
12842
12873
  }
12843
- function aiderLoginLauncher(os39) {
12874
+ function aiderLoginLauncher(os40) {
12844
12875
  return {
12845
12876
  async ensureInstalled() {
12846
- if (os39.findInPath("aider")) return true;
12877
+ if (os40.findInPath("aider")) return true;
12847
12878
  console.error(
12848
12879
  "\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
12849
12880
  );
@@ -12853,7 +12884,7 @@ function aiderLoginLauncher(os39) {
12853
12884
  console.error(
12854
12885
  "\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"
12855
12886
  );
12856
- return (0, import_node_child_process9.spawn)(os39.id === "win32" ? "cmd.exe" : "sh", os39.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
12887
+ return (0, import_node_child_process9.spawn)(os40.id === "win32" ? "cmd.exe" : "sh", os40.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
12857
12888
  stdio: "ignore"
12858
12889
  });
12859
12890
  }
@@ -12925,8 +12956,8 @@ var AiderRuntimeStrategy = class {
12925
12956
  meta = getAgent("aider");
12926
12957
  mode = "interactive";
12927
12958
  os;
12928
- constructor(os39) {
12929
- this.os = os39;
12959
+ constructor(os40) {
12960
+ this.os = os40;
12930
12961
  }
12931
12962
  async prepareLaunch() {
12932
12963
  const binary = this.os.findInPath("aider");
@@ -13055,8 +13086,8 @@ function geminiCredentialLocator() {
13055
13086
  function geminiLoginLauncher() {
13056
13087
  return {
13057
13088
  async ensureInstalled() {
13058
- const os39 = createOsStrategy();
13059
- return os39.findInPath("gemini") !== null;
13089
+ const os40 = createOsStrategy();
13090
+ return os40.findInPath("gemini") !== null;
13060
13091
  },
13061
13092
  launch() {
13062
13093
  return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
@@ -13089,8 +13120,8 @@ var GeminiRuntimeStrategy = class {
13089
13120
  meta = getAgent("gemini");
13090
13121
  mode = "interactive";
13091
13122
  os;
13092
- constructor(os39) {
13093
- this.os = os39;
13123
+ constructor(os40) {
13124
+ this.os = os40;
13094
13125
  }
13095
13126
  async prepareLaunch() {
13096
13127
  const binary = this.os.findInPath("gemini");
@@ -13189,18 +13220,18 @@ var GeminiRuntimeStrategy = class {
13189
13220
 
13190
13221
  // src/agents/registry.ts
13191
13222
  var runtimeBuilders = {
13192
- claude: (os39) => new ClaudeRuntimeStrategy(os39),
13193
- codex: (os39) => new CodexRuntimeStrategy(os39),
13194
- coderabbit: (os39) => new CoderabbitRuntimeStrategy(os39),
13195
- cursor: (os39) => new CursorRuntimeStrategy(os39),
13196
- aider: (os39) => new AiderRuntimeStrategy(os39),
13197
- gemini: (os39) => new GeminiRuntimeStrategy(os39)
13223
+ claude: (os40) => new ClaudeRuntimeStrategy(os40),
13224
+ codex: (os40) => new CodexRuntimeStrategy(os40),
13225
+ coderabbit: (os40) => new CoderabbitRuntimeStrategy(os40),
13226
+ cursor: (os40) => new CursorRuntimeStrategy(os40),
13227
+ aider: (os40) => new AiderRuntimeStrategy(os40),
13228
+ gemini: (os40) => new GeminiRuntimeStrategy(os40)
13198
13229
  };
13199
13230
  var deployBuilders = {
13200
13231
  claude: () => new ClaudeDeployStrategy(),
13201
13232
  codex: () => new CodexDeployStrategy()
13202
13233
  };
13203
- function createAgentStrategy(agent, os39 = createOsStrategy()) {
13234
+ function createAgentStrategy(agent, os40 = createOsStrategy()) {
13204
13235
  if (!AGENT_REGISTRY[agent]?.enabled) {
13205
13236
  throw new Error(
13206
13237
  `Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
@@ -13210,10 +13241,10 @@ function createAgentStrategy(agent, os39 = createOsStrategy()) {
13210
13241
  if (!build) {
13211
13242
  throw new Error(`No runtime strategy registered for agent "${agent}"`);
13212
13243
  }
13213
- return build(os39);
13244
+ return build(os40);
13214
13245
  }
13215
- function createInteractiveAgentStrategy(agent, os39 = createOsStrategy()) {
13216
- const s = createAgentStrategy(agent, os39);
13246
+ function createInteractiveAgentStrategy(agent, os40 = createOsStrategy()) {
13247
+ const s = createAgentStrategy(agent, os40);
13217
13248
  if (s.mode !== "interactive") {
13218
13249
  throw new Error(
13219
13250
  `Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
@@ -14516,11 +14547,11 @@ function resolveDoltInstallStrategy(platform3) {
14516
14547
  }
14517
14548
  var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
14518
14549
  function doltPlatformTuple(platform3, arch2) {
14519
- const os39 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
14550
+ const os40 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
14520
14551
  const a = arch2 === "x64" ? "amd64" : arch2 === "arm64" ? "arm64" : null;
14521
14552
  if (!a) return null;
14522
- if (os39 === "windows" && a !== "amd64") return null;
14523
- return `${os39}-${a}`;
14553
+ if (os40 === "windows" && a !== "amd64") return null;
14554
+ return `${os40}-${a}`;
14524
14555
  }
14525
14556
  function resolveDoltTarballStrategy(targetDir, platform3, arch2) {
14526
14557
  const tuple = doltPlatformTuple(platform3, arch2);
@@ -16838,10 +16869,10 @@ async function startInfraOnly(agentId) {
16838
16869
  }
16839
16870
 
16840
16871
  // src/commands/host-agent.ts
16841
- var import_node_child_process13 = require("child_process");
16842
- var os32 = __toESM(require("os"));
16843
- var fs39 = __toESM(require("fs"));
16844
- var path45 = __toESM(require("path"));
16872
+ var import_node_child_process14 = require("child_process");
16873
+ var os33 = __toESM(require("os"));
16874
+ var fs40 = __toESM(require("fs"));
16875
+ var path46 = __toESM(require("path"));
16845
16876
 
16846
16877
  // src/commands/host/host-client.ts
16847
16878
  var fs35 = __toESM(require("fs"));
@@ -17112,6 +17143,61 @@ function repoCloneUrl(repoRef, cloneToken) {
17112
17143
  function maskCloneUrl(url) {
17113
17144
  return url.replace(/(https?:\/\/)[^@/]+@/, "$1***@");
17114
17145
  }
17146
+ async function fetchGithubIdentity(token) {
17147
+ try {
17148
+ const res = await fetch("https://api.github.com/user", {
17149
+ headers: {
17150
+ Authorization: `Bearer ${token}`,
17151
+ "User-Agent": "codeam-cli",
17152
+ Accept: "application/vnd.github+json"
17153
+ }
17154
+ });
17155
+ if (!res.ok) return null;
17156
+ const body = await res.json();
17157
+ return { login: body.login, email: body.email ?? void 0 };
17158
+ } catch {
17159
+ return null;
17160
+ }
17161
+ }
17162
+ async function configureGitCredentials(dest, repoRef, cloneToken) {
17163
+ const gh = githubOwnerRepo(repoRef.trim());
17164
+ if (!gh || !cloneToken) return;
17165
+ const credFile = path42.join(dest, ".git", "codeam-credentials");
17166
+ fs36.writeFileSync(credFile, `https://x-access-token:${cloneToken}@github.com
17167
+ `, { mode: 384 });
17168
+ try {
17169
+ fs36.chmodSync(credFile, 384);
17170
+ } catch {
17171
+ }
17172
+ const env = nonInteractiveGitEnv();
17173
+ const git2 = (args2) => execFileP5("git", ["-C", dest, ...args2], { timeout: 3e4, env });
17174
+ const credFilePosix = credFile.split(path42.sep).join("/");
17175
+ await git2(["config", "--local", "--replace-all", "credential.helper", ""]).catch(() => {
17176
+ });
17177
+ await git2([
17178
+ "config",
17179
+ "--local",
17180
+ "--add",
17181
+ "credential.helper",
17182
+ `store --file=${credFilePosix}`
17183
+ ]).catch(() => {
17184
+ });
17185
+ await git2(["remote", "set-url", "origin", repoCloneUrl(repoRef)]).catch(() => {
17186
+ });
17187
+ const hasIdentity = await git2(["config", "user.email"]).then(() => true).catch(() => false);
17188
+ if (!hasIdentity) {
17189
+ const who = await fetchGithubIdentity(cloneToken);
17190
+ if (who?.login) {
17191
+ await git2(["config", "--local", "user.name", who.login]).catch(() => {
17192
+ });
17193
+ }
17194
+ const email = who?.email ?? (who?.login ? `${who.login}@users.noreply.github.com` : void 0);
17195
+ if (email) {
17196
+ await git2(["config", "--local", "user.email", email]).catch(() => {
17197
+ });
17198
+ }
17199
+ }
17200
+ }
17115
17201
  function maskToken(text, cloneToken) {
17116
17202
  const masked = maskCloneUrl(text);
17117
17203
  if (cloneToken && cloneToken.length > 0) {
@@ -17128,6 +17214,7 @@ async function prepareWorkspace(repoOrPath, deployId, cloneToken) {
17128
17214
  }
17129
17215
  const dest = path42.join(selfHostedWorkspaceRoot(), deployId);
17130
17216
  if (fs36.existsSync(path42.join(dest, ".git"))) {
17217
+ if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken);
17131
17218
  return dest;
17132
17219
  }
17133
17220
  fs36.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
@@ -17142,6 +17229,7 @@ async function prepareWorkspace(repoOrPath, deployId, cloneToken) {
17142
17229
  const reason = err instanceof Error ? err.message : String(err);
17143
17230
  throw new Error(`git clone failed for ${maskCloneUrl(cloneUrl)}: ${maskToken(reason, cloneToken)}`);
17144
17231
  }
17232
+ if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken);
17145
17233
  return dest;
17146
17234
  }
17147
17235
 
@@ -17215,6 +17303,167 @@ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os30.homedir(
17215
17303
  return provisioner.write(auth, homeDir2);
17216
17304
  }
17217
17305
 
17306
+ // src/commands/host/git-tooling.ts
17307
+ var import_node_child_process12 = require("child_process");
17308
+ var fs38 = __toESM(require("fs"));
17309
+ var os31 = __toESM(require("os"));
17310
+ var path44 = __toESM(require("path"));
17311
+ function codeamBinDir() {
17312
+ return process.env.CODEAM_BIN_DIR ?? path44.join(os31.homedir(), ".codeam", "bin");
17313
+ }
17314
+ var FALLBACK_GH_VERSION = "2.62.0";
17315
+ var RELEASE_API = "https://api.github.com/repos/cli/cli/releases/latest";
17316
+ function ghArch() {
17317
+ if (process.arch === "x64") return "amd64";
17318
+ if (process.arch === "arm64") return "arm64";
17319
+ return null;
17320
+ }
17321
+ async function resolveLatestGhVersion(token) {
17322
+ try {
17323
+ const headers = {
17324
+ Accept: "application/vnd.github+json",
17325
+ "User-Agent": "codeam-cli"
17326
+ };
17327
+ if (token) headers.Authorization = `Bearer ${token}`;
17328
+ const res = await fetch(RELEASE_API, { headers });
17329
+ if (!res.ok) return FALLBACK_GH_VERSION;
17330
+ const body = await res.json();
17331
+ if (typeof body.tag_name === "string" && body.tag_name) {
17332
+ return body.tag_name.replace(/^v/, "");
17333
+ }
17334
+ return FALLBACK_GH_VERSION;
17335
+ } catch {
17336
+ return FALLBACK_GH_VERSION;
17337
+ }
17338
+ }
17339
+ async function download(url, dest) {
17340
+ try {
17341
+ const res = await fetch(url, { headers: { "User-Agent": "codeam-cli" } });
17342
+ if (!res.ok || !res.body) return false;
17343
+ const buf = Buffer.from(await res.arrayBuffer());
17344
+ fs38.writeFileSync(dest, buf);
17345
+ return true;
17346
+ } catch {
17347
+ return false;
17348
+ }
17349
+ }
17350
+ async function ensureGhCli(runner, token, deps = {}) {
17351
+ if (runner.which("gh")) return "gh";
17352
+ const arch2 = ghArch();
17353
+ const platform3 = process.platform;
17354
+ if (arch2 === null || platform3 !== "linux" && platform3 !== "darwin" && platform3 !== "win32") {
17355
+ log.warn("host-agent", `gh auto-install unsupported on ${platform3}/${process.arch} \u2014 skipping`);
17356
+ return null;
17357
+ }
17358
+ const osToken = platform3 === "darwin" ? "macOS" : platform3 === "win32" ? "windows" : "linux";
17359
+ const ext = platform3 === "linux" ? "tar.gz" : "zip";
17360
+ const binaryName = platform3 === "win32" ? "gh.exe" : "gh";
17361
+ const downloadFn = deps.downloadFn ?? download;
17362
+ const resolveVersionFn = deps.resolveVersionFn ?? resolveLatestGhVersion;
17363
+ try {
17364
+ const version3 = await resolveVersionFn(token);
17365
+ const asset = `gh_${version3}_${osToken}_${arch2}`;
17366
+ const url = `https://github.com/cli/cli/releases/download/v${version3}/${asset}.${ext}`;
17367
+ const tmpRoot = fs38.mkdtempSync(path44.join(os31.tmpdir(), "codeam-gh-"));
17368
+ const archive = path44.join(tmpRoot, `${asset}.${ext}`);
17369
+ if (!await downloadFn(url, archive)) {
17370
+ log.warn("host-agent", "gh download failed \u2014 skipping (git pull/push still work via the credential helper)");
17371
+ return null;
17372
+ }
17373
+ const extract = await runner.run("tar", ["-xf", archive, "-C", tmpRoot], { timeoutMs: 6e4 });
17374
+ if (extract.code !== 0) {
17375
+ log.warn("host-agent", `gh archive extraction failed (code=${String(extract.code)}) \u2014 skipping`);
17376
+ return null;
17377
+ }
17378
+ const extractedBin = path44.join(tmpRoot, asset, "bin", binaryName);
17379
+ if (!fs38.existsSync(extractedBin)) {
17380
+ log.warn("host-agent", "gh binary not found in the extracted archive \u2014 skipping");
17381
+ return null;
17382
+ }
17383
+ const binDir = codeamBinDir();
17384
+ fs38.mkdirSync(binDir, { recursive: true });
17385
+ const target = path44.join(binDir, binaryName);
17386
+ fs38.copyFileSync(extractedBin, target);
17387
+ fs38.chmodSync(target, 493);
17388
+ log.info("host-agent", `gh installed to ${target} (v${version3})`);
17389
+ return target;
17390
+ } catch (e) {
17391
+ log.warn("host-agent", `gh auto-install errored: ${e instanceof Error ? e.message : String(e)} \u2014 skipping`);
17392
+ return null;
17393
+ }
17394
+ }
17395
+ async function ensureGhAuth(runner, ghCmd, token) {
17396
+ if (!token) return;
17397
+ try {
17398
+ const status2 = await runner.run(ghCmd, ["auth", "status"], { timeoutMs: 15e3 });
17399
+ if (status2.code === 0) {
17400
+ log.info("host-agent", "gh already authenticated \u2014 leaving the existing login untouched");
17401
+ return;
17402
+ }
17403
+ const login = await runner.run(ghCmd, ["auth", "login", "--with-token"], {
17404
+ timeoutMs: 2e4,
17405
+ input: `${token}
17406
+ `
17407
+ });
17408
+ if (login.code === 0) {
17409
+ log.info("host-agent", "gh authenticated with the linked GitHub token");
17410
+ } else {
17411
+ log.warn("host-agent", `gh auth login failed (code=${String(login.code)}) \u2014 gh unauthenticated`);
17412
+ }
17413
+ } catch (e) {
17414
+ log.warn("host-agent", `gh auth errored: ${e instanceof Error ? e.message : String(e)}`);
17415
+ }
17416
+ }
17417
+ var defaultGitToolingRunner = {
17418
+ which(cmd) {
17419
+ try {
17420
+ const probe = process.platform === "win32" ? "where" : "which";
17421
+ (0, import_node_child_process12.execFileSync)(probe, [cmd], { stdio: "ignore" });
17422
+ return true;
17423
+ } catch {
17424
+ return false;
17425
+ }
17426
+ },
17427
+ run(cmd, args2, opts = {}) {
17428
+ return new Promise((resolve7) => {
17429
+ const child = (0, import_node_child_process12.spawn)(cmd, args2, {
17430
+ stdio: [opts.input !== void 0 ? "pipe" : "ignore", "ignore", "pipe"]
17431
+ });
17432
+ let stderr = "";
17433
+ let settled = false;
17434
+ const done = (code) => {
17435
+ if (settled) return;
17436
+ settled = true;
17437
+ resolve7({ code, stderr });
17438
+ };
17439
+ child.stderr?.on("data", (b) => {
17440
+ stderr += b.toString();
17441
+ });
17442
+ if (opts.input !== void 0) {
17443
+ child.stdin?.end(opts.input);
17444
+ }
17445
+ let timer;
17446
+ if (opts.timeoutMs !== void 0) {
17447
+ timer = setTimeout(() => {
17448
+ try {
17449
+ child.kill("SIGTERM");
17450
+ } catch {
17451
+ }
17452
+ done(null);
17453
+ }, opts.timeoutMs);
17454
+ }
17455
+ child.once("exit", (code) => {
17456
+ if (timer) clearTimeout(timer);
17457
+ done(code);
17458
+ });
17459
+ child.once("error", () => {
17460
+ if (timer) clearTimeout(timer);
17461
+ done(null);
17462
+ });
17463
+ });
17464
+ }
17465
+ };
17466
+
17218
17467
  // src/services/headroom/stats-reporter.ts
17219
17468
  var DEFAULT_INPUT_PRICE_PER_MILLION = 3;
17220
17469
  var ZERO = {
@@ -17298,23 +17547,23 @@ var HeadroomStatsReporter = class {
17298
17547
  };
17299
17548
 
17300
17549
  // src/lib/updateNotifier.ts
17301
- var fs38 = __toESM(require("fs"));
17302
- var os31 = __toESM(require("os"));
17303
- var path44 = __toESM(require("path"));
17550
+ var fs39 = __toESM(require("fs"));
17551
+ var os32 = __toESM(require("os"));
17552
+ var path45 = __toESM(require("path"));
17304
17553
  var https6 = __toESM(require("https"));
17305
- var import_node_child_process12 = require("child_process");
17554
+ var import_node_child_process13 = require("child_process");
17306
17555
  var import_picocolors3 = __toESM(require("picocolors"));
17307
17556
  var PKG_NAME = "codeam-cli";
17308
17557
  var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
17309
17558
  var TTL_MS = 24 * 60 * 60 * 1e3;
17310
17559
  var REQUEST_TIMEOUT_MS = 1500;
17311
17560
  function cachePath() {
17312
- const dir = path44.join(os31.homedir(), ".codeam");
17313
- return path44.join(dir, "update-check.json");
17561
+ const dir = path45.join(os32.homedir(), ".codeam");
17562
+ return path45.join(dir, "update-check.json");
17314
17563
  }
17315
17564
  function readCache() {
17316
17565
  try {
17317
- const raw = fs38.readFileSync(cachePath(), "utf8");
17566
+ const raw = fs39.readFileSync(cachePath(), "utf8");
17318
17567
  const parsed = JSON.parse(raw);
17319
17568
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
17320
17569
  return parsed;
@@ -17325,10 +17574,10 @@ function readCache() {
17325
17574
  function writeCache(cache) {
17326
17575
  try {
17327
17576
  const file = cachePath();
17328
- fs38.mkdirSync(path44.dirname(file), { recursive: true });
17577
+ fs39.mkdirSync(path45.dirname(file), { recursive: true });
17329
17578
  const tmp = `${file}.${process.pid}.tmp`;
17330
- fs38.writeFileSync(tmp, JSON.stringify(cache));
17331
- fs38.renameSync(tmp, file);
17579
+ fs39.writeFileSync(tmp, JSON.stringify(cache));
17580
+ fs39.renameSync(tmp, file);
17332
17581
  } catch {
17333
17582
  }
17334
17583
  }
@@ -17396,14 +17645,14 @@ function notifyIfStale(currentVersion, latest) {
17396
17645
  }
17397
17646
  function isLinkedInstall() {
17398
17647
  try {
17399
- const root = (0, import_node_child_process12.execSync)("npm root -g", {
17648
+ const root = (0, import_node_child_process13.execSync)("npm root -g", {
17400
17649
  encoding: "utf8",
17401
17650
  stdio: ["ignore", "pipe", "ignore"],
17402
17651
  timeout: 2e3
17403
17652
  }).trim();
17404
17653
  if (!root) return false;
17405
- const pkgPath = path44.join(root, PKG_NAME);
17406
- return fs38.lstatSync(pkgPath).isSymbolicLink();
17654
+ const pkgPath = path45.join(root, PKG_NAME);
17655
+ return fs39.lstatSync(pkgPath).isSymbolicLink();
17407
17656
  } catch {
17408
17657
  return false;
17409
17658
  }
@@ -17424,7 +17673,7 @@ function maybeAutoUpdate(currentVersion, latest) {
17424
17673
 
17425
17674
  `
17426
17675
  );
17427
- const install = (0, import_node_child_process12.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
17676
+ const install = (0, import_node_child_process13.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
17428
17677
  stdio: "inherit",
17429
17678
  env: process.env
17430
17679
  });
@@ -17439,24 +17688,40 @@ function maybeAutoUpdate(currentVersion, latest) {
17439
17688
  return;
17440
17689
  }
17441
17690
  try {
17442
- fs38.unlinkSync(cachePath());
17691
+ fs39.unlinkSync(cachePath());
17443
17692
  } catch {
17444
17693
  }
17445
17694
  process.stderr.write(` ${import_picocolors3.default.green("\u2713")} Updated. Resuming session...
17446
17695
 
17447
17696
  `);
17448
- const child = (0, import_node_child_process12.spawnSync)("codeam", process.argv.slice(2), {
17697
+ const child = (0, import_node_child_process13.spawnSync)("codeam", process.argv.slice(2), {
17449
17698
  stdio: "inherit",
17450
17699
  env: process.env
17451
17700
  });
17452
17701
  process.exit(child.status ?? 0);
17453
17702
  }
17703
+ async function autoUpgradeBeforeCriticalCommand() {
17704
+ if (process.env.NODE_ENV === "test") return;
17705
+ if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17706
+ if (process.env.CI) return;
17707
+ const current = true ? "2.39.84" : null;
17708
+ if (!current) return;
17709
+ const cache = readCache();
17710
+ const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
17711
+ let latest = fresh && cache ? cache.latest : null;
17712
+ if (!latest) {
17713
+ latest = await fetchLatest();
17714
+ if (latest) writeCache({ fetchedAt: Date.now(), latest });
17715
+ }
17716
+ if (!latest) return;
17717
+ maybeAutoUpdate(current, latest);
17718
+ }
17454
17719
  function checkForUpdates() {
17455
17720
  if (process.env.NODE_ENV === "test") return;
17456
17721
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17457
17722
  if (process.env.CI) return;
17458
17723
  if (!process.stdout.isTTY) return;
17459
- const current = true ? "2.39.82" : null;
17724
+ const current = true ? "2.39.84" : null;
17460
17725
  if (!current) return;
17461
17726
  const cache = readCache();
17462
17727
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17565,7 +17830,7 @@ var HEADROOM_MIN_FREE_DISK_BYTES = 2 * 1024 * 1024 * 1024;
17565
17830
  var defaultHeadroomRunner = {
17566
17831
  which(cmd) {
17567
17832
  try {
17568
- (0, import_node_child_process13.execFileSync)("which", [cmd], { stdio: "ignore" });
17833
+ (0, import_node_child_process14.execFileSync)("which", [cmd], { stdio: "ignore" });
17569
17834
  return true;
17570
17835
  } catch {
17571
17836
  return false;
@@ -17573,7 +17838,7 @@ var defaultHeadroomRunner = {
17573
17838
  },
17574
17839
  run(cmd, args2, opts = {}) {
17575
17840
  return new Promise((resolve7) => {
17576
- const child = (0, import_node_child_process13.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"] });
17841
+ const child = (0, import_node_child_process14.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"] });
17577
17842
  let stderrBuf = "";
17578
17843
  let settled = false;
17579
17844
  const done = (code) => {
@@ -17727,15 +17992,15 @@ function agentIdToHeadroomKind(agentId) {
17727
17992
  return "claude";
17728
17993
  }
17729
17994
  function headroomConfigPath() {
17730
- return path45.join(os32.homedir(), ".codeam", "headroom-config.json");
17995
+ return path46.join(os33.homedir(), ".codeam", "headroom-config.json");
17731
17996
  }
17732
17997
  function persistHeadroomConfig(config) {
17733
17998
  try {
17734
17999
  const file = headroomConfigPath();
17735
- fs39.mkdirSync(path45.dirname(file), { recursive: true, mode: 448 });
18000
+ fs40.mkdirSync(path46.dirname(file), { recursive: true, mode: 448 });
17736
18001
  const tmp = `${file}.tmp-${process.pid}`;
17737
- fs39.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
17738
- fs39.renameSync(tmp, file);
18002
+ fs40.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
18003
+ fs40.renameSync(tmp, file);
17739
18004
  } catch (err) {
17740
18005
  log.warn(
17741
18006
  "host-agent",
@@ -17745,7 +18010,7 @@ function persistHeadroomConfig(config) {
17745
18010
  }
17746
18011
  function readHeadroomChildEnv() {
17747
18012
  try {
17748
- const raw = fs39.readFileSync(headroomConfigPath(), "utf8");
18013
+ const raw = fs40.readFileSync(headroomConfigPath(), "utf8");
17749
18014
  const parsed = JSON.parse(raw);
17750
18015
  if (typeof parsed !== "object" || parsed === null) return {};
17751
18016
  const o = parsed;
@@ -17765,37 +18030,37 @@ function bundledClaudeBinDir() {
17765
18030
  const roots = /* @__PURE__ */ new Set();
17766
18031
  let dir = __dirname;
17767
18032
  for (let i = 0; i < 6; i++) {
17768
- roots.add(path45.join(dir, "node_modules"));
17769
- const parent = path45.dirname(dir);
18033
+ roots.add(path46.join(dir, "node_modules"));
18034
+ const parent = path46.dirname(dir);
17770
18035
  if (parent === dir) break;
17771
18036
  dir = parent;
17772
18037
  }
17773
18038
  try {
17774
18039
  const main2 = require.resolve("@anthropic-ai/claude-agent-sdk");
17775
- const marker = `${path45.sep}@anthropic-ai${path45.sep}`;
18040
+ const marker = `${path46.sep}@anthropic-ai${path46.sep}`;
17776
18041
  const idx = main2.lastIndexOf(marker);
17777
18042
  if (idx !== -1) roots.add(main2.slice(0, idx));
17778
18043
  } catch {
17779
18044
  }
17780
18045
  for (const nm of roots) {
17781
- const atAnthropic = path45.join(nm, "@anthropic-ai");
18046
+ const atAnthropic = path46.join(nm, "@anthropic-ai");
17782
18047
  let entries;
17783
18048
  try {
17784
- entries = fs39.readdirSync(atAnthropic);
18049
+ entries = fs40.readdirSync(atAnthropic);
17785
18050
  } catch {
17786
18051
  continue;
17787
18052
  }
17788
18053
  for (const entry of entries) {
17789
18054
  if (!entry.startsWith("claude-agent-sdk-")) continue;
17790
- const bin = path45.join(atAnthropic, entry, "claude");
17791
- if (fs39.existsSync(bin)) return path45.dirname(bin);
18055
+ const bin = path46.join(atAnthropic, entry, "claude");
18056
+ if (fs40.existsSync(bin)) return path46.dirname(bin);
17792
18057
  }
17793
18058
  }
17794
18059
  return null;
17795
18060
  }
17796
18061
  async function getFreeDiskBytes(dir) {
17797
18062
  try {
17798
- const s = await fs39.promises.statfs(dir);
18063
+ const s = await fs40.promises.statfs(dir);
17799
18064
  return s.bsize * s.bavail;
17800
18065
  } catch {
17801
18066
  return null;
@@ -17845,14 +18110,14 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
17845
18110
  if (initKind === "claude") {
17846
18111
  const claudeDir = bundledClaudeBinDir();
17847
18112
  if (claudeDir) {
17848
- initEnv.PATH = `${claudeDir}${path45.delimiter}${process.env["PATH"] ?? ""}`;
18113
+ initEnv.PATH = `${claudeDir}${path46.delimiter}${process.env["PATH"] ?? ""}`;
17849
18114
  log.info("host-agent", `headroom init: bundled claude on PATH (${claudeDir})`);
17850
18115
  } else {
17851
18116
  log.warn("host-agent", "headroom init: bundled claude binary not found \u2014 init may fail");
17852
18117
  }
17853
18118
  }
17854
18119
  const initOk = await new Promise((resolve7) => {
17855
- (0, import_node_child_process13.execFile)(
18120
+ (0, import_node_child_process14.execFile)(
17856
18121
  "headroom",
17857
18122
  ["init", "--global", initKind],
17858
18123
  { env: initEnv },
@@ -17873,7 +18138,7 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
17873
18138
  return false;
17874
18139
  }
17875
18140
  try {
17876
- const proxy = (0, import_node_child_process13.spawn)("headroom", ["proxy", "--port", "8787"], {
18141
+ const proxy = (0, import_node_child_process14.spawn)("headroom", ["proxy", "--port", "8787"], {
17877
18142
  stdio: "ignore",
17878
18143
  detached: true,
17879
18144
  env: { ...process.env, HEADROOM_KOMPRESS_BACKEND: "onnx_cpu" }
@@ -17887,18 +18152,18 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
17887
18152
  }
17888
18153
  return true;
17889
18154
  }
17890
- var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process13.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
18155
+ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process14.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
17891
18156
  cwd,
17892
18157
  env: { ...process.env, ...env },
17893
18158
  stdio: ["ignore", "pipe", "pipe"],
17894
18159
  detached: false
17895
18160
  });
17896
18161
  function currentCliVersion() {
17897
- return true ? "2.39.82" : null;
18162
+ return true ? "2.39.84" : null;
17898
18163
  }
17899
18164
  function runCmd(cmd, args2, timeoutMs) {
17900
18165
  return new Promise((resolve7) => {
17901
- (0, import_node_child_process13.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
18166
+ (0, import_node_child_process14.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
17902
18167
  const code = err && typeof err.code === "number" ? err.code : err ? null : 0;
17903
18168
  resolve7({ code, stdout: stdout ?? "", stderr: stderr ?? "" });
17904
18169
  });
@@ -17969,20 +18234,20 @@ var defaultOnUpdated = (version3) => {
17969
18234
  };
17970
18235
  var defaultDisableService = () => {
17971
18236
  try {
17972
- (0, import_node_child_process13.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
18237
+ (0, import_node_child_process14.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
17973
18238
  } catch {
17974
18239
  }
17975
18240
  };
17976
18241
  var defaultTeardownHeadroom = () => {
17977
18242
  try {
17978
- const kind = JSON.parse(fs39.readFileSync(headroomConfigPath(), "utf8")).agent;
18243
+ const kind = JSON.parse(fs40.readFileSync(headroomConfigPath(), "utf8")).agent;
17979
18244
  if (kind) {
17980
- (0, import_node_child_process13.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
18245
+ (0, import_node_child_process14.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
17981
18246
  }
17982
18247
  } catch {
17983
18248
  }
17984
18249
  try {
17985
- (0, import_node_child_process13.execFileSync)("pkill", ["-TERM", "-f", "headroom.*proxy"], { stdio: "ignore" });
18250
+ (0, import_node_child_process14.execFileSync)("pkill", ["-TERM", "-f", "headroom.*proxy"], { stdio: "ignore" });
17986
18251
  } catch {
17987
18252
  }
17988
18253
  persistHeadroomConfig({ enabled: false });
@@ -18303,15 +18568,30 @@ var HostAgentSupervisor = class {
18303
18568
  report("installing", "installing agent CLI");
18304
18569
  await this.runAgentInstall(payload.agentInstallScript);
18305
18570
  }
18306
- const home = process.env.HOME || os32.homedir();
18571
+ const home = process.env.HOME || os33.homedir();
18307
18572
  childEnv.PATH = `${home}/.local/bin:${process.env.PATH ?? ""}`;
18573
+ if (payload.cloneToken) {
18574
+ try {
18575
+ report("preparing", "configuring git tooling");
18576
+ const ghCmd = await ensureGhCli(defaultGitToolingRunner, payload.cloneToken);
18577
+ if (ghCmd) {
18578
+ childEnv.PATH = `${codeamBinDir()}${path46.delimiter}${childEnv.PATH}`;
18579
+ await ensureGhAuth(defaultGitToolingRunner, ghCmd, payload.cloneToken);
18580
+ }
18581
+ } catch (e) {
18582
+ log.warn(
18583
+ "host-agent",
18584
+ `gh tooling setup skipped: ${e instanceof Error ? e.message : String(e)}`
18585
+ );
18586
+ }
18587
+ }
18308
18588
  if (payload.previewTunnelToken && payload.previewHostname) {
18309
18589
  childEnv.PREVIEW_TUNNEL_TOKEN = payload.previewTunnelToken;
18310
18590
  childEnv.PREVIEW_TUNNEL_HOSTNAME = payload.previewHostname;
18311
18591
  }
18312
18592
  if (payload.headroomEnabled && payload.headroomAgent && payload.headroomSavingsIngestUrl) {
18313
18593
  report("headroom", "setting up Headroom proxy");
18314
- const freeBytes = await this.getFreeDisk(os32.homedir());
18594
+ const freeBytes = await this.getFreeDisk(os33.homedir());
18315
18595
  const alreadyInstalled = this.isHeadroomInstalled();
18316
18596
  if (!alreadyInstalled && freeBytes !== null && freeBytes < HEADROOM_MIN_FREE_DISK_BYTES) {
18317
18597
  const freeGb = (freeBytes / 1e9).toFixed(1);
@@ -18427,8 +18707,8 @@ var HostAgentSupervisor = class {
18427
18707
  */
18428
18708
  runAgentInstall(script) {
18429
18709
  return new Promise((resolve7) => {
18430
- const home = process.env.HOME || os32.homedir();
18431
- const child = (0, import_node_child_process13.spawn)("sh", ["-c", script], {
18710
+ const home = process.env.HOME || os33.homedir();
18711
+ const child = (0, import_node_child_process14.spawn)("sh", ["-c", script], {
18432
18712
  env: { ...process.env, HOME: home },
18433
18713
  stdio: ["ignore", "pipe", "pipe"]
18434
18714
  });
@@ -18582,12 +18862,12 @@ function readTokenFromArgs(args2) {
18582
18862
  }
18583
18863
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
18584
18864
  if (fileFlag) {
18585
- const path59 = fileFlag.slice("--token-file=".length);
18865
+ const path60 = fileFlag.slice("--token-file=".length);
18586
18866
  try {
18587
- const content = fs40.readFileSync(path59, "utf8").trim();
18588
- if (content.length === 0) fail(`--token-file ${path59} is empty`);
18867
+ const content = fs41.readFileSync(path60, "utf8").trim();
18868
+ if (content.length === 0) fail(`--token-file ${path60} is empty`);
18589
18869
  try {
18590
- fs40.unlinkSync(path59);
18870
+ fs41.unlinkSync(path60);
18591
18871
  } catch {
18592
18872
  }
18593
18873
  return content;
@@ -18613,7 +18893,7 @@ async function claimOnce(token, pluginId, pluginSecretHash) {
18613
18893
  pluginId,
18614
18894
  ideName: "codeam-cli (codespace)",
18615
18895
  ideVersion: process.env.npm_package_version ?? "unknown",
18616
- hostname: os33.hostname(),
18896
+ hostname: os34.hostname(),
18617
18897
  codespaceName: process.env.CODESPACE_NAME ?? "",
18618
18898
  // Current git branch of the codespace's working directory, so the
18619
18899
  // backend can populate `PairedSession.branch` for the codespace pair.
@@ -18674,7 +18954,7 @@ async function claim(token, pluginId, pluginSecretHash) {
18674
18954
  }
18675
18955
  }
18676
18956
  function pairAutoLockPath() {
18677
- return path46.join(os33.homedir(), ".codeam", "pair-auto.lock");
18957
+ return path47.join(os34.homedir(), ".codeam", "pair-auto.lock");
18678
18958
  }
18679
18959
  function isLivePairAuto(pid) {
18680
18960
  if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
@@ -18684,7 +18964,7 @@ function isLivePairAuto(pid) {
18684
18964
  if (e.code !== "EPERM") return false;
18685
18965
  }
18686
18966
  try {
18687
- return fs40.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
18967
+ return fs41.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
18688
18968
  } catch {
18689
18969
  return true;
18690
18970
  }
@@ -18694,24 +18974,24 @@ function isLiveCodeam(pid) {
18694
18974
  }
18695
18975
  function daemonLockPath(sessionId) {
18696
18976
  const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
18697
- return path46.join(os33.homedir(), ".codeam", `daemon-${safe}.lock`);
18977
+ return path47.join(os34.homedir(), ".codeam", `daemon-${safe}.lock`);
18698
18978
  }
18699
18979
  function acquireDaemonLock(sessionId) {
18700
18980
  const lockPath = daemonLockPath(sessionId);
18701
18981
  try {
18702
- fs40.mkdirSync(path46.dirname(lockPath), { recursive: true });
18982
+ fs41.mkdirSync(path47.dirname(lockPath), { recursive: true });
18703
18983
  try {
18704
- fs40.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
18984
+ fs41.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
18705
18985
  } catch (e) {
18706
18986
  if (e.code !== "EEXIST") throw e;
18707
- const holder = Number(fs40.readFileSync(lockPath, "utf8").trim());
18987
+ const holder = Number(fs41.readFileSync(lockPath, "utf8").trim());
18708
18988
  if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
18709
- fs40.writeFileSync(lockPath, String(process.pid));
18989
+ fs41.writeFileSync(lockPath, String(process.pid));
18710
18990
  }
18711
18991
  const release3 = () => {
18712
18992
  try {
18713
- if (fs40.existsSync(lockPath) && Number(fs40.readFileSync(lockPath, "utf8").trim()) === process.pid) {
18714
- fs40.unlinkSync(lockPath);
18993
+ if (fs41.existsSync(lockPath) && Number(fs41.readFileSync(lockPath, "utf8").trim()) === process.pid) {
18994
+ fs41.unlinkSync(lockPath);
18715
18995
  }
18716
18996
  } catch {
18717
18997
  }
@@ -18733,19 +19013,19 @@ function acquireDaemonLock(sessionId) {
18733
19013
  function acquireSingletonLock() {
18734
19014
  const lockPath = pairAutoLockPath();
18735
19015
  try {
18736
- fs40.mkdirSync(path46.dirname(lockPath), { recursive: true });
19016
+ fs41.mkdirSync(path47.dirname(lockPath), { recursive: true });
18737
19017
  try {
18738
- fs40.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
19018
+ fs41.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
18739
19019
  } catch (e) {
18740
19020
  if (e.code !== "EEXIST") throw e;
18741
- const holder = Number(fs40.readFileSync(lockPath, "utf8").trim());
19021
+ const holder = Number(fs41.readFileSync(lockPath, "utf8").trim());
18742
19022
  if (isLivePairAuto(holder)) return false;
18743
- fs40.writeFileSync(lockPath, String(process.pid));
19023
+ fs41.writeFileSync(lockPath, String(process.pid));
18744
19024
  }
18745
19025
  process.once("exit", () => {
18746
19026
  try {
18747
- if (fs40.existsSync(lockPath) && Number(fs40.readFileSync(lockPath, "utf8").trim()) === process.pid) {
18748
- fs40.unlinkSync(lockPath);
19027
+ if (fs41.existsSync(lockPath) && Number(fs41.readFileSync(lockPath, "utf8").trim()) === process.pid) {
19028
+ fs41.unlinkSync(lockPath);
18749
19029
  }
18750
19030
  } catch {
18751
19031
  }
@@ -18827,7 +19107,7 @@ async function pairAuto(args2) {
18827
19107
  }
18828
19108
 
18829
19109
  // src/services/headroom/wrap-launch.ts
18830
- var import_node_child_process14 = require("child_process");
19110
+ var import_node_child_process15 = require("child_process");
18831
19111
  function wrapWithHeadroom(launch, opts) {
18832
19112
  if (!opts.enabled || !opts.headroomPresent) return launch;
18833
19113
  return {
@@ -18840,7 +19120,7 @@ var _present;
18840
19120
  function headroomPresent() {
18841
19121
  if (_present !== void 0) return Promise.resolve(_present);
18842
19122
  return new Promise((resolve7) => {
18843
- (0, import_node_child_process14.execFile)("headroom", ["--version"], (err) => {
19123
+ (0, import_node_child_process15.execFile)("headroom", ["--version"], (err) => {
18844
19124
  _present = !err;
18845
19125
  resolve7(_present);
18846
19126
  });
@@ -19190,19 +19470,19 @@ var AgentService = class _AgentService {
19190
19470
  };
19191
19471
 
19192
19472
  // src/agents/acp/adapters.ts
19193
- var path47 = __toESM(require("path"));
19473
+ var path48 = __toESM(require("path"));
19194
19474
  var require_ = require;
19195
19475
  function resolveBin(pkgName, binName) {
19196
19476
  try {
19197
19477
  const manifestPath = require_.resolve(`${pkgName}/package.json`);
19198
19478
  const manifest = require_(`${pkgName}/package.json`);
19199
- const pkgDir = path47.dirname(manifestPath);
19479
+ const pkgDir = path48.dirname(manifestPath);
19200
19480
  const bin = manifest.bin;
19201
19481
  if (!bin) return null;
19202
- if (typeof bin === "string") return path47.resolve(pkgDir, bin);
19482
+ if (typeof bin === "string") return path48.resolve(pkgDir, bin);
19203
19483
  const target = binName ?? Object.keys(bin)[0];
19204
19484
  if (!target || !bin[target]) return null;
19205
- return path47.resolve(pkgDir, bin[target]);
19485
+ return path48.resolve(pkgDir, bin[target]);
19206
19486
  } catch {
19207
19487
  return null;
19208
19488
  }
@@ -19278,9 +19558,9 @@ function requiresAcp(agent) {
19278
19558
  var import_node_crypto7 = require("crypto");
19279
19559
 
19280
19560
  // src/services/history.service.ts
19281
- var fs41 = __toESM(require("fs"));
19282
- var path48 = __toESM(require("path"));
19283
- var os34 = __toESM(require("os"));
19561
+ var fs42 = __toESM(require("fs"));
19562
+ var path49 = __toESM(require("path"));
19563
+ var os35 = __toESM(require("os"));
19284
19564
  var https7 = __toESM(require("https"));
19285
19565
  var http6 = __toESM(require("http"));
19286
19566
  var import_zod2 = require("zod");
@@ -19307,7 +19587,7 @@ function parseJsonl(filePath) {
19307
19587
  const messages = [];
19308
19588
  let raw;
19309
19589
  try {
19310
- raw = fs41.readFileSync(filePath, "utf8");
19590
+ raw = fs42.readFileSync(filePath, "utf8");
19311
19591
  } catch (err) {
19312
19592
  if (err.code !== "ENOENT") {
19313
19593
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -19448,7 +19728,7 @@ var HistoryService = class _HistoryService {
19448
19728
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
19449
19729
  }
19450
19730
  get projectDir() {
19451
- return this.runtime.resolveHistoryDir(this.cwd) ?? path48.join(os34.homedir(), ".claude", "projects", encodeCwd(this.cwd));
19731
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path49.join(os35.homedir(), ".claude", "projects", encodeCwd(this.cwd));
19452
19732
  }
19453
19733
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
19454
19734
  setCurrentConversationId(id) {
@@ -19460,7 +19740,7 @@ var HistoryService = class _HistoryService {
19460
19740
  /** Return the current message count in the active conversation. */
19461
19741
  getCurrentMessageCount() {
19462
19742
  if (!this.currentConversationId) return 0;
19463
- const filePath = path48.join(this.projectDir, `${this.currentConversationId}.jsonl`);
19743
+ const filePath = path49.join(this.projectDir, `${this.currentConversationId}.jsonl`);
19464
19744
  return parseJsonl(filePath).length;
19465
19745
  }
19466
19746
  /**
@@ -19471,7 +19751,7 @@ var HistoryService = class _HistoryService {
19471
19751
  const deadline = Date.now() + timeoutMs;
19472
19752
  while (Date.now() < deadline) {
19473
19753
  if (!this.currentConversationId) return null;
19474
- const filePath = path48.join(this.projectDir, `${this.currentConversationId}.jsonl`);
19754
+ const filePath = path49.join(this.projectDir, `${this.currentConversationId}.jsonl`);
19475
19755
  const messages = parseJsonl(filePath);
19476
19756
  if (messages.length > previousCount) {
19477
19757
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -19497,16 +19777,16 @@ var HistoryService = class _HistoryService {
19497
19777
  const dir = this.projectDir;
19498
19778
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
19499
19779
  try {
19500
- const files = fs41.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
19780
+ const files = fs42.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
19501
19781
  try {
19502
- const stat3 = fs41.statSync(path48.join(dir, e.name));
19782
+ const stat3 = fs42.statSync(path49.join(dir, e.name));
19503
19783
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
19504
19784
  } catch {
19505
19785
  return { name: e.name, mtime: 0, birthtime: 0 };
19506
19786
  }
19507
19787
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
19508
19788
  if (files.length > 0) {
19509
- this.currentConversationId = path48.basename(files[0].name, ".jsonl");
19789
+ this.currentConversationId = path49.basename(files[0].name, ".jsonl");
19510
19790
  }
19511
19791
  } catch {
19512
19792
  }
@@ -19540,13 +19820,13 @@ var HistoryService = class _HistoryService {
19540
19820
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
19541
19821
  let entries;
19542
19822
  try {
19543
- entries = fs41.readdirSync(dir, { withFileTypes: true });
19823
+ entries = fs42.readdirSync(dir, { withFileTypes: true });
19544
19824
  } catch {
19545
19825
  return null;
19546
19826
  }
19547
19827
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
19548
19828
  try {
19549
- const stat3 = fs41.statSync(path48.join(dir, e.name));
19829
+ const stat3 = fs42.statSync(path49.join(dir, e.name));
19550
19830
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
19551
19831
  } catch {
19552
19832
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -19555,12 +19835,12 @@ var HistoryService = class _HistoryService {
19555
19835
  if (files.length === 0) return null;
19556
19836
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
19557
19837
  if (!files.some((f) => f.name === targetFile)) return null;
19558
- return this.extractUsageFromFile(path48.join(dir, targetFile));
19838
+ return this.extractUsageFromFile(path49.join(dir, targetFile));
19559
19839
  }
19560
19840
  extractUsageFromFile(filePath) {
19561
19841
  let raw;
19562
19842
  try {
19563
- raw = fs41.readFileSync(filePath, "utf8");
19843
+ raw = fs42.readFileSync(filePath, "utf8");
19564
19844
  } catch {
19565
19845
  return null;
19566
19846
  }
@@ -19605,9 +19885,9 @@ var HistoryService = class _HistoryService {
19605
19885
  let totalCost = 0;
19606
19886
  let files;
19607
19887
  try {
19608
- files = fs41.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
19888
+ files = fs42.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
19609
19889
  try {
19610
- return fs41.statSync(path48.join(projectDir, f)).mtimeMs >= monthStartMs;
19890
+ return fs42.statSync(path49.join(projectDir, f)).mtimeMs >= monthStartMs;
19611
19891
  } catch {
19612
19892
  return false;
19613
19893
  }
@@ -19618,7 +19898,7 @@ var HistoryService = class _HistoryService {
19618
19898
  for (const file of files) {
19619
19899
  let raw;
19620
19900
  try {
19621
- raw = fs41.readFileSync(path48.join(projectDir, file), "utf8");
19901
+ raw = fs42.readFileSync(path49.join(projectDir, file), "utf8");
19622
19902
  } catch {
19623
19903
  continue;
19624
19904
  }
@@ -19686,7 +19966,7 @@ var HistoryService = class _HistoryService {
19686
19966
  * showing an empty conversation.
19687
19967
  */
19688
19968
  async loadConversation(sessionId) {
19689
- const filePath = path48.join(this.projectDir, `${sessionId}.jsonl`);
19969
+ const filePath = path49.join(this.projectDir, `${sessionId}.jsonl`);
19690
19970
  const messages = parseJsonl(filePath);
19691
19971
  if (messages.length === 0) return;
19692
19972
  const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
@@ -19736,10 +20016,10 @@ var HistoryService = class _HistoryService {
19736
20016
  * or no transcript exists yet (not an error).
19737
20017
  */
19738
20018
  async uploadConversationIfChanged(sessionId) {
19739
- const filePath = path48.join(this.projectDir, `${sessionId}.jsonl`);
20019
+ const filePath = path49.join(this.projectDir, `${sessionId}.jsonl`);
19740
20020
  let mtimeMs;
19741
20021
  try {
19742
- mtimeMs = fs41.statSync(filePath).mtimeMs;
20022
+ mtimeMs = fs42.statSync(filePath).mtimeMs;
19743
20023
  } catch {
19744
20024
  return false;
19745
20025
  }
@@ -19778,7 +20058,7 @@ var HistoryService = class _HistoryService {
19778
20058
  sessionId = this.currentConversationId;
19779
20059
  if (!sessionId) return 0;
19780
20060
  }
19781
- const filePath = path48.join(this.projectDir, `${sessionId}.jsonl`);
20061
+ const filePath = path49.join(this.projectDir, `${sessionId}.jsonl`);
19782
20062
  const messages = parseJsonl(filePath);
19783
20063
  if (messages.length === 0) return 0;
19784
20064
  const marker = this.lastUploadedUuid.get(sessionId);
@@ -19808,11 +20088,11 @@ var HistoryService = class _HistoryService {
19808
20088
  };
19809
20089
 
19810
20090
  // src/agents/acp/client.ts
19811
- var import_node_child_process15 = require("child_process");
19812
- var fs42 = __toESM(require("fs/promises"));
20091
+ var import_node_child_process16 = require("child_process");
20092
+ var fs43 = __toESM(require("fs/promises"));
19813
20093
  var fsSync = __toESM(require("fs"));
19814
- var os35 = __toESM(require("os"));
19815
- var path49 = __toESM(require("path"));
20094
+ var os36 = __toESM(require("os"));
20095
+ var path50 = __toESM(require("path"));
19816
20096
  var import_node_stream = require("stream");
19817
20097
 
19818
20098
  // ../../node_modules/@agentclientprotocol/sdk/dist/acp.js
@@ -22349,7 +22629,7 @@ var AcpClient = class {
22349
22629
  "acpClient",
22350
22630
  `spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
22351
22631
  );
22352
- const child = (0, import_node_child_process15.spawn)(adapter.command, adapter.args, {
22632
+ const child = (0, import_node_child_process16.spawn)(adapter.command, adapter.args, {
22353
22633
  cwd,
22354
22634
  env: { ...process.env, PATH: augmentedPath },
22355
22635
  stdio: ["pipe", "pipe", "pipe"]
@@ -22606,7 +22886,7 @@ var AcpClient = class {
22606
22886
  },
22607
22887
  readTextFile: async (params) => {
22608
22888
  try {
22609
- const content = await fs42.readFile(params.path, "utf8");
22889
+ const content = await fs43.readFile(params.path, "utf8");
22610
22890
  return applyLineRange(content, params.line ?? null, params.limit ?? null);
22611
22891
  } catch (err) {
22612
22892
  const code = err.code;
@@ -22626,7 +22906,7 @@ var AcpClient = class {
22626
22906
  },
22627
22907
  writeTextFile: async (params) => {
22628
22908
  try {
22629
- await fs42.writeFile(params.path, params.content, "utf8");
22909
+ await fs43.writeFile(params.path, params.content, "utf8");
22630
22910
  return {};
22631
22911
  } catch (err) {
22632
22912
  const code = err.code;
@@ -22675,25 +22955,25 @@ function applyLineRange(content, line, limit) {
22675
22955
  return { content: lines.slice(start2, end).join("\n") };
22676
22956
  }
22677
22957
  function knownAgentBinaryDirs() {
22678
- const home = os35.homedir();
22958
+ const home = os36.homedir();
22679
22959
  const out2 = [];
22680
22960
  out2.push("/tmp/codeam-node20/bin");
22681
22961
  for (const root of [
22682
22962
  "/usr/local/share/nvm/versions/node",
22683
- path49.join(home, ".nvm/versions/node")
22963
+ path50.join(home, ".nvm/versions/node")
22684
22964
  ]) {
22685
22965
  try {
22686
22966
  for (const child of fsSync.readdirSync(root)) {
22687
- out2.push(path49.join(root, child, "bin"));
22967
+ out2.push(path50.join(root, child, "bin"));
22688
22968
  }
22689
22969
  } catch {
22690
22970
  }
22691
22971
  }
22692
- out2.push(path49.join(home, ".volta/bin"));
22972
+ out2.push(path50.join(home, ".volta/bin"));
22693
22973
  out2.push("/usr/local/bin");
22694
22974
  out2.push("/usr/bin");
22695
- out2.push(path49.join(home, ".local/bin"));
22696
- out2.push(path49.join(home, "bin"));
22975
+ out2.push(path50.join(home, ".local/bin"));
22976
+ out2.push(path50.join(home, "bin"));
22697
22977
  return out2.filter((p2) => {
22698
22978
  try {
22699
22979
  return fsSync.statSync(p2).isDirectory();
@@ -22704,7 +22984,7 @@ function knownAgentBinaryDirs() {
22704
22984
  }
22705
22985
  function expandPathForAgentBinaries(existingPath) {
22706
22986
  const existing = new Set(
22707
- existingPath.split(path49.delimiter).filter((p2) => p2.length > 0)
22987
+ existingPath.split(path50.delimiter).filter((p2) => p2.length > 0)
22708
22988
  );
22709
22989
  const additions = [];
22710
22990
  for (const dir of knownAgentBinaryDirs()) {
@@ -22714,7 +22994,7 @@ function expandPathForAgentBinaries(existingPath) {
22714
22994
  }
22715
22995
  }
22716
22996
  if (additions.length === 0) return existingPath;
22717
- return [...additions, existingPath].filter((p2) => p2.length > 0).join(path49.delimiter);
22997
+ return [...additions, existingPath].filter((p2) => p2.length > 0).join(path50.delimiter);
22718
22998
  }
22719
22999
 
22720
23000
  // src/services/streaming/transport.ts
@@ -23041,15 +23321,15 @@ function reconcileCumulative(existing, incoming) {
23041
23321
  }
23042
23322
 
23043
23323
  // src/agents/acp/onboarding.ts
23044
- var fs43 = __toESM(require("fs"));
23045
- var os36 = __toESM(require("os"));
23046
- var path50 = __toESM(require("path"));
23324
+ var fs44 = __toESM(require("fs"));
23325
+ var os37 = __toESM(require("os"));
23326
+ var path51 = __toESM(require("path"));
23047
23327
  var _onboardingSeam = {
23048
- markerPath: (sessionId) => path50.join(os36.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
23049
- exists: (p2) => fs43.existsSync(p2),
23328
+ markerPath: (sessionId) => path51.join(os37.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
23329
+ exists: (p2) => fs44.existsSync(p2),
23050
23330
  write: (p2) => {
23051
- fs43.mkdirSync(path50.dirname(p2), { recursive: true });
23052
- fs43.writeFileSync(p2, "");
23331
+ fs44.mkdirSync(path51.dirname(p2), { recursive: true });
23332
+ fs44.writeFileSync(p2, "");
23053
23333
  },
23054
23334
  disabled: () => {
23055
23335
  const v = process.env.CODEAM_ONBOARDING_DISABLED;
@@ -23057,7 +23337,7 @@ var _onboardingSeam = {
23057
23337
  }
23058
23338
  };
23059
23339
  function buildOnboardingWelcome(cwd) {
23060
- const repo = path50.basename(cwd || "") || "this project";
23340
+ const repo = path51.basename(cwd || "") || "this project";
23061
23341
  return [
23062
23342
  `Welcome to CodeAgent Mobile! \u{1F44B} You're now driving this agent from your phone \u2014 and it comes fully wired, zero setup:`,
23063
23343
  "",
@@ -23323,8 +23603,8 @@ var import_crypto5 = require("crypto");
23323
23603
 
23324
23604
  // src/services/turn-files/git-changeset.ts
23325
23605
  var import_child_process22 = require("child_process");
23326
- var fs44 = __toESM(require("fs/promises"));
23327
- var path51 = __toESM(require("path"));
23606
+ var fs45 = __toESM(require("fs/promises"));
23607
+ var path52 = __toESM(require("path"));
23328
23608
  async function collectRepoChangeset(opts) {
23329
23609
  const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
23330
23610
  if (status2 === null) return null;
@@ -23342,7 +23622,7 @@ async function collectRepoChangeset(opts) {
23342
23622
  let stats;
23343
23623
  if (row.fileStatus === "added" && numstatEntry === void 0) {
23344
23624
  const lineCount = await readUntrackedLineCount(
23345
- path51.join(opts.repoRoot, row.filePath)
23625
+ path52.join(opts.repoRoot, row.filePath)
23346
23626
  );
23347
23627
  stats = { added: lineCount, removed: 0 };
23348
23628
  } else {
@@ -23373,7 +23653,7 @@ function readUntrackedLineCount(absPath) {
23373
23653
  }
23374
23654
  async function defaultReadUntrackedLineCount(absPath) {
23375
23655
  try {
23376
- const content = await fs44.readFile(absPath, "utf8");
23656
+ const content = await fs45.readFile(absPath, "utf8");
23377
23657
  let count = 0;
23378
23658
  let pos = -1;
23379
23659
  while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
@@ -23465,7 +23745,7 @@ function defaultRunGit(cwd, args2) {
23465
23745
  });
23466
23746
  }
23467
23747
  async function discoverRepos(workingDir, maxDepth = 4) {
23468
- const fs48 = await import("fs/promises");
23748
+ const fs49 = await import("fs/promises");
23469
23749
  const out2 = [];
23470
23750
  await walk(workingDir, 0);
23471
23751
  return out2;
@@ -23473,7 +23753,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
23473
23753
  if (depth > maxDepth) return;
23474
23754
  let entries = [];
23475
23755
  try {
23476
- const dirents = await fs48.readdir(dir, { withFileTypes: true });
23756
+ const dirents = await fs49.readdir(dir, { withFileTypes: true });
23477
23757
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
23478
23758
  } catch {
23479
23759
  return;
@@ -23484,8 +23764,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
23484
23764
  if (hasGit) {
23485
23765
  out2.push({
23486
23766
  repoRoot: dir,
23487
- repoPath: path51.relative(workingDir, dir),
23488
- repoName: path51.basename(dir)
23767
+ repoPath: path52.relative(workingDir, dir),
23768
+ repoName: path52.basename(dir)
23489
23769
  });
23490
23770
  return;
23491
23771
  }
@@ -23493,14 +23773,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
23493
23773
  if (!entry.isDirectory) continue;
23494
23774
  if (entry.name === "node_modules") continue;
23495
23775
  if (entry.name === "dist" || entry.name === "build") continue;
23496
- await walk(path51.join(dir, entry.name), depth + 1);
23776
+ await walk(path52.join(dir, entry.name), depth + 1);
23497
23777
  }
23498
23778
  }
23499
23779
  }
23500
23780
 
23501
23781
  // src/services/turn-files/files-outbox.ts
23502
- var fs45 = __toESM(require("fs/promises"));
23503
- var path52 = __toESM(require("path"));
23782
+ var fs46 = __toESM(require("fs/promises"));
23783
+ var path53 = __toESM(require("path"));
23504
23784
  var import_os7 = require("os");
23505
23785
  var HOME_OUTBOX_DIR = ".codeam/outbox";
23506
23786
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -23533,16 +23813,16 @@ var FilesOutbox = class {
23533
23813
  backoffIndex = 0;
23534
23814
  stopped = false;
23535
23815
  constructor(opts) {
23536
- const base = opts.baseDir ?? path52.join(homeDir(), HOME_OUTBOX_DIR);
23537
- this.filePath = path52.join(base, `${opts.sessionId}.jsonl`);
23816
+ const base = opts.baseDir ?? path53.join(homeDir(), HOME_OUTBOX_DIR);
23817
+ this.filePath = path53.join(base, `${opts.sessionId}.jsonl`);
23538
23818
  this.post = opts.post;
23539
23819
  this.autoSchedule = opts.autoSchedule !== false;
23540
23820
  }
23541
23821
  /** Persist the entry to disk and trigger a flush. Returns once the
23542
23822
  * line is durable on disk (not once the POST succeeds). */
23543
23823
  async enqueue(entry) {
23544
- await fs45.mkdir(path52.dirname(this.filePath), { recursive: true });
23545
- await fs45.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
23824
+ await fs46.mkdir(path53.dirname(this.filePath), { recursive: true });
23825
+ await fs46.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
23546
23826
  this.backoffIndex = 0;
23547
23827
  if (this.autoSchedule) this.scheduleFlush(0);
23548
23828
  }
@@ -23631,7 +23911,7 @@ var FilesOutbox = class {
23631
23911
  async readAll() {
23632
23912
  let raw = "";
23633
23913
  try {
23634
- raw = await fs45.readFile(this.filePath, "utf8");
23914
+ raw = await fs46.readFile(this.filePath, "utf8");
23635
23915
  } catch {
23636
23916
  return [];
23637
23917
  }
@@ -23655,12 +23935,12 @@ var FilesOutbox = class {
23655
23935
  async rewrite(entries) {
23656
23936
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
23657
23937
  if (entries.length === 0) {
23658
- await fs45.unlink(this.filePath).catch(() => void 0);
23938
+ await fs46.unlink(this.filePath).catch(() => void 0);
23659
23939
  return;
23660
23940
  }
23661
23941
  const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
23662
- await fs45.writeFile(tmpPath, payload, "utf8");
23663
- await fs45.rename(tmpPath, this.filePath);
23942
+ await fs46.writeFile(tmpPath, payload, "utf8");
23943
+ await fs46.rename(tmpPath, this.filePath);
23664
23944
  }
23665
23945
  };
23666
23946
  function applyJitter(ms) {
@@ -25868,15 +26148,15 @@ function fetchQuotaUsage(runtime, historySvc) {
25868
26148
  }
25869
26149
 
25870
26150
  // src/agents/claude/onboarding.ts
25871
- var fs46 = __toESM(require("fs"));
25872
- var os37 = __toESM(require("os"));
25873
- var path53 = __toESM(require("path"));
26151
+ var fs47 = __toESM(require("fs"));
26152
+ var os38 = __toESM(require("os"));
26153
+ var path54 = __toESM(require("path"));
25874
26154
  function ensureClaudeOnboarded() {
25875
26155
  try {
25876
- const file = path53.join(os37.homedir(), ".claude.json");
26156
+ const file = path54.join(os38.homedir(), ".claude.json");
25877
26157
  let config = {};
25878
26158
  try {
25879
- config = JSON.parse(fs46.readFileSync(file, "utf8"));
26159
+ config = JSON.parse(fs47.readFileSync(file, "utf8"));
25880
26160
  } catch {
25881
26161
  }
25882
26162
  if (config.hasCompletedOnboarding === true && typeof config.theme === "string") {
@@ -25887,8 +26167,8 @@ function ensureClaudeOnboarded() {
25887
26167
  if (typeof config.lastOnboardingVersion !== "string") {
25888
26168
  config.lastOnboardingVersion = "2.1.177";
25889
26169
  }
25890
- fs46.mkdirSync(path53.dirname(file), { recursive: true });
25891
- fs46.writeFileSync(file, JSON.stringify(config, null, 2));
26170
+ fs47.mkdirSync(path54.dirname(file), { recursive: true });
26171
+ fs47.writeFileSync(file, JSON.stringify(config, null, 2));
25892
26172
  log.info("claude", "pre-completed Claude onboarding (skip first-run theme picker)");
25893
26173
  } catch (err) {
25894
26174
  log.warn("claude", `ensureClaudeOnboarded failed (non-fatal): ${err.message}`);
@@ -26528,7 +26808,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
26528
26808
  var import_child_process23 = require("child_process");
26529
26809
  var import_util4 = require("util");
26530
26810
  var import_picocolors9 = __toESM(require("picocolors"));
26531
- var path54 = __toESM(require("path"));
26811
+ var path55 = __toESM(require("path"));
26532
26812
  var execFileP6 = (0, import_util4.promisify)(import_child_process23.execFile);
26533
26813
  var MAX_BUFFER = 8 * 1024 * 1024;
26534
26814
  function resetStdinForChild() {
@@ -27017,7 +27297,7 @@ var GitHubCodespacesProvider = class {
27017
27297
  });
27018
27298
  }
27019
27299
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
27020
- const remoteDir = path54.posix.dirname(remotePath);
27300
+ const remoteDir = path55.posix.dirname(remotePath);
27021
27301
  const parts = [
27022
27302
  `mkdir -p ${shellQuote(remoteDir)}`,
27023
27303
  `cat > ${shellQuote(remotePath)}`
@@ -27087,7 +27367,7 @@ function shellQuote(s) {
27087
27367
  // src/services/providers/gitpod.ts
27088
27368
  var import_child_process24 = require("child_process");
27089
27369
  var import_util5 = require("util");
27090
- var path55 = __toESM(require("path"));
27370
+ var path56 = __toESM(require("path"));
27091
27371
  var import_picocolors10 = __toESM(require("picocolors"));
27092
27372
  var execFileP7 = (0, import_util5.promisify)(import_child_process24.execFile);
27093
27373
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -27327,7 +27607,7 @@ var GitpodProvider = class {
27327
27607
  });
27328
27608
  }
27329
27609
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
27330
- const remoteDir = path55.posix.dirname(remotePath);
27610
+ const remoteDir = path56.posix.dirname(remotePath);
27331
27611
  const parts = [
27332
27612
  `mkdir -p ${shellQuote2(remoteDir)}`,
27333
27613
  `cat > ${shellQuote2(remotePath)}`
@@ -27363,7 +27643,7 @@ function shellQuote2(s) {
27363
27643
  // src/services/providers/gitlab-workspaces.ts
27364
27644
  var import_child_process25 = require("child_process");
27365
27645
  var import_util6 = require("util");
27366
- var path56 = __toESM(require("path"));
27646
+ var path57 = __toESM(require("path"));
27367
27647
  var execFileP8 = (0, import_util6.promisify)(import_child_process25.execFile);
27368
27648
  var MAX_BUFFER3 = 8 * 1024 * 1024;
27369
27649
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -27623,7 +27903,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
27623
27903
  }
27624
27904
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
27625
27905
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
27626
- const remoteDir = path56.posix.dirname(remotePath);
27906
+ const remoteDir = path57.posix.dirname(remotePath);
27627
27907
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
27628
27908
  if (options.mode != null) {
27629
27909
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -27691,7 +27971,7 @@ function shellQuote3(s) {
27691
27971
  // src/services/providers/railway.ts
27692
27972
  var import_child_process26 = require("child_process");
27693
27973
  var import_util7 = require("util");
27694
- var path57 = __toESM(require("path"));
27974
+ var path58 = __toESM(require("path"));
27695
27975
  var execFileP9 = (0, import_util7.promisify)(import_child_process26.execFile);
27696
27976
  var MAX_BUFFER4 = 8 * 1024 * 1024;
27697
27977
  function resetStdinForChild4() {
@@ -27927,7 +28207,7 @@ var RailwayProvider = class {
27927
28207
  if (!projectId || !serviceId) {
27928
28208
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
27929
28209
  }
27930
- const remoteDir = path57.posix.dirname(remotePath);
28210
+ const remoteDir = path58.posix.dirname(remotePath);
27931
28211
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
27932
28212
  if (options.mode != null) {
27933
28213
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -28515,8 +28795,8 @@ async function host(args2) {
28515
28795
  var import_node_dns = require("dns");
28516
28796
  var import_node_util5 = require("util");
28517
28797
  var import_node_crypto8 = require("crypto");
28518
- var fs47 = __toESM(require("fs"));
28519
- var path58 = __toESM(require("path"));
28798
+ var fs48 = __toESM(require("fs"));
28799
+ var path59 = __toESM(require("path"));
28520
28800
  var import_picocolors13 = __toESM(require("picocolors"));
28521
28801
  var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
28522
28802
  async function checkDns(apiBase2) {
@@ -28572,13 +28852,13 @@ async function checkHealth(apiBase2) {
28572
28852
  }
28573
28853
  }
28574
28854
  function checkConfigDir() {
28575
- const dir = path58.join(require("os").homedir(), ".codeam");
28855
+ const dir = path59.join(require("os").homedir(), ".codeam");
28576
28856
  try {
28577
- fs47.mkdirSync(dir, { recursive: true, mode: 448 });
28578
- const probe = path58.join(dir, ".doctor-probe");
28579
- fs47.writeFileSync(probe, "ok", { mode: 384 });
28580
- const read2 = fs47.readFileSync(probe, "utf8");
28581
- fs47.unlinkSync(probe);
28857
+ fs48.mkdirSync(dir, { recursive: true, mode: 448 });
28858
+ const probe = path59.join(dir, ".doctor-probe");
28859
+ fs48.writeFileSync(probe, "ok", { mode: 384 });
28860
+ const read2 = fs48.readFileSync(probe, "utf8");
28861
+ fs48.unlinkSync(probe);
28582
28862
  if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
28583
28863
  return {
28584
28864
  id: "config-dir",
@@ -28618,9 +28898,9 @@ function checkSessions() {
28618
28898
  }
28619
28899
  }
28620
28900
  function checkAgentBinaries() {
28621
- const os39 = createOsStrategy();
28901
+ const os40 = createOsStrategy();
28622
28902
  return getEnabledAgents().map((meta) => {
28623
- const found = os39.findInPath(meta.binaryName);
28903
+ const found = os40.findInPath(meta.binaryName);
28624
28904
  return {
28625
28905
  id: `agent-${meta.id}`,
28626
28906
  label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
@@ -28642,7 +28922,7 @@ function checkNodePty() {
28642
28922
  detail: "not required on this platform"
28643
28923
  };
28644
28924
  }
28645
- const vendoredPath = path58.join(__dirname, "vendor", "node-pty");
28925
+ const vendoredPath = path59.join(__dirname, "vendor", "node-pty");
28646
28926
  for (const target of [vendoredPath, "node-pty"]) {
28647
28927
  try {
28648
28928
  require(target);
@@ -28684,7 +28964,7 @@ function checkChokidar() {
28684
28964
  }
28685
28965
  async function doctor(args2 = []) {
28686
28966
  const json = args2.includes("--json");
28687
- const cliVersion = true ? "2.39.82" : "0.0.0-dev";
28967
+ const cliVersion = true ? "2.39.84" : "0.0.0-dev";
28688
28968
  const apiBase2 = resolveApiBaseUrl();
28689
28969
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
28690
28970
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -28883,7 +29163,7 @@ async function completion(args2) {
28883
29163
  // src/commands/version.ts
28884
29164
  var import_picocolors14 = __toESM(require("picocolors"));
28885
29165
  function version2() {
28886
- const v = true ? "2.39.82" : "unknown";
29166
+ const v = true ? "2.39.84" : "unknown";
28887
29167
  console.log(`${import_picocolors14.default.bold("codeam-cli")} ${import_picocolors14.default.cyan(v)}`);
28888
29168
  }
28889
29169
 
@@ -29027,10 +29307,10 @@ var EXIT_CODE_NAMES = {
29027
29307
  };
29028
29308
 
29029
29309
  // src/index.ts
29030
- var os38 = __toESM(require("os"));
29310
+ var os39 = __toESM(require("os"));
29031
29311
  if (!process.env.HOME) {
29032
29312
  try {
29033
- const home = os38.homedir();
29313
+ const home = os39.homedir();
29034
29314
  if (home) process.env.HOME = home;
29035
29315
  } catch {
29036
29316
  }
@@ -29039,7 +29319,13 @@ loadCodespaceEnv();
29039
29319
  var [, , command, ...args] = process.argv;
29040
29320
  async function main() {
29041
29321
  const isMetaCommand = command === "--version" || command === "-v" || command === "version" || command === "--help" || command === "-h" || command === "help";
29042
- if (!isMetaCommand) checkForUpdates();
29322
+ if (!isMetaCommand) {
29323
+ if (command === "link" || command === "pair") {
29324
+ await autoUpgradeBeforeCriticalCommand();
29325
+ } else {
29326
+ checkForUpdates();
29327
+ }
29328
+ }
29043
29329
  if (initTelemetry()) {
29044
29330
  maybePrintFirstRunBanner();
29045
29331
  capture("cli_boot", { command: command ?? "(default)" });