codeam-cli 2.74.0 → 2.74.2

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 +16 -0
  2. package/dist/index.js +108 -46
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,22 @@ All notable changes to `codeam-cli` are documented here.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [2.74.1] — 2026-09-04
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Npx integration servers start with npm audit off; bound mcp-warm; 25-min fleet-box step (#701)
12
+
13
+ ## [2.74.0] — 2026-09-03
14
+
15
+ ### Added
16
+
17
+ - **cli:** Tool router (4 schemas instead of hundreds) + house agent's real context window (#700)
18
+
19
+ ### Tests
20
+
21
+ - **cli:** Two of today's tests were not Windows-portable — main went red (#699)
22
+
7
23
  ## [2.73.10] — 2026-09-03
8
24
 
9
25
  ### Fixed
package/dist/index.js CHANGED
@@ -271,8 +271,8 @@ var init_stdio_proxy = __esm({
271
271
  }
272
272
  async spawnChild(stdout, preResolved) {
273
273
  const spec = preResolved ?? await this.opts.spawnSpec();
274
- const spawn47 = this.opts.spawnImpl ?? import_node_child_process33.spawn;
275
- const child = spawn47(spec.command, spec.args, {
274
+ const spawn48 = this.opts.spawnImpl ?? import_node_child_process33.spawn;
275
+ const child = spawn48(spec.command, spec.args, {
276
276
  env: { ...process.env, ...spec.env },
277
277
  // env only — never argv
278
278
  stdio: ["pipe", "pipe", "inherit"]
@@ -8136,7 +8136,7 @@ function readAnonId() {
8136
8136
  }
8137
8137
  function superProperties() {
8138
8138
  return {
8139
- cliVersion: true ? "2.74.0" : "0.0.0-dev",
8139
+ cliVersion: true ? "2.74.2" : "0.0.0-dev",
8140
8140
  nodeVersion: process.version,
8141
8141
  platform: process.platform,
8142
8142
  arch: process.arch,
@@ -8378,7 +8378,7 @@ var http = __toESM(require("http"));
8378
8378
  // package.json
8379
8379
  var package_default = {
8380
8380
  name: "codeam-cli",
8381
- version: "2.74.0",
8381
+ version: "2.74.2",
8382
8382
  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.",
8383
8383
  type: "commonjs",
8384
8384
  main: "dist/index.js",
@@ -9971,7 +9971,7 @@ var CommandRelayService = class _CommandRelayService {
9971
9971
  // fresh + clear the "CLI update available" banner after a self-update
9972
9972
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
9973
9973
  // pair/reconnect). Older backends ignore the extra field.
9974
- ..."2.74.0" ? { ideVersion: "2.74.0" } : {}
9974
+ ..."2.74.2" ? { ideVersion: "2.74.2" } : {}
9975
9975
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
9976
9976
  }
9977
9977
  /**
@@ -22272,7 +22272,7 @@ async function autoUpgradeBeforeCriticalCommand() {
22272
22272
  if (process.env.NODE_ENV === "test") return;
22273
22273
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
22274
22274
  if (process.env.CI) return;
22275
- const current2 = true ? "2.74.0" : null;
22275
+ const current2 = true ? "2.74.2" : null;
22276
22276
  if (!current2) return;
22277
22277
  const cache = readCache();
22278
22278
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -22289,7 +22289,7 @@ function checkForUpdates() {
22289
22289
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
22290
22290
  if (process.env.CI) return;
22291
22291
  if (!process.stdout.isTTY) return;
22292
- const current2 = true ? "2.74.0" : null;
22292
+ const current2 = true ? "2.74.2" : null;
22293
22293
  if (!current2) return;
22294
22294
  const cache = readCache();
22295
22295
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -22312,7 +22312,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
22312
22312
  var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
22313
22313
  var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
22314
22314
  function currentCliVersion() {
22315
- return true ? "2.74.0" : null;
22315
+ return true ? "2.74.2" : null;
22316
22316
  }
22317
22317
  async function installedVersion(deps) {
22318
22318
  const ls = await deps.run(
@@ -24956,11 +24956,23 @@ function safeParseDetection(raw) {
24956
24956
  if (!raw) return null;
24957
24957
  const parsed = parseDetectionObject(raw);
24958
24958
  if (!parsed) return null;
24959
+ if (isUnsupportedAnswer(parsed)) {
24960
+ return {
24961
+ framework: "unsupported",
24962
+ notes: typeof parsed.notes === "string" ? parsed.notes : void 0
24963
+ };
24964
+ }
24959
24965
  for (const field of REQUIRED_FIELDS2) {
24960
24966
  if (!(field in parsed)) return null;
24961
24967
  }
24962
24968
  return parsed;
24963
24969
  }
24970
+ function isUnsupportedAnswer(parsed) {
24971
+ return parsed.framework === "unsupported";
24972
+ }
24973
+ function isUnsupportedDetection(d3) {
24974
+ return d3.framework === "unsupported";
24975
+ }
24964
24976
  function parseDetectionObject(raw) {
24965
24977
  let parsed = tryParseObject(raw.trim());
24966
24978
  if (!parsed) {
@@ -25044,6 +25056,7 @@ function describeDetectionFailure(raw) {
25044
25056
  rawExcerpt
25045
25057
  };
25046
25058
  }
25059
+ if (isUnsupportedAnswer(parsed)) return null;
25047
25060
  const missing = REQUIRED_FIELDS2.filter((f) => !(f in parsed)).map(String);
25048
25061
  if (missing.length > 0) {
25049
25062
  return {
@@ -29462,7 +29475,7 @@ ${failure?.rawExcerpt ?? ""}`
29462
29475
  });
29463
29476
  return;
29464
29477
  }
29465
- if (detection.framework === "unsupported") {
29478
+ if (isUnsupportedDetection(detection)) {
29466
29479
  log.info("preview", "detect: framework=unsupported");
29467
29480
  emitPreviewEvent({
29468
29481
  sessionId: ctx.sessionId,
@@ -29530,7 +29543,7 @@ function prewarmPreviewDetection(runtime) {
29530
29543
  log.info("preview", `prewarm: detection failed reason=${failure?.reason ?? "unknown"}`);
29531
29544
  return;
29532
29545
  }
29533
- if (detection.framework === "unsupported") return;
29546
+ if (isUnsupportedDetection(detection)) return;
29534
29547
  await writePreviewConfig(cwd, detection);
29535
29548
  log.info(
29536
29549
  "preview",
@@ -36844,12 +36857,12 @@ function buildRelaunchProxyEnv(baseEnv) {
36844
36857
  return env;
36845
36858
  }
36846
36859
  var relaunchProxyWithoutBudget = async () => {
36847
- const { spawn: spawn47 } = await import("child_process");
36860
+ const { spawn: spawn48 } = await import("child_process");
36848
36861
  killHeadroomProxy();
36849
36862
  await new Promise((r) => setTimeout(r, 500));
36850
36863
  const proxyEnv = buildRelaunchProxyEnv(process.env);
36851
36864
  try {
36852
- const proxy = spawn47(
36865
+ const proxy = spawn48(
36853
36866
  "headroom",
36854
36867
  ["proxy", "--port", "8787"],
36855
36868
  { stdio: "ignore", detached: true, env: proxyEnv }
@@ -47437,7 +47450,7 @@ function checkChokidar() {
47437
47450
  }
47438
47451
  async function doctor(args2 = []) {
47439
47452
  const json = args2.includes("--json");
47440
- const cliVersion = true ? "2.74.0" : "0.0.0-dev";
47453
+ const cliVersion = true ? "2.74.2" : "0.0.0-dev";
47441
47454
  const apiBase2 = resolveApiBaseUrl();
47442
47455
  const diagnosticId = (0, import_node_crypto13.randomUUID)();
47443
47456
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -47635,6 +47648,15 @@ async function completion(args2) {
47635
47648
 
47636
47649
  // src/integrations/mcp-run.ts
47637
47650
  var import_node_child_process34 = require("child_process");
47651
+
47652
+ // src/integrations/launcher-env.ts
47653
+ var LAUNCHER_ENV = Object.freeze({
47654
+ npm_config_audit: "false",
47655
+ npm_config_fund: "false",
47656
+ npm_config_update_notifier: "false"
47657
+ });
47658
+
47659
+ // src/integrations/mcp-run.ts
47638
47660
  var import_node_fs14 = require("fs");
47639
47661
  var import_node_os14 = __toESM(require("os"));
47640
47662
  var import_node_path13 = __toESM(require("path"));
@@ -47764,6 +47786,14 @@ function ensureCommand(command2) {
47764
47786
  );
47765
47787
  }
47766
47788
  }
47789
+ function childEnvFor(delivery, token) {
47790
+ const env = { ...LAUNCHER_ENV, ...delivery.staticEnv };
47791
+ for (const [envVar, field] of Object.entries(delivery.envMapping)) {
47792
+ const value = token[field];
47793
+ if (typeof value === "string" && value) env[envVar] = value;
47794
+ }
47795
+ return env;
47796
+ }
47767
47797
  async function mcpRun(args2) {
47768
47798
  const id = args2[0] ?? process.env.CODEAM_MCP_INTEGRATION_ID;
47769
47799
  const sessionId = process.env.CODEAM_MCP_SESSION_ID;
@@ -47813,12 +47843,7 @@ async function mcpRun(args2) {
47813
47843
  const proxy = new RestartableStdioProxy({
47814
47844
  spawnSpec: async () => {
47815
47845
  current2 = await client3.getToken(id);
47816
- const env = { ...delivery.staticEnv };
47817
- for (const [envVar, field] of Object.entries(delivery.envMapping)) {
47818
- const value = current2[field];
47819
- if (typeof value === "string" && value) env[envVar] = value;
47820
- }
47821
- return { command: launcher, args: delivery.args, env };
47846
+ return { command: launcher, args: delivery.args, env: childEnvFor(delivery, current2) };
47822
47847
  },
47823
47848
  shouldRestartNow: () => current2 !== null && new Date(current2.expiresAt).getTime() - Date.now() < RESTART_AHEAD_MS
47824
47849
  });
@@ -47865,37 +47890,72 @@ function warmCommand(target) {
47865
47890
  }
47866
47891
  return null;
47867
47892
  }
47868
- async function mcpWarm(argv = []) {
47869
- const timeoutMs = 3e5;
47893
+ var WARM_PACKAGE_TIMEOUT_MS = 12e4;
47894
+ var WARM_TOTAL_BUDGET_MS = 10 * 6e4;
47895
+ var WARM_CONCURRENCY = 4;
47896
+ function runCapturing(command2, args2, timeoutMs) {
47897
+ return new Promise((resolve11) => {
47898
+ const child = (0, import_node_child_process35.spawn)(command2, args2, {
47899
+ env: { ...process.env, ...LAUNCHER_ENV },
47900
+ stdio: ["ignore", "ignore", "pipe"]
47901
+ });
47902
+ let stderr = "";
47903
+ child.stderr?.setEncoding("utf8");
47904
+ child.stderr?.on("data", (c2) => stderr += c2);
47905
+ const timer = setTimeout(() => {
47906
+ child.kill("SIGKILL");
47907
+ resolve11({ status: null, stderr, error: new Error(`spawn ${command2} ETIMEDOUT`) });
47908
+ }, timeoutMs);
47909
+ child.on("error", (error) => {
47910
+ clearTimeout(timer);
47911
+ resolve11({ status: null, stderr, error });
47912
+ });
47913
+ child.on("close", (status2) => {
47914
+ clearTimeout(timer);
47915
+ resolve11({ status: status2, stderr });
47916
+ });
47917
+ });
47918
+ }
47919
+ async function mcpWarm(argv = [], opts = {}) {
47920
+ const packageTimeoutMs = opts.packageTimeoutMs ?? WARM_PACKAGE_TIMEOUT_MS;
47921
+ const totalBudgetMs = opts.totalBudgetMs ?? WARM_TOTAL_BUDGET_MS;
47922
+ const concurrency = opts.concurrency ?? WARM_CONCURRENCY;
47870
47923
  const targets = warmTargets();
47871
47924
  const only = argv.filter((a) => !a.startsWith("-"));
47872
47925
  const selected = only.length > 0 ? targets.filter((t2) => only.includes(t2.id)) : targets;
47873
47926
  const result = { warmed: [], skipped: [], failed: [] };
47874
47927
  console.log(`[codeam mcp-warm] ${selected.length} MCP package(s) to pre-fetch`);
47875
- for (const target of selected) {
47876
- const cmd = warmCommand(target);
47877
- if (!cmd) {
47878
- result.skipped.push(`${target.spec} (no warm recipe for '${target.launcher}')`);
47879
- continue;
47880
- }
47881
- const started = Date.now();
47882
- const run = (0, import_node_child_process35.spawnSync)(cmd.command, cmd.args, {
47883
- stdio: ["ignore", "ignore", "pipe"],
47884
- timeout: timeoutMs,
47885
- encoding: "utf8"
47886
- });
47887
- const secs = ((Date.now() - started) / 1e3).toFixed(1);
47888
- if (run.status === 0) {
47889
- result.warmed.push(target.spec);
47890
- console.log(` OK ${target.spec} (${secs}s)`);
47891
- } else {
47892
- const noise = /^npm (warn|notice)\b/;
47893
- const lines = (run.stderr ?? "").split("\n").map((l) => l.trim()).filter((l) => l.length > 0 && !noise.test(l));
47894
- const reason = run.error?.message ?? lines[lines.length - 1] ?? `exit ${String(run.status)} (no stderr)`;
47895
- result.failed.push({ spec: target.spec, reason });
47896
- console.log(` MISS ${target.spec} (${secs}s) \u2014 fetched at runtime instead: ${reason}`);
47928
+ const deadline = Date.now() + totalBudgetMs;
47929
+ const queue = [...selected];
47930
+ const worker = async () => {
47931
+ for (let target = queue.shift(); target; target = queue.shift()) {
47932
+ const cmd = warmCommand(target);
47933
+ if (!cmd) {
47934
+ result.skipped.push(`${target.spec} (no warm recipe for '${target.launcher}')`);
47935
+ continue;
47936
+ }
47937
+ const remaining = deadline - Date.now();
47938
+ if (remaining <= 0) {
47939
+ result.failed.push({ spec: target.spec, reason: "warm budget spent" });
47940
+ console.log(` MISS ${target.spec} (0.0s) \u2014 fetched at runtime instead: warm budget spent`);
47941
+ continue;
47942
+ }
47943
+ const started = Date.now();
47944
+ const run = await runCapturing(cmd.command, cmd.args, Math.min(packageTimeoutMs, remaining));
47945
+ const secs = ((Date.now() - started) / 1e3).toFixed(1);
47946
+ if (run.status === 0) {
47947
+ result.warmed.push(target.spec);
47948
+ console.log(` OK ${target.spec} (${secs}s)`);
47949
+ } else {
47950
+ const noise = /^npm (warn|notice)\b/;
47951
+ const lines = run.stderr.split("\n").map((l) => l.trim()).filter((l) => l.length > 0 && !noise.test(l));
47952
+ const reason = run.error?.message ?? lines[lines.length - 1] ?? `exit ${String(run.status)} (no stderr)`;
47953
+ result.failed.push({ spec: target.spec, reason });
47954
+ console.log(` MISS ${target.spec} (${secs}s) \u2014 fetched at runtime instead: ${reason}`);
47955
+ }
47897
47956
  }
47898
- }
47957
+ };
47958
+ await Promise.all(Array.from({ length: Math.max(1, concurrency) }, worker));
47899
47959
  console.log(
47900
47960
  `[codeam mcp-warm] warmed=${result.warmed.length} failed=${result.failed.length} skipped=${result.skipped.length}`
47901
47961
  );
@@ -47903,12 +47963,13 @@ async function mcpWarm(argv = []) {
47903
47963
  "mcpWarm",
47904
47964
  `warmed=${result.warmed.length} failed=${result.failed.length} skipped=${result.skipped.length}`
47905
47965
  );
47966
+ return result;
47906
47967
  }
47907
47968
 
47908
47969
  // src/commands/version.ts
47909
47970
  var import_picocolors15 = __toESM(require("picocolors"));
47910
47971
  function version2() {
47911
- const v = true ? "2.74.0" : "unknown";
47972
+ const v = true ? "2.74.2" : "unknown";
47912
47973
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
47913
47974
  }
47914
47975
 
@@ -48110,7 +48171,8 @@ async function main() {
48110
48171
  return mcpRun(args);
48111
48172
  }
48112
48173
  if (command === "mcp-warm") {
48113
- return mcpWarm(args);
48174
+ await mcpWarm(args);
48175
+ return;
48114
48176
  }
48115
48177
  if (command === "mcp-router") {
48116
48178
  return mcpRouter();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.74.0",
3
+ "version": "2.74.2",
4
4
  "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 — async. The terminal companion for CodeAgent Mobile.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/index.js",