groundcrew-cli 0.15.9 → 0.15.10
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/index.js +42 -0
- package/package.json +1 -1
- package/src/index.ts +52 -0
package/dist/index.js
CHANGED
|
@@ -336,6 +336,44 @@ async function destroyAll() {
|
|
|
336
336
|
}
|
|
337
337
|
console.log(green("All session data and history deleted."));
|
|
338
338
|
}
|
|
339
|
+
async function prune() {
|
|
340
|
+
const active = await readActiveSessions();
|
|
341
|
+
const activeIds = new Set(Object.keys(active));
|
|
342
|
+
let allDirs = [];
|
|
343
|
+
try {
|
|
344
|
+
allDirs = await fs.readdir(SESSIONS_DIR);
|
|
345
|
+
} catch {
|
|
346
|
+
}
|
|
347
|
+
if (allDirs.length === 0) {
|
|
348
|
+
console.log(dim("No sessions to prune."));
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
let pruned = 0;
|
|
352
|
+
for (const dir of allDirs) {
|
|
353
|
+
if (activeIds.has(dir)) {
|
|
354
|
+
const entry = active[dir];
|
|
355
|
+
try {
|
|
356
|
+
process.kill(entry.pid, 0);
|
|
357
|
+
continue;
|
|
358
|
+
} catch {
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
const sessionDir = path.join(SESSIONS_DIR, dir);
|
|
362
|
+
await fs.rm(sessionDir, { recursive: true, force: true });
|
|
363
|
+
console.log(` ${green("pruned")} ${cyan(dir)}`);
|
|
364
|
+
pruned++;
|
|
365
|
+
if (activeIds.has(dir)) {
|
|
366
|
+
delete active[dir];
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
await fs.writeFile(ACTIVE_SESSIONS_FILE, JSON.stringify(active, null, 2));
|
|
370
|
+
if (pruned === 0) {
|
|
371
|
+
console.log(dim("No stale sessions to prune. All sessions are active."));
|
|
372
|
+
} else {
|
|
373
|
+
console.log(green(`
|
|
374
|
+
Pruned ${pruned} stale session(s).`));
|
|
375
|
+
}
|
|
376
|
+
}
|
|
339
377
|
async function listSessionChoices() {
|
|
340
378
|
const active = await readActiveSessions();
|
|
341
379
|
const choices = [];
|
|
@@ -696,6 +734,7 @@ ${bold("Usage:")}
|
|
|
696
734
|
groundcrew clear Clear all pending tasks
|
|
697
735
|
groundcrew stop Stop all active sessions
|
|
698
736
|
groundcrew stop --session <id> Stop a specific session
|
|
737
|
+
groundcrew prune Remove stale/ended sessions (keeps active)
|
|
699
738
|
groundcrew destroy Delete all sessions, history, and data
|
|
700
739
|
groundcrew destroy --session <id> Delete a specific session
|
|
701
740
|
|
|
@@ -754,6 +793,9 @@ async function main() {
|
|
|
754
793
|
await destroyAll();
|
|
755
794
|
}
|
|
756
795
|
return;
|
|
796
|
+
case "prune":
|
|
797
|
+
await prune();
|
|
798
|
+
return;
|
|
757
799
|
case "help":
|
|
758
800
|
case "--help":
|
|
759
801
|
case "-h":
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -435,6 +435,54 @@ async function destroyAll(): Promise<void> {
|
|
|
435
435
|
console.log(green("All session data and history deleted."));
|
|
436
436
|
}
|
|
437
437
|
|
|
438
|
+
async function prune(): Promise<void> {
|
|
439
|
+
const active = await readActiveSessions();
|
|
440
|
+
const activeIds = new Set(Object.keys(active));
|
|
441
|
+
|
|
442
|
+
let allDirs: string[] = [];
|
|
443
|
+
try { allDirs = await fs.readdir(SESSIONS_DIR); } catch {}
|
|
444
|
+
|
|
445
|
+
if (allDirs.length === 0) {
|
|
446
|
+
console.log(dim("No sessions to prune."));
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
let pruned = 0;
|
|
451
|
+
|
|
452
|
+
for (const dir of allDirs) {
|
|
453
|
+
// Skip active/parked sessions (registered in active-sessions.json)
|
|
454
|
+
if (activeIds.has(dir)) {
|
|
455
|
+
// Check if session is still alive (PID running)
|
|
456
|
+
const entry = active[dir];
|
|
457
|
+
try {
|
|
458
|
+
process.kill(entry.pid, 0); // test if process exists
|
|
459
|
+
continue; // still running, skip
|
|
460
|
+
} catch {
|
|
461
|
+
// PID not running — session is stale, safe to prune
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const sessionDir = path.join(SESSIONS_DIR, dir);
|
|
466
|
+
await fs.rm(sessionDir, { recursive: true, force: true });
|
|
467
|
+
console.log(` ${green("pruned")} ${cyan(dir)}`);
|
|
468
|
+
pruned++;
|
|
469
|
+
|
|
470
|
+
// Remove from active sessions if it was there
|
|
471
|
+
if (activeIds.has(dir)) {
|
|
472
|
+
delete active[dir];
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Update active sessions file
|
|
477
|
+
await fs.writeFile(ACTIVE_SESSIONS_FILE, JSON.stringify(active, null, 2));
|
|
478
|
+
|
|
479
|
+
if (pruned === 0) {
|
|
480
|
+
console.log(dim("No stale sessions to prune. All sessions are active."));
|
|
481
|
+
} else {
|
|
482
|
+
console.log(green(`\nPruned ${pruned} stale session(s).`));
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
438
486
|
// ── Chat Mode ────────────────────────────────────────────────────────────────
|
|
439
487
|
|
|
440
488
|
interface SessionChoice {
|
|
@@ -883,6 +931,7 @@ ${bold("Usage:")}
|
|
|
883
931
|
groundcrew clear Clear all pending tasks
|
|
884
932
|
groundcrew stop Stop all active sessions
|
|
885
933
|
groundcrew stop --session <id> Stop a specific session
|
|
934
|
+
groundcrew prune Remove stale/ended sessions (keeps active)
|
|
886
935
|
groundcrew destroy Delete all sessions, history, and data
|
|
887
936
|
groundcrew destroy --session <id> Delete a specific session
|
|
888
937
|
|
|
@@ -948,6 +997,9 @@ async function main(): Promise<void> {
|
|
|
948
997
|
await destroyAll();
|
|
949
998
|
}
|
|
950
999
|
return;
|
|
1000
|
+
case "prune":
|
|
1001
|
+
await prune();
|
|
1002
|
+
return;
|
|
951
1003
|
case "help":
|
|
952
1004
|
case "--help":
|
|
953
1005
|
case "-h":
|