codeam-cli 2.67.5 → 2.67.7

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ 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.67.5] — 2026-08-27
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Un preview parado no puede resucitar por auto-sanacion
12
+
7
13
  ## [2.67.3] — 2026-08-25
8
14
 
9
15
  ### Fixed
package/dist/index.js CHANGED
@@ -8081,7 +8081,7 @@ function readAnonId() {
8081
8081
  }
8082
8082
  function superProperties() {
8083
8083
  return {
8084
- cliVersion: true ? "2.67.5" : "0.0.0-dev",
8084
+ cliVersion: true ? "2.67.7" : "0.0.0-dev",
8085
8085
  nodeVersion: process.version,
8086
8086
  platform: process.platform,
8087
8087
  arch: process.arch,
@@ -8323,7 +8323,7 @@ var http = __toESM(require("http"));
8323
8323
  // package.json
8324
8324
  var package_default = {
8325
8325
  name: "codeam-cli",
8326
- version: "2.67.5",
8326
+ version: "2.67.7",
8327
8327
  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.",
8328
8328
  type: "commonjs",
8329
8329
  main: "dist/index.js",
@@ -9855,7 +9855,7 @@ var CommandRelayService = class _CommandRelayService {
9855
9855
  // fresh + clear the "CLI update available" banner after a self-update
9856
9856
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
9857
9857
  // pair/reconnect). Older backends ignore the extra field.
9858
- ..."2.67.5" ? { ideVersion: "2.67.5" } : {}
9858
+ ..."2.67.7" ? { ideVersion: "2.67.7" } : {}
9859
9859
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
9860
9860
  }
9861
9861
  /**
@@ -19743,6 +19743,38 @@ async function linkDryRunPreflight(ctx) {
19743
19743
  process.exit(1);
19744
19744
  }
19745
19745
 
19746
+ // src/services/preview/serialized-emitter.ts
19747
+ function makeSerializedEmitter(post2) {
19748
+ let chain = Promise.resolve();
19749
+ return (args2) => {
19750
+ chain = chain.then(() => post2(args2)).then(
19751
+ () => void 0,
19752
+ () => void 0
19753
+ );
19754
+ void chain;
19755
+ };
19756
+ }
19757
+
19758
+ // src/services/preview/reaffirm.ts
19759
+ var PREVIEW_REAFFIRM_INTERVAL_MS = 5 * 6e4;
19760
+ function makePreviewHeartbeatReaffirm(deps) {
19761
+ const now = deps.now ?? Date.now;
19762
+ const intervalMs = deps.intervalMs ?? PREVIEW_REAFFIRM_INTERVAL_MS;
19763
+ let lastAffirmedAt = null;
19764
+ return ({ firstAfterConnect }) => {
19765
+ const current2 = deps.serving();
19766
+ if (!current2) {
19767
+ lastAffirmedAt = null;
19768
+ return;
19769
+ }
19770
+ const at3 = now();
19771
+ if (!firstAfterConnect && lastAffirmedAt !== null && at3 - lastAffirmedAt < intervalMs) return;
19772
+ lastAffirmedAt = at3;
19773
+ log.trace("preview", `reaffirm: preview sigue sirviendo en ${current2.url}`);
19774
+ deps.emitReady(current2);
19775
+ };
19776
+ }
19777
+
19746
19778
  // src/agents/coderabbit/configure.ts
19747
19779
  var import_node_child_process17 = require("child_process");
19748
19780
  var import_node_fs6 = require("fs");
@@ -22082,7 +22114,7 @@ async function autoUpgradeBeforeCriticalCommand() {
22082
22114
  if (process.env.NODE_ENV === "test") return;
22083
22115
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
22084
22116
  if (process.env.CI) return;
22085
- const current2 = true ? "2.67.5" : null;
22117
+ const current2 = true ? "2.67.7" : null;
22086
22118
  if (!current2) return;
22087
22119
  const cache = readCache();
22088
22120
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -22099,7 +22131,7 @@ function checkForUpdates() {
22099
22131
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
22100
22132
  if (process.env.CI) return;
22101
22133
  if (!process.stdout.isTTY) return;
22102
- const current2 = true ? "2.67.5" : null;
22134
+ const current2 = true ? "2.67.7" : null;
22103
22135
  if (!current2) return;
22104
22136
  const cache = readCache();
22105
22137
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -22122,7 +22154,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
22122
22154
  var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
22123
22155
  var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
22124
22156
  function currentCliVersion() {
22125
- return true ? "2.67.5" : null;
22157
+ return true ? "2.67.7" : null;
22126
22158
  }
22127
22159
  async function installedVersion(deps) {
22128
22160
  const ls = await deps.run(
@@ -28288,6 +28320,9 @@ function parseInsightText(text) {
28288
28320
  securityNote: securityMatch?.[1]?.trim() || void 0
28289
28321
  };
28290
28322
  }
28323
+ var emitPreviewEvent = makeSerializedEmitter(
28324
+ (args2) => postPreviewEvent(args2)
28325
+ );
28291
28326
  var requestPreviewDetectH = (ctx) => {
28292
28327
  if (!ctx.pluginAuthToken) {
28293
28328
  log.info("preview", "no pluginAuthToken \u2014 skipping detect");
@@ -28295,7 +28330,7 @@ var requestPreviewDetectH = (ctx) => {
28295
28330
  }
28296
28331
  if (typeof ctx.runtime.generateOneShot !== "function") {
28297
28332
  log.info("preview", `runtime ${ctx.runtime.id} has no generateOneShot \u2014 emitting unsupported`);
28298
- void postPreviewEvent({
28333
+ emitPreviewEvent({
28299
28334
  sessionId: ctx.sessionId,
28300
28335
  pluginId: ctx.pluginId,
28301
28336
  pluginAuthToken: ctx.pluginAuthToken,
@@ -28312,7 +28347,7 @@ var requestPreviewDetectH = (ctx) => {
28312
28347
  const fromFile = await readPreviewConfig(process.cwd());
28313
28348
  if (fromFile) {
28314
28349
  log.info("preview", `detect: using .codeam/preview.json (${fromFile.framework})`);
28315
- void postPreviewEvent({
28350
+ emitPreviewEvent({
28316
28351
  sessionId: ctx.sessionId,
28317
28352
  pluginId: ctx.pluginId,
28318
28353
  pluginAuthToken,
@@ -28321,7 +28356,7 @@ var requestPreviewDetectH = (ctx) => {
28321
28356
  });
28322
28357
  return;
28323
28358
  }
28324
- void postPreviewEvent({
28359
+ emitPreviewEvent({
28325
28360
  sessionId: ctx.sessionId,
28326
28361
  pluginId: ctx.pluginId,
28327
28362
  pluginAuthToken,
@@ -28337,7 +28372,7 @@ var requestPreviewDetectH = (ctx) => {
28337
28372
  const detection = safeParseDetection(raw);
28338
28373
  if (!detection) {
28339
28374
  log.info("preview", `detect: invalid agent output after ${tookMs}ms`);
28340
- void postPreviewEvent({
28375
+ emitPreviewEvent({
28341
28376
  sessionId: ctx.sessionId,
28342
28377
  pluginId: ctx.pluginId,
28343
28378
  pluginAuthToken,
@@ -28351,7 +28386,7 @@ var requestPreviewDetectH = (ctx) => {
28351
28386
  }
28352
28387
  if (detection.framework === "unsupported") {
28353
28388
  log.info("preview", "detect: framework=unsupported");
28354
- void postPreviewEvent({
28389
+ emitPreviewEvent({
28355
28390
  sessionId: ctx.sessionId,
28356
28391
  pluginId: ctx.pluginId,
28357
28392
  pluginAuthToken,
@@ -28367,7 +28402,7 @@ var requestPreviewDetectH = (ctx) => {
28367
28402
  void writePreviewConfig(process.cwd(), detection).catch((err) => {
28368
28403
  log.info("preview", `detect: writePreviewConfig failed (non-fatal): ${String(err)}`);
28369
28404
  });
28370
- void postPreviewEvent({
28405
+ emitPreviewEvent({
28371
28406
  sessionId: ctx.sessionId,
28372
28407
  pluginId: ctx.pluginId,
28373
28408
  pluginAuthToken,
@@ -28377,6 +28412,31 @@ var requestPreviewDetectH = (ctx) => {
28377
28412
  })();
28378
28413
  };
28379
28414
  var previewPrewarmStarted = false;
28415
+ function makePreviewReaffirm(args2) {
28416
+ const token = args2.pluginAuthToken;
28417
+ const sessionId = args2.sessionId;
28418
+ if (!token || !sessionId) return void 0;
28419
+ return makePreviewHeartbeatReaffirm({
28420
+ serving: () => {
28421
+ const active2 = activePreviews.get(sessionId);
28422
+ if (!active2 || active2.devServer.exitCode !== null) return null;
28423
+ return {
28424
+ url: active2.url,
28425
+ framework: active2.framework,
28426
+ port: active2.detection.port
28427
+ };
28428
+ },
28429
+ emitReady: (payload) => {
28430
+ emitPreviewEvent({
28431
+ sessionId,
28432
+ pluginId: args2.pluginId,
28433
+ pluginAuthToken: token,
28434
+ type: USER_EVENTS.PREVIEW_READY,
28435
+ payload
28436
+ });
28437
+ }
28438
+ });
28439
+ }
28380
28440
  function prewarmPreviewDetection(runtime) {
28381
28441
  if (previewPrewarmStarted) return;
28382
28442
  previewPrewarmStarted = true;
@@ -28412,7 +28472,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
28412
28472
  };
28413
28473
  function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
28414
28474
  const emit2 = (type, payload) => {
28415
- void postPreviewEvent({
28475
+ emitPreviewEvent({
28416
28476
  sessionId: ctx.sessionId,
28417
28477
  pluginId: ctx.pluginId,
28418
28478
  pluginAuthToken,
@@ -28455,7 +28515,7 @@ function maybeAttachBuildHeal(ctx, pluginAuthToken) {
28455
28515
  })();
28456
28516
  },
28457
28517
  notify: (message) => {
28458
- void postPreviewEvent({
28518
+ emitPreviewEvent({
28459
28519
  sessionId: ctx.sessionId,
28460
28520
  pluginId: ctx.pluginId,
28461
28521
  pluginAuthToken,
@@ -28476,7 +28536,7 @@ var previewStopH = (ctx) => {
28476
28536
  await killPreview(ctx.sessionId);
28477
28537
  resetBuildHealState(ctx.sessionId);
28478
28538
  log.info("preview", `stopped session=${ctx.sessionId}`);
28479
- void postPreviewEvent({
28539
+ emitPreviewEvent({
28480
28540
  sessionId: ctx.sessionId,
28481
28541
  pluginId: ctx.pluginId,
28482
28542
  pluginAuthToken,
@@ -28774,8 +28834,16 @@ async function startInfraOnly(agentId) {
28774
28834
  }
28775
28835
  },
28776
28836
  agentMeta,
28777
- []
28837
+ [],
28778
28838
  // empty agents list → dashboard renders NoAgentHero
28839
+ void 0,
28840
+ // El camino infra-only NO tiene agente, pero SÍ puede tener preview (es la
28841
+ // ruta del panel de archivos), así que su snapshot caduca igual.
28842
+ makePreviewReaffirm({
28843
+ sessionId: session.id,
28844
+ pluginId,
28845
+ pluginAuthToken: session.pluginAuthToken ?? void 0
28846
+ })
28779
28847
  );
28780
28848
  ctx.relay = relay;
28781
28849
  relayRef = relay;
@@ -40650,7 +40718,22 @@ async function runAcpSession(opts) {
40650
40718
  emitSwitchEvent
40651
40719
  );
40652
40720
  },
40653
- { id: opts.agent, name: opts.agent, displayName: opts.agent }
40721
+ { id: opts.agent, name: opts.agent, displayName: opts.agent },
40722
+ void 0,
40723
+ void 0,
40724
+ // Pasajero del tick de 20 s que YA existe: re-afirma el preview mientras su
40725
+ // dev server siga vivo, para que el snapshot (1 h de TTL en Redis) no
40726
+ // caduque y la sesión no vuelva al estado vacío al refrescar. Ni un
40727
+ // temporizador nuevo. Ver `services/preview/reaffirm.ts`.
40728
+ //
40729
+ // ⚠️ Va en ESTE relay, el que vive lo que dura la sesión — no en el
40730
+ // `errRelay` del camino de fallo, que es efímero y donde no hay preview
40731
+ // ninguno que afirmar.
40732
+ makePreviewReaffirm({
40733
+ sessionId: opts.sessionId,
40734
+ pluginId: opts.pluginId,
40735
+ pluginAuthToken: opts.pluginAuthToken
40736
+ })
40654
40737
  );
40655
40738
  const HANDOFF_MAX_CHARS = 16e3;
40656
40739
  const pendingHandoff = { current: null };
@@ -43276,9 +43359,23 @@ async function start(requestedAgent, presetSession) {
43276
43359
  agentId: session.agent,
43277
43360
  pluginAuthToken: session.pluginAuthToken ?? void 0
43278
43361
  };
43279
- const relay = new CommandRelayService(pluginId, async (cmd) => {
43280
- await dispatchCommand(ctx, cmd);
43281
- }, runtime.meta);
43362
+ const relay = new CommandRelayService(
43363
+ pluginId,
43364
+ async (cmd) => {
43365
+ await dispatchCommand(ctx, cmd);
43366
+ },
43367
+ runtime.meta,
43368
+ void 0,
43369
+ void 0,
43370
+ // Pasajero del tick de 20 s que ya existe: re-afirma el preview para que
43371
+ // su snapshot (1 h de TTL en Redis) no caduque con el dev server vivo.
43372
+ // Ni un temporizador nuevo. Ver `services/preview/reaffirm.ts`.
43373
+ makePreviewReaffirm({
43374
+ sessionId: session.id,
43375
+ pluginId,
43376
+ pluginAuthToken: session.pluginAuthToken
43377
+ })
43378
+ );
43282
43379
  ctx.relay = relay;
43283
43380
  void beadsReady.then((started) => {
43284
43381
  ctx.beads = started;
@@ -45893,7 +45990,7 @@ function checkChokidar() {
45893
45990
  }
45894
45991
  async function doctor(args2 = []) {
45895
45992
  const json = args2.includes("--json");
45896
- const cliVersion = true ? "2.67.5" : "0.0.0-dev";
45993
+ const cliVersion = true ? "2.67.7" : "0.0.0-dev";
45897
45994
  const apiBase2 = resolveApiBaseUrl();
45898
45995
  const diagnosticId = (0, import_node_crypto13.randomUUID)();
45899
45996
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -46284,7 +46381,7 @@ async function mcpRun(args2) {
46284
46381
  // src/commands/version.ts
46285
46382
  var import_picocolors15 = __toESM(require("picocolors"));
46286
46383
  function version2() {
46287
- const v = true ? "2.67.5" : "unknown";
46384
+ const v = true ? "2.67.7" : "unknown";
46288
46385
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
46289
46386
  }
46290
46387
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.67.5",
3
+ "version": "2.67.7",
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",