@ekkos/cli 1.0.26 → 1.0.27

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.
@@ -67,6 +67,7 @@ const chalk_1 = __importDefault(require("chalk"));
67
67
  const commander_1 = require("commander");
68
68
  const usage_parser_js_1 = require("../lib/usage-parser.js");
69
69
  const state_js_1 = require("../utils/state.js");
70
+ const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
70
71
  // ── Pricing ──
71
72
  // Pricing per MTok from https://platform.claude.com/docs/en/about-claude/pricing
72
73
  const MODEL_PRICING = {
@@ -272,6 +273,55 @@ function parseJsonlFile(jsonlPath, sessionName) {
272
273
  turns,
273
274
  };
274
275
  }
276
+ function readJsonFile(filePath) {
277
+ try {
278
+ if (!fs.existsSync(filePath))
279
+ return null;
280
+ return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
281
+ }
282
+ catch {
283
+ return null;
284
+ }
285
+ }
286
+ function resolveSessionAlias(sessionId) {
287
+ const normalized = sessionId.toLowerCase();
288
+ // Project-local hook state (most reliable for the active session)
289
+ const projectState = readJsonFile(path.join(process.cwd(), '.claude', 'state', 'current-session.json'));
290
+ if (projectState?.session_id?.toLowerCase() === normalized &&
291
+ projectState.session_name &&
292
+ !UUID_REGEX.test(projectState.session_name)) {
293
+ return projectState.session_name;
294
+ }
295
+ // Global Claude hook state
296
+ const claudeState = readJsonFile(path.join(os.homedir(), '.claude', 'state', 'current-session.json'));
297
+ if (claudeState?.session_id?.toLowerCase() === normalized &&
298
+ claudeState.session_name &&
299
+ !UUID_REGEX.test(claudeState.session_name)) {
300
+ return claudeState.session_name;
301
+ }
302
+ // ekkOS global state
303
+ const ekkosState = readJsonFile(path.join(os.homedir(), '.ekkos', 'current-session.json'));
304
+ if (ekkosState?.session_id?.toLowerCase() === normalized &&
305
+ ekkosState.session_name &&
306
+ !UUID_REGEX.test(ekkosState.session_name)) {
307
+ return ekkosState.session_name;
308
+ }
309
+ // Multi-session index fallback
310
+ const activeSessions = readJsonFile(path.join(os.homedir(), '.ekkos', 'active-sessions.json')) || [];
311
+ const bySessionId = activeSessions
312
+ .filter(s => s.sessionId?.toLowerCase() === normalized && s.sessionName && !UUID_REGEX.test(s.sessionName))
313
+ .sort((a, b) => (b.lastHeartbeat || '').localeCompare(a.lastHeartbeat || ''));
314
+ if (bySessionId.length > 0)
315
+ return bySessionId[0].sessionName || null;
316
+ return null;
317
+ }
318
+ function displaySessionName(rawName) {
319
+ if (!rawName)
320
+ return 'session';
321
+ if (!UUID_REGEX.test(rawName))
322
+ return rawName;
323
+ return resolveSessionAlias(rawName) || (0, state_js_1.uuidToWords)(rawName);
324
+ }
275
325
  // ── Resolve session to JSONL path ──
276
326
  function resolveJsonlPath(sessionName, createdAfterMs) {
277
327
  // 1) Try standard resolution (works when sessionId is a real UUID)
@@ -499,7 +549,7 @@ function sleep(ms) {
499
549
  }
500
550
  // ── TUI Dashboard ──
501
551
  async function launchDashboard(initialSessionName, jsonlPath, refreshMs) {
502
- let sessionName = initialSessionName;
552
+ let sessionName = displaySessionName(initialSessionName);
503
553
  const blessed = require('blessed');
504
554
  const contrib = require('blessed-contrib');
505
555
  const inTmux = process.env.TMUX !== undefined;
@@ -836,12 +886,20 @@ async function launchDashboard(initialSessionName, jsonlPath, refreshMs) {
836
886
  const basename = path.basename(jsonlPath, '.jsonl');
837
887
  // JSONL filename is the session UUID (e.g., 607bd8e4-0a04-4db2-acf5-3f794be0f956.jsonl)
838
888
  if (/^[0-9a-f]{8}-/.test(basename)) {
839
- sessionName = (0, state_js_1.uuidToWords)(basename);
889
+ sessionName = displaySessionName(basename);
840
890
  screen.title = `ekkOS - ${sessionName}`;
841
891
  }
842
892
  }
843
893
  catch { }
844
894
  }
895
+ // If we started with a UUID fallback, keep trying to resolve to the bound word session.
896
+ if (UUID_REGEX.test(sessionName)) {
897
+ const resolvedName = displaySessionName(sessionName);
898
+ if (resolvedName !== sessionName) {
899
+ sessionName = resolvedName;
900
+ screen.title = `ekkOS - ${sessionName}`;
901
+ }
902
+ }
845
903
  let data;
846
904
  try {
847
905
  const stat = fs.statSync(jsonlPath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ekkos/cli",
3
- "version": "1.0.26",
3
+ "version": "1.0.27",
4
4
  "description": "Setup ekkOS memory for AI coding assistants (Claude Code, Cursor, Windsurf)",
5
5
  "main": "dist/index.js",
6
6
  "bin": {