@kb-labs/agent-cli 0.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 +56 -0
- package/dist/cli/commands/diff.d.ts +17 -0
- package/dist/cli/commands/diff.js +182 -0
- package/dist/cli/commands/diff.js.map +1 -0
- package/dist/cli/commands/history.d.ts +16 -0
- package/dist/cli/commands/history.js +216 -0
- package/dist/cli/commands/history.js.map +1 -0
- package/dist/cli/commands/quality-report.d.ts +21 -0
- package/dist/cli/commands/quality-report.js +457 -0
- package/dist/cli/commands/quality-report.js.map +1 -0
- package/dist/cli/commands/rollback.d.ts +27 -0
- package/dist/cli/commands/rollback.js +109 -0
- package/dist/cli/commands/rollback.js.map +1 -0
- package/dist/cli/commands/run.d.ts +42 -0
- package/dist/cli/commands/run.js +923 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/trace-context.d.ts +22 -0
- package/dist/cli/commands/trace-context.js +131 -0
- package/dist/cli/commands/trace-context.js.map +1 -0
- package/dist/cli/commands/trace-diagnose.d.ts +20 -0
- package/dist/cli/commands/trace-diagnose.js +434 -0
- package/dist/cli/commands/trace-diagnose.js.map +1 -0
- package/dist/cli/commands/trace-event-normalizer.d.ts +13 -0
- package/dist/cli/commands/trace-event-normalizer.js +39 -0
- package/dist/cli/commands/trace-event-normalizer.js.map +1 -0
- package/dist/cli/commands/trace-filter.d.ts +19 -0
- package/dist/cli/commands/trace-filter.js +153 -0
- package/dist/cli/commands/trace-filter.js.map +1 -0
- package/dist/cli/commands/trace-iteration.d.ts +18 -0
- package/dist/cli/commands/trace-iteration.js +192 -0
- package/dist/cli/commands/trace-iteration.js.map +1 -0
- package/dist/cli/commands/trace-stats.d.ts +17 -0
- package/dist/cli/commands/trace-stats.js +247 -0
- package/dist/cli/commands/trace-stats.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +473 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +184 -0
- package/dist/manifest.js +473 -0
- package/dist/manifest.js.map +1 -0
- package/dist/rest/handlers/approve-handler.d.ts +15 -0
- package/dist/rest/handlers/approve-handler.js +60 -0
- package/dist/rest/handlers/approve-handler.js.map +1 -0
- package/dist/rest/handlers/approve-session-plan-handler.d.ts +10 -0
- package/dist/rest/handlers/approve-session-plan-handler.js +52 -0
- package/dist/rest/handlers/approve-session-plan-handler.js.map +1 -0
- package/dist/rest/handlers/correct-handler.d.ts +7 -0
- package/dist/rest/handlers/correct-handler.js +326 -0
- package/dist/rest/handlers/correct-handler.js.map +1 -0
- package/dist/rest/handlers/create-session-handler.d.ts +7 -0
- package/dist/rest/handlers/create-session-handler.js +25 -0
- package/dist/rest/handlers/create-session-handler.js.map +1 -0
- package/dist/rest/handlers/execute-session-plan-handler.d.ts +10 -0
- package/dist/rest/handlers/execute-session-plan-handler.js +635 -0
- package/dist/rest/handlers/execute-session-plan-handler.js.map +1 -0
- package/dist/rest/handlers/generate-spec-handler.d.ts +10 -0
- package/dist/rest/handlers/generate-spec-handler.js +389 -0
- package/dist/rest/handlers/generate-spec-handler.js.map +1 -0
- package/dist/rest/handlers/get-file-diff-handler.d.ts +24 -0
- package/dist/rest/handlers/get-file-diff-handler.js +44 -0
- package/dist/rest/handlers/get-file-diff-handler.js.map +1 -0
- package/dist/rest/handlers/get-session-handler.d.ts +10 -0
- package/dist/rest/handlers/get-session-handler.js +23 -0
- package/dist/rest/handlers/get-session-handler.js.map +1 -0
- package/dist/rest/handlers/get-session-plan-handler.d.ts +10 -0
- package/dist/rest/handlers/get-session-plan-handler.js +53 -0
- package/dist/rest/handlers/get-session-plan-handler.js.map +1 -0
- package/dist/rest/handlers/get-session-turns-handler.d.ts +16 -0
- package/dist/rest/handlers/get-session-turns-handler.js +35 -0
- package/dist/rest/handlers/get-session-turns-handler.js.map +1 -0
- package/dist/rest/handlers/get-spec-handler.d.ts +10 -0
- package/dist/rest/handlers/get-spec-handler.js +39 -0
- package/dist/rest/handlers/get-spec-handler.js.map +1 -0
- package/dist/rest/handlers/list-file-changes-handler.d.ts +13 -0
- package/dist/rest/handlers/list-file-changes-handler.js +34 -0
- package/dist/rest/handlers/list-file-changes-handler.js.map +1 -0
- package/dist/rest/handlers/list-sessions-handler.d.ts +7 -0
- package/dist/rest/handlers/list-sessions-handler.js +23 -0
- package/dist/rest/handlers/list-sessions-handler.js.map +1 -0
- package/dist/rest/handlers/rollback-handler.d.ts +22 -0
- package/dist/rest/handlers/rollback-handler.js +91 -0
- package/dist/rest/handlers/rollback-handler.js.map +1 -0
- package/dist/rest/handlers/run-handler.d.ts +7 -0
- package/dist/rest/handlers/run-handler.js +516 -0
- package/dist/rest/handlers/run-handler.js.map +1 -0
- package/dist/rest/handlers/sessions-handler.d.ts +18 -0
- package/dist/rest/handlers/sessions-handler.js +56 -0
- package/dist/rest/handlers/sessions-handler.js.map +1 -0
- package/dist/rest/handlers/status-handler.d.ts +7 -0
- package/dist/rest/handlers/status-handler.js +313 -0
- package/dist/rest/handlers/status-handler.js.map +1 -0
- package/dist/rest/handlers/stop-handler.d.ts +7 -0
- package/dist/rest/handlers/stop-handler.js +317 -0
- package/dist/rest/handlers/stop-handler.js.map +1 -0
- package/dist/widgets/220.js +446 -0
- package/dist/widgets/220.js.map +1 -0
- package/dist/widgets/331.js +2 -0
- package/dist/widgets/331.js.map +1 -0
- package/dist/widgets/403.js +2 -0
- package/dist/widgets/403.js.map +1 -0
- package/dist/widgets/406.js +35 -0
- package/dist/widgets/406.js.map +1 -0
- package/dist/widgets/455.js +2 -0
- package/dist/widgets/455.js.map +1 -0
- package/dist/widgets/482.js +2 -0
- package/dist/widgets/482.js.map +1 -0
- package/dist/widgets/485.js +2 -0
- package/dist/widgets/485.js.map +1 -0
- package/dist/widgets/527.js +2 -0
- package/dist/widgets/527.js.map +1 -0
- package/dist/widgets/628.js +2 -0
- package/dist/widgets/628.js.map +1 -0
- package/dist/widgets/694.js +2 -0
- package/dist/widgets/694.js.map +1 -0
- package/dist/widgets/712.js +2 -0
- package/dist/widgets/712.js.map +1 -0
- package/dist/widgets/866.js +2 -0
- package/dist/widgets/866.js.map +1 -0
- package/dist/widgets/915.js +39 -0
- package/dist/widgets/915.js.map +1 -0
- package/dist/widgets/957.js +10 -0
- package/dist/widgets/957.js.map +1 -0
- package/dist/widgets/983.js +2 -0
- package/dist/widgets/983.js.map +1 -0
- package/dist/widgets/@mf-types.d.ts +3 -0
- package/dist/widgets/@mf-types.zip +0 -0
- package/dist/widgets/__federation_expose_AgentsPage.js +2 -0
- package/dist/widgets/__federation_expose_AgentsPage.js.map +1 -0
- package/dist/widgets/mf-manifest.json +260 -0
- package/dist/widgets/mf-stats.json +305 -0
- package/dist/widgets/remoteEntry.js +7 -0
- package/dist/widgets/remoteEntry.js.map +1 -0
- package/dist/ws/session-stream-handler.d.ts +8 -0
- package/dist/ws/session-stream-handler.js +409 -0
- package/dist/ws/session-stream-handler.js.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
import { defineCommand } from '@kb-labs/sdk';
|
|
2
|
+
import { promises } from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { execFile as execFile$1 } from 'child_process';
|
|
5
|
+
import { promisify } from 'util';
|
|
6
|
+
|
|
7
|
+
// src/cli/commands/quality-report.ts
|
|
8
|
+
var execFile = promisify(execFile$1);
|
|
9
|
+
function deriveQualityStatus(payload) {
|
|
10
|
+
if (payload?.qualityGate?.status === "pass" || payload?.qualityGate?.status === "partial") {
|
|
11
|
+
return payload.qualityGate.status;
|
|
12
|
+
}
|
|
13
|
+
if (payload?.qualityGateStatus === "pass" || payload?.qualityGateStatus === "partial") {
|
|
14
|
+
return payload.qualityGateStatus;
|
|
15
|
+
}
|
|
16
|
+
return payload?.success ? "pass" : "partial";
|
|
17
|
+
}
|
|
18
|
+
var quality_report_default = defineCommand({
|
|
19
|
+
id: "quality:report",
|
|
20
|
+
description: "Show quality control report for agent runs (quality, tokens, tools, drift, regressions)",
|
|
21
|
+
handler: {
|
|
22
|
+
async execute(ctx, input) {
|
|
23
|
+
const flags = input.flags ?? input;
|
|
24
|
+
const days = Number(flags.days ?? 1);
|
|
25
|
+
const limit = Number(flags.limit ?? 200);
|
|
26
|
+
const rawSessionId = flags["session-id"] ?? flags.sessionId;
|
|
27
|
+
const sessionIdFilter = typeof rawSessionId === "string" ? rawSessionId : void 0;
|
|
28
|
+
const json = Boolean(flags.json);
|
|
29
|
+
if (!Number.isFinite(days) || days <= 0) {
|
|
30
|
+
const err = { success: false, error: "--days must be a positive number" };
|
|
31
|
+
ctx.ui.write(JSON.stringify(err, null, 2) + "\n");
|
|
32
|
+
return { exitCode: 1, response: err };
|
|
33
|
+
}
|
|
34
|
+
const analyticsDir = path.join(process.cwd(), ".kb", "analytics", "buffer");
|
|
35
|
+
const files = await listEventFiles(analyticsDir, days);
|
|
36
|
+
if (files.length === 0) {
|
|
37
|
+
const out = { success: true, message: "No analytics files found for selected period", runs: 0 };
|
|
38
|
+
ctx.ui.write(JSON.stringify(out, null, 2) + "\n");
|
|
39
|
+
return { exitCode: 0, response: out };
|
|
40
|
+
}
|
|
41
|
+
const since = Date.now() - days * 24 * 60 * 60 * 1e3;
|
|
42
|
+
let { runs, regressions } = await readEvents(files, since, sessionIdFilter, limit);
|
|
43
|
+
if (runs.length === 0) {
|
|
44
|
+
const sqlitePath = path.join(process.cwd(), ".kb", "analytics", "analytics.sqlite");
|
|
45
|
+
const sqliteEvents = await readEventsFromSqlite(sqlitePath, since, sessionIdFilter, limit);
|
|
46
|
+
runs = sqliteEvents.runs;
|
|
47
|
+
regressions = sqliteEvents.regressions;
|
|
48
|
+
}
|
|
49
|
+
const report = buildReport(runs, regressions, { days, sessionIdFilter });
|
|
50
|
+
if (json) {
|
|
51
|
+
ctx.ui.write(JSON.stringify({ success: true, report }, null, 2) + "\n");
|
|
52
|
+
} else {
|
|
53
|
+
printReport(ctx, report);
|
|
54
|
+
}
|
|
55
|
+
return { exitCode: 0, response: report };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
async function listEventFiles(dir, days) {
|
|
60
|
+
try {
|
|
61
|
+
const entries = await promises.readdir(dir);
|
|
62
|
+
const candidates = entries.filter((name) => /^events-\d{8}\.jsonl$/.test(name)).sort();
|
|
63
|
+
const keep = Math.max(1, Math.min(candidates.length, days + 2));
|
|
64
|
+
return candidates.slice(-keep).map((name) => path.join(dir, name));
|
|
65
|
+
} catch {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function readEvents(files, sinceMs, sessionIdFilter, limit) {
|
|
70
|
+
const runs = [];
|
|
71
|
+
const regressions = [];
|
|
72
|
+
for (const file of files) {
|
|
73
|
+
const content = await promises.readFile(file, "utf-8");
|
|
74
|
+
const lines = content.split("\n").filter(Boolean);
|
|
75
|
+
for (const line of lines) {
|
|
76
|
+
let raw;
|
|
77
|
+
try {
|
|
78
|
+
raw = JSON.parse(line);
|
|
79
|
+
} catch {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const ts = typeof raw.ts === "string" ? Date.parse(raw.ts) : NaN;
|
|
83
|
+
if (!Number.isFinite(ts) || ts < sinceMs) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (raw.type === "agent.kpi.run_completed") {
|
|
87
|
+
const event = raw;
|
|
88
|
+
const p = event.payload || {};
|
|
89
|
+
const sessionId = p.sessionId || "unknown";
|
|
90
|
+
if (sessionIdFilter && sessionId !== sessionIdFilter) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
runs.push({
|
|
94
|
+
ts: event.ts || new Date(ts).toISOString(),
|
|
95
|
+
sessionId,
|
|
96
|
+
success: Boolean(p.success),
|
|
97
|
+
task: p.task || "",
|
|
98
|
+
summaryPreview: p.summaryPreview || "",
|
|
99
|
+
tokensUsed: Number(p.tokensUsed || 0),
|
|
100
|
+
durationMs: Number(p.durationMs || 0),
|
|
101
|
+
iterationsUsed: Number(p.iterationsUsed || 0),
|
|
102
|
+
iterationBudget: Number(p.iterationBudget || 0),
|
|
103
|
+
iterationUtilization: Number(p.iterationUtilization || 0),
|
|
104
|
+
toolCallsTotal: Number(p.toolCallsTotal || 0),
|
|
105
|
+
toolErrorRate: Number(p.toolErrorRate || 0),
|
|
106
|
+
todoUsed: Boolean(p.todoUsed),
|
|
107
|
+
evidenceDensity: Number(p.evidenceDensity || 0),
|
|
108
|
+
driftRate: Number(p.driftRate || 0),
|
|
109
|
+
qualityStatus: deriveQualityStatus(p),
|
|
110
|
+
qualityScore: Number(p.qualityGate?.score ?? (p.success ? 1 : 0)),
|
|
111
|
+
qualityReasons: Array.isArray(p.qualityGate?.reasons) ? p.qualityGate.reasons : [],
|
|
112
|
+
startTier: p.startTier === "small" || p.startTier === "large" ? p.startTier : "medium",
|
|
113
|
+
finalTier: p.finalTier === "small" || p.finalTier === "large" ? p.finalTier : "medium",
|
|
114
|
+
escalated: Boolean(p.escalated),
|
|
115
|
+
escalationCount: Number(p.escalationCount || 0),
|
|
116
|
+
escalationReasons: Array.isArray(p.escalationReasons) ? p.escalationReasons.filter((v) => typeof v === "string") : [],
|
|
117
|
+
escalationPath: Array.isArray(p.escalationPath) ? p.escalationPath.filter((v) => typeof v === "string") : []
|
|
118
|
+
});
|
|
119
|
+
} else if (raw.type === "agent.kpi.quality_regression") {
|
|
120
|
+
const event = raw;
|
|
121
|
+
const sessionId = event.payload?.sessionId;
|
|
122
|
+
if (sessionIdFilter && sessionId !== sessionIdFilter) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
regressions.push(event);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
runs.sort((a, b) => Date.parse(b.ts) - Date.parse(a.ts));
|
|
130
|
+
const trimmedRuns = runs.slice(0, Math.max(1, limit));
|
|
131
|
+
return { runs: trimmedRuns, regressions };
|
|
132
|
+
}
|
|
133
|
+
async function readEventsFromSqlite(sqlitePath, sinceMs, sessionIdFilter, limit) {
|
|
134
|
+
try {
|
|
135
|
+
await promises.access(sqlitePath);
|
|
136
|
+
} catch {
|
|
137
|
+
return { runs: [], regressions: [] };
|
|
138
|
+
}
|
|
139
|
+
const sinceIso = new Date(sinceMs).toISOString();
|
|
140
|
+
const sql = [
|
|
141
|
+
"SELECT type, ts, payload",
|
|
142
|
+
"FROM events",
|
|
143
|
+
`WHERE ts >= '${sinceIso}'`,
|
|
144
|
+
" AND type IN ('agent.kpi.run_completed', 'agent.kpi.quality_regression')",
|
|
145
|
+
"ORDER BY ts DESC",
|
|
146
|
+
`LIMIT ${Math.max(limit * 5, 500)};`
|
|
147
|
+
].join(" ");
|
|
148
|
+
try {
|
|
149
|
+
const { stdout } = await execFile("sqlite3", ["-json", sqlitePath, sql], {
|
|
150
|
+
maxBuffer: 20 * 1024 * 1024
|
|
151
|
+
});
|
|
152
|
+
const rows = JSON.parse(stdout || "[]");
|
|
153
|
+
const pseudoFileEvents = rows.map((row) => ({
|
|
154
|
+
type: row.type ?? "",
|
|
155
|
+
ts: row.ts,
|
|
156
|
+
payload: parseJsonSafe(row.payload)
|
|
157
|
+
}));
|
|
158
|
+
return readInMemoryEvents(pseudoFileEvents, sinceMs, sessionIdFilter, limit);
|
|
159
|
+
} catch {
|
|
160
|
+
return { runs: [], regressions: [] };
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function parseJsonSafe(value) {
|
|
164
|
+
if (value && typeof value === "object") {
|
|
165
|
+
return value;
|
|
166
|
+
}
|
|
167
|
+
if (typeof value !== "string") {
|
|
168
|
+
return {};
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
const parsed = JSON.parse(value);
|
|
172
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
173
|
+
} catch {
|
|
174
|
+
return {};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function readInMemoryEvents(rows, sinceMs, sessionIdFilter, limit) {
|
|
178
|
+
const runs = [];
|
|
179
|
+
const regressions = [];
|
|
180
|
+
for (const raw of rows) {
|
|
181
|
+
const ts = typeof raw.ts === "string" ? Date.parse(raw.ts) : NaN;
|
|
182
|
+
if (!Number.isFinite(ts) || ts < sinceMs) {
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (raw.type === "agent.kpi.run_completed") {
|
|
186
|
+
const p = raw.payload || {};
|
|
187
|
+
const sessionId = p?.sessionId || "unknown";
|
|
188
|
+
if (sessionIdFilter && sessionId !== sessionIdFilter) {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
runs.push({
|
|
192
|
+
ts: raw.ts || new Date(ts).toISOString(),
|
|
193
|
+
sessionId,
|
|
194
|
+
success: Boolean(p?.success),
|
|
195
|
+
task: p?.task || "",
|
|
196
|
+
summaryPreview: p?.summaryPreview || "",
|
|
197
|
+
tokensUsed: Number(p?.tokensUsed || 0),
|
|
198
|
+
durationMs: Number(p?.durationMs || 0),
|
|
199
|
+
iterationsUsed: Number(p?.iterationsUsed || 0),
|
|
200
|
+
iterationBudget: Number(p?.iterationBudget || 0),
|
|
201
|
+
iterationUtilization: Number(p?.iterationUtilization || 0),
|
|
202
|
+
toolCallsTotal: Number(p?.toolCallsTotal || 0),
|
|
203
|
+
toolErrorRate: Number(p?.toolErrorRate || 0),
|
|
204
|
+
todoUsed: Boolean(p?.todoUsed),
|
|
205
|
+
evidenceDensity: Number(p?.evidenceDensity || 0),
|
|
206
|
+
driftRate: Number(p?.driftRate || 0),
|
|
207
|
+
qualityStatus: deriveQualityStatus(p),
|
|
208
|
+
qualityScore: Number(p?.qualityGate?.score ?? (p?.success ? 1 : 0)),
|
|
209
|
+
qualityReasons: Array.isArray(p?.qualityGate?.reasons) ? p?.qualityGate.reasons : [],
|
|
210
|
+
startTier: p?.startTier === "small" || p?.startTier === "large" ? p.startTier : "medium",
|
|
211
|
+
finalTier: p?.finalTier === "small" || p?.finalTier === "large" ? p.finalTier : "medium",
|
|
212
|
+
escalated: Boolean(p?.escalated),
|
|
213
|
+
escalationCount: Number(p?.escalationCount || 0),
|
|
214
|
+
escalationReasons: Array.isArray(p?.escalationReasons) ? p.escalationReasons.filter((v) => typeof v === "string") : [],
|
|
215
|
+
escalationPath: Array.isArray(p?.escalationPath) ? p.escalationPath.filter((v) => typeof v === "string") : []
|
|
216
|
+
});
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (raw.type === "agent.kpi.quality_regression") {
|
|
220
|
+
const event = {
|
|
221
|
+
type: raw.type,
|
|
222
|
+
ts: raw.ts,
|
|
223
|
+
payload: raw.payload
|
|
224
|
+
};
|
|
225
|
+
const sessionId = event.payload?.sessionId;
|
|
226
|
+
if (sessionIdFilter && sessionId !== sessionIdFilter) {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
regressions.push(event);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
runs.sort((a, b) => Date.parse(b.ts) - Date.parse(a.ts));
|
|
233
|
+
return { runs: runs.slice(0, Math.max(1, limit)), regressions };
|
|
234
|
+
}
|
|
235
|
+
function buildReport(runs, regressions, meta) {
|
|
236
|
+
const count = runs.length;
|
|
237
|
+
if (count === 0) {
|
|
238
|
+
return {
|
|
239
|
+
periodDays: meta.days,
|
|
240
|
+
sessionId: meta.sessionIdFilter,
|
|
241
|
+
runs: 0,
|
|
242
|
+
message: "No agent.kpi.run_completed events in selected period"
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
const scorecard = scorecardOf(runs);
|
|
246
|
+
const topTokenRuns = [...runs].sort((a, b) => b.tokensUsed - a.tokensUsed).slice(0, 5);
|
|
247
|
+
const worstQualityRuns = [...runs].sort((a, b) => a.qualityScore - b.qualityScore || b.tokensUsed - a.tokensUsed).slice(0, 5);
|
|
248
|
+
const alerts = [];
|
|
249
|
+
if (scorecard.successRate < 0.85) {
|
|
250
|
+
alerts.push(`Low success rate: ${(scorecard.successRate * 100).toFixed(1)}%`);
|
|
251
|
+
}
|
|
252
|
+
if (scorecard.qualityPassRate < 0.9) {
|
|
253
|
+
alerts.push(`Quality pass rate below target: ${(scorecard.qualityPassRate * 100).toFixed(1)}%`);
|
|
254
|
+
}
|
|
255
|
+
if (scorecard.avgToolErrorRate > 0.05) {
|
|
256
|
+
alerts.push(`High tool error rate: ${(scorecard.avgToolErrorRate * 100).toFixed(1)}%`);
|
|
257
|
+
}
|
|
258
|
+
if (scorecard.avgDriftRate > 0.08) {
|
|
259
|
+
alerts.push(`Scope drift is elevated: ${(scorecard.avgDriftRate * 100).toFixed(1)}%`);
|
|
260
|
+
}
|
|
261
|
+
if (scorecard.nearBudgetRate > 0.35) {
|
|
262
|
+
alerts.push(`Too many runs near iteration budget: ${(scorecard.nearBudgetRate * 100).toFixed(1)}%`);
|
|
263
|
+
}
|
|
264
|
+
if (scorecard.escalationRate > 0.55) {
|
|
265
|
+
alerts.push(`Escalation rate too high: ${(scorecard.escalationRate * 100).toFixed(1)}%`);
|
|
266
|
+
}
|
|
267
|
+
if (scorecard.escalationRate > 0.2 && scorecard.escalationSuccessRate < 0.7) {
|
|
268
|
+
alerts.push(`Escalation effectiveness is low: ${(scorecard.escalationSuccessRate * 100).toFixed(1)}%`);
|
|
269
|
+
}
|
|
270
|
+
if (regressions.length > 0) {
|
|
271
|
+
alerts.push(`Quality regression events observed: ${regressions.length}`);
|
|
272
|
+
}
|
|
273
|
+
const sliceSize = Math.max(3, Math.min(10, Math.floor(runs.length / 2)));
|
|
274
|
+
const latestSlice = runs.slice(0, sliceSize);
|
|
275
|
+
const previousSlice = runs.slice(sliceSize, sliceSize * 2);
|
|
276
|
+
const latestScorecard = scorecardOf(latestSlice);
|
|
277
|
+
const previousScorecard = scorecardOf(previousSlice);
|
|
278
|
+
const slices = previousSlice.length > 0 ? {
|
|
279
|
+
sliceSize,
|
|
280
|
+
latest: latestScorecard,
|
|
281
|
+
previous: previousScorecard,
|
|
282
|
+
delta: {
|
|
283
|
+
successRate: latestScorecard.successRate - previousScorecard.successRate,
|
|
284
|
+
qualityPassRate: latestScorecard.qualityPassRate - previousScorecard.qualityPassRate,
|
|
285
|
+
avgQualityScore: latestScorecard.avgQualityScore - previousScorecard.avgQualityScore,
|
|
286
|
+
avgTokens: latestScorecard.avgTokens - previousScorecard.avgTokens,
|
|
287
|
+
p95Tokens: latestScorecard.p95Tokens - previousScorecard.p95Tokens,
|
|
288
|
+
avgDurationMs: latestScorecard.avgDurationMs - previousScorecard.avgDurationMs,
|
|
289
|
+
avgToolCalls: latestScorecard.avgToolCalls - previousScorecard.avgToolCalls,
|
|
290
|
+
avgToolErrorRate: latestScorecard.avgToolErrorRate - previousScorecard.avgToolErrorRate,
|
|
291
|
+
avgDriftRate: latestScorecard.avgDriftRate - previousScorecard.avgDriftRate,
|
|
292
|
+
avgEvidenceDensity: latestScorecard.avgEvidenceDensity - previousScorecard.avgEvidenceDensity,
|
|
293
|
+
nearBudgetRate: latestScorecard.nearBudgetRate - previousScorecard.nearBudgetRate,
|
|
294
|
+
escalationRate: latestScorecard.escalationRate - previousScorecard.escalationRate,
|
|
295
|
+
escalationSuccessRate: latestScorecard.escalationSuccessRate - previousScorecard.escalationSuccessRate,
|
|
296
|
+
avgEscalationCount: latestScorecard.avgEscalationCount - previousScorecard.avgEscalationCount
|
|
297
|
+
}
|
|
298
|
+
} : null;
|
|
299
|
+
return {
|
|
300
|
+
periodDays: meta.days,
|
|
301
|
+
sessionId: meta.sessionIdFilter,
|
|
302
|
+
runs: count,
|
|
303
|
+
regressions: regressions.length,
|
|
304
|
+
scorecard,
|
|
305
|
+
slices,
|
|
306
|
+
alerts,
|
|
307
|
+
topTokenRuns: topTokenRuns.map(toRunBrief),
|
|
308
|
+
worstQualityRuns: worstQualityRuns.map(toRunBrief)
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function toRunBrief(run) {
|
|
312
|
+
return {
|
|
313
|
+
ts: run.ts,
|
|
314
|
+
sessionId: run.sessionId,
|
|
315
|
+
task: run.task.slice(0, 120),
|
|
316
|
+
tokensUsed: run.tokensUsed,
|
|
317
|
+
durationMs: run.durationMs,
|
|
318
|
+
toolCallsTotal: run.toolCallsTotal,
|
|
319
|
+
qualityStatus: run.qualityStatus,
|
|
320
|
+
qualityScore: run.qualityScore,
|
|
321
|
+
qualityReasons: run.qualityReasons,
|
|
322
|
+
startTier: run.startTier,
|
|
323
|
+
finalTier: run.finalTier,
|
|
324
|
+
escalated: run.escalated,
|
|
325
|
+
escalationCount: run.escalationCount,
|
|
326
|
+
escalationReasons: run.escalationReasons
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
function avg(values) {
|
|
330
|
+
if (values.length === 0) {
|
|
331
|
+
return 0;
|
|
332
|
+
}
|
|
333
|
+
return values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
334
|
+
}
|
|
335
|
+
function p95(values) {
|
|
336
|
+
if (values.length === 0) {
|
|
337
|
+
return 0;
|
|
338
|
+
}
|
|
339
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
340
|
+
const index = Math.max(0, Math.min(sorted.length - 1, Math.ceil(sorted.length * 0.95) - 1));
|
|
341
|
+
return sorted[index] || 0;
|
|
342
|
+
}
|
|
343
|
+
function scorecardOf(runs) {
|
|
344
|
+
const escalatedRuns = runs.filter((r) => r.escalated);
|
|
345
|
+
const nonEscalatedRuns = runs.filter((r) => !r.escalated);
|
|
346
|
+
return {
|
|
347
|
+
successRate: avg(runs.map((r) => r.success ? 1 : 0)),
|
|
348
|
+
qualityPassRate: avg(runs.map((r) => r.qualityStatus === "pass" ? 1 : 0)),
|
|
349
|
+
avgQualityScore: avg(runs.map((r) => r.qualityScore)),
|
|
350
|
+
avgTokens: avg(runs.map((r) => r.tokensUsed)),
|
|
351
|
+
p95Tokens: p95(runs.map((r) => r.tokensUsed)),
|
|
352
|
+
avgDurationMs: avg(runs.map((r) => r.durationMs)),
|
|
353
|
+
avgToolCalls: avg(runs.map((r) => r.toolCallsTotal)),
|
|
354
|
+
avgToolErrorRate: avg(runs.map((r) => r.toolErrorRate)),
|
|
355
|
+
avgDriftRate: avg(runs.map((r) => r.driftRate)),
|
|
356
|
+
avgEvidenceDensity: avg(runs.map((r) => r.evidenceDensity)),
|
|
357
|
+
nearBudgetRate: avg(runs.map((r) => r.iterationUtilization >= 0.9 ? 1 : 0)),
|
|
358
|
+
escalationRate: avg(runs.map((r) => r.escalated ? 1 : 0)),
|
|
359
|
+
escalationSuccessRate: escalatedRuns.length > 0 ? avg(escalatedRuns.map((r) => r.success ? 1 : 0)) : 0,
|
|
360
|
+
avgEscalationCount: avg(runs.map((r) => r.escalationCount)),
|
|
361
|
+
avgTokensEscalated: escalatedRuns.length > 0 ? avg(escalatedRuns.map((r) => r.tokensUsed)) : 0,
|
|
362
|
+
avgTokensNonEscalated: nonEscalatedRuns.length > 0 ? avg(nonEscalatedRuns.map((r) => r.tokensUsed)) : 0,
|
|
363
|
+
avgQualityEscalated: escalatedRuns.length > 0 ? avg(escalatedRuns.map((r) => r.qualityScore)) : 0,
|
|
364
|
+
avgQualityNonEscalated: nonEscalatedRuns.length > 0 ? avg(nonEscalatedRuns.map((r) => r.qualityScore)) : 0
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
function printReport(ctx, report) {
|
|
368
|
+
if (report.runs === 0) {
|
|
369
|
+
ctx.ui.write(`No KPI runs for selected period (${report.periodDays}d)
|
|
370
|
+
`);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
const s = report.scorecard;
|
|
374
|
+
ctx.ui.write("\u250C\u2500\u2500 Agent Quality Control Report\n");
|
|
375
|
+
ctx.ui.write(`\u2502 Period: ${report.periodDays}d
|
|
376
|
+
`);
|
|
377
|
+
if (report.sessionId) {
|
|
378
|
+
ctx.ui.write(`\u2502 Session: ${report.sessionId}
|
|
379
|
+
`);
|
|
380
|
+
}
|
|
381
|
+
ctx.ui.write(`\u2502 Runs: ${report.runs} | Regressions: ${report.regressions}
|
|
382
|
+
`);
|
|
383
|
+
ctx.ui.write("\u2502\n");
|
|
384
|
+
ctx.ui.write(`\u2502 Success Rate: ${(s.successRate * 100).toFixed(1)}%
|
|
385
|
+
`);
|
|
386
|
+
ctx.ui.write(`\u2502 Quality Pass: ${(s.qualityPassRate * 100).toFixed(1)}% | Avg score: ${s.avgQualityScore.toFixed(2)}
|
|
387
|
+
`);
|
|
388
|
+
ctx.ui.write(`\u2502 Tokens: avg ${Math.round(s.avgTokens)} | p95 ${Math.round(s.p95Tokens)}
|
|
389
|
+
`);
|
|
390
|
+
ctx.ui.write(`\u2502 Duration: avg ${(s.avgDurationMs / 1e3).toFixed(1)}s
|
|
391
|
+
`);
|
|
392
|
+
ctx.ui.write(`\u2502 Tools: avg ${s.avgToolCalls.toFixed(1)} | error ${(s.avgToolErrorRate * 100).toFixed(2)}%
|
|
393
|
+
`);
|
|
394
|
+
ctx.ui.write(`\u2502 Drift: ${(s.avgDriftRate * 100).toFixed(2)}% | Evidence density: ${s.avgEvidenceDensity.toFixed(2)}
|
|
395
|
+
`);
|
|
396
|
+
ctx.ui.write(`\u2502 Near budget rate: ${(s.nearBudgetRate * 100).toFixed(1)}%
|
|
397
|
+
`);
|
|
398
|
+
ctx.ui.write(`\u2502 Escalation: ${(s.escalationRate * 100).toFixed(1)}% runs | success ${(s.escalationSuccessRate * 100).toFixed(1)}% | avg count ${s.avgEscalationCount.toFixed(2)}
|
|
399
|
+
`);
|
|
400
|
+
if (s.escalationRate > 0 && s.escalationRate < 1) {
|
|
401
|
+
const tokenDelta = s.avgTokensEscalated - s.avgTokensNonEscalated;
|
|
402
|
+
const qualityDelta = s.avgQualityEscalated - s.avgQualityNonEscalated;
|
|
403
|
+
ctx.ui.write(`\u2502 Escalated vs non-escalated: \u0394tokens ${tokenDelta >= 0 ? "+" : ""}${Math.round(tokenDelta)} | \u0394quality ${qualityDelta >= 0 ? "+" : ""}${qualityDelta.toFixed(2)}
|
|
404
|
+
`);
|
|
405
|
+
} else {
|
|
406
|
+
ctx.ui.write("\u2502 Escalated vs non-escalated: n/a (need both escalated and non-escalated runs)\n");
|
|
407
|
+
}
|
|
408
|
+
if (report.slices) {
|
|
409
|
+
const d = report.slices.delta;
|
|
410
|
+
ctx.ui.write("\u2502\n");
|
|
411
|
+
ctx.ui.write(`\u2502 Slices (${report.slices.sliceSize} latest vs previous):
|
|
412
|
+
`);
|
|
413
|
+
ctx.ui.write(`\u2502 \u0394 Quality score: ${d.avgQualityScore >= 0 ? "+" : ""}${d.avgQualityScore.toFixed(2)}
|
|
414
|
+
`);
|
|
415
|
+
ctx.ui.write(`\u2502 \u0394 Avg tokens: ${d.avgTokens >= 0 ? "+" : ""}${Math.round(d.avgTokens)}
|
|
416
|
+
`);
|
|
417
|
+
ctx.ui.write(`\u2502 \u0394 Avg duration: ${d.avgDurationMs >= 0 ? "+" : ""}${(d.avgDurationMs / 1e3).toFixed(1)}s
|
|
418
|
+
`);
|
|
419
|
+
ctx.ui.write(`\u2502 \u0394 Tool errors: ${d.avgToolErrorRate >= 0 ? "+" : ""}${(d.avgToolErrorRate * 100).toFixed(2)}%
|
|
420
|
+
`);
|
|
421
|
+
ctx.ui.write(`\u2502 \u0394 Drift: ${d.avgDriftRate >= 0 ? "+" : ""}${(d.avgDriftRate * 100).toFixed(2)}%
|
|
422
|
+
`);
|
|
423
|
+
ctx.ui.write(`\u2502 \u0394 Escalation rate: ${d.escalationRate >= 0 ? "+" : ""}${(d.escalationRate * 100).toFixed(1)}%
|
|
424
|
+
`);
|
|
425
|
+
ctx.ui.write(`\u2502 \u0394 Escalation success: ${d.escalationSuccessRate >= 0 ? "+" : ""}${(d.escalationSuccessRate * 100).toFixed(1)}%
|
|
426
|
+
`);
|
|
427
|
+
ctx.ui.write(`\u2502 \u0394 Escalation count: ${d.avgEscalationCount >= 0 ? "+" : ""}${d.avgEscalationCount.toFixed(2)}
|
|
428
|
+
`);
|
|
429
|
+
}
|
|
430
|
+
if (report.alerts.length > 0) {
|
|
431
|
+
ctx.ui.write("\u2502\n");
|
|
432
|
+
ctx.ui.write("\u2502 Alerts:\n");
|
|
433
|
+
for (const alert of report.alerts) {
|
|
434
|
+
ctx.ui.write(`\u2502 - ${alert}
|
|
435
|
+
`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
ctx.ui.write("\u2502\n");
|
|
439
|
+
ctx.ui.write("\u2502 Top expensive runs:\n");
|
|
440
|
+
for (const run of report.topTokenRuns) {
|
|
441
|
+
const esc = run.escalated ? ` | esc=${run.escalationCount}` : "";
|
|
442
|
+
ctx.ui.write(`\u2502 - ${run.ts} | tok=${run.tokensUsed} | q=${run.qualityScore.toFixed(2)}${esc} | ${run.task}
|
|
443
|
+
`);
|
|
444
|
+
}
|
|
445
|
+
ctx.ui.write("\u2502\n");
|
|
446
|
+
ctx.ui.write("\u2502 Worst quality runs:\n");
|
|
447
|
+
for (const run of report.worstQualityRuns) {
|
|
448
|
+
const reasons = (run.qualityReasons || []).join(", ");
|
|
449
|
+
ctx.ui.write(`\u2502 - ${run.ts} | q=${run.qualityScore.toFixed(2)} | tok=${run.tokensUsed} | reasons=${reasons || "n/a"}
|
|
450
|
+
`);
|
|
451
|
+
}
|
|
452
|
+
ctx.ui.write("\u2514\u2500\u2500\n");
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
export { quality_report_default as default };
|
|
456
|
+
//# sourceMappingURL=quality-report.js.map
|
|
457
|
+
//# sourceMappingURL=quality-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/quality-report.ts"],"names":["execFileCb","fs"],"mappings":"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","file":"quality-report.js","sourcesContent":["/**\n * agent:quality:report - Agent execution quality control report\n *\n * Usage:\n * pnpm kb agent quality report\n * pnpm kb agent quality report --days=3\n * pnpm kb agent quality report --session-id=session-123\n * pnpm kb agent quality report --json\n */\n\nimport { defineCommand, type PluginContextV3 } from '@kb-labs/sdk';\nimport { promises as fs } from 'fs';\nimport path from 'path';\nimport { execFile as execFileCb } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execFile = promisify(execFileCb);\n\ntype QualityReportInput = {\n days?: number;\n limit?: number;\n sessionId?: string;\n 'session-id'?: string;\n json?: boolean;\n};\n\ntype KpiRunEvent = {\n type: string;\n ts?: string;\n payload?: {\n sessionId?: string;\n success?: boolean;\n task?: string;\n summaryPreview?: string;\n tokensUsed?: number;\n durationMs?: number;\n iterationsUsed?: number;\n iterationBudget?: number;\n iterationUtilization?: number;\n toolCallsTotal?: number;\n toolErrorRate?: number;\n todoUsed?: boolean;\n evidenceDensity?: number;\n driftRate?: number;\n startTier?: 'small' | 'medium' | 'large';\n finalTier?: 'small' | 'medium' | 'large';\n escalated?: boolean;\n escalationCount?: number;\n escalationReasons?: string[];\n escalationPath?: string[];\n qualityGate?: {\n status?: 'pass' | 'partial';\n score?: number;\n reasons?: string[];\n };\n qualityGateStatus?: 'pass' | 'partial';\n };\n};\n\ntype RegressionEvent = {\n type: string;\n ts?: string;\n payload?: {\n sessionId?: string;\n reasons?: string[];\n metrics?: {\n driftRate?: number;\n evidenceDensity?: number;\n toolErrorRate?: number;\n iterationsUsed?: number;\n iterationBudget?: number;\n };\n };\n};\n\ntype RunSnapshot = {\n ts: string;\n sessionId: string;\n success: boolean;\n task: string;\n summaryPreview: string;\n tokensUsed: number;\n durationMs: number;\n iterationsUsed: number;\n iterationBudget: number;\n iterationUtilization: number;\n toolCallsTotal: number;\n toolErrorRate: number;\n todoUsed: boolean;\n evidenceDensity: number;\n driftRate: number;\n qualityStatus: 'pass' | 'partial';\n qualityScore: number;\n qualityReasons: string[];\n startTier: 'small' | 'medium' | 'large';\n finalTier: 'small' | 'medium' | 'large';\n escalated: boolean;\n escalationCount: number;\n escalationReasons: string[];\n escalationPath: string[];\n};\n\nfunction deriveQualityStatus(payload: KpiRunEvent['payload'] | undefined): 'pass' | 'partial' {\n if (payload?.qualityGate?.status === 'pass' || payload?.qualityGate?.status === 'partial') {\n return payload.qualityGate.status;\n }\n if (payload?.qualityGateStatus === 'pass' || payload?.qualityGateStatus === 'partial') {\n return payload.qualityGateStatus;\n }\n return payload?.success ? 'pass' : 'partial';\n}\n\nexport default defineCommand({\n id: 'quality:report',\n description: 'Show quality control report for agent runs (quality, tokens, tools, drift, regressions)',\n\n handler: {\n async execute(ctx: PluginContextV3, input: QualityReportInput): Promise<{ exitCode: number; response?: unknown }> {\n const flags = (input as any).flags ?? input;\n const days = Number(flags.days ?? 1);\n const limit = Number(flags.limit ?? 200);\n const rawSessionId = flags['session-id'] ?? flags.sessionId;\n const sessionIdFilter = typeof rawSessionId === 'string' ? rawSessionId : undefined;\n const json = Boolean(flags.json);\n\n if (!Number.isFinite(days) || days <= 0) {\n const err = { success: false, error: '--days must be a positive number' };\n ctx.ui.write(JSON.stringify(err, null, 2) + '\\n');\n return { exitCode: 1, response: err };\n }\n\n const analyticsDir = path.join(process.cwd(), '.kb', 'analytics', 'buffer');\n const files = await listEventFiles(analyticsDir, days);\n if (files.length === 0) {\n const out = { success: true, message: 'No analytics files found for selected period', runs: 0 };\n ctx.ui.write(JSON.stringify(out, null, 2) + '\\n');\n return { exitCode: 0, response: out };\n }\n\n const since = Date.now() - days * 24 * 60 * 60 * 1000;\n let { runs, regressions } = await readEvents(files, since, sessionIdFilter, limit);\n if (runs.length === 0) {\n const sqlitePath = path.join(process.cwd(), '.kb', 'analytics', 'analytics.sqlite');\n const sqliteEvents = await readEventsFromSqlite(sqlitePath, since, sessionIdFilter, limit);\n runs = sqliteEvents.runs;\n regressions = sqliteEvents.regressions;\n }\n const report = buildReport(runs, regressions, { days, sessionIdFilter });\n\n if (json) {\n ctx.ui.write(JSON.stringify({ success: true, report }, null, 2) + '\\n');\n } else {\n printReport(ctx, report);\n }\n\n return { exitCode: 0, response: report };\n },\n },\n});\n\nasync function listEventFiles(dir: string, days: number): Promise<string[]> {\n try {\n const entries = await fs.readdir(dir);\n const candidates = entries\n .filter((name) => /^events-\\d{8}\\.jsonl$/.test(name))\n .sort();\n\n const keep = Math.max(1, Math.min(candidates.length, days + 2));\n return candidates.slice(-keep).map((name) => path.join(dir, name));\n } catch {\n return [];\n }\n}\n\nasync function readEvents(\n files: string[],\n sinceMs: number,\n sessionIdFilter: string | undefined,\n limit: number\n): Promise<{ runs: RunSnapshot[]; regressions: RegressionEvent[] }> {\n const runs: RunSnapshot[] = [];\n const regressions: RegressionEvent[] = [];\n\n for (const file of files) {\n const content = await fs.readFile(file, 'utf-8');\n const lines = content.split('\\n').filter(Boolean);\n\n for (const line of lines) {\n let raw: any;\n try {\n raw = JSON.parse(line);\n } catch {\n continue;\n }\n\n const ts = typeof raw.ts === 'string' ? Date.parse(raw.ts) : NaN;\n if (!Number.isFinite(ts) || ts < sinceMs) {\n continue;\n }\n\n if (raw.type === 'agent.kpi.run_completed') {\n const event = raw as KpiRunEvent;\n const p = event.payload || {};\n const sessionId = p.sessionId || 'unknown';\n if (sessionIdFilter && sessionId !== sessionIdFilter) {\n continue;\n }\n\n runs.push({\n ts: event.ts || new Date(ts).toISOString(),\n sessionId,\n success: Boolean(p.success),\n task: p.task || '',\n summaryPreview: p.summaryPreview || '',\n tokensUsed: Number(p.tokensUsed || 0),\n durationMs: Number(p.durationMs || 0),\n iterationsUsed: Number(p.iterationsUsed || 0),\n iterationBudget: Number(p.iterationBudget || 0),\n iterationUtilization: Number(p.iterationUtilization || 0),\n toolCallsTotal: Number(p.toolCallsTotal || 0),\n toolErrorRate: Number(p.toolErrorRate || 0),\n todoUsed: Boolean(p.todoUsed),\n evidenceDensity: Number(p.evidenceDensity || 0),\n driftRate: Number(p.driftRate || 0),\n qualityStatus: deriveQualityStatus(p),\n qualityScore: Number(p.qualityGate?.score ?? (p.success ? 1 : 0)),\n qualityReasons: Array.isArray(p.qualityGate?.reasons) ? p.qualityGate!.reasons! : [],\n startTier: (p.startTier === 'small' || p.startTier === 'large') ? p.startTier : 'medium',\n finalTier: (p.finalTier === 'small' || p.finalTier === 'large') ? p.finalTier : 'medium',\n escalated: Boolean(p.escalated),\n escalationCount: Number(p.escalationCount || 0),\n escalationReasons: Array.isArray(p.escalationReasons)\n ? p.escalationReasons.filter((v): v is string => typeof v === 'string')\n : [],\n escalationPath: Array.isArray(p.escalationPath)\n ? p.escalationPath.filter((v): v is string => typeof v === 'string')\n : [],\n });\n } else if (raw.type === 'agent.kpi.quality_regression') {\n const event = raw as RegressionEvent;\n const sessionId = event.payload?.sessionId;\n if (sessionIdFilter && sessionId !== sessionIdFilter) {\n continue;\n }\n regressions.push(event);\n }\n }\n }\n\n runs.sort((a, b) => Date.parse(b.ts) - Date.parse(a.ts));\n const trimmedRuns = runs.slice(0, Math.max(1, limit));\n return { runs: trimmedRuns, regressions };\n}\n\nasync function readEventsFromSqlite(\n sqlitePath: string,\n sinceMs: number,\n sessionIdFilter: string | undefined,\n limit: number,\n): Promise<{ runs: RunSnapshot[]; regressions: RegressionEvent[] }> {\n try {\n await fs.access(sqlitePath);\n } catch {\n return { runs: [], regressions: [] };\n }\n\n const sinceIso = new Date(sinceMs).toISOString();\n const sql = [\n 'SELECT type, ts, payload',\n 'FROM events',\n `WHERE ts >= '${sinceIso}'`,\n \" AND type IN ('agent.kpi.run_completed', 'agent.kpi.quality_regression')\",\n 'ORDER BY ts DESC',\n `LIMIT ${Math.max(limit * 5, 500)};`,\n ].join(' ');\n\n try {\n const { stdout } = await execFile('sqlite3', ['-json', sqlitePath, sql], {\n maxBuffer: 20 * 1024 * 1024,\n });\n const rows = JSON.parse(stdout || '[]') as Array<{\n type?: string;\n ts?: string;\n payload?: string;\n }>;\n const pseudoFileEvents = rows.map((row) => ({\n type: row.type ?? '',\n ts: row.ts,\n payload: parseJsonSafe(row.payload),\n }));\n return readInMemoryEvents(pseudoFileEvents, sinceMs, sessionIdFilter, limit);\n } catch {\n return { runs: [], regressions: [] };\n }\n}\n\nfunction parseJsonSafe(value: unknown): Record<string, unknown> {\n if (value && typeof value === 'object') {\n return value as Record<string, unknown>;\n }\n if (typeof value !== 'string') {\n return {};\n }\n try {\n const parsed = JSON.parse(value) as Record<string, unknown>;\n return parsed && typeof parsed === 'object' ? parsed : {};\n } catch {\n return {};\n }\n}\n\nfunction readInMemoryEvents(\n rows: Array<{ type: string; ts?: string; payload?: Record<string, unknown> }>,\n sinceMs: number,\n sessionIdFilter: string | undefined,\n limit: number\n): { runs: RunSnapshot[]; regressions: RegressionEvent[] } {\n const runs: RunSnapshot[] = [];\n const regressions: RegressionEvent[] = [];\n\n for (const raw of rows) {\n const ts = typeof raw.ts === 'string' ? Date.parse(raw.ts) : NaN;\n if (!Number.isFinite(ts) || ts < sinceMs) {\n continue;\n }\n\n if (raw.type === 'agent.kpi.run_completed') {\n const p = (raw.payload || {}) as KpiRunEvent['payload'];\n const sessionId = p?.sessionId || 'unknown';\n if (sessionIdFilter && sessionId !== sessionIdFilter) {\n continue;\n }\n runs.push({\n ts: raw.ts || new Date(ts).toISOString(),\n sessionId,\n success: Boolean(p?.success),\n task: p?.task || '',\n summaryPreview: p?.summaryPreview || '',\n tokensUsed: Number(p?.tokensUsed || 0),\n durationMs: Number(p?.durationMs || 0),\n iterationsUsed: Number(p?.iterationsUsed || 0),\n iterationBudget: Number(p?.iterationBudget || 0),\n iterationUtilization: Number(p?.iterationUtilization || 0),\n toolCallsTotal: Number(p?.toolCallsTotal || 0),\n toolErrorRate: Number(p?.toolErrorRate || 0),\n todoUsed: Boolean(p?.todoUsed),\n evidenceDensity: Number(p?.evidenceDensity || 0),\n driftRate: Number(p?.driftRate || 0),\n qualityStatus: deriveQualityStatus(p),\n qualityScore: Number(p?.qualityGate?.score ?? (p?.success ? 1 : 0)),\n qualityReasons: Array.isArray(p?.qualityGate?.reasons) ? p?.qualityGate.reasons : [],\n startTier: (p?.startTier === 'small' || p?.startTier === 'large') ? p.startTier : 'medium',\n finalTier: (p?.finalTier === 'small' || p?.finalTier === 'large') ? p.finalTier : 'medium',\n escalated: Boolean(p?.escalated),\n escalationCount: Number(p?.escalationCount || 0),\n escalationReasons: Array.isArray(p?.escalationReasons)\n ? p.escalationReasons.filter((v): v is string => typeof v === 'string')\n : [],\n escalationPath: Array.isArray(p?.escalationPath)\n ? p.escalationPath.filter((v): v is string => typeof v === 'string')\n : [],\n });\n continue;\n }\n\n if (raw.type === 'agent.kpi.quality_regression') {\n const event: RegressionEvent = {\n type: raw.type,\n ts: raw.ts,\n payload: raw.payload as RegressionEvent['payload'],\n };\n const sessionId = event.payload?.sessionId;\n if (sessionIdFilter && sessionId !== sessionIdFilter) {\n continue;\n }\n regressions.push(event);\n }\n }\n\n runs.sort((a, b) => Date.parse(b.ts) - Date.parse(a.ts));\n return { runs: runs.slice(0, Math.max(1, limit)), regressions };\n}\n\nfunction buildReport(\n runs: RunSnapshot[],\n regressions: RegressionEvent[],\n meta: { days: number; sessionIdFilter?: string }\n) {\n const count = runs.length;\n if (count === 0) {\n return {\n periodDays: meta.days,\n sessionId: meta.sessionIdFilter,\n runs: 0,\n message: 'No agent.kpi.run_completed events in selected period',\n };\n }\n\n const scorecard = scorecardOf(runs);\n\n const topTokenRuns = [...runs].sort((a, b) => b.tokensUsed - a.tokensUsed).slice(0, 5);\n const worstQualityRuns = [...runs]\n .sort((a, b) => a.qualityScore - b.qualityScore || b.tokensUsed - a.tokensUsed)\n .slice(0, 5);\n\n const alerts: string[] = [];\n if (scorecard.successRate < 0.85) {alerts.push(`Low success rate: ${(scorecard.successRate * 100).toFixed(1)}%`);}\n if (scorecard.qualityPassRate < 0.9) {alerts.push(`Quality pass rate below target: ${(scorecard.qualityPassRate * 100).toFixed(1)}%`);}\n if (scorecard.avgToolErrorRate > 0.05) {alerts.push(`High tool error rate: ${(scorecard.avgToolErrorRate * 100).toFixed(1)}%`);}\n if (scorecard.avgDriftRate > 0.08) {alerts.push(`Scope drift is elevated: ${(scorecard.avgDriftRate * 100).toFixed(1)}%`);}\n if (scorecard.nearBudgetRate > 0.35) {alerts.push(`Too many runs near iteration budget: ${(scorecard.nearBudgetRate * 100).toFixed(1)}%`);}\n if (scorecard.escalationRate > 0.55) {alerts.push(`Escalation rate too high: ${(scorecard.escalationRate * 100).toFixed(1)}%`);}\n if (scorecard.escalationRate > 0.2 && scorecard.escalationSuccessRate < 0.7) {\n alerts.push(`Escalation effectiveness is low: ${(scorecard.escalationSuccessRate * 100).toFixed(1)}%`);\n }\n if (regressions.length > 0) {alerts.push(`Quality regression events observed: ${regressions.length}`);}\n\n const sliceSize = Math.max(3, Math.min(10, Math.floor(runs.length / 2)));\n const latestSlice = runs.slice(0, sliceSize);\n const previousSlice = runs.slice(sliceSize, sliceSize * 2);\n const latestScorecard = scorecardOf(latestSlice);\n const previousScorecard = scorecardOf(previousSlice);\n\n const slices = previousSlice.length > 0\n ? {\n sliceSize,\n latest: latestScorecard,\n previous: previousScorecard,\n delta: {\n successRate: latestScorecard.successRate - previousScorecard.successRate,\n qualityPassRate: latestScorecard.qualityPassRate - previousScorecard.qualityPassRate,\n avgQualityScore: latestScorecard.avgQualityScore - previousScorecard.avgQualityScore,\n avgTokens: latestScorecard.avgTokens - previousScorecard.avgTokens,\n p95Tokens: latestScorecard.p95Tokens - previousScorecard.p95Tokens,\n avgDurationMs: latestScorecard.avgDurationMs - previousScorecard.avgDurationMs,\n avgToolCalls: latestScorecard.avgToolCalls - previousScorecard.avgToolCalls,\n avgToolErrorRate: latestScorecard.avgToolErrorRate - previousScorecard.avgToolErrorRate,\n avgDriftRate: latestScorecard.avgDriftRate - previousScorecard.avgDriftRate,\n avgEvidenceDensity: latestScorecard.avgEvidenceDensity - previousScorecard.avgEvidenceDensity,\n nearBudgetRate: latestScorecard.nearBudgetRate - previousScorecard.nearBudgetRate,\n escalationRate: latestScorecard.escalationRate - previousScorecard.escalationRate,\n escalationSuccessRate: latestScorecard.escalationSuccessRate - previousScorecard.escalationSuccessRate,\n avgEscalationCount: latestScorecard.avgEscalationCount - previousScorecard.avgEscalationCount,\n },\n }\n : null;\n\n return {\n periodDays: meta.days,\n sessionId: meta.sessionIdFilter,\n runs: count,\n regressions: regressions.length,\n scorecard,\n slices,\n alerts,\n topTokenRuns: topTokenRuns.map(toRunBrief),\n worstQualityRuns: worstQualityRuns.map(toRunBrief),\n };\n}\n\nfunction toRunBrief(run: RunSnapshot) {\n return {\n ts: run.ts,\n sessionId: run.sessionId,\n task: run.task.slice(0, 120),\n tokensUsed: run.tokensUsed,\n durationMs: run.durationMs,\n toolCallsTotal: run.toolCallsTotal,\n qualityStatus: run.qualityStatus,\n qualityScore: run.qualityScore,\n qualityReasons: run.qualityReasons,\n startTier: run.startTier,\n finalTier: run.finalTier,\n escalated: run.escalated,\n escalationCount: run.escalationCount,\n escalationReasons: run.escalationReasons,\n };\n}\n\nfunction avg(values: number[]): number {\n if (values.length === 0) {return 0;}\n return values.reduce((sum, value) => sum + value, 0) / values.length;\n}\n\nfunction p95(values: number[]): number {\n if (values.length === 0) {return 0;}\n const sorted = [...values].sort((a, b) => a - b);\n const index = Math.max(0, Math.min(sorted.length - 1, Math.ceil(sorted.length * 0.95) - 1));\n return sorted[index] || 0;\n}\n\nfunction scorecardOf(runs: RunSnapshot[]) {\n const escalatedRuns = runs.filter((r) => r.escalated);\n const nonEscalatedRuns = runs.filter((r) => !r.escalated);\n\n return {\n successRate: avg(runs.map((r) => (r.success ? 1 : 0))),\n qualityPassRate: avg(runs.map((r) => (r.qualityStatus === 'pass' ? 1 : 0))),\n avgQualityScore: avg(runs.map((r) => r.qualityScore)),\n avgTokens: avg(runs.map((r) => r.tokensUsed)),\n p95Tokens: p95(runs.map((r) => r.tokensUsed)),\n avgDurationMs: avg(runs.map((r) => r.durationMs)),\n avgToolCalls: avg(runs.map((r) => r.toolCallsTotal)),\n avgToolErrorRate: avg(runs.map((r) => r.toolErrorRate)),\n avgDriftRate: avg(runs.map((r) => r.driftRate)),\n avgEvidenceDensity: avg(runs.map((r) => r.evidenceDensity)),\n nearBudgetRate: avg(runs.map((r) => (r.iterationUtilization >= 0.9 ? 1 : 0))),\n escalationRate: avg(runs.map((r) => (r.escalated ? 1 : 0))),\n escalationSuccessRate: escalatedRuns.length > 0 ? avg(escalatedRuns.map((r) => (r.success ? 1 : 0))) : 0,\n avgEscalationCount: avg(runs.map((r) => r.escalationCount)),\n avgTokensEscalated: escalatedRuns.length > 0 ? avg(escalatedRuns.map((r) => r.tokensUsed)) : 0,\n avgTokensNonEscalated: nonEscalatedRuns.length > 0 ? avg(nonEscalatedRuns.map((r) => r.tokensUsed)) : 0,\n avgQualityEscalated: escalatedRuns.length > 0 ? avg(escalatedRuns.map((r) => r.qualityScore)) : 0,\n avgQualityNonEscalated: nonEscalatedRuns.length > 0 ? avg(nonEscalatedRuns.map((r) => r.qualityScore)) : 0,\n };\n}\n\nfunction printReport(ctx: PluginContextV3, report: any): void {\n if (report.runs === 0) {\n ctx.ui.write(`No KPI runs for selected period (${report.periodDays}d)\\n`);\n return;\n }\n\n const s = report.scorecard;\n ctx.ui.write('┌── Agent Quality Control Report\\n');\n ctx.ui.write(`│ Period: ${report.periodDays}d\\n`);\n if (report.sessionId) {\n ctx.ui.write(`│ Session: ${report.sessionId}\\n`);\n }\n ctx.ui.write(`│ Runs: ${report.runs} | Regressions: ${report.regressions}\\n`);\n ctx.ui.write('│\\n');\n ctx.ui.write(`│ Success Rate: ${(s.successRate * 100).toFixed(1)}%\\n`);\n ctx.ui.write(`│ Quality Pass: ${(s.qualityPassRate * 100).toFixed(1)}% | Avg score: ${s.avgQualityScore.toFixed(2)}\\n`);\n ctx.ui.write(`│ Tokens: avg ${Math.round(s.avgTokens)} | p95 ${Math.round(s.p95Tokens)}\\n`);\n ctx.ui.write(`│ Duration: avg ${(s.avgDurationMs / 1000).toFixed(1)}s\\n`);\n ctx.ui.write(`│ Tools: avg ${s.avgToolCalls.toFixed(1)} | error ${(s.avgToolErrorRate * 100).toFixed(2)}%\\n`);\n ctx.ui.write(`│ Drift: ${(s.avgDriftRate * 100).toFixed(2)}% | Evidence density: ${s.avgEvidenceDensity.toFixed(2)}\\n`);\n ctx.ui.write(`│ Near budget rate: ${(s.nearBudgetRate * 100).toFixed(1)}%\\n`);\n ctx.ui.write(`│ Escalation: ${(s.escalationRate * 100).toFixed(1)}% runs | success ${(s.escalationSuccessRate * 100).toFixed(1)}% | avg count ${s.avgEscalationCount.toFixed(2)}\\n`);\n if (s.escalationRate > 0 && s.escalationRate < 1) {\n const tokenDelta = s.avgTokensEscalated - s.avgTokensNonEscalated;\n const qualityDelta = s.avgQualityEscalated - s.avgQualityNonEscalated;\n ctx.ui.write(`│ Escalated vs non-escalated: Δtokens ${tokenDelta >= 0 ? '+' : ''}${Math.round(tokenDelta)} | Δquality ${qualityDelta >= 0 ? '+' : ''}${qualityDelta.toFixed(2)}\\n`);\n } else {\n ctx.ui.write('│ Escalated vs non-escalated: n/a (need both escalated and non-escalated runs)\\n');\n }\n\n if (report.slices) {\n const d = report.slices.delta;\n ctx.ui.write('│\\n');\n ctx.ui.write(`│ Slices (${report.slices.sliceSize} latest vs previous):\\n`);\n ctx.ui.write(`│ Δ Quality score: ${d.avgQualityScore >= 0 ? '+' : ''}${d.avgQualityScore.toFixed(2)}\\n`);\n ctx.ui.write(`│ Δ Avg tokens: ${d.avgTokens >= 0 ? '+' : ''}${Math.round(d.avgTokens)}\\n`);\n ctx.ui.write(`│ Δ Avg duration: ${d.avgDurationMs >= 0 ? '+' : ''}${(d.avgDurationMs / 1000).toFixed(1)}s\\n`);\n ctx.ui.write(`│ Δ Tool errors: ${d.avgToolErrorRate >= 0 ? '+' : ''}${(d.avgToolErrorRate * 100).toFixed(2)}%\\n`);\n ctx.ui.write(`│ Δ Drift: ${d.avgDriftRate >= 0 ? '+' : ''}${(d.avgDriftRate * 100).toFixed(2)}%\\n`);\n ctx.ui.write(`│ Δ Escalation rate: ${d.escalationRate >= 0 ? '+' : ''}${(d.escalationRate * 100).toFixed(1)}%\\n`);\n ctx.ui.write(`│ Δ Escalation success: ${d.escalationSuccessRate >= 0 ? '+' : ''}${(d.escalationSuccessRate * 100).toFixed(1)}%\\n`);\n ctx.ui.write(`│ Δ Escalation count: ${d.avgEscalationCount >= 0 ? '+' : ''}${d.avgEscalationCount.toFixed(2)}\\n`);\n }\n\n if (report.alerts.length > 0) {\n ctx.ui.write('│\\n');\n ctx.ui.write('│ Alerts:\\n');\n for (const alert of report.alerts) {\n ctx.ui.write(`│ - ${alert}\\n`);\n }\n }\n\n ctx.ui.write('│\\n');\n ctx.ui.write('│ Top expensive runs:\\n');\n for (const run of report.topTokenRuns) {\n const esc = run.escalated ? ` | esc=${run.escalationCount}` : '';\n ctx.ui.write(`│ - ${run.ts} | tok=${run.tokensUsed} | q=${run.qualityScore.toFixed(2)}${esc} | ${run.task}\\n`);\n }\n\n ctx.ui.write('│\\n');\n ctx.ui.write('│ Worst quality runs:\\n');\n for (const run of report.worstQualityRuns) {\n const reasons = (run.qualityReasons || []).join(', ');\n ctx.ui.write(`│ - ${run.ts} | q=${run.qualityScore.toFixed(2)} | tok=${run.tokensUsed} | reasons=${reasons || 'n/a'}\\n`);\n }\n ctx.ui.write('└──\\n');\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* agent:rollback — Rollback file changes made by agents.
|
|
5
|
+
*
|
|
6
|
+
* Uses ChangeStore from @kb-labs/agent-history.
|
|
7
|
+
* All rollback logic is in ChangeTrackingMiddleware.rollbackRun() or handled here via ChangeStore.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* pnpm kb agent:rollback --run-id={id} --session-id={id}
|
|
11
|
+
* pnpm kb agent:rollback --file=src/index.ts --session-id={id}
|
|
12
|
+
* pnpm kb agent:rollback --session-id={id}
|
|
13
|
+
* pnpm kb agent:rollback --run-id={id} --session-id={id} --dry-run
|
|
14
|
+
*/
|
|
15
|
+
type RollbackInput = {
|
|
16
|
+
'run-id'?: string;
|
|
17
|
+
runId?: string;
|
|
18
|
+
'session-id'?: string;
|
|
19
|
+
sessionId?: string;
|
|
20
|
+
file?: string;
|
|
21
|
+
'dry-run'?: boolean;
|
|
22
|
+
dryRun?: boolean;
|
|
23
|
+
json?: boolean;
|
|
24
|
+
};
|
|
25
|
+
declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, RollbackInput, unknown>;
|
|
26
|
+
|
|
27
|
+
export { _default as default };
|