@ekkos/cli 1.2.16 → 1.2.17
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/dist/commands/run.js +49 -18
- package/package.json +1 -1
package/dist/commands/run.js
CHANGED
|
@@ -1419,18 +1419,50 @@ async function run(options) {
|
|
|
1419
1419
|
// Claude creates the transcript file BEFORE outputting the session name
|
|
1420
1420
|
// So we watch for new files rather than parsing TUI output (which is slower)
|
|
1421
1421
|
// ════════════════════════════════════════════════════════════════════════════
|
|
1422
|
-
const
|
|
1423
|
-
const
|
|
1422
|
+
const projectPath = process.cwd();
|
|
1423
|
+
const projectsRoot = path.join(os.homedir(), '.claude', 'projects');
|
|
1424
|
+
const projectDirCandidates = (() => {
|
|
1425
|
+
// Claude's project-dir encoding is platform/version dependent.
|
|
1426
|
+
// Probe a small set of known-safe variants to avoid missing the session file.
|
|
1427
|
+
const encodings = new Set([
|
|
1428
|
+
projectPath.replace(/\//g, '-'),
|
|
1429
|
+
projectPath.replace(/[\\/]/g, '-'),
|
|
1430
|
+
projectPath.replace(/[:\\/]/g, '-'),
|
|
1431
|
+
`-${projectPath.replace(/[:\\/]/g, '-').replace(/^-+/, '')}`,
|
|
1432
|
+
projectPath.replace(/[^a-zA-Z0-9]/g, '-'),
|
|
1433
|
+
`-${projectPath.replace(/^[\\/]+/, '').replace(/[^a-zA-Z0-9]/g, '-')}`,
|
|
1434
|
+
]);
|
|
1435
|
+
return [...encodings]
|
|
1436
|
+
.filter(Boolean)
|
|
1437
|
+
.map(encoded => path.join(projectsRoot, encoded));
|
|
1438
|
+
})();
|
|
1424
1439
|
const launchTime = Date.now();
|
|
1440
|
+
function listCandidateJsonlFiles() {
|
|
1441
|
+
const jsonlFiles = [];
|
|
1442
|
+
for (const candidateDir of projectDirCandidates) {
|
|
1443
|
+
if (!fs.existsSync(candidateDir))
|
|
1444
|
+
continue;
|
|
1445
|
+
try {
|
|
1446
|
+
for (const file of fs.readdirSync(candidateDir)) {
|
|
1447
|
+
if (file.endsWith('.jsonl')) {
|
|
1448
|
+
jsonlFiles.push(path.join(candidateDir, file));
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
catch {
|
|
1453
|
+
// Ignore candidate-dir read errors and keep scanning others.
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
return jsonlFiles;
|
|
1457
|
+
}
|
|
1425
1458
|
// Track existing jsonl files at startup
|
|
1426
1459
|
let existingJsonlFiles = new Set();
|
|
1427
1460
|
try {
|
|
1428
|
-
|
|
1429
|
-
existingJsonlFiles = new Set(files.filter(f => f.endsWith('.jsonl')));
|
|
1461
|
+
existingJsonlFiles = new Set(listCandidateJsonlFiles());
|
|
1430
1462
|
dlog(`[TRANSCRIPT] Found ${existingJsonlFiles.size} existing jsonl files at startup`);
|
|
1431
1463
|
}
|
|
1432
1464
|
catch {
|
|
1433
|
-
dlog('[TRANSCRIPT]
|
|
1465
|
+
dlog('[TRANSCRIPT] No candidate project dir exists yet');
|
|
1434
1466
|
}
|
|
1435
1467
|
// Poll for new transcript file every 500ms for up to 30 seconds.
|
|
1436
1468
|
// Safety rule: do NOT guess using "most recent" files; that can cross-bind sessions.
|
|
@@ -1450,13 +1482,11 @@ async function run(options) {
|
|
|
1450
1482
|
// In proxy mode this is intentionally disabled to avoid cross-session mixing.
|
|
1451
1483
|
if (!proxyModeEnabled && !transcriptPath) {
|
|
1452
1484
|
try {
|
|
1453
|
-
const
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
path: path.join(projectDir, f),
|
|
1459
|
-
mtime: fs.statSync(path.join(projectDir, f)).mtimeMs
|
|
1485
|
+
const jsonlFiles = listCandidateJsonlFiles()
|
|
1486
|
+
.map(fullPath => ({
|
|
1487
|
+
name: path.basename(fullPath),
|
|
1488
|
+
path: fullPath,
|
|
1489
|
+
mtime: fs.statSync(fullPath).mtimeMs
|
|
1460
1490
|
}))
|
|
1461
1491
|
.sort((a, b) => b.mtime - a.mtime);
|
|
1462
1492
|
if (jsonlFiles.length > 0) {
|
|
@@ -1486,14 +1516,13 @@ async function run(options) {
|
|
|
1486
1516
|
return;
|
|
1487
1517
|
}
|
|
1488
1518
|
try {
|
|
1489
|
-
const
|
|
1490
|
-
const jsonlFiles = currentFiles.filter(f => f.endsWith('.jsonl'));
|
|
1519
|
+
const jsonlFiles = listCandidateJsonlFiles();
|
|
1491
1520
|
// Find NEW files (created after we started)
|
|
1492
1521
|
for (const file of jsonlFiles) {
|
|
1493
1522
|
if (!existingJsonlFiles.has(file)) {
|
|
1494
1523
|
// New file! This is our transcript
|
|
1495
|
-
const fullPath =
|
|
1496
|
-
const sessionId = file.replace('.jsonl', '');
|
|
1524
|
+
const fullPath = file;
|
|
1525
|
+
const sessionId = path.basename(file).replace('.jsonl', '');
|
|
1497
1526
|
transcriptPath = fullPath;
|
|
1498
1527
|
currentSessionId = sessionId;
|
|
1499
1528
|
currentSession = (0, state_1.uuidToWords)(sessionId);
|
|
@@ -1608,8 +1637,10 @@ async function run(options) {
|
|
|
1608
1637
|
function resolveTranscriptFromSessionId(source) {
|
|
1609
1638
|
if (!currentSessionId || transcriptPath)
|
|
1610
1639
|
return;
|
|
1611
|
-
const candidate =
|
|
1612
|
-
|
|
1640
|
+
const candidate = projectDirCandidates
|
|
1641
|
+
.map(projectDir => path.join(projectDir, `${currentSessionId}.jsonl`))
|
|
1642
|
+
.find(fullPath => fs.existsSync(fullPath));
|
|
1643
|
+
if (!candidate)
|
|
1613
1644
|
return;
|
|
1614
1645
|
transcriptPath = candidate;
|
|
1615
1646
|
evictionDebugLog('TRANSCRIPT_SET', `Set from session ID (${source})`, {
|