nodebench-mcp 2.17.0 → 2.18.1

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 (57) hide show
  1. package/LICENSE +21 -0
  2. package/NODEBENCH_AGENTS.md +2 -2
  3. package/README.md +516 -82
  4. package/dist/__tests__/analytics.test.d.ts +11 -0
  5. package/dist/__tests__/analytics.test.js +546 -0
  6. package/dist/__tests__/analytics.test.js.map +1 -0
  7. package/dist/__tests__/dynamicLoading.test.d.ts +1 -0
  8. package/dist/__tests__/dynamicLoading.test.js +278 -0
  9. package/dist/__tests__/dynamicLoading.test.js.map +1 -0
  10. package/dist/__tests__/evalHarness.test.js +1 -1
  11. package/dist/__tests__/evalHarness.test.js.map +1 -1
  12. package/dist/__tests__/helpers/answerMatch.js +22 -22
  13. package/dist/__tests__/presetRealWorldBench.test.js +9 -0
  14. package/dist/__tests__/presetRealWorldBench.test.js.map +1 -1
  15. package/dist/__tests__/tools.test.js +1 -1
  16. package/dist/__tests__/toolsetGatingEval.test.js +9 -1
  17. package/dist/__tests__/toolsetGatingEval.test.js.map +1 -1
  18. package/dist/analytics/index.d.ts +10 -0
  19. package/dist/analytics/index.js +11 -0
  20. package/dist/analytics/index.js.map +1 -0
  21. package/dist/analytics/projectDetector.d.ts +19 -0
  22. package/dist/analytics/projectDetector.js +259 -0
  23. package/dist/analytics/projectDetector.js.map +1 -0
  24. package/dist/analytics/schema.d.ts +57 -0
  25. package/dist/analytics/schema.js +157 -0
  26. package/dist/analytics/schema.js.map +1 -0
  27. package/dist/analytics/smartPreset.d.ts +63 -0
  28. package/dist/analytics/smartPreset.js +300 -0
  29. package/dist/analytics/smartPreset.js.map +1 -0
  30. package/dist/analytics/toolTracker.d.ts +59 -0
  31. package/dist/analytics/toolTracker.js +163 -0
  32. package/dist/analytics/toolTracker.js.map +1 -0
  33. package/dist/analytics/usageStats.d.ts +64 -0
  34. package/dist/analytics/usageStats.js +252 -0
  35. package/dist/analytics/usageStats.js.map +1 -0
  36. package/dist/db.js +359 -321
  37. package/dist/db.js.map +1 -1
  38. package/dist/index.d.ts +2 -1
  39. package/dist/index.js +652 -89
  40. package/dist/index.js.map +1 -1
  41. package/dist/tools/architectTools.js +13 -13
  42. package/dist/tools/critterTools.js +14 -14
  43. package/dist/tools/parallelAgentTools.js +176 -176
  44. package/dist/tools/patternTools.js +11 -11
  45. package/dist/tools/progressiveDiscoveryTools.d.ts +5 -1
  46. package/dist/tools/progressiveDiscoveryTools.js +111 -19
  47. package/dist/tools/progressiveDiscoveryTools.js.map +1 -1
  48. package/dist/tools/researchWritingTools.js +42 -42
  49. package/dist/tools/rssTools.js +396 -396
  50. package/dist/tools/toolRegistry.d.ts +17 -0
  51. package/dist/tools/toolRegistry.js +65 -17
  52. package/dist/tools/toolRegistry.js.map +1 -1
  53. package/dist/tools/voiceBridgeTools.js +498 -498
  54. package/dist/toolsetRegistry.d.ts +10 -0
  55. package/dist/toolsetRegistry.js +84 -0
  56. package/dist/toolsetRegistry.js.map +1 -0
  57. package/package.json +4 -4
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Smart Preset Generator — Weighted Multi-Signal Scoring Model
3
+ *
4
+ * Recommends preset (default vs full) using 5 weighted signals derived from
5
+ * actual project context and historical usage data:
6
+ *
7
+ * 1. Project Type Affinity — static: how many specialized toolsets fit this project type
8
+ * 2. Usage Breadth — empirical: how many distinct toolsets were actually used
9
+ * 3. Specialized Usage Depth — empirical: calls to non-default toolsets (weighted by recency)
10
+ * 4. Failure Penalty — empirical: frequently failing tools penalize confidence
11
+ * 5. History Weight — meta: more history = higher confidence in the recommendation
12
+ *
13
+ * The final score is a weighted sum normalized to [0, 1].
14
+ * score > 0.55 → recommend full
15
+ * score <= 0.55 → recommend default
16
+ * confidence = f(history_weight, failure_penalty)
17
+ */
18
+ import { detectProject } from './projectDetector.js';
19
+ import { getToolUsageStats, getToolsetUsageStats, getFrequentlyFailingTools, } from './usageStats.js';
20
+ // ── Constants ───────────────────────────────────────────────────────────
21
+ const DEFAULT_TOOLSETS = ['verification', 'eval', 'quality_gate', 'learning', 'flywheel', 'recon', 'security', 'boilerplate'];
22
+ const DEFAULT_TOOLSET_SET = new Set(DEFAULT_TOOLSETS);
23
+ const SCORE_THRESHOLD = 0.55; // above this → recommend full
24
+ // Signal weights (sum to 1.0)
25
+ const W_PROJECT_TYPE = 0.25;
26
+ const W_USAGE_BREADTH = 0.30;
27
+ const W_SPECIALIZED_DEPTH = 0.30;
28
+ const W_HISTORY = 0.15;
29
+ // Project type → extra toolsets beyond default
30
+ const PROJECT_TYPE_EXTRAS = {
31
+ web_frontend: ['ui_capture', 'vision'],
32
+ web_backend: ['web', 'github'],
33
+ fullstack: ['ui_capture', 'vision', 'web', 'github', 'llm'],
34
+ mobile: [],
35
+ desktop: [],
36
+ cli: [],
37
+ library: ['docs', 'github'],
38
+ data_science: ['local_file', 'llm'],
39
+ devops: ['github'],
40
+ unknown: [],
41
+ };
42
+ // All toolsets considered "specialized" (not in default)
43
+ const SPECIALIZED_TOOLSETS = [
44
+ 'ui_capture', 'vision', 'web', 'github', 'docs', 'local_file',
45
+ 'self_eval', 'parallel', 'llm', 'platform', 'research_writing',
46
+ 'bootstrap', 'flicker_detection', 'figma_flow', 'benchmark',
47
+ 'gaia_solvers', 'session_memory', 'toon', 'pattern', 'git_workflow',
48
+ 'seo', 'voice_bridge', 'critter', 'email', 'rss', 'architect',
49
+ ];
50
+ // ── Helpers ─────────────────────────────────────────────────────────────
51
+ function calculateToolsetCount(toolsets, toolsetMap) {
52
+ let count = 0;
53
+ for (const ts of toolsets)
54
+ count += toolsetMap[ts]?.length || 0;
55
+ return count + 6; // +6 meta/discovery
56
+ }
57
+ function createPresets(toolsetMap) {
58
+ return {
59
+ default: {
60
+ name: 'default',
61
+ toolsets: DEFAULT_TOOLSETS,
62
+ toolCount: calculateToolsetCount(DEFAULT_TOOLSETS, toolsetMap),
63
+ },
64
+ full: {
65
+ name: 'full',
66
+ toolsets: Object.keys(toolsetMap),
67
+ toolCount: Object.values(toolsetMap).reduce((s, t) => s + t.length, 0) + 6,
68
+ },
69
+ };
70
+ }
71
+ // ── Signal computation ──────────────────────────────────────────────────
72
+ function computeProjectTypeAffinity(projectType) {
73
+ const extras = PROJECT_TYPE_EXTRAS[projectType] || [];
74
+ // 0 extras → 0.0 (default is fine), 5+ extras → 1.0 (needs full)
75
+ return Math.min(extras.length / 5, 1.0);
76
+ }
77
+ function computeUsageBreadth(toolsetStats, totalAvailableToolsets) {
78
+ if (totalAvailableToolsets === 0)
79
+ return 0;
80
+ const usedCount = toolsetStats.filter(ts => ts.totalCalls > 0).length;
81
+ // Fraction of available toolsets that were actually used
82
+ return Math.min(usedCount / totalAvailableToolsets, 1.0);
83
+ }
84
+ function computeSpecializedDepth(toolsetStats, totalCalls) {
85
+ if (totalCalls === 0)
86
+ return 0;
87
+ // What fraction of total calls went to non-default toolsets?
88
+ const specializedCalls = toolsetStats
89
+ .filter(ts => !DEFAULT_TOOLSET_SET.has(ts.toolset))
90
+ .reduce((sum, ts) => sum + ts.totalCalls, 0);
91
+ return Math.min(specializedCalls / totalCalls, 1.0);
92
+ }
93
+ function computeFailurePenalty(failingTools, totalCalls) {
94
+ if (totalCalls === 0 || failingTools.length === 0)
95
+ return 0;
96
+ const totalFailures = failingTools.reduce((s, t) => s + t.failureCount, 0);
97
+ // Cap at 0.5 — failures reduce confidence but don't dominate
98
+ return Math.min(totalFailures / totalCalls, 0.5);
99
+ }
100
+ function computeHistoryWeight(totalCalls) {
101
+ // No history → 0, 10 calls → 0.5, 100+ calls → 1.0 (logarithmic)
102
+ if (totalCalls === 0)
103
+ return 0;
104
+ return Math.min(Math.log10(totalCalls + 1) / 2, 1.0);
105
+ }
106
+ // ── Core: generate recommendation ───────────────────────────────────────
107
+ export function generateSmartPreset(db, toolsetMap, projectPath = process.cwd()) {
108
+ const projectContext = detectProject(projectPath);
109
+ const presets = createPresets(toolsetMap);
110
+ const availableToolsets = Object.keys(toolsetMap);
111
+ // Gather empirical data
112
+ const toolsetStats = getToolsetUsageStats(db, projectPath, 30);
113
+ const toolStats = getToolUsageStats(db, projectPath, 30);
114
+ const failingToolsRaw = getFrequentlyFailingTools(db, projectPath, 30, 2);
115
+ const totalCalls = toolStats.reduce((s, t) => s + t.callCount, 0);
116
+ // Compute 5 signals
117
+ const projectTypeAffinity = computeProjectTypeAffinity(projectContext.projectType);
118
+ const usageBreadth = computeUsageBreadth(toolsetStats, availableToolsets.length);
119
+ const specializedDepth = computeSpecializedDepth(toolsetStats, totalCalls);
120
+ const failurePenalty = computeFailurePenalty(failingToolsRaw, totalCalls);
121
+ const historyWeight = computeHistoryWeight(totalCalls);
122
+ const signals = {
123
+ projectTypeAffinity,
124
+ usageBreadth,
125
+ specializedDepth,
126
+ failurePenalty,
127
+ historyWeight,
128
+ };
129
+ // Weighted score: blend static (project type) with empirical signals
130
+ // When history is low, project type dominates. When history is rich, usage dominates.
131
+ const empiricalBlend = historyWeight; // 0 = no history, 1 = trust history fully
132
+ const staticScore = projectTypeAffinity;
133
+ const empiricalScore = (usageBreadth * W_USAGE_BREADTH + specializedDepth * W_SPECIALIZED_DEPTH + historyWeight * W_HISTORY)
134
+ / (W_USAGE_BREADTH + W_SPECIALIZED_DEPTH + W_HISTORY);
135
+ // Normalize: simple weighted average where empirical grows with history
136
+ const score = Math.min(staticScore * (1 - empiricalBlend) + empiricalScore * empiricalBlend, 1.0);
137
+ // Decision
138
+ const preset = score > SCORE_THRESHOLD ? 'full' : 'default';
139
+ // Confidence: higher with more history, penalized by failures
140
+ const baseConfidence = historyWeight > 0
141
+ ? 0.6 + historyWeight * 0.35 // 0.6 → 0.95 as history grows
142
+ : 0.5 + projectTypeAffinity * 0.3; // 0.5 → 0.8 for static-only
143
+ const confidence = Math.max(0.3, baseConfidence - failurePenalty * 0.2);
144
+ // Build reason
145
+ const reason = buildReason(preset, signals, projectContext, totalCalls);
146
+ // Build suggested toolsets: default + project-type extras + actually-used specialized
147
+ const extras = PROJECT_TYPE_EXTRAS[projectContext.projectType] || [];
148
+ const usedSpecialized = toolsetStats
149
+ .filter(ts => !DEFAULT_TOOLSET_SET.has(ts.toolset) && ts.totalCalls > 0)
150
+ .map(ts => ts.toolset);
151
+ const suggestedToolsets = [...new Set([...DEFAULT_TOOLSETS, ...extras, ...usedSpecialized])];
152
+ const optionalToolsets = SPECIALIZED_TOOLSETS.filter(ts => !suggestedToolsets.includes(ts));
153
+ // Usage insights
154
+ const mostUsedToolsets = toolsetStats
155
+ .filter(ts => ts.totalCalls > 0)
156
+ .sort((a, b) => b.totalCalls - a.totalCalls)
157
+ .map(ts => ts.toolset)
158
+ .slice(0, 5);
159
+ const usedSet = new Set(toolsetStats.filter(ts => ts.totalCalls > 0).map(ts => ts.toolset));
160
+ const unusedToolsets = availableToolsets.filter(ts => !usedSet.has(ts));
161
+ return {
162
+ preset,
163
+ reason,
164
+ confidence: Math.round(confidence * 100) / 100,
165
+ score: Math.round(score * 1000) / 1000,
166
+ suggestedToolsets,
167
+ optionalToolsets,
168
+ projectContext,
169
+ usageInsights: {
170
+ mostUsedToolsets,
171
+ unusedToolsets,
172
+ frequentlyFailingTools: failingToolsRaw.map(t => ({
173
+ name: t.toolName,
174
+ failures: t.failureCount,
175
+ lastError: t.lastError,
176
+ })),
177
+ totalCallsLast30d: totalCalls,
178
+ uniqueToolsetsUsed: toolsetStats.filter(ts => ts.totalCalls > 0).length,
179
+ },
180
+ signals,
181
+ };
182
+ }
183
+ function buildReason(preset, signals, ctx, totalCalls) {
184
+ const parts = [];
185
+ if (totalCalls === 0) {
186
+ parts.push(`No usage history yet.`);
187
+ if (preset === 'full') {
188
+ parts.push(`Project type (${ctx.projectType}) suggests specialized toolsets would help.`);
189
+ }
190
+ else {
191
+ parts.push(`Project type (${ctx.projectType}) aligns with default preset.`);
192
+ }
193
+ parts.push(`As you use more tools, this recommendation will improve.`);
194
+ }
195
+ else {
196
+ parts.push(`Based on ${totalCalls} tool calls across ${signals.historyWeight > 0.5 ? 'rich' : 'limited'} history.`);
197
+ if (signals.specializedDepth > 0.3) {
198
+ parts.push(`${(signals.specializedDepth * 100).toFixed(0)}% of calls use specialized (non-default) toolsets.`);
199
+ }
200
+ if (signals.usageBreadth > 0.4) {
201
+ parts.push(`Broad toolset usage detected across ${(signals.usageBreadth * 100).toFixed(0)}% of available toolsets.`);
202
+ }
203
+ if (preset === 'full') {
204
+ parts.push(`Full preset recommended for comprehensive coverage.`);
205
+ }
206
+ else {
207
+ parts.push(`Default preset covers your current usage patterns.`);
208
+ }
209
+ }
210
+ if (signals.failurePenalty > 0.1) {
211
+ parts.push(`Note: ${(signals.failurePenalty * 100).toFixed(0)}% failure rate detected - check failing tools below.`);
212
+ }
213
+ return parts.join(' ');
214
+ }
215
+ // ── Preset listing ──────────────────────────────────────────────────────
216
+ export function getPresetConfig(preset, toolsetMap) {
217
+ return createPresets(toolsetMap)[preset];
218
+ }
219
+ export function listPresets(toolsetMap) {
220
+ const presets = createPresets(toolsetMap);
221
+ const THEMED_PRESETS = [
222
+ { name: 'web_dev', extras: ['ui_capture', 'vision', 'web', 'seo', 'git_workflow', 'architect'], description: 'Web projects — adds visual QA, SEO audit, git workflow, code architecture' },
223
+ { name: 'research', extras: ['web', 'llm', 'rss', 'email', 'docs'], description: 'Research workflows — adds web search, LLM calls, RSS feeds, email, docs' },
224
+ { name: 'data', extras: ['local_file', 'llm', 'web'], description: 'Data analysis — adds CSV/XLSX/PDF/JSON parsing, LLM extraction, web fetch' },
225
+ { name: 'devops', extras: ['git_workflow', 'session_memory', 'benchmark', 'pattern'], description: 'CI/CD & ops — adds git compliance, session memory, benchmarks, pattern mining' },
226
+ { name: 'mobile', extras: ['ui_capture', 'vision', 'flicker_detection'], description: 'Mobile apps — adds screenshot capture, vision analysis, flicker detection' },
227
+ { name: 'academic', extras: ['research_writing', 'llm', 'web', 'local_file'], description: 'Academic papers — adds polish, review, translate, logic check, data analysis' },
228
+ { name: 'multi_agent', extras: ['parallel', 'self_eval', 'session_memory', 'pattern', 'toon'], description: 'Multi-agent teams — adds task locking, messaging, roles, oracle testing' },
229
+ { name: 'content', extras: ['llm', 'critter', 'email', 'rss', 'platform', 'architect'], description: 'Content & publishing — adds LLM, accountability, email, RSS, platform queue' },
230
+ ];
231
+ const result = [
232
+ {
233
+ name: 'default',
234
+ toolsets: presets.default.toolsets,
235
+ toolCount: presets.default.toolCount,
236
+ description: 'Core AI Flywheel methodology — verification, eval, quality gates, learning, recon, security, boilerplate',
237
+ },
238
+ ];
239
+ for (const themed of THEMED_PRESETS) {
240
+ const toolsets = [...DEFAULT_TOOLSETS, ...themed.extras];
241
+ result.push({
242
+ name: themed.name,
243
+ toolsets,
244
+ toolCount: calculateToolsetCount(toolsets, toolsetMap),
245
+ description: themed.description,
246
+ });
247
+ }
248
+ result.push({
249
+ name: 'full',
250
+ toolsets: presets.full.toolsets,
251
+ toolCount: presets.full.toolCount,
252
+ description: `All ${presets.full.toolCount} tools across ${Object.keys(toolsetMap).length} toolsets — complete coverage`,
253
+ });
254
+ return result;
255
+ }
256
+ // ── Formatted output ────────────────────────────────────────────────────
257
+ export function formatPresetRecommendation(recommendation, toolsetMap) {
258
+ const lines = [];
259
+ const { signals: s, usageInsights: u, projectContext: p } = recommendation;
260
+ lines.push(`\n=== Smart Preset Recommendation ===\n`);
261
+ lines.push(` Preset: ${recommendation.preset.toUpperCase()}`);
262
+ lines.push(` Confidence: ${(recommendation.confidence * 100).toFixed(0)}%`);
263
+ lines.push(` Score: ${recommendation.score.toFixed(3)} (threshold: ${SCORE_THRESHOLD})\n`);
264
+ lines.push(` ${recommendation.reason}`);
265
+ // Signal breakdown
266
+ lines.push(`\n--- Signal Breakdown ---`);
267
+ lines.push(` Project Type Affinity: ${(s.projectTypeAffinity * 100).toFixed(0)}% (${p.projectType}/${p.language}${p.framework ? '/' + p.framework : ''})`);
268
+ lines.push(` Usage Breadth: ${(s.usageBreadth * 100).toFixed(0)}% (${u.uniqueToolsetsUsed}/${Object.keys(toolsetMap).length} toolsets used)`);
269
+ lines.push(` Specialized Depth: ${(s.specializedDepth * 100).toFixed(0)}% (non-default call share)`);
270
+ lines.push(` History Weight: ${(s.historyWeight * 100).toFixed(0)}% (${u.totalCallsLast30d} calls in 30d)`);
271
+ lines.push(` Failure Penalty: ${(s.failurePenalty * 100).toFixed(0)}%`);
272
+ // Project context
273
+ lines.push(`\n--- Project ---`);
274
+ lines.push(` Type: ${p.projectType} | Language: ${p.language}${p.framework ? ' | Framework: ' + p.framework : ''}`);
275
+ lines.push(` Tests: ${p.hasTests ? 'Yes' : 'No'} | CI: ${p.hasCI ? 'Yes' : 'No'} | Files: ${p.fileCount}`);
276
+ // Suggested toolsets
277
+ lines.push(`\n--- Suggested Toolsets (${calculateToolsetCount(recommendation.suggestedToolsets, toolsetMap)} tools) ---`);
278
+ lines.push(` ${recommendation.suggestedToolsets.join(', ')}`);
279
+ // Usage insights
280
+ if (u.mostUsedToolsets.length > 0) {
281
+ lines.push(`\n--- Most Used (30d) ---`);
282
+ lines.push(` ${u.mostUsedToolsets.join(', ')}`);
283
+ }
284
+ // Failing tools warnings
285
+ if (u.frequentlyFailingTools.length > 0) {
286
+ lines.push(`\n--- Failing Tools (action required) ---`);
287
+ for (const t of u.frequentlyFailingTools) {
288
+ lines.push(` ! ${t.name}: ${t.failures} failures${t.lastError ? ' - ' + t.lastError.slice(0, 80) : ''}`);
289
+ }
290
+ }
291
+ // How to apply
292
+ lines.push(`\n--- Apply ---`);
293
+ lines.push(` npx nodebench-mcp --preset ${recommendation.preset}`);
294
+ if (recommendation.suggestedToolsets.length > DEFAULT_TOOLSETS.length) {
295
+ lines.push(` npx nodebench-mcp --toolsets ${recommendation.suggestedToolsets.join(',')}`);
296
+ }
297
+ lines.push('');
298
+ return lines.join('\n');
299
+ }
300
+ //# sourceMappingURL=smartPreset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smartPreset.js","sourceRoot":"","sources":["../../src/analytics/smartPreset.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * AnalyticsTracker — Singleton analytics engine for NodeBench MCP
3
+ *
4
+ * Owns the full lifecycle: DB open, tool-call recording, project context,
5
+ * session stats, retention cleanup, and graceful shutdown.
6
+ * index.ts calls tracker.record() instead of inline SQL.
7
+ */
8
+ import Database from 'better-sqlite3';
9
+ export interface TrackerConfig {
10
+ projectPath: string;
11
+ preset: string;
12
+ toolCount: number;
13
+ /** tool name → toolset name lookup */
14
+ toolToToolset: Map<string, string>;
15
+ /** Tools to skip tracking (avoid recursion) */
16
+ skipTools?: Set<string>;
17
+ /** Days to keep analytics data (default 90) */
18
+ retentionDays?: number;
19
+ }
20
+ export interface SessionStats {
21
+ totalCalls: number;
22
+ successCount: number;
23
+ failureCount: number;
24
+ totalDuration: number;
25
+ uniqueTools: number;
26
+ topTools: Array<{
27
+ name: string;
28
+ count: number;
29
+ }>;
30
+ errorRate: number;
31
+ }
32
+ export declare class AnalyticsTracker {
33
+ private db;
34
+ private projectPath;
35
+ private preset;
36
+ private toolToToolset;
37
+ private skipTools;
38
+ private sessionStart;
39
+ private _callCount;
40
+ private _insertStmt;
41
+ private constructor();
42
+ /** Get or create the singleton tracker */
43
+ static init(config: TrackerConfig): AnalyticsTracker;
44
+ /** Get existing instance (returns null if not initialized) */
45
+ static get(): AnalyticsTracker | null;
46
+ /** Underlying DB handle (for stats queries that need it) */
47
+ getDb(): Database.Database;
48
+ /**
49
+ * Record a tool call outcome. Called from the CallToolRequestSchema handler.
50
+ * Returns silently on any error — analytics must never break tool dispatch.
51
+ */
52
+ record(toolName: string, startMs: number, success: boolean, errorMsg: string | null, args?: Record<string, unknown>): void;
53
+ getSessionStats(): SessionStats;
54
+ get callCount(): number;
55
+ close(): void;
56
+ private _initProjectContext;
57
+ }
58
+ /** @deprecated Use AnalyticsTracker.init() instead */
59
+ export declare function initializeProjectContext(db: Database.Database, projectPath: string | undefined, preset: string, toolCount?: number): void;
@@ -0,0 +1,163 @@
1
+ /**
2
+ * AnalyticsTracker — Singleton analytics engine for NodeBench MCP
3
+ *
4
+ * Owns the full lifecycle: DB open, tool-call recording, project context,
5
+ * session stats, retention cleanup, and graceful shutdown.
6
+ * index.ts calls tracker.record() instead of inline SQL.
7
+ */
8
+ import { getAnalyticsDb, closeAnalyticsDb, updateProjectContext, recordPresetSelection, clearOldRecords, } from './schema.js';
9
+ import { detectProject } from './projectDetector.js';
10
+ // ── Singleton ───────────────────────────────────────────────────────────
11
+ let _instance = null;
12
+ export class AnalyticsTracker {
13
+ db;
14
+ projectPath;
15
+ preset;
16
+ toolToToolset;
17
+ skipTools;
18
+ sessionStart;
19
+ _callCount = 0;
20
+ _insertStmt = null;
21
+ constructor(config) {
22
+ this.db = getAnalyticsDb();
23
+ this.projectPath = config.projectPath;
24
+ this.preset = config.preset;
25
+ this.toolToToolset = config.toolToToolset;
26
+ this.skipTools = config.skipTools ?? new Set();
27
+ this.sessionStart = Date.now();
28
+ // Run retention cleanup once on startup (non-blocking, best-effort)
29
+ const retentionDays = config.retentionDays ?? 90;
30
+ try {
31
+ clearOldRecords(this.db, retentionDays);
32
+ }
33
+ catch { /* ignore */ }
34
+ // Register project context
35
+ this._initProjectContext(config);
36
+ // Pre-compile the insert statement for performance
37
+ this._insertStmt = this.db.prepare(`INSERT INTO tool_usage (tool_name, toolset, timestamp, duration, success, error_message, project_path, preset, args)
38
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`);
39
+ }
40
+ /** Get or create the singleton tracker */
41
+ static init(config) {
42
+ if (!_instance) {
43
+ _instance = new AnalyticsTracker(config);
44
+ }
45
+ return _instance;
46
+ }
47
+ /** Get existing instance (returns null if not initialized) */
48
+ static get() {
49
+ return _instance;
50
+ }
51
+ /** Underlying DB handle (for stats queries that need it) */
52
+ getDb() {
53
+ return this.db;
54
+ }
55
+ // ── Core: record a tool call ────────────────────────────────────────
56
+ /**
57
+ * Record a tool call outcome. Called from the CallToolRequestSchema handler.
58
+ * Returns silently on any error — analytics must never break tool dispatch.
59
+ */
60
+ record(toolName, startMs, success, errorMsg, args) {
61
+ if (this.skipTools.has(toolName))
62
+ return;
63
+ try {
64
+ const toolset = this.toolToToolset.get(toolName) ?? 'unknown';
65
+ this._insertStmt.run(toolName, toolset, startMs, Date.now() - startMs, success ? 1 : 0, errorMsg, this.projectPath, this.preset, args ? JSON.stringify(args) : null);
66
+ this._callCount++;
67
+ }
68
+ catch { /* never break tool dispatch */ }
69
+ }
70
+ // ── Session stats ───────────────────────────────────────────────────
71
+ getSessionStats() {
72
+ const stmt = this.db.prepare(`
73
+ SELECT
74
+ COUNT(*) as totalCalls,
75
+ SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) as successCount,
76
+ SUM(CASE WHEN success = 0 THEN 1 ELSE 0 END) as failureCount,
77
+ SUM(duration) as totalDuration,
78
+ COUNT(DISTINCT tool_name) as uniqueTools
79
+ FROM tool_usage
80
+ WHERE project_path = ? AND timestamp >= ?
81
+ `);
82
+ const r = stmt.get(this.projectPath, this.sessionStart);
83
+ const topStmt = this.db.prepare(`
84
+ SELECT tool_name as name, COUNT(*) as count
85
+ FROM tool_usage
86
+ WHERE project_path = ? AND timestamp >= ?
87
+ GROUP BY tool_name ORDER BY count DESC LIMIT 5
88
+ `);
89
+ const topTools = topStmt.all(this.projectPath, this.sessionStart);
90
+ const total = r.totalCalls || 0;
91
+ const failures = r.failureCount || 0;
92
+ return {
93
+ totalCalls: total,
94
+ successCount: r.successCount || 0,
95
+ failureCount: failures,
96
+ totalDuration: r.totalDuration || 0,
97
+ uniqueTools: r.uniqueTools || 0,
98
+ topTools,
99
+ errorRate: total > 0 ? failures / total : 0,
100
+ };
101
+ }
102
+ get callCount() {
103
+ return this._callCount;
104
+ }
105
+ // ── Lifecycle ───────────────────────────────────────────────────────
106
+ close() {
107
+ try {
108
+ closeAnalyticsDb(this.db);
109
+ }
110
+ catch { /* ignore */ }
111
+ _instance = null;
112
+ }
113
+ // ── Private helpers ─────────────────────────────────────────────────
114
+ _initProjectContext(config) {
115
+ const context = detectProject(config.projectPath);
116
+ const now = Date.now();
117
+ updateProjectContext(this.db, {
118
+ projectPath: config.projectPath,
119
+ projectType: context.projectType,
120
+ detectedAt: now,
121
+ lastSeen: now,
122
+ language: context.language,
123
+ framework: context.framework,
124
+ hasTests: context.hasTests,
125
+ hasCI: context.hasCI,
126
+ hasDocs: context.hasDocs,
127
+ fileCount: context.fileCount,
128
+ });
129
+ recordPresetSelection(this.db, {
130
+ projectPath: config.projectPath,
131
+ preset: config.preset,
132
+ toolsetCount: config.toolCount,
133
+ selectedAt: now,
134
+ selectionReason: 'manual',
135
+ });
136
+ }
137
+ }
138
+ // ── Convenience re-exports for backward compat ────────────────────────
139
+ /** @deprecated Use AnalyticsTracker.init() instead */
140
+ export function initializeProjectContext(db, projectPath = process.cwd(), preset, toolCount = 44) {
141
+ const context = detectProject(projectPath);
142
+ const now = Date.now();
143
+ updateProjectContext(db, {
144
+ projectPath,
145
+ projectType: context.projectType,
146
+ detectedAt: now,
147
+ lastSeen: now,
148
+ language: context.language,
149
+ framework: context.framework,
150
+ hasTests: context.hasTests,
151
+ hasCI: context.hasCI,
152
+ hasDocs: context.hasDocs,
153
+ fileCount: context.fileCount,
154
+ });
155
+ recordPresetSelection(db, {
156
+ projectPath,
157
+ preset,
158
+ toolsetCount: toolCount,
159
+ selectedAt: now,
160
+ selectionReason: 'manual',
161
+ });
162
+ }
163
+ //# sourceMappingURL=toolTracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolTracker.js","sourceRoot":"","sources":["../../src/analytics/toolTracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Usage Statistics Aggregation
3
+ *
4
+ * Aggregates tool usage data to generate insights and recommendations.
5
+ */
6
+ import Database from 'better-sqlite3';
7
+ export interface ToolUsageStats {
8
+ toolName: string;
9
+ toolset: string;
10
+ callCount: number;
11
+ successCount: number;
12
+ failureCount: number;
13
+ avgDuration: number;
14
+ lastUsed: number;
15
+ firstUsed: number;
16
+ }
17
+ export interface ToolsetUsageStats {
18
+ toolset: string;
19
+ toolCount: number;
20
+ totalCalls: number;
21
+ uniqueToolsUsed: number;
22
+ avgCallsPerTool: number;
23
+ }
24
+ export interface ProjectUsageSummary {
25
+ projectPath: string;
26
+ totalCalls: number;
27
+ uniqueToolsUsed: number;
28
+ totalDuration: number;
29
+ avgDuration: number;
30
+ successRate: number;
31
+ mostUsedTool: string;
32
+ mostUsedToolset: string;
33
+ topTools: Array<{
34
+ name: string;
35
+ count: number;
36
+ }>;
37
+ topToolsets: Array<{
38
+ name: string;
39
+ count: number;
40
+ }>;
41
+ }
42
+ export interface UsageTrend {
43
+ date: string;
44
+ callCount: number;
45
+ uniqueTools: number;
46
+ avgDuration: number;
47
+ }
48
+ export declare function getToolUsageStats(db: Database.Database, projectPath: string, days?: number): ToolUsageStats[];
49
+ export declare function getToolsetUsageStats(db: Database.Database, projectPath: string, days?: number): ToolsetUsageStats[];
50
+ export declare function getProjectUsageSummary(db: Database.Database, projectPath: string, days?: number): ProjectUsageSummary | null;
51
+ export declare function getUsageTrend(db: Database.Database, projectPath: string, days?: number): UsageTrend[];
52
+ export declare function getUnusedTools(db: Database.Database, projectPath: string, availableTools: string[], days?: number): string[];
53
+ export declare function getFrequentlyFailingTools(db: Database.Database, projectPath: string, days?: number, minFailures?: number): Array<{
54
+ toolName: string;
55
+ failureCount: number;
56
+ lastError: string | null;
57
+ }>;
58
+ export declare function getAllProjects(db: Database.Database): Array<{
59
+ projectPath: string;
60
+ lastSeen: number;
61
+ }>;
62
+ export declare function exportUsageStats(db: Database.Database, projectPath: string, days?: number): string;
63
+ export declare function getCachedProjectSummary(db: Database.Database, projectPath: string, days?: number): ProjectUsageSummary | null;
64
+ export declare function formatStatsDisplay(summary: ProjectUsageSummary, projectPath: string): string;