codeam-cli 2.49.4 → 2.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.js +463 -207
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -522,9 +522,9 @@ var _default = makeConfig();
522
522
  var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, setDisable1mContext, clearAll, saveCliConfig, loadCliConfig } = _default;
523
523
 
524
524
  // src/commands/pair-auto.ts
525
- var fs41 = __toESM(require("fs"));
526
- var os34 = __toESM(require("os"));
527
- var path47 = __toESM(require("path"));
525
+ var fs42 = __toESM(require("fs"));
526
+ var os35 = __toESM(require("os"));
527
+ var path48 = __toESM(require("path"));
528
528
  var import_crypto4 = require("crypto");
529
529
 
530
530
  // src/services/telemetry.service.ts
@@ -560,8 +560,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
560
560
  return decodedFile;
561
561
  };
562
562
  }
563
- function normalizeWindowsPath(path60) {
564
- return path60.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
563
+ function normalizeWindowsPath(path61) {
564
+ return path61.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
565
565
  }
566
566
 
567
567
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -3041,9 +3041,9 @@ async function addSourceContext(frames) {
3041
3041
  LRU_FILE_CONTENTS_CACHE.reduce();
3042
3042
  return frames;
3043
3043
  }
3044
- function getContextLinesFromFile(path60, ranges, output) {
3044
+ function getContextLinesFromFile(path61, ranges, output) {
3045
3045
  return new Promise((resolve7) => {
3046
- const stream = (0, import_node_fs.createReadStream)(path60);
3046
+ const stream = (0, import_node_fs.createReadStream)(path61);
3047
3047
  const lineReaded = (0, import_node_readline.createInterface)({
3048
3048
  input: stream
3049
3049
  });
@@ -3058,7 +3058,7 @@ function getContextLinesFromFile(path60, ranges, output) {
3058
3058
  let rangeStart = range[0];
3059
3059
  let rangeEnd = range[1];
3060
3060
  function onStreamError() {
3061
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path60, 1);
3061
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path61, 1);
3062
3062
  lineReaded.close();
3063
3063
  lineReaded.removeAllListeners();
3064
3064
  destroyStreamAndResolve();
@@ -3119,8 +3119,8 @@ function clearLineContext(frame) {
3119
3119
  delete frame.context_line;
3120
3120
  delete frame.post_context;
3121
3121
  }
3122
- function shouldSkipContextLinesForFile(path60) {
3123
- return path60.startsWith("node:") || path60.endsWith(".min.js") || path60.endsWith(".min.cjs") || path60.endsWith(".min.mjs") || path60.startsWith("data:");
3122
+ function shouldSkipContextLinesForFile(path61) {
3123
+ return path61.startsWith("node:") || path61.endsWith(".min.js") || path61.endsWith(".min.cjs") || path61.endsWith(".min.mjs") || path61.startsWith("data:");
3124
3124
  }
3125
3125
  function shouldSkipContextLinesForFrame(frame) {
3126
3126
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -5397,7 +5397,7 @@ function readAnonId() {
5397
5397
  }
5398
5398
  function superProperties() {
5399
5399
  return {
5400
- cliVersion: true ? "2.49.4" : "0.0.0-dev",
5400
+ cliVersion: true ? "2.50.0" : "0.0.0-dev",
5401
5401
  nodeVersion: process.version,
5402
5402
  platform: process.platform,
5403
5403
  arch: process.arch,
@@ -5578,7 +5578,7 @@ var os4 = __toESM(require("os"));
5578
5578
  // package.json
5579
5579
  var package_default = {
5580
5580
  name: "codeam-cli",
5581
- version: "2.49.4",
5581
+ version: "2.50.0",
5582
5582
  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.",
5583
5583
  type: "commonjs",
5584
5584
  main: "dist/index.js",
@@ -5871,6 +5871,28 @@ async function postHeadroomEvent(input) {
5871
5871
  };
5872
5872
  }
5873
5873
  }
5874
+ async function postBeadsEvent(input) {
5875
+ try {
5876
+ await _transport.postJsonAuthed(
5877
+ `${API_BASE}/api/beads/events`,
5878
+ {
5879
+ sessionId: input.sessionId,
5880
+ pluginId: input.pluginId,
5881
+ type: input.type,
5882
+ payload: input.payload ?? {}
5883
+ },
5884
+ input.pluginAuthToken
5885
+ );
5886
+ return { ok: true };
5887
+ } catch (err) {
5888
+ const e = err;
5889
+ return {
5890
+ ok: false,
5891
+ status: typeof e.statusCode === "number" ? e.statusCode : 0,
5892
+ message: e.message || "unknown"
5893
+ };
5894
+ }
5895
+ }
5874
5896
  async function postBeadsProvisioning(input) {
5875
5897
  try {
5876
5898
  await _transport.postJsonAuthed(
@@ -7706,9 +7728,9 @@ function closeAllTerminals() {
7706
7728
  }
7707
7729
 
7708
7730
  // src/commands/start/handlers.ts
7709
- var fs40 = __toESM(require("fs"));
7710
- var os33 = __toESM(require("os"));
7711
- var path46 = __toESM(require("path"));
7731
+ var fs41 = __toESM(require("fs"));
7732
+ var os34 = __toESM(require("os"));
7733
+ var path47 = __toESM(require("path"));
7712
7734
  var import_crypto3 = require("crypto");
7713
7735
  var import_child_process20 = require("child_process");
7714
7736
  var import_which2 = __toESM(require("which"));
@@ -11142,10 +11164,10 @@ function buildForPlatform(platform3) {
11142
11164
  var import_node_crypto4 = require("crypto");
11143
11165
 
11144
11166
  // src/agents/claude/resolver.ts
11145
- function buildClaudeLaunch(extraArgs = [], os40 = createOsStrategy()) {
11146
- const found = os40.findInPath("claude") ?? os40.findInPath("claude-code");
11167
+ function buildClaudeLaunch(extraArgs = [], os41 = createOsStrategy()) {
11168
+ const found = os41.findInPath("claude") ?? os41.findInPath("claude-code");
11147
11169
  if (!found) return null;
11148
- return os40.buildLaunch(found, extraArgs);
11170
+ return os41.buildLaunch(found, extraArgs);
11149
11171
  }
11150
11172
 
11151
11173
  // src/agents/claude/installer.ts
@@ -11738,8 +11760,8 @@ var ClaudeRuntimeStrategy = class {
11738
11760
  meta = getAgent("claude");
11739
11761
  mode = "interactive";
11740
11762
  os;
11741
- constructor(os40) {
11742
- this.os = os40;
11763
+ constructor(os41) {
11764
+ this.os = os41;
11743
11765
  }
11744
11766
  /**
11745
11767
  * Claude Code's react-ink TUI enables bracketed-paste mode at
@@ -12416,8 +12438,8 @@ function codexCredentialLocator() {
12416
12438
  function codexLoginLauncher() {
12417
12439
  return {
12418
12440
  async ensureInstalled() {
12419
- const os40 = createOsStrategy();
12420
- return os40.findInPath("codex") !== null;
12441
+ const os41 = createOsStrategy();
12442
+ return os41.findInPath("codex") !== null;
12421
12443
  },
12422
12444
  launch() {
12423
12445
  return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
@@ -12440,8 +12462,8 @@ var CodexRuntimeStrategy = class {
12440
12462
  meta = getAgent("codex");
12441
12463
  mode = "interactive";
12442
12464
  os;
12443
- constructor(os40) {
12444
- this.os = os40;
12465
+ constructor(os41) {
12466
+ this.os = os41;
12445
12467
  }
12446
12468
  async prepareLaunch() {
12447
12469
  let binary = this.os.findInPath("codex");
@@ -12540,12 +12562,12 @@ var CodexRuntimeStrategy = class {
12540
12562
  });
12541
12563
  }
12542
12564
  };
12543
- function resolveNpm(os40) {
12544
- return os40.id === "win32" ? "npm.cmd" : "npm";
12565
+ function resolveNpm(os41) {
12566
+ return os41.id === "win32" ? "npm.cmd" : "npm";
12545
12567
  }
12546
- async function installCodexViaNpm(os40) {
12568
+ async function installCodexViaNpm(os41) {
12547
12569
  return new Promise((resolve7, reject) => {
12548
- const proc = (0, import_node_child_process4.spawn)(resolveNpm(os40), ["install", "-g", "@openai/codex"], {
12570
+ const proc = (0, import_node_child_process4.spawn)(resolveNpm(os41), ["install", "-g", "@openai/codex"], {
12549
12571
  stdio: "inherit"
12550
12572
  });
12551
12573
  proc.on("close", (code) => {
@@ -12562,16 +12584,16 @@ async function installCodexViaNpm(os40) {
12562
12584
  });
12563
12585
  });
12564
12586
  }
12565
- function augmentNpmGlobalBin(os40) {
12587
+ function augmentNpmGlobalBin(os41) {
12566
12588
  try {
12567
- const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os40), ["prefix", "-g"], {
12589
+ const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os41), ["prefix", "-g"], {
12568
12590
  stdio: ["ignore", "pipe", "ignore"]
12569
12591
  });
12570
12592
  if (result.status !== 0) return;
12571
12593
  const prefix = result.stdout.toString().trim();
12572
12594
  if (!prefix) return;
12573
- const binDir = os40.id === "win32" ? prefix : path22.join(prefix, "bin");
12574
- os40.augmentPath([binDir]);
12595
+ const binDir = os41.id === "win32" ? prefix : path22.join(prefix, "bin");
12596
+ os41.augmentPath([binDir]);
12575
12597
  } catch {
12576
12598
  }
12577
12599
  }
@@ -12655,9 +12677,9 @@ var import_node_child_process7 = require("child_process");
12655
12677
  // src/agents/coderabbit/installer.ts
12656
12678
  var import_node_child_process5 = require("child_process");
12657
12679
  var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
12658
- async function ensureCoderabbitInstalled(os40) {
12659
- if (os40.findInPath("coderabbit")) return true;
12660
- if (os40.id === "win32") {
12680
+ async function ensureCoderabbitInstalled(os41) {
12681
+ if (os41.findInPath("coderabbit")) return true;
12682
+ if (os41.id === "win32") {
12661
12683
  console.error(
12662
12684
  "\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"
12663
12685
  );
@@ -12672,8 +12694,8 @@ async function ensureCoderabbitInstalled(os40) {
12672
12694
  proc.on("error", () => resolve7(false));
12673
12695
  });
12674
12696
  if (!ok) return false;
12675
- os40.augmentPath([`${os40.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
12676
- return os40.findInPath("coderabbit") !== null;
12697
+ os41.augmentPath([`${os41.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
12698
+ return os41.findInPath("coderabbit") !== null;
12677
12699
  }
12678
12700
 
12679
12701
  // src/agents/coderabbit/link.ts
@@ -12708,10 +12730,10 @@ function coderabbitCredentialLocator() {
12708
12730
  validate: validateNonEmptyCredential
12709
12731
  };
12710
12732
  }
12711
- function coderabbitLoginLauncher(os40) {
12733
+ function coderabbitLoginLauncher(os41) {
12712
12734
  return {
12713
12735
  async ensureInstalled() {
12714
- return ensureCoderabbitInstalled(os40);
12736
+ return ensureCoderabbitInstalled(os41);
12715
12737
  },
12716
12738
  launch() {
12717
12739
  return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
@@ -12734,11 +12756,11 @@ function parseReview(stdout) {
12734
12756
  for (const line of lines) {
12735
12757
  const m = line.match(HUNK_LINE_RE);
12736
12758
  if (!m) continue;
12737
- const [, path60, lineNo, sevToken, message] = m;
12738
- if (!path60 || !lineNo || !message) continue;
12759
+ const [, path61, lineNo, sevToken, message] = m;
12760
+ if (!path61 || !lineNo || !message) continue;
12739
12761
  const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
12740
12762
  hunks.push({
12741
- path: path60.trim(),
12763
+ path: path61.trim(),
12742
12764
  line: Number(lineNo),
12743
12765
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
12744
12766
  message: cleanedMessage
@@ -12757,8 +12779,8 @@ var CoderabbitRuntimeStrategy = class {
12757
12779
  meta = getAgent("coderabbit");
12758
12780
  mode = "batch";
12759
12781
  os;
12760
- constructor(os40) {
12761
- this.os = os40;
12782
+ constructor(os41) {
12783
+ this.os = os41;
12762
12784
  }
12763
12785
  getDefaultArgs() {
12764
12786
  return ["review"];
@@ -12874,10 +12896,10 @@ function cursorCredentialLocator() {
12874
12896
  validate: validateNonEmptyCredential
12875
12897
  };
12876
12898
  }
12877
- function cursorLoginLauncher(os40) {
12899
+ function cursorLoginLauncher(os41) {
12878
12900
  return {
12879
12901
  async ensureInstalled() {
12880
- if (os40.findInPath("cursor-agent")) return true;
12902
+ if (os41.findInPath("cursor-agent")) return true;
12881
12903
  console.error(
12882
12904
  "\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"
12883
12905
  );
@@ -12939,8 +12961,8 @@ var CursorRuntimeStrategy = class {
12939
12961
  meta = getAgent("cursor");
12940
12962
  mode = "interactive";
12941
12963
  os;
12942
- constructor(os40) {
12943
- this.os = os40;
12964
+ constructor(os41) {
12965
+ this.os = os41;
12944
12966
  }
12945
12967
  async prepareLaunch() {
12946
12968
  const binary = this.os.findInPath("cursor-agent");
@@ -13079,10 +13101,10 @@ function aiderCredentialLocator() {
13079
13101
  validate: validateNonEmptyCredential
13080
13102
  };
13081
13103
  }
13082
- function aiderLoginLauncher(os40) {
13104
+ function aiderLoginLauncher(os41) {
13083
13105
  return {
13084
13106
  async ensureInstalled() {
13085
- if (os40.findInPath("aider")) return true;
13107
+ if (os41.findInPath("aider")) return true;
13086
13108
  console.error(
13087
13109
  "\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
13088
13110
  );
@@ -13092,7 +13114,7 @@ function aiderLoginLauncher(os40) {
13092
13114
  console.error(
13093
13115
  "\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"
13094
13116
  );
13095
- return (0, import_node_child_process9.spawn)(os40.id === "win32" ? "cmd.exe" : "sh", os40.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
13117
+ return (0, import_node_child_process9.spawn)(os41.id === "win32" ? "cmd.exe" : "sh", os41.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
13096
13118
  stdio: "ignore"
13097
13119
  });
13098
13120
  }
@@ -13164,8 +13186,8 @@ var AiderRuntimeStrategy = class {
13164
13186
  meta = getAgent("aider");
13165
13187
  mode = "interactive";
13166
13188
  os;
13167
- constructor(os40) {
13168
- this.os = os40;
13189
+ constructor(os41) {
13190
+ this.os = os41;
13169
13191
  }
13170
13192
  async prepareLaunch() {
13171
13193
  const binary = this.os.findInPath("aider");
@@ -13294,8 +13316,8 @@ function geminiCredentialLocator() {
13294
13316
  function geminiLoginLauncher() {
13295
13317
  return {
13296
13318
  async ensureInstalled() {
13297
- const os40 = createOsStrategy();
13298
- return os40.findInPath("gemini") !== null;
13319
+ const os41 = createOsStrategy();
13320
+ return os41.findInPath("gemini") !== null;
13299
13321
  },
13300
13322
  launch() {
13301
13323
  return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
@@ -13328,8 +13350,8 @@ var GeminiRuntimeStrategy = class {
13328
13350
  meta = getAgent("gemini");
13329
13351
  mode = "interactive";
13330
13352
  os;
13331
- constructor(os40) {
13332
- this.os = os40;
13353
+ constructor(os41) {
13354
+ this.os = os41;
13333
13355
  }
13334
13356
  async prepareLaunch() {
13335
13357
  const binary = this.os.findInPath("gemini");
@@ -13428,18 +13450,18 @@ var GeminiRuntimeStrategy = class {
13428
13450
 
13429
13451
  // src/agents/registry.ts
13430
13452
  var runtimeBuilders = {
13431
- claude: (os40) => new ClaudeRuntimeStrategy(os40),
13432
- codex: (os40) => new CodexRuntimeStrategy(os40),
13433
- coderabbit: (os40) => new CoderabbitRuntimeStrategy(os40),
13434
- cursor: (os40) => new CursorRuntimeStrategy(os40),
13435
- aider: (os40) => new AiderRuntimeStrategy(os40),
13436
- gemini: (os40) => new GeminiRuntimeStrategy(os40)
13453
+ claude: (os41) => new ClaudeRuntimeStrategy(os41),
13454
+ codex: (os41) => new CodexRuntimeStrategy(os41),
13455
+ coderabbit: (os41) => new CoderabbitRuntimeStrategy(os41),
13456
+ cursor: (os41) => new CursorRuntimeStrategy(os41),
13457
+ aider: (os41) => new AiderRuntimeStrategy(os41),
13458
+ gemini: (os41) => new GeminiRuntimeStrategy(os41)
13437
13459
  };
13438
13460
  var deployBuilders = {
13439
13461
  claude: () => new ClaudeDeployStrategy(),
13440
13462
  codex: () => new CodexDeployStrategy()
13441
13463
  };
13442
- function createAgentStrategy(agent, os40 = createOsStrategy()) {
13464
+ function createAgentStrategy(agent, os41 = createOsStrategy()) {
13443
13465
  if (!AGENT_REGISTRY[agent]?.enabled) {
13444
13466
  throw new Error(
13445
13467
  `Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
@@ -13449,10 +13471,10 @@ function createAgentStrategy(agent, os40 = createOsStrategy()) {
13449
13471
  if (!build) {
13450
13472
  throw new Error(`No runtime strategy registered for agent "${agent}"`);
13451
13473
  }
13452
- return build(os40);
13474
+ return build(os41);
13453
13475
  }
13454
- function createInteractiveAgentStrategy(agent, os40 = createOsStrategy()) {
13455
- const s = createAgentStrategy(agent, os40);
13476
+ function createInteractiveAgentStrategy(agent, os41 = createOsStrategy()) {
13477
+ const s = createAgentStrategy(agent, os41);
13456
13478
  if (s.mode !== "interactive") {
13457
13479
  throw new Error(
13458
13480
  `Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
@@ -14747,7 +14769,7 @@ async function autoUpgradeBeforeCriticalCommand() {
14747
14769
  if (process.env.NODE_ENV === "test") return;
14748
14770
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
14749
14771
  if (process.env.CI) return;
14750
- const current = true ? "2.49.4" : null;
14772
+ const current = true ? "2.50.0" : null;
14751
14773
  if (!current) return;
14752
14774
  const cache = readCache();
14753
14775
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -14764,7 +14786,7 @@ function checkForUpdates() {
14764
14786
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
14765
14787
  if (process.env.CI) return;
14766
14788
  if (!process.stdout.isTTY) return;
14767
- const current = true ? "2.49.4" : null;
14789
+ const current = true ? "2.50.0" : null;
14768
14790
  if (!current) return;
14769
14791
  const cache = readCache();
14770
14792
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -14827,6 +14849,51 @@ function maybeStartHeadroomReporter(ctx) {
14827
14849
  return null;
14828
14850
  }
14829
14851
  }
14852
+ function maybeResumeLocalHeadroomReporter(ctx) {
14853
+ if (process.env["HEADROOM_ENABLED"] === "1") return null;
14854
+ try {
14855
+ const file = headroomConfigPath();
14856
+ if (!fs31.existsSync(file)) return null;
14857
+ const cfg = JSON.parse(fs31.readFileSync(file, "utf8"));
14858
+ if (!cfg?.enabled) return null;
14859
+ const agent = cfg.agent ?? "claude";
14860
+ const ingestUrl = `${resolveApiBaseUrl()}/api/sessions/${ctx.sessionId}/headroom-savings`;
14861
+ const reporter = new HeadroomStatsReporter({
14862
+ inputPricePerMillionUsd: resolveInputPricePerMillion(agent),
14863
+ fetchStats: async () => {
14864
+ const res = await fetch("http://localhost:8787/stats");
14865
+ return res.json();
14866
+ },
14867
+ // Body MUST match HeadroomSavingsDto + PluginAuthGuard (sessionId +
14868
+ // pluginId in the body) — same shape as the codespace reporter above and
14869
+ // the on-demand `startReporter` in handlers.ts.
14870
+ postSavings: async (delta) => {
14871
+ await fetch(ingestUrl, {
14872
+ method: "POST",
14873
+ headers: {
14874
+ "Content-Type": "application/json",
14875
+ "X-Plugin-Auth-Token": ctx.pluginAuthToken
14876
+ },
14877
+ body: JSON.stringify({
14878
+ sessionId: ctx.sessionId,
14879
+ pluginId: ctx.pluginId,
14880
+ agentId: agent,
14881
+ savings: delta
14882
+ })
14883
+ });
14884
+ }
14885
+ });
14886
+ reporter.start();
14887
+ log.info("headroom", "resumed on-demand local savings reporter from config");
14888
+ return reporter;
14889
+ } catch (err) {
14890
+ log.warn(
14891
+ "headroom",
14892
+ `failed to resume local Headroom reporter (best-effort): ${err instanceof Error ? err.message : String(err)}`
14893
+ );
14894
+ return null;
14895
+ }
14896
+ }
14830
14897
  function isRefreshCredentialsPayload(p2) {
14831
14898
  return typeof p2.agentId === "string" && typeof p2.sealedAgentAuth === "string";
14832
14899
  }
@@ -15400,7 +15467,7 @@ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process14.s
15400
15467
  detached: false
15401
15468
  });
15402
15469
  function currentCliVersion() {
15403
- return true ? "2.49.4" : null;
15470
+ return true ? "2.50.0" : null;
15404
15471
  }
15405
15472
  function runCmd(cmd, args2, timeoutMs) {
15406
15473
  return new Promise((resolve7) => {
@@ -17081,11 +17148,11 @@ function resolveDoltInstallStrategy(platform3) {
17081
17148
  }
17082
17149
  var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
17083
17150
  function doltPlatformTuple(platform3, arch2) {
17084
- const os40 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
17151
+ const os41 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
17085
17152
  const a = arch2 === "x64" ? "amd64" : arch2 === "arm64" ? "arm64" : null;
17086
17153
  if (!a) return null;
17087
- if (os40 === "windows" && a !== "amd64") return null;
17088
- return `${os40}-${a}`;
17154
+ if (os41 === "windows" && a !== "amd64") return null;
17155
+ return `${os41}-${a}`;
17089
17156
  }
17090
17157
  function resolveDoltTarballStrategy(targetDir, platform3, arch2) {
17091
17158
  const tuple = doltPlatformTuple(platform3, arch2);
@@ -17964,6 +18031,30 @@ async function handleBeadsActionCommand(action, started) {
17964
18031
  });
17965
18032
  }
17966
18033
 
18034
+ // src/beads/config-store.ts
18035
+ var import_node_fs5 = __toESM(require("fs"));
18036
+ var import_node_os3 = __toESM(require("os"));
18037
+ var import_node_path4 = __toESM(require("path"));
18038
+ function beadsConfigPath() {
18039
+ return import_node_path4.default.join(import_node_os3.default.homedir(), ".codeam", "beads-config.json");
18040
+ }
18041
+ function readBeadsEnabled() {
18042
+ try {
18043
+ const raw = import_node_fs5.default.readFileSync(beadsConfigPath(), "utf8");
18044
+ const cfg = JSON.parse(raw);
18045
+ return cfg.enabled !== false;
18046
+ } catch {
18047
+ return true;
18048
+ }
18049
+ }
18050
+ function persistBeadsConfig(cfg) {
18051
+ const file = beadsConfigPath();
18052
+ import_node_fs5.default.mkdirSync(import_node_path4.default.dirname(file), { recursive: true });
18053
+ const tmp = `${file}.tmp`;
18054
+ import_node_fs5.default.writeFileSync(tmp, JSON.stringify(cfg), { mode: 384 });
18055
+ import_node_fs5.default.renameSync(tmp, file);
18056
+ }
18057
+
17967
18058
  // src/beads/wiring.ts
17968
18059
  function beadsKilled() {
17969
18060
  const v = process.env.CODEAM_BEADS_DISABLED;
@@ -17974,6 +18065,10 @@ async function provisionBeadsForStart(ctx) {
17974
18065
  log.trace("beads", "CODEAM_BEADS_DISABLED set \u2014 beads off this run");
17975
18066
  return null;
17976
18067
  }
18068
+ if (readBeadsEnabled() === false) {
18069
+ log.trace("beads", "beads disabled by persisted config \u2014 beads off this run");
18070
+ return null;
18071
+ }
17977
18072
  delete process.env.BEADS_DIR;
17978
18073
  process.env.BEADS_DOLT_SHARED_SERVER = "1";
17979
18074
  if (!ctx.pluginAuthToken) {
@@ -18034,12 +18129,69 @@ function beadsActionFromPayload(payload) {
18034
18129
  };
18035
18130
  }
18036
18131
 
18132
+ // src/beads/configure.ts
18133
+ var _probeSeam = {
18134
+ resolveBd: (cwd) => new BdAdapter({ cwd }).isAvailable(),
18135
+ doltOnPath: () => ensureDoltResolvable(),
18136
+ ping: async (cwd) => {
18137
+ const adapter = new BdAdapter({ cwd });
18138
+ if (!adapter.isAvailable()) return false;
18139
+ const r = await adapter.run(["ping"]);
18140
+ return r.code === 0;
18141
+ },
18142
+ derivePrefix: (cwd) => {
18143
+ try {
18144
+ const { projectKey } = deriveProjectIdentity(cwd);
18145
+ return prefixForProjectKey(projectKey);
18146
+ } catch {
18147
+ return null;
18148
+ }
18149
+ }
18150
+ };
18151
+ async function probeBeadsStatus(cwd = process.cwd()) {
18152
+ const bdAvailable = _probeSeam.resolveBd(cwd);
18153
+ const doltAvailable = _probeSeam.doltOnPath();
18154
+ const serverUp = bdAvailable && doltAvailable ? await _probeSeam.ping(cwd) : false;
18155
+ const prefix = _probeSeam.derivePrefix(cwd);
18156
+ return { bdAvailable, doltAvailable, serverUp, prefix };
18157
+ }
18158
+ async function configureBeads(action, ctx, deps) {
18159
+ if (action === "status") {
18160
+ if (deps.readEnabled() === false) {
18161
+ deps.emit({ type: "beads_status", state: "disabled", running: false });
18162
+ return { enabled: false, running: false };
18163
+ }
18164
+ const p3 = await deps.probe();
18165
+ const running2 = p3.serverUp && p3.bdAvailable;
18166
+ deps.emit({ type: "beads_status", state: running2 ? "enabled" : "disabled", running: running2, ...p3 });
18167
+ return { enabled: running2, running: running2, ...p3 };
18168
+ }
18169
+ if (action === "disable") {
18170
+ deps.persist({ enabled: false });
18171
+ await deps.stopWatcher().catch(() => void 0);
18172
+ await deps.revertAgentHook(ctx.agent).catch(() => void 0);
18173
+ deps.emit({ type: "beads_status", state: "disabled" });
18174
+ return { enabled: false };
18175
+ }
18176
+ deps.persist({ enabled: true });
18177
+ deps.emit({ type: "beads_status", state: "provisioning" });
18178
+ const p2 = await deps.provision();
18179
+ if (!p2.serverUp || !p2.bdAvailable) {
18180
+ deps.emit({ type: "beads_status", state: "error", error: "Beads provisioning failed", ...p2 });
18181
+ return { enabled: false, ...p2 };
18182
+ }
18183
+ await deps.startWatcher().catch(() => void 0);
18184
+ const running = true;
18185
+ deps.emit({ type: "beads_status", state: "enabled", running, ...p2 });
18186
+ return { enabled: true, running, ...p2 };
18187
+ }
18188
+
18037
18189
  // src/commands/start/handlers.ts
18038
18190
  var pendingAttachmentFiles = /* @__PURE__ */ new Set();
18039
18191
  function cleanupAttachmentTempFiles() {
18040
18192
  for (const p2 of pendingAttachmentFiles) {
18041
18193
  try {
18042
- fs40.unlinkSync(p2);
18194
+ fs41.unlinkSync(p2);
18043
18195
  } catch {
18044
18196
  }
18045
18197
  }
@@ -18048,8 +18200,8 @@ function cleanupAttachmentTempFiles() {
18048
18200
  function saveFilesTemp(files) {
18049
18201
  return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
18050
18202
  const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
18051
- const tmpPath = path46.join(os33.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
18052
- fs40.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
18203
+ const tmpPath = path47.join(os34.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
18204
+ fs41.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
18053
18205
  pendingAttachmentFiles.add(tmpPath);
18054
18206
  return tmpPath;
18055
18207
  });
@@ -18069,7 +18221,7 @@ var startTask = (ctx, _cmd, parsed) => {
18069
18221
  setTimeout(() => {
18070
18222
  for (const p2 of paths) {
18071
18223
  try {
18072
- fs40.unlinkSync(p2);
18224
+ fs41.unlinkSync(p2);
18073
18225
  } catch {
18074
18226
  }
18075
18227
  pendingAttachmentFiles.delete(p2);
@@ -18270,9 +18422,9 @@ var listFiles = async (ctx, cmd, parsed) => {
18270
18422
  await ctx.relay.sendResult(cmd.id, "completed", result);
18271
18423
  };
18272
18424
  var envReadH = async (ctx, cmd) => {
18273
- const envPath = path46.join(process.cwd(), ".env");
18425
+ const envPath = path47.join(process.cwd(), ".env");
18274
18426
  try {
18275
- const raw = await fs40.promises.readFile(envPath, "utf8");
18427
+ const raw = await fs41.promises.readFile(envPath, "utf8");
18276
18428
  await ctx.relay.sendResult(cmd.id, "completed", {
18277
18429
  exists: true,
18278
18430
  vars: parseDotenv(raw)
@@ -18303,14 +18455,14 @@ var envWriteH = async (ctx, cmd, parsed) => {
18303
18455
  }
18304
18456
  seen.add(v.key);
18305
18457
  }
18306
- const envPath = path46.join(process.cwd(), ".env");
18307
- const tmpPath = path46.join(process.cwd(), ".env.codeam.tmp");
18458
+ const envPath = path47.join(process.cwd(), ".env");
18459
+ const tmpPath = path47.join(process.cwd(), ".env.codeam.tmp");
18308
18460
  try {
18309
- await fs40.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
18310
- await fs40.promises.rename(tmpPath, envPath);
18461
+ await fs41.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
18462
+ await fs41.promises.rename(tmpPath, envPath);
18311
18463
  await ctx.relay.sendResult(cmd.id, "completed", { ok: true, count: vars.length });
18312
18464
  } catch (err) {
18313
- await fs40.promises.rm(tmpPath, { force: true }).catch(() => void 0);
18465
+ await fs41.promises.rm(tmpPath, { force: true }).catch(() => void 0);
18314
18466
  await ctx.relay.sendResult(cmd.id, "failed", { error: err.message });
18315
18467
  }
18316
18468
  };
@@ -18328,7 +18480,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
18328
18480
  let configuredAgent = rawAgentId;
18329
18481
  if (!configuredAgent) {
18330
18482
  try {
18331
- const raw = JSON.parse(fs40.readFileSync(headroomConfigPath(), "utf8"));
18483
+ const raw = JSON.parse(fs41.readFileSync(headroomConfigPath(), "utf8"));
18332
18484
  configuredAgent = raw.agent ?? "";
18333
18485
  } catch {
18334
18486
  }
@@ -18362,7 +18514,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
18362
18514
  persist: persistHeadroomConfig,
18363
18515
  readEnabled: () => {
18364
18516
  try {
18365
- const raw = JSON.parse(fs40.readFileSync(headroomConfigPath(), "utf8"));
18517
+ const raw = JSON.parse(fs41.readFileSync(headroomConfigPath(), "utf8"));
18366
18518
  return raw.enabled === true;
18367
18519
  } catch {
18368
18520
  return false;
@@ -18383,7 +18535,19 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
18383
18535
  "Content-Type": "application/json",
18384
18536
  ...opts.pluginAuthToken ? { "X-Plugin-Auth-Token": opts.pluginAuthToken } : {}
18385
18537
  },
18386
- body: JSON.stringify({ agentId: opts.agent, ...delta })
18538
+ // Body MUST match HeadroomSavingsDto + PluginAuthGuard, which read
18539
+ // `sessionId` + `pluginId` from the body and 401 if either is
18540
+ // missing. Mirror the self-hosted reporter in host-agent.ts exactly.
18541
+ // Previously this sent `{ agentId, ...delta }` (no sessionId/pluginId,
18542
+ // delta spread flat instead of nested under `savings`) → every POST
18543
+ // was rejected 401 at the guard and silently swallowed (fetch status
18544
+ // unchecked), so local on-demand savings never reached the backend.
18545
+ body: JSON.stringify({
18546
+ sessionId: ctx.sessionId,
18547
+ pluginId: ctx.pluginId,
18548
+ agentId: opts.agent,
18549
+ savings: delta
18550
+ })
18387
18551
  });
18388
18552
  }
18389
18553
  });
@@ -18423,6 +18587,65 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
18423
18587
  });
18424
18588
  await ctx.relay.sendResult(cmd.id, "completed", result);
18425
18589
  };
18590
+ var _beadsEmitChain = Promise.resolve();
18591
+ var beadsConfigureH = async (ctx, cmd, parsed) => {
18592
+ const action = parsed.action;
18593
+ if (action !== "enable" && action !== "disable" && action !== "status") {
18594
+ await ctx.relay.sendResult(cmd.id, "failed", { error: "action must be enable|disable|status" });
18595
+ return;
18596
+ }
18597
+ let rawAgentId = ctx.agentId || (typeof parsed.agentId === "string" ? parsed.agentId : "");
18598
+ if (rawAgentId === "claude_code") rawAgentId = "claude";
18599
+ const agentIds = rawAgentId && isKnownAgentId(rawAgentId) ? [rawAgentId] : [];
18600
+ const deps = {
18601
+ provision: async () => {
18602
+ const r = await provisionBeads({ cwd: process.cwd(), agents: agentIds });
18603
+ return { bdAvailable: r.bdAvailable, doltAvailable: r.doltAvailable, serverUp: r.serverUp, prefix: r.prefix };
18604
+ },
18605
+ probe: async () => probeBeadsStatus(process.cwd()),
18606
+ startWatcher: async () => {
18607
+ if (!ctx.pluginAuthToken) return;
18608
+ const started = await startBeads({
18609
+ sessionId: ctx.sessionId,
18610
+ pluginId: ctx.pluginId,
18611
+ pluginAuthToken: ctx.pluginAuthToken,
18612
+ cwd: process.cwd(),
18613
+ agents: agentIds
18614
+ });
18615
+ if (started) {
18616
+ ctx.beads = started;
18617
+ }
18618
+ },
18619
+ stopWatcher: async () => {
18620
+ if (ctx.beads) {
18621
+ await ctx.beads.watcher.stop();
18622
+ ctx.beads = null;
18623
+ }
18624
+ },
18625
+ revertAgentHook: async (agent) => {
18626
+ log.info("beads", `revertAgentHook: bd has no --remove flag \u2014 leaving ${agent} hook in place (no-op disable path)`);
18627
+ },
18628
+ persist: (cfg) => persistBeadsConfig(cfg),
18629
+ readEnabled: () => readBeadsEnabled(),
18630
+ emit: (event) => {
18631
+ const token = ctx.pluginAuthToken;
18632
+ if (!token) return;
18633
+ _beadsEmitChain = _beadsEmitChain.then(
18634
+ () => postBeadsEvent({
18635
+ sessionId: ctx.sessionId,
18636
+ pluginId: ctx.pluginId,
18637
+ pluginAuthToken: token,
18638
+ type: "beads_status",
18639
+ payload: Object.fromEntries(
18640
+ Object.entries(event).filter(([k2]) => k2 !== "type")
18641
+ )
18642
+ })
18643
+ );
18644
+ }
18645
+ };
18646
+ const result = await configureBeads(action, { agent: rawAgentId, cwd: process.cwd(), pluginAuthToken: ctx.pluginAuthToken }, deps);
18647
+ await ctx.relay.sendResult(cmd.id, "completed", result);
18648
+ };
18426
18649
  var terminalOpenH = async (ctx, cmd, parsed) => {
18427
18650
  const r = openTerminal({
18428
18651
  cols: typeof parsed.cols === "number" ? parsed.cols : void 0,
@@ -18859,8 +19082,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
18859
19082
  if (args2.length === 0) return detection;
18860
19083
  const binName = args2[0];
18861
19084
  if (binName.startsWith("-")) return detection;
18862
- const binPath = path46.join(cwd, "node_modules", ".bin", binName);
18863
- if (!fs40.existsSync(binPath)) return detection;
19085
+ const binPath = path47.join(cwd, "node_modules", ".bin", binName);
19086
+ if (!fs41.existsSync(binPath)) return detection;
18864
19087
  return {
18865
19088
  ...detection,
18866
19089
  command: binPath,
@@ -19408,7 +19631,8 @@ var handlers = {
19408
19631
  save_preview_config: savePreviewConfigH,
19409
19632
  env_read: envReadH,
19410
19633
  env_write: envWriteH,
19411
- headroom_configure: headroomConfigureH
19634
+ headroom_configure: headroomConfigureH,
19635
+ beads_configure: beadsConfigureH
19412
19636
  };
19413
19637
  async function dispatchCommand(ctx, cmd) {
19414
19638
  if (cmd.type === "beads_action") {
@@ -19676,12 +19900,12 @@ function readTokenFromArgs(args2) {
19676
19900
  }
19677
19901
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
19678
19902
  if (fileFlag) {
19679
- const path60 = fileFlag.slice("--token-file=".length);
19903
+ const path61 = fileFlag.slice("--token-file=".length);
19680
19904
  try {
19681
- const content = fs41.readFileSync(path60, "utf8").trim();
19682
- if (content.length === 0) fail(`--token-file ${path60} is empty`);
19905
+ const content = fs42.readFileSync(path61, "utf8").trim();
19906
+ if (content.length === 0) fail(`--token-file ${path61} is empty`);
19683
19907
  try {
19684
- fs41.unlinkSync(path60);
19908
+ fs42.unlinkSync(path61);
19685
19909
  } catch {
19686
19910
  }
19687
19911
  return content;
@@ -19707,7 +19931,7 @@ async function claimOnce(token, pluginId, pluginSecretHash) {
19707
19931
  pluginId,
19708
19932
  ideName: "codeam-cli (codespace)",
19709
19933
  ideVersion: process.env.npm_package_version ?? "unknown",
19710
- hostname: os34.hostname(),
19934
+ hostname: os35.hostname(),
19711
19935
  codespaceName: process.env.CODESPACE_NAME ?? "",
19712
19936
  // Current git branch of the codespace's working directory, so the
19713
19937
  // backend can populate `PairedSession.branch` for the codespace pair.
@@ -19768,7 +19992,7 @@ async function claim(token, pluginId, pluginSecretHash) {
19768
19992
  }
19769
19993
  }
19770
19994
  function pairAutoLockPath() {
19771
- return path47.join(os34.homedir(), ".codeam", "pair-auto.lock");
19995
+ return path48.join(os35.homedir(), ".codeam", "pair-auto.lock");
19772
19996
  }
19773
19997
  function isLivePairAuto(pid) {
19774
19998
  if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
@@ -19778,7 +20002,7 @@ function isLivePairAuto(pid) {
19778
20002
  if (e.code !== "EPERM") return false;
19779
20003
  }
19780
20004
  try {
19781
- return fs41.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
20005
+ return fs42.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
19782
20006
  } catch {
19783
20007
  return true;
19784
20008
  }
@@ -19788,24 +20012,24 @@ function isLiveCodeam(pid) {
19788
20012
  }
19789
20013
  function daemonLockPath(sessionId) {
19790
20014
  const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
19791
- return path47.join(os34.homedir(), ".codeam", `daemon-${safe}.lock`);
20015
+ return path48.join(os35.homedir(), ".codeam", `daemon-${safe}.lock`);
19792
20016
  }
19793
20017
  function acquireDaemonLock(sessionId) {
19794
20018
  const lockPath = daemonLockPath(sessionId);
19795
20019
  try {
19796
- fs41.mkdirSync(path47.dirname(lockPath), { recursive: true });
20020
+ fs42.mkdirSync(path48.dirname(lockPath), { recursive: true });
19797
20021
  try {
19798
- fs41.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
20022
+ fs42.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
19799
20023
  } catch (e) {
19800
20024
  if (e.code !== "EEXIST") throw e;
19801
- const holder = Number(fs41.readFileSync(lockPath, "utf8").trim());
20025
+ const holder = Number(fs42.readFileSync(lockPath, "utf8").trim());
19802
20026
  if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
19803
- fs41.writeFileSync(lockPath, String(process.pid));
20027
+ fs42.writeFileSync(lockPath, String(process.pid));
19804
20028
  }
19805
20029
  const release3 = () => {
19806
20030
  try {
19807
- if (fs41.existsSync(lockPath) && Number(fs41.readFileSync(lockPath, "utf8").trim()) === process.pid) {
19808
- fs41.unlinkSync(lockPath);
20031
+ if (fs42.existsSync(lockPath) && Number(fs42.readFileSync(lockPath, "utf8").trim()) === process.pid) {
20032
+ fs42.unlinkSync(lockPath);
19809
20033
  }
19810
20034
  } catch {
19811
20035
  }
@@ -19827,19 +20051,19 @@ function acquireDaemonLock(sessionId) {
19827
20051
  function acquireSingletonLock() {
19828
20052
  const lockPath = pairAutoLockPath();
19829
20053
  try {
19830
- fs41.mkdirSync(path47.dirname(lockPath), { recursive: true });
20054
+ fs42.mkdirSync(path48.dirname(lockPath), { recursive: true });
19831
20055
  try {
19832
- fs41.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
20056
+ fs42.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
19833
20057
  } catch (e) {
19834
20058
  if (e.code !== "EEXIST") throw e;
19835
- const holder = Number(fs41.readFileSync(lockPath, "utf8").trim());
20059
+ const holder = Number(fs42.readFileSync(lockPath, "utf8").trim());
19836
20060
  if (isLivePairAuto(holder)) return false;
19837
- fs41.writeFileSync(lockPath, String(process.pid));
20061
+ fs42.writeFileSync(lockPath, String(process.pid));
19838
20062
  }
19839
20063
  process.once("exit", () => {
19840
20064
  try {
19841
- if (fs41.existsSync(lockPath) && Number(fs41.readFileSync(lockPath, "utf8").trim()) === process.pid) {
19842
- fs41.unlinkSync(lockPath);
20065
+ if (fs42.existsSync(lockPath) && Number(fs42.readFileSync(lockPath, "utf8").trim()) === process.pid) {
20066
+ fs42.unlinkSync(lockPath);
19843
20067
  }
19844
20068
  } catch {
19845
20069
  }
@@ -20284,19 +20508,19 @@ var AgentService = class _AgentService {
20284
20508
  };
20285
20509
 
20286
20510
  // src/agents/acp/adapters.ts
20287
- var path48 = __toESM(require("path"));
20511
+ var path49 = __toESM(require("path"));
20288
20512
  var require_ = require;
20289
20513
  function resolveBin(pkgName, binName) {
20290
20514
  try {
20291
20515
  const manifestPath = require_.resolve(`${pkgName}/package.json`);
20292
20516
  const manifest = require_(`${pkgName}/package.json`);
20293
- const pkgDir = path48.dirname(manifestPath);
20517
+ const pkgDir = path49.dirname(manifestPath);
20294
20518
  const bin = manifest.bin;
20295
20519
  if (!bin) return null;
20296
- if (typeof bin === "string") return path48.resolve(pkgDir, bin);
20520
+ if (typeof bin === "string") return path49.resolve(pkgDir, bin);
20297
20521
  const target = binName ?? Object.keys(bin)[0];
20298
20522
  if (!target || !bin[target]) return null;
20299
- return path48.resolve(pkgDir, bin[target]);
20523
+ return path49.resolve(pkgDir, bin[target]);
20300
20524
  } catch {
20301
20525
  return null;
20302
20526
  }
@@ -20366,9 +20590,9 @@ function requiresAcp(agent) {
20366
20590
  var import_node_crypto7 = require("crypto");
20367
20591
 
20368
20592
  // src/services/history.service.ts
20369
- var fs42 = __toESM(require("fs"));
20370
- var path49 = __toESM(require("path"));
20371
- var os35 = __toESM(require("os"));
20593
+ var fs43 = __toESM(require("fs"));
20594
+ var path50 = __toESM(require("path"));
20595
+ var os36 = __toESM(require("os"));
20372
20596
  var https7 = __toESM(require("https"));
20373
20597
  var http6 = __toESM(require("http"));
20374
20598
  var import_zod2 = require("zod");
@@ -20395,7 +20619,7 @@ function parseJsonl(filePath) {
20395
20619
  const messages = [];
20396
20620
  let raw;
20397
20621
  try {
20398
- raw = fs42.readFileSync(filePath, "utf8");
20622
+ raw = fs43.readFileSync(filePath, "utf8");
20399
20623
  } catch (err) {
20400
20624
  if (err.code !== "ENOENT") {
20401
20625
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -20536,7 +20760,7 @@ var HistoryService = class _HistoryService {
20536
20760
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
20537
20761
  }
20538
20762
  get projectDir() {
20539
- return this.runtime.resolveHistoryDir(this.cwd) ?? path49.join(os35.homedir(), ".claude", "projects", encodeCwd(this.cwd));
20763
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path50.join(os36.homedir(), ".claude", "projects", encodeCwd(this.cwd));
20540
20764
  }
20541
20765
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
20542
20766
  setCurrentConversationId(id) {
@@ -20548,7 +20772,7 @@ var HistoryService = class _HistoryService {
20548
20772
  /** Return the current message count in the active conversation. */
20549
20773
  getCurrentMessageCount() {
20550
20774
  if (!this.currentConversationId) return 0;
20551
- const filePath = path49.join(this.projectDir, `${this.currentConversationId}.jsonl`);
20775
+ const filePath = path50.join(this.projectDir, `${this.currentConversationId}.jsonl`);
20552
20776
  return parseJsonl(filePath).length;
20553
20777
  }
20554
20778
  /**
@@ -20559,7 +20783,7 @@ var HistoryService = class _HistoryService {
20559
20783
  const deadline = Date.now() + timeoutMs;
20560
20784
  while (Date.now() < deadline) {
20561
20785
  if (!this.currentConversationId) return null;
20562
- const filePath = path49.join(this.projectDir, `${this.currentConversationId}.jsonl`);
20786
+ const filePath = path50.join(this.projectDir, `${this.currentConversationId}.jsonl`);
20563
20787
  const messages = parseJsonl(filePath);
20564
20788
  if (messages.length > previousCount) {
20565
20789
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -20585,16 +20809,16 @@ var HistoryService = class _HistoryService {
20585
20809
  const dir = this.projectDir;
20586
20810
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
20587
20811
  try {
20588
- const files = fs42.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
20812
+ const files = fs43.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
20589
20813
  try {
20590
- const stat3 = fs42.statSync(path49.join(dir, e.name));
20814
+ const stat3 = fs43.statSync(path50.join(dir, e.name));
20591
20815
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
20592
20816
  } catch {
20593
20817
  return { name: e.name, mtime: 0, birthtime: 0 };
20594
20818
  }
20595
20819
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
20596
20820
  if (files.length > 0) {
20597
- this.currentConversationId = path49.basename(files[0].name, ".jsonl");
20821
+ this.currentConversationId = path50.basename(files[0].name, ".jsonl");
20598
20822
  }
20599
20823
  } catch {
20600
20824
  }
@@ -20628,13 +20852,13 @@ var HistoryService = class _HistoryService {
20628
20852
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
20629
20853
  let entries;
20630
20854
  try {
20631
- entries = fs42.readdirSync(dir, { withFileTypes: true });
20855
+ entries = fs43.readdirSync(dir, { withFileTypes: true });
20632
20856
  } catch {
20633
20857
  return null;
20634
20858
  }
20635
20859
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
20636
20860
  try {
20637
- const stat3 = fs42.statSync(path49.join(dir, e.name));
20861
+ const stat3 = fs43.statSync(path50.join(dir, e.name));
20638
20862
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
20639
20863
  } catch {
20640
20864
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -20643,12 +20867,12 @@ var HistoryService = class _HistoryService {
20643
20867
  if (files.length === 0) return null;
20644
20868
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
20645
20869
  if (!files.some((f) => f.name === targetFile)) return null;
20646
- return this.extractUsageFromFile(path49.join(dir, targetFile));
20870
+ return this.extractUsageFromFile(path50.join(dir, targetFile));
20647
20871
  }
20648
20872
  extractUsageFromFile(filePath) {
20649
20873
  let raw;
20650
20874
  try {
20651
- raw = fs42.readFileSync(filePath, "utf8");
20875
+ raw = fs43.readFileSync(filePath, "utf8");
20652
20876
  } catch {
20653
20877
  return null;
20654
20878
  }
@@ -20693,9 +20917,9 @@ var HistoryService = class _HistoryService {
20693
20917
  let totalCost = 0;
20694
20918
  let files;
20695
20919
  try {
20696
- files = fs42.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
20920
+ files = fs43.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
20697
20921
  try {
20698
- return fs42.statSync(path49.join(projectDir, f)).mtimeMs >= monthStartMs;
20922
+ return fs43.statSync(path50.join(projectDir, f)).mtimeMs >= monthStartMs;
20699
20923
  } catch {
20700
20924
  return false;
20701
20925
  }
@@ -20706,7 +20930,7 @@ var HistoryService = class _HistoryService {
20706
20930
  for (const file of files) {
20707
20931
  let raw;
20708
20932
  try {
20709
- raw = fs42.readFileSync(path49.join(projectDir, file), "utf8");
20933
+ raw = fs43.readFileSync(path50.join(projectDir, file), "utf8");
20710
20934
  } catch {
20711
20935
  continue;
20712
20936
  }
@@ -20785,7 +21009,7 @@ var HistoryService = class _HistoryService {
20785
21009
  if (this.runtime.resolveHistoryFile) {
20786
21010
  return this.runtime.resolveHistoryFile(this.cwd, sessionId);
20787
21011
  }
20788
- return path49.join(this.projectDir, `${sessionId}.jsonl`);
21012
+ return path50.join(this.projectDir, `${sessionId}.jsonl`);
20789
21013
  }
20790
21014
  /**
20791
21015
  * Parse a conversation's messages from disk, agent-aware. Claude uses the
@@ -20819,7 +21043,7 @@ var HistoryService = class _HistoryService {
20819
21043
  };
20820
21044
  });
20821
21045
  }
20822
- return parseJsonl(path49.join(this.projectDir, `${sessionId}.jsonl`));
21046
+ return parseJsonl(path50.join(this.projectDir, `${sessionId}.jsonl`));
20823
21047
  }
20824
21048
  async loadConversation(sessionId) {
20825
21049
  const messages = this.readConversation(sessionId);
@@ -20875,7 +21099,7 @@ var HistoryService = class _HistoryService {
20875
21099
  if (!filePath) return false;
20876
21100
  let mtimeMs;
20877
21101
  try {
20878
- mtimeMs = fs42.statSync(filePath).mtimeMs;
21102
+ mtimeMs = fs43.statSync(filePath).mtimeMs;
20879
21103
  } catch {
20880
21104
  return false;
20881
21105
  }
@@ -20944,10 +21168,10 @@ var HistoryService = class _HistoryService {
20944
21168
 
20945
21169
  // src/agents/acp/client.ts
20946
21170
  var import_node_child_process16 = require("child_process");
20947
- var fs43 = __toESM(require("fs/promises"));
21171
+ var fs44 = __toESM(require("fs/promises"));
20948
21172
  var fsSync = __toESM(require("fs"));
20949
- var os36 = __toESM(require("os"));
20950
- var path50 = __toESM(require("path"));
21173
+ var os37 = __toESM(require("os"));
21174
+ var path51 = __toESM(require("path"));
20951
21175
  var import_node_stream = require("stream");
20952
21176
 
20953
21177
  // ../../node_modules/@agentclientprotocol/sdk/dist/acp.js
@@ -23780,7 +24004,7 @@ var AcpClient = class {
23780
24004
  },
23781
24005
  readTextFile: async (params) => {
23782
24006
  try {
23783
- const content = await fs43.readFile(params.path, "utf8");
24007
+ const content = await fs44.readFile(params.path, "utf8");
23784
24008
  return applyLineRange(content, params.line ?? null, params.limit ?? null);
23785
24009
  } catch (err) {
23786
24010
  const code = err.code;
@@ -23800,7 +24024,7 @@ var AcpClient = class {
23800
24024
  },
23801
24025
  writeTextFile: async (params) => {
23802
24026
  try {
23803
- await fs43.writeFile(params.path, params.content, "utf8");
24027
+ await fs44.writeFile(params.path, params.content, "utf8");
23804
24028
  return {};
23805
24029
  } catch (err) {
23806
24030
  const code = err.code;
@@ -23849,25 +24073,25 @@ function applyLineRange(content, line, limit) {
23849
24073
  return { content: lines.slice(start2, end).join("\n") };
23850
24074
  }
23851
24075
  function knownAgentBinaryDirs() {
23852
- const home = os36.homedir();
24076
+ const home = os37.homedir();
23853
24077
  const out2 = [];
23854
24078
  out2.push("/tmp/codeam-node20/bin");
23855
24079
  for (const root of [
23856
24080
  "/usr/local/share/nvm/versions/node",
23857
- path50.join(home, ".nvm/versions/node")
24081
+ path51.join(home, ".nvm/versions/node")
23858
24082
  ]) {
23859
24083
  try {
23860
24084
  for (const child of fsSync.readdirSync(root)) {
23861
- out2.push(path50.join(root, child, "bin"));
24085
+ out2.push(path51.join(root, child, "bin"));
23862
24086
  }
23863
24087
  } catch {
23864
24088
  }
23865
24089
  }
23866
- out2.push(path50.join(home, ".volta/bin"));
24090
+ out2.push(path51.join(home, ".volta/bin"));
23867
24091
  out2.push("/usr/local/bin");
23868
24092
  out2.push("/usr/bin");
23869
- out2.push(path50.join(home, ".local/bin"));
23870
- out2.push(path50.join(home, "bin"));
24093
+ out2.push(path51.join(home, ".local/bin"));
24094
+ out2.push(path51.join(home, "bin"));
23871
24095
  return out2.filter((p2) => {
23872
24096
  try {
23873
24097
  return fsSync.statSync(p2).isDirectory();
@@ -23878,7 +24102,7 @@ function knownAgentBinaryDirs() {
23878
24102
  }
23879
24103
  function expandPathForAgentBinaries(existingPath) {
23880
24104
  const existing = new Set(
23881
- existingPath.split(path50.delimiter).filter((p2) => p2.length > 0)
24105
+ existingPath.split(path51.delimiter).filter((p2) => p2.length > 0)
23882
24106
  );
23883
24107
  const additions = [];
23884
24108
  for (const dir of knownAgentBinaryDirs()) {
@@ -23888,7 +24112,7 @@ function expandPathForAgentBinaries(existingPath) {
23888
24112
  }
23889
24113
  }
23890
24114
  if (additions.length === 0) return existingPath;
23891
- return [...additions, existingPath].filter((p2) => p2.length > 0).join(path50.delimiter);
24115
+ return [...additions, existingPath].filter((p2) => p2.length > 0).join(path51.delimiter);
23892
24116
  }
23893
24117
 
23894
24118
  // src/services/streaming/transport.ts
@@ -24300,15 +24524,15 @@ function commonPrefixLength(a, b) {
24300
24524
 
24301
24525
  // src/agents/acp/onboarding.ts
24302
24526
  var import_child_process22 = require("child_process");
24303
- var fs44 = __toESM(require("fs"));
24304
- var os37 = __toESM(require("os"));
24305
- var path51 = __toESM(require("path"));
24527
+ var fs45 = __toESM(require("fs"));
24528
+ var os38 = __toESM(require("os"));
24529
+ var path52 = __toESM(require("path"));
24306
24530
  var _onboardingSeam = {
24307
- markerPath: (sessionId) => path51.join(os37.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
24308
- exists: (p2) => fs44.existsSync(p2),
24531
+ markerPath: (sessionId) => path52.join(os38.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
24532
+ exists: (p2) => fs45.existsSync(p2),
24309
24533
  write: (p2) => {
24310
- fs44.mkdirSync(path51.dirname(p2), { recursive: true });
24311
- fs44.writeFileSync(p2, "");
24534
+ fs45.mkdirSync(path52.dirname(p2), { recursive: true });
24535
+ fs45.writeFileSync(p2, "");
24312
24536
  },
24313
24537
  disabled: () => {
24314
24538
  const v = process.env.CODEAM_ONBOARDING_DISABLED;
@@ -24345,7 +24569,7 @@ function resolveRepoName(cwd) {
24345
24569
  if (name) return name;
24346
24570
  }
24347
24571
  }
24348
- const base = path51.basename(cwd || "");
24572
+ const base = path52.basename(cwd || "");
24349
24573
  if (base && !isUuid(base)) return base;
24350
24574
  return "this project";
24351
24575
  }
@@ -24618,13 +24842,28 @@ function extractSelectPrompt(text) {
24618
24842
  };
24619
24843
  }
24620
24844
 
24845
+ // src/agents/acp/inputSuggestion.ts
24846
+ var MIN_LEN = 8;
24847
+ var MAX_LEN = 200;
24848
+ function deriveInputSuggestion(finalText) {
24849
+ if (finalText.length === 0) return null;
24850
+ const lines = finalText.split("\n");
24851
+ let i = lines.length - 1;
24852
+ while (i >= 0 && lines[i].trim() === "") i--;
24853
+ if (i < 0) return null;
24854
+ const lastLine = lines[i].trim();
24855
+ if (!lastLine.endsWith("?")) return null;
24856
+ if (lastLine.length < MIN_LEN || lastLine.length > MAX_LEN) return null;
24857
+ return lastLine;
24858
+ }
24859
+
24621
24860
  // src/services/turn-files/turn-file-aggregator.ts
24622
24861
  var import_crypto5 = require("crypto");
24623
24862
 
24624
24863
  // src/services/turn-files/git-changeset.ts
24625
24864
  var import_child_process23 = require("child_process");
24626
- var fs45 = __toESM(require("fs/promises"));
24627
- var path52 = __toESM(require("path"));
24865
+ var fs46 = __toESM(require("fs/promises"));
24866
+ var path53 = __toESM(require("path"));
24628
24867
  async function collectRepoChangeset(opts) {
24629
24868
  const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
24630
24869
  if (status2 === null) return null;
@@ -24642,7 +24881,7 @@ async function collectRepoChangeset(opts) {
24642
24881
  let stats;
24643
24882
  if (row.fileStatus === "added" && numstatEntry === void 0) {
24644
24883
  const lineCount = await readUntrackedLineCount(
24645
- path52.join(opts.repoRoot, row.filePath)
24884
+ path53.join(opts.repoRoot, row.filePath)
24646
24885
  );
24647
24886
  stats = { added: lineCount, removed: 0 };
24648
24887
  } else {
@@ -24673,7 +24912,7 @@ function readUntrackedLineCount(absPath) {
24673
24912
  }
24674
24913
  async function defaultReadUntrackedLineCount(absPath) {
24675
24914
  try {
24676
- const content = await fs45.readFile(absPath, "utf8");
24915
+ const content = await fs46.readFile(absPath, "utf8");
24677
24916
  let count = 0;
24678
24917
  let pos = -1;
24679
24918
  while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
@@ -24765,7 +25004,7 @@ function defaultRunGit(cwd, args2) {
24765
25004
  });
24766
25005
  }
24767
25006
  async function discoverRepos(workingDir, maxDepth = 4) {
24768
- const fs49 = await import("fs/promises");
25007
+ const fs50 = await import("fs/promises");
24769
25008
  const out2 = [];
24770
25009
  await walk(workingDir, 0);
24771
25010
  return out2;
@@ -24773,7 +25012,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
24773
25012
  if (depth > maxDepth) return;
24774
25013
  let entries = [];
24775
25014
  try {
24776
- const dirents = await fs49.readdir(dir, { withFileTypes: true });
25015
+ const dirents = await fs50.readdir(dir, { withFileTypes: true });
24777
25016
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
24778
25017
  } catch {
24779
25018
  return;
@@ -24784,8 +25023,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
24784
25023
  if (hasGit) {
24785
25024
  out2.push({
24786
25025
  repoRoot: dir,
24787
- repoPath: path52.relative(workingDir, dir),
24788
- repoName: path52.basename(dir)
25026
+ repoPath: path53.relative(workingDir, dir),
25027
+ repoName: path53.basename(dir)
24789
25028
  });
24790
25029
  return;
24791
25030
  }
@@ -24793,14 +25032,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
24793
25032
  if (!entry.isDirectory) continue;
24794
25033
  if (entry.name === "node_modules") continue;
24795
25034
  if (entry.name === "dist" || entry.name === "build") continue;
24796
- await walk(path52.join(dir, entry.name), depth + 1);
25035
+ await walk(path53.join(dir, entry.name), depth + 1);
24797
25036
  }
24798
25037
  }
24799
25038
  }
24800
25039
 
24801
25040
  // src/services/turn-files/files-outbox.ts
24802
- var fs46 = __toESM(require("fs/promises"));
24803
- var path53 = __toESM(require("path"));
25041
+ var fs47 = __toESM(require("fs/promises"));
25042
+ var path54 = __toESM(require("path"));
24804
25043
  var import_os7 = require("os");
24805
25044
  var HOME_OUTBOX_DIR = ".codeam/outbox";
24806
25045
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -24833,16 +25072,16 @@ var FilesOutbox = class {
24833
25072
  backoffIndex = 0;
24834
25073
  stopped = false;
24835
25074
  constructor(opts) {
24836
- const base = opts.baseDir ?? path53.join(homeDir(), HOME_OUTBOX_DIR);
24837
- this.filePath = path53.join(base, `${opts.sessionId}.jsonl`);
25075
+ const base = opts.baseDir ?? path54.join(homeDir(), HOME_OUTBOX_DIR);
25076
+ this.filePath = path54.join(base, `${opts.sessionId}.jsonl`);
24838
25077
  this.post = opts.post;
24839
25078
  this.autoSchedule = opts.autoSchedule !== false;
24840
25079
  }
24841
25080
  /** Persist the entry to disk and trigger a flush. Returns once the
24842
25081
  * line is durable on disk (not once the POST succeeds). */
24843
25082
  async enqueue(entry) {
24844
- await fs46.mkdir(path53.dirname(this.filePath), { recursive: true });
24845
- await fs46.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
25083
+ await fs47.mkdir(path54.dirname(this.filePath), { recursive: true });
25084
+ await fs47.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
24846
25085
  this.backoffIndex = 0;
24847
25086
  if (this.autoSchedule) this.scheduleFlush(0);
24848
25087
  }
@@ -24931,7 +25170,7 @@ var FilesOutbox = class {
24931
25170
  async readAll() {
24932
25171
  let raw = "";
24933
25172
  try {
24934
- raw = await fs46.readFile(this.filePath, "utf8");
25173
+ raw = await fs47.readFile(this.filePath, "utf8");
24935
25174
  } catch {
24936
25175
  return [];
24937
25176
  }
@@ -24955,12 +25194,12 @@ var FilesOutbox = class {
24955
25194
  async rewrite(entries) {
24956
25195
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
24957
25196
  if (entries.length === 0) {
24958
- await fs46.unlink(this.filePath).catch(() => void 0);
25197
+ await fs47.unlink(this.filePath).catch(() => void 0);
24959
25198
  return;
24960
25199
  }
24961
25200
  const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
24962
- await fs46.writeFile(tmpPath, payload, "utf8");
24963
- await fs46.rename(tmpPath, this.filePath);
25201
+ await fs47.writeFile(tmpPath, payload, "utf8");
25202
+ await fs47.rename(tmpPath, this.filePath);
24964
25203
  }
24965
25204
  };
24966
25205
  function applyJitter(ms) {
@@ -25489,7 +25728,7 @@ var StreamingState = class {
25489
25728
  this.publisher.publishOutput({ type: "text", content: finalText, done: true }),
25490
25729
  flushSc
25491
25730
  ]);
25492
- return;
25731
+ return false;
25493
25732
  }
25494
25733
  log.info(
25495
25734
  "acpRunner",
@@ -25516,6 +25755,7 @@ var StreamingState = class {
25516
25755
  done: true
25517
25756
  });
25518
25757
  await flushSc;
25758
+ return true;
25519
25759
  }
25520
25760
  };
25521
25761
  var PERMISSION_TIMEOUT_MS = 5 * 60 * 1e3;
@@ -25889,7 +26129,9 @@ async function runAcpSession(opts) {
25889
26129
  flushHistory: () => void history.flush(),
25890
26130
  beginTurn: () => streaming.beginTurn(),
25891
26131
  getCurrentText: () => streaming.getCurrentText(),
25892
- closeTurn: () => streaming.closeTurnWithInteractiveDetection(),
26132
+ closeTurn: async () => {
26133
+ await streaming.closeTurnWithInteractiveDetection();
26134
+ },
25893
26135
  recoverFromFailedTurn: () => recoverFromFailedTurn(client2, streaming),
25894
26136
  reconnectWith1mDisabled,
25895
26137
  promptAgent: (blocks) => client2.prompt(blocks),
@@ -26090,13 +26332,19 @@ async function handleCommand(cmd, client2, relay, acpSessionId, models, streamin
26090
26332
  } else if (shouldOfferOneMRecovery({ detail: "", recentStderr: recentStderr.join("\n"), finalText })) {
26091
26333
  await oneMRecovery.offer(cmd.id, blocks);
26092
26334
  } else {
26093
- await streaming.closeTurnWithInteractiveDetection();
26335
+ const emittedSelectPrompt = await streaming.closeTurnWithInteractiveDetection();
26094
26336
  const replyLine = formatAgentReplyLine(finalText);
26095
26337
  if (replyLine.length > 0) {
26096
26338
  showInfo(replyLine);
26097
26339
  }
26098
26340
  history.appendAgentReply(finalText);
26099
26341
  void history.flush();
26342
+ if (!emittedSelectPrompt) {
26343
+ const suggestion = deriveInputSuggestion(finalText);
26344
+ if (suggestion !== null) {
26345
+ void publisher.publishOutput({ type: "input_suggestion", content: suggestion, done: true });
26346
+ }
26347
+ }
26100
26348
  turnFiles.flushTurn().catch((err) => {
26101
26349
  log.warn("acpRunner", `turnFiles.flushTurn failed: ${describeError(err)}`);
26102
26350
  });
@@ -27470,15 +27718,15 @@ function fetchQuotaUsage(runtime, historySvc) {
27470
27718
  }
27471
27719
 
27472
27720
  // src/agents/claude/onboarding.ts
27473
- var fs47 = __toESM(require("fs"));
27474
- var os38 = __toESM(require("os"));
27475
- var path54 = __toESM(require("path"));
27721
+ var fs48 = __toESM(require("fs"));
27722
+ var os39 = __toESM(require("os"));
27723
+ var path55 = __toESM(require("path"));
27476
27724
  function ensureClaudeOnboarded() {
27477
27725
  try {
27478
- const file = path54.join(os38.homedir(), ".claude.json");
27726
+ const file = path55.join(os39.homedir(), ".claude.json");
27479
27727
  let config = {};
27480
27728
  try {
27481
- config = JSON.parse(fs47.readFileSync(file, "utf8"));
27729
+ config = JSON.parse(fs48.readFileSync(file, "utf8"));
27482
27730
  } catch {
27483
27731
  }
27484
27732
  if (config.hasCompletedOnboarding === true && typeof config.theme === "string") {
@@ -27489,8 +27737,8 @@ function ensureClaudeOnboarded() {
27489
27737
  if (typeof config.lastOnboardingVersion !== "string") {
27490
27738
  config.lastOnboardingVersion = "2.1.177";
27491
27739
  }
27492
- fs47.mkdirSync(path54.dirname(file), { recursive: true });
27493
- fs47.writeFileSync(file, JSON.stringify(config, null, 2));
27740
+ fs48.mkdirSync(path55.dirname(file), { recursive: true });
27741
+ fs48.writeFileSync(file, JSON.stringify(config, null, 2));
27494
27742
  log.info("claude", "pre-completed Claude onboarding (skip first-run theme picker)");
27495
27743
  } catch (err) {
27496
27744
  log.warn("claude", `ensureClaudeOnboarded failed (non-fatal): ${err.message}`);
@@ -27568,6 +27816,14 @@ async function start(requestedAgent) {
27568
27816
  process.once("exit", () => {
27569
27817
  headroomReporter?.stop();
27570
27818
  });
27819
+ const localHeadroomReporter = session.pluginAuthToken ? maybeResumeLocalHeadroomReporter({
27820
+ sessionId: session.id,
27821
+ pluginId,
27822
+ pluginAuthToken: session.pluginAuthToken
27823
+ }) : null;
27824
+ process.once("exit", () => {
27825
+ localHeadroomReporter?.stop();
27826
+ });
27571
27827
  if (process.env.CODESPACES === "true") ensureClaudeOnboarded();
27572
27828
  let beads = null;
27573
27829
  const getBeads = () => beads;
@@ -28132,7 +28388,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
28132
28388
  var import_child_process24 = require("child_process");
28133
28389
  var import_util4 = require("util");
28134
28390
  var import_picocolors9 = __toESM(require("picocolors"));
28135
- var path55 = __toESM(require("path"));
28391
+ var path56 = __toESM(require("path"));
28136
28392
  var execFileP6 = (0, import_util4.promisify)(import_child_process24.execFile);
28137
28393
  var MAX_BUFFER = 8 * 1024 * 1024;
28138
28394
  function resetStdinForChild() {
@@ -28621,7 +28877,7 @@ var GitHubCodespacesProvider = class {
28621
28877
  });
28622
28878
  }
28623
28879
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
28624
- const remoteDir = path55.posix.dirname(remotePath);
28880
+ const remoteDir = path56.posix.dirname(remotePath);
28625
28881
  const parts = [
28626
28882
  `mkdir -p ${shellQuote(remoteDir)}`,
28627
28883
  `cat > ${shellQuote(remotePath)}`
@@ -28691,7 +28947,7 @@ function shellQuote(s) {
28691
28947
  // src/services/providers/gitpod.ts
28692
28948
  var import_child_process25 = require("child_process");
28693
28949
  var import_util5 = require("util");
28694
- var path56 = __toESM(require("path"));
28950
+ var path57 = __toESM(require("path"));
28695
28951
  var import_picocolors10 = __toESM(require("picocolors"));
28696
28952
  var execFileP7 = (0, import_util5.promisify)(import_child_process25.execFile);
28697
28953
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -28931,7 +29187,7 @@ var GitpodProvider = class {
28931
29187
  });
28932
29188
  }
28933
29189
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
28934
- const remoteDir = path56.posix.dirname(remotePath);
29190
+ const remoteDir = path57.posix.dirname(remotePath);
28935
29191
  const parts = [
28936
29192
  `mkdir -p ${shellQuote2(remoteDir)}`,
28937
29193
  `cat > ${shellQuote2(remotePath)}`
@@ -28967,7 +29223,7 @@ function shellQuote2(s) {
28967
29223
  // src/services/providers/gitlab-workspaces.ts
28968
29224
  var import_child_process26 = require("child_process");
28969
29225
  var import_util6 = require("util");
28970
- var path57 = __toESM(require("path"));
29226
+ var path58 = __toESM(require("path"));
28971
29227
  var execFileP8 = (0, import_util6.promisify)(import_child_process26.execFile);
28972
29228
  var MAX_BUFFER3 = 8 * 1024 * 1024;
28973
29229
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -29227,7 +29483,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
29227
29483
  }
29228
29484
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
29229
29485
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
29230
- const remoteDir = path57.posix.dirname(remotePath);
29486
+ const remoteDir = path58.posix.dirname(remotePath);
29231
29487
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
29232
29488
  if (options.mode != null) {
29233
29489
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -29295,7 +29551,7 @@ function shellQuote3(s) {
29295
29551
  // src/services/providers/railway.ts
29296
29552
  var import_child_process27 = require("child_process");
29297
29553
  var import_util7 = require("util");
29298
- var path58 = __toESM(require("path"));
29554
+ var path59 = __toESM(require("path"));
29299
29555
  var execFileP9 = (0, import_util7.promisify)(import_child_process27.execFile);
29300
29556
  var MAX_BUFFER4 = 8 * 1024 * 1024;
29301
29557
  function resetStdinForChild4() {
@@ -29531,7 +29787,7 @@ var RailwayProvider = class {
29531
29787
  if (!projectId || !serviceId) {
29532
29788
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
29533
29789
  }
29534
- const remoteDir = path58.posix.dirname(remotePath);
29790
+ const remoteDir = path59.posix.dirname(remotePath);
29535
29791
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
29536
29792
  if (options.mode != null) {
29537
29793
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -30177,8 +30433,8 @@ async function invite() {
30177
30433
  var import_node_dns = require("dns");
30178
30434
  var import_node_util5 = require("util");
30179
30435
  var import_node_crypto8 = require("crypto");
30180
- var fs48 = __toESM(require("fs"));
30181
- var path59 = __toESM(require("path"));
30436
+ var fs49 = __toESM(require("fs"));
30437
+ var path60 = __toESM(require("path"));
30182
30438
  var import_picocolors14 = __toESM(require("picocolors"));
30183
30439
  var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
30184
30440
  async function checkDns(apiBase2) {
@@ -30234,13 +30490,13 @@ async function checkHealth(apiBase2) {
30234
30490
  }
30235
30491
  }
30236
30492
  function checkConfigDir() {
30237
- const dir = path59.join(require("os").homedir(), ".codeam");
30493
+ const dir = path60.join(require("os").homedir(), ".codeam");
30238
30494
  try {
30239
- fs48.mkdirSync(dir, { recursive: true, mode: 448 });
30240
- const probe = path59.join(dir, ".doctor-probe");
30241
- fs48.writeFileSync(probe, "ok", { mode: 384 });
30242
- const read2 = fs48.readFileSync(probe, "utf8");
30243
- fs48.unlinkSync(probe);
30495
+ fs49.mkdirSync(dir, { recursive: true, mode: 448 });
30496
+ const probe = path60.join(dir, ".doctor-probe");
30497
+ fs49.writeFileSync(probe, "ok", { mode: 384 });
30498
+ const read2 = fs49.readFileSync(probe, "utf8");
30499
+ fs49.unlinkSync(probe);
30244
30500
  if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
30245
30501
  return {
30246
30502
  id: "config-dir",
@@ -30280,9 +30536,9 @@ function checkSessions() {
30280
30536
  }
30281
30537
  }
30282
30538
  function checkAgentBinaries() {
30283
- const os40 = createOsStrategy();
30539
+ const os41 = createOsStrategy();
30284
30540
  return getEnabledAgents().map((meta) => {
30285
- const found = os40.findInPath(meta.binaryName);
30541
+ const found = os41.findInPath(meta.binaryName);
30286
30542
  return {
30287
30543
  id: `agent-${meta.id}`,
30288
30544
  label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
@@ -30304,7 +30560,7 @@ function checkNodePty() {
30304
30560
  detail: "not required on this platform"
30305
30561
  };
30306
30562
  }
30307
- const vendoredPath = path59.join(__dirname, "vendor", "node-pty");
30563
+ const vendoredPath = path60.join(__dirname, "vendor", "node-pty");
30308
30564
  for (const target of [vendoredPath, "node-pty"]) {
30309
30565
  try {
30310
30566
  require(target);
@@ -30346,7 +30602,7 @@ function checkChokidar() {
30346
30602
  }
30347
30603
  async function doctor(args2 = []) {
30348
30604
  const json = args2.includes("--json");
30349
- const cliVersion = true ? "2.49.4" : "0.0.0-dev";
30605
+ const cliVersion = true ? "2.50.0" : "0.0.0-dev";
30350
30606
  const apiBase2 = resolveApiBaseUrl();
30351
30607
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
30352
30608
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -30545,7 +30801,7 @@ async function completion(args2) {
30545
30801
  // src/commands/version.ts
30546
30802
  var import_picocolors15 = __toESM(require("picocolors"));
30547
30803
  function version2() {
30548
- const v = true ? "2.49.4" : "unknown";
30804
+ const v = true ? "2.50.0" : "unknown";
30549
30805
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
30550
30806
  }
30551
30807
 
@@ -30694,10 +30950,10 @@ var EXIT_CODE_NAMES = {
30694
30950
  };
30695
30951
 
30696
30952
  // src/index.ts
30697
- var os39 = __toESM(require("os"));
30953
+ var os40 = __toESM(require("os"));
30698
30954
  if (!process.env.HOME) {
30699
30955
  try {
30700
- const home = os39.homedir();
30956
+ const home = os40.homedir();
30701
30957
  if (home) process.env.HOME = home;
30702
30958
  } catch {
30703
30959
  }