driftdetect-mcp 0.6.0 → 0.7.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/dist/bin/server.js +0 -0
- package/dist/enterprise-server.d.ts +1 -0
- package/dist/enterprise-server.d.ts.map +1 -1
- package/dist/enterprise-server.js +8 -1
- package/dist/enterprise-server.js.map +1 -1
- package/dist/tools/analysis/constants.d.ts +99 -0
- package/dist/tools/analysis/constants.d.ts.map +1 -0
- package/dist/tools/analysis/constants.js +421 -0
- package/dist/tools/analysis/constants.js.map +1 -0
- package/dist/tools/analysis/index.d.ts +1 -0
- package/dist/tools/analysis/index.d.ts.map +1 -1
- package/dist/tools/analysis/index.js +70 -0
- package/dist/tools/analysis/index.js.map +1 -1
- package/dist/tools/exploration/env.d.ts +53 -0
- package/dist/tools/exploration/env.d.ts.map +1 -0
- package/dist/tools/exploration/env.js +283 -0
- package/dist/tools/exploration/env.js.map +1 -0
- package/dist/tools/exploration/index.d.ts +2 -0
- package/dist/tools/exploration/index.d.ts.map +1 -1
- package/dist/tools/exploration/index.js +32 -0
- package/dist/tools/exploration/index.js.map +1 -1
- package/dist/tools/index.d.ts +6 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +6 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/registry.d.ts +7 -5
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +10 -4
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/surgical/callers.d.ts +85 -0
- package/dist/tools/surgical/callers.d.ts.map +1 -0
- package/dist/tools/surgical/callers.js +239 -0
- package/dist/tools/surgical/callers.js.map +1 -0
- package/dist/tools/surgical/dependencies.d.ts +96 -0
- package/dist/tools/surgical/dependencies.d.ts.map +1 -0
- package/dist/tools/surgical/dependencies.js +433 -0
- package/dist/tools/surgical/dependencies.js.map +1 -0
- package/dist/tools/surgical/errors.d.ts +88 -0
- package/dist/tools/surgical/errors.d.ts.map +1 -0
- package/dist/tools/surgical/errors.js +275 -0
- package/dist/tools/surgical/errors.js.map +1 -0
- package/dist/tools/surgical/hooks.d.ts +69 -0
- package/dist/tools/surgical/hooks.d.ts.map +1 -0
- package/dist/tools/surgical/hooks.js +247 -0
- package/dist/tools/surgical/hooks.js.map +1 -0
- package/dist/tools/surgical/imports.d.ts +61 -0
- package/dist/tools/surgical/imports.d.ts.map +1 -0
- package/dist/tools/surgical/imports.js +211 -0
- package/dist/tools/surgical/imports.js.map +1 -0
- package/dist/tools/surgical/index.d.ts +42 -0
- package/dist/tools/surgical/index.d.ts.map +1 -0
- package/dist/tools/surgical/index.js +66 -0
- package/dist/tools/surgical/index.js.map +1 -0
- package/dist/tools/surgical/middleware.d.ts +69 -0
- package/dist/tools/surgical/middleware.d.ts.map +1 -0
- package/dist/tools/surgical/middleware.js +237 -0
- package/dist/tools/surgical/middleware.js.map +1 -0
- package/dist/tools/surgical/prevalidate.d.ts +76 -0
- package/dist/tools/surgical/prevalidate.d.ts.map +1 -0
- package/dist/tools/surgical/prevalidate.js +303 -0
- package/dist/tools/surgical/prevalidate.js.map +1 -0
- package/dist/tools/surgical/recent.d.ts +66 -0
- package/dist/tools/surgical/recent.d.ts.map +1 -0
- package/dist/tools/surgical/recent.js +238 -0
- package/dist/tools/surgical/recent.js.map +1 -0
- package/dist/tools/surgical/signature.d.ts +73 -0
- package/dist/tools/surgical/signature.d.ts.map +1 -0
- package/dist/tools/surgical/signature.js +190 -0
- package/dist/tools/surgical/signature.js.map +1 -0
- package/dist/tools/surgical/similar.d.ts +77 -0
- package/dist/tools/surgical/similar.d.ts.map +1 -0
- package/dist/tools/surgical/similar.js +285 -0
- package/dist/tools/surgical/similar.js.map +1 -0
- package/dist/tools/surgical/test-template.d.ts +70 -0
- package/dist/tools/surgical/test-template.d.ts.map +1 -0
- package/dist/tools/surgical/test-template.js +298 -0
- package/dist/tools/surgical/test-template.js.map +1 -0
- package/dist/tools/surgical/type.d.ts +69 -0
- package/dist/tools/surgical/type.d.ts.map +1 -0
- package/dist/tools/surgical/type.js +289 -0
- package/dist/tools/surgical/type.js.map +1 -0
- package/package.json +11 -11
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* drift_recent - Show Recent Changes
|
|
3
|
+
*
|
|
4
|
+
* Layer: Surgical
|
|
5
|
+
* Token Budget: 400 target, 800 max
|
|
6
|
+
* Cache TTL: 1 minute (changes frequently)
|
|
7
|
+
* Invalidation Keys: git, decisions
|
|
8
|
+
*
|
|
9
|
+
* Shows what changed recently in a specific area.
|
|
10
|
+
* Solves: AI writes code using OLD patterns because it read an old file.
|
|
11
|
+
*/
|
|
12
|
+
export interface RecentArgs {
|
|
13
|
+
/** Directory or file to check */
|
|
14
|
+
area: string;
|
|
15
|
+
/** How far back to look (default: 7) */
|
|
16
|
+
days?: number;
|
|
17
|
+
/** Filter by change type */
|
|
18
|
+
type?: 'feat' | 'fix' | 'refactor' | 'all';
|
|
19
|
+
}
|
|
20
|
+
export interface RecentChange {
|
|
21
|
+
file: string;
|
|
22
|
+
type: 'added' | 'modified' | 'deleted';
|
|
23
|
+
commitType: string;
|
|
24
|
+
summary: string;
|
|
25
|
+
date: string;
|
|
26
|
+
author: string;
|
|
27
|
+
}
|
|
28
|
+
export interface RecentData {
|
|
29
|
+
changes: RecentChange[];
|
|
30
|
+
patternsChanged: string[];
|
|
31
|
+
newConventions: string[];
|
|
32
|
+
preferFiles: string[];
|
|
33
|
+
}
|
|
34
|
+
export declare function handleRecent(args: RecentArgs, projectRoot: string): Promise<{
|
|
35
|
+
content: Array<{
|
|
36
|
+
type: string;
|
|
37
|
+
text: string;
|
|
38
|
+
}>;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* Tool definition for MCP registration
|
|
42
|
+
*/
|
|
43
|
+
export declare const recentToolDefinition: {
|
|
44
|
+
name: string;
|
|
45
|
+
description: string;
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: "object";
|
|
48
|
+
properties: {
|
|
49
|
+
area: {
|
|
50
|
+
type: string;
|
|
51
|
+
description: string;
|
|
52
|
+
};
|
|
53
|
+
days: {
|
|
54
|
+
type: string;
|
|
55
|
+
description: string;
|
|
56
|
+
};
|
|
57
|
+
type: {
|
|
58
|
+
type: string;
|
|
59
|
+
enum: string[];
|
|
60
|
+
description: string;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
required: string[];
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=recent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recent.d.ts","sourceRoot":"","sources":["../../../src/tools/surgical/recent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAYH,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,UAAU,GAAG,KAAK,CAAC;CAC5C;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAMD,wBAAsB,YAAY,CAChC,IAAI,EAAE,UAAU,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAqJ7D;AAkFD;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;CAsBhC,CAAC"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* drift_recent - Show Recent Changes
|
|
3
|
+
*
|
|
4
|
+
* Layer: Surgical
|
|
5
|
+
* Token Budget: 400 target, 800 max
|
|
6
|
+
* Cache TTL: 1 minute (changes frequently)
|
|
7
|
+
* Invalidation Keys: git, decisions
|
|
8
|
+
*
|
|
9
|
+
* Shows what changed recently in a specific area.
|
|
10
|
+
* Solves: AI writes code using OLD patterns because it read an old file.
|
|
11
|
+
*/
|
|
12
|
+
import { createResponseBuilder, Errors, metrics } from '../../infrastructure/index.js';
|
|
13
|
+
import { exec } from 'node:child_process';
|
|
14
|
+
import { promisify } from 'node:util';
|
|
15
|
+
const execAsync = promisify(exec);
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Handler
|
|
18
|
+
// ============================================================================
|
|
19
|
+
export async function handleRecent(args, projectRoot) {
|
|
20
|
+
const startTime = Date.now();
|
|
21
|
+
const builder = createResponseBuilder();
|
|
22
|
+
// Validate input
|
|
23
|
+
if (!args.area || args.area.trim() === '') {
|
|
24
|
+
throw Errors.missingParameter('area');
|
|
25
|
+
}
|
|
26
|
+
const area = args.area.trim();
|
|
27
|
+
const days = Math.min(args.days ?? 7, 30);
|
|
28
|
+
const typeFilter = args.type ?? 'all';
|
|
29
|
+
// Get git log for the area
|
|
30
|
+
const since = `${days}.days.ago`;
|
|
31
|
+
try {
|
|
32
|
+
// Get commits affecting the area
|
|
33
|
+
const { stdout: logOutput } = await execAsync(`git log --since="${since}" --pretty=format:"%H|%s|%an|%ai" --name-status -- "${area}"`, { cwd: projectRoot, maxBuffer: 1024 * 1024 });
|
|
34
|
+
if (!logOutput.trim()) {
|
|
35
|
+
const data = {
|
|
36
|
+
changes: [],
|
|
37
|
+
patternsChanged: [],
|
|
38
|
+
newConventions: [],
|
|
39
|
+
preferFiles: [],
|
|
40
|
+
};
|
|
41
|
+
return builder
|
|
42
|
+
.withSummary(`No changes in "${area}" in the last ${days} days`)
|
|
43
|
+
.withData(data)
|
|
44
|
+
.withHints({
|
|
45
|
+
nextActions: ['Area is stable - existing code is current', 'Use drift_similar to find examples'],
|
|
46
|
+
relatedTools: ['drift_similar', 'drift_code_examples'],
|
|
47
|
+
})
|
|
48
|
+
.buildContent();
|
|
49
|
+
}
|
|
50
|
+
// Parse git log output
|
|
51
|
+
const changes = [];
|
|
52
|
+
const lines = logOutput.split('\n');
|
|
53
|
+
let currentCommit = null;
|
|
54
|
+
for (const line of lines) {
|
|
55
|
+
if (line.includes('|')) {
|
|
56
|
+
// Commit line
|
|
57
|
+
const [hash, message, author, date] = line.split('|');
|
|
58
|
+
currentCommit = {
|
|
59
|
+
hash: hash ?? '',
|
|
60
|
+
message: message ?? '',
|
|
61
|
+
author: author ?? '',
|
|
62
|
+
date: date?.split(' ')[0] ?? '',
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
else if (line.trim() && currentCommit) {
|
|
66
|
+
// File change line (A/M/D followed by filename)
|
|
67
|
+
const match = line.match(/^([AMD])\t(.+)$/);
|
|
68
|
+
if (match) {
|
|
69
|
+
const [, status, file] = match;
|
|
70
|
+
// Parse conventional commit type
|
|
71
|
+
const commitType = parseCommitType(currentCommit.message);
|
|
72
|
+
// Apply type filter
|
|
73
|
+
if (typeFilter !== 'all' && commitType !== typeFilter) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
changes.push({
|
|
77
|
+
file: file ?? '',
|
|
78
|
+
type: status === 'A' ? 'added' : status === 'D' ? 'deleted' : 'modified',
|
|
79
|
+
commitType,
|
|
80
|
+
summary: currentCommit.message.slice(0, 80),
|
|
81
|
+
date: currentCommit.date,
|
|
82
|
+
author: currentCommit.author,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Deduplicate by file (keep most recent)
|
|
88
|
+
const byFile = new Map();
|
|
89
|
+
for (const change of changes) {
|
|
90
|
+
if (!byFile.has(change.file)) {
|
|
91
|
+
byFile.set(change.file, change);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const uniqueChanges = Array.from(byFile.values()).slice(0, 15);
|
|
95
|
+
// Analyze patterns changed
|
|
96
|
+
const patternsChanged = analyzePatternChanges(uniqueChanges);
|
|
97
|
+
// Detect new conventions
|
|
98
|
+
const newConventions = detectNewConventions(uniqueChanges);
|
|
99
|
+
// Files to prefer (recently modified = more current)
|
|
100
|
+
const preferFiles = uniqueChanges
|
|
101
|
+
.filter(c => c.type === 'modified' && c.commitType !== 'fix')
|
|
102
|
+
.map(c => c.file)
|
|
103
|
+
.slice(0, 5);
|
|
104
|
+
const data = {
|
|
105
|
+
changes: uniqueChanges,
|
|
106
|
+
patternsChanged,
|
|
107
|
+
newConventions,
|
|
108
|
+
preferFiles,
|
|
109
|
+
};
|
|
110
|
+
// Build summary
|
|
111
|
+
const summary = `${uniqueChanges.length} change${uniqueChanges.length !== 1 ? 's' : ''} in "${area}" over last ${days} days. ${preferFiles.length} files recommended as current examples.`;
|
|
112
|
+
// Build hints
|
|
113
|
+
const hints = {
|
|
114
|
+
nextActions: preferFiles.length > 0
|
|
115
|
+
? [
|
|
116
|
+
`Use "${preferFiles[0]}" as a reference - it's recently updated`,
|
|
117
|
+
'Check patternsChanged for any migration notes',
|
|
118
|
+
]
|
|
119
|
+
: [
|
|
120
|
+
'No recent modifications - existing patterns are stable',
|
|
121
|
+
'Use drift_similar to find examples',
|
|
122
|
+
],
|
|
123
|
+
relatedTools: ['drift_similar', 'drift_signature', 'drift_code_examples'],
|
|
124
|
+
};
|
|
125
|
+
if (patternsChanged.length > 0) {
|
|
126
|
+
hints.warnings = [`Patterns changed recently: ${patternsChanged.join(', ')}`];
|
|
127
|
+
}
|
|
128
|
+
// Record metrics
|
|
129
|
+
metrics.recordRequest('drift_recent', Date.now() - startTime, true, false);
|
|
130
|
+
return builder
|
|
131
|
+
.withSummary(summary)
|
|
132
|
+
.withData(data)
|
|
133
|
+
.withHints(hints)
|
|
134
|
+
.buildContent();
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
// Git command failed - might not be a git repo
|
|
138
|
+
throw Errors.custom('GIT_ERROR', 'Failed to read git history. Ensure this is a git repository.', ['drift_status']);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// ============================================================================
|
|
142
|
+
// Helpers
|
|
143
|
+
// ============================================================================
|
|
144
|
+
/**
|
|
145
|
+
* Parse conventional commit type from message
|
|
146
|
+
*/
|
|
147
|
+
function parseCommitType(message) {
|
|
148
|
+
const match = message.match(/^(feat|fix|refactor|chore|docs|test|style|perf|ci|build)(\(.+\))?:/i);
|
|
149
|
+
if (match) {
|
|
150
|
+
return match[1].toLowerCase();
|
|
151
|
+
}
|
|
152
|
+
// Fallback heuristics
|
|
153
|
+
const lower = message.toLowerCase();
|
|
154
|
+
if (lower.includes('fix') || lower.includes('bug'))
|
|
155
|
+
return 'fix';
|
|
156
|
+
if (lower.includes('add') || lower.includes('new') || lower.includes('implement'))
|
|
157
|
+
return 'feat';
|
|
158
|
+
if (lower.includes('refactor') || lower.includes('clean') || lower.includes('improve'))
|
|
159
|
+
return 'refactor';
|
|
160
|
+
return 'other';
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Analyze which patterns might have changed
|
|
164
|
+
*/
|
|
165
|
+
function analyzePatternChanges(changes) {
|
|
166
|
+
const patterns = [];
|
|
167
|
+
for (const change of changes) {
|
|
168
|
+
const msg = change.summary.toLowerCase();
|
|
169
|
+
// Look for pattern-related keywords
|
|
170
|
+
if (msg.includes('error') || msg.includes('exception')) {
|
|
171
|
+
patterns.push('error-handling');
|
|
172
|
+
}
|
|
173
|
+
if (msg.includes('auth') || msg.includes('permission')) {
|
|
174
|
+
patterns.push('auth');
|
|
175
|
+
}
|
|
176
|
+
if (msg.includes('api') || msg.includes('endpoint')) {
|
|
177
|
+
patterns.push('api');
|
|
178
|
+
}
|
|
179
|
+
if (msg.includes('test')) {
|
|
180
|
+
patterns.push('testing');
|
|
181
|
+
}
|
|
182
|
+
if (msg.includes('style') || msg.includes('css') || msg.includes('theme')) {
|
|
183
|
+
patterns.push('styling');
|
|
184
|
+
}
|
|
185
|
+
if (msg.includes('migrat') || msg.includes('deprecat')) {
|
|
186
|
+
patterns.push('migration');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Deduplicate
|
|
190
|
+
return [...new Set(patterns)];
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Detect new conventions from commit messages
|
|
194
|
+
*/
|
|
195
|
+
function detectNewConventions(changes) {
|
|
196
|
+
const conventions = [];
|
|
197
|
+
for (const change of changes) {
|
|
198
|
+
const msg = change.summary.toLowerCase();
|
|
199
|
+
// Look for convention-related keywords
|
|
200
|
+
if (msg.includes('migrat') && msg.includes('to')) {
|
|
201
|
+
conventions.push(change.summary);
|
|
202
|
+
}
|
|
203
|
+
if (msg.includes('switch') || msg.includes('replace')) {
|
|
204
|
+
conventions.push(change.summary);
|
|
205
|
+
}
|
|
206
|
+
if (msg.includes('new pattern') || msg.includes('introduce')) {
|
|
207
|
+
conventions.push(change.summary);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return conventions.slice(0, 3);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Tool definition for MCP registration
|
|
214
|
+
*/
|
|
215
|
+
export const recentToolDefinition = {
|
|
216
|
+
name: 'drift_recent',
|
|
217
|
+
description: 'Show what changed recently in a specific area. Returns recent commits, pattern changes, and files to prefer as current examples. Use to avoid writing code based on outdated patterns.',
|
|
218
|
+
inputSchema: {
|
|
219
|
+
type: 'object',
|
|
220
|
+
properties: {
|
|
221
|
+
area: {
|
|
222
|
+
type: 'string',
|
|
223
|
+
description: 'Directory or file to check (e.g., "src/api/", "src/services/user.ts")',
|
|
224
|
+
},
|
|
225
|
+
days: {
|
|
226
|
+
type: 'number',
|
|
227
|
+
description: 'How far back to look (default: 7, max: 30)',
|
|
228
|
+
},
|
|
229
|
+
type: {
|
|
230
|
+
type: 'string',
|
|
231
|
+
enum: ['feat', 'fix', 'refactor', 'all'],
|
|
232
|
+
description: 'Filter by commit type (default: all)',
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
required: ['area'],
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
//# sourceMappingURL=recent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recent.js","sourceRoot":"","sources":["../../../src/tools/surgical/recent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* drift_signature - Get Function/Class Signatures
|
|
3
|
+
*
|
|
4
|
+
* Layer: Surgical
|
|
5
|
+
* Token Budget: 200 target, 500 max
|
|
6
|
+
* Cache TTL: 5 minutes
|
|
7
|
+
* Invalidation Keys: callgraph, file:{path}
|
|
8
|
+
*
|
|
9
|
+
* Returns just the signature without reading entire files.
|
|
10
|
+
* Solves: AI reads 500-line files just to see a 1-line signature.
|
|
11
|
+
*/
|
|
12
|
+
import type { CallGraphStore } from 'driftdetect-core';
|
|
13
|
+
export interface SignatureArgs {
|
|
14
|
+
/** Symbol to look up (function, method, class name) */
|
|
15
|
+
symbol: string;
|
|
16
|
+
/** Optional: specific file to search in */
|
|
17
|
+
file?: string;
|
|
18
|
+
/** Include JSDoc/docstring? (default: true) */
|
|
19
|
+
includeDocs?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface SignatureInfo {
|
|
22
|
+
file: string;
|
|
23
|
+
line: number;
|
|
24
|
+
kind: 'function' | 'method' | 'class' | 'interface' | 'type';
|
|
25
|
+
signature: string;
|
|
26
|
+
parameters?: Array<{
|
|
27
|
+
name: string;
|
|
28
|
+
type: string;
|
|
29
|
+
required: boolean;
|
|
30
|
+
default?: string | undefined;
|
|
31
|
+
}>;
|
|
32
|
+
returnType?: string | undefined;
|
|
33
|
+
docs?: string | undefined;
|
|
34
|
+
exported: boolean;
|
|
35
|
+
className?: string | undefined;
|
|
36
|
+
decorators?: string[] | undefined;
|
|
37
|
+
}
|
|
38
|
+
export interface SignatureData {
|
|
39
|
+
found: boolean;
|
|
40
|
+
signatures: SignatureInfo[];
|
|
41
|
+
}
|
|
42
|
+
export declare function handleSignature(store: CallGraphStore, args: SignatureArgs): Promise<{
|
|
43
|
+
content: Array<{
|
|
44
|
+
type: string;
|
|
45
|
+
text: string;
|
|
46
|
+
}>;
|
|
47
|
+
}>;
|
|
48
|
+
/**
|
|
49
|
+
* Tool definition for MCP registration
|
|
50
|
+
*/
|
|
51
|
+
export declare const signatureToolDefinition: {
|
|
52
|
+
name: string;
|
|
53
|
+
description: string;
|
|
54
|
+
inputSchema: {
|
|
55
|
+
type: "object";
|
|
56
|
+
properties: {
|
|
57
|
+
symbol: {
|
|
58
|
+
type: string;
|
|
59
|
+
description: string;
|
|
60
|
+
};
|
|
61
|
+
file: {
|
|
62
|
+
type: string;
|
|
63
|
+
description: string;
|
|
64
|
+
};
|
|
65
|
+
includeDocs: {
|
|
66
|
+
type: string;
|
|
67
|
+
description: string;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
required: string[];
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=signature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../../../src/tools/surgical/signature.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,kBAAkB,CAAC;AAOrE,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,WAAW,GAAG,MAAM,CAAC;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,KAAK,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAC9B,CAAC,CAAC;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAMD,wBAAsB,eAAe,CACnC,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CA4H7D;AAwDD;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;CAqBnC,CAAC"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* drift_signature - Get Function/Class Signatures
|
|
3
|
+
*
|
|
4
|
+
* Layer: Surgical
|
|
5
|
+
* Token Budget: 200 target, 500 max
|
|
6
|
+
* Cache TTL: 5 minutes
|
|
7
|
+
* Invalidation Keys: callgraph, file:{path}
|
|
8
|
+
*
|
|
9
|
+
* Returns just the signature without reading entire files.
|
|
10
|
+
* Solves: AI reads 500-line files just to see a 1-line signature.
|
|
11
|
+
*/
|
|
12
|
+
import { createResponseBuilder, Errors, metrics } from '../../infrastructure/index.js';
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Handler
|
|
15
|
+
// ============================================================================
|
|
16
|
+
export async function handleSignature(store, args) {
|
|
17
|
+
const startTime = Date.now();
|
|
18
|
+
const builder = createResponseBuilder();
|
|
19
|
+
// Validate input
|
|
20
|
+
if (!args.symbol || args.symbol.trim() === '') {
|
|
21
|
+
throw Errors.missingParameter('symbol');
|
|
22
|
+
}
|
|
23
|
+
const symbol = args.symbol.trim();
|
|
24
|
+
// includeDocs reserved for future use
|
|
25
|
+
// const includeDocs = args.includeDocs !== false;
|
|
26
|
+
// Load call graph
|
|
27
|
+
await store.initialize();
|
|
28
|
+
const graph = store.getGraph();
|
|
29
|
+
if (!graph) {
|
|
30
|
+
throw Errors.custom('CALLGRAPH_NOT_BUILT', 'Call graph has not been built. Run "drift callgraph build" first.', ['drift_status']);
|
|
31
|
+
}
|
|
32
|
+
// Find matching functions
|
|
33
|
+
const matches = [];
|
|
34
|
+
for (const [, func] of graph.functions) {
|
|
35
|
+
// Match by name or qualified name
|
|
36
|
+
const nameMatch = func.name === symbol ||
|
|
37
|
+
func.qualifiedName === symbol ||
|
|
38
|
+
func.qualifiedName.endsWith(`.${symbol}`);
|
|
39
|
+
// If file specified, filter by file
|
|
40
|
+
const fileMatch = !args.file ||
|
|
41
|
+
func.file === args.file ||
|
|
42
|
+
func.file.endsWith(args.file);
|
|
43
|
+
if (nameMatch && fileMatch) {
|
|
44
|
+
matches.push(func);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Build signatures
|
|
48
|
+
const signatures = matches.map(func => {
|
|
49
|
+
const sig = buildSignature(func);
|
|
50
|
+
return {
|
|
51
|
+
file: func.file,
|
|
52
|
+
line: func.startLine,
|
|
53
|
+
kind: func.className ? 'method' : 'function',
|
|
54
|
+
signature: sig,
|
|
55
|
+
parameters: func.parameters.map(p => ({
|
|
56
|
+
name: p.name,
|
|
57
|
+
type: p.type || 'unknown',
|
|
58
|
+
required: !p.hasDefault,
|
|
59
|
+
default: p.hasDefault ? '...' : undefined,
|
|
60
|
+
})),
|
|
61
|
+
returnType: func.returnType,
|
|
62
|
+
exported: func.isExported,
|
|
63
|
+
className: func.className,
|
|
64
|
+
decorators: func.decorators.length > 0 ? func.decorators : undefined,
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
// Sort by relevance: exact name match first, then exported, then by file
|
|
68
|
+
signatures.sort((a, b) => {
|
|
69
|
+
// Exact name match
|
|
70
|
+
const aExact = a.signature.includes(` ${symbol}(`) ? 0 : 1;
|
|
71
|
+
const bExact = b.signature.includes(` ${symbol}(`) ? 0 : 1;
|
|
72
|
+
if (aExact !== bExact)
|
|
73
|
+
return aExact - bExact;
|
|
74
|
+
// Exported first
|
|
75
|
+
if (a.exported !== b.exported)
|
|
76
|
+
return a.exported ? -1 : 1;
|
|
77
|
+
// Alphabetical by file
|
|
78
|
+
return a.file.localeCompare(b.file);
|
|
79
|
+
});
|
|
80
|
+
// Limit results
|
|
81
|
+
const limitedSignatures = signatures.slice(0, 5);
|
|
82
|
+
const data = {
|
|
83
|
+
found: limitedSignatures.length > 0,
|
|
84
|
+
signatures: limitedSignatures,
|
|
85
|
+
};
|
|
86
|
+
// Build summary
|
|
87
|
+
let summary;
|
|
88
|
+
if (limitedSignatures.length === 0) {
|
|
89
|
+
summary = `No signature found for "${symbol}"`;
|
|
90
|
+
}
|
|
91
|
+
else if (limitedSignatures.length === 1) {
|
|
92
|
+
const sig = limitedSignatures[0];
|
|
93
|
+
summary = `Found ${sig.kind} "${symbol}" in ${sig.file}:${sig.line}`;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
summary = `Found ${limitedSignatures.length} matches for "${symbol}"`;
|
|
97
|
+
}
|
|
98
|
+
// Build hints
|
|
99
|
+
const hints = {
|
|
100
|
+
nextActions: limitedSignatures.length > 0
|
|
101
|
+
? [
|
|
102
|
+
`Use drift_callers to see who calls "${symbol}"`,
|
|
103
|
+
`Use drift_imports to get correct import statement`,
|
|
104
|
+
]
|
|
105
|
+
: [
|
|
106
|
+
'Check spelling or try a partial name',
|
|
107
|
+
'Use drift_files_list to find relevant files',
|
|
108
|
+
],
|
|
109
|
+
relatedTools: ['drift_callers', 'drift_imports', 'drift_type'],
|
|
110
|
+
};
|
|
111
|
+
if (signatures.length > 5) {
|
|
112
|
+
hints.warnings = [`${signatures.length - 5} additional matches not shown. Specify file to narrow results.`];
|
|
113
|
+
}
|
|
114
|
+
// Record metrics
|
|
115
|
+
metrics.recordRequest('drift_signature', Date.now() - startTime, true, false);
|
|
116
|
+
return builder
|
|
117
|
+
.withSummary(summary)
|
|
118
|
+
.withData(data)
|
|
119
|
+
.withHints(hints)
|
|
120
|
+
.buildContent();
|
|
121
|
+
}
|
|
122
|
+
// ============================================================================
|
|
123
|
+
// Helpers
|
|
124
|
+
// ============================================================================
|
|
125
|
+
/**
|
|
126
|
+
* Build a human-readable signature string
|
|
127
|
+
*/
|
|
128
|
+
function buildSignature(func) {
|
|
129
|
+
const parts = [];
|
|
130
|
+
// Decorators (first one only for brevity)
|
|
131
|
+
if (func.decorators.length > 0) {
|
|
132
|
+
parts.push(`@${func.decorators[0]}`);
|
|
133
|
+
}
|
|
134
|
+
// Export keyword
|
|
135
|
+
if (func.isExported) {
|
|
136
|
+
parts.push('export');
|
|
137
|
+
}
|
|
138
|
+
// Async keyword
|
|
139
|
+
if (func.isAsync) {
|
|
140
|
+
parts.push('async');
|
|
141
|
+
}
|
|
142
|
+
// Function keyword
|
|
143
|
+
parts.push('function');
|
|
144
|
+
// Name
|
|
145
|
+
parts.push(func.name);
|
|
146
|
+
// Parameters
|
|
147
|
+
const params = func.parameters.map(p => {
|
|
148
|
+
let param = p.name;
|
|
149
|
+
if (p.type) {
|
|
150
|
+
param += `: ${p.type}`;
|
|
151
|
+
}
|
|
152
|
+
if (p.hasDefault) {
|
|
153
|
+
param += ' = ...';
|
|
154
|
+
}
|
|
155
|
+
return param;
|
|
156
|
+
}).join(', ');
|
|
157
|
+
// Build signature
|
|
158
|
+
let sig = parts.join(' ') + `(${params})`;
|
|
159
|
+
// Return type
|
|
160
|
+
if (func.returnType) {
|
|
161
|
+
sig += `: ${func.returnType}`;
|
|
162
|
+
}
|
|
163
|
+
return sig;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Tool definition for MCP registration
|
|
167
|
+
*/
|
|
168
|
+
export const signatureToolDefinition = {
|
|
169
|
+
name: 'drift_signature',
|
|
170
|
+
description: 'Get function/class signature without reading entire files. Returns signature, parameters, return type, and location. Use when you need to know a function\'s interface.',
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: 'object',
|
|
173
|
+
properties: {
|
|
174
|
+
symbol: {
|
|
175
|
+
type: 'string',
|
|
176
|
+
description: 'Function, method, or class name to look up',
|
|
177
|
+
},
|
|
178
|
+
file: {
|
|
179
|
+
type: 'string',
|
|
180
|
+
description: 'Optional: specific file to search in (relative path)',
|
|
181
|
+
},
|
|
182
|
+
includeDocs: {
|
|
183
|
+
type: 'boolean',
|
|
184
|
+
description: 'Include JSDoc/docstring (default: true)',
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
required: ['symbol'],
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
//# sourceMappingURL=signature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature.js","sourceRoot":"","sources":["../../../src/tools/surgical/signature.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* drift_similar - Find Semantically Similar Code
|
|
3
|
+
*
|
|
4
|
+
* Layer: Surgical
|
|
5
|
+
* Token Budget: 500 target, 1000 max
|
|
6
|
+
* Cache TTL: 5 minutes
|
|
7
|
+
* Invalidation Keys: patterns, callgraph
|
|
8
|
+
*
|
|
9
|
+
* Finds code semantically similar to what the AI is about to write.
|
|
10
|
+
* Solves: AI needs to see an example but there are 50 options. Which is most relevant?
|
|
11
|
+
*/
|
|
12
|
+
import type { CallGraphStore, PatternStore } from 'driftdetect-core';
|
|
13
|
+
export interface SimilarArgs {
|
|
14
|
+
/** What kind of code are you writing? */
|
|
15
|
+
intent: 'api_endpoint' | 'service' | 'component' | 'hook' | 'utility' | 'test' | 'middleware';
|
|
16
|
+
/** Natural language description */
|
|
17
|
+
description: string;
|
|
18
|
+
/** Optional: limit to specific directory */
|
|
19
|
+
scope?: string;
|
|
20
|
+
/** Max results (default: 3) */
|
|
21
|
+
limit?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface SimilarMatch {
|
|
24
|
+
file: string;
|
|
25
|
+
function?: string | undefined;
|
|
26
|
+
class?: string | undefined;
|
|
27
|
+
similarity: number;
|
|
28
|
+
reason: string;
|
|
29
|
+
preview: string;
|
|
30
|
+
patterns: string[];
|
|
31
|
+
}
|
|
32
|
+
export interface SimilarConventions {
|
|
33
|
+
naming: string;
|
|
34
|
+
errorHandling: string;
|
|
35
|
+
imports: string;
|
|
36
|
+
}
|
|
37
|
+
export interface SimilarData {
|
|
38
|
+
matches: SimilarMatch[];
|
|
39
|
+
conventions: SimilarConventions;
|
|
40
|
+
}
|
|
41
|
+
export declare function handleSimilar(callGraphStore: CallGraphStore, patternStore: PatternStore, args: SimilarArgs): Promise<{
|
|
42
|
+
content: Array<{
|
|
43
|
+
type: string;
|
|
44
|
+
text: string;
|
|
45
|
+
}>;
|
|
46
|
+
}>;
|
|
47
|
+
/**
|
|
48
|
+
* Tool definition for MCP registration
|
|
49
|
+
*/
|
|
50
|
+
export declare const similarToolDefinition: {
|
|
51
|
+
name: string;
|
|
52
|
+
description: string;
|
|
53
|
+
inputSchema: {
|
|
54
|
+
type: "object";
|
|
55
|
+
properties: {
|
|
56
|
+
intent: {
|
|
57
|
+
type: string;
|
|
58
|
+
enum: string[];
|
|
59
|
+
description: string;
|
|
60
|
+
};
|
|
61
|
+
description: {
|
|
62
|
+
type: string;
|
|
63
|
+
description: string;
|
|
64
|
+
};
|
|
65
|
+
scope: {
|
|
66
|
+
type: string;
|
|
67
|
+
description: string;
|
|
68
|
+
};
|
|
69
|
+
limit: {
|
|
70
|
+
type: string;
|
|
71
|
+
description: string;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
required: string[];
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=similar.d.ts.map
|