codeam-cli 2.39.82 → 2.39.83

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 +498 -239
  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.83" : "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.83",
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
@@ -11588,8 +11588,8 @@ var ClaudeRuntimeStrategy = class {
11588
11588
  meta = getAgent("claude");
11589
11589
  mode = "interactive";
11590
11590
  os;
11591
- constructor(os39) {
11592
- this.os = os39;
11591
+ constructor(os40) {
11592
+ this.os = os40;
11593
11593
  }
11594
11594
  /**
11595
11595
  * Claude Code's react-ink TUI enables bracketed-paste mode at
@@ -12208,8 +12208,8 @@ function codexCredentialLocator() {
12208
12208
  function codexLoginLauncher() {
12209
12209
  return {
12210
12210
  async ensureInstalled() {
12211
- const os39 = createOsStrategy();
12212
- return os39.findInPath("codex") !== null;
12211
+ const os40 = createOsStrategy();
12212
+ return os40.findInPath("codex") !== null;
12213
12213
  },
12214
12214
  launch() {
12215
12215
  return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
@@ -12232,8 +12232,8 @@ var CodexRuntimeStrategy = class {
12232
12232
  meta = getAgent("codex");
12233
12233
  mode = "interactive";
12234
12234
  os;
12235
- constructor(os39) {
12236
- this.os = os39;
12235
+ constructor(os40) {
12236
+ this.os = os40;
12237
12237
  }
12238
12238
  async prepareLaunch() {
12239
12239
  let binary = this.os.findInPath("codex");
@@ -12329,12 +12329,12 @@ var CodexRuntimeStrategy = class {
12329
12329
  });
12330
12330
  }
12331
12331
  };
12332
- function resolveNpm(os39) {
12333
- return os39.id === "win32" ? "npm.cmd" : "npm";
12332
+ function resolveNpm(os40) {
12333
+ return os40.id === "win32" ? "npm.cmd" : "npm";
12334
12334
  }
12335
- async function installCodexViaNpm(os39) {
12335
+ async function installCodexViaNpm(os40) {
12336
12336
  return new Promise((resolve7, reject) => {
12337
- const proc = (0, import_node_child_process4.spawn)(resolveNpm(os39), ["install", "-g", "@openai/codex"], {
12337
+ const proc = (0, import_node_child_process4.spawn)(resolveNpm(os40), ["install", "-g", "@openai/codex"], {
12338
12338
  stdio: "inherit"
12339
12339
  });
12340
12340
  proc.on("close", (code) => {
@@ -12351,16 +12351,16 @@ async function installCodexViaNpm(os39) {
12351
12351
  });
12352
12352
  });
12353
12353
  }
12354
- function augmentNpmGlobalBin(os39) {
12354
+ function augmentNpmGlobalBin(os40) {
12355
12355
  try {
12356
- const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os39), ["prefix", "-g"], {
12356
+ const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os40), ["prefix", "-g"], {
12357
12357
  stdio: ["ignore", "pipe", "ignore"]
12358
12358
  });
12359
12359
  if (result.status !== 0) return;
12360
12360
  const prefix = result.stdout.toString().trim();
12361
12361
  if (!prefix) return;
12362
- const binDir = os39.id === "win32" ? prefix : path22.join(prefix, "bin");
12363
- os39.augmentPath([binDir]);
12362
+ const binDir = os40.id === "win32" ? prefix : path22.join(prefix, "bin");
12363
+ os40.augmentPath([binDir]);
12364
12364
  } catch {
12365
12365
  }
12366
12366
  }
@@ -12444,9 +12444,9 @@ var import_node_child_process7 = require("child_process");
12444
12444
  // src/agents/coderabbit/installer.ts
12445
12445
  var import_node_child_process5 = require("child_process");
12446
12446
  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") {
12447
+ async function ensureCoderabbitInstalled(os40) {
12448
+ if (os40.findInPath("coderabbit")) return true;
12449
+ if (os40.id === "win32") {
12450
12450
  console.error(
12451
12451
  "\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
12452
  );
@@ -12461,8 +12461,8 @@ async function ensureCoderabbitInstalled(os39) {
12461
12461
  proc.on("error", () => resolve7(false));
12462
12462
  });
12463
12463
  if (!ok) return false;
12464
- os39.augmentPath([`${os39.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
12465
- return os39.findInPath("coderabbit") !== null;
12464
+ os40.augmentPath([`${os40.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
12465
+ return os40.findInPath("coderabbit") !== null;
12466
12466
  }
12467
12467
 
12468
12468
  // src/agents/coderabbit/link.ts
@@ -12489,10 +12489,10 @@ function coderabbitCredentialLocator() {
12489
12489
  extract: extractLocalCoderabbitToken
12490
12490
  };
12491
12491
  }
12492
- function coderabbitLoginLauncher(os39) {
12492
+ function coderabbitLoginLauncher(os40) {
12493
12493
  return {
12494
12494
  async ensureInstalled() {
12495
- return ensureCoderabbitInstalled(os39);
12495
+ return ensureCoderabbitInstalled(os40);
12496
12496
  },
12497
12497
  launch() {
12498
12498
  return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
@@ -12515,11 +12515,11 @@ function parseReview(stdout) {
12515
12515
  for (const line of lines) {
12516
12516
  const m = line.match(HUNK_LINE_RE);
12517
12517
  if (!m) continue;
12518
- const [, path59, lineNo, sevToken, message] = m;
12519
- if (!path59 || !lineNo || !message) continue;
12518
+ const [, path60, lineNo, sevToken, message] = m;
12519
+ if (!path60 || !lineNo || !message) continue;
12520
12520
  const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
12521
12521
  hunks.push({
12522
- path: path59.trim(),
12522
+ path: path60.trim(),
12523
12523
  line: Number(lineNo),
12524
12524
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
12525
12525
  message: cleanedMessage
@@ -12538,8 +12538,8 @@ var CoderabbitRuntimeStrategy = class {
12538
12538
  meta = getAgent("coderabbit");
12539
12539
  mode = "batch";
12540
12540
  os;
12541
- constructor(os39) {
12542
- this.os = os39;
12541
+ constructor(os40) {
12542
+ this.os = os40;
12543
12543
  }
12544
12544
  getDefaultArgs() {
12545
12545
  return ["review"];
@@ -12654,10 +12654,10 @@ function cursorCredentialLocator() {
12654
12654
  extract: extractLocalCursorToken
12655
12655
  };
12656
12656
  }
12657
- function cursorLoginLauncher(os39) {
12657
+ function cursorLoginLauncher(os40) {
12658
12658
  return {
12659
12659
  async ensureInstalled() {
12660
- if (os39.findInPath("cursor-agent")) return true;
12660
+ if (os40.findInPath("cursor-agent")) return true;
12661
12661
  console.error(
12662
12662
  "\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
12663
  );
@@ -12719,8 +12719,8 @@ var CursorRuntimeStrategy = class {
12719
12719
  meta = getAgent("cursor");
12720
12720
  mode = "interactive";
12721
12721
  os;
12722
- constructor(os39) {
12723
- this.os = os39;
12722
+ constructor(os40) {
12723
+ this.os = os40;
12724
12724
  }
12725
12725
  async prepareLaunch() {
12726
12726
  const binary = this.os.findInPath("cursor-agent");
@@ -12840,10 +12840,10 @@ function aiderCredentialLocator() {
12840
12840
  extract: extractLocalAiderToken
12841
12841
  };
12842
12842
  }
12843
- function aiderLoginLauncher(os39) {
12843
+ function aiderLoginLauncher(os40) {
12844
12844
  return {
12845
12845
  async ensureInstalled() {
12846
- if (os39.findInPath("aider")) return true;
12846
+ if (os40.findInPath("aider")) return true;
12847
12847
  console.error(
12848
12848
  "\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
12849
12849
  );
@@ -12853,7 +12853,7 @@ function aiderLoginLauncher(os39) {
12853
12853
  console.error(
12854
12854
  "\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
12855
  );
12856
- return (0, import_node_child_process9.spawn)(os39.id === "win32" ? "cmd.exe" : "sh", os39.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
12856
+ return (0, import_node_child_process9.spawn)(os40.id === "win32" ? "cmd.exe" : "sh", os40.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
12857
12857
  stdio: "ignore"
12858
12858
  });
12859
12859
  }
@@ -12925,8 +12925,8 @@ var AiderRuntimeStrategy = class {
12925
12925
  meta = getAgent("aider");
12926
12926
  mode = "interactive";
12927
12927
  os;
12928
- constructor(os39) {
12929
- this.os = os39;
12928
+ constructor(os40) {
12929
+ this.os = os40;
12930
12930
  }
12931
12931
  async prepareLaunch() {
12932
12932
  const binary = this.os.findInPath("aider");
@@ -13055,8 +13055,8 @@ function geminiCredentialLocator() {
13055
13055
  function geminiLoginLauncher() {
13056
13056
  return {
13057
13057
  async ensureInstalled() {
13058
- const os39 = createOsStrategy();
13059
- return os39.findInPath("gemini") !== null;
13058
+ const os40 = createOsStrategy();
13059
+ return os40.findInPath("gemini") !== null;
13060
13060
  },
13061
13061
  launch() {
13062
13062
  return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
@@ -13089,8 +13089,8 @@ var GeminiRuntimeStrategy = class {
13089
13089
  meta = getAgent("gemini");
13090
13090
  mode = "interactive";
13091
13091
  os;
13092
- constructor(os39) {
13093
- this.os = os39;
13092
+ constructor(os40) {
13093
+ this.os = os40;
13094
13094
  }
13095
13095
  async prepareLaunch() {
13096
13096
  const binary = this.os.findInPath("gemini");
@@ -13189,18 +13189,18 @@ var GeminiRuntimeStrategy = class {
13189
13189
 
13190
13190
  // src/agents/registry.ts
13191
13191
  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)
13192
+ claude: (os40) => new ClaudeRuntimeStrategy(os40),
13193
+ codex: (os40) => new CodexRuntimeStrategy(os40),
13194
+ coderabbit: (os40) => new CoderabbitRuntimeStrategy(os40),
13195
+ cursor: (os40) => new CursorRuntimeStrategy(os40),
13196
+ aider: (os40) => new AiderRuntimeStrategy(os40),
13197
+ gemini: (os40) => new GeminiRuntimeStrategy(os40)
13198
13198
  };
13199
13199
  var deployBuilders = {
13200
13200
  claude: () => new ClaudeDeployStrategy(),
13201
13201
  codex: () => new CodexDeployStrategy()
13202
13202
  };
13203
- function createAgentStrategy(agent, os39 = createOsStrategy()) {
13203
+ function createAgentStrategy(agent, os40 = createOsStrategy()) {
13204
13204
  if (!AGENT_REGISTRY[agent]?.enabled) {
13205
13205
  throw new Error(
13206
13206
  `Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
@@ -13210,10 +13210,10 @@ function createAgentStrategy(agent, os39 = createOsStrategy()) {
13210
13210
  if (!build) {
13211
13211
  throw new Error(`No runtime strategy registered for agent "${agent}"`);
13212
13212
  }
13213
- return build(os39);
13213
+ return build(os40);
13214
13214
  }
13215
- function createInteractiveAgentStrategy(agent, os39 = createOsStrategy()) {
13216
- const s = createAgentStrategy(agent, os39);
13215
+ function createInteractiveAgentStrategy(agent, os40 = createOsStrategy()) {
13216
+ const s = createAgentStrategy(agent, os40);
13217
13217
  if (s.mode !== "interactive") {
13218
13218
  throw new Error(
13219
13219
  `Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
@@ -14516,11 +14516,11 @@ function resolveDoltInstallStrategy(platform3) {
14516
14516
  }
14517
14517
  var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
14518
14518
  function doltPlatformTuple(platform3, arch2) {
14519
- const os39 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
14519
+ const os40 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
14520
14520
  const a = arch2 === "x64" ? "amd64" : arch2 === "arm64" ? "arm64" : null;
14521
14521
  if (!a) return null;
14522
- if (os39 === "windows" && a !== "amd64") return null;
14523
- return `${os39}-${a}`;
14522
+ if (os40 === "windows" && a !== "amd64") return null;
14523
+ return `${os40}-${a}`;
14524
14524
  }
14525
14525
  function resolveDoltTarballStrategy(targetDir, platform3, arch2) {
14526
14526
  const tuple = doltPlatformTuple(platform3, arch2);
@@ -16838,10 +16838,10 @@ async function startInfraOnly(agentId) {
16838
16838
  }
16839
16839
 
16840
16840
  // 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"));
16841
+ var import_node_child_process14 = require("child_process");
16842
+ var os33 = __toESM(require("os"));
16843
+ var fs40 = __toESM(require("fs"));
16844
+ var path46 = __toESM(require("path"));
16845
16845
 
16846
16846
  // src/commands/host/host-client.ts
16847
16847
  var fs35 = __toESM(require("fs"));
@@ -17112,6 +17112,60 @@ function repoCloneUrl(repoRef, cloneToken) {
17112
17112
  function maskCloneUrl(url) {
17113
17113
  return url.replace(/(https?:\/\/)[^@/]+@/, "$1***@");
17114
17114
  }
17115
+ async function fetchGithubIdentity(token) {
17116
+ try {
17117
+ const res = await fetch("https://api.github.com/user", {
17118
+ headers: {
17119
+ Authorization: `Bearer ${token}`,
17120
+ "User-Agent": "codeam-cli",
17121
+ Accept: "application/vnd.github+json"
17122
+ }
17123
+ });
17124
+ if (!res.ok) return null;
17125
+ const body = await res.json();
17126
+ return { login: body.login, email: body.email ?? void 0 };
17127
+ } catch {
17128
+ return null;
17129
+ }
17130
+ }
17131
+ async function configureGitCredentials(dest, repoRef, cloneToken) {
17132
+ const gh = githubOwnerRepo(repoRef.trim());
17133
+ if (!gh || !cloneToken) return;
17134
+ const credFile = path42.join(dest, ".git", "codeam-credentials");
17135
+ fs36.writeFileSync(credFile, `https://x-access-token:${cloneToken}@github.com
17136
+ `, { mode: 384 });
17137
+ try {
17138
+ fs36.chmodSync(credFile, 384);
17139
+ } catch {
17140
+ }
17141
+ const env = nonInteractiveGitEnv();
17142
+ const git2 = (args2) => execFileP5("git", ["-C", dest, ...args2], { timeout: 3e4, env });
17143
+ await git2(["config", "--local", "--replace-all", "credential.helper", ""]).catch(() => {
17144
+ });
17145
+ await git2([
17146
+ "config",
17147
+ "--local",
17148
+ "--add",
17149
+ "credential.helper",
17150
+ `store --file=${credFile}`
17151
+ ]).catch(() => {
17152
+ });
17153
+ await git2(["remote", "set-url", "origin", repoCloneUrl(repoRef)]).catch(() => {
17154
+ });
17155
+ const hasIdentity = await git2(["config", "user.email"]).then(() => true).catch(() => false);
17156
+ if (!hasIdentity) {
17157
+ const who = await fetchGithubIdentity(cloneToken);
17158
+ if (who?.login) {
17159
+ await git2(["config", "--local", "user.name", who.login]).catch(() => {
17160
+ });
17161
+ }
17162
+ const email = who?.email ?? (who?.login ? `${who.login}@users.noreply.github.com` : void 0);
17163
+ if (email) {
17164
+ await git2(["config", "--local", "user.email", email]).catch(() => {
17165
+ });
17166
+ }
17167
+ }
17168
+ }
17115
17169
  function maskToken(text, cloneToken) {
17116
17170
  const masked = maskCloneUrl(text);
17117
17171
  if (cloneToken && cloneToken.length > 0) {
@@ -17128,6 +17182,7 @@ async function prepareWorkspace(repoOrPath, deployId, cloneToken) {
17128
17182
  }
17129
17183
  const dest = path42.join(selfHostedWorkspaceRoot(), deployId);
17130
17184
  if (fs36.existsSync(path42.join(dest, ".git"))) {
17185
+ if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken);
17131
17186
  return dest;
17132
17187
  }
17133
17188
  fs36.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
@@ -17142,6 +17197,7 @@ async function prepareWorkspace(repoOrPath, deployId, cloneToken) {
17142
17197
  const reason = err instanceof Error ? err.message : String(err);
17143
17198
  throw new Error(`git clone failed for ${maskCloneUrl(cloneUrl)}: ${maskToken(reason, cloneToken)}`);
17144
17199
  }
17200
+ if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken);
17145
17201
  return dest;
17146
17202
  }
17147
17203
 
@@ -17215,6 +17271,172 @@ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os30.homedir(
17215
17271
  return provisioner.write(auth, homeDir2);
17216
17272
  }
17217
17273
 
17274
+ // src/commands/host/git-tooling.ts
17275
+ var import_node_child_process12 = require("child_process");
17276
+ var fs38 = __toESM(require("fs"));
17277
+ var os31 = __toESM(require("os"));
17278
+ var path44 = __toESM(require("path"));
17279
+ function codeamBinDir() {
17280
+ return process.env.CODEAM_BIN_DIR ?? path44.join(os31.homedir(), ".codeam", "bin");
17281
+ }
17282
+ var FALLBACK_GH_VERSION = "2.62.0";
17283
+ var RELEASE_API = "https://api.github.com/repos/cli/cli/releases/latest";
17284
+ function ghArch() {
17285
+ if (process.arch === "x64") return "amd64";
17286
+ if (process.arch === "arm64") return "arm64";
17287
+ return null;
17288
+ }
17289
+ async function resolveLatestGhVersion(token) {
17290
+ try {
17291
+ const headers = {
17292
+ Accept: "application/vnd.github+json",
17293
+ "User-Agent": "codeam-cli"
17294
+ };
17295
+ if (token) headers.Authorization = `Bearer ${token}`;
17296
+ const res = await fetch(RELEASE_API, { headers });
17297
+ if (!res.ok) return FALLBACK_GH_VERSION;
17298
+ const body = await res.json();
17299
+ if (typeof body.tag_name === "string" && body.tag_name) {
17300
+ return body.tag_name.replace(/^v/, "");
17301
+ }
17302
+ return FALLBACK_GH_VERSION;
17303
+ } catch {
17304
+ return FALLBACK_GH_VERSION;
17305
+ }
17306
+ }
17307
+ async function download(url, dest) {
17308
+ try {
17309
+ const res = await fetch(url, { headers: { "User-Agent": "codeam-cli" } });
17310
+ if (!res.ok || !res.body) return false;
17311
+ const buf = Buffer.from(await res.arrayBuffer());
17312
+ fs38.writeFileSync(dest, buf);
17313
+ return true;
17314
+ } catch {
17315
+ return false;
17316
+ }
17317
+ }
17318
+ async function ensureGhCli(runner, token, deps = {}) {
17319
+ if (runner.which("gh")) return "gh";
17320
+ const arch2 = ghArch();
17321
+ const platform3 = process.platform;
17322
+ if (arch2 === null || platform3 !== "linux" && platform3 !== "darwin") {
17323
+ log.warn("host-agent", `gh auto-install unsupported on ${platform3}/${process.arch} \u2014 skipping`);
17324
+ return null;
17325
+ }
17326
+ const downloadFn = deps.downloadFn ?? download;
17327
+ const resolveVersionFn = deps.resolveVersionFn ?? resolveLatestGhVersion;
17328
+ try {
17329
+ const version3 = await resolveVersionFn(token);
17330
+ const osToken = platform3 === "darwin" ? "macOS" : "linux";
17331
+ const ext = platform3 === "darwin" ? "zip" : "tar.gz";
17332
+ const asset = `gh_${version3}_${osToken}_${arch2}`;
17333
+ const url = `https://github.com/cli/cli/releases/download/v${version3}/${asset}.${ext}`;
17334
+ const tmpRoot = fs38.mkdtempSync(path44.join(os31.tmpdir(), "codeam-gh-"));
17335
+ const archive = path44.join(tmpRoot, `${asset}.${ext}`);
17336
+ if (!await downloadFn(url, archive)) {
17337
+ log.warn("host-agent", "gh download failed \u2014 skipping (git pull/push still work via the credential helper)");
17338
+ return null;
17339
+ }
17340
+ let extractCode = null;
17341
+ if (platform3 === "darwin") {
17342
+ const r = await runner.run("unzip", ["-o", archive, "-d", tmpRoot], { timeoutMs: 6e4 });
17343
+ extractCode = r.code;
17344
+ } else {
17345
+ const r = await runner.run("tar", ["-xzf", archive, "-C", tmpRoot], { timeoutMs: 6e4 });
17346
+ extractCode = r.code;
17347
+ }
17348
+ if (extractCode !== 0) {
17349
+ log.warn("host-agent", `gh archive extraction failed (code=${String(extractCode)}) \u2014 skipping`);
17350
+ return null;
17351
+ }
17352
+ const extractedBin = path44.join(tmpRoot, asset, "bin", "gh");
17353
+ if (!fs38.existsSync(extractedBin)) {
17354
+ log.warn("host-agent", "gh binary not found in the extracted archive \u2014 skipping");
17355
+ return null;
17356
+ }
17357
+ const binDir = codeamBinDir();
17358
+ fs38.mkdirSync(binDir, { recursive: true });
17359
+ const target = path44.join(binDir, "gh");
17360
+ fs38.copyFileSync(extractedBin, target);
17361
+ fs38.chmodSync(target, 493);
17362
+ log.info("host-agent", `gh installed to ${target} (v${version3})`);
17363
+ return target;
17364
+ } catch (e) {
17365
+ log.warn("host-agent", `gh auto-install errored: ${e instanceof Error ? e.message : String(e)} \u2014 skipping`);
17366
+ return null;
17367
+ }
17368
+ }
17369
+ async function ensureGhAuth(runner, ghCmd, token) {
17370
+ if (!token) return;
17371
+ try {
17372
+ const status2 = await runner.run(ghCmd, ["auth", "status"], { timeoutMs: 15e3 });
17373
+ if (status2.code === 0) {
17374
+ log.info("host-agent", "gh already authenticated \u2014 leaving the existing login untouched");
17375
+ return;
17376
+ }
17377
+ const login = await runner.run(ghCmd, ["auth", "login", "--with-token"], {
17378
+ timeoutMs: 2e4,
17379
+ input: `${token}
17380
+ `
17381
+ });
17382
+ if (login.code === 0) {
17383
+ log.info("host-agent", "gh authenticated with the linked GitHub token");
17384
+ } else {
17385
+ log.warn("host-agent", `gh auth login failed (code=${String(login.code)}) \u2014 gh unauthenticated`);
17386
+ }
17387
+ } catch (e) {
17388
+ log.warn("host-agent", `gh auth errored: ${e instanceof Error ? e.message : String(e)}`);
17389
+ }
17390
+ }
17391
+ var defaultGitToolingRunner = {
17392
+ which(cmd) {
17393
+ try {
17394
+ (0, import_node_child_process12.execFileSync)("which", [cmd], { stdio: "ignore" });
17395
+ return true;
17396
+ } catch {
17397
+ return false;
17398
+ }
17399
+ },
17400
+ run(cmd, args2, opts = {}) {
17401
+ return new Promise((resolve7) => {
17402
+ const child = (0, import_node_child_process12.spawn)(cmd, args2, {
17403
+ stdio: [opts.input !== void 0 ? "pipe" : "ignore", "ignore", "pipe"]
17404
+ });
17405
+ let stderr = "";
17406
+ let settled = false;
17407
+ const done = (code) => {
17408
+ if (settled) return;
17409
+ settled = true;
17410
+ resolve7({ code, stderr });
17411
+ };
17412
+ child.stderr?.on("data", (b) => {
17413
+ stderr += b.toString();
17414
+ });
17415
+ if (opts.input !== void 0) {
17416
+ child.stdin?.end(opts.input);
17417
+ }
17418
+ let timer;
17419
+ if (opts.timeoutMs !== void 0) {
17420
+ timer = setTimeout(() => {
17421
+ try {
17422
+ child.kill("SIGTERM");
17423
+ } catch {
17424
+ }
17425
+ done(null);
17426
+ }, opts.timeoutMs);
17427
+ }
17428
+ child.once("exit", (code) => {
17429
+ if (timer) clearTimeout(timer);
17430
+ done(code);
17431
+ });
17432
+ child.once("error", () => {
17433
+ if (timer) clearTimeout(timer);
17434
+ done(null);
17435
+ });
17436
+ });
17437
+ }
17438
+ };
17439
+
17218
17440
  // src/services/headroom/stats-reporter.ts
17219
17441
  var DEFAULT_INPUT_PRICE_PER_MILLION = 3;
17220
17442
  var ZERO = {
@@ -17298,23 +17520,23 @@ var HeadroomStatsReporter = class {
17298
17520
  };
17299
17521
 
17300
17522
  // src/lib/updateNotifier.ts
17301
- var fs38 = __toESM(require("fs"));
17302
- var os31 = __toESM(require("os"));
17303
- var path44 = __toESM(require("path"));
17523
+ var fs39 = __toESM(require("fs"));
17524
+ var os32 = __toESM(require("os"));
17525
+ var path45 = __toESM(require("path"));
17304
17526
  var https6 = __toESM(require("https"));
17305
- var import_node_child_process12 = require("child_process");
17527
+ var import_node_child_process13 = require("child_process");
17306
17528
  var import_picocolors3 = __toESM(require("picocolors"));
17307
17529
  var PKG_NAME = "codeam-cli";
17308
17530
  var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
17309
17531
  var TTL_MS = 24 * 60 * 60 * 1e3;
17310
17532
  var REQUEST_TIMEOUT_MS = 1500;
17311
17533
  function cachePath() {
17312
- const dir = path44.join(os31.homedir(), ".codeam");
17313
- return path44.join(dir, "update-check.json");
17534
+ const dir = path45.join(os32.homedir(), ".codeam");
17535
+ return path45.join(dir, "update-check.json");
17314
17536
  }
17315
17537
  function readCache() {
17316
17538
  try {
17317
- const raw = fs38.readFileSync(cachePath(), "utf8");
17539
+ const raw = fs39.readFileSync(cachePath(), "utf8");
17318
17540
  const parsed = JSON.parse(raw);
17319
17541
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
17320
17542
  return parsed;
@@ -17325,10 +17547,10 @@ function readCache() {
17325
17547
  function writeCache(cache) {
17326
17548
  try {
17327
17549
  const file = cachePath();
17328
- fs38.mkdirSync(path44.dirname(file), { recursive: true });
17550
+ fs39.mkdirSync(path45.dirname(file), { recursive: true });
17329
17551
  const tmp = `${file}.${process.pid}.tmp`;
17330
- fs38.writeFileSync(tmp, JSON.stringify(cache));
17331
- fs38.renameSync(tmp, file);
17552
+ fs39.writeFileSync(tmp, JSON.stringify(cache));
17553
+ fs39.renameSync(tmp, file);
17332
17554
  } catch {
17333
17555
  }
17334
17556
  }
@@ -17396,14 +17618,14 @@ function notifyIfStale(currentVersion, latest) {
17396
17618
  }
17397
17619
  function isLinkedInstall() {
17398
17620
  try {
17399
- const root = (0, import_node_child_process12.execSync)("npm root -g", {
17621
+ const root = (0, import_node_child_process13.execSync)("npm root -g", {
17400
17622
  encoding: "utf8",
17401
17623
  stdio: ["ignore", "pipe", "ignore"],
17402
17624
  timeout: 2e3
17403
17625
  }).trim();
17404
17626
  if (!root) return false;
17405
- const pkgPath = path44.join(root, PKG_NAME);
17406
- return fs38.lstatSync(pkgPath).isSymbolicLink();
17627
+ const pkgPath = path45.join(root, PKG_NAME);
17628
+ return fs39.lstatSync(pkgPath).isSymbolicLink();
17407
17629
  } catch {
17408
17630
  return false;
17409
17631
  }
@@ -17424,7 +17646,7 @@ function maybeAutoUpdate(currentVersion, latest) {
17424
17646
 
17425
17647
  `
17426
17648
  );
17427
- const install = (0, import_node_child_process12.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
17649
+ const install = (0, import_node_child_process13.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
17428
17650
  stdio: "inherit",
17429
17651
  env: process.env
17430
17652
  });
@@ -17439,24 +17661,40 @@ function maybeAutoUpdate(currentVersion, latest) {
17439
17661
  return;
17440
17662
  }
17441
17663
  try {
17442
- fs38.unlinkSync(cachePath());
17664
+ fs39.unlinkSync(cachePath());
17443
17665
  } catch {
17444
17666
  }
17445
17667
  process.stderr.write(` ${import_picocolors3.default.green("\u2713")} Updated. Resuming session...
17446
17668
 
17447
17669
  `);
17448
- const child = (0, import_node_child_process12.spawnSync)("codeam", process.argv.slice(2), {
17670
+ const child = (0, import_node_child_process13.spawnSync)("codeam", process.argv.slice(2), {
17449
17671
  stdio: "inherit",
17450
17672
  env: process.env
17451
17673
  });
17452
17674
  process.exit(child.status ?? 0);
17453
17675
  }
17676
+ async function autoUpgradeBeforeCriticalCommand() {
17677
+ if (process.env.NODE_ENV === "test") return;
17678
+ if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17679
+ if (process.env.CI) return;
17680
+ const current = true ? "2.39.83" : null;
17681
+ if (!current) return;
17682
+ const cache = readCache();
17683
+ const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
17684
+ let latest = fresh && cache ? cache.latest : null;
17685
+ if (!latest) {
17686
+ latest = await fetchLatest();
17687
+ if (latest) writeCache({ fetchedAt: Date.now(), latest });
17688
+ }
17689
+ if (!latest) return;
17690
+ maybeAutoUpdate(current, latest);
17691
+ }
17454
17692
  function checkForUpdates() {
17455
17693
  if (process.env.NODE_ENV === "test") return;
17456
17694
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17457
17695
  if (process.env.CI) return;
17458
17696
  if (!process.stdout.isTTY) return;
17459
- const current = true ? "2.39.82" : null;
17697
+ const current = true ? "2.39.83" : null;
17460
17698
  if (!current) return;
17461
17699
  const cache = readCache();
17462
17700
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17565,7 +17803,7 @@ var HEADROOM_MIN_FREE_DISK_BYTES = 2 * 1024 * 1024 * 1024;
17565
17803
  var defaultHeadroomRunner = {
17566
17804
  which(cmd) {
17567
17805
  try {
17568
- (0, import_node_child_process13.execFileSync)("which", [cmd], { stdio: "ignore" });
17806
+ (0, import_node_child_process14.execFileSync)("which", [cmd], { stdio: "ignore" });
17569
17807
  return true;
17570
17808
  } catch {
17571
17809
  return false;
@@ -17573,7 +17811,7 @@ var defaultHeadroomRunner = {
17573
17811
  },
17574
17812
  run(cmd, args2, opts = {}) {
17575
17813
  return new Promise((resolve7) => {
17576
- const child = (0, import_node_child_process13.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"] });
17814
+ const child = (0, import_node_child_process14.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"] });
17577
17815
  let stderrBuf = "";
17578
17816
  let settled = false;
17579
17817
  const done = (code) => {
@@ -17727,15 +17965,15 @@ function agentIdToHeadroomKind(agentId) {
17727
17965
  return "claude";
17728
17966
  }
17729
17967
  function headroomConfigPath() {
17730
- return path45.join(os32.homedir(), ".codeam", "headroom-config.json");
17968
+ return path46.join(os33.homedir(), ".codeam", "headroom-config.json");
17731
17969
  }
17732
17970
  function persistHeadroomConfig(config) {
17733
17971
  try {
17734
17972
  const file = headroomConfigPath();
17735
- fs39.mkdirSync(path45.dirname(file), { recursive: true, mode: 448 });
17973
+ fs40.mkdirSync(path46.dirname(file), { recursive: true, mode: 448 });
17736
17974
  const tmp = `${file}.tmp-${process.pid}`;
17737
- fs39.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
17738
- fs39.renameSync(tmp, file);
17975
+ fs40.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
17976
+ fs40.renameSync(tmp, file);
17739
17977
  } catch (err) {
17740
17978
  log.warn(
17741
17979
  "host-agent",
@@ -17745,7 +17983,7 @@ function persistHeadroomConfig(config) {
17745
17983
  }
17746
17984
  function readHeadroomChildEnv() {
17747
17985
  try {
17748
- const raw = fs39.readFileSync(headroomConfigPath(), "utf8");
17986
+ const raw = fs40.readFileSync(headroomConfigPath(), "utf8");
17749
17987
  const parsed = JSON.parse(raw);
17750
17988
  if (typeof parsed !== "object" || parsed === null) return {};
17751
17989
  const o = parsed;
@@ -17765,37 +18003,37 @@ function bundledClaudeBinDir() {
17765
18003
  const roots = /* @__PURE__ */ new Set();
17766
18004
  let dir = __dirname;
17767
18005
  for (let i = 0; i < 6; i++) {
17768
- roots.add(path45.join(dir, "node_modules"));
17769
- const parent = path45.dirname(dir);
18006
+ roots.add(path46.join(dir, "node_modules"));
18007
+ const parent = path46.dirname(dir);
17770
18008
  if (parent === dir) break;
17771
18009
  dir = parent;
17772
18010
  }
17773
18011
  try {
17774
18012
  const main2 = require.resolve("@anthropic-ai/claude-agent-sdk");
17775
- const marker = `${path45.sep}@anthropic-ai${path45.sep}`;
18013
+ const marker = `${path46.sep}@anthropic-ai${path46.sep}`;
17776
18014
  const idx = main2.lastIndexOf(marker);
17777
18015
  if (idx !== -1) roots.add(main2.slice(0, idx));
17778
18016
  } catch {
17779
18017
  }
17780
18018
  for (const nm of roots) {
17781
- const atAnthropic = path45.join(nm, "@anthropic-ai");
18019
+ const atAnthropic = path46.join(nm, "@anthropic-ai");
17782
18020
  let entries;
17783
18021
  try {
17784
- entries = fs39.readdirSync(atAnthropic);
18022
+ entries = fs40.readdirSync(atAnthropic);
17785
18023
  } catch {
17786
18024
  continue;
17787
18025
  }
17788
18026
  for (const entry of entries) {
17789
18027
  if (!entry.startsWith("claude-agent-sdk-")) continue;
17790
- const bin = path45.join(atAnthropic, entry, "claude");
17791
- if (fs39.existsSync(bin)) return path45.dirname(bin);
18028
+ const bin = path46.join(atAnthropic, entry, "claude");
18029
+ if (fs40.existsSync(bin)) return path46.dirname(bin);
17792
18030
  }
17793
18031
  }
17794
18032
  return null;
17795
18033
  }
17796
18034
  async function getFreeDiskBytes(dir) {
17797
18035
  try {
17798
- const s = await fs39.promises.statfs(dir);
18036
+ const s = await fs40.promises.statfs(dir);
17799
18037
  return s.bsize * s.bavail;
17800
18038
  } catch {
17801
18039
  return null;
@@ -17845,14 +18083,14 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
17845
18083
  if (initKind === "claude") {
17846
18084
  const claudeDir = bundledClaudeBinDir();
17847
18085
  if (claudeDir) {
17848
- initEnv.PATH = `${claudeDir}${path45.delimiter}${process.env["PATH"] ?? ""}`;
18086
+ initEnv.PATH = `${claudeDir}${path46.delimiter}${process.env["PATH"] ?? ""}`;
17849
18087
  log.info("host-agent", `headroom init: bundled claude on PATH (${claudeDir})`);
17850
18088
  } else {
17851
18089
  log.warn("host-agent", "headroom init: bundled claude binary not found \u2014 init may fail");
17852
18090
  }
17853
18091
  }
17854
18092
  const initOk = await new Promise((resolve7) => {
17855
- (0, import_node_child_process13.execFile)(
18093
+ (0, import_node_child_process14.execFile)(
17856
18094
  "headroom",
17857
18095
  ["init", "--global", initKind],
17858
18096
  { env: initEnv },
@@ -17873,7 +18111,7 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
17873
18111
  return false;
17874
18112
  }
17875
18113
  try {
17876
- const proxy = (0, import_node_child_process13.spawn)("headroom", ["proxy", "--port", "8787"], {
18114
+ const proxy = (0, import_node_child_process14.spawn)("headroom", ["proxy", "--port", "8787"], {
17877
18115
  stdio: "ignore",
17878
18116
  detached: true,
17879
18117
  env: { ...process.env, HEADROOM_KOMPRESS_BACKEND: "onnx_cpu" }
@@ -17887,18 +18125,18 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
17887
18125
  }
17888
18126
  return true;
17889
18127
  }
17890
- var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process13.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
18128
+ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process14.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
17891
18129
  cwd,
17892
18130
  env: { ...process.env, ...env },
17893
18131
  stdio: ["ignore", "pipe", "pipe"],
17894
18132
  detached: false
17895
18133
  });
17896
18134
  function currentCliVersion() {
17897
- return true ? "2.39.82" : null;
18135
+ return true ? "2.39.83" : null;
17898
18136
  }
17899
18137
  function runCmd(cmd, args2, timeoutMs) {
17900
18138
  return new Promise((resolve7) => {
17901
- (0, import_node_child_process13.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
18139
+ (0, import_node_child_process14.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
17902
18140
  const code = err && typeof err.code === "number" ? err.code : err ? null : 0;
17903
18141
  resolve7({ code, stdout: stdout ?? "", stderr: stderr ?? "" });
17904
18142
  });
@@ -17969,20 +18207,20 @@ var defaultOnUpdated = (version3) => {
17969
18207
  };
17970
18208
  var defaultDisableService = () => {
17971
18209
  try {
17972
- (0, import_node_child_process13.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
18210
+ (0, import_node_child_process14.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
17973
18211
  } catch {
17974
18212
  }
17975
18213
  };
17976
18214
  var defaultTeardownHeadroom = () => {
17977
18215
  try {
17978
- const kind = JSON.parse(fs39.readFileSync(headroomConfigPath(), "utf8")).agent;
18216
+ const kind = JSON.parse(fs40.readFileSync(headroomConfigPath(), "utf8")).agent;
17979
18217
  if (kind) {
17980
- (0, import_node_child_process13.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
18218
+ (0, import_node_child_process14.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
17981
18219
  }
17982
18220
  } catch {
17983
18221
  }
17984
18222
  try {
17985
- (0, import_node_child_process13.execFileSync)("pkill", ["-TERM", "-f", "headroom.*proxy"], { stdio: "ignore" });
18223
+ (0, import_node_child_process14.execFileSync)("pkill", ["-TERM", "-f", "headroom.*proxy"], { stdio: "ignore" });
17986
18224
  } catch {
17987
18225
  }
17988
18226
  persistHeadroomConfig({ enabled: false });
@@ -18303,15 +18541,30 @@ var HostAgentSupervisor = class {
18303
18541
  report("installing", "installing agent CLI");
18304
18542
  await this.runAgentInstall(payload.agentInstallScript);
18305
18543
  }
18306
- const home = process.env.HOME || os32.homedir();
18544
+ const home = process.env.HOME || os33.homedir();
18307
18545
  childEnv.PATH = `${home}/.local/bin:${process.env.PATH ?? ""}`;
18546
+ if (payload.cloneToken) {
18547
+ try {
18548
+ report("preparing", "configuring git tooling");
18549
+ const ghCmd = await ensureGhCli(defaultGitToolingRunner, payload.cloneToken);
18550
+ if (ghCmd) {
18551
+ childEnv.PATH = `${codeamBinDir()}:${childEnv.PATH}`;
18552
+ await ensureGhAuth(defaultGitToolingRunner, ghCmd, payload.cloneToken);
18553
+ }
18554
+ } catch (e) {
18555
+ log.warn(
18556
+ "host-agent",
18557
+ `gh tooling setup skipped: ${e instanceof Error ? e.message : String(e)}`
18558
+ );
18559
+ }
18560
+ }
18308
18561
  if (payload.previewTunnelToken && payload.previewHostname) {
18309
18562
  childEnv.PREVIEW_TUNNEL_TOKEN = payload.previewTunnelToken;
18310
18563
  childEnv.PREVIEW_TUNNEL_HOSTNAME = payload.previewHostname;
18311
18564
  }
18312
18565
  if (payload.headroomEnabled && payload.headroomAgent && payload.headroomSavingsIngestUrl) {
18313
18566
  report("headroom", "setting up Headroom proxy");
18314
- const freeBytes = await this.getFreeDisk(os32.homedir());
18567
+ const freeBytes = await this.getFreeDisk(os33.homedir());
18315
18568
  const alreadyInstalled = this.isHeadroomInstalled();
18316
18569
  if (!alreadyInstalled && freeBytes !== null && freeBytes < HEADROOM_MIN_FREE_DISK_BYTES) {
18317
18570
  const freeGb = (freeBytes / 1e9).toFixed(1);
@@ -18427,8 +18680,8 @@ var HostAgentSupervisor = class {
18427
18680
  */
18428
18681
  runAgentInstall(script) {
18429
18682
  return new Promise((resolve7) => {
18430
- const home = process.env.HOME || os32.homedir();
18431
- const child = (0, import_node_child_process13.spawn)("sh", ["-c", script], {
18683
+ const home = process.env.HOME || os33.homedir();
18684
+ const child = (0, import_node_child_process14.spawn)("sh", ["-c", script], {
18432
18685
  env: { ...process.env, HOME: home },
18433
18686
  stdio: ["ignore", "pipe", "pipe"]
18434
18687
  });
@@ -18582,12 +18835,12 @@ function readTokenFromArgs(args2) {
18582
18835
  }
18583
18836
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
18584
18837
  if (fileFlag) {
18585
- const path59 = fileFlag.slice("--token-file=".length);
18838
+ const path60 = fileFlag.slice("--token-file=".length);
18586
18839
  try {
18587
- const content = fs40.readFileSync(path59, "utf8").trim();
18588
- if (content.length === 0) fail(`--token-file ${path59} is empty`);
18840
+ const content = fs41.readFileSync(path60, "utf8").trim();
18841
+ if (content.length === 0) fail(`--token-file ${path60} is empty`);
18589
18842
  try {
18590
- fs40.unlinkSync(path59);
18843
+ fs41.unlinkSync(path60);
18591
18844
  } catch {
18592
18845
  }
18593
18846
  return content;
@@ -18613,7 +18866,7 @@ async function claimOnce(token, pluginId, pluginSecretHash) {
18613
18866
  pluginId,
18614
18867
  ideName: "codeam-cli (codespace)",
18615
18868
  ideVersion: process.env.npm_package_version ?? "unknown",
18616
- hostname: os33.hostname(),
18869
+ hostname: os34.hostname(),
18617
18870
  codespaceName: process.env.CODESPACE_NAME ?? "",
18618
18871
  // Current git branch of the codespace's working directory, so the
18619
18872
  // backend can populate `PairedSession.branch` for the codespace pair.
@@ -18674,7 +18927,7 @@ async function claim(token, pluginId, pluginSecretHash) {
18674
18927
  }
18675
18928
  }
18676
18929
  function pairAutoLockPath() {
18677
- return path46.join(os33.homedir(), ".codeam", "pair-auto.lock");
18930
+ return path47.join(os34.homedir(), ".codeam", "pair-auto.lock");
18678
18931
  }
18679
18932
  function isLivePairAuto(pid) {
18680
18933
  if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
@@ -18684,7 +18937,7 @@ function isLivePairAuto(pid) {
18684
18937
  if (e.code !== "EPERM") return false;
18685
18938
  }
18686
18939
  try {
18687
- return fs40.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
18940
+ return fs41.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
18688
18941
  } catch {
18689
18942
  return true;
18690
18943
  }
@@ -18694,24 +18947,24 @@ function isLiveCodeam(pid) {
18694
18947
  }
18695
18948
  function daemonLockPath(sessionId) {
18696
18949
  const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
18697
- return path46.join(os33.homedir(), ".codeam", `daemon-${safe}.lock`);
18950
+ return path47.join(os34.homedir(), ".codeam", `daemon-${safe}.lock`);
18698
18951
  }
18699
18952
  function acquireDaemonLock(sessionId) {
18700
18953
  const lockPath = daemonLockPath(sessionId);
18701
18954
  try {
18702
- fs40.mkdirSync(path46.dirname(lockPath), { recursive: true });
18955
+ fs41.mkdirSync(path47.dirname(lockPath), { recursive: true });
18703
18956
  try {
18704
- fs40.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
18957
+ fs41.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
18705
18958
  } catch (e) {
18706
18959
  if (e.code !== "EEXIST") throw e;
18707
- const holder = Number(fs40.readFileSync(lockPath, "utf8").trim());
18960
+ const holder = Number(fs41.readFileSync(lockPath, "utf8").trim());
18708
18961
  if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
18709
- fs40.writeFileSync(lockPath, String(process.pid));
18962
+ fs41.writeFileSync(lockPath, String(process.pid));
18710
18963
  }
18711
18964
  const release3 = () => {
18712
18965
  try {
18713
- if (fs40.existsSync(lockPath) && Number(fs40.readFileSync(lockPath, "utf8").trim()) === process.pid) {
18714
- fs40.unlinkSync(lockPath);
18966
+ if (fs41.existsSync(lockPath) && Number(fs41.readFileSync(lockPath, "utf8").trim()) === process.pid) {
18967
+ fs41.unlinkSync(lockPath);
18715
18968
  }
18716
18969
  } catch {
18717
18970
  }
@@ -18733,19 +18986,19 @@ function acquireDaemonLock(sessionId) {
18733
18986
  function acquireSingletonLock() {
18734
18987
  const lockPath = pairAutoLockPath();
18735
18988
  try {
18736
- fs40.mkdirSync(path46.dirname(lockPath), { recursive: true });
18989
+ fs41.mkdirSync(path47.dirname(lockPath), { recursive: true });
18737
18990
  try {
18738
- fs40.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
18991
+ fs41.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
18739
18992
  } catch (e) {
18740
18993
  if (e.code !== "EEXIST") throw e;
18741
- const holder = Number(fs40.readFileSync(lockPath, "utf8").trim());
18994
+ const holder = Number(fs41.readFileSync(lockPath, "utf8").trim());
18742
18995
  if (isLivePairAuto(holder)) return false;
18743
- fs40.writeFileSync(lockPath, String(process.pid));
18996
+ fs41.writeFileSync(lockPath, String(process.pid));
18744
18997
  }
18745
18998
  process.once("exit", () => {
18746
18999
  try {
18747
- if (fs40.existsSync(lockPath) && Number(fs40.readFileSync(lockPath, "utf8").trim()) === process.pid) {
18748
- fs40.unlinkSync(lockPath);
19000
+ if (fs41.existsSync(lockPath) && Number(fs41.readFileSync(lockPath, "utf8").trim()) === process.pid) {
19001
+ fs41.unlinkSync(lockPath);
18749
19002
  }
18750
19003
  } catch {
18751
19004
  }
@@ -18827,7 +19080,7 @@ async function pairAuto(args2) {
18827
19080
  }
18828
19081
 
18829
19082
  // src/services/headroom/wrap-launch.ts
18830
- var import_node_child_process14 = require("child_process");
19083
+ var import_node_child_process15 = require("child_process");
18831
19084
  function wrapWithHeadroom(launch, opts) {
18832
19085
  if (!opts.enabled || !opts.headroomPresent) return launch;
18833
19086
  return {
@@ -18840,7 +19093,7 @@ var _present;
18840
19093
  function headroomPresent() {
18841
19094
  if (_present !== void 0) return Promise.resolve(_present);
18842
19095
  return new Promise((resolve7) => {
18843
- (0, import_node_child_process14.execFile)("headroom", ["--version"], (err) => {
19096
+ (0, import_node_child_process15.execFile)("headroom", ["--version"], (err) => {
18844
19097
  _present = !err;
18845
19098
  resolve7(_present);
18846
19099
  });
@@ -19190,19 +19443,19 @@ var AgentService = class _AgentService {
19190
19443
  };
19191
19444
 
19192
19445
  // src/agents/acp/adapters.ts
19193
- var path47 = __toESM(require("path"));
19446
+ var path48 = __toESM(require("path"));
19194
19447
  var require_ = require;
19195
19448
  function resolveBin(pkgName, binName) {
19196
19449
  try {
19197
19450
  const manifestPath = require_.resolve(`${pkgName}/package.json`);
19198
19451
  const manifest = require_(`${pkgName}/package.json`);
19199
- const pkgDir = path47.dirname(manifestPath);
19452
+ const pkgDir = path48.dirname(manifestPath);
19200
19453
  const bin = manifest.bin;
19201
19454
  if (!bin) return null;
19202
- if (typeof bin === "string") return path47.resolve(pkgDir, bin);
19455
+ if (typeof bin === "string") return path48.resolve(pkgDir, bin);
19203
19456
  const target = binName ?? Object.keys(bin)[0];
19204
19457
  if (!target || !bin[target]) return null;
19205
- return path47.resolve(pkgDir, bin[target]);
19458
+ return path48.resolve(pkgDir, bin[target]);
19206
19459
  } catch {
19207
19460
  return null;
19208
19461
  }
@@ -19278,9 +19531,9 @@ function requiresAcp(agent) {
19278
19531
  var import_node_crypto7 = require("crypto");
19279
19532
 
19280
19533
  // src/services/history.service.ts
19281
- var fs41 = __toESM(require("fs"));
19282
- var path48 = __toESM(require("path"));
19283
- var os34 = __toESM(require("os"));
19534
+ var fs42 = __toESM(require("fs"));
19535
+ var path49 = __toESM(require("path"));
19536
+ var os35 = __toESM(require("os"));
19284
19537
  var https7 = __toESM(require("https"));
19285
19538
  var http6 = __toESM(require("http"));
19286
19539
  var import_zod2 = require("zod");
@@ -19307,7 +19560,7 @@ function parseJsonl(filePath) {
19307
19560
  const messages = [];
19308
19561
  let raw;
19309
19562
  try {
19310
- raw = fs41.readFileSync(filePath, "utf8");
19563
+ raw = fs42.readFileSync(filePath, "utf8");
19311
19564
  } catch (err) {
19312
19565
  if (err.code !== "ENOENT") {
19313
19566
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -19448,7 +19701,7 @@ var HistoryService = class _HistoryService {
19448
19701
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
19449
19702
  }
19450
19703
  get projectDir() {
19451
- return this.runtime.resolveHistoryDir(this.cwd) ?? path48.join(os34.homedir(), ".claude", "projects", encodeCwd(this.cwd));
19704
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path49.join(os35.homedir(), ".claude", "projects", encodeCwd(this.cwd));
19452
19705
  }
19453
19706
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
19454
19707
  setCurrentConversationId(id) {
@@ -19460,7 +19713,7 @@ var HistoryService = class _HistoryService {
19460
19713
  /** Return the current message count in the active conversation. */
19461
19714
  getCurrentMessageCount() {
19462
19715
  if (!this.currentConversationId) return 0;
19463
- const filePath = path48.join(this.projectDir, `${this.currentConversationId}.jsonl`);
19716
+ const filePath = path49.join(this.projectDir, `${this.currentConversationId}.jsonl`);
19464
19717
  return parseJsonl(filePath).length;
19465
19718
  }
19466
19719
  /**
@@ -19471,7 +19724,7 @@ var HistoryService = class _HistoryService {
19471
19724
  const deadline = Date.now() + timeoutMs;
19472
19725
  while (Date.now() < deadline) {
19473
19726
  if (!this.currentConversationId) return null;
19474
- const filePath = path48.join(this.projectDir, `${this.currentConversationId}.jsonl`);
19727
+ const filePath = path49.join(this.projectDir, `${this.currentConversationId}.jsonl`);
19475
19728
  const messages = parseJsonl(filePath);
19476
19729
  if (messages.length > previousCount) {
19477
19730
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -19497,16 +19750,16 @@ var HistoryService = class _HistoryService {
19497
19750
  const dir = this.projectDir;
19498
19751
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
19499
19752
  try {
19500
- const files = fs41.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
19753
+ const files = fs42.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
19501
19754
  try {
19502
- const stat3 = fs41.statSync(path48.join(dir, e.name));
19755
+ const stat3 = fs42.statSync(path49.join(dir, e.name));
19503
19756
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
19504
19757
  } catch {
19505
19758
  return { name: e.name, mtime: 0, birthtime: 0 };
19506
19759
  }
19507
19760
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
19508
19761
  if (files.length > 0) {
19509
- this.currentConversationId = path48.basename(files[0].name, ".jsonl");
19762
+ this.currentConversationId = path49.basename(files[0].name, ".jsonl");
19510
19763
  }
19511
19764
  } catch {
19512
19765
  }
@@ -19540,13 +19793,13 @@ var HistoryService = class _HistoryService {
19540
19793
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
19541
19794
  let entries;
19542
19795
  try {
19543
- entries = fs41.readdirSync(dir, { withFileTypes: true });
19796
+ entries = fs42.readdirSync(dir, { withFileTypes: true });
19544
19797
  } catch {
19545
19798
  return null;
19546
19799
  }
19547
19800
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
19548
19801
  try {
19549
- const stat3 = fs41.statSync(path48.join(dir, e.name));
19802
+ const stat3 = fs42.statSync(path49.join(dir, e.name));
19550
19803
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
19551
19804
  } catch {
19552
19805
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -19555,12 +19808,12 @@ var HistoryService = class _HistoryService {
19555
19808
  if (files.length === 0) return null;
19556
19809
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
19557
19810
  if (!files.some((f) => f.name === targetFile)) return null;
19558
- return this.extractUsageFromFile(path48.join(dir, targetFile));
19811
+ return this.extractUsageFromFile(path49.join(dir, targetFile));
19559
19812
  }
19560
19813
  extractUsageFromFile(filePath) {
19561
19814
  let raw;
19562
19815
  try {
19563
- raw = fs41.readFileSync(filePath, "utf8");
19816
+ raw = fs42.readFileSync(filePath, "utf8");
19564
19817
  } catch {
19565
19818
  return null;
19566
19819
  }
@@ -19605,9 +19858,9 @@ var HistoryService = class _HistoryService {
19605
19858
  let totalCost = 0;
19606
19859
  let files;
19607
19860
  try {
19608
- files = fs41.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
19861
+ files = fs42.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
19609
19862
  try {
19610
- return fs41.statSync(path48.join(projectDir, f)).mtimeMs >= monthStartMs;
19863
+ return fs42.statSync(path49.join(projectDir, f)).mtimeMs >= monthStartMs;
19611
19864
  } catch {
19612
19865
  return false;
19613
19866
  }
@@ -19618,7 +19871,7 @@ var HistoryService = class _HistoryService {
19618
19871
  for (const file of files) {
19619
19872
  let raw;
19620
19873
  try {
19621
- raw = fs41.readFileSync(path48.join(projectDir, file), "utf8");
19874
+ raw = fs42.readFileSync(path49.join(projectDir, file), "utf8");
19622
19875
  } catch {
19623
19876
  continue;
19624
19877
  }
@@ -19686,7 +19939,7 @@ var HistoryService = class _HistoryService {
19686
19939
  * showing an empty conversation.
19687
19940
  */
19688
19941
  async loadConversation(sessionId) {
19689
- const filePath = path48.join(this.projectDir, `${sessionId}.jsonl`);
19942
+ const filePath = path49.join(this.projectDir, `${sessionId}.jsonl`);
19690
19943
  const messages = parseJsonl(filePath);
19691
19944
  if (messages.length === 0) return;
19692
19945
  const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
@@ -19736,10 +19989,10 @@ var HistoryService = class _HistoryService {
19736
19989
  * or no transcript exists yet (not an error).
19737
19990
  */
19738
19991
  async uploadConversationIfChanged(sessionId) {
19739
- const filePath = path48.join(this.projectDir, `${sessionId}.jsonl`);
19992
+ const filePath = path49.join(this.projectDir, `${sessionId}.jsonl`);
19740
19993
  let mtimeMs;
19741
19994
  try {
19742
- mtimeMs = fs41.statSync(filePath).mtimeMs;
19995
+ mtimeMs = fs42.statSync(filePath).mtimeMs;
19743
19996
  } catch {
19744
19997
  return false;
19745
19998
  }
@@ -19778,7 +20031,7 @@ var HistoryService = class _HistoryService {
19778
20031
  sessionId = this.currentConversationId;
19779
20032
  if (!sessionId) return 0;
19780
20033
  }
19781
- const filePath = path48.join(this.projectDir, `${sessionId}.jsonl`);
20034
+ const filePath = path49.join(this.projectDir, `${sessionId}.jsonl`);
19782
20035
  const messages = parseJsonl(filePath);
19783
20036
  if (messages.length === 0) return 0;
19784
20037
  const marker = this.lastUploadedUuid.get(sessionId);
@@ -19808,11 +20061,11 @@ var HistoryService = class _HistoryService {
19808
20061
  };
19809
20062
 
19810
20063
  // src/agents/acp/client.ts
19811
- var import_node_child_process15 = require("child_process");
19812
- var fs42 = __toESM(require("fs/promises"));
20064
+ var import_node_child_process16 = require("child_process");
20065
+ var fs43 = __toESM(require("fs/promises"));
19813
20066
  var fsSync = __toESM(require("fs"));
19814
- var os35 = __toESM(require("os"));
19815
- var path49 = __toESM(require("path"));
20067
+ var os36 = __toESM(require("os"));
20068
+ var path50 = __toESM(require("path"));
19816
20069
  var import_node_stream = require("stream");
19817
20070
 
19818
20071
  // ../../node_modules/@agentclientprotocol/sdk/dist/acp.js
@@ -22349,7 +22602,7 @@ var AcpClient = class {
22349
22602
  "acpClient",
22350
22603
  `spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
22351
22604
  );
22352
- const child = (0, import_node_child_process15.spawn)(adapter.command, adapter.args, {
22605
+ const child = (0, import_node_child_process16.spawn)(adapter.command, adapter.args, {
22353
22606
  cwd,
22354
22607
  env: { ...process.env, PATH: augmentedPath },
22355
22608
  stdio: ["pipe", "pipe", "pipe"]
@@ -22606,7 +22859,7 @@ var AcpClient = class {
22606
22859
  },
22607
22860
  readTextFile: async (params) => {
22608
22861
  try {
22609
- const content = await fs42.readFile(params.path, "utf8");
22862
+ const content = await fs43.readFile(params.path, "utf8");
22610
22863
  return applyLineRange(content, params.line ?? null, params.limit ?? null);
22611
22864
  } catch (err) {
22612
22865
  const code = err.code;
@@ -22626,7 +22879,7 @@ var AcpClient = class {
22626
22879
  },
22627
22880
  writeTextFile: async (params) => {
22628
22881
  try {
22629
- await fs42.writeFile(params.path, params.content, "utf8");
22882
+ await fs43.writeFile(params.path, params.content, "utf8");
22630
22883
  return {};
22631
22884
  } catch (err) {
22632
22885
  const code = err.code;
@@ -22675,25 +22928,25 @@ function applyLineRange(content, line, limit) {
22675
22928
  return { content: lines.slice(start2, end).join("\n") };
22676
22929
  }
22677
22930
  function knownAgentBinaryDirs() {
22678
- const home = os35.homedir();
22931
+ const home = os36.homedir();
22679
22932
  const out2 = [];
22680
22933
  out2.push("/tmp/codeam-node20/bin");
22681
22934
  for (const root of [
22682
22935
  "/usr/local/share/nvm/versions/node",
22683
- path49.join(home, ".nvm/versions/node")
22936
+ path50.join(home, ".nvm/versions/node")
22684
22937
  ]) {
22685
22938
  try {
22686
22939
  for (const child of fsSync.readdirSync(root)) {
22687
- out2.push(path49.join(root, child, "bin"));
22940
+ out2.push(path50.join(root, child, "bin"));
22688
22941
  }
22689
22942
  } catch {
22690
22943
  }
22691
22944
  }
22692
- out2.push(path49.join(home, ".volta/bin"));
22945
+ out2.push(path50.join(home, ".volta/bin"));
22693
22946
  out2.push("/usr/local/bin");
22694
22947
  out2.push("/usr/bin");
22695
- out2.push(path49.join(home, ".local/bin"));
22696
- out2.push(path49.join(home, "bin"));
22948
+ out2.push(path50.join(home, ".local/bin"));
22949
+ out2.push(path50.join(home, "bin"));
22697
22950
  return out2.filter((p2) => {
22698
22951
  try {
22699
22952
  return fsSync.statSync(p2).isDirectory();
@@ -22704,7 +22957,7 @@ function knownAgentBinaryDirs() {
22704
22957
  }
22705
22958
  function expandPathForAgentBinaries(existingPath) {
22706
22959
  const existing = new Set(
22707
- existingPath.split(path49.delimiter).filter((p2) => p2.length > 0)
22960
+ existingPath.split(path50.delimiter).filter((p2) => p2.length > 0)
22708
22961
  );
22709
22962
  const additions = [];
22710
22963
  for (const dir of knownAgentBinaryDirs()) {
@@ -22714,7 +22967,7 @@ function expandPathForAgentBinaries(existingPath) {
22714
22967
  }
22715
22968
  }
22716
22969
  if (additions.length === 0) return existingPath;
22717
- return [...additions, existingPath].filter((p2) => p2.length > 0).join(path49.delimiter);
22970
+ return [...additions, existingPath].filter((p2) => p2.length > 0).join(path50.delimiter);
22718
22971
  }
22719
22972
 
22720
22973
  // src/services/streaming/transport.ts
@@ -23041,15 +23294,15 @@ function reconcileCumulative(existing, incoming) {
23041
23294
  }
23042
23295
 
23043
23296
  // src/agents/acp/onboarding.ts
23044
- var fs43 = __toESM(require("fs"));
23045
- var os36 = __toESM(require("os"));
23046
- var path50 = __toESM(require("path"));
23297
+ var fs44 = __toESM(require("fs"));
23298
+ var os37 = __toESM(require("os"));
23299
+ var path51 = __toESM(require("path"));
23047
23300
  var _onboardingSeam = {
23048
- markerPath: (sessionId) => path50.join(os36.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
23049
- exists: (p2) => fs43.existsSync(p2),
23301
+ markerPath: (sessionId) => path51.join(os37.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
23302
+ exists: (p2) => fs44.existsSync(p2),
23050
23303
  write: (p2) => {
23051
- fs43.mkdirSync(path50.dirname(p2), { recursive: true });
23052
- fs43.writeFileSync(p2, "");
23304
+ fs44.mkdirSync(path51.dirname(p2), { recursive: true });
23305
+ fs44.writeFileSync(p2, "");
23053
23306
  },
23054
23307
  disabled: () => {
23055
23308
  const v = process.env.CODEAM_ONBOARDING_DISABLED;
@@ -23057,7 +23310,7 @@ var _onboardingSeam = {
23057
23310
  }
23058
23311
  };
23059
23312
  function buildOnboardingWelcome(cwd) {
23060
- const repo = path50.basename(cwd || "") || "this project";
23313
+ const repo = path51.basename(cwd || "") || "this project";
23061
23314
  return [
23062
23315
  `Welcome to CodeAgent Mobile! \u{1F44B} You're now driving this agent from your phone \u2014 and it comes fully wired, zero setup:`,
23063
23316
  "",
@@ -23323,8 +23576,8 @@ var import_crypto5 = require("crypto");
23323
23576
 
23324
23577
  // src/services/turn-files/git-changeset.ts
23325
23578
  var import_child_process22 = require("child_process");
23326
- var fs44 = __toESM(require("fs/promises"));
23327
- var path51 = __toESM(require("path"));
23579
+ var fs45 = __toESM(require("fs/promises"));
23580
+ var path52 = __toESM(require("path"));
23328
23581
  async function collectRepoChangeset(opts) {
23329
23582
  const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
23330
23583
  if (status2 === null) return null;
@@ -23342,7 +23595,7 @@ async function collectRepoChangeset(opts) {
23342
23595
  let stats;
23343
23596
  if (row.fileStatus === "added" && numstatEntry === void 0) {
23344
23597
  const lineCount = await readUntrackedLineCount(
23345
- path51.join(opts.repoRoot, row.filePath)
23598
+ path52.join(opts.repoRoot, row.filePath)
23346
23599
  );
23347
23600
  stats = { added: lineCount, removed: 0 };
23348
23601
  } else {
@@ -23373,7 +23626,7 @@ function readUntrackedLineCount(absPath) {
23373
23626
  }
23374
23627
  async function defaultReadUntrackedLineCount(absPath) {
23375
23628
  try {
23376
- const content = await fs44.readFile(absPath, "utf8");
23629
+ const content = await fs45.readFile(absPath, "utf8");
23377
23630
  let count = 0;
23378
23631
  let pos = -1;
23379
23632
  while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
@@ -23465,7 +23718,7 @@ function defaultRunGit(cwd, args2) {
23465
23718
  });
23466
23719
  }
23467
23720
  async function discoverRepos(workingDir, maxDepth = 4) {
23468
- const fs48 = await import("fs/promises");
23721
+ const fs49 = await import("fs/promises");
23469
23722
  const out2 = [];
23470
23723
  await walk(workingDir, 0);
23471
23724
  return out2;
@@ -23473,7 +23726,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
23473
23726
  if (depth > maxDepth) return;
23474
23727
  let entries = [];
23475
23728
  try {
23476
- const dirents = await fs48.readdir(dir, { withFileTypes: true });
23729
+ const dirents = await fs49.readdir(dir, { withFileTypes: true });
23477
23730
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
23478
23731
  } catch {
23479
23732
  return;
@@ -23484,8 +23737,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
23484
23737
  if (hasGit) {
23485
23738
  out2.push({
23486
23739
  repoRoot: dir,
23487
- repoPath: path51.relative(workingDir, dir),
23488
- repoName: path51.basename(dir)
23740
+ repoPath: path52.relative(workingDir, dir),
23741
+ repoName: path52.basename(dir)
23489
23742
  });
23490
23743
  return;
23491
23744
  }
@@ -23493,14 +23746,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
23493
23746
  if (!entry.isDirectory) continue;
23494
23747
  if (entry.name === "node_modules") continue;
23495
23748
  if (entry.name === "dist" || entry.name === "build") continue;
23496
- await walk(path51.join(dir, entry.name), depth + 1);
23749
+ await walk(path52.join(dir, entry.name), depth + 1);
23497
23750
  }
23498
23751
  }
23499
23752
  }
23500
23753
 
23501
23754
  // src/services/turn-files/files-outbox.ts
23502
- var fs45 = __toESM(require("fs/promises"));
23503
- var path52 = __toESM(require("path"));
23755
+ var fs46 = __toESM(require("fs/promises"));
23756
+ var path53 = __toESM(require("path"));
23504
23757
  var import_os7 = require("os");
23505
23758
  var HOME_OUTBOX_DIR = ".codeam/outbox";
23506
23759
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -23533,16 +23786,16 @@ var FilesOutbox = class {
23533
23786
  backoffIndex = 0;
23534
23787
  stopped = false;
23535
23788
  constructor(opts) {
23536
- const base = opts.baseDir ?? path52.join(homeDir(), HOME_OUTBOX_DIR);
23537
- this.filePath = path52.join(base, `${opts.sessionId}.jsonl`);
23789
+ const base = opts.baseDir ?? path53.join(homeDir(), HOME_OUTBOX_DIR);
23790
+ this.filePath = path53.join(base, `${opts.sessionId}.jsonl`);
23538
23791
  this.post = opts.post;
23539
23792
  this.autoSchedule = opts.autoSchedule !== false;
23540
23793
  }
23541
23794
  /** Persist the entry to disk and trigger a flush. Returns once the
23542
23795
  * line is durable on disk (not once the POST succeeds). */
23543
23796
  async enqueue(entry) {
23544
- await fs45.mkdir(path52.dirname(this.filePath), { recursive: true });
23545
- await fs45.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
23797
+ await fs46.mkdir(path53.dirname(this.filePath), { recursive: true });
23798
+ await fs46.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
23546
23799
  this.backoffIndex = 0;
23547
23800
  if (this.autoSchedule) this.scheduleFlush(0);
23548
23801
  }
@@ -23631,7 +23884,7 @@ var FilesOutbox = class {
23631
23884
  async readAll() {
23632
23885
  let raw = "";
23633
23886
  try {
23634
- raw = await fs45.readFile(this.filePath, "utf8");
23887
+ raw = await fs46.readFile(this.filePath, "utf8");
23635
23888
  } catch {
23636
23889
  return [];
23637
23890
  }
@@ -23655,12 +23908,12 @@ var FilesOutbox = class {
23655
23908
  async rewrite(entries) {
23656
23909
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
23657
23910
  if (entries.length === 0) {
23658
- await fs45.unlink(this.filePath).catch(() => void 0);
23911
+ await fs46.unlink(this.filePath).catch(() => void 0);
23659
23912
  return;
23660
23913
  }
23661
23914
  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);
23915
+ await fs46.writeFile(tmpPath, payload, "utf8");
23916
+ await fs46.rename(tmpPath, this.filePath);
23664
23917
  }
23665
23918
  };
23666
23919
  function applyJitter(ms) {
@@ -25868,15 +26121,15 @@ function fetchQuotaUsage(runtime, historySvc) {
25868
26121
  }
25869
26122
 
25870
26123
  // src/agents/claude/onboarding.ts
25871
- var fs46 = __toESM(require("fs"));
25872
- var os37 = __toESM(require("os"));
25873
- var path53 = __toESM(require("path"));
26124
+ var fs47 = __toESM(require("fs"));
26125
+ var os38 = __toESM(require("os"));
26126
+ var path54 = __toESM(require("path"));
25874
26127
  function ensureClaudeOnboarded() {
25875
26128
  try {
25876
- const file = path53.join(os37.homedir(), ".claude.json");
26129
+ const file = path54.join(os38.homedir(), ".claude.json");
25877
26130
  let config = {};
25878
26131
  try {
25879
- config = JSON.parse(fs46.readFileSync(file, "utf8"));
26132
+ config = JSON.parse(fs47.readFileSync(file, "utf8"));
25880
26133
  } catch {
25881
26134
  }
25882
26135
  if (config.hasCompletedOnboarding === true && typeof config.theme === "string") {
@@ -25887,8 +26140,8 @@ function ensureClaudeOnboarded() {
25887
26140
  if (typeof config.lastOnboardingVersion !== "string") {
25888
26141
  config.lastOnboardingVersion = "2.1.177";
25889
26142
  }
25890
- fs46.mkdirSync(path53.dirname(file), { recursive: true });
25891
- fs46.writeFileSync(file, JSON.stringify(config, null, 2));
26143
+ fs47.mkdirSync(path54.dirname(file), { recursive: true });
26144
+ fs47.writeFileSync(file, JSON.stringify(config, null, 2));
25892
26145
  log.info("claude", "pre-completed Claude onboarding (skip first-run theme picker)");
25893
26146
  } catch (err) {
25894
26147
  log.warn("claude", `ensureClaudeOnboarded failed (non-fatal): ${err.message}`);
@@ -26528,7 +26781,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
26528
26781
  var import_child_process23 = require("child_process");
26529
26782
  var import_util4 = require("util");
26530
26783
  var import_picocolors9 = __toESM(require("picocolors"));
26531
- var path54 = __toESM(require("path"));
26784
+ var path55 = __toESM(require("path"));
26532
26785
  var execFileP6 = (0, import_util4.promisify)(import_child_process23.execFile);
26533
26786
  var MAX_BUFFER = 8 * 1024 * 1024;
26534
26787
  function resetStdinForChild() {
@@ -27017,7 +27270,7 @@ var GitHubCodespacesProvider = class {
27017
27270
  });
27018
27271
  }
27019
27272
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
27020
- const remoteDir = path54.posix.dirname(remotePath);
27273
+ const remoteDir = path55.posix.dirname(remotePath);
27021
27274
  const parts = [
27022
27275
  `mkdir -p ${shellQuote(remoteDir)}`,
27023
27276
  `cat > ${shellQuote(remotePath)}`
@@ -27087,7 +27340,7 @@ function shellQuote(s) {
27087
27340
  // src/services/providers/gitpod.ts
27088
27341
  var import_child_process24 = require("child_process");
27089
27342
  var import_util5 = require("util");
27090
- var path55 = __toESM(require("path"));
27343
+ var path56 = __toESM(require("path"));
27091
27344
  var import_picocolors10 = __toESM(require("picocolors"));
27092
27345
  var execFileP7 = (0, import_util5.promisify)(import_child_process24.execFile);
27093
27346
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -27327,7 +27580,7 @@ var GitpodProvider = class {
27327
27580
  });
27328
27581
  }
27329
27582
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
27330
- const remoteDir = path55.posix.dirname(remotePath);
27583
+ const remoteDir = path56.posix.dirname(remotePath);
27331
27584
  const parts = [
27332
27585
  `mkdir -p ${shellQuote2(remoteDir)}`,
27333
27586
  `cat > ${shellQuote2(remotePath)}`
@@ -27363,7 +27616,7 @@ function shellQuote2(s) {
27363
27616
  // src/services/providers/gitlab-workspaces.ts
27364
27617
  var import_child_process25 = require("child_process");
27365
27618
  var import_util6 = require("util");
27366
- var path56 = __toESM(require("path"));
27619
+ var path57 = __toESM(require("path"));
27367
27620
  var execFileP8 = (0, import_util6.promisify)(import_child_process25.execFile);
27368
27621
  var MAX_BUFFER3 = 8 * 1024 * 1024;
27369
27622
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -27623,7 +27876,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
27623
27876
  }
27624
27877
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
27625
27878
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
27626
- const remoteDir = path56.posix.dirname(remotePath);
27879
+ const remoteDir = path57.posix.dirname(remotePath);
27627
27880
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
27628
27881
  if (options.mode != null) {
27629
27882
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -27691,7 +27944,7 @@ function shellQuote3(s) {
27691
27944
  // src/services/providers/railway.ts
27692
27945
  var import_child_process26 = require("child_process");
27693
27946
  var import_util7 = require("util");
27694
- var path57 = __toESM(require("path"));
27947
+ var path58 = __toESM(require("path"));
27695
27948
  var execFileP9 = (0, import_util7.promisify)(import_child_process26.execFile);
27696
27949
  var MAX_BUFFER4 = 8 * 1024 * 1024;
27697
27950
  function resetStdinForChild4() {
@@ -27927,7 +28180,7 @@ var RailwayProvider = class {
27927
28180
  if (!projectId || !serviceId) {
27928
28181
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
27929
28182
  }
27930
- const remoteDir = path57.posix.dirname(remotePath);
28183
+ const remoteDir = path58.posix.dirname(remotePath);
27931
28184
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
27932
28185
  if (options.mode != null) {
27933
28186
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -28515,8 +28768,8 @@ async function host(args2) {
28515
28768
  var import_node_dns = require("dns");
28516
28769
  var import_node_util5 = require("util");
28517
28770
  var import_node_crypto8 = require("crypto");
28518
- var fs47 = __toESM(require("fs"));
28519
- var path58 = __toESM(require("path"));
28771
+ var fs48 = __toESM(require("fs"));
28772
+ var path59 = __toESM(require("path"));
28520
28773
  var import_picocolors13 = __toESM(require("picocolors"));
28521
28774
  var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
28522
28775
  async function checkDns(apiBase2) {
@@ -28572,13 +28825,13 @@ async function checkHealth(apiBase2) {
28572
28825
  }
28573
28826
  }
28574
28827
  function checkConfigDir() {
28575
- const dir = path58.join(require("os").homedir(), ".codeam");
28828
+ const dir = path59.join(require("os").homedir(), ".codeam");
28576
28829
  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);
28830
+ fs48.mkdirSync(dir, { recursive: true, mode: 448 });
28831
+ const probe = path59.join(dir, ".doctor-probe");
28832
+ fs48.writeFileSync(probe, "ok", { mode: 384 });
28833
+ const read2 = fs48.readFileSync(probe, "utf8");
28834
+ fs48.unlinkSync(probe);
28582
28835
  if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
28583
28836
  return {
28584
28837
  id: "config-dir",
@@ -28618,9 +28871,9 @@ function checkSessions() {
28618
28871
  }
28619
28872
  }
28620
28873
  function checkAgentBinaries() {
28621
- const os39 = createOsStrategy();
28874
+ const os40 = createOsStrategy();
28622
28875
  return getEnabledAgents().map((meta) => {
28623
- const found = os39.findInPath(meta.binaryName);
28876
+ const found = os40.findInPath(meta.binaryName);
28624
28877
  return {
28625
28878
  id: `agent-${meta.id}`,
28626
28879
  label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
@@ -28642,7 +28895,7 @@ function checkNodePty() {
28642
28895
  detail: "not required on this platform"
28643
28896
  };
28644
28897
  }
28645
- const vendoredPath = path58.join(__dirname, "vendor", "node-pty");
28898
+ const vendoredPath = path59.join(__dirname, "vendor", "node-pty");
28646
28899
  for (const target of [vendoredPath, "node-pty"]) {
28647
28900
  try {
28648
28901
  require(target);
@@ -28684,7 +28937,7 @@ function checkChokidar() {
28684
28937
  }
28685
28938
  async function doctor(args2 = []) {
28686
28939
  const json = args2.includes("--json");
28687
- const cliVersion = true ? "2.39.82" : "0.0.0-dev";
28940
+ const cliVersion = true ? "2.39.83" : "0.0.0-dev";
28688
28941
  const apiBase2 = resolveApiBaseUrl();
28689
28942
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
28690
28943
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -28883,7 +29136,7 @@ async function completion(args2) {
28883
29136
  // src/commands/version.ts
28884
29137
  var import_picocolors14 = __toESM(require("picocolors"));
28885
29138
  function version2() {
28886
- const v = true ? "2.39.82" : "unknown";
29139
+ const v = true ? "2.39.83" : "unknown";
28887
29140
  console.log(`${import_picocolors14.default.bold("codeam-cli")} ${import_picocolors14.default.cyan(v)}`);
28888
29141
  }
28889
29142
 
@@ -29027,10 +29280,10 @@ var EXIT_CODE_NAMES = {
29027
29280
  };
29028
29281
 
29029
29282
  // src/index.ts
29030
- var os38 = __toESM(require("os"));
29283
+ var os39 = __toESM(require("os"));
29031
29284
  if (!process.env.HOME) {
29032
29285
  try {
29033
- const home = os38.homedir();
29286
+ const home = os39.homedir();
29034
29287
  if (home) process.env.HOME = home;
29035
29288
  } catch {
29036
29289
  }
@@ -29039,7 +29292,13 @@ loadCodespaceEnv();
29039
29292
  var [, , command, ...args] = process.argv;
29040
29293
  async function main() {
29041
29294
  const isMetaCommand = command === "--version" || command === "-v" || command === "version" || command === "--help" || command === "-h" || command === "help";
29042
- if (!isMetaCommand) checkForUpdates();
29295
+ if (!isMetaCommand) {
29296
+ if (command === "link" || command === "pair") {
29297
+ await autoUpgradeBeforeCriticalCommand();
29298
+ } else {
29299
+ checkForUpdates();
29300
+ }
29301
+ }
29043
29302
  if (initTelemetry()) {
29044
29303
  maybePrintFirstRunBanner();
29045
29304
  capture("cli_boot", { command: command ?? "(default)" });