nodebench-mcp 2.17.0 → 2.18.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/LICENSE +21 -0
- package/NODEBENCH_AGENTS.md +2 -2
- package/README.md +514 -82
- package/dist/__tests__/analytics.test.d.ts +11 -0
- package/dist/__tests__/analytics.test.js +546 -0
- package/dist/__tests__/analytics.test.js.map +1 -0
- package/dist/__tests__/dynamicLoading.test.d.ts +1 -0
- package/dist/__tests__/dynamicLoading.test.js +278 -0
- package/dist/__tests__/dynamicLoading.test.js.map +1 -0
- package/dist/__tests__/evalHarness.test.js +1 -1
- package/dist/__tests__/evalHarness.test.js.map +1 -1
- package/dist/__tests__/helpers/answerMatch.js +22 -22
- package/dist/__tests__/presetRealWorldBench.test.js +9 -0
- package/dist/__tests__/presetRealWorldBench.test.js.map +1 -1
- package/dist/__tests__/tools.test.js +1 -1
- package/dist/__tests__/toolsetGatingEval.test.js +9 -1
- package/dist/__tests__/toolsetGatingEval.test.js.map +1 -1
- package/dist/analytics/index.d.ts +10 -0
- package/dist/analytics/index.js +11 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/projectDetector.d.ts +19 -0
- package/dist/analytics/projectDetector.js +259 -0
- package/dist/analytics/projectDetector.js.map +1 -0
- package/dist/analytics/schema.d.ts +57 -0
- package/dist/analytics/schema.js +157 -0
- package/dist/analytics/schema.js.map +1 -0
- package/dist/analytics/smartPreset.d.ts +63 -0
- package/dist/analytics/smartPreset.js +300 -0
- package/dist/analytics/smartPreset.js.map +1 -0
- package/dist/analytics/toolTracker.d.ts +59 -0
- package/dist/analytics/toolTracker.js +163 -0
- package/dist/analytics/toolTracker.js.map +1 -0
- package/dist/analytics/usageStats.d.ts +64 -0
- package/dist/analytics/usageStats.js +252 -0
- package/dist/analytics/usageStats.js.map +1 -0
- package/dist/db.js +359 -321
- package/dist/db.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +652 -89
- package/dist/index.js.map +1 -1
- package/dist/tools/architectTools.js +13 -13
- package/dist/tools/critterTools.js +14 -14
- package/dist/tools/parallelAgentTools.js +176 -176
- package/dist/tools/patternTools.js +11 -11
- package/dist/tools/progressiveDiscoveryTools.d.ts +5 -1
- package/dist/tools/progressiveDiscoveryTools.js +111 -19
- package/dist/tools/progressiveDiscoveryTools.js.map +1 -1
- package/dist/tools/researchWritingTools.js +42 -42
- package/dist/tools/rssTools.js +396 -396
- package/dist/tools/toolRegistry.d.ts +17 -0
- package/dist/tools/toolRegistry.js +65 -17
- package/dist/tools/toolRegistry.js.map +1 -1
- package/dist/tools/voiceBridgeTools.js +498 -498
- package/dist/toolsetRegistry.d.ts +10 -0
- package/dist/toolsetRegistry.js +84 -0
- package/dist/toolsetRegistry.js.map +1 -0
- 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;
|