nodebench-mcp 2.22.0 → 2.26.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.
Files changed (96) hide show
  1. package/NODEBENCH_AGENTS.md +5 -4
  2. package/README.md +495 -280
  3. package/dist/__tests__/architectComplex.test.js +3 -5
  4. package/dist/__tests__/architectComplex.test.js.map +1 -1
  5. package/dist/__tests__/batchAutopilot.test.d.ts +8 -0
  6. package/dist/__tests__/batchAutopilot.test.js +218 -0
  7. package/dist/__tests__/batchAutopilot.test.js.map +1 -0
  8. package/dist/__tests__/cliSubcommands.test.d.ts +1 -0
  9. package/dist/__tests__/cliSubcommands.test.js +138 -0
  10. package/dist/__tests__/cliSubcommands.test.js.map +1 -0
  11. package/dist/__tests__/evalHarness.test.js +1 -1
  12. package/dist/__tests__/forecastingDogfood.test.d.ts +9 -0
  13. package/dist/__tests__/forecastingDogfood.test.js +284 -0
  14. package/dist/__tests__/forecastingDogfood.test.js.map +1 -0
  15. package/dist/__tests__/forecastingScoring.test.d.ts +9 -0
  16. package/dist/__tests__/forecastingScoring.test.js +202 -0
  17. package/dist/__tests__/forecastingScoring.test.js.map +1 -0
  18. package/dist/__tests__/localDashboard.test.d.ts +1 -0
  19. package/dist/__tests__/localDashboard.test.js +226 -0
  20. package/dist/__tests__/localDashboard.test.js.map +1 -0
  21. package/dist/__tests__/multiHopDogfood.test.d.ts +12 -0
  22. package/dist/__tests__/multiHopDogfood.test.js +303 -0
  23. package/dist/__tests__/multiHopDogfood.test.js.map +1 -0
  24. package/dist/__tests__/openclawDogfood.test.d.ts +23 -0
  25. package/dist/__tests__/openclawDogfood.test.js +535 -0
  26. package/dist/__tests__/openclawDogfood.test.js.map +1 -0
  27. package/dist/__tests__/openclawMessaging.test.d.ts +14 -0
  28. package/dist/__tests__/openclawMessaging.test.js +232 -0
  29. package/dist/__tests__/openclawMessaging.test.js.map +1 -0
  30. package/dist/__tests__/tools.test.js +7 -3
  31. package/dist/__tests__/tools.test.js.map +1 -1
  32. package/dist/__tests__/traceabilityDogfood.test.d.ts +12 -0
  33. package/dist/__tests__/traceabilityDogfood.test.js +241 -0
  34. package/dist/__tests__/traceabilityDogfood.test.js.map +1 -0
  35. package/dist/__tests__/webmcpTools.test.d.ts +7 -0
  36. package/dist/__tests__/webmcpTools.test.js +195 -0
  37. package/dist/__tests__/webmcpTools.test.js.map +1 -0
  38. package/dist/dashboard/briefHtml.d.ts +20 -0
  39. package/dist/dashboard/briefHtml.js +1000 -0
  40. package/dist/dashboard/briefHtml.js.map +1 -0
  41. package/dist/dashboard/briefServer.d.ts +18 -0
  42. package/dist/dashboard/briefServer.js +320 -0
  43. package/dist/dashboard/briefServer.js.map +1 -0
  44. package/dist/dashboard/html.d.ts +18 -0
  45. package/dist/dashboard/html.js +1491 -0
  46. package/dist/dashboard/html.js.map +1 -0
  47. package/dist/dashboard/server.d.ts +17 -0
  48. package/dist/dashboard/server.js +403 -0
  49. package/dist/dashboard/server.js.map +1 -0
  50. package/dist/db.js +38 -0
  51. package/dist/db.js.map +1 -1
  52. package/dist/index.js +211 -5
  53. package/dist/index.js.map +1 -1
  54. package/dist/tools/critterTools.js +4 -0
  55. package/dist/tools/critterTools.js.map +1 -1
  56. package/dist/tools/forecastingTools.d.ts +11 -0
  57. package/dist/tools/forecastingTools.js +616 -0
  58. package/dist/tools/forecastingTools.js.map +1 -0
  59. package/dist/tools/localDashboardTools.d.ts +8 -0
  60. package/dist/tools/localDashboardTools.js +332 -0
  61. package/dist/tools/localDashboardTools.js.map +1 -0
  62. package/dist/tools/metaTools.js +170 -1
  63. package/dist/tools/metaTools.js.map +1 -1
  64. package/dist/tools/openclawTools.d.ts +11 -0
  65. package/dist/tools/openclawTools.js +1017 -0
  66. package/dist/tools/openclawTools.js.map +1 -0
  67. package/dist/tools/overstoryTools.d.ts +14 -0
  68. package/dist/tools/overstoryTools.js +426 -0
  69. package/dist/tools/overstoryTools.js.map +1 -0
  70. package/dist/tools/prReportTools.d.ts +11 -0
  71. package/dist/tools/prReportTools.js +911 -0
  72. package/dist/tools/prReportTools.js.map +1 -0
  73. package/dist/tools/progressiveDiscoveryTools.js +28 -9
  74. package/dist/tools/progressiveDiscoveryTools.js.map +1 -1
  75. package/dist/tools/selfEvalTools.js +8 -1
  76. package/dist/tools/selfEvalTools.js.map +1 -1
  77. package/dist/tools/sessionMemoryTools.js +14 -2
  78. package/dist/tools/sessionMemoryTools.js.map +1 -1
  79. package/dist/tools/skillUpdateTools.d.ts +24 -0
  80. package/dist/tools/skillUpdateTools.js +469 -0
  81. package/dist/tools/skillUpdateTools.js.map +1 -0
  82. package/dist/tools/toolRegistry.js +178 -0
  83. package/dist/tools/toolRegistry.js.map +1 -1
  84. package/dist/tools/uiUxDiveAdvancedTools.js +61 -0
  85. package/dist/tools/uiUxDiveAdvancedTools.js.map +1 -1
  86. package/dist/tools/uiUxDiveTools.js +154 -1
  87. package/dist/tools/uiUxDiveTools.js.map +1 -1
  88. package/dist/tools/visualQaTools.d.ts +2 -0
  89. package/dist/tools/visualQaTools.js +1088 -0
  90. package/dist/tools/visualQaTools.js.map +1 -0
  91. package/dist/tools/webmcpTools.d.ts +16 -0
  92. package/dist/tools/webmcpTools.js +703 -0
  93. package/dist/tools/webmcpTools.js.map +1 -0
  94. package/dist/toolsetRegistry.js +4 -0
  95. package/dist/toolsetRegistry.js.map +1 -1
  96. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/dashboard/html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,UAAU,gBAAgB;IAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA87CD,CAAC;AACT,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * NodeBench MCP — Local Dashboard Server
3
+ *
4
+ * Serves a local web dashboard showing the full UI Dive flywheel cycle:
5
+ * explored routes, components, interactions, screenshots, bugs,
6
+ * code locations, fixes, changelogs, generated tests, code reviews.
7
+ *
8
+ * Inspired by Serena MCP's local dashboard. Zero external deps — uses
9
+ * Node's built-in http module + reads from existing SQLite DB.
10
+ */
11
+ import type Database from "better-sqlite3";
12
+ /** Start the dashboard HTTP server. Returns the port it's listening on. */
13
+ export declare function startDashboardServer(db: Database.Database, preferredPort?: number): Promise<number>;
14
+ /** Stop the dashboard server */
15
+ export declare function stopDashboardServer(): void;
16
+ /** Get the current dashboard URL */
17
+ export declare function getDashboardUrl(): string | null;
@@ -0,0 +1,403 @@
1
+ /**
2
+ * NodeBench MCP — Local Dashboard Server
3
+ *
4
+ * Serves a local web dashboard showing the full UI Dive flywheel cycle:
5
+ * explored routes, components, interactions, screenshots, bugs,
6
+ * code locations, fixes, changelogs, generated tests, code reviews.
7
+ *
8
+ * Inspired by Serena MCP's local dashboard. Zero external deps — uses
9
+ * Node's built-in http module + reads from existing SQLite DB.
10
+ */
11
+ import { createServer } from "node:http";
12
+ import { getDashboardHtml } from "./html.js";
13
+ let _server = null;
14
+ let _port = 0;
15
+ /** Start the dashboard HTTP server. Returns the port it's listening on. */
16
+ export function startDashboardServer(db, preferredPort = 6274) {
17
+ return new Promise((resolve, reject) => {
18
+ if (_server) {
19
+ resolve(_port);
20
+ return;
21
+ }
22
+ _server = createServer((req, res) => handleRequest(db, req, res));
23
+ let attempts = 0;
24
+ const maxAttempts = 10;
25
+ function tryListen(port) {
26
+ _server.listen(port, "127.0.0.1", () => {
27
+ _port = port;
28
+ resolve(_port);
29
+ });
30
+ }
31
+ _server.on("error", (err) => {
32
+ if (err.code === "EADDRINUSE" && attempts < maxAttempts) {
33
+ attempts++;
34
+ tryListen(preferredPort + attempts);
35
+ }
36
+ else {
37
+ reject(err);
38
+ }
39
+ });
40
+ tryListen(preferredPort);
41
+ });
42
+ }
43
+ /** Stop the dashboard server */
44
+ export function stopDashboardServer() {
45
+ if (_server) {
46
+ _server.close();
47
+ _server = null;
48
+ _port = 0;
49
+ }
50
+ }
51
+ /** Get the current dashboard URL */
52
+ export function getDashboardUrl() {
53
+ return _port ? `http://127.0.0.1:${_port}` : null;
54
+ }
55
+ // ── Request Router ──────────────────────────────────────────────────
56
+ function handleRequest(db, req, res) {
57
+ const url = new URL(req.url || "/", `http://127.0.0.1:${_port}`);
58
+ const path = url.pathname;
59
+ // CORS for local dev
60
+ res.setHeader("Access-Control-Allow-Origin", "*");
61
+ res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
62
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
63
+ if (req.method === "OPTIONS") {
64
+ res.writeHead(204);
65
+ res.end();
66
+ return;
67
+ }
68
+ try {
69
+ if (path === "/" || path === "/index.html") {
70
+ serveHtml(res);
71
+ }
72
+ else if (path === "/api/sessions") {
73
+ apiSessions(db, res);
74
+ }
75
+ else if (path.startsWith("/api/screenshot/") && path.endsWith("/image")) {
76
+ const ssId = decodeURIComponent(path.split("/api/screenshot/")[1].split("/image")[0]);
77
+ apiScreenshotImage(db, ssId, res);
78
+ }
79
+ else if (path.startsWith("/api/session/")) {
80
+ const sessionId = decodeURIComponent(path.split("/api/session/")[1].split("/")[0]);
81
+ const sub = path.split(sessionId + "/")[1] || "overview";
82
+ apiSessionDetail(db, sessionId, sub, res);
83
+ }
84
+ else if (path === "/api/latest") {
85
+ apiLatestSession(db, res);
86
+ }
87
+ else if (path === "/api/agents/status") {
88
+ apiAgentStatus(db, res);
89
+ }
90
+ else if (path === "/api/agents/activity") {
91
+ apiAgentActivity(db, res);
92
+ }
93
+ else if (path === "/api/agents/mailbox") {
94
+ apiAgentMailbox(db, res);
95
+ }
96
+ else {
97
+ res.writeHead(404, { "Content-Type": "application/json" });
98
+ res.end(JSON.stringify({ error: "Not found" }));
99
+ }
100
+ }
101
+ catch (err) {
102
+ res.writeHead(500, { "Content-Type": "application/json" });
103
+ res.end(JSON.stringify({ error: err.message }));
104
+ }
105
+ }
106
+ // ── HTML ────────────────────────────────────────────────────────────
107
+ function serveHtml(res) {
108
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
109
+ res.end(getDashboardHtml());
110
+ }
111
+ // ── API: List sessions ──────────────────────────────────────────────
112
+ function apiSessions(db, res) {
113
+ const rows = db.prepare(`
114
+ SELECT s.id, s.app_url, s.app_name, s.status, s.created_at, s.completed_at,
115
+ (SELECT COUNT(*) FROM ui_dive_components WHERE session_id = s.id) as component_count,
116
+ (SELECT COUNT(*) FROM ui_dive_bugs WHERE session_id = s.id) as bug_count,
117
+ (SELECT COUNT(*) FROM ui_dive_bugs WHERE session_id = s.id AND status = 'resolved') as bugs_resolved,
118
+ (SELECT COUNT(*) FROM ui_dive_interactions WHERE session_id = s.id) as interaction_count,
119
+ (SELECT COUNT(*) FROM ui_dive_fix_verifications WHERE session_id = s.id) as fix_count,
120
+ (SELECT COUNT(*) FROM ui_dive_code_reviews WHERE session_id = s.id) as review_count
121
+ FROM ui_dive_sessions s
122
+ ORDER BY s.created_at DESC
123
+ LIMIT 50
124
+ `).all();
125
+ json(res, rows);
126
+ }
127
+ // ── API: Latest session redirect ────────────────────────────────────
128
+ function apiLatestSession(db, res) {
129
+ const row = db.prepare(`
130
+ SELECT id FROM ui_dive_sessions ORDER BY created_at DESC LIMIT 1
131
+ `).get();
132
+ if (!row) {
133
+ json(res, { error: "No sessions found" }, 404);
134
+ return;
135
+ }
136
+ // Return full overview for latest
137
+ apiSessionDetail(db, row.id, "overview", res);
138
+ }
139
+ // ── API: Session detail ─────────────────────────────────────────────
140
+ function apiSessionDetail(db, sessionId, sub, res) {
141
+ switch (sub) {
142
+ case "overview":
143
+ return apiOverview(db, sessionId, res);
144
+ case "components":
145
+ return apiComponents(db, sessionId, res);
146
+ case "bugs":
147
+ return apiBugs(db, sessionId, res);
148
+ case "interactions":
149
+ return apiInteractions(db, sessionId, res);
150
+ case "screenshots":
151
+ return apiScreenshots(db, sessionId, res);
152
+ case "code-locations":
153
+ return apiCodeLocations(db, sessionId, res);
154
+ case "fixes":
155
+ return apiFixes(db, sessionId, res);
156
+ case "changelogs":
157
+ return apiChangelogs(db, sessionId, res);
158
+ case "tests":
159
+ return apiTests(db, sessionId, res);
160
+ case "reviews":
161
+ return apiReviews(db, sessionId, res);
162
+ case "design-issues":
163
+ return apiDesignIssues(db, sessionId, res);
164
+ default:
165
+ json(res, { error: `Unknown sub-route: ${sub}` }, 404);
166
+ }
167
+ }
168
+ function apiOverview(db, sid, res) {
169
+ const session = db.prepare("SELECT * FROM ui_dive_sessions WHERE id = ?").get(sid);
170
+ if (!session) {
171
+ json(res, { error: "Session not found" }, 404);
172
+ return;
173
+ }
174
+ const stats = {
175
+ components: db.prepare("SELECT COUNT(*) as c FROM ui_dive_components WHERE session_id = ?").get(sid),
176
+ interactions: db.prepare("SELECT COUNT(*) as c FROM ui_dive_interactions WHERE session_id = ?").get(sid),
177
+ bugs: db.prepare("SELECT COUNT(*) as c FROM ui_dive_bugs WHERE session_id = ?").get(sid),
178
+ bugsOpen: db.prepare("SELECT COUNT(*) as c FROM ui_dive_bugs WHERE session_id = ? AND status = 'open'").get(sid),
179
+ bugsResolved: db.prepare("SELECT COUNT(*) as c FROM ui_dive_bugs WHERE session_id = ? AND status = 'resolved'").get(sid),
180
+ screenshots: db.prepare("SELECT COUNT(*) as c FROM ui_dive_screenshots WHERE session_id = ?").get(sid),
181
+ tests: db.prepare("SELECT COUNT(*) as c FROM ui_dive_interaction_tests WHERE session_id = ?").get(sid),
182
+ designIssues: db.prepare("SELECT COUNT(*) as c FROM ui_dive_design_issues WHERE session_id = ?").get(sid),
183
+ codeLocations: db.prepare("SELECT COUNT(*) as c FROM ui_dive_code_locations WHERE session_id = ?").get(sid),
184
+ fixes: db.prepare("SELECT COUNT(*) as c FROM ui_dive_fix_verifications WHERE session_id = ?").get(sid),
185
+ fixesVerified: db.prepare("SELECT COUNT(*) as c FROM ui_dive_fix_verifications WHERE session_id = ? AND verified = 1").get(sid),
186
+ changelogs: db.prepare("SELECT COUNT(*) as c FROM ui_dive_changelogs WHERE session_id = ?").get(sid),
187
+ generatedTests: db.prepare("SELECT COUNT(*) as c FROM ui_dive_generated_tests WHERE session_id = ?").get(sid),
188
+ codeReviews: db.prepare("SELECT COUNT(*) as c FROM ui_dive_code_reviews WHERE session_id = ?").get(sid),
189
+ };
190
+ const latestReview = db.prepare("SELECT score, summary, severity_counts, recommendations FROM ui_dive_code_reviews WHERE session_id = ? ORDER BY created_at DESC LIMIT 1").get(sid);
191
+ json(res, {
192
+ session,
193
+ stats: Object.fromEntries(Object.entries(stats).map(([k, v]) => [k, v?.c ?? 0])),
194
+ latestReview,
195
+ });
196
+ }
197
+ function apiComponents(db, sid, res) {
198
+ json(res, db.prepare("SELECT * FROM ui_dive_components WHERE session_id = ? ORDER BY created_at").all(sid));
199
+ }
200
+ function apiBugs(db, sid, res) {
201
+ json(res, db.prepare(`
202
+ SELECT b.*, c.name as component_name
203
+ FROM ui_dive_bugs b
204
+ LEFT JOIN ui_dive_components c ON b.component_id = c.id
205
+ WHERE b.session_id = ?
206
+ ORDER BY
207
+ CASE b.severity WHEN 'critical' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 ELSE 3 END,
208
+ b.created_at
209
+ `).all(sid));
210
+ }
211
+ function apiInteractions(db, sid, res) {
212
+ json(res, db.prepare(`
213
+ SELECT i.*, c.name as component_name
214
+ FROM ui_dive_interactions i
215
+ LEFT JOIN ui_dive_components c ON i.component_id = c.id
216
+ WHERE i.session_id = ?
217
+ ORDER BY i.sequence_num
218
+ `).all(sid));
219
+ }
220
+ function apiScreenshots(db, sid, res) {
221
+ json(res, db.prepare("SELECT id, session_id, component_id, label, route, file_path, base64_thumbnail, width, height, metadata, created_at FROM ui_dive_screenshots WHERE session_id = ? ORDER BY created_at").all(sid));
222
+ }
223
+ /** Serve a screenshot as an actual PNG image */
224
+ function apiScreenshotImage(db, ssId, res) {
225
+ const row = db.prepare("SELECT base64_thumbnail, file_path FROM ui_dive_screenshots WHERE id = ?").get(ssId);
226
+ if (!row) {
227
+ res.writeHead(404, { "Content-Type": "text/plain" });
228
+ res.end("Screenshot not found");
229
+ return;
230
+ }
231
+ // Prefer inline base64, fall back to file on disk
232
+ if (row.base64_thumbnail) {
233
+ const buf = Buffer.from(row.base64_thumbnail, "base64");
234
+ res.writeHead(200, {
235
+ "Content-Type": "image/png",
236
+ "Content-Length": buf.length.toString(),
237
+ "Cache-Control": "public, max-age=86400",
238
+ });
239
+ res.end(buf);
240
+ return;
241
+ }
242
+ if (row.file_path) {
243
+ try {
244
+ const fs = require("node:fs");
245
+ const buf = fs.readFileSync(row.file_path);
246
+ res.writeHead(200, {
247
+ "Content-Type": "image/png",
248
+ "Content-Length": buf.length.toString(),
249
+ "Cache-Control": "public, max-age=86400",
250
+ });
251
+ res.end(buf);
252
+ }
253
+ catch {
254
+ res.writeHead(404, { "Content-Type": "text/plain" });
255
+ res.end("Screenshot file not found on disk");
256
+ }
257
+ return;
258
+ }
259
+ res.writeHead(404, { "Content-Type": "text/plain" });
260
+ res.end("No image data available");
261
+ }
262
+ function apiCodeLocations(db, sid, res) {
263
+ json(res, db.prepare("SELECT * FROM ui_dive_code_locations WHERE session_id = ? ORDER BY created_at").all(sid));
264
+ }
265
+ function apiFixes(db, sid, res) {
266
+ json(res, db.prepare(`
267
+ SELECT f.*, b.title as bug_title, b.severity as bug_severity, b.status as bug_status
268
+ FROM ui_dive_fix_verifications f
269
+ LEFT JOIN ui_dive_bugs b ON f.bug_id = b.id
270
+ WHERE f.session_id = ?
271
+ ORDER BY f.created_at
272
+ `).all(sid));
273
+ }
274
+ function apiChangelogs(db, sid, res) {
275
+ json(res, db.prepare("SELECT * FROM ui_dive_changelogs WHERE session_id = ? ORDER BY created_at DESC").all(sid));
276
+ }
277
+ function apiTests(db, sid, res) {
278
+ json(res, db.prepare("SELECT * FROM ui_dive_generated_tests WHERE session_id = ? ORDER BY created_at").all(sid));
279
+ }
280
+ function apiReviews(db, sid, res) {
281
+ json(res, db.prepare("SELECT * FROM ui_dive_code_reviews WHERE session_id = ? ORDER BY created_at DESC").all(sid));
282
+ }
283
+ function apiDesignIssues(db, sid, res) {
284
+ json(res, db.prepare("SELECT * FROM ui_dive_design_issues WHERE session_id = ? ORDER BY created_at").all(sid));
285
+ }
286
+ // ── API: Agent Monitor ──────────────────────────────────────────────
287
+ function apiAgentStatus(db, res) {
288
+ // Only agents active in the last 2 hours (has recent calls OR a claimed task)
289
+ const roles = db.prepare(`
290
+ SELECT r.session_id, r.role, r.focus_area, r.created_at
291
+ FROM agent_roles r
292
+ WHERE EXISTS (
293
+ SELECT 1 FROM tool_call_log t
294
+ WHERE t.session_id = r.session_id AND t.created_at >= datetime('now', '-2 hours')
295
+ ) OR EXISTS (
296
+ SELECT 1 FROM agent_tasks a
297
+ WHERE a.session_id = r.session_id AND a.status = 'claimed'
298
+ AND a.claimed_at >= datetime('now', '-4 hours')
299
+ )
300
+ ORDER BY r.created_at DESC
301
+ LIMIT 20
302
+ `).all();
303
+ const agents = roles.map(r => {
304
+ const task = db.prepare(`
305
+ SELECT task_key, description, claimed_at
306
+ FROM agent_tasks
307
+ WHERE session_id = ? AND status = 'claimed'
308
+ ORDER BY claimed_at DESC LIMIT 1
309
+ `).get(r.session_id);
310
+ const callCount = db.prepare(`
311
+ SELECT COUNT(*) as c FROM tool_call_log
312
+ WHERE session_id = ? AND created_at >= datetime('now', '-30 minutes')
313
+ `).get(r.session_id);
314
+ const lastCall = db.prepare(`
315
+ SELECT created_at FROM tool_call_log
316
+ WHERE session_id = ? ORDER BY created_at DESC LIMIT 1
317
+ `).get(r.session_id);
318
+ const budget = db.prepare(`
319
+ SELECT tokens_used, tokens_limit FROM context_budget_log
320
+ WHERE session_id = ? ORDER BY created_at DESC LIMIT 1
321
+ `).get(r.session_id);
322
+ const unread = db.prepare(`
323
+ SELECT COUNT(*) as c FROM agent_mailbox
324
+ WHERE (recipient_id = ? OR recipient_role = ?) AND read = 0
325
+ `).get(r.session_id, r.role);
326
+ return {
327
+ sessionId: r.session_id,
328
+ role: r.role,
329
+ focusArea: r.focus_area,
330
+ assignedAt: r.created_at,
331
+ currentTask: task ? { key: task.task_key, description: task.description, claimedAt: task.claimed_at } : null,
332
+ toolCallCount: callCount.c,
333
+ lastCallAt: lastCall?.created_at ?? null,
334
+ tokenBudget: budget
335
+ ? { used: budget.tokens_used, limit: budget.tokens_limit, percent: Math.round((budget.tokens_used / budget.tokens_limit) * 100) }
336
+ : { used: 0, limit: 200000, percent: 0 },
337
+ unreadMessages: unread.c,
338
+ };
339
+ });
340
+ // Summary stats
341
+ const activeSessions = agents.map(a => a.sessionId);
342
+ const totalCalls = activeSessions.length > 0
343
+ ? db.prepare(`SELECT COUNT(*) as c FROM tool_call_log WHERE session_id IN (${activeSessions.map(() => "?").join(",")})`)
344
+ .get(...activeSessions).c
345
+ : 0;
346
+ const claimedCount = agents.filter(a => a.currentTask).length;
347
+ const completedTasks = db.prepare(`
348
+ SELECT task_key, session_id, description, progress_note, released_at
349
+ FROM agent_tasks
350
+ WHERE status = 'released' AND released_at >= datetime('now', '-1 hour')
351
+ ORDER BY released_at DESC LIMIT 20
352
+ `).all();
353
+ json(res, {
354
+ agents,
355
+ completedTasks,
356
+ summary: {
357
+ activeAgents: agents.length,
358
+ activeTasks: claimedCount,
359
+ completedTasks: completedTasks.length,
360
+ totalCalls,
361
+ },
362
+ });
363
+ }
364
+ function apiAgentActivity(db, res) {
365
+ // Only show calls from agents active in last 2 hours
366
+ const calls = db.prepare(`
367
+ SELECT t.tool_name, t.session_id, t.result_status, t.duration_ms, t.created_at
368
+ FROM tool_call_log t
369
+ WHERE EXISTS (
370
+ SELECT 1 FROM agent_roles r
371
+ WHERE r.session_id = t.session_id AND (
372
+ EXISTS (SELECT 1 FROM tool_call_log t2 WHERE t2.session_id = r.session_id AND t2.created_at >= datetime('now', '-2 hours'))
373
+ OR EXISTS (SELECT 1 FROM agent_tasks a WHERE a.session_id = r.session_id AND a.status = 'claimed')
374
+ )
375
+ )
376
+ ORDER BY t.created_at DESC LIMIT 30
377
+ `).all();
378
+ json(res, { calls, totalCalls: calls.length });
379
+ }
380
+ function apiAgentMailbox(db, res) {
381
+ // Deduplicate by subject+sender — keep only the latest of each
382
+ const messages = db.prepare(`
383
+ SELECT id, sender_id, recipient_id, recipient_role, category, priority, subject, body, created_at
384
+ FROM agent_mailbox
385
+ WHERE read = 0 AND id IN (
386
+ SELECT id FROM (
387
+ SELECT id, ROW_NUMBER() OVER (PARTITION BY sender_id, subject ORDER BY created_at DESC) as rn
388
+ FROM agent_mailbox WHERE read = 0
389
+ ) WHERE rn = 1
390
+ )
391
+ ORDER BY
392
+ CASE priority WHEN 'critical' THEN 0 WHEN 'high' THEN 1 WHEN 'normal' THEN 2 ELSE 3 END,
393
+ created_at DESC
394
+ LIMIT 10
395
+ `).all();
396
+ json(res, { messages });
397
+ }
398
+ // ── Helpers ─────────────────────────────────────────────────────────
399
+ function json(res, data, status = 200) {
400
+ res.writeHead(status, { "Content-Type": "application/json" });
401
+ res.end(JSON.stringify(data));
402
+ }
403
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/dashboard/server.ts"],"names":[],"mappings":"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"}
package/dist/db.js CHANGED
@@ -614,6 +614,44 @@ CREATE INDEX IF NOT EXISTS idx_dive_code_locations_bug ON ui_dive_code_locations
614
614
  CREATE INDEX IF NOT EXISTS idx_dive_fix_verifications_bug ON ui_dive_fix_verifications(bug_id);
615
615
  CREATE INDEX IF NOT EXISTS idx_dive_generated_tests_session ON ui_dive_generated_tests(session_id);
616
616
  CREATE INDEX IF NOT EXISTS idx_dive_code_reviews_session ON ui_dive_code_reviews(session_id);
617
+
618
+ -- ═══════════════════════════════════════════
619
+ -- SKILL SELF-UPDATE PROTOCOL — Track rule/
620
+ -- memory file provenance, source hashes,
621
+ -- update triggers, sync history.
622
+ -- ═══════════════════════════════════════════
623
+
624
+ CREATE TABLE IF NOT EXISTS skills (
625
+ id TEXT PRIMARY KEY,
626
+ skill_id TEXT NOT NULL UNIQUE,
627
+ name TEXT NOT NULL,
628
+ file_path TEXT NOT NULL,
629
+ description TEXT,
630
+ source_files TEXT NOT NULL DEFAULT '[]',
631
+ source_hash TEXT,
632
+ update_triggers TEXT NOT NULL DEFAULT '[]',
633
+ update_instructions TEXT NOT NULL DEFAULT '[]',
634
+ last_synced_at TEXT,
635
+ status TEXT NOT NULL DEFAULT 'fresh',
636
+ metadata TEXT,
637
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
638
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
639
+ );
640
+
641
+ CREATE TABLE IF NOT EXISTS skill_sync_history (
642
+ id TEXT PRIMARY KEY,
643
+ skill_id TEXT NOT NULL,
644
+ previous_hash TEXT,
645
+ new_hash TEXT NOT NULL,
646
+ changed_sources TEXT,
647
+ trigger_reason TEXT,
648
+ sync_notes TEXT,
649
+ synced_at TEXT NOT NULL DEFAULT (datetime('now'))
650
+ );
651
+
652
+ CREATE INDEX IF NOT EXISTS idx_skills_skill_id ON skills(skill_id);
653
+ CREATE INDEX IF NOT EXISTS idx_skills_status ON skills(status);
654
+ CREATE INDEX IF NOT EXISTS idx_skill_sync_history_skill ON skill_sync_history(skill_id);
617
655
  `;
618
656
  export function getDb() {
619
657
  if (_db)
package/dist/db.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}