codeam-cli 2.60.9 → 2.60.11

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,18 @@ 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.60.10] — 2026-07-08
8
+
9
+ ### Added
10
+
11
+ - **cli:** Detailed observability for the gemini baton paths
12
+
13
+ ## [2.60.9] — 2026-07-08
14
+
15
+ ### Added
16
+
17
+ - **cli:** Baton support for gemini (native-TUI mirror + resume)
18
+
7
19
  ## [2.60.8] — 2026-07-08
8
20
 
9
21
  ### Fixed
package/dist/index.js CHANGED
@@ -220,15 +220,18 @@ var MODEL_PRICING = {
220
220
  "claude-3-5-haiku": { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },
221
221
  "claude-3-haiku": { input: 0.25, output: 1.25, cacheRead: 0.03, cacheWrite: 0.3 },
222
222
  // ── Codex / OpenAI ────────────────────────────────────────
223
- // Phase 2 placeholder pricing: 0 across the board until OpenAI publishes
224
- // confirmed rates for the GPT-5.x catalog. Sync from
225
- // developers.openai.com/pricing when available.
226
- "gpt-5.5": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
227
- "gpt-5.4": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
228
- "gpt-5.4-mini": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
229
- "gpt-5.3-codex": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
230
- "gpt-5.2": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
231
- "codex-auto-review": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }
223
+ // GPT-5.x rows are derived from OpenAI's published GPT-5 family rates
224
+ // (standard tier: $1.25/1M in, $10/1M out, cached input at ~10% of input;
225
+ // mini tier: $0.25/1M in, $2/1M out). OpenAI has no separate cache-WRITE
226
+ // premium, so cacheWrite mirrors the input rate. Replace with the exact
227
+ // per-version numbers from developers.openai.com/pricing when published
228
+ // these were the ZERO placeholders that rendered Codex sessions as $0.
229
+ "gpt-5.5": { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 1.25 },
230
+ "gpt-5.4": { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 1.25 },
231
+ "gpt-5.4-mini": { input: 0.25, output: 2, cacheRead: 0.025, cacheWrite: 0.25 },
232
+ "gpt-5.3-codex": { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 1.25 },
233
+ "gpt-5.2": { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 1.25 },
234
+ "codex-auto-review": { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 1.25 }
232
235
  };
233
236
  var MODEL_CONTEXT_WINDOW = {
234
237
  // ── Anthropic / Claude ────────────────────────────────────
@@ -261,8 +264,14 @@ function longestPrefixMatch(table, model) {
261
264
  }
262
265
  return best;
263
266
  }
267
+ var UNKNOWN_MODEL_PRICING = {
268
+ input: 0,
269
+ output: 0,
270
+ cacheRead: 0,
271
+ cacheWrite: 0
272
+ };
264
273
  function getPricing(model) {
265
- return longestPrefixMatch(MODEL_PRICING, model) ?? MODEL_PRICING["claude-sonnet-4"];
274
+ return longestPrefixMatch(MODEL_PRICING, model) ?? UNKNOWN_MODEL_PRICING;
266
275
  }
267
276
  function getContextWindow(model) {
268
277
  if (!model) return DEFAULT_CONTEXT_WINDOW;
@@ -5653,7 +5662,7 @@ function readAnonId() {
5653
5662
  }
5654
5663
  function superProperties() {
5655
5664
  return {
5656
- cliVersion: true ? "2.60.9" : "0.0.0-dev",
5665
+ cliVersion: true ? "2.60.11" : "0.0.0-dev",
5657
5666
  nodeVersion: process.version,
5658
5667
  platform: process.platform,
5659
5668
  arch: process.arch,
@@ -5834,7 +5843,7 @@ var os4 = __toESM(require("os"));
5834
5843
  // package.json
5835
5844
  var package_default = {
5836
5845
  name: "codeam-cli",
5837
- version: "2.60.9",
5846
+ version: "2.60.11",
5838
5847
  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.",
5839
5848
  type: "commonjs",
5840
5849
  main: "dist/index.js",
@@ -6905,7 +6914,7 @@ var CommandRelayService = class {
6905
6914
  // fresh + clear the "CLI update available" banner after a self-update
6906
6915
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
6907
6916
  // pair/reconnect). Older backends ignore the extra field.
6908
- ..."2.60.9" ? { ideVersion: "2.60.9" } : {}
6917
+ ..."2.60.11" ? { ideVersion: "2.60.11" } : {}
6909
6918
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
6910
6919
  }
6911
6920
  /**
@@ -13978,36 +13987,56 @@ function projectNameForCwd(cwd, root) {
13978
13987
  } catch {
13979
13988
  }
13980
13989
  }
13981
- } catch {
13990
+ log.debug("gemini", `projects.json has no entry for cwd=${cwd} \u2014 using basename fallback`);
13991
+ } catch (err) {
13992
+ log.debug("gemini", `projects.json unreadable at ${root} \u2014 using basename fallback`, err);
13982
13993
  }
13983
13994
  return path32.basename(cwd) || null;
13984
13995
  }
13985
13996
  function resolveHistoryDir5(cwd, root = GEMINI_ROOT) {
13986
13997
  const name = projectNameForCwd(cwd, root);
13987
- if (!name) return null;
13998
+ if (!name) {
13999
+ log.warn("gemini", `resolveHistoryDir \u2014 could not derive a project name for cwd=${cwd}`);
14000
+ return null;
14001
+ }
13988
14002
  const dir = path32.join(root, "tmp", name, "chats");
13989
- return fs28.existsSync(dir) ? dir : null;
14003
+ if (!fs28.existsSync(dir)) {
14004
+ log.debug("gemini", `resolveHistoryDir \u2014 chats dir not present yet: ${dir} (project=${name})`);
14005
+ return null;
14006
+ }
14007
+ return dir;
13990
14008
  }
13991
14009
  function resolveHistoryFile4(cwd, sessionId, root = GEMINI_ROOT) {
14010
+ const id8 = sessionId.slice(0, 8);
13992
14011
  const dir = resolveHistoryDir5(cwd, root);
13993
14012
  if (!dir) return null;
13994
14013
  let files;
13995
14014
  try {
13996
14015
  files = fs28.readdirSync(dir).filter((f) => f.startsWith("session-") && f.endsWith(".jsonl"));
13997
- } catch {
14016
+ } catch (err) {
14017
+ log.warn("gemini", `resolveHistoryFile \u2014 cannot read chats dir ${dir} (id8=${id8})`, err);
14018
+ return null;
14019
+ }
14020
+ if (files.length === 0) {
14021
+ log.debug("gemini", `resolveHistoryFile \u2014 no session-*.jsonl yet in ${dir} (id8=${id8})`);
13998
14022
  return null;
13999
14023
  }
14000
- if (files.length === 0) return null;
14001
- const id8 = sessionId.slice(0, 8);
14002
14024
  const byName = files.find((f) => id8.length > 0 && f.includes(id8));
14003
- if (byName) return path32.join(dir, byName);
14025
+ if (byName) {
14026
+ log.info("gemini", `resolveHistoryFile \u2014 matched by filename id8=${id8}: ${byName}`);
14027
+ return path32.join(dir, byName);
14028
+ }
14004
14029
  for (const f of files) {
14005
14030
  const full = path32.join(dir, f);
14006
14031
  try {
14007
14032
  const firstLine = fs28.readFileSync(full, "utf8").split("\n", 1)[0] ?? "";
14008
14033
  const hdr = JSON.parse(firstLine);
14009
- if (hdr.sessionId === sessionId) return full;
14010
- } catch {
14034
+ if (hdr.sessionId === sessionId) {
14035
+ log.info("gemini", `resolveHistoryFile \u2014 matched by header sessionId: ${f}`);
14036
+ return full;
14037
+ }
14038
+ } catch (err) {
14039
+ log.debug("gemini", `resolveHistoryFile \u2014 unreadable/non-JSON header in ${f}`, err);
14011
14040
  }
14012
14041
  }
14013
14042
  let newest = null;
@@ -14018,6 +14047,10 @@ function resolveHistoryFile4(cwd, sessionId, root = GEMINI_ROOT) {
14018
14047
  } catch {
14019
14048
  }
14020
14049
  }
14050
+ log.warn(
14051
+ "gemini",
14052
+ `resolveHistoryFile \u2014 no id8=${id8} match among ${files.length} file(s) in ${dir}; falling back to newest=${newest?.file ?? "none"}`
14053
+ );
14021
14054
  return newest ? path32.join(dir, newest.file) : null;
14022
14055
  }
14023
14056
  function extractGeminiText(content) {
@@ -14047,12 +14080,14 @@ function parseHistoryFile5(filePath) {
14047
14080
  let raw;
14048
14081
  try {
14049
14082
  raw = fs28.readFileSync(filePath, "utf8");
14050
- } catch {
14083
+ } catch (err) {
14084
+ log.warn("gemini", `parseHistoryFile \u2014 cannot read ${filePath}`, err);
14051
14085
  return [];
14052
14086
  }
14053
14087
  const out2 = [];
14054
14088
  const seen = /* @__PURE__ */ new Set();
14055
14089
  let idx = 0;
14090
+ let malformed = 0;
14056
14091
  const consider = (m) => {
14057
14092
  if (m.type !== "user" && m.type !== "gemini") return;
14058
14093
  const id = typeof m.id === "string" ? m.id : `pos-${idx}`;
@@ -14074,6 +14109,7 @@ function parseHistoryFile5(filePath) {
14074
14109
  try {
14075
14110
  rec = JSON.parse(line);
14076
14111
  } catch {
14112
+ malformed += 1;
14077
14113
  continue;
14078
14114
  }
14079
14115
  if (rec.$set && Array.isArray(rec.$set.messages)) {
@@ -14082,6 +14118,10 @@ function parseHistoryFile5(filePath) {
14082
14118
  consider(rec);
14083
14119
  }
14084
14120
  }
14121
+ log.trace(
14122
+ "gemini",
14123
+ `parseHistoryFile \u2014 ${out2.length} turn(s) from ${path32.basename(filePath)}` + (malformed > 0 ? ` (${malformed} malformed line(s) skipped)` : "")
14124
+ );
14085
14125
  return out2;
14086
14126
  }
14087
14127
 
@@ -14122,6 +14162,10 @@ var GeminiRuntimeStrategy = class {
14122
14162
  }
14123
14163
  const sessionId = (0, import_node_crypto5.randomUUID)();
14124
14164
  const launch = this.os.buildLaunch(binary, ["--session-id", sessionId]);
14165
+ log.info(
14166
+ "gemini",
14167
+ `prepareLaunch \u2014 native TUI, binary=${binary} sessionId=${sessionId} (id8=${sessionId.slice(0, 8)})`
14168
+ );
14125
14169
  return { cmd: launch.cmd, args: launch.args, sessionId };
14126
14170
  }
14127
14171
  // Re-attach the same conversation on hand-back (baton) by passing the same
@@ -16140,7 +16184,7 @@ async function autoUpgradeBeforeCriticalCommand() {
16140
16184
  if (process.env.NODE_ENV === "test") return;
16141
16185
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16142
16186
  if (process.env.CI) return;
16143
- const current = true ? "2.60.9" : null;
16187
+ const current = true ? "2.60.11" : null;
16144
16188
  if (!current) return;
16145
16189
  const cache = readCache();
16146
16190
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16157,7 +16201,7 @@ function checkForUpdates() {
16157
16201
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16158
16202
  if (process.env.CI) return;
16159
16203
  if (!process.stdout.isTTY) return;
16160
- const current = true ? "2.60.9" : null;
16204
+ const current = true ? "2.60.11" : null;
16161
16205
  if (!current) return;
16162
16206
  const cache = readCache();
16163
16207
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16177,7 +16221,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
16177
16221
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
16178
16222
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
16179
16223
  function currentCliVersion() {
16180
- return true ? "2.60.9" : null;
16224
+ return true ? "2.60.11" : null;
16181
16225
  }
16182
16226
  function runCmd(cmd, args2, timeoutMs) {
16183
16227
  return new Promise((resolve7) => {
@@ -32956,7 +33000,7 @@ function checkChokidar() {
32956
33000
  }
32957
33001
  async function doctor(args2 = []) {
32958
33002
  const json = args2.includes("--json");
32959
- const cliVersion = true ? "2.60.9" : "0.0.0-dev";
33003
+ const cliVersion = true ? "2.60.11" : "0.0.0-dev";
32960
33004
  const apiBase2 = resolveApiBaseUrl();
32961
33005
  const diagnosticId = (0, import_node_crypto10.randomUUID)();
32962
33006
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -33155,7 +33199,7 @@ async function completion(args2) {
33155
33199
  // src/commands/version.ts
33156
33200
  var import_picocolors15 = __toESM(require("picocolors"));
33157
33201
  function version2() {
33158
- const v = true ? "2.60.9" : "unknown";
33202
+ const v = true ? "2.60.11" : "unknown";
33159
33203
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
33160
33204
  }
33161
33205
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.60.9",
3
+ "version": "2.60.11",
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",