codeam-cli 1.4.36 → 1.4.38

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 (2) hide show
  1. package/dist/index.js +49 -45
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -116,7 +116,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
116
116
  // package.json
117
117
  var package_default = {
118
118
  name: "codeam-cli",
119
- version: "1.4.36",
119
+ version: "1.4.38",
120
120
  description: "Remote control Claude Code from your mobile device",
121
121
  main: "dist/index.js",
122
122
  bin: {
@@ -1116,7 +1116,8 @@ function filterChrome(lines) {
1116
1116
  if (/^\?\s.*shortcut/i.test(t)) continue;
1117
1117
  if (/spending limit|usage limit/i.test(t) && t.length < 80) continue;
1118
1118
  if (/↑\s*\/?\s*↓\s*to\s*navigate/i.test(t)) continue;
1119
- if (/^[❯>]\s+\S/.test(t) && !/^[❯>]\s*\d+\./.test(t)) {
1119
+ const stripped = t.replace(/^[│╭╰╮╯┌└┐┘├┤┬┴┼]\s?/, "");
1120
+ if (/^[❯>]\s+\S/.test(stripped) && !/^[❯>]\s*\d+\./.test(stripped)) {
1120
1121
  skipEchoContinuation = true;
1121
1122
  continue;
1122
1123
  }
@@ -1148,7 +1149,15 @@ var OutputService = class _OutputService {
1148
1149
  static IDLE_MS = 3e3;
1149
1150
  /** Shorter idle threshold for selector detection (UI is ready immediately). */
1150
1151
  static SELECTOR_IDLE_MS = 1500;
1151
- static EMPTY_TIMEOUT_MS = 3e4;
1152
+ /**
1153
+ * Grace period before the first tick processes output.
1154
+ * Prevents the raw PTY input echo from being captured before Claude Code
1155
+ * clears and re-renders its TUI (which happens within ~100-200 ms of
1156
+ * receiving the input, but we give a 1.5 s margin for loaded machines).
1157
+ */
1158
+ static WARMUP_MS = 1500;
1159
+ /** Max idle with no visible content (spinner only) before finalizing. */
1160
+ static EMPTY_TIMEOUT_MS = 6e4;
1152
1161
  static MAX_MS = 12e4;
1153
1162
  newTurn() {
1154
1163
  this.stopPoll();
@@ -1222,6 +1231,7 @@ var OutputService = class _OutputService {
1222
1231
  this.finalize();
1223
1232
  return;
1224
1233
  }
1234
+ if (elapsed < _OutputService.WARMUP_MS) return;
1225
1235
  const lines = renderToLines(this.rawBuffer);
1226
1236
  const selector = detectSelector(lines) ?? detectListSelector(lines);
1227
1237
  if (selector) {
@@ -1356,6 +1366,7 @@ function parseJsonl(filePath) {
1356
1366
  const ts = record["timestamp"];
1357
1367
  const timestamp = typeof ts === "string" ? new Date(ts).getTime() : typeof ts === "number" ? ts : Date.now();
1358
1368
  const uuid = record["uuid"] ?? `${Date.now()}-${Math.random()}`;
1369
+ if (record["isMeta"]) continue;
1359
1370
  if (type === "user" && msg) {
1360
1371
  const text = extractText(msg["content"]).trim();
1361
1372
  if (text) messages.push({ id: uuid, role: "user", text, timestamp });
@@ -1558,61 +1569,54 @@ var HistoryService = class {
1558
1569
  return { used: inputTokens, total, percent, model: lastModel, outputTokens, cacheReadTokens: lastUsage["cache_read_input_tokens"] ?? 0 };
1559
1570
  }
1560
1571
  /**
1561
- * Estimate the total API cost for the current month across all projects.
1562
- * Scans all JSONL files modified this month under ~/.claude/projects/.
1572
+ * Estimate the API cost for the current month in the current project directory.
1573
+ * Scans only the JSONL files for this project (cwd), so the value reflects
1574
+ * usage from the active Claude Code session rather than the entire machine.
1563
1575
  */
1564
1576
  getMonthlyEstimatedCost() {
1565
- const claudeDir = path4.join(os4.homedir(), ".claude", "projects");
1566
- let projectDirs;
1567
- try {
1568
- projectDirs = fs4.readdirSync(claudeDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path4.join(claudeDir, e.name));
1569
- } catch {
1570
- return 0;
1571
- }
1577
+ const projectDir = this.projectDir;
1572
1578
  const now = /* @__PURE__ */ new Date();
1573
1579
  const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
1574
1580
  const monthStartIso = monthStart.toISOString();
1575
1581
  const monthStartMs = monthStart.getTime();
1576
1582
  let totalCost = 0;
1577
- for (const projectDir of projectDirs) {
1578
- let files;
1583
+ let files;
1584
+ try {
1585
+ files = fs4.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
1586
+ try {
1587
+ return fs4.statSync(path4.join(projectDir, f)).mtimeMs >= monthStartMs;
1588
+ } catch {
1589
+ return false;
1590
+ }
1591
+ });
1592
+ } catch {
1593
+ return 0;
1594
+ }
1595
+ for (const file of files) {
1596
+ let raw;
1579
1597
  try {
1580
- files = fs4.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
1581
- try {
1582
- return fs4.statSync(path4.join(projectDir, f)).mtimeMs >= monthStartMs;
1583
- } catch {
1584
- return false;
1585
- }
1586
- });
1598
+ raw = fs4.readFileSync(path4.join(projectDir, file), "utf8");
1587
1599
  } catch {
1588
1600
  continue;
1589
1601
  }
1590
- for (const file of files) {
1591
- let raw;
1602
+ for (const line of raw.split("\n").filter(Boolean)) {
1592
1603
  try {
1593
- raw = fs4.readFileSync(path4.join(projectDir, file), "utf8");
1604
+ const record = JSON.parse(line);
1605
+ if (record["type"] !== "assistant") continue;
1606
+ const timestamp = record["timestamp"];
1607
+ if (timestamp && timestamp < monthStartIso) continue;
1608
+ const msg = record["message"];
1609
+ if (!msg || msg["model"] === "<synthetic>") continue;
1610
+ const model = msg["model"] || "";
1611
+ const usage = msg["usage"];
1612
+ if (!usage) continue;
1613
+ const pricing = getPricing(model);
1614
+ const input = usage["input_tokens"] ?? 0;
1615
+ const output = usage["output_tokens"] ?? 0;
1616
+ const cacheRead = usage["cache_read_input_tokens"] ?? 0;
1617
+ const cacheWrite = usage["cache_creation_input_tokens"] ?? 0;
1618
+ totalCost += input / 1e6 * pricing.input + output / 1e6 * pricing.output + cacheRead / 1e6 * pricing.cacheRead + cacheWrite / 1e6 * pricing.cacheWrite;
1594
1619
  } catch {
1595
- continue;
1596
- }
1597
- for (const line of raw.split("\n").filter(Boolean)) {
1598
- try {
1599
- const record = JSON.parse(line);
1600
- if (record["type"] !== "assistant") continue;
1601
- const timestamp = record["timestamp"];
1602
- if (timestamp && timestamp < monthStartIso) continue;
1603
- const msg = record["message"];
1604
- if (!msg || msg["model"] === "<synthetic>") continue;
1605
- const model = msg["model"] || "";
1606
- const usage = msg["usage"];
1607
- if (!usage) continue;
1608
- const pricing = getPricing(model);
1609
- const input = usage["input_tokens"] ?? 0;
1610
- const output = usage["output_tokens"] ?? 0;
1611
- const cacheRead = usage["cache_read_input_tokens"] ?? 0;
1612
- const cacheWrite = usage["cache_creation_input_tokens"] ?? 0;
1613
- totalCost += input / 1e6 * pricing.input + output / 1e6 * pricing.output + cacheRead / 1e6 * pricing.cacheRead + cacheWrite / 1e6 * pricing.cacheWrite;
1614
- } catch {
1615
- }
1616
1620
  }
1617
1621
  }
1618
1622
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "1.4.36",
3
+ "version": "1.4.38",
4
4
  "description": "Remote control Claude Code from your mobile device",
5
5
  "main": "dist/index.js",
6
6
  "bin": {