nodebench-mcp 2.14.2 → 2.17.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/NODEBENCH_AGENTS.md +3 -3
- package/README.md +9 -9
- package/dist/__tests__/architectComplex.test.d.ts +1 -0
- package/dist/__tests__/architectComplex.test.js +375 -0
- package/dist/__tests__/architectComplex.test.js.map +1 -0
- package/dist/__tests__/architectSmoke.test.d.ts +1 -0
- package/dist/__tests__/architectSmoke.test.js +92 -0
- package/dist/__tests__/architectSmoke.test.js.map +1 -0
- package/dist/__tests__/critterCalibrationEval.d.ts +8 -0
- package/dist/__tests__/critterCalibrationEval.js +370 -0
- package/dist/__tests__/critterCalibrationEval.js.map +1 -0
- package/dist/__tests__/embeddingProvider.test.d.ts +1 -0
- package/dist/__tests__/embeddingProvider.test.js +86 -0
- package/dist/__tests__/embeddingProvider.test.js.map +1 -0
- package/dist/__tests__/evalHarness.test.js +6 -1
- package/dist/__tests__/evalHarness.test.js.map +1 -1
- package/dist/__tests__/gaiaCapabilityAudioEval.test.js +1 -1
- package/dist/__tests__/gaiaCapabilityAudioEval.test.js.map +1 -1
- package/dist/__tests__/gaiaCapabilityEval.test.js +759 -28
- package/dist/__tests__/gaiaCapabilityEval.test.js.map +1 -1
- package/dist/__tests__/gaiaCapabilityFilesEval.test.js +1 -1
- package/dist/__tests__/gaiaCapabilityFilesEval.test.js.map +1 -1
- package/dist/__tests__/gaiaCapabilityMediaEval.test.js +558 -4
- package/dist/__tests__/gaiaCapabilityMediaEval.test.js.map +1 -1
- package/dist/__tests__/presetRealWorldBench.test.js +2 -2
- package/dist/__tests__/presetRealWorldBench.test.js.map +1 -1
- package/dist/__tests__/tools.test.js +1016 -8
- package/dist/__tests__/tools.test.js.map +1 -1
- package/dist/__tests__/toolsetGatingEval.test.js +3 -3
- package/dist/__tests__/toolsetGatingEval.test.js.map +1 -1
- package/dist/db.js +64 -0
- package/dist/db.js.map +1 -1
- package/dist/index.js +76 -9
- package/dist/index.js.map +1 -1
- package/dist/tools/architectTools.d.ts +15 -0
- package/dist/tools/architectTools.js +304 -0
- package/dist/tools/architectTools.js.map +1 -0
- package/dist/tools/critterTools.d.ts +21 -0
- package/dist/tools/critterTools.js +230 -0
- package/dist/tools/critterTools.js.map +1 -0
- package/dist/tools/emailTools.d.ts +15 -0
- package/dist/tools/emailTools.js +664 -0
- package/dist/tools/emailTools.js.map +1 -0
- package/dist/tools/embeddingProvider.d.ts +67 -0
- package/dist/tools/embeddingProvider.js +299 -0
- package/dist/tools/embeddingProvider.js.map +1 -0
- package/dist/tools/metaTools.js +660 -0
- package/dist/tools/metaTools.js.map +1 -1
- package/dist/tools/progressiveDiscoveryTools.js +24 -7
- package/dist/tools/progressiveDiscoveryTools.js.map +1 -1
- package/dist/tools/reconTools.js +83 -33
- package/dist/tools/reconTools.js.map +1 -1
- package/dist/tools/rssTools.d.ts +8 -0
- package/dist/tools/rssTools.js +833 -0
- package/dist/tools/rssTools.js.map +1 -0
- package/dist/tools/toolRegistry.d.ts +30 -2
- package/dist/tools/toolRegistry.js +424 -25
- package/dist/tools/toolRegistry.js.map +1 -1
- package/package.json +14 -3
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architect Tools — Structural code analysis and concept verification.
|
|
3
|
+
*
|
|
4
|
+
* Instead of hardcoded feature tiers, these tools let agents dynamically
|
|
5
|
+
* discover what a codebase can do and what's missing. The agent searches
|
|
6
|
+
* the web for new concepts, defines the required code signatures, then
|
|
7
|
+
* uses these tools to verify and plan implementation.
|
|
8
|
+
*
|
|
9
|
+
* 3 tools:
|
|
10
|
+
* - scan_capabilities: Analyze a file for structural patterns (regex-based)
|
|
11
|
+
* - verify_concept_support: Check if a file contains required code signatures
|
|
12
|
+
* - generate_implementation_plan: Build a plan for missing signatures
|
|
13
|
+
*/
|
|
14
|
+
import { readFile } from "node:fs/promises";
|
|
15
|
+
import { getDb, genId } from "../db.js";
|
|
16
|
+
// ── DB setup ────────────────────────────────────────────────────────────────
|
|
17
|
+
function ensureConceptTable() {
|
|
18
|
+
const db = getDb();
|
|
19
|
+
db.exec(`
|
|
20
|
+
CREATE TABLE IF NOT EXISTS concept_verifications (
|
|
21
|
+
id TEXT PRIMARY KEY,
|
|
22
|
+
concept_name TEXT NOT NULL,
|
|
23
|
+
file_path TEXT NOT NULL,
|
|
24
|
+
status TEXT NOT NULL,
|
|
25
|
+
match_score REAL NOT NULL,
|
|
26
|
+
signatures_total INTEGER NOT NULL,
|
|
27
|
+
signatures_found INTEGER NOT NULL,
|
|
28
|
+
gap_list TEXT,
|
|
29
|
+
verified_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
30
|
+
)
|
|
31
|
+
`);
|
|
32
|
+
}
|
|
33
|
+
const STATE_PATTERNS = {
|
|
34
|
+
boolean_flags: { pattern: /const \[\w+, set\w+\] = useState(?:<boolean>)?\(/g, count: true },
|
|
35
|
+
complex_objects: { pattern: /const \[\w+, set\w+\] = useState<\{/g, count: true },
|
|
36
|
+
refs: { pattern: /useRef</g, count: true },
|
|
37
|
+
reducers: { pattern: /useReducer\(/g, count: true },
|
|
38
|
+
context_consumers: { pattern: /useContext\(/g, count: true },
|
|
39
|
+
effects: { pattern: /useEffect\(/g, count: true },
|
|
40
|
+
memos: { pattern: /useMemo\(/g, count: true },
|
|
41
|
+
callbacks: { pattern: /useCallback\(/g, count: true },
|
|
42
|
+
};
|
|
43
|
+
const LAYOUT_PATTERNS = {
|
|
44
|
+
has_overlay: { pattern: /(?:fixed|absolute)\s+inset-0|z-50|z-\[/ },
|
|
45
|
+
has_sidebar: { pattern: /w-\[.*?\].*?(?:flex|border-[lr])|sidebar|side-panel/i },
|
|
46
|
+
has_resizable: { pattern: /resize|cursor-(?:col|row)-resize|onResize/ },
|
|
47
|
+
has_grid: { pattern: /grid-cols-|display:\s*grid/ },
|
|
48
|
+
has_responsive: { pattern: /sm:|md:|lg:|xl:|@media/ },
|
|
49
|
+
has_modal: { pattern: /(?:modal|dialog)(?:Open|Visible|Show)/i },
|
|
50
|
+
};
|
|
51
|
+
const INTERACTION_PATTERNS = {
|
|
52
|
+
keyboard_shortcuts: { pattern: /addEventListener\(['"]keydown|onKeyDown|useHotkeys/ },
|
|
53
|
+
drag_drop: { pattern: /onDrop|onDragOver|useDrag|useDrop|draggable/ },
|
|
54
|
+
clipboard: { pattern: /navigator\.clipboard|execCommand\(['"]copy/ },
|
|
55
|
+
voice: { pattern: /SpeechRecognition|webkitSpeechRecognition|MediaRecorder/ },
|
|
56
|
+
touch: { pattern: /onTouchStart|onTouchMove|onTouchEnd/ },
|
|
57
|
+
scroll: { pattern: /onScroll|IntersectionObserver|scrollIntoView/ },
|
|
58
|
+
animation: { pattern: /framer-motion|useSpring|@keyframes|transition:/ },
|
|
59
|
+
};
|
|
60
|
+
const RENDERING_PATTERNS = {
|
|
61
|
+
markdown: { pattern: /ReactMarkdown|remark|rehype|marked/ },
|
|
62
|
+
code_highlighting: { pattern: /SyntaxHighlighter|Prism|highlight\.js|shiki/ },
|
|
63
|
+
math: { pattern: /KaTeX|MathJax|mathjax/ },
|
|
64
|
+
dynamic_lists: { pattern: /\.map\(\s*\(/g, count: true },
|
|
65
|
+
streaming: { pattern: /ReadableStream|EventSource|onmessage|text\/event-stream/ },
|
|
66
|
+
virtualization: { pattern: /react-window|react-virtualized|useVirtualizer/ },
|
|
67
|
+
};
|
|
68
|
+
const BACKEND_PATTERNS = {
|
|
69
|
+
rest_routes: { pattern: /app\.(get|post|put|patch|delete)\s*\(/g, count: true },
|
|
70
|
+
middleware: { pattern: /app\.use\(|router\.use\(|middleware/g, count: true },
|
|
71
|
+
db_queries: { pattern: /\.query\(|\.exec\(|\.prepare\(|prisma\.|knex\./g, count: true },
|
|
72
|
+
auth_guards: { pattern: /isAuthenticated|requireAuth|verifyToken|passport\.authenticate/g, count: true },
|
|
73
|
+
websocket: { pattern: /WebSocket|wss?\.|socket\.on|io\.on/ },
|
|
74
|
+
graphql: { pattern: /typeDefs|resolvers|gql`|graphql/ },
|
|
75
|
+
cron_jobs: { pattern: /cron\.|schedule\(|setInterval\(/ },
|
|
76
|
+
};
|
|
77
|
+
function analyzePatterns(content, patterns) {
|
|
78
|
+
const result = {};
|
|
79
|
+
for (const [key, { pattern, count }] of Object.entries(patterns)) {
|
|
80
|
+
if (count) {
|
|
81
|
+
const matches = content.match(pattern);
|
|
82
|
+
result[key] = matches ? matches.length : 0;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
result[key] = pattern.test(content);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
// ── Tools ──────────────────────────────────────────────────────────────────
|
|
91
|
+
export const architectTools = [
|
|
92
|
+
{
|
|
93
|
+
name: "scan_capabilities",
|
|
94
|
+
description: "Analyze a source file for structural code patterns. Returns a capability report showing what the code can structurally DO — state management (hooks, refs, reducers), layout (overlay, sidebar, grid, responsive), interactions (keyboard, drag-drop, clipboard, voice, touch), rendering (markdown, code highlighting, math, streaming), and backend patterns (REST routes, middleware, DB queries, auth guards, WebSocket). Pure regex analysis, no LLM needed.",
|
|
95
|
+
inputSchema: {
|
|
96
|
+
type: "object",
|
|
97
|
+
properties: {
|
|
98
|
+
file_path: {
|
|
99
|
+
type: "string",
|
|
100
|
+
description: "Absolute or relative path to the source file to analyze",
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
required: ["file_path"],
|
|
104
|
+
},
|
|
105
|
+
handler: async (args) => {
|
|
106
|
+
const content = await readFile(args.file_path, "utf-8");
|
|
107
|
+
const lines = content.split("\n").length;
|
|
108
|
+
const capabilities = {
|
|
109
|
+
file: {
|
|
110
|
+
path: args.file_path,
|
|
111
|
+
lines,
|
|
112
|
+
sizeBytes: Buffer.byteLength(content, "utf-8"),
|
|
113
|
+
},
|
|
114
|
+
state_management: analyzePatterns(content, STATE_PATTERNS),
|
|
115
|
+
layout_structure: analyzePatterns(content, LAYOUT_PATTERNS),
|
|
116
|
+
interaction_patterns: analyzePatterns(content, INTERACTION_PATTERNS),
|
|
117
|
+
rendering_capabilities: analyzePatterns(content, RENDERING_PATTERNS),
|
|
118
|
+
backend_patterns: analyzePatterns(content, BACKEND_PATTERNS),
|
|
119
|
+
imports: {
|
|
120
|
+
count: (content.match(/^import /gm) || []).length,
|
|
121
|
+
has_react: /from ['"]react/.test(content),
|
|
122
|
+
has_next: /from ['"]next/.test(content),
|
|
123
|
+
has_express: /from ['"]express/.test(content),
|
|
124
|
+
has_test_framework: /from ['"](?:vitest|jest|mocha|chai)/.test(content),
|
|
125
|
+
},
|
|
126
|
+
exports: {
|
|
127
|
+
default_export: /export default/.test(content),
|
|
128
|
+
named_exports: (content.match(/^export (?:const|function|class|type|interface)/gm) || []).length,
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
return capabilities;
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: "verify_concept_support",
|
|
136
|
+
description: "Check if a source file contains all required code signatures for a concept. Provide a concept name and a list of regex patterns that MUST exist for the concept to be considered implemented. Returns match score (0-100%), status (Fully/Partially/Not Implemented), evidence found, and gap analysis. Results are persisted to SQLite for tracking progress over time.",
|
|
137
|
+
inputSchema: {
|
|
138
|
+
type: "object",
|
|
139
|
+
properties: {
|
|
140
|
+
file_path: {
|
|
141
|
+
type: "string",
|
|
142
|
+
description: "Path to the source file to verify",
|
|
143
|
+
},
|
|
144
|
+
concept_name: {
|
|
145
|
+
type: "string",
|
|
146
|
+
description: 'The feature/concept to verify (e.g., "Dark Mode", "Canvas Artifacts", "Real-time Collaboration")',
|
|
147
|
+
},
|
|
148
|
+
required_signatures: {
|
|
149
|
+
type: "array",
|
|
150
|
+
items: { type: "string" },
|
|
151
|
+
description: 'Regex patterns that MUST exist for the concept to be implemented. E.g., ["prefers-color-scheme", "theme.*dark", "toggle.*theme"]',
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
required: ["file_path", "concept_name", "required_signatures"],
|
|
155
|
+
},
|
|
156
|
+
handler: async (args) => {
|
|
157
|
+
ensureConceptTable();
|
|
158
|
+
const content = await readFile(args.file_path, "utf-8");
|
|
159
|
+
const found = [];
|
|
160
|
+
const missing = [];
|
|
161
|
+
for (const sig of args.required_signatures) {
|
|
162
|
+
try {
|
|
163
|
+
const regex = new RegExp(sig, "i");
|
|
164
|
+
if (regex.test(content)) {
|
|
165
|
+
found.push(sig);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
missing.push(sig);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
// Invalid regex — treat as literal string search
|
|
173
|
+
if (content.toLowerCase().includes(sig.toLowerCase())) {
|
|
174
|
+
found.push(sig);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
missing.push(sig);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const score = args.required_signatures.length > 0
|
|
182
|
+
? Math.round((found.length / args.required_signatures.length) * 100)
|
|
183
|
+
: 0;
|
|
184
|
+
const status = score === 100
|
|
185
|
+
? "Fully Implemented"
|
|
186
|
+
: score > 50
|
|
187
|
+
? "Partially Implemented"
|
|
188
|
+
: "Not Implemented";
|
|
189
|
+
// Persist to SQLite
|
|
190
|
+
const id = genId("cv");
|
|
191
|
+
const db = getDb();
|
|
192
|
+
db.prepare(`INSERT INTO concept_verifications (id, concept_name, file_path, status, match_score, signatures_total, signatures_found, gap_list)
|
|
193
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(id, args.concept_name, args.file_path, status, score, args.required_signatures.length, found.length, JSON.stringify(missing));
|
|
194
|
+
return {
|
|
195
|
+
id,
|
|
196
|
+
concept: args.concept_name,
|
|
197
|
+
file: args.file_path,
|
|
198
|
+
status,
|
|
199
|
+
match_score: `${score}%`,
|
|
200
|
+
signatures_total: args.required_signatures.length,
|
|
201
|
+
evidence_found: found,
|
|
202
|
+
gap_analysis: missing,
|
|
203
|
+
recommendation: missing.length === 0
|
|
204
|
+
? "All required signatures found. Concept is fully implemented."
|
|
205
|
+
: missing.length <= 2
|
|
206
|
+
? `Nearly there — ${missing.length} signature(s) missing: ${missing.join(", ")}`
|
|
207
|
+
: `${missing.length} of ${args.required_signatures.length} signatures missing. Major implementation work needed.`,
|
|
208
|
+
};
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
name: "generate_implementation_plan",
|
|
213
|
+
description: "Generate a structured implementation plan for missing code signatures. Takes the gap analysis from verify_concept_support and produces a step-by-step plan with per-signature requirements and injection strategies. Optionally takes the output of scan_capabilities as context to avoid conflicts with existing patterns.",
|
|
214
|
+
inputSchema: {
|
|
215
|
+
type: "object",
|
|
216
|
+
properties: {
|
|
217
|
+
concept_name: {
|
|
218
|
+
type: "string",
|
|
219
|
+
description: "The concept being implemented",
|
|
220
|
+
},
|
|
221
|
+
missing_signatures: {
|
|
222
|
+
type: "array",
|
|
223
|
+
items: { type: "string" },
|
|
224
|
+
description: "List of missing regex patterns from verify_concept_support gap_analysis",
|
|
225
|
+
},
|
|
226
|
+
current_context: {
|
|
227
|
+
type: "string",
|
|
228
|
+
description: "Brief description or JSON of the current component capabilities (from scan_capabilities output). Helps avoid conflicts.",
|
|
229
|
+
},
|
|
230
|
+
target_file: {
|
|
231
|
+
type: "string",
|
|
232
|
+
description: "Path to the file where changes will be made (optional, for reference)",
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
required: ["concept_name", "missing_signatures"],
|
|
236
|
+
},
|
|
237
|
+
handler: async (args) => {
|
|
238
|
+
const steps = args.missing_signatures.map((sig, i) => ({
|
|
239
|
+
step: i + 1,
|
|
240
|
+
requirement: sig,
|
|
241
|
+
description: `Inject pattern matching: ${sig}`,
|
|
242
|
+
strategy: inferStrategy(sig),
|
|
243
|
+
conflicts: args.current_context
|
|
244
|
+
? `Review current context for overlap with: ${sig}`
|
|
245
|
+
: "No context provided — run scan_capabilities first for conflict detection",
|
|
246
|
+
}));
|
|
247
|
+
return {
|
|
248
|
+
concept: args.concept_name,
|
|
249
|
+
target_file: args.target_file || "(not specified)",
|
|
250
|
+
total_steps: steps.length,
|
|
251
|
+
estimated_complexity: steps.length <= 2 ? "low" : steps.length <= 5 ? "medium" : "high",
|
|
252
|
+
context_provided: !!args.current_context,
|
|
253
|
+
steps,
|
|
254
|
+
workflow: [
|
|
255
|
+
"1. Run scan_capabilities on the target file (if not already done)",
|
|
256
|
+
"2. Review each step below and implement in order",
|
|
257
|
+
"3. After each step, run verify_concept_support to track progress",
|
|
258
|
+
"4. When all signatures match, the concept is fully implemented",
|
|
259
|
+
],
|
|
260
|
+
};
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
];
|
|
264
|
+
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
265
|
+
function inferStrategy(signature) {
|
|
266
|
+
const lower = signature.toLowerCase();
|
|
267
|
+
// State patterns
|
|
268
|
+
if (/usestate|useref|usereducer|usecontext/i.test(lower))
|
|
269
|
+
return "Add React hook to component body (before return statement)";
|
|
270
|
+
if (/useeffect|usememo|usecallback/i.test(lower))
|
|
271
|
+
return "Add React hook — check dependency array for existing effects to avoid duplicates";
|
|
272
|
+
// Layout patterns
|
|
273
|
+
if (/grid|flex|sidebar|overlay|modal|dialog/i.test(lower))
|
|
274
|
+
return "Add CSS/layout structure to JSX return — check existing layout for nesting conflicts";
|
|
275
|
+
if (/responsive|media|breakpoint/i.test(lower))
|
|
276
|
+
return "Add responsive breakpoints — check existing Tailwind/CSS classes for conflicts";
|
|
277
|
+
// Interaction patterns
|
|
278
|
+
if (/keydown|keyboard|hotkey/i.test(lower))
|
|
279
|
+
return "Add keyboard event listener — check for existing keydown handlers to merge, not duplicate";
|
|
280
|
+
if (/drag|drop/i.test(lower))
|
|
281
|
+
return "Add drag-and-drop handlers — ensure no conflicting pointer event handlers";
|
|
282
|
+
if (/clipboard|copy/i.test(lower))
|
|
283
|
+
return "Add clipboard API call — wrap in try/catch for permission handling";
|
|
284
|
+
if (/speech|voice|recognition/i.test(lower))
|
|
285
|
+
return "Add Web Speech API — feature-detect first (not available in all browsers)";
|
|
286
|
+
// Backend patterns
|
|
287
|
+
if (/app\.\w+\(|router\.\w+\(|route/i.test(lower))
|
|
288
|
+
return "Add route handler — check existing routes for path conflicts";
|
|
289
|
+
if (/middleware|use\(/i.test(lower))
|
|
290
|
+
return "Add middleware — check execution order in middleware stack";
|
|
291
|
+
if (/query|prepare|prisma|knex/i.test(lower))
|
|
292
|
+
return "Add database query — ensure schema/migration exists for required tables";
|
|
293
|
+
if (/auth|token|passport/i.test(lower))
|
|
294
|
+
return "Add authentication logic — verify auth middleware is applied to the right routes";
|
|
295
|
+
if (/websocket|socket/i.test(lower))
|
|
296
|
+
return "Add WebSocket handler — check for existing connection managers to reuse";
|
|
297
|
+
// Rendering patterns
|
|
298
|
+
if (/markdown|remark/i.test(lower))
|
|
299
|
+
return "Add markdown renderer — install remark/rehype plugins if needed";
|
|
300
|
+
if (/highlight|syntax|prism|shiki/i.test(lower))
|
|
301
|
+
return "Add code highlighting — check bundle size impact of syntax theme";
|
|
302
|
+
return "Inject this pattern into the appropriate location in the file";
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=architectTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architectTools.js","sourceRoot":"","sources":["../../src/tools/architectTools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Critter Tools — The accountability partner that wants to know everything.
|
|
3
|
+
*
|
|
4
|
+
* Like a girlfriend who asks "so why are you doing this? who is it for?" —
|
|
5
|
+
* annoying in the moment, but actually a great productivity enhancer.
|
|
6
|
+
* The friction is the feature: making agents slow down to articulate purpose
|
|
7
|
+
* and audience prevents scope creep, cargo-cult coding, and aimless exploration.
|
|
8
|
+
*
|
|
9
|
+
* What critter catches:
|
|
10
|
+
* - Circular reasoning ("I'm adding auth because we need auth")
|
|
11
|
+
* - Vague audiences ("it's for users" — which users? doing what?)
|
|
12
|
+
* - Deference over understanding ("because the ticket says so")
|
|
13
|
+
* - Missing success criteria (how will you know it worked?)
|
|
14
|
+
*
|
|
15
|
+
* Inspired by daily intentionality questions that surface clarity from chaos.
|
|
16
|
+
*
|
|
17
|
+
* 1 tool:
|
|
18
|
+
* - critter_check: Submit a task + why + who for intentionality scoring
|
|
19
|
+
*/
|
|
20
|
+
import type { McpTool } from "../types.js";
|
|
21
|
+
export declare const critterTools: McpTool[];
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Critter Tools — The accountability partner that wants to know everything.
|
|
3
|
+
*
|
|
4
|
+
* Like a girlfriend who asks "so why are you doing this? who is it for?" —
|
|
5
|
+
* annoying in the moment, but actually a great productivity enhancer.
|
|
6
|
+
* The friction is the feature: making agents slow down to articulate purpose
|
|
7
|
+
* and audience prevents scope creep, cargo-cult coding, and aimless exploration.
|
|
8
|
+
*
|
|
9
|
+
* What critter catches:
|
|
10
|
+
* - Circular reasoning ("I'm adding auth because we need auth")
|
|
11
|
+
* - Vague audiences ("it's for users" — which users? doing what?)
|
|
12
|
+
* - Deference over understanding ("because the ticket says so")
|
|
13
|
+
* - Missing success criteria (how will you know it worked?)
|
|
14
|
+
*
|
|
15
|
+
* Inspired by daily intentionality questions that surface clarity from chaos.
|
|
16
|
+
*
|
|
17
|
+
* 1 tool:
|
|
18
|
+
* - critter_check: Submit a task + why + who for intentionality scoring
|
|
19
|
+
*/
|
|
20
|
+
import { getDb, genId } from "../db.js";
|
|
21
|
+
// ── DB setup ────────────────────────────────────────────────────────────────
|
|
22
|
+
function ensureCritterTable() {
|
|
23
|
+
const db = getDb();
|
|
24
|
+
db.exec(`
|
|
25
|
+
CREATE TABLE IF NOT EXISTS critter_checks (
|
|
26
|
+
id TEXT PRIMARY KEY,
|
|
27
|
+
task TEXT NOT NULL,
|
|
28
|
+
why TEXT NOT NULL,
|
|
29
|
+
who TEXT NOT NULL,
|
|
30
|
+
success_looks_like TEXT,
|
|
31
|
+
simplest_version TEXT,
|
|
32
|
+
score INTEGER NOT NULL,
|
|
33
|
+
verdict TEXT NOT NULL,
|
|
34
|
+
feedback TEXT NOT NULL,
|
|
35
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
36
|
+
)
|
|
37
|
+
`);
|
|
38
|
+
}
|
|
39
|
+
function scoreCritterCheck(input) {
|
|
40
|
+
const feedback = [];
|
|
41
|
+
let score = 100;
|
|
42
|
+
const taskLower = input.task.toLowerCase().trim();
|
|
43
|
+
const whyLower = input.why.toLowerCase().trim();
|
|
44
|
+
const whoLower = input.who.toLowerCase().trim();
|
|
45
|
+
// ── Check 1: Circular reasoning — "why" just restates the task ────────
|
|
46
|
+
const taskWords = new Set(taskLower.split(/\s+/).filter((w) => w.length > 3));
|
|
47
|
+
const whyWords = whyLower.split(/\s+/).filter((w) => w.length > 3);
|
|
48
|
+
const overlap = whyWords.filter((w) => taskWords.has(w));
|
|
49
|
+
if (whyWords.length > 0 && overlap.length / whyWords.length > 0.5) {
|
|
50
|
+
score -= 30;
|
|
51
|
+
feedback.push("Circular: your 'why' mostly restates the task. Dig deeper — what outcome does this enable?");
|
|
52
|
+
}
|
|
53
|
+
// ── Check 2: Vague audience ───────────────────────────────────────────
|
|
54
|
+
const vagueAudiences = ["users", "everyone", "people", "the team", "stakeholders", "clients", "customers", "developers"];
|
|
55
|
+
if (vagueAudiences.includes(whoLower)) {
|
|
56
|
+
score -= 20;
|
|
57
|
+
feedback.push(`Vague audience: "${input.who}" is too broad. Who specifically benefits? Name a role, persona, or individual.`);
|
|
58
|
+
}
|
|
59
|
+
// ── Check 3: Empty or trivially short responses ───────────────────────
|
|
60
|
+
if (whyLower.length === 0) {
|
|
61
|
+
score -= 40;
|
|
62
|
+
feedback.push("Empty 'why': you haven't stated any purpose at all. Why does this work matter?");
|
|
63
|
+
}
|
|
64
|
+
else if (whyLower.length < 10) {
|
|
65
|
+
score -= 25;
|
|
66
|
+
feedback.push("The 'why' is too short. A clear purpose needs at least a full sentence.");
|
|
67
|
+
}
|
|
68
|
+
if (whoLower.length < 3) {
|
|
69
|
+
score -= 25;
|
|
70
|
+
feedback.push("The 'who' is too short. Specify who benefits from this work.");
|
|
71
|
+
}
|
|
72
|
+
// ── Check 4: "Because I was told to" or "it's in the ticket" ─────────
|
|
73
|
+
const deferPatterns = [
|
|
74
|
+
"was told", "asked to", "ticket says", "was asked", "requirement says",
|
|
75
|
+
"spec says", "jira", "because I was", "they said", "assigned to me",
|
|
76
|
+
];
|
|
77
|
+
if (deferPatterns.some((p) => whyLower.includes(p))) {
|
|
78
|
+
score -= 15;
|
|
79
|
+
feedback.push("Deference detected: you're citing authority rather than understanding purpose. Why does this matter beyond the ticket?");
|
|
80
|
+
}
|
|
81
|
+
// ── Check 5: Non-answer patterns — explicit "I don't know" ───────────
|
|
82
|
+
const nonAnswerPatterns = [
|
|
83
|
+
"just because", "don't know", "not sure", "why not", "might need it",
|
|
84
|
+
"no reason", "no idea", "whatever", "idk", "tbd",
|
|
85
|
+
];
|
|
86
|
+
const nonAnswerHits = nonAnswerPatterns.filter((p) => whyLower.includes(p)).length;
|
|
87
|
+
if (nonAnswerHits > 0) {
|
|
88
|
+
const nonAnswerPenalty = Math.min(nonAnswerHits * 20, 40); // -20 per match, cap -40
|
|
89
|
+
score -= nonAnswerPenalty;
|
|
90
|
+
feedback.push("Non-answer: your 'why' signals you haven't figured out the purpose yet. What specific problem does this solve?");
|
|
91
|
+
}
|
|
92
|
+
// ── Check 6: Repetitive padding — same words repeated to fake length ──
|
|
93
|
+
const whyAllWords = whyLower.split(/\s+/).filter((w) => w.length > 2);
|
|
94
|
+
if (whyAllWords.length >= 5) {
|
|
95
|
+
const whyUniqueWords = new Set(whyAllWords);
|
|
96
|
+
if (whyUniqueWords.size / whyAllWords.length < 0.4) {
|
|
97
|
+
score -= 25;
|
|
98
|
+
feedback.push("Repetitive: your 'why' repeats the same words. Articulate distinct reasoning.");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const whoAllWords = whoLower.split(/\s+/).filter((w) => w.length > 2);
|
|
102
|
+
if (whoAllWords.length >= 5) {
|
|
103
|
+
const whoUniqueWords = new Set(whoAllWords);
|
|
104
|
+
if (whoUniqueWords.size / whoAllWords.length < 0.4) {
|
|
105
|
+
score -= 25;
|
|
106
|
+
feedback.push("Repetitive: your 'who' repeats the same words. Name a real audience.");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// ── Check 7: Buzzword-heavy corporate-speak ──────────────────────────
|
|
110
|
+
const buzzwords = [
|
|
111
|
+
"leverage", "synergies", "synergy", "paradigm", "holistic", "alignment",
|
|
112
|
+
"transformation", "innovative", "disruptive", "best practices",
|
|
113
|
+
"streamline", "ecosystem", "actionable", "circle back",
|
|
114
|
+
];
|
|
115
|
+
const allText = `${whyLower} ${whoLower}`;
|
|
116
|
+
const buzzCount = buzzwords.filter((b) => allText.includes(b)).length;
|
|
117
|
+
if (buzzCount >= 4) {
|
|
118
|
+
score -= 35;
|
|
119
|
+
feedback.push("Buzzword-heavy: corporate-speak without concrete meaning. What specific problem does this solve?");
|
|
120
|
+
}
|
|
121
|
+
else if (buzzCount >= 3) {
|
|
122
|
+
score -= 30;
|
|
123
|
+
feedback.push("Buzzword-heavy: corporate-speak without concrete meaning. What specific problem does this solve?");
|
|
124
|
+
}
|
|
125
|
+
else if (buzzCount >= 2) {
|
|
126
|
+
score -= 20;
|
|
127
|
+
feedback.push("Buzzword-heavy: corporate-speak without concrete meaning. What specific problem does this solve?");
|
|
128
|
+
}
|
|
129
|
+
// ── Check 8: Hedging language — signals unclear value ─────────────────
|
|
130
|
+
const hedgeWords = ["could", "potentially", "maybe", "possibly", "might", "perhaps", "hopefully"];
|
|
131
|
+
const hedgeCount = hedgeWords.filter((h) => {
|
|
132
|
+
const regex = new RegExp(`\\b${h}\\b`, "i");
|
|
133
|
+
return regex.test(whyLower);
|
|
134
|
+
}).length;
|
|
135
|
+
if (hedgeCount >= 2) {
|
|
136
|
+
score -= 15;
|
|
137
|
+
feedback.push("Hedging: too many 'could/maybe/potentially' signals uncertain value. What WILL this achieve?");
|
|
138
|
+
}
|
|
139
|
+
// ── Check 9: Task-word echo — same word from task repeated 3+ times in why
|
|
140
|
+
for (const tw of taskWords) {
|
|
141
|
+
const twCount = whyWords.filter((w) => w === tw).length;
|
|
142
|
+
if (twCount >= 3) {
|
|
143
|
+
score -= 20;
|
|
144
|
+
feedback.push(`Echo: "${tw}" appears ${twCount} times in your 'why' — this is filler, not reasoning.`);
|
|
145
|
+
break; // one echo penalty max
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// ── Check 10: Bonus for specificity ───────────────────────────────────
|
|
149
|
+
if (input.success_looks_like && input.success_looks_like.length > 20) {
|
|
150
|
+
score += 10;
|
|
151
|
+
feedback.push("Good: you defined what success looks like — this makes verification concrete.");
|
|
152
|
+
}
|
|
153
|
+
if (input.simplest_version && input.simplest_version.length > 20) {
|
|
154
|
+
score += 10;
|
|
155
|
+
feedback.push("Good: you identified the simplest version — this guards against over-engineering.");
|
|
156
|
+
}
|
|
157
|
+
// Clamp
|
|
158
|
+
score = Math.max(0, Math.min(100, score));
|
|
159
|
+
// Verdict
|
|
160
|
+
let verdict;
|
|
161
|
+
if (score >= 70) {
|
|
162
|
+
verdict = "proceed";
|
|
163
|
+
if (feedback.length === 0) {
|
|
164
|
+
feedback.push("Strong intentionality. Purpose and audience are clear — proceed with confidence.");
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else if (score >= 40) {
|
|
168
|
+
verdict = "reconsider";
|
|
169
|
+
feedback.push("Pause and sharpen your thinking before writing code. Re-run critter_check once you have clearer answers.");
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
verdict = "stop";
|
|
173
|
+
feedback.push("Stop: the purpose is unclear. Do not proceed until you can articulate WHY and WHO clearly.");
|
|
174
|
+
}
|
|
175
|
+
return { score, verdict, feedback, id: genId("crit") };
|
|
176
|
+
}
|
|
177
|
+
// ── Tool definition ─────────────────────────────────────────────────────────
|
|
178
|
+
export const critterTools = [
|
|
179
|
+
{
|
|
180
|
+
name: "critter_check",
|
|
181
|
+
description: "The accountability partner that wants to know everything — answer 'Why are you doing this? Who is it for?' before starting work. " +
|
|
182
|
+
"Scores your answers for circular reasoning, vague audiences, and deference-over-understanding. " +
|
|
183
|
+
"Returns a go/no-go verdict. The friction is the feature: slowing down to think prevents scope creep and aimless work. " +
|
|
184
|
+
"Call this at the start of any non-trivial task.",
|
|
185
|
+
inputSchema: {
|
|
186
|
+
type: "object",
|
|
187
|
+
properties: {
|
|
188
|
+
task: {
|
|
189
|
+
type: "string",
|
|
190
|
+
description: "What you are about to do (the action, not the goal)",
|
|
191
|
+
},
|
|
192
|
+
why: {
|
|
193
|
+
type: "string",
|
|
194
|
+
description: "Why are you doing this? Explain the purpose, not just the instruction. Avoid restating the task.",
|
|
195
|
+
},
|
|
196
|
+
who: {
|
|
197
|
+
type: "string",
|
|
198
|
+
description: "Who is this for? Name a specific role, persona, or person — not 'users' or 'everyone'.",
|
|
199
|
+
},
|
|
200
|
+
success_looks_like: {
|
|
201
|
+
type: "string",
|
|
202
|
+
description: "Optional: What does success look like? How will you know this worked?",
|
|
203
|
+
},
|
|
204
|
+
simplest_version: {
|
|
205
|
+
type: "string",
|
|
206
|
+
description: "Optional: What is the simplest version that still delivers value?",
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
required: ["task", "why", "who"],
|
|
210
|
+
},
|
|
211
|
+
handler: async (args) => {
|
|
212
|
+
ensureCritterTable();
|
|
213
|
+
const result = scoreCritterCheck(args);
|
|
214
|
+
// Persist for accountability
|
|
215
|
+
const db = getDb();
|
|
216
|
+
db.prepare(`INSERT INTO critter_checks (id, task, why, who, success_looks_like, simplest_version, score, verdict, feedback)
|
|
217
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(result.id, args.task, args.why, args.who, args.success_looks_like ?? null, args.simplest_version ?? null, result.score, result.verdict, JSON.stringify(result.feedback));
|
|
218
|
+
return {
|
|
219
|
+
id: result.id,
|
|
220
|
+
score: result.score,
|
|
221
|
+
verdict: result.verdict,
|
|
222
|
+
feedback: result.feedback,
|
|
223
|
+
tip: result.verdict === "proceed"
|
|
224
|
+
? "You've passed the critter check. Proceed with clear intent."
|
|
225
|
+
: "Sharpen your answers and re-run critter_check before proceeding.",
|
|
226
|
+
};
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
];
|
|
230
|
+
//# sourceMappingURL=critterTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"critterTools.js","sourceRoot":"","sources":["../../src/tools/critterTools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email Tools — Send and read emails via raw SMTP/IMAP over TLS.
|
|
3
|
+
*
|
|
4
|
+
* Zero npm dependencies — uses Node's built-in `tls` module.
|
|
5
|
+
*
|
|
6
|
+
* Environment variables:
|
|
7
|
+
* - EMAIL_USER: Email address (e.g., agent@gmail.com)
|
|
8
|
+
* - EMAIL_PASS: App password (NOT regular password for Gmail)
|
|
9
|
+
* - EMAIL_SMTP_HOST: SMTP server (default: smtp.gmail.com)
|
|
10
|
+
* - EMAIL_SMTP_PORT: SMTP port (default: 465)
|
|
11
|
+
* - EMAIL_IMAP_HOST: IMAP server (default: imap.gmail.com)
|
|
12
|
+
* - EMAIL_IMAP_PORT: IMAP port (default: 993)
|
|
13
|
+
*/
|
|
14
|
+
import type { McpTool } from "../types.js";
|
|
15
|
+
export declare const emailTools: McpTool[];
|