codeam-cli 2.26.7 → 2.26.8

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.26.7] — 2026-06-03
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Preview no longer pollutes the host terminal + waits for tunnel DNS (#240)
12
+
7
13
  ## [2.26.6] — 2026-06-03
8
14
 
9
15
  ### Fixed
package/dist/index.js CHANGED
@@ -472,7 +472,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
472
472
  // package.json
473
473
  var package_default = {
474
474
  name: "codeam-cli",
475
- version: "2.26.7",
475
+ version: "2.26.8",
476
476
  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.",
477
477
  type: "commonjs",
478
478
  main: "dist/index.js",
@@ -5829,7 +5829,7 @@ function readAnonId() {
5829
5829
  }
5830
5830
  function superProperties() {
5831
5831
  return {
5832
- cliVersion: true ? "2.26.7" : "0.0.0-dev",
5832
+ cliVersion: true ? "2.26.8" : "0.0.0-dev",
5833
5833
  nodeVersion: process.version,
5834
5834
  platform: process.platform,
5835
5835
  arch: process.arch,
@@ -9572,6 +9572,50 @@ function parseHistoryFile(filePath) {
9572
9572
  }
9573
9573
  return out2;
9574
9574
  }
9575
+ function listResumableSessions(cwd) {
9576
+ const dir = resolveHistoryDir(cwd);
9577
+ if (!dir) return [];
9578
+ let entries;
9579
+ try {
9580
+ entries = fs9.readdirSync(dir, { withFileTypes: true });
9581
+ } catch {
9582
+ return [];
9583
+ }
9584
+ const out2 = [];
9585
+ for (const entry of entries) {
9586
+ if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
9587
+ const id = entry.name.slice(0, -".jsonl".length);
9588
+ const filePath = path12.join(dir, entry.name);
9589
+ let timestamp = Date.now();
9590
+ try {
9591
+ timestamp = fs9.statSync(filePath).mtimeMs;
9592
+ } catch {
9593
+ }
9594
+ let summary = "";
9595
+ try {
9596
+ const raw = fs9.readFileSync(filePath, "utf8");
9597
+ for (const line of raw.split("\n")) {
9598
+ if (!line.trim()) continue;
9599
+ try {
9600
+ const record = JSON.parse(line);
9601
+ if (record["type"] === "user") {
9602
+ const msg = record["message"];
9603
+ const text = extractText(msg?.["content"]).trim();
9604
+ if (text) {
9605
+ summary = text.slice(0, 120);
9606
+ break;
9607
+ }
9608
+ }
9609
+ } catch {
9610
+ }
9611
+ }
9612
+ } catch {
9613
+ }
9614
+ if (summary) out2.push({ id, summary, timestamp });
9615
+ }
9616
+ out2.sort((a, b) => b.timestamp - a.timestamp);
9617
+ return out2;
9618
+ }
9575
9619
 
9576
9620
  // src/agents/claude/parsing.ts
9577
9621
  function filterChrome(lines) {
@@ -9933,6 +9977,9 @@ var ClaudeRuntimeStrategy = class {
9933
9977
  getCurrentUsage(historyDir) {
9934
9978
  return getCurrentUsage(historyDir);
9935
9979
  }
9980
+ listResumableSessions(cwd) {
9981
+ return listResumableSessions(cwd);
9982
+ }
9936
9983
  async fetchWeeklyUsage() {
9937
9984
  return fetchClaudeQuota();
9938
9985
  }
@@ -10297,6 +10344,84 @@ function parseHistoryFile2(filePath) {
10297
10344
  }
10298
10345
  return out2;
10299
10346
  }
10347
+ function listResumableSessions2(cwd, homeOverride) {
10348
+ const home = homeOverride ?? import_node_os.default.homedir();
10349
+ const sessionsRoot = import_node_path2.default.join(home, ".codex", "sessions");
10350
+ if (!import_node_fs3.default.existsSync(sessionsRoot)) return [];
10351
+ let resolvedCurrent;
10352
+ try {
10353
+ resolvedCurrent = import_node_fs3.default.realpathSync(cwd);
10354
+ } catch {
10355
+ resolvedCurrent = import_node_path2.default.resolve(cwd);
10356
+ }
10357
+ const out2 = [];
10358
+ const now = /* @__PURE__ */ new Date();
10359
+ for (let dayOffset = 0; dayOffset < 7; dayOffset += 1) {
10360
+ const d3 = new Date(now.getTime() - dayOffset * 24 * 60 * 60 * 1e3);
10361
+ const yyyy = String(d3.getUTCFullYear());
10362
+ const mm = String(d3.getUTCMonth() + 1).padStart(2, "0");
10363
+ const dd = String(d3.getUTCDate()).padStart(2, "0");
10364
+ const dayDir = import_node_path2.default.join(sessionsRoot, yyyy, mm, dd);
10365
+ if (!import_node_fs3.default.existsSync(dayDir)) continue;
10366
+ let dayFiles;
10367
+ try {
10368
+ dayFiles = import_node_fs3.default.readdirSync(dayDir, { withFileTypes: true });
10369
+ } catch {
10370
+ continue;
10371
+ }
10372
+ for (const entry of dayFiles) {
10373
+ if (!entry.isFile()) continue;
10374
+ if (!entry.name.startsWith("rollout-") || !entry.name.endsWith(".jsonl")) {
10375
+ continue;
10376
+ }
10377
+ const filePath = import_node_path2.default.join(dayDir, entry.name);
10378
+ let timestamp = Date.now();
10379
+ try {
10380
+ timestamp = import_node_fs3.default.statSync(filePath).mtimeMs;
10381
+ } catch {
10382
+ }
10383
+ let metaCwd;
10384
+ let metaId;
10385
+ let summary = "";
10386
+ try {
10387
+ const raw = import_node_fs3.default.readFileSync(filePath, "utf8");
10388
+ for (const line of raw.split("\n")) {
10389
+ if (!line.trim()) continue;
10390
+ const rec = parseLine(line);
10391
+ if (!rec) continue;
10392
+ if (rec.type === "session_meta") {
10393
+ const meta = rec.payload;
10394
+ metaCwd = typeof meta?.cwd === "string" ? meta.cwd : void 0;
10395
+ metaId = typeof meta?.id === "string" ? meta.id : void 0;
10396
+ continue;
10397
+ }
10398
+ if (!summary && rec.type === "response_item") {
10399
+ const payload = rec.payload;
10400
+ const msg = payload?.Message;
10401
+ if (msg && msg.role === "user") {
10402
+ const text = extractMessageText(msg.content).trim();
10403
+ if (text) summary = text.slice(0, 120);
10404
+ }
10405
+ }
10406
+ if (metaCwd !== void 0 && summary) break;
10407
+ }
10408
+ } catch {
10409
+ continue;
10410
+ }
10411
+ if (!metaCwd || !metaId || !summary) continue;
10412
+ let resolvedMeta;
10413
+ try {
10414
+ resolvedMeta = import_node_fs3.default.realpathSync(metaCwd);
10415
+ } catch {
10416
+ resolvedMeta = import_node_path2.default.resolve(metaCwd);
10417
+ }
10418
+ if (resolvedMeta !== resolvedCurrent) continue;
10419
+ out2.push({ id: metaId, summary, timestamp });
10420
+ }
10421
+ }
10422
+ out2.sort((a, b) => b.timestamp - a.timestamp);
10423
+ return out2;
10424
+ }
10300
10425
  function getCurrentUsage2(historyDir) {
10301
10426
  if (!import_node_fs3.default.existsSync(historyDir)) return null;
10302
10427
  const files = import_node_fs3.default.readdirSync(historyDir).filter((f) => f.startsWith("rollout-") && f.endsWith(".jsonl")).map((f) => ({ name: f, full: import_node_path2.default.join(historyDir, f) })).map((e) => ({ ...e, mtime: import_node_fs3.default.statSync(e.full).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
@@ -10830,6 +10955,9 @@ var CodexRuntimeStrategy = class {
10830
10955
  getCurrentUsage(historyDir) {
10831
10956
  return getCurrentUsage2(historyDir);
10832
10957
  }
10958
+ listResumableSessions(cwd) {
10959
+ return listResumableSessions2(cwd);
10960
+ }
10833
10961
  /**
10834
10962
  * Codex's quota lives behind the `account/get_account_rate_limits` RPC,
10835
10963
  * not a TUI slash command. Phase 2 ships with this stubbed to null so the
@@ -12731,52 +12859,32 @@ var HistoryService = class _HistoryService {
12731
12859
  return Math.round(totalCost * 100) / 100;
12732
12860
  }
12733
12861
  /**
12734
- * Read session list from disk and POST it to the API.
12735
- * Called once ~2 s after Claude spawns (non-blocking).
12862
+ * Push the active agent's resumable-sessions list to the backend.
12863
+ * Delegates the per-agent JSONL/rollout walk to
12864
+ * `runtime.listResumableSessions(cwd)` so each agent reads its own
12865
+ * on-disk format (Claude's JSONL files vs Codex's date-bucketed
12866
+ * rollouts). Strategies that don't yet expose the helper (Cursor,
12867
+ * Aider) cause this to no-op — the Conversations sheet on mobile
12868
+ * just shows the empty state for those agents until each one's
12869
+ * `listResumableSessions` lands.
12870
+ *
12871
+ * The push body now includes `agentId` so the backend keys by
12872
+ * (pluginId, agentId). Old CLI clients that omit `agentId` continue
12873
+ * to land in the `claude-code` slot via the backend's default.
12874
+ *
12875
+ * Called once ~2 s after the agent spawns (non-blocking).
12736
12876
  */
12737
12877
  async load() {
12738
- const dir = this.projectDir;
12739
- let entries;
12740
- try {
12741
- entries = fs20.readdirSync(dir, { withFileTypes: true });
12742
- } catch {
12878
+ if (!this.runtime.listResumableSessions) {
12743
12879
  return;
12744
12880
  }
12745
- const sessions3 = [];
12746
- for (const entry of entries) {
12747
- if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
12748
- const id = path24.basename(entry.name, ".jsonl");
12749
- const filePath = path24.join(dir, entry.name);
12750
- let mtime = Date.now();
12751
- try {
12752
- mtime = fs20.statSync(filePath).mtimeMs;
12753
- } catch {
12754
- }
12755
- let summary = "";
12756
- try {
12757
- const raw = fs20.readFileSync(filePath, "utf8");
12758
- for (const line of raw.split("\n")) {
12759
- if (!line.trim()) continue;
12760
- try {
12761
- const record = JSON.parse(line);
12762
- if (record["type"] === "user") {
12763
- const msg = record["message"];
12764
- const text = extractText2(msg?.["content"]).trim();
12765
- if (text) {
12766
- summary = text.slice(0, 120);
12767
- break;
12768
- }
12769
- }
12770
- } catch {
12771
- }
12772
- }
12773
- } catch {
12774
- }
12775
- if (summary) sessions3.push({ id, summary, timestamp: mtime });
12776
- }
12881
+ const sessions3 = this.runtime.listResumableSessions(this.cwd);
12777
12882
  if (sessions3.length === 0) return;
12778
- sessions3.sort((a, b) => b.timestamp - a.timestamp);
12779
- await post("/api/sessions/list", { pluginId: this.pluginId, sessions: sessions3 });
12883
+ await post("/api/sessions/list", {
12884
+ pluginId: this.pluginId,
12885
+ agentId: this.runtime.id,
12886
+ sessions: sessions3
12887
+ });
12780
12888
  }
12781
12889
  /**
12782
12890
  * Read a specific session's full conversation and POST it to the API in batches.
@@ -20036,7 +20144,7 @@ function checkChokidar() {
20036
20144
  }
20037
20145
  async function doctor(args2 = []) {
20038
20146
  const json = args2.includes("--json");
20039
- const cliVersion = true ? "2.26.7" : "0.0.0-dev";
20147
+ const cliVersion = true ? "2.26.8" : "0.0.0-dev";
20040
20148
  const apiBase = resolveApiBaseUrl();
20041
20149
  const diagnosticId = (0, import_node_crypto6.randomUUID)();
20042
20150
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -20235,7 +20343,7 @@ async function completion(args2) {
20235
20343
  // src/commands/version.ts
20236
20344
  var import_picocolors13 = __toESM(require("picocolors"));
20237
20345
  function version2() {
20238
- const v = true ? "2.26.7" : "unknown";
20346
+ const v = true ? "2.26.8" : "unknown";
20239
20347
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
20240
20348
  }
20241
20349
 
@@ -20463,7 +20571,7 @@ function checkForUpdates() {
20463
20571
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
20464
20572
  if (process.env.CI) return;
20465
20573
  if (!process.stdout.isTTY) return;
20466
- const current = true ? "2.26.7" : null;
20574
+ const current = true ? "2.26.8" : null;
20467
20575
  if (!current) return;
20468
20576
  const cache = readCache();
20469
20577
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.26.7",
3
+ "version": "2.26.8",
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",