@dadado/agent-kit-cli 5.4.0 → 5.5.0
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/README.md +2 -1
- package/dashboard/dashboard-data.mjs +72 -1
- package/dashboard/dashboard.html +19 -1
- package/dist/index.js +1218 -251
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,7 +63,8 @@ On an interactive TTY, long-running commands (`init`, `install`, `doctor`, `upda
|
|
|
63
63
|
|---------|---------|
|
|
64
64
|
| `agent-kit install` | Bootstrap L0 (+ optional packs) and write `agent-kit.json` |
|
|
65
65
|
| `agent-kit status` | Show installed kit version and profile |
|
|
66
|
-
| `agent-kit doctor` | Diagnose repository readiness |
|
|
66
|
+
| `agent-kit doctor` | Diagnose repository readiness (`--json` includes an `env` pillar: bin-on-PATH, npm prefix writability, Node version, shell profile) |
|
|
67
|
+
| `agent-kit setup-global` | Self-heal a root-owned npm global prefix (relocate to `~/.npm-global`, fix `PATH`, reinstall) |
|
|
67
68
|
| `agent-kit update` | Re-apply L0/packs/skills from the registry |
|
|
68
69
|
| `agent-kit dashboard` | Start Mission Control for this workspace |
|
|
69
70
|
| `agent-kit add <id>` | Install a skill or L1 pack |
|
|
@@ -111,7 +111,7 @@ const SNAPSHOT = {
|
|
|
111
111
|
dashboardDataVersion: "Semantic version of the data model schema",
|
|
112
112
|
plans: "Active plans from .cursor/plans/*.plan.md with frontmatter parsing",
|
|
113
113
|
system:
|
|
114
|
-
"System metadata: repoRoot, listen port, handoff state, allowlisted config summary, package info, version, name, contextPacks",
|
|
114
|
+
"System metadata: repoRoot, listen port, handoff state, allowlisted config summary, package info, version, name, contextPacks, detachedAuditSessions ({count, oldestAgeSeconds}|null; host-wide detached agent-kit-audit-* PTYs)",
|
|
115
115
|
agents: "Agent definitions from .cursor/agents/*.md",
|
|
116
116
|
commands: "Slash commands from .cursor/commands/*.md",
|
|
117
117
|
memory:
|
|
@@ -641,6 +641,77 @@ try {
|
|
|
641
641
|
SNAPSHOT.processes = [];
|
|
642
642
|
}
|
|
643
643
|
|
|
644
|
+
// 13b. Detached audit-session visibility (plan phase3-visibility).
|
|
645
|
+
// Mirrors the sessionStart hook semantics (packages/cli/src/hooks/session-start.ts):
|
|
646
|
+
// whole agent-kit-audit- namespace (any token, legacy unscoped names included),
|
|
647
|
+
// detached sessions only; attached sessions are operator work and never counted.
|
|
648
|
+
// Fail-open: null when zero sessions or tmux/screen is missing/errors.
|
|
649
|
+
SNAPSHOT.system.detachedAuditSessions = null;
|
|
650
|
+
try {
|
|
651
|
+
if (withinSnapshotBudget(400)) {
|
|
652
|
+
const auditAges = [];
|
|
653
|
+
const nowEpoch = Math.floor(Date.now() / 1000);
|
|
654
|
+
try {
|
|
655
|
+
const tmuxOut = execSync(
|
|
656
|
+
"tmux list-sessions -F '#{session_name} #{session_attached} #{session_created}'",
|
|
657
|
+
{ encoding: "utf-8", timeout: 2000, stdio: ["ignore", "pipe", "ignore"] },
|
|
658
|
+
);
|
|
659
|
+
for (const line of tmuxOut.split("\n")) {
|
|
660
|
+
const m = line.trim().match(/^(\S+)\s+(\d+)\s+(\d+)$/);
|
|
661
|
+
if (!m) continue;
|
|
662
|
+
if (!m[1].startsWith("agent-kit-audit-")) continue;
|
|
663
|
+
if (Number(m[2]) > 0) continue;
|
|
664
|
+
const created = Number(m[3]);
|
|
665
|
+
auditAges.push(nowEpoch >= created ? nowEpoch - created : -1);
|
|
666
|
+
}
|
|
667
|
+
} catch {
|
|
668
|
+
// tmux missing or no server: fail-open
|
|
669
|
+
}
|
|
670
|
+
try {
|
|
671
|
+
// `screen -ls` exits 1 while successfully listing, so soften the exit code.
|
|
672
|
+
const screenOut = execSync("screen -ls || true", {
|
|
673
|
+
encoding: "utf-8",
|
|
674
|
+
timeout: 2000,
|
|
675
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
676
|
+
});
|
|
677
|
+
// The "N Sockets in <dir>." line trails the session list; socket mtime ~ start time.
|
|
678
|
+
let sockdir = null;
|
|
679
|
+
for (const line of screenOut.split("\n")) {
|
|
680
|
+
const dirMatch = line.match(/^\d+\s+Sockets?\s+in\s+(.+)\.$/);
|
|
681
|
+
if (dirMatch) sockdir = dirMatch[1];
|
|
682
|
+
}
|
|
683
|
+
for (const line of screenOut.split("\n")) {
|
|
684
|
+
const m = line.match(/^\s+(\d+)\.(\S+)\s+\((.*)\)/);
|
|
685
|
+
if (!m) continue;
|
|
686
|
+
if (!m[2].startsWith("agent-kit-audit-")) continue;
|
|
687
|
+
// "Detached" has a single t before "ached", so it never matches [Aa]ttached.
|
|
688
|
+
if (/[Aa]ttached/.test(m[3])) continue;
|
|
689
|
+
let age = -1;
|
|
690
|
+
if (sockdir) {
|
|
691
|
+
try {
|
|
692
|
+
const mtimeMs = statSync(join(sockdir, `${m[1]}.${m[2]}`)).mtimeMs;
|
|
693
|
+
if (Date.now() >= mtimeMs) age = Math.floor((Date.now() - mtimeMs) / 1000);
|
|
694
|
+
} catch {
|
|
695
|
+
// socket not stat-able: age stays unknown, session still counted
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
auditAges.push(age);
|
|
699
|
+
}
|
|
700
|
+
} catch {
|
|
701
|
+
// screen missing: fail-open
|
|
702
|
+
}
|
|
703
|
+
if (auditAges.length > 0) {
|
|
704
|
+
const known = auditAges.filter((a) => a >= 0);
|
|
705
|
+
SNAPSHOT.system.detachedAuditSessions = {
|
|
706
|
+
count: auditAges.length,
|
|
707
|
+
oldestAgeSeconds: known.length ? Math.max(...known) : null,
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
} catch {
|
|
712
|
+
SNAPSHOT.system.detachedAuditSessions = null;
|
|
713
|
+
}
|
|
714
|
+
|
|
644
715
|
// 10. Health checks (originally)
|
|
645
716
|
const checks = [
|
|
646
717
|
{ id: "plans", label: "Plans directory", ok: existsSync(plansDir) && SNAPSHOT.plans.length > 0 },
|
package/dashboard/dashboard.html
CHANGED
|
@@ -4270,6 +4270,16 @@ function fmtDate(iso) {
|
|
|
4270
4270
|
return d.toLocaleString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' });
|
|
4271
4271
|
}
|
|
4272
4272
|
|
|
4273
|
+
// Humanize a duration in seconds (mirrors formatSessionAge in the sessionStart hook).
|
|
4274
|
+
function formatDuration(seconds) {
|
|
4275
|
+
const s = Number(seconds);
|
|
4276
|
+
if (!Number.isFinite(s) || s < 0) return 'unknown';
|
|
4277
|
+
if (s >= 86400) return Math.floor(s / 86400) + 'd';
|
|
4278
|
+
if (s >= 3600) return Math.floor(s / 3600) + 'h';
|
|
4279
|
+
if (s >= 60) return Math.floor(s / 60) + 'm';
|
|
4280
|
+
return Math.floor(s) + 's';
|
|
4281
|
+
}
|
|
4282
|
+
|
|
4273
4283
|
// Presentation contract (Phase 2): progress is never an error signal. Any
|
|
4274
4284
|
// in-flight percentage (0-99) renders the neutral accent; 100% renders green
|
|
4275
4285
|
// (lifecycle completed with total > 0 implies 100 per the Phase 0 contract).
|
|
@@ -8289,6 +8299,14 @@ function renderUnsafe() {
|
|
|
8289
8299
|
|
|
8290
8300
|
// ===== Processes =====
|
|
8291
8301
|
const processes = d.processes || [];
|
|
8302
|
+
// Detached audit-session visibility (phase3): host-wide agent-kit-audit-* PTYs.
|
|
8303
|
+
const auditSessions = d.system?.detachedAuditSessions || null;
|
|
8304
|
+
const auditSessionsNote = auditSessions && auditSessions.count > 0
|
|
8305
|
+
? `
|
|
8306
|
+
<div class="processes-note">
|
|
8307
|
+
<span><strong>${auditSessions.count} detached audit ${auditSessions.count === 1 ? 'session' : 'sessions'}.</strong> Host-wide <code>agent-kit-audit-*</code> plan-review ${auditSessions.count === 1 ? 'PTY is' : 'PTYs are'} still alive (${auditSessions.oldestAgeSeconds != null ? `oldest ~${formatDuration(auditSessions.oldestAgeSeconds)}` : 'oldest age unknown'}). Inspect with <code>tmux attach -t <name></code> / <code>screen -r <name></code>, or let the audit launcher's session GC dispose of them on the next spawn.</span>
|
|
8308
|
+
</div>`
|
|
8309
|
+
: '';
|
|
8292
8310
|
parts.push(`
|
|
8293
8311
|
<div class="content-section" id="section-processes">
|
|
8294
8312
|
<div class="section-title">
|
|
@@ -8297,7 +8315,7 @@ function renderUnsafe() {
|
|
|
8297
8315
|
</div>
|
|
8298
8316
|
<div class="processes-note">
|
|
8299
8317
|
<span><strong>Live ps snapshot.</strong> Agent chats spawned inside the IDE do not appear here; the Crew monitor on the Overview tab tracks that activity.</span>
|
|
8300
|
-
</div
|
|
8318
|
+
</div>${auditSessionsNote}
|
|
8301
8319
|
${processes.length === 0
|
|
8302
8320
|
? renderEmptyStateCta({
|
|
8303
8321
|
headline: 'All quiet',
|