codeam-cli 2.42.0 → 2.43.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 +11 -0
  2. package/dist/index.js +126 -13
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,17 @@ 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.42.0] — 2026-06-24
8
+
9
+ ### Added
10
+
11
+ - **cli:** Confirm provider outage via status page on turn stall/failure (catch-all)
12
+
13
+ ### Fixed
14
+
15
+ - **cli:** Make agent-failure messaging honest — outage only on real provider error, re-auth on auth-notice replies
16
+ - **cli:** Keep the heartbeat punctual by detecting the git branch off the hot path
17
+
7
18
  ## [2.41.0] — 2026-06-24
8
19
 
9
20
  ### Added
package/dist/index.js CHANGED
@@ -476,6 +476,13 @@ function makeConfig(baseDir) {
476
476
  matches.sort((a, b) => b.pairedAt - a.pairedAt);
477
477
  return matches[0];
478
478
  }
479
+ function setDisable1mContext2(pluginId, value) {
480
+ const c2 = load();
481
+ const s = c2.sessions.find((x) => x.pluginId === pluginId);
482
+ if (!s) return;
483
+ s.disable1mContext = value;
484
+ save(c2);
485
+ }
479
486
  function clearAll2() {
480
487
  try {
481
488
  fs.unlinkSync(file);
@@ -488,7 +495,7 @@ function makeConfig(baseDir) {
488
495
  function loadCliConfig2() {
489
496
  return load();
490
497
  }
491
- return { getConfig: getConfig2, ensurePluginId: ensurePluginId2, addSession: addSession2, removeSession: removeSession2, setActiveSession: setActiveSession2, getActiveSession: getActiveSession2, getActiveSessionForAgent: getActiveSessionForAgent2, clearAll: clearAll2, saveCliConfig: saveCliConfig2, loadCliConfig: loadCliConfig2 };
498
+ return { getConfig: getConfig2, ensurePluginId: ensurePluginId2, addSession: addSession2, removeSession: removeSession2, setActiveSession: setActiveSession2, getActiveSession: getActiveSession2, getActiveSessionForAgent: getActiveSessionForAgent2, setDisable1mContext: setDisable1mContext2, clearAll: clearAll2, saveCliConfig: saveCliConfig2, loadCliConfig: loadCliConfig2 };
492
499
  }
493
500
  var CODESPACE_ENV_KEYS = [
494
501
  "PREVIEW_TUNNEL_TOKEN",
@@ -512,7 +519,7 @@ function loadCodespaceEnv() {
512
519
  }
513
520
  }
514
521
  var _default = makeConfig();
515
- var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, clearAll, saveCliConfig, loadCliConfig } = _default;
522
+ var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, setDisable1mContext, clearAll, saveCliConfig, loadCliConfig } = _default;
516
523
 
517
524
  // src/commands/pair-auto.ts
518
525
  var fs41 = __toESM(require("fs"));
@@ -5390,7 +5397,7 @@ function readAnonId() {
5390
5397
  }
5391
5398
  function superProperties() {
5392
5399
  return {
5393
- cliVersion: true ? "2.42.0" : "0.0.0-dev",
5400
+ cliVersion: true ? "2.43.0" : "0.0.0-dev",
5394
5401
  nodeVersion: process.version,
5395
5402
  platform: process.platform,
5396
5403
  arch: process.arch,
@@ -5571,7 +5578,7 @@ var os4 = __toESM(require("os"));
5571
5578
  // package.json
5572
5579
  var package_default = {
5573
5580
  name: "codeam-cli",
5574
- version: "2.42.0",
5581
+ version: "2.43.0",
5575
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.",
5576
5583
  type: "commonjs",
5577
5584
  main: "dist/index.js",
@@ -17804,7 +17811,7 @@ async function autoUpgradeBeforeCriticalCommand() {
17804
17811
  if (process.env.NODE_ENV === "test") return;
17805
17812
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17806
17813
  if (process.env.CI) return;
17807
- const current = true ? "2.42.0" : null;
17814
+ const current = true ? "2.43.0" : null;
17808
17815
  if (!current) return;
17809
17816
  const cache = readCache();
17810
17817
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17821,7 +17828,7 @@ function checkForUpdates() {
17821
17828
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17822
17829
  if (process.env.CI) return;
17823
17830
  if (!process.stdout.isTTY) return;
17824
- const current = true ? "2.42.0" : null;
17831
+ const current = true ? "2.43.0" : null;
17825
17832
  if (!current) return;
17826
17833
  const cache = readCache();
17827
17834
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -18259,7 +18266,7 @@ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process14.s
18259
18266
  detached: false
18260
18267
  });
18261
18268
  function currentCliVersion() {
18262
- return true ? "2.42.0" : null;
18269
+ return true ? "2.43.0" : null;
18263
18270
  }
18264
18271
  function runCmd(cmd, args2, timeoutMs) {
18265
18272
  return new Promise((resolve7) => {
@@ -22737,7 +22744,10 @@ var AcpClient = class {
22737
22744
  );
22738
22745
  const child = (0, import_node_child_process16.spawn)(adapter.command, adapter.args, {
22739
22746
  cwd,
22740
- env: { ...process.env, PATH: augmentedPath },
22747
+ // extraEnv (e.g. CLAUDE_CODE_DISABLE_1M_CONTEXT=1 on an on-demand
22748
+ // re-spawn) layers over process.env; PATH stays last so the augmented
22749
+ // PATH always wins.
22750
+ env: { ...process.env, ...this.opts.extraEnv ?? {}, PATH: augmentedPath },
22741
22751
  stdio: ["pipe", "pipe", "pipe"]
22742
22752
  });
22743
22753
  this.child = child;
@@ -23431,6 +23441,66 @@ function buildAcpPromptBlocks(payload) {
23431
23441
  return blocks;
23432
23442
  }
23433
23443
 
23444
+ // src/agents/acp/oneMContextRecovery.ts
23445
+ var ONE_M_CONTEXT_CREDITS_RE = /usage credits required for 1m context/i;
23446
+ function looksLike1mContextCreditsError(text) {
23447
+ return ONE_M_CONTEXT_CREDITS_RE.test(text);
23448
+ }
23449
+ var ONE_M_DISABLE_OPTION = "Disable 1M context and continue";
23450
+ function shouldOfferOneMRecovery(opts) {
23451
+ return looksLike1mContextCreditsError(opts.detail) || looksLike1mContextCreditsError(opts.recentStderr) || looksLike1mContextCreditsError(opts.finalText);
23452
+ }
23453
+ function oneMRecoverySelectPrompt() {
23454
+ return {
23455
+ question: "\u26A0\uFE0F This agent's Anthropic account needs usage credits for 1M context. You can disable 1M context (uses standard 200K context) and continue.",
23456
+ options: [ONE_M_DISABLE_OPTION]
23457
+ };
23458
+ }
23459
+ function createOneMRecovery(deps) {
23460
+ let pending = null;
23461
+ const sp = oneMRecoverySelectPrompt();
23462
+ return {
23463
+ offer: async (commandId, blocks) => {
23464
+ pending = { blocks };
23465
+ await deps.publishText(sp.question);
23466
+ await deps.publishSelectPrompt(sp.question, sp.options);
23467
+ deps.appendAgentReply(sp.question);
23468
+ deps.flushHistory();
23469
+ deps.log?.(`1M-context credits gate \u2014 recovery offered id=${commandId.slice(0, 8)}`);
23470
+ await deps.sendResult(commandId, "failed", {
23471
+ error: "1M context requires usage credits \u2014 recovery offered"
23472
+ });
23473
+ },
23474
+ tryRecover: async (commandId) => {
23475
+ if (!pending) return false;
23476
+ const blocks = pending.blocks;
23477
+ pending = null;
23478
+ deps.log?.("1M-context recovery \u2192 disable + reconnect + rerun");
23479
+ await deps.reconnectWith1mDisabled();
23480
+ await deps.beginTurn();
23481
+ try {
23482
+ const reply = await deps.promptAgent(blocks);
23483
+ const finalText = deps.getCurrentText();
23484
+ await deps.closeTurn();
23485
+ deps.appendAgentReply(finalText);
23486
+ deps.flushHistory();
23487
+ await deps.sendResult(commandId, "completed", { stopReason: reply.stopReason });
23488
+ } catch (err) {
23489
+ await deps.recoverFromFailedTurn();
23490
+ const d3 = deps.describeError(err);
23491
+ const b = deps.failureBubbleFor(d3);
23492
+ if (b) {
23493
+ await deps.publishText(b);
23494
+ deps.appendAgentReply(b);
23495
+ deps.flushHistory();
23496
+ }
23497
+ await deps.sendResult(commandId, "failed", { error: d3 });
23498
+ }
23499
+ return true;
23500
+ }
23501
+ };
23502
+ }
23503
+
23434
23504
  // src/agents/acp/reconcileDelta.ts
23435
23505
  function reconcileCumulative(existing, incoming) {
23436
23506
  if (incoming.length === 0) return existing;
@@ -24793,9 +24863,11 @@ async function runAcpSession(opts) {
24793
24863
  }
24794
24864
  });
24795
24865
  let updateCount = 0;
24796
- const client2 = new AcpClient({
24866
+ const disable1mContext = loadCliConfig().sessions.find((s) => s.pluginId === opts.pluginId)?.disable1mContext === true;
24867
+ const clientOptions = {
24797
24868
  adapter: opts.adapter,
24798
24869
  cwd: opts.cwd,
24870
+ extraEnv: disable1mContext ? { CLAUDE_CODE_DISABLE_1M_CONTEXT: "1" } : {},
24799
24871
  onSessionUpdate: (notification) => {
24800
24872
  updateCount += 1;
24801
24873
  const variant = notification.update?.sessionUpdate ?? "unknown";
@@ -24860,6 +24932,39 @@ async function runAcpSession(opts) {
24860
24932
  process.exit(1);
24861
24933
  })();
24862
24934
  }
24935
+ };
24936
+ let client2 = new AcpClient(clientOptions);
24937
+ const reconnectWith1mDisabled = async () => {
24938
+ setDisable1mContext(opts.pluginId, true);
24939
+ try {
24940
+ await client2.stop();
24941
+ } catch {
24942
+ }
24943
+ client2 = new AcpClient({ ...clientOptions, extraEnv: { CLAUDE_CODE_DISABLE_1M_CONTEXT: "1" } });
24944
+ await client2.start();
24945
+ };
24946
+ const oneMRecovery = createOneMRecovery({
24947
+ publishText: (text) => publisher.publishOutput({ type: "text", content: text, done: true }),
24948
+ publishSelectPrompt: (question, options) => publisher.publishOutput({
24949
+ type: "select_prompt",
24950
+ content: question,
24951
+ options,
24952
+ optionDescriptions: options.map(() => ""),
24953
+ currentIndex: 0,
24954
+ done: true
24955
+ }),
24956
+ sendResult: (commandId, status2, result) => relay.sendResult(commandId, status2, result),
24957
+ appendAgentReply: (text) => history.appendAgentReply(text),
24958
+ flushHistory: () => void history.flush(),
24959
+ beginTurn: () => streaming.beginTurn(),
24960
+ getCurrentText: () => streaming.getCurrentText(),
24961
+ closeTurn: () => streaming.closeTurnWithInteractiveDetection(),
24962
+ recoverFromFailedTurn: () => recoverFromFailedTurn(client2, streaming),
24963
+ reconnectWith1mDisabled,
24964
+ promptAgent: (blocks) => client2.prompt(blocks),
24965
+ failureBubbleFor: (detail) => failureBubble({ detail, recentStderr: recentStderr.join("\n"), hadText: false, agent: opts.agent }),
24966
+ describeError,
24967
+ log: (msg) => log.info("acpRunner", msg)
24863
24968
  });
24864
24969
  showInfo(`Starting ${opts.agent} via ACP adapter (${opts.adapter.requiresAgentBinary})\u2026`);
24865
24970
  const {
@@ -24954,7 +25059,8 @@ async function runAcpSession(opts) {
24954
25059
  turnFiles,
24955
25060
  getBeads,
24956
25061
  publisher,
24957
- recentStderr
25062
+ recentStderr,
25063
+ oneMRecovery
24958
25064
  );
24959
25065
  },
24960
25066
  { id: opts.agent, name: opts.agent, displayName: opts.agent }
@@ -24978,7 +25084,7 @@ async function runAcpSession(opts) {
24978
25084
  await new Promise(() => {
24979
25085
  });
24980
25086
  }
24981
- async function handleCommand(cmd, client2, relay, acpSessionId, models, streaming, opts, history, jsonlHistory, agentCaps, turnFiles, getBeads, publisher, recentStderr) {
25087
+ async function handleCommand(cmd, client2, relay, acpSessionId, models, streaming, opts, history, jsonlHistory, agentCaps, turnFiles, getBeads, publisher, recentStderr, oneMRecovery) {
24982
25088
  switch (cmd.type) {
24983
25089
  case "beads_action": {
24984
25090
  const beads = getBeads();
@@ -25029,6 +25135,8 @@ async function handleCommand(cmd, client2, relay, acpSessionId, models, streamin
25029
25135
  void reportCredentialInvalid(opts);
25030
25136
  log.info("acpRunner", `start_task \u2190 auth-failure-in-reply id=${cmd.id.slice(0, 8)}`);
25031
25137
  await relay.sendResult(cmd.id, "failed", { error: "agent reply reported auth failure" });
25138
+ } else if (shouldOfferOneMRecovery({ detail: "", recentStderr: recentStderr.join("\n"), finalText })) {
25139
+ await oneMRecovery.offer(cmd.id, blocks);
25032
25140
  } else {
25033
25141
  await streaming.closeTurnWithInteractiveDetection();
25034
25142
  const replyLine = formatAgentReplyLine(finalText);
@@ -25048,6 +25156,10 @@ async function handleCommand(cmd, client2, relay, acpSessionId, models, streamin
25048
25156
  await recoverFromFailedTurn(client2, streaming);
25049
25157
  const detail = describeError(err);
25050
25158
  log.warn("acpRunner", `prompt failed: ${detail}`);
25159
+ if (shouldOfferOneMRecovery({ detail, recentStderr: recentStderr.join("\n"), finalText: "" })) {
25160
+ await oneMRecovery.offer(cmd.id, blocks);
25161
+ return;
25162
+ }
25051
25163
  const bubble = failureBubble({
25052
25164
  detail,
25053
25165
  recentStderr: recentStderr.join("\n"),
@@ -25142,6 +25254,7 @@ async function handleCommand(cmd, client2, relay, acpSessionId, models, streamin
25142
25254
  return;
25143
25255
  }
25144
25256
  case "select_option": {
25257
+ if (await oneMRecovery.tryRecover(cmd.id)) return;
25145
25258
  const payload = cmd.payload;
25146
25259
  const index = typeof payload?.index === "number" ? payload.index : 0;
25147
25260
  const offset = typeof payload?.from === "number" ? payload.from : 0;
@@ -29211,7 +29324,7 @@ function checkChokidar() {
29211
29324
  }
29212
29325
  async function doctor(args2 = []) {
29213
29326
  const json = args2.includes("--json");
29214
- const cliVersion = true ? "2.42.0" : "0.0.0-dev";
29327
+ const cliVersion = true ? "2.43.0" : "0.0.0-dev";
29215
29328
  const apiBase2 = resolveApiBaseUrl();
29216
29329
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
29217
29330
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -29410,7 +29523,7 @@ async function completion(args2) {
29410
29523
  // src/commands/version.ts
29411
29524
  var import_picocolors14 = __toESM(require("picocolors"));
29412
29525
  function version2() {
29413
- const v = true ? "2.42.0" : "unknown";
29526
+ const v = true ? "2.43.0" : "unknown";
29414
29527
  console.log(`${import_picocolors14.default.bold("codeam-cli")} ${import_picocolors14.default.cyan(v)}`);
29415
29528
  }
29416
29529
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.42.0",
3
+ "version": "2.43.0",
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",