pikakit 3.8.4 → 3.9.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/bin/kit.mjs CHANGED
@@ -24,6 +24,9 @@ const COMMANDS = {
24
24
  validate: { module: "./lib/commands/validate.js", hasParam: true, aliases: ["check"] },
25
25
  analyze: { module: "./lib/commands/analyze.js", hasParam: true },
26
26
 
27
+ // Metrics & Observability
28
+ metrics: { module: "./lib/commands/metrics.js", hasParam: true, aliases: ["stats"] },
29
+
27
30
  // Info
28
31
  info: { module: "./lib/commands/info.js", hasParam: true, aliases: ["show"] },
29
32
  help: { module: "./lib/commands/help.js", aliases: ["--help", "-h"] }
@@ -0,0 +1,208 @@
1
+ /**
2
+ * kit metrics - View autopilot execution metrics
3
+ * @description Display metrics from autopilot runs with various views
4
+ *
5
+ * Usage:
6
+ * kit metrics - Show latest run summary
7
+ * kit metrics list - List all runs
8
+ * kit metrics <id> - Show specific run details
9
+ * kit metrics summary - Show aggregate stats
10
+ */
11
+ import { c } from "../ui.js";
12
+ import path from "path";
13
+ import { createRequire } from "module";
14
+
15
+ const require = createRequire(import.meta.url);
16
+
17
+ /**
18
+ * Find agent-skill-kit installation
19
+ */
20
+ function findSkillKit() {
21
+ // Try common locations
22
+ const searchPaths = [
23
+ process.cwd(),
24
+ path.join(process.cwd(), ".."),
25
+ path.join(process.cwd(), "../agent-skill-kit")
26
+ ];
27
+
28
+ for (const basePath of searchPaths) {
29
+ const metricsPath = path.join(basePath, ".agent/skills/skill-generator/lib/metrics-collector.cjs");
30
+ try {
31
+ const { MetricsCollector } = require(metricsPath);
32
+ return new MetricsCollector({
33
+ metricsDir: path.join(basePath, ".agent/metrics")
34
+ });
35
+ } catch {
36
+ continue;
37
+ }
38
+ }
39
+ return null;
40
+ }
41
+
42
+ /**
43
+ * Format duration in human-readable format
44
+ */
45
+ function formatDuration(seconds) {
46
+ if (!seconds) return "0s";
47
+ if (seconds < 60) return `${seconds}s`;
48
+ const mins = Math.floor(seconds / 60);
49
+ const secs = seconds % 60;
50
+ return secs > 0 ? `${mins}m ${secs}s` : `${mins}m`;
51
+ }
52
+
53
+ /**
54
+ * Print run summary
55
+ */
56
+ function printRunSummary(run) {
57
+ if (!run || !run.metrics) {
58
+ console.log(c.yellow("No metrics data available"));
59
+ return;
60
+ }
61
+
62
+ const m = run.metrics;
63
+
64
+ console.log(`\n${c.cyan("╔")}${"═".repeat(50)}${c.cyan("╗")}`);
65
+ console.log(`${c.cyan("║")} ${c.bold("📊 AUTOPILOT RUN: " + (run.task_id || "Unknown"))}`.padEnd(60) + `${c.cyan("║")}`);
66
+ console.log(`${c.cyan("╠")}${"═".repeat(50)}${c.cyan("╣")}`);
67
+
68
+ console.log(`${c.cyan("║")} Duration: ${formatDuration(m.speed?.time_to_completion || 0)}`.padEnd(51) + `${c.cyan("║")}`);
69
+ console.log(`${c.cyan("║")} Phases: ${m.speed?.total_phases || 0}`.padEnd(51) + `${c.cyan("║")}`);
70
+ console.log(`${c.cyan("╠")}${"─".repeat(50)}${c.cyan("╣")}`);
71
+
72
+ const autonomy = m.autonomy?.autonomous_completion_rate || 0;
73
+ const autonomyColor = autonomy >= 80 ? c.green : autonomy >= 50 ? c.yellow : c.red;
74
+ console.log(`${c.cyan("║")} Autonomy: ${autonomyColor(autonomy + "%")}`.padEnd(60) + `${c.cyan("║")}`);
75
+
76
+ const interventions = m.intervention?.human_interventions || 0;
77
+ const intColor = interventions === 0 ? c.green : c.yellow;
78
+ console.log(`${c.cyan("║")} Interventions: ${intColor(interventions)}`.padEnd(60) + `${c.cyan("║")}`);
79
+
80
+ const successRate = m.quality?.first_time_success_rate || 0;
81
+ const successColor = successRate >= 90 ? c.green : successRate >= 70 ? c.yellow : c.red;
82
+ console.log(`${c.cyan("║")} Success Rate: ${successColor(successRate + "%")}`.padEnd(60) + `${c.cyan("║")}`);
83
+
84
+ console.log(`${c.cyan("╚")}${"═".repeat(50)}${c.cyan("╝")}\n`);
85
+
86
+ // Show phases if available
87
+ if (run.phases && run.phases.length > 0) {
88
+ console.log(c.gray("Phases:"));
89
+ for (const phase of run.phases) {
90
+ const icon = phase.status === "success" ? c.green("✓") : c.red("✗");
91
+ console.log(` ${icon} ${phase.name} (${formatDuration(Math.round(phase.duration_ms / 1000))})`);
92
+ }
93
+ console.log();
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Print runs list
99
+ */
100
+ function printRunsList(runs) {
101
+ if (!runs || runs.length === 0) {
102
+ console.log(c.yellow("\nNo autopilot runs found.\n"));
103
+ return;
104
+ }
105
+
106
+ console.log(`\n${c.cyan("📋 AUTOPILOT RUNS")} (${runs.length} total)\n`);
107
+ console.log(`${"ID".padEnd(20)} ${"TASK".padEnd(25)} ${"DURATION".padEnd(10)} ${"STATUS"}`);
108
+ console.log(`${"-".repeat(20)} ${"-".repeat(25)} ${"-".repeat(10)} ${"-".repeat(8)}`);
109
+
110
+ for (const run of runs.slice(0, 10)) {
111
+ const summary = run.metrics_summary || {};
112
+ const duration = formatDuration(summary.time_to_completion || 0);
113
+ const status = (summary.human_interventions || 0) === 0 ? c.green("✓ Auto") : c.yellow("⚡ Mixed");
114
+
115
+ console.log(
116
+ `${(run.id || "?").slice(0, 20).padEnd(20)} ` +
117
+ `${(run.task_id || "?").slice(0, 24).padEnd(25)} ` +
118
+ `${duration.padEnd(10)} ` +
119
+ `${status}`
120
+ );
121
+ }
122
+ console.log();
123
+ }
124
+
125
+ /**
126
+ * Print aggregate summary
127
+ */
128
+ function printSummary(collector) {
129
+ const runs = collector.listRuns();
130
+
131
+ console.log(`\n${c.cyan("╔")}${"═".repeat(50)}${c.cyan("╗")}`);
132
+ console.log(`${c.cyan("║")} ${c.bold("📈 AUTOPILOT METRICS SUMMARY")}`.padEnd(60) + `${c.cyan("║")}`);
133
+ console.log(`${c.cyan("╠")}${"═".repeat(50)}${c.cyan("╣")}`);
134
+
135
+ if (runs.length === 0) {
136
+ console.log(`${c.cyan("║")} ${c.yellow("No runs recorded yet")}`.padEnd(60) + `${c.cyan("║")}`);
137
+ console.log(`${c.cyan("╚")}${"═".repeat(50)}${c.cyan("╝")}\n`);
138
+ return;
139
+ }
140
+
141
+ // Calculate aggregates
142
+ let totalDuration = 0;
143
+ let totalInterventions = 0;
144
+ let totalAutonomy = 0;
145
+ let validRuns = 0;
146
+
147
+ for (const runInfo of runs.slice(0, 10)) {
148
+ const run = collector.loadRun(runInfo.id);
149
+ if (run && run.metrics) {
150
+ totalDuration += run.metrics.speed?.time_to_completion || 0;
151
+ totalInterventions += run.metrics.intervention?.human_interventions || 0;
152
+ totalAutonomy += run.metrics.autonomy?.autonomous_completion_rate || 0;
153
+ validRuns++;
154
+ }
155
+ }
156
+
157
+ const avgDuration = validRuns > 0 ? Math.round(totalDuration / validRuns) : 0;
158
+ const avgInterventions = validRuns > 0 ? (totalInterventions / validRuns).toFixed(1) : 0;
159
+ const avgAutonomy = validRuns > 0 ? Math.round(totalAutonomy / validRuns) : 0;
160
+
161
+ console.log(`${c.cyan("║")} Total Runs: ${runs.length}`.padEnd(51) + `${c.cyan("║")}`);
162
+ console.log(`${c.cyan("║")} Avg Duration: ${formatDuration(avgDuration)}`.padEnd(51) + `${c.cyan("║")}`);
163
+ console.log(`${c.cyan("║")} Avg Interventions: ${avgInterventions}`.padEnd(51) + `${c.cyan("║")}`);
164
+
165
+ const autoColor = avgAutonomy >= 80 ? c.green : avgAutonomy >= 50 ? c.yellow : c.red;
166
+ console.log(`${c.cyan("║")} Avg Autonomy: ${autoColor(avgAutonomy + "%")}`.padEnd(60) + `${c.cyan("║")}`);
167
+
168
+ console.log(`${c.cyan("╚")}${"═".repeat(50)}${c.cyan("╝")}\n`);
169
+ }
170
+
171
+ /**
172
+ * Run the metrics command
173
+ */
174
+ export async function run(subcommand) {
175
+ const collector = findSkillKit();
176
+
177
+ if (!collector) {
178
+ console.log(c.red("\n✗ Could not find agent-skill-kit installation."));
179
+ console.log(c.gray(" Make sure you're in a directory with .agent/skills/skill-generator/\n"));
180
+ return;
181
+ }
182
+
183
+ const runs = collector.listRuns();
184
+
185
+ // Handle subcommands
186
+ if (!subcommand || subcommand === "latest") {
187
+ // Show latest run
188
+ if (runs.length === 0) {
189
+ console.log(c.yellow("\nNo autopilot runs found. Run /autopilot to generate metrics.\n"));
190
+ return;
191
+ }
192
+ const latest = collector.loadRun(runs[0].id);
193
+ printRunSummary(latest);
194
+ } else if (subcommand === "list" || subcommand === "ls") {
195
+ printRunsList(runs);
196
+ } else if (subcommand === "summary" || subcommand === "stats") {
197
+ printSummary(collector);
198
+ } else {
199
+ // Try to load specific run by ID
200
+ const run = collector.loadRun(subcommand);
201
+ if (run) {
202
+ printRunSummary(run);
203
+ } else {
204
+ console.log(c.red(`\n✗ Run "${subcommand}" not found.`));
205
+ console.log(c.gray(" Use 'kit metrics list' to see available runs.\n"));
206
+ }
207
+ }
208
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pikakit",
3
- "version": "3.8.4",
3
+ "version": "3.9.0",
4
4
  "description": "Enterprise-grade Agent Skill Manager with Antigravity Skills support, Progressive Disclosure detection, and semantic routing validation",
5
5
  "license": "MIT",
6
6
  "author": "pikakit <pikakit@gmail.com>",