codeam-cli 1.4.8 → 1.4.9

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 +105 -15
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -115,7 +115,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
115
115
  // package.json
116
116
  var package_default = {
117
117
  name: "codeam-cli",
118
- version: "1.4.8",
118
+ version: "1.4.9",
119
119
  description: "Remote control Claude Code from your mobile device",
120
120
  main: "dist/index.js",
121
121
  bin: {
@@ -1121,9 +1121,10 @@ function filterChrome(lines) {
1121
1121
  return result;
1122
1122
  }
1123
1123
  var OutputService = class _OutputService {
1124
- constructor(sessionId, pluginId) {
1124
+ constructor(sessionId, pluginId, onSessionIdDetected) {
1125
1125
  this.sessionId = sessionId;
1126
1126
  this.pluginId = pluginId;
1127
+ this.onSessionIdDetected = onSessionIdDetected;
1127
1128
  }
1128
1129
  sessionId;
1129
1130
  pluginId;
@@ -1133,6 +1134,7 @@ var OutputService = class _OutputService {
1133
1134
  startTime = 0;
1134
1135
  active = false;
1135
1136
  lastPushTime = 0;
1137
+ onSessionIdDetected;
1136
1138
  static POLL_MS = 1e3;
1137
1139
  static IDLE_MS = 3e3;
1138
1140
  /** Shorter idle threshold for selector detection (UI is ready immediately). */
@@ -1170,7 +1172,26 @@ var OutputService = class _OutputService {
1170
1172
  if (!this.active) return;
1171
1173
  this.rawBuffer += raw;
1172
1174
  const printable = raw.replace(/\x1B\[[^@-~]*[@-~]/g, "").replace(/[\x00-\x1F\x7F]/g, "");
1173
- if (printable.trim()) this.lastPushTime = Date.now();
1175
+ if (printable.trim()) {
1176
+ this.lastPushTime = Date.now();
1177
+ this.tryExtractSessionId(printable);
1178
+ }
1179
+ }
1180
+ /** Extract Claude conversation ID from output text (e.g., from /cost command or session resume) */
1181
+ tryExtractSessionId(text) {
1182
+ const patterns = [
1183
+ /Resuming session[:\s]+([a-f0-9-]{36})/i,
1184
+ /Session[:\s]+([a-f0-9-]{36})/i,
1185
+ /Conversation[:\s]+([a-f0-9-]{36})/i,
1186
+ /Session\s+ID[:\s]+([a-f0-9-]{36})/i
1187
+ ];
1188
+ for (const pattern of patterns) {
1189
+ const match = text.match(pattern);
1190
+ if (match && this.onSessionIdDetected) {
1191
+ this.onSessionIdDetected(match[1]);
1192
+ return;
1193
+ }
1194
+ }
1174
1195
  }
1175
1196
  dispose() {
1176
1197
  this.stopPoll();
@@ -1366,9 +1387,29 @@ var HistoryService = class {
1366
1387
  }
1367
1388
  pluginId;
1368
1389
  cwd;
1390
+ currentConversationId = null;
1369
1391
  get projectDir() {
1370
1392
  return path4.join(os4.homedir(), ".claude", "projects", encodeCwd(this.cwd));
1371
1393
  }
1394
+ /** Set the current Claude conversation ID (extracted from /cost command or session start) */
1395
+ setCurrentConversationId(id) {
1396
+ this.currentConversationId = id;
1397
+ }
1398
+ /** Extract conversation ID from Claude output (e.g., from session resume messages) */
1399
+ tryExtractConversationIdFromOutput(output) {
1400
+ const patterns = [
1401
+ /Resuming session[:\s]+([a-f0-9-]{36})/i,
1402
+ /session[:\s]+([a-f0-9-]{36})/i,
1403
+ /conversation[:\s]+([a-f0-9-]{36})/i
1404
+ ];
1405
+ for (const pattern of patterns) {
1406
+ const match = output.match(pattern);
1407
+ if (match) {
1408
+ this.currentConversationId = match[1];
1409
+ return;
1410
+ }
1411
+ }
1412
+ }
1372
1413
  /**
1373
1414
  * Read the most recently modified JSONL session file and extract the
1374
1415
  * context window usage from the last assistant message's usage field.
@@ -1379,10 +1420,13 @@ var HistoryService = class {
1379
1420
  */
1380
1421
  getCurrentUsage() {
1381
1422
  const dir = this.projectDir;
1423
+ console.log(`[HistoryService] Looking for sessions in: ${dir}`);
1424
+ console.log(`[HistoryService] Current conversation ID: ${this.currentConversationId ?? "not set"}`);
1382
1425
  let entries;
1383
1426
  try {
1384
1427
  entries = fs4.readdirSync(dir, { withFileTypes: true });
1385
- } catch {
1428
+ } catch (err) {
1429
+ console.log(`[HistoryService] Failed to read directory: ${err}`);
1386
1430
  return null;
1387
1431
  }
1388
1432
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
@@ -1392,29 +1436,66 @@ var HistoryService = class {
1392
1436
  return { name: e.name, mtime: 0 };
1393
1437
  }
1394
1438
  }).sort((a, b) => b.mtime - a.mtime);
1395
- if (files.length === 0) return null;
1439
+ if (files.length === 0) {
1440
+ console.log(`[HistoryService] No .jsonl files found in directory`);
1441
+ return null;
1442
+ }
1443
+ let targetFile = files[0].name;
1444
+ if (this.currentConversationId) {
1445
+ const conversationFile = `${this.currentConversationId}.jsonl`;
1446
+ const exists = files.some((f) => f.name === conversationFile);
1447
+ if (exists) {
1448
+ targetFile = conversationFile;
1449
+ console.log(`[HistoryService] Using tracked conversation file: ${targetFile}`);
1450
+ } else {
1451
+ console.log(`[HistoryService] Tracked conversation file not found, using most recent: ${targetFile}`);
1452
+ }
1453
+ } else {
1454
+ console.log(`[HistoryService] No tracked conversation, using most recent: ${targetFile}`);
1455
+ }
1396
1456
  let raw;
1397
1457
  try {
1398
- raw = fs4.readFileSync(path4.join(dir, files[0].name), "utf8");
1399
- } catch {
1458
+ raw = fs4.readFileSync(path4.join(dir, targetFile), "utf8");
1459
+ } catch (err) {
1460
+ console.log(`[HistoryService] Failed to read file: ${err}`);
1400
1461
  return null;
1401
1462
  }
1402
1463
  let lastUsage = null;
1403
1464
  let lastModel = null;
1404
- for (const line of raw.split("\n").filter(Boolean)) {
1465
+ let assistantMessageCount = 0;
1466
+ let hasAnyMessages = false;
1467
+ const lines = raw.split("\n").filter(Boolean);
1468
+ console.log(`[HistoryService] File has ${lines.length} lines`);
1469
+ for (const line of lines) {
1405
1470
  try {
1406
1471
  const record = JSON.parse(line);
1472
+ if (record["type"] === "user" || record["type"] === "assistant") {
1473
+ hasAnyMessages = true;
1474
+ }
1407
1475
  if (record["type"] === "assistant") {
1476
+ assistantMessageCount++;
1408
1477
  const msg = record["message"];
1409
- if (msg?.["usage"]) lastUsage = msg["usage"];
1478
+ const usage = msg?.["usage"];
1479
+ if (usage && (usage["input_tokens"] !== void 0 || usage["prompt_tokens"] !== void 0)) {
1480
+ lastUsage = usage;
1481
+ console.log(`[HistoryService] Found usage data: ${JSON.stringify(lastUsage)}`);
1482
+ }
1410
1483
  if (msg?.["model"]) lastModel = msg["model"];
1411
1484
  }
1412
1485
  } catch {
1413
1486
  }
1414
1487
  }
1415
- if (!lastUsage) return null;
1416
- const inputTokens = (lastUsage["input_tokens"] ?? 0) + (lastUsage["cache_read_input_tokens"] ?? 0) + (lastUsage["cache_creation_input_tokens"] ?? 0);
1417
- const outputTokens = lastUsage["output_tokens"] ?? 0;
1488
+ console.log(`[HistoryService] Processed ${assistantMessageCount} assistant messages, hasAnyMessages: ${hasAnyMessages}, lastUsage: ${lastUsage ? "found" : "not found"}, lastModel: ${lastModel}`);
1489
+ if (!lastUsage) {
1490
+ if (hasAnyMessages) {
1491
+ console.log(`[HistoryService] File has messages but no usage data (Claude Code may not have recorded usage yet)`);
1492
+ return { used: 0, total: 2e5, percent: 0, model: lastModel, outputTokens: 0, cacheReadTokens: 0 };
1493
+ }
1494
+ console.log(`[HistoryService] No messages or usage data found in session file`);
1495
+ return null;
1496
+ }
1497
+ const inputTokens = (lastUsage["input_tokens"] ?? lastUsage["prompt_tokens"] ?? 0) + (lastUsage["cache_read_input_tokens"] ?? 0) + (lastUsage["cache_creation_input_tokens"] ?? 0);
1498
+ const outputTokens = lastUsage["output_tokens"] ?? lastUsage["completion_tokens"] ?? 0;
1418
1499
  const total = 2e5;
1419
1500
  const percent = Math.min(100, Math.round(inputTokens / total * 100));
1420
1501
  return { used: inputTokens, total, percent, model: lastModel, outputTokens, cacheReadTokens: lastUsage["cache_read_input_tokens"] ?? 0 };
@@ -1503,9 +1584,15 @@ async function start() {
1503
1584
  const pluginId = session.pluginId ?? ensurePluginId();
1504
1585
  showInfo(`${session.userName} \xB7 ${import_picocolors2.default.cyan(session.plan)}`);
1505
1586
  showInfo("Launching Claude Code...\n");
1587
+ const cwd = process.cwd();
1588
+ console.log(`[CLI] Starting with cwd: ${cwd}`);
1589
+ console.log(`[CLI] Session: ${session.id}, Plugin: ${pluginId}`);
1506
1590
  const ws = new WebSocketService(session.id, pluginId);
1507
- const outputSvc = new OutputService(session.id, pluginId);
1508
- const historySvc = new HistoryService(pluginId, process.cwd());
1591
+ const historySvc = new HistoryService(pluginId, cwd);
1592
+ const outputSvc = new OutputService(session.id, pluginId, (conversationId) => {
1593
+ console.log(`[CLI] Detected Claude conversation ID: ${conversationId}`);
1594
+ historySvc.setCurrentConversationId(conversationId);
1595
+ });
1509
1596
  function sendPrompt(prompt) {
1510
1597
  outputSvc.newTurn();
1511
1598
  claude.sendCommand(prompt);
@@ -1554,8 +1641,11 @@ async function start() {
1554
1641
  claude.interrupt();
1555
1642
  break;
1556
1643
  case "get_context": {
1644
+ console.log(`[CLI] Received get_context command, fetching usage...`);
1557
1645
  const usage = historySvc.getCurrentUsage();
1558
- await relay.sendResult(cmd.id, "completed", usage ?? { error: "No usage data found" });
1646
+ const result = usage ?? { used: 0, total: 2e5, percent: 0, model: null, outputTokens: 0, cacheReadTokens: 0, error: "No usage data found" };
1647
+ console.log(`[CLI] Sending context result: ${JSON.stringify(result)}`);
1648
+ await relay.sendResult(cmd.id, "completed", result);
1559
1649
  break;
1560
1650
  }
1561
1651
  case "resume_session": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "1.4.8",
3
+ "version": "1.4.9",
4
4
  "description": "Remote control Claude Code from your mobile device",
5
5
  "main": "dist/index.js",
6
6
  "bin": {