nodebench-mcp 2.21.1 → 2.25.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 (40) hide show
  1. package/README.md +366 -280
  2. package/dist/__tests__/dynamicLoading.test.js +4 -2
  3. package/dist/__tests__/dynamicLoading.test.js.map +1 -1
  4. package/dist/__tests__/multiHopDogfood.test.d.ts +12 -0
  5. package/dist/__tests__/multiHopDogfood.test.js +303 -0
  6. package/dist/__tests__/multiHopDogfood.test.js.map +1 -0
  7. package/dist/__tests__/presetRealWorldBench.test.js +2 -0
  8. package/dist/__tests__/presetRealWorldBench.test.js.map +1 -1
  9. package/dist/__tests__/tools.test.js +158 -6
  10. package/dist/__tests__/tools.test.js.map +1 -1
  11. package/dist/__tests__/toolsetGatingEval.test.js +2 -0
  12. package/dist/__tests__/toolsetGatingEval.test.js.map +1 -1
  13. package/dist/dashboard/html.d.ts +18 -0
  14. package/dist/dashboard/html.js +1251 -0
  15. package/dist/dashboard/html.js.map +1 -0
  16. package/dist/dashboard/server.d.ts +17 -0
  17. package/dist/dashboard/server.js +278 -0
  18. package/dist/dashboard/server.js.map +1 -0
  19. package/dist/db.js +108 -0
  20. package/dist/db.js.map +1 -1
  21. package/dist/index.js +19 -9
  22. package/dist/index.js.map +1 -1
  23. package/dist/tools/prReportTools.d.ts +11 -0
  24. package/dist/tools/prReportTools.js +911 -0
  25. package/dist/tools/prReportTools.js.map +1 -0
  26. package/dist/tools/progressiveDiscoveryTools.js +111 -24
  27. package/dist/tools/progressiveDiscoveryTools.js.map +1 -1
  28. package/dist/tools/skillUpdateTools.d.ts +24 -0
  29. package/dist/tools/skillUpdateTools.js +469 -0
  30. package/dist/tools/skillUpdateTools.js.map +1 -0
  31. package/dist/tools/toolRegistry.d.ts +15 -1
  32. package/dist/tools/toolRegistry.js +379 -11
  33. package/dist/tools/toolRegistry.js.map +1 -1
  34. package/dist/tools/uiUxDiveAdvancedTools.js +688 -0
  35. package/dist/tools/uiUxDiveAdvancedTools.js.map +1 -1
  36. package/dist/tools/uiUxDiveTools.js +154 -1
  37. package/dist/tools/uiUxDiveTools.js.map +1 -1
  38. package/dist/toolsetRegistry.js +4 -0
  39. package/dist/toolsetRegistry.js.map +1 -1
  40. package/package.json +2 -2
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA8sCD,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,278 @@
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
+ _server.on("error", (err) => {
24
+ if (err.code === "EADDRINUSE") {
25
+ // Try next port
26
+ _server.listen(preferredPort + 1, "127.0.0.1");
27
+ _port = preferredPort + 1;
28
+ }
29
+ else {
30
+ reject(err);
31
+ }
32
+ });
33
+ _server.listen(preferredPort, "127.0.0.1", () => {
34
+ _port = preferredPort;
35
+ resolve(_port);
36
+ });
37
+ });
38
+ }
39
+ /** Stop the dashboard server */
40
+ export function stopDashboardServer() {
41
+ if (_server) {
42
+ _server.close();
43
+ _server = null;
44
+ _port = 0;
45
+ }
46
+ }
47
+ /** Get the current dashboard URL */
48
+ export function getDashboardUrl() {
49
+ return _port ? `http://127.0.0.1:${_port}` : null;
50
+ }
51
+ // ── Request Router ──────────────────────────────────────────────────
52
+ function handleRequest(db, req, res) {
53
+ const url = new URL(req.url || "/", `http://127.0.0.1:${_port}`);
54
+ const path = url.pathname;
55
+ // CORS for local dev
56
+ res.setHeader("Access-Control-Allow-Origin", "*");
57
+ res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
58
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
59
+ if (req.method === "OPTIONS") {
60
+ res.writeHead(204);
61
+ res.end();
62
+ return;
63
+ }
64
+ try {
65
+ if (path === "/" || path === "/index.html") {
66
+ serveHtml(res);
67
+ }
68
+ else if (path === "/api/sessions") {
69
+ apiSessions(db, res);
70
+ }
71
+ else if (path.startsWith("/api/screenshot/") && path.endsWith("/image")) {
72
+ const ssId = decodeURIComponent(path.split("/api/screenshot/")[1].split("/image")[0]);
73
+ apiScreenshotImage(db, ssId, res);
74
+ }
75
+ else if (path.startsWith("/api/session/")) {
76
+ const sessionId = decodeURIComponent(path.split("/api/session/")[1].split("/")[0]);
77
+ const sub = path.split(sessionId + "/")[1] || "overview";
78
+ apiSessionDetail(db, sessionId, sub, res);
79
+ }
80
+ else if (path === "/api/latest") {
81
+ apiLatestSession(db, res);
82
+ }
83
+ else {
84
+ res.writeHead(404, { "Content-Type": "application/json" });
85
+ res.end(JSON.stringify({ error: "Not found" }));
86
+ }
87
+ }
88
+ catch (err) {
89
+ res.writeHead(500, { "Content-Type": "application/json" });
90
+ res.end(JSON.stringify({ error: err.message }));
91
+ }
92
+ }
93
+ // ── HTML ────────────────────────────────────────────────────────────
94
+ function serveHtml(res) {
95
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
96
+ res.end(getDashboardHtml());
97
+ }
98
+ // ── API: List sessions ──────────────────────────────────────────────
99
+ function apiSessions(db, res) {
100
+ const rows = db.prepare(`
101
+ SELECT s.id, s.app_url, s.app_name, s.status, s.created_at, s.completed_at,
102
+ (SELECT COUNT(*) FROM ui_dive_components WHERE session_id = s.id) as component_count,
103
+ (SELECT COUNT(*) FROM ui_dive_bugs WHERE session_id = s.id) as bug_count,
104
+ (SELECT COUNT(*) FROM ui_dive_bugs WHERE session_id = s.id AND status = 'resolved') as bugs_resolved,
105
+ (SELECT COUNT(*) FROM ui_dive_interactions WHERE session_id = s.id) as interaction_count,
106
+ (SELECT COUNT(*) FROM ui_dive_fix_verifications WHERE session_id = s.id) as fix_count,
107
+ (SELECT COUNT(*) FROM ui_dive_code_reviews WHERE session_id = s.id) as review_count
108
+ FROM ui_dive_sessions s
109
+ ORDER BY s.created_at DESC
110
+ LIMIT 50
111
+ `).all();
112
+ json(res, rows);
113
+ }
114
+ // ── API: Latest session redirect ────────────────────────────────────
115
+ function apiLatestSession(db, res) {
116
+ const row = db.prepare(`
117
+ SELECT id FROM ui_dive_sessions ORDER BY created_at DESC LIMIT 1
118
+ `).get();
119
+ if (!row) {
120
+ json(res, { error: "No sessions found" }, 404);
121
+ return;
122
+ }
123
+ // Return full overview for latest
124
+ apiSessionDetail(db, row.id, "overview", res);
125
+ }
126
+ // ── API: Session detail ─────────────────────────────────────────────
127
+ function apiSessionDetail(db, sessionId, sub, res) {
128
+ switch (sub) {
129
+ case "overview":
130
+ return apiOverview(db, sessionId, res);
131
+ case "components":
132
+ return apiComponents(db, sessionId, res);
133
+ case "bugs":
134
+ return apiBugs(db, sessionId, res);
135
+ case "interactions":
136
+ return apiInteractions(db, sessionId, res);
137
+ case "screenshots":
138
+ return apiScreenshots(db, sessionId, res);
139
+ case "code-locations":
140
+ return apiCodeLocations(db, sessionId, res);
141
+ case "fixes":
142
+ return apiFixes(db, sessionId, res);
143
+ case "changelogs":
144
+ return apiChangelogs(db, sessionId, res);
145
+ case "tests":
146
+ return apiTests(db, sessionId, res);
147
+ case "reviews":
148
+ return apiReviews(db, sessionId, res);
149
+ case "design-issues":
150
+ return apiDesignIssues(db, sessionId, res);
151
+ default:
152
+ json(res, { error: `Unknown sub-route: ${sub}` }, 404);
153
+ }
154
+ }
155
+ function apiOverview(db, sid, res) {
156
+ const session = db.prepare("SELECT * FROM ui_dive_sessions WHERE id = ?").get(sid);
157
+ if (!session) {
158
+ json(res, { error: "Session not found" }, 404);
159
+ return;
160
+ }
161
+ const stats = {
162
+ components: db.prepare("SELECT COUNT(*) as c FROM ui_dive_components WHERE session_id = ?").get(sid),
163
+ interactions: db.prepare("SELECT COUNT(*) as c FROM ui_dive_interactions WHERE session_id = ?").get(sid),
164
+ bugs: db.prepare("SELECT COUNT(*) as c FROM ui_dive_bugs WHERE session_id = ?").get(sid),
165
+ bugsOpen: db.prepare("SELECT COUNT(*) as c FROM ui_dive_bugs WHERE session_id = ? AND status = 'open'").get(sid),
166
+ bugsResolved: db.prepare("SELECT COUNT(*) as c FROM ui_dive_bugs WHERE session_id = ? AND status = 'resolved'").get(sid),
167
+ screenshots: db.prepare("SELECT COUNT(*) as c FROM ui_dive_screenshots WHERE session_id = ?").get(sid),
168
+ tests: db.prepare("SELECT COUNT(*) as c FROM ui_dive_interaction_tests WHERE session_id = ?").get(sid),
169
+ designIssues: db.prepare("SELECT COUNT(*) as c FROM ui_dive_design_issues WHERE session_id = ?").get(sid),
170
+ codeLocations: db.prepare("SELECT COUNT(*) as c FROM ui_dive_code_locations WHERE session_id = ?").get(sid),
171
+ fixes: db.prepare("SELECT COUNT(*) as c FROM ui_dive_fix_verifications WHERE session_id = ?").get(sid),
172
+ fixesVerified: db.prepare("SELECT COUNT(*) as c FROM ui_dive_fix_verifications WHERE session_id = ? AND verified = 1").get(sid),
173
+ changelogs: db.prepare("SELECT COUNT(*) as c FROM ui_dive_changelogs WHERE session_id = ?").get(sid),
174
+ generatedTests: db.prepare("SELECT COUNT(*) as c FROM ui_dive_generated_tests WHERE session_id = ?").get(sid),
175
+ codeReviews: db.prepare("SELECT COUNT(*) as c FROM ui_dive_code_reviews WHERE session_id = ?").get(sid),
176
+ };
177
+ 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);
178
+ json(res, {
179
+ session,
180
+ stats: Object.fromEntries(Object.entries(stats).map(([k, v]) => [k, v?.c ?? 0])),
181
+ latestReview,
182
+ });
183
+ }
184
+ function apiComponents(db, sid, res) {
185
+ json(res, db.prepare("SELECT * FROM ui_dive_components WHERE session_id = ? ORDER BY created_at").all(sid));
186
+ }
187
+ function apiBugs(db, sid, res) {
188
+ json(res, db.prepare(`
189
+ SELECT b.*, c.name as component_name
190
+ FROM ui_dive_bugs b
191
+ LEFT JOIN ui_dive_components c ON b.component_id = c.id
192
+ WHERE b.session_id = ?
193
+ ORDER BY
194
+ CASE b.severity WHEN 'critical' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 ELSE 3 END,
195
+ b.created_at
196
+ `).all(sid));
197
+ }
198
+ function apiInteractions(db, sid, res) {
199
+ json(res, db.prepare(`
200
+ SELECT i.*, c.name as component_name
201
+ FROM ui_dive_interactions i
202
+ LEFT JOIN ui_dive_components c ON i.component_id = c.id
203
+ WHERE i.session_id = ?
204
+ ORDER BY i.sequence_num
205
+ `).all(sid));
206
+ }
207
+ function apiScreenshots(db, sid, res) {
208
+ 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));
209
+ }
210
+ /** Serve a screenshot as an actual PNG image */
211
+ function apiScreenshotImage(db, ssId, res) {
212
+ const row = db.prepare("SELECT base64_thumbnail, file_path FROM ui_dive_screenshots WHERE id = ?").get(ssId);
213
+ if (!row) {
214
+ res.writeHead(404, { "Content-Type": "text/plain" });
215
+ res.end("Screenshot not found");
216
+ return;
217
+ }
218
+ // Prefer inline base64, fall back to file on disk
219
+ if (row.base64_thumbnail) {
220
+ const buf = Buffer.from(row.base64_thumbnail, "base64");
221
+ res.writeHead(200, {
222
+ "Content-Type": "image/png",
223
+ "Content-Length": buf.length.toString(),
224
+ "Cache-Control": "public, max-age=86400",
225
+ });
226
+ res.end(buf);
227
+ return;
228
+ }
229
+ if (row.file_path) {
230
+ try {
231
+ const fs = require("node:fs");
232
+ const buf = fs.readFileSync(row.file_path);
233
+ res.writeHead(200, {
234
+ "Content-Type": "image/png",
235
+ "Content-Length": buf.length.toString(),
236
+ "Cache-Control": "public, max-age=86400",
237
+ });
238
+ res.end(buf);
239
+ }
240
+ catch {
241
+ res.writeHead(404, { "Content-Type": "text/plain" });
242
+ res.end("Screenshot file not found on disk");
243
+ }
244
+ return;
245
+ }
246
+ res.writeHead(404, { "Content-Type": "text/plain" });
247
+ res.end("No image data available");
248
+ }
249
+ function apiCodeLocations(db, sid, res) {
250
+ json(res, db.prepare("SELECT * FROM ui_dive_code_locations WHERE session_id = ? ORDER BY created_at").all(sid));
251
+ }
252
+ function apiFixes(db, sid, res) {
253
+ json(res, db.prepare(`
254
+ SELECT f.*, b.title as bug_title, b.severity as bug_severity, b.status as bug_status
255
+ FROM ui_dive_fix_verifications f
256
+ LEFT JOIN ui_dive_bugs b ON f.bug_id = b.id
257
+ WHERE f.session_id = ?
258
+ ORDER BY f.created_at
259
+ `).all(sid));
260
+ }
261
+ function apiChangelogs(db, sid, res) {
262
+ json(res, db.prepare("SELECT * FROM ui_dive_changelogs WHERE session_id = ? ORDER BY created_at DESC").all(sid));
263
+ }
264
+ function apiTests(db, sid, res) {
265
+ json(res, db.prepare("SELECT * FROM ui_dive_generated_tests WHERE session_id = ? ORDER BY created_at").all(sid));
266
+ }
267
+ function apiReviews(db, sid, res) {
268
+ json(res, db.prepare("SELECT * FROM ui_dive_code_reviews WHERE session_id = ? ORDER BY created_at DESC").all(sid));
269
+ }
270
+ function apiDesignIssues(db, sid, res) {
271
+ json(res, db.prepare("SELECT * FROM ui_dive_design_issues WHERE session_id = ? ORDER BY created_at").all(sid));
272
+ }
273
+ // ── Helpers ─────────────────────────────────────────────────────────
274
+ function json(res, data, status = 200) {
275
+ res.writeHead(status, { "Content-Type": "application/json" });
276
+ res.end(JSON.stringify(data));
277
+ }
278
+ //# 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
@@ -544,6 +544,114 @@ CREATE INDEX IF NOT EXISTS idx_dive_test_steps_test ON ui_dive_test_steps(test_i
544
544
  CREATE INDEX IF NOT EXISTS idx_dive_design_issues_session ON ui_dive_design_issues(session_id);
545
545
  CREATE INDEX IF NOT EXISTS idx_dive_backend_links_component ON ui_dive_backend_links(component_id);
546
546
  CREATE INDEX IF NOT EXISTS idx_dive_changelogs_session ON ui_dive_changelogs(session_id);
547
+
548
+ -- ═══════════════════════════════════════════
549
+ -- UI/UX FULL DIVE v3 — Flywheel: locate code,
550
+ -- fix-verify, re-explore, generate tests,
551
+ -- code review.
552
+ -- ═══════════════════════════════════════════
553
+
554
+ CREATE TABLE IF NOT EXISTS ui_dive_code_locations (
555
+ id TEXT PRIMARY KEY,
556
+ session_id TEXT NOT NULL REFERENCES ui_dive_sessions(id) ON DELETE CASCADE,
557
+ bug_id TEXT,
558
+ component_id TEXT,
559
+ design_issue_id TEXT,
560
+ file_path TEXT NOT NULL,
561
+ line_start INTEGER,
562
+ line_end INTEGER,
563
+ code_snippet TEXT,
564
+ search_query TEXT,
565
+ confidence TEXT NOT NULL DEFAULT 'high',
566
+ notes TEXT,
567
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
568
+ );
569
+
570
+ CREATE TABLE IF NOT EXISTS ui_dive_fix_verifications (
571
+ id TEXT PRIMARY KEY,
572
+ session_id TEXT NOT NULL REFERENCES ui_dive_sessions(id) ON DELETE CASCADE,
573
+ bug_id TEXT NOT NULL,
574
+ route TEXT,
575
+ before_screenshot_id TEXT,
576
+ after_screenshot_id TEXT,
577
+ fix_description TEXT NOT NULL,
578
+ files_changed TEXT,
579
+ git_commit TEXT,
580
+ verified INTEGER NOT NULL DEFAULT 0,
581
+ verification_notes TEXT,
582
+ changelog_id TEXT,
583
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
584
+ );
585
+
586
+ CREATE TABLE IF NOT EXISTS ui_dive_generated_tests (
587
+ id TEXT PRIMARY KEY,
588
+ session_id TEXT NOT NULL REFERENCES ui_dive_sessions(id) ON DELETE CASCADE,
589
+ bug_id TEXT,
590
+ component_id TEXT,
591
+ test_id TEXT,
592
+ test_framework TEXT NOT NULL DEFAULT 'playwright',
593
+ test_code TEXT NOT NULL,
594
+ test_file_path TEXT,
595
+ description TEXT,
596
+ covers TEXT,
597
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
598
+ );
599
+
600
+ CREATE TABLE IF NOT EXISTS ui_dive_code_reviews (
601
+ id TEXT PRIMARY KEY,
602
+ session_id TEXT NOT NULL REFERENCES ui_dive_sessions(id) ON DELETE CASCADE,
603
+ review_type TEXT NOT NULL DEFAULT 'dive_findings',
604
+ severity_counts TEXT,
605
+ findings TEXT NOT NULL,
606
+ summary TEXT,
607
+ recommendations TEXT,
608
+ score INTEGER,
609
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
610
+ );
611
+
612
+ CREATE INDEX IF NOT EXISTS idx_dive_code_locations_session ON ui_dive_code_locations(session_id);
613
+ CREATE INDEX IF NOT EXISTS idx_dive_code_locations_bug ON ui_dive_code_locations(bug_id);
614
+ CREATE INDEX IF NOT EXISTS idx_dive_fix_verifications_bug ON ui_dive_fix_verifications(bug_id);
615
+ CREATE INDEX IF NOT EXISTS idx_dive_generated_tests_session ON ui_dive_generated_tests(session_id);
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);
547
655
  `;
548
656
  export function getDb() {
549
657
  if (_db)
package/dist/db.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,IAAI,GAAG,GAA6B,IAAI,CAAC;AAEzC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6hBlB,CAAC;AAEF,MAAM,UAAU,KAAK;IACnB,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC;IACpB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;IAC1C,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,GAAG,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC;IAC9C,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAErB,gFAAgF;IAChF,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAC,GAAG,EAAS,CAAC;QAChF,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC,GAAG,EAAS,CAAC;QACvF,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,GAAG,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC,GAAG,EAAS,CAAC;QACrE,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC,GAAG,EAAS,CAAC;QAC5E,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,GAAG,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,sEAAsE,CAAC,CAAC;IAElF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC,GAAG,EAAS,CAAC;IACjF,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,MAAc;IAClC,OAAO,GAAG,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AAC9E,CAAC"}
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -20,6 +20,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
20
20
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
21
21
  import { ListToolsRequestSchema, CallToolRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
22
22
  import { getDb, genId } from "./db.js";
23
+ import { startDashboardServer } from "./dashboard/server.js";
23
24
  import { getAnalyticsDb, closeAnalyticsDb, clearOldRecords } from "./analytics/index.js";
24
25
  import { AnalyticsTracker } from "./analytics/toolTracker.js";
25
26
  import { generateSmartPreset, formatPresetRecommendation, listPresets } from "./analytics/index.js";
@@ -42,14 +43,16 @@ const exportStats = cliArgs.includes("--export-stats");
42
43
  const resetStats = cliArgs.includes("--reset-stats");
43
44
  const listPresetsFlag = cliArgs.includes("--list-presets");
44
45
  export { TOOLSET_MAP };
46
+ // Default: 50 tools (core AI Flywheel + recon + security + boilerplate)
47
+ // skill_update available via load_toolset("skill_update") for rule file freshness tracking
45
48
  const DEFAULT_TOOLSETS = ["verification", "eval", "quality_gate", "learning", "flywheel", "recon", "security", "boilerplate"];
46
49
  const PRESETS = {
47
50
  default: DEFAULT_TOOLSETS,
48
51
  // Themed presets — bridge between default (50 tools) and full (175 tools)
49
- web_dev: [...DEFAULT_TOOLSETS, "ui_capture", "vision", "web", "seo", "git_workflow", "architect", "ui_ux_dive", "ui_ux_dive_v2", "mcp_bridge"],
52
+ web_dev: [...DEFAULT_TOOLSETS, "ui_capture", "vision", "web", "seo", "git_workflow", "architect", "ui_ux_dive", "ui_ux_dive_v2", "mcp_bridge", "pr_report"],
50
53
  research: [...DEFAULT_TOOLSETS, "web", "llm", "rss", "email", "docs"],
51
54
  data: [...DEFAULT_TOOLSETS, "local_file", "llm", "web"],
52
- devops: [...DEFAULT_TOOLSETS, "git_workflow", "session_memory", "benchmark", "pattern"],
55
+ devops: [...DEFAULT_TOOLSETS, "git_workflow", "session_memory", "benchmark", "pattern", "pr_report"],
53
56
  mobile: [...DEFAULT_TOOLSETS, "ui_capture", "vision", "flicker_detection", "ui_ux_dive", "ui_ux_dive_v2", "mcp_bridge"],
54
57
  academic: [...DEFAULT_TOOLSETS, "research_writing", "llm", "web", "local_file"],
55
58
  multi_agent: [...DEFAULT_TOOLSETS, "parallel", "self_eval", "session_memory", "pattern", "toon"],
@@ -58,10 +61,10 @@ const PRESETS = {
58
61
  };
59
62
  const PRESET_DESCRIPTIONS = {
60
63
  default: "Core AI Flywheel — verification, eval, quality gates, learning, recon",
61
- web_dev: "Web projects — adds visual QA, SEO audit, git workflow, code architecture",
64
+ web_dev: "Web projects — adds visual QA, SEO audit, git workflow, PR reports, code architecture",
62
65
  research: "Research workflows — adds web search, LLM calls, RSS feeds, email, docs",
63
66
  data: "Data analysis — adds CSV/XLSX/PDF/JSON parsing, LLM extraction, web fetch",
64
- devops: "CI/CD & ops — adds git compliance, session memory, benchmarks, pattern mining",
67
+ devops: "CI/CD & ops — adds git compliance, session memory, benchmarks, pattern mining, PR reports",
65
68
  mobile: "Mobile apps — adds screenshot capture, vision analysis, flicker detection",
66
69
  academic: "Academic papers — adds polish, review, translate, logic check, data analysis",
67
70
  multi_agent: "Multi-agent teams — adds task locking, messaging, roles, oracle testing",
@@ -99,12 +102,12 @@ function parseToolsets() {
99
102
  }),
100
103
  "",
101
104
  "Examples:",
102
- " npx nodebench-mcp # Default (50 tools) - core AI Flywheel",
105
+ " npx nodebench-mcp # Default (54 tools) - core AI Flywheel",
103
106
  " npx nodebench-mcp --preset web_dev # Web development (+ vision, SEO, git)",
104
107
  " npx nodebench-mcp --preset research # Research workflows (+ web, LLM, RSS, email)",
105
108
  " npx nodebench-mcp --preset data # Data analysis (+ local file parsing, LLM)",
106
109
  " npx nodebench-mcp --preset academic # Academic writing (+ paper tools, LLM)",
107
- " npx nodebench-mcp --preset full # All 175 tools",
110
+ " npx nodebench-mcp --preset full # All 218 tools",
108
111
  " npx nodebench-mcp --smart-preset # Get AI-powered preset recommendation",
109
112
  " npx nodebench-mcp --stats # Show usage statistics",
110
113
  " npx nodebench-mcp --toolsets verification,eval,recon",
@@ -682,7 +685,7 @@ if (useEmbedding) {
682
685
  // Tool nodes: individual tools with full metadata text
683
686
  const toolCorpus = ALL_REGISTRY_ENTRIES.map((entry) => ({
684
687
  name: entry.name,
685
- text: `${entry.name} ${entry.tags.join(" ")} ${entry.category} ${entry.phase} ${descMap.get(entry.name) ?? ""}`,
688
+ text: `${entry.name} ${entry.tags.join(" ")} ${entry.category} ${entry.phase} ${(entry.quickRef.relatedTools ?? []).join(" ")} ${descMap.get(entry.name) ?? ""}`,
686
689
  nodeType: "tool",
687
690
  }));
688
691
  // Domain nodes: aggregate category descriptions for upward traversal
@@ -1308,7 +1311,7 @@ Use NodeBench tools when you need to:
1308
1311
  - Audit SEO, analyze Figma flows, detect Android flicker
1309
1312
  - Call LLMs (GPT, Claude, Gemini) for analysis and extraction
1310
1313
  Start with discover_tools("<your task>") to find the right tool.`;
1311
- const server = new Server({ name: "nodebench-mcp-methodology", version: "2.21.1" }, {
1314
+ const server = new Server({ name: "nodebench-mcp-methodology", version: "2.24.0" }, {
1312
1315
  capabilities: { tools: { listChanged: true }, prompts: {} },
1313
1316
  instructions: SERVER_INSTRUCTIONS,
1314
1317
  });
@@ -1486,8 +1489,15 @@ process.on('exit', () => {
1486
1489
  // Connect via stdio
1487
1490
  const transport = new StdioServerTransport();
1488
1491
  await server.connect(transport);
1492
+ // Start local dashboard server (non-blocking, best-effort)
1493
+ let dashboardPort = 0;
1494
+ try {
1495
+ dashboardPort = await startDashboardServer(getDb(), 6274);
1496
+ }
1497
+ catch { /* dashboard is optional — don't block MCP */ }
1489
1498
  const toolsetInfo = cliArgs.includes("--toolsets") || cliArgs.includes("--exclude") || cliArgs.includes("--preset")
1490
1499
  ? ` [gated: ${domainTools.length} domain + 2 meta]`
1491
1500
  : "";
1492
- console.error(`nodebench-mcp ready (${allTools.length} tools, ${PROMPTS.length} prompts${toolsetInfo}, SQLite at ~/.nodebench/)`);
1501
+ const dashInfo = dashboardPort ? ` dashboard at http://127.0.0.1:${dashboardPort}` : "";
1502
+ console.error(`nodebench-mcp ready (${allTools.length} tools, ${PROMPTS.length} prompts${toolsetInfo}, SQLite at ~/.nodebench/${dashInfo})`);
1493
1503
  //# sourceMappingURL=index.js.map