codeam-cli 2.75.2 → 2.75.3

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 +20 -0
  2. package/dist/index.js +212 -66
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,26 @@ 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.75.2] — 2026-09-15
8
+
9
+ ### Added
10
+
11
+ - **shared:** Declare the credits_changed user event
12
+
13
+ ### CI
14
+
15
+ - **release:** Wait up to 7.5 min for npm to serve the published version (#754)
16
+
17
+ ### Fixed
18
+
19
+ - **cli:** A managed-rail outage must never be blamed on Anthropic (#757)
20
+
21
+ ## [2.75.1] — 2026-09-12
22
+
23
+ ### Fixed
24
+
25
+ - **cli:** Managed sessions announce the managed agent, not the Claude Code runtime (#753)
26
+
7
27
  ## [2.75.0] — 2026-09-12
8
28
 
9
29
  ### Added
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 spawn48 = this.opts.spawnImpl ?? import_node_child_process33.spawn;
275
- const child = spawn48(spec.command, spec.args, {
274
+ const spawn49 = this.opts.spawnImpl ?? import_node_child_process33.spawn;
275
+ const child = spawn49(spec.command, spec.args, {
276
276
  env: { ...process.env, ...spec.env },
277
277
  // env only — never argv
278
278
  stdio: ["pipe", "pipe", "inherit"]
@@ -300,7 +300,9 @@ var convex_admin_mcp_exports = {};
300
300
  __export(convex_admin_mcp_exports, {
301
301
  callConvexTool: () => callConvexTool,
302
302
  deploymentNameFromKey: () => deploymentNameFromKey,
303
- runConvexAdminMcp: () => runConvexAdminMcp
303
+ resolveConvexBin: () => resolveConvexBin,
304
+ runConvexAdminMcp: () => runConvexAdminMcp,
305
+ runConvexDeploy: () => runConvexDeploy
304
306
  });
305
307
  function deploymentNameFromKey(key) {
306
308
  const prefix = key.split("|")[0];
@@ -310,6 +312,81 @@ function deploymentNameFromKey(key) {
310
312
  }
311
313
  return null;
312
314
  }
315
+ function defaultSpawn(timeoutMs) {
316
+ return (cmd, args2, opts) => new Promise((resolve11) => {
317
+ let out2 = "";
318
+ let err = "";
319
+ let done = false;
320
+ const finish = (code) => {
321
+ if (done) return;
322
+ done = true;
323
+ resolve11({ code, stdout: out2, stderr: err });
324
+ };
325
+ let child;
326
+ try {
327
+ child = (0, import_node_child_process34.spawn)(cmd, args2, { cwd: opts.cwd, env: opts.env, stdio: ["ignore", "pipe", "pipe"] });
328
+ } catch (e) {
329
+ finish(1);
330
+ err = e instanceof Error ? e.message : String(e);
331
+ return;
332
+ }
333
+ const timer = setTimeout(() => {
334
+ try {
335
+ child.kill("SIGKILL");
336
+ } catch {
337
+ }
338
+ err += `
339
+ [codeam] convex deploy timed out after ${Math.round(timeoutMs / 1e3)}s`;
340
+ finish(124);
341
+ }, timeoutMs);
342
+ child.stdout?.on("data", (c2) => {
343
+ out2 += c2.toString();
344
+ });
345
+ child.stderr?.on("data", (c2) => {
346
+ err += c2.toString();
347
+ });
348
+ child.on("error", (e) => {
349
+ clearTimeout(timer);
350
+ err += (err ? "\n" : "") + e.message;
351
+ finish(1);
352
+ });
353
+ child.on("close", (code) => {
354
+ clearTimeout(timer);
355
+ finish(code ?? 1);
356
+ });
357
+ });
358
+ }
359
+ function resolveConvexBin(cwd) {
360
+ const local = path95.join(cwd, "node_modules", ".bin", process.platform === "win32" ? "convex.cmd" : "convex");
361
+ if (fs83.existsSync(local)) return { cmd: local, args: [] };
362
+ return { cmd: "npx", args: ["--yes", "convex"] };
363
+ }
364
+ function redact(text, key) {
365
+ if (!key) return text;
366
+ return text.split(key).join("***");
367
+ }
368
+ async function runConvexDeploy(key, args2, opts = {}) {
369
+ const cwd = args2.projectDir ?? opts.cwd ?? process.cwd();
370
+ const timeoutMs = opts.timeoutMs ?? 3e5;
371
+ const run = opts.spawnImpl ?? defaultSpawn(timeoutMs);
372
+ const bin = resolveConvexBin(cwd);
373
+ const argv = [...bin.args, "deploy"];
374
+ if (args2.previewName) argv.push("--preview-create", String(args2.previewName));
375
+ const { code, stdout, stderr } = await run(bin.cmd, argv, {
376
+ cwd,
377
+ // The ONLY place the secret travels.
378
+ env: { ...process.env, CONVEX_DEPLOY_KEY: key }
379
+ });
380
+ const body = redact([stdout, stderr].filter(Boolean).join("\n").trim(), key);
381
+ if (code === 0) {
382
+ return { ok: true, text: body || "Convex deploy completed." };
383
+ }
384
+ return {
385
+ ok: false,
386
+ text: `Convex deploy failed (exit ${code}).
387
+ ${body}`
388
+ };
389
+ }
313
390
  async function adminQuery(baseUrl, key, api, body, fetchImpl = fetch) {
314
391
  const res = await fetchImpl(`${baseUrl}/api/${api}`, {
315
392
  method: "POST",
@@ -320,7 +397,24 @@ async function adminQuery(baseUrl, key, api, body, fetchImpl = fetch) {
320
397
  const ok = res.ok && !/"status"\s*:\s*"error"/.test(text);
321
398
  return { ok, text };
322
399
  }
323
- async function callConvexTool(baseUrl, key, tool, args2, fetchImpl = fetch) {
400
+ async function callConvexTool(baseUrl, key, tool, args2, fetchImpl = fetch, deployOpts = {}) {
401
+ switch (tool) {
402
+ case "deploy":
403
+ return runConvexDeploy(
404
+ key,
405
+ {
406
+ projectDir: typeof args2.projectDir === "string" ? args2.projectDir : void 0,
407
+ previewName: typeof args2.previewName === "string" ? args2.previewName : void 0
408
+ },
409
+ deployOpts
410
+ );
411
+ }
412
+ if (!baseUrl) {
413
+ return {
414
+ ok: false,
415
+ text: `The connected Convex deploy key is a PROJECT key, which names no single deployment, so '${tool}' (and the other data tools) cannot reach one. Use the 'deploy' tool \u2014 it resolves the target from the key itself \u2014 or reconnect Convex with a dev/prod deploy key (Convex Dashboard \u2192 Project Settings \u2192 Deploy Keys) to enable the data tools.`
416
+ };
417
+ }
324
418
  switch (tool) {
325
419
  case "tables":
326
420
  return adminQuery(baseUrl, key, "query", {
@@ -362,12 +456,11 @@ async function runConvexAdminMcp(client3, id) {
362
456
  const name = deploymentNameFromKey(key);
363
457
  if (!name) {
364
458
  process.stderr.write(
365
- `[codeam mcp-run convex] could not derive a deployment from the deploy key (expected a dev/prod deploy key like dev:name|\u2026 \u2014 got prefix "${key.split(":")[0]}"). Generate a deploy key at Convex Dashboard \u2192 Project Settings \u2192 Deploy Keys.
459
+ `[codeam mcp-run convex] the deploy key names no single deployment (prefix "${key.split(":")[0]}"): the data tools are unavailable, 'deploy' still works. For the data tools, reconnect with a dev/prod deploy key (Convex Dashboard \u2192 Project Settings \u2192 Deploy Keys).
366
460
  `
367
461
  );
368
- process.exit(1);
369
462
  }
370
- const baseUrl = `https://${name}.convex.cloud`;
463
+ const baseUrl = name ? `https://${name}.convex.cloud` : "";
371
464
  const { Server } = await import("@modelcontextprotocol/sdk/server/index.js");
372
465
  const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
373
466
  const { ListToolsRequestSchema, CallToolRequestSchema } = await import("@modelcontextprotocol/sdk/types.js");
@@ -396,10 +489,13 @@ async function runConvexAdminMcp(client3, id) {
396
489
  });
397
490
  await server.connect(new StdioServerTransport());
398
491
  }
399
- var TOOLS;
492
+ var import_node_child_process34, fs83, path95, TOOLS;
400
493
  var init_convex_admin_mcp = __esm({
401
494
  "src/integrations/convex-admin-mcp.ts"() {
402
495
  "use strict";
496
+ import_node_child_process34 = require("child_process");
497
+ fs83 = __toESM(require("fs"));
498
+ path95 = __toESM(require("path"));
403
499
  TOOLS = [
404
500
  {
405
501
  name: "tables",
@@ -449,6 +545,24 @@ var init_convex_admin_mcp = __esm({
449
545
  required: ["functionPath"],
450
546
  additionalProperties: false
451
547
  }
548
+ },
549
+ {
550
+ name: "deploy",
551
+ description: 'Deploy this repo\'s `convex/` functions, schema and indexes to the Convex deployment this integration is connected to. Use this after editing anything under `convex/` \u2014 a function you just wrote does NOT exist for the running app until it is deployed ("Could not find public function for ..." means exactly this). Do NOT run `npx convex deploy` or `npx convex dev` in the shell: those need an interactive login, and this tool already holds the credential.',
552
+ inputSchema: {
553
+ type: "object",
554
+ properties: {
555
+ projectDir: {
556
+ type: "string",
557
+ description: "Repo root holding the `convex/` directory. Defaults to the session cwd."
558
+ },
559
+ previewName: {
560
+ type: "string",
561
+ description: "Only for a PREVIEW deploy key: name the preview deployment to create (e.g. a branch name)."
562
+ }
563
+ },
564
+ additionalProperties: false
565
+ }
452
566
  }
453
567
  ];
454
568
  }
@@ -889,12 +1003,34 @@ var AGENT_REGISTRY = {
889
1003
  displayName: "Gemini CLI",
890
1004
  binaryName: "gemini",
891
1005
  enabled: true,
892
- // OAuth via `gemini auth login` (captured by `codeam link gemini`
893
- // from ~/.gemini/oauth_creds.json) AND GEMINI_API_KEY are both
894
- // accepted by the backend's GeminiProvisioningStrategy and propagated
895
- // into codespace deploys.
896
- supportedAuthKinds: ["oauth_token", "api_key"],
897
- preferredAuthKind: "oauth_token",
1006
+ // ⚠️ API KEY ONLY since 2026-06-18, when Google stopped Gemini CLI (and the
1007
+ // Gemini Code Assist IDE extensions) serving requests for AI Pro, AI Ultra
1008
+ // and free users, in the move to Antigravity CLI. Its announcement is
1009
+ // explicit about what survives: "Gemini CLI will remain accessible via paid
1010
+ // Gemini and Gemini Enterprise Agent Platform API keys."
1011
+ //
1012
+ // So the agent stays — `@google/gemini-cli` is NOT deprecated, it still
1013
+ // ships weekly — but the OAuth door has to go: it captures a
1014
+ // `~/.gemini/oauth_creds.json` from a CONSUMER Google account, which is
1015
+ // exactly the tier that no longer serves requests. We used to PREFER that
1016
+ // path, so it was the one we recommended first; on 2026-09-15 prod held 63
1017
+ // Gemini links, 46 of them OAuth, 19 created after 2026-09-01 and the
1018
+ // newest that same day. Three months of sending people through a bricked
1019
+ // door — each one landing on `isGeminiIneligibleTier` at first use.
1020
+ //
1021
+ // ⚠️ Antigravity CLI is NOT a drop-in replacement for us: no official ACP
1022
+ // mode (google-antigravity/antigravity-cli#31 open, 192 comments, zero
1023
+ // `acp` hits in the repo as of 2026-09-15), and every third-party ACP
1024
+ // adapter warns that driving `agy` that way matches what Google's FAQ calls
1025
+ // a ToS violation — risking the USER's Google account. Our whole Gemini
1026
+ // path is ACP, so adopting it would mean shipping that risk. Revisit only
1027
+ // when #31 ships an official mode.
1028
+ //
1029
+ // Existing OAuth rows are NOT migrated: `supportedAuthMethods` gates the
1030
+ // LINK call only, so the 46 stay readable and simply keep failing at the
1031
+ // provider, where the ineligible-tier message already explains why.
1032
+ supportedAuthKinds: ["api_key"],
1033
+ preferredAuthKind: "api_key",
898
1034
  // Not listed by `headroom wrap --help` — runs native.
899
1035
  headroomWrappable: false,
900
1036
  // Native ACP server: `gemini --skip-trust --acp`.
@@ -2058,6 +2194,16 @@ var INTEGRATION_REGISTRY = {
2058
2194
  // tools ourselves via a BUILT-IN MCP (delivery.builtin) against that admin
2059
2195
  // API — see apps/cli/src/integrations/convex-admin-mcp.ts. The user still
2060
2196
  // pastes a deploy key (Dashboard → Project Settings → Deploy Keys).
2197
+ //
2198
+ // ⚠️ That built-in ALSO owns `deploy`, and it is the only way an agent can
2199
+ // push `convex/` changes. Deploying is bundle + push, not a REST call, so
2200
+ // that one tool drives Convex's own CLI with the deploy key injected into
2201
+ // THAT CHILD's env — the agent's shell never sees the credential. Before
2202
+ // it existed the agent had the credential's power through the MCP but no
2203
+ // way to deploy, so it looped on `npx convex dev` (interactive login) and
2204
+ // asked the user to paste the token into the chat; the user ended up
2205
+ // re-entering the SAME key by hand in Environment Variables, after burning
2206
+ // real credits (2026-09-15).
2061
2207
  enabled: true,
2062
2208
  auth: {
2063
2209
  kind: "api_key",
@@ -3256,11 +3402,11 @@ function quiet(fn) {
3256
3402
  log.debug(TAG, "ignored sync error", err);
3257
3403
  }
3258
3404
  }
3259
- function rmIfExistsQuiet(path96) {
3405
+ function rmIfExistsQuiet(path97) {
3260
3406
  try {
3261
- fs2.rmSync(path96, { force: true });
3407
+ fs2.rmSync(path97, { force: true });
3262
3408
  } catch (err) {
3263
- log.debug(TAG, `rmIfExists failed for ${path96}`, err);
3409
+ log.debug(TAG, `rmIfExists failed for ${path97}`, err);
3264
3410
  }
3265
3411
  }
3266
3412
  function killQuiet(target, signal = "SIGTERM") {
@@ -3467,8 +3613,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
3467
3613
  return decodedFile;
3468
3614
  };
3469
3615
  }
3470
- function normalizeWindowsPath(path96) {
3471
- return path96.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
3616
+ function normalizeWindowsPath(path97) {
3617
+ return path97.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
3472
3618
  }
3473
3619
 
3474
3620
  // ../../node_modules/@posthog/core/dist/error-tracking/index.mjs
@@ -6201,13 +6347,13 @@ var PostHogCoreStateless = class {
6201
6347
  sentFromRoute += batchMessages.length;
6202
6348
  }
6203
6349
  }
6204
- async _sendOtlpBatch({ path: path96, payload }) {
6350
+ async _sendOtlpBatch({ path: path97, payload }) {
6205
6351
  if (this.disabled) return {
6206
6352
  kind: "fatal",
6207
6353
  error: new Error("The client is disabled")
6208
6354
  };
6209
6355
  const serialized = JSON.stringify(payload);
6210
- const url2 = `${this.host}/i/v1/${path96}?token=${encodeURIComponent(this.apiKey)}`;
6356
+ const url2 = `${this.host}/i/v1/${path97}?token=${encodeURIComponent(this.apiKey)}`;
6211
6357
  const gzippedPayload = this.disableCompression ? null : await this.compressPayload(serialized);
6212
6358
  const fetchOptions = {
6213
6359
  method: "POST",
@@ -7447,14 +7593,14 @@ async function addSourceContext(frames, openSourceFile = import_promises.open, l
7447
7593
  LRU_FILE_CONTENTS_CACHE.reduce();
7448
7594
  return frames;
7449
7595
  }
7450
- async function openRegularSourceFile(path96, openSourceFile, logger) {
7596
+ async function openRegularSourceFile(path97, openSourceFile, logger) {
7451
7597
  let fileHandle;
7452
7598
  let isValid = false;
7453
7599
  try {
7454
- fileHandle = await openSourceFile(path96, import_node_fs.constants.O_RDONLY | import_node_fs.constants.O_NONBLOCK);
7600
+ fileHandle = await openSourceFile(path97, import_node_fs.constants.O_RDONLY | import_node_fs.constants.O_NONBLOCK);
7455
7601
  const fileStat = await fileHandle.stat();
7456
7602
  if (!fileStat.isFile()) return;
7457
- if (fileStat.size > MAX_CONTEXTLINES_FILE_SIZE) return void logger?.debug(`Skipping source context for oversized file ${path96}: ${fileStat.size} bytes exceeds ${MAX_CONTEXTLINES_FILE_SIZE}`);
7603
+ if (fileStat.size > MAX_CONTEXTLINES_FILE_SIZE) return void logger?.debug(`Skipping source context for oversized file ${path97}: ${fileStat.size} bytes exceeds ${MAX_CONTEXTLINES_FILE_SIZE}`);
7458
7604
  isValid = true;
7459
7605
  return fileHandle;
7460
7606
  } catch {
@@ -7464,8 +7610,8 @@ async function openRegularSourceFile(path96, openSourceFile, logger) {
7464
7610
  });
7465
7611
  }
7466
7612
  }
7467
- async function getContextLinesFromFile(path96, ranges, output, cacheKey, openSourceFile, logger) {
7468
- const fileHandle = await openRegularSourceFile(path96, openSourceFile, logger);
7613
+ async function getContextLinesFromFile(path97, ranges, output, cacheKey, openSourceFile, logger) {
7614
+ const fileHandle = await openRegularSourceFile(path97, openSourceFile, logger);
7469
7615
  if (void 0 === fileHandle) return void LRU_FILE_CONTENTS_FS_READ_FAILED.set(cacheKey, 1);
7470
7616
  const openedFileHandle = fileHandle;
7471
7617
  return new Promise((resolve11) => {
@@ -7567,22 +7713,22 @@ function clearLineContext(frame) {
7567
7713
  delete frame.context_line;
7568
7714
  delete frame.post_context;
7569
7715
  }
7570
- function shouldSkipContextLinesForFile(path96) {
7571
- return path96.startsWith("node:") || path96.endsWith(".min.js") || path96.endsWith(".min.cjs") || path96.endsWith(".min.mjs") || path96.startsWith("data:");
7716
+ function shouldSkipContextLinesForFile(path97) {
7717
+ return path97.startsWith("node:") || path97.endsWith(".min.js") || path97.endsWith(".min.cjs") || path97.endsWith(".min.mjs") || path97.startsWith("data:");
7572
7718
  }
7573
7719
  function shouldSkipContextLinesForFrame(frame) {
7574
7720
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
7575
7721
  if (void 0 !== frame.colno && frame.colno > MAX_CONTEXTLINES_COLNO) return true;
7576
7722
  return false;
7577
7723
  }
7578
- function makeSourceCacheKey(path96, basePath) {
7579
- if ((0, import_node_path.isAbsolute)(path96)) return JSON.stringify([
7724
+ function makeSourceCacheKey(path97, basePath) {
7725
+ if ((0, import_node_path.isAbsolute)(path97)) return JSON.stringify([
7580
7726
  null,
7581
- path96
7727
+ path97
7582
7728
  ]);
7583
7729
  return void 0 === basePath ? void 0 : JSON.stringify([
7584
7730
  basePath,
7585
- path96
7731
+ path97
7586
7732
  ]);
7587
7733
  }
7588
7734
  function rangeExistsInContentCache(cacheKey, range) {
@@ -10243,7 +10389,7 @@ function readAnonId() {
10243
10389
  }
10244
10390
  function superProperties() {
10245
10391
  return {
10246
- cliVersion: true ? "2.75.2" : "0.0.0-dev",
10392
+ cliVersion: true ? "2.75.3" : "0.0.0-dev",
10247
10393
  nodeVersion: process.version,
10248
10394
  platform: process.platform,
10249
10395
  arch: process.arch,
@@ -10485,7 +10631,7 @@ var http = __toESM(require("http"));
10485
10631
  // package.json
10486
10632
  var package_default = {
10487
10633
  name: "codeam-cli",
10488
- version: "2.75.2",
10634
+ version: "2.75.3",
10489
10635
  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.",
10490
10636
  type: "commonjs",
10491
10637
  main: "dist/index.js",
@@ -12176,7 +12322,7 @@ var CommandRelayService = class _CommandRelayService {
12176
12322
  // fresh + clear the "CLI update available" banner after a self-update
12177
12323
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
12178
12324
  // pair/reconnect). Older backends ignore the extra field.
12179
- ..."2.75.2" ? { ideVersion: "2.75.2" } : {}
12325
+ ..."2.75.3" ? { ideVersion: "2.75.3" } : {}
12180
12326
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
12181
12327
  }
12182
12328
  /**
@@ -19812,8 +19958,8 @@ function pickLine(obj) {
19812
19958
  function toHunk(raw, groupSeverity) {
19813
19959
  if (!raw || typeof raw !== "object") return null;
19814
19960
  const o = raw;
19815
- const path96 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
19816
- if (!path96) return null;
19961
+ const path97 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
19962
+ if (!path97) return null;
19817
19963
  const message = asString(
19818
19964
  pick(o, [
19819
19965
  "comment",
@@ -19830,7 +19976,7 @@ function toHunk(raw, groupSeverity) {
19830
19976
  const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
19831
19977
  const locObj = pick(o, ["location"]) ?? o;
19832
19978
  return {
19833
- path: path96.trim(),
19979
+ path: path97.trim(),
19834
19980
  line: pickLine(o) ?? pickLine(locObj),
19835
19981
  severity,
19836
19982
  message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
@@ -19913,10 +20059,10 @@ function parsePlain(stdout) {
19913
20059
  for (const line of stdout.split(/\r?\n/)) {
19914
20060
  const m = line.match(HUNK_LINE_RE);
19915
20061
  if (!m) continue;
19916
- const [, path96, lineNo, sevToken, message] = m;
19917
- if (!path96 || !lineNo || !message) continue;
20062
+ const [, path97, lineNo, sevToken, message] = m;
20063
+ if (!path97 || !lineNo || !message) continue;
19918
20064
  hunks.push({
19919
- path: path96.trim(),
20065
+ path: path97.trim(),
19920
20066
  line: Number(lineNo),
19921
20067
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
19922
20068
  message: message.trim().replace(/^[*-]\s+/, "")
@@ -20634,14 +20780,14 @@ function defaultSdkDir() {
20634
20780
  return resolveSdkDirViaRequire();
20635
20781
  }
20636
20782
  function resolveClaudeNativeBinary(deps = {}) {
20637
- const existsSync29 = deps.existsSync ?? import_fs.default.existsSync;
20783
+ const existsSync30 = deps.existsSync ?? import_fs.default.existsSync;
20638
20784
  const platformKey = deps.platformKey ?? currentPlatformKey();
20639
20785
  const sdkDir = deps.sdkDir !== void 0 ? deps.sdkDir : defaultSdkDir();
20640
20786
  if (!sdkDir) return null;
20641
20787
  const scopeDir = import_path4.default.dirname(sdkDir);
20642
20788
  const binName = platformKey.startsWith("win32-") ? "claude.exe" : "claude";
20643
20789
  const candidate = import_path4.default.join(scopeDir, `claude-agent-sdk-${platformKey}`, binName);
20644
- return existsSync29(candidate) ? candidate : null;
20790
+ return existsSync30(candidate) ? candidate : null;
20645
20791
  }
20646
20792
  var realSleep = (ms) => new Promise((resolve11) => setTimeout(resolve11, ms));
20647
20793
  async function waitForClaudeNativeBinary(opts = {}) {
@@ -20723,18 +20869,18 @@ function augmentUserLocalBinPaths(deps = {}) {
20723
20869
  env.PATH = [...additions, ...parts].join(p2.delimiter);
20724
20870
  }
20725
20871
  function resolveCursorAgentBinary(deps = {}) {
20726
- const existsSync29 = deps.existsSync ?? import_fs.default.existsSync;
20872
+ const existsSync30 = deps.existsSync ?? import_fs.default.existsSync;
20727
20873
  const platform3 = deps.platform ?? process.platform;
20728
20874
  const env = deps.env ?? process.env;
20729
20875
  if (platform3 === "win32") {
20730
20876
  const localAppData = env.LOCALAPPDATA;
20731
20877
  if (!localAppData) return null;
20732
20878
  const exe = import_path4.default.win32.join(localAppData, "cursor-agent", "cursor-agent.exe");
20733
- return existsSync29(exe) ? exe : null;
20879
+ return existsSync30(exe) ? exe : null;
20734
20880
  }
20735
20881
  const home = deps.homedir ?? import_os4.default.homedir();
20736
20882
  const unix = import_path4.default.posix.join(home, ".local", "bin", "cursor-agent");
20737
- return existsSync29(unix) ? unix : null;
20883
+ return existsSync30(unix) ? unix : null;
20738
20884
  }
20739
20885
  async function waitForCursorAgent(opts = {}) {
20740
20886
  const timeoutMs = opts.timeoutMs ?? 18e4;
@@ -24510,7 +24656,7 @@ async function autoUpgradeBeforeCriticalCommand() {
24510
24656
  if (process.env.NODE_ENV === "test") return;
24511
24657
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
24512
24658
  if (process.env.CI) return;
24513
- const current2 = true ? "2.75.2" : null;
24659
+ const current2 = true ? "2.75.3" : null;
24514
24660
  if (!current2) return;
24515
24661
  const cache = readCache();
24516
24662
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -24527,7 +24673,7 @@ function checkForUpdates() {
24527
24673
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
24528
24674
  if (process.env.CI) return;
24529
24675
  if (!process.stdout.isTTY) return;
24530
- const current2 = true ? "2.75.2" : null;
24676
+ const current2 = true ? "2.75.3" : null;
24531
24677
  if (!current2) return;
24532
24678
  const cache = readCache();
24533
24679
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -24550,7 +24696,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
24550
24696
  var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
24551
24697
  var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
24552
24698
  function currentCliVersion() {
24553
- return true ? "2.75.2" : null;
24699
+ return true ? "2.75.3" : null;
24554
24700
  }
24555
24701
  async function installedVersion(deps) {
24556
24702
  const ls = await deps.run(
@@ -26527,7 +26673,7 @@ async function defaultFetchJson(url2) {
26527
26673
  async function readUsageReport(deps = {}) {
26528
26674
  const port = deps.port ?? HEADROOM_PROXY_PORT;
26529
26675
  const base = `http://127.0.0.1:${port}`;
26530
- const get4 = deps.fetchJson ?? ((path96) => defaultFetchJson(`${base}${path96}`));
26676
+ const get4 = deps.fetchJson ?? ((path97) => defaultFetchJson(`${base}${path97}`));
26531
26677
  let history;
26532
26678
  try {
26533
26679
  history = await get4("/stats-history");
@@ -32301,11 +32447,11 @@ function resolveTokenValue(args2) {
32301
32447
  }
32302
32448
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
32303
32449
  if (fileFlag) {
32304
- const path96 = fileFlag.slice("--token-file=".length);
32450
+ const path97 = fileFlag.slice("--token-file=".length);
32305
32451
  try {
32306
- const content = fs66.readFileSync(path96, "utf8").trim();
32307
- if (content.length === 0) fail(`--token-file ${path96} is empty`);
32308
- rmIfExistsQuiet(path96);
32452
+ const content = fs66.readFileSync(path97, "utf8").trim();
32453
+ if (content.length === 0) fail(`--token-file ${path97} is empty`);
32454
+ rmIfExistsQuiet(path97);
32309
32455
  return content;
32310
32456
  } catch (err) {
32311
32457
  fail(`Could not read --token-file: ${err.message}`);
@@ -39238,12 +39384,12 @@ function buildRelaunchProxyEnv(baseEnv) {
39238
39384
  return env;
39239
39385
  }
39240
39386
  var relaunchProxyWithoutBudget = async () => {
39241
- const { spawn: spawn48 } = await import("child_process");
39387
+ const { spawn: spawn49 } = await import("child_process");
39242
39388
  killHeadroomProxy();
39243
39389
  await new Promise((r) => setTimeout(r, 500));
39244
39390
  const proxyEnv = buildRelaunchProxyEnv(process.env);
39245
39391
  try {
39246
- const proxy = spawn48(
39392
+ const proxy = spawn49(
39247
39393
  "headroom",
39248
39394
  ["proxy", "--port", "8787"],
39249
39395
  { stdio: "ignore", detached: true, env: proxyEnv }
@@ -40775,7 +40921,7 @@ function defaultRunGit(cwd, args2) {
40775
40921
  });
40776
40922
  }
40777
40923
  async function discoverRepos(workingDir, maxDepth = 4) {
40778
- const fs83 = await import("fs/promises");
40924
+ const fs84 = await import("fs/promises");
40779
40925
  const out2 = [];
40780
40926
  await walk(workingDir, 0);
40781
40927
  return out2;
@@ -40783,7 +40929,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
40783
40929
  if (depth > maxDepth) return;
40784
40930
  let entries = [];
40785
40931
  try {
40786
- const dirents = await fs83.readdir(dir, { withFileTypes: true });
40932
+ const dirents = await fs84.readdir(dir, { withFileTypes: true });
40787
40933
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
40788
40934
  } catch {
40789
40935
  return;
@@ -49989,7 +50135,7 @@ function checkChokidar() {
49989
50135
  }
49990
50136
  async function doctor(args2 = []) {
49991
50137
  const json = args2.includes("--json");
49992
- const cliVersion = true ? "2.75.2" : "0.0.0-dev";
50138
+ const cliVersion = true ? "2.75.3" : "0.0.0-dev";
49993
50139
  const apiBase2 = resolveApiBaseUrl();
49994
50140
  const diagnosticId = (0, import_node_crypto13.randomUUID)();
49995
50141
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -50186,7 +50332,7 @@ async function completion(args2) {
50186
50332
  }
50187
50333
 
50188
50334
  // src/integrations/mcp-run.ts
50189
- var import_node_child_process34 = require("child_process");
50335
+ var import_node_child_process35 = require("child_process");
50190
50336
 
50191
50337
  // src/integrations/launcher-env.ts
50192
50338
  var LAUNCHER_ENV = Object.freeze({
@@ -50270,7 +50416,7 @@ function resolveDelivery(id) {
50270
50416
  function commandExists(command2) {
50271
50417
  try {
50272
50418
  const probe = process.platform === "win32" ? "where" : "which";
50273
- (0, import_node_child_process34.execFileSync)(probe, [command2], { stdio: "ignore" });
50419
+ (0, import_node_child_process35.execFileSync)(probe, [command2], { stdio: "ignore" });
50274
50420
  return true;
50275
50421
  } catch {
50276
50422
  return false;
@@ -50303,7 +50449,7 @@ function ensureCommand(command2) {
50303
50449
  }
50304
50450
  if (command2 === "uvx") {
50305
50451
  try {
50306
- (0, import_node_child_process34.execSync)("curl -LsSf https://astral.sh/uv/install.sh | sh", {
50452
+ (0, import_node_child_process35.execSync)("curl -LsSf https://astral.sh/uv/install.sh | sh", {
50307
50453
  stdio: ["ignore", process.stderr, process.stderr],
50308
50454
  timeout: 18e4,
50309
50455
  env: { ...process.env, UV_NO_MODIFY_PATH: "1" }
@@ -50312,7 +50458,7 @@ function ensureCommand(command2) {
50312
50458
  }
50313
50459
  if (resolveLauncherPath(command2) !== command2) return;
50314
50460
  try {
50315
- (0, import_node_child_process34.execSync)("python3 -m pip install --user --quiet uv", {
50461
+ (0, import_node_child_process35.execSync)("python3 -m pip install --user --quiet uv", {
50316
50462
  stdio: ["ignore", process.stderr, process.stderr],
50317
50463
  timeout: 18e4
50318
50464
  });
@@ -50390,7 +50536,7 @@ async function mcpRun(args2) {
50390
50536
  }
50391
50537
 
50392
50538
  // src/integrations/mcp-warm.ts
50393
- var import_node_child_process35 = require("child_process");
50539
+ var import_node_child_process36 = require("child_process");
50394
50540
  function specOf(delivery) {
50395
50541
  if (!delivery.command) return null;
50396
50542
  const spec = (delivery.args ?? []).find((a) => !a.startsWith("-"));
@@ -50434,7 +50580,7 @@ var WARM_TOTAL_BUDGET_MS = 10 * 6e4;
50434
50580
  var WARM_CONCURRENCY = 4;
50435
50581
  function runCapturing(command2, args2, timeoutMs) {
50436
50582
  return new Promise((resolve11) => {
50437
- const child = (0, import_node_child_process35.spawn)(command2, args2, {
50583
+ const child = (0, import_node_child_process36.spawn)(command2, args2, {
50438
50584
  env: { ...process.env, ...LAUNCHER_ENV },
50439
50585
  stdio: ["ignore", "ignore", "pipe"],
50440
50586
  // `npx`/`uv` are `.cmd` shims on Windows; Node ≥ 20.12 refuses to spawn a
@@ -50513,7 +50659,7 @@ async function mcpWarm(argv = [], opts = {}) {
50513
50659
  // src/commands/version.ts
50514
50660
  var import_picocolors15 = __toESM(require("picocolors"));
50515
50661
  function version2() {
50516
- const v = true ? "2.75.2" : "unknown";
50662
+ const v = true ? "2.75.3" : "unknown";
50517
50663
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
50518
50664
  }
50519
50665
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.75.2",
3
+ "version": "2.75.3",
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",