@mrclrchtr/supi-code-intelligence 1.6.0 → 1.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/README.md +42 -24
- package/node_modules/@mrclrchtr/supi-core/package.json +6 -2
- package/node_modules/@mrclrchtr/supi-core/src/api.ts +12 -1
- package/node_modules/@mrclrchtr/supi-core/src/config/config.ts +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/index.ts +12 -1
- package/node_modules/@mrclrchtr/supi-core/src/tool-framework.ts +116 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +6 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/api.ts +12 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config/config.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/index.ts +12 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/tool-framework.ts +116 -0
- package/node_modules/@mrclrchtr/supi-lsp/package.json +9 -3
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +8 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +79 -190
- package/node_modules/@mrclrchtr/supi-lsp/src/config/server-config.ts +38 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/config/types.ts +61 -387
- package/node_modules/@mrclrchtr/supi-lsp/src/format.ts +16 -8
- package/node_modules/@mrclrchtr/supi-lsp/src/lsp.ts +2 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-project-info.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/session/lsp-state.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/guidance.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/tool-specs.ts +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +6 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/api.ts +12 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config.ts +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/index.ts +12 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/tool-framework.ts +116 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/LICENSE +21 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/README.md +265 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.cjs +4661 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.cjs.map +7 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.js +4605 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.js.map +7 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm +0 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm.map +57 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/package.json +100 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.cjs +4063 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.cjs.map +7 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.cts +1025 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.cts.map +58 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.ts +1025 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.ts.map +58 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.js +4007 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.js.map +7 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm +0 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm.map +55 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +2 -2
- package/package.json +4 -4
- package/src/actions/affected-action.ts +67 -54
- package/src/actions/brief-action.ts +142 -5
- package/src/actions/callees-action.ts +1 -1
- package/src/actions/callers-action.ts +38 -67
- package/src/actions/implementations-action.ts +27 -63
- package/src/actions/map-action.ts +206 -0
- package/src/actions/pattern-action.ts +1 -1
- package/src/api.ts +1 -0
- package/src/brief-focused.ts +5 -5
- package/src/brief.ts +3 -3
- package/src/code-intelligence.ts +6 -75
- package/src/index.ts +1 -0
- package/src/pattern-structured.ts +1 -1
- package/src/prioritization-signals.ts +13 -26
- package/src/query-params.ts +15 -0
- package/src/resolve-target.ts +2 -2
- package/src/search-helpers.ts +2 -2
- package/src/target-resolution.ts +27 -102
- package/src/tool/execute-affected.ts +25 -0
- package/src/tool/execute-brief.ts +25 -0
- package/src/tool/execute-map.ts +32 -0
- package/src/tool/execute-pattern.ts +26 -0
- package/src/tool/execute-relations.ts +48 -0
- package/src/tool/guidance.ts +24 -13
- package/src/tool/register-tools.ts +32 -0
- package/src/tool/tool-specs.ts +184 -0
- package/src/tool/validation.ts +43 -0
- package/src/types.ts +10 -0
- package/src/actions/index-action.ts +0 -187
- package/src/tool/action-specs.ts +0 -66
- package/src/tool-actions.ts +0 -100
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-tree-sitter",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "SuPi Tree-sitter extension — structural AST analysis for pi",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"web-tree-sitter": "^0.26.8",
|
|
27
|
-
"@mrclrchtr/supi-core": "1.
|
|
27
|
+
"@mrclrchtr/supi-core": "1.7.0"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"@earendil-works/pi-ai": "*",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-code-intelligence",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "SuPi Code Intelligence extension — architecture briefs, caller/callee analysis, impact assessment, and pattern search for pi",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"src/**/*.ts"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@mrclrchtr/supi-core": "1.
|
|
23
|
-
"@mrclrchtr/supi-
|
|
24
|
-
"@mrclrchtr/supi-
|
|
22
|
+
"@mrclrchtr/supi-core": "1.7.0",
|
|
23
|
+
"@mrclrchtr/supi-tree-sitter": "1.7.0",
|
|
24
|
+
"@mrclrchtr/supi-lsp": "1.7.0"
|
|
25
25
|
},
|
|
26
26
|
"bundledDependencies": [
|
|
27
27
|
"@mrclrchtr/supi-core",
|
|
@@ -8,22 +8,15 @@ import {
|
|
|
8
8
|
summarizePrioritySignalsForFiles,
|
|
9
9
|
} from "../prioritization-signals.ts";
|
|
10
10
|
import { getSemanticService } from "../providers/semantic-provider.ts";
|
|
11
|
+
import type { CodeQueryParams as ActionParams } from "../query-params.ts";
|
|
11
12
|
import { resolveTarget } from "../resolve-target.ts";
|
|
12
|
-
import {
|
|
13
|
-
escapeRegex,
|
|
14
|
-
filterOutDeclaration,
|
|
15
|
-
isInProjectPath,
|
|
16
|
-
normalizePath,
|
|
17
|
-
runRipgrep,
|
|
18
|
-
uriToFile,
|
|
19
|
-
} from "../search-helpers.ts";
|
|
13
|
+
import { filterOutDeclaration, isInProjectPath, uriToFile } from "../search-helpers.ts";
|
|
20
14
|
import {
|
|
21
15
|
dedupeFileLineRefs,
|
|
22
16
|
highestConfidence,
|
|
23
17
|
isResolvedTargetGroup,
|
|
24
18
|
} from "../semantic-action-helpers.ts";
|
|
25
19
|
import type { ResolvedTarget, ResolvedTargetGroup } from "../target-resolution.ts";
|
|
26
|
-
import type { ActionParams } from "../tool-actions.ts";
|
|
27
20
|
import type { AffectedDetails, CodeIntelResult, ConfidenceMode } from "../types.ts";
|
|
28
21
|
|
|
29
22
|
export async function executeAffectedAction(
|
|
@@ -89,7 +82,15 @@ async function executeSingleAffected(
|
|
|
89
82
|
cwd,
|
|
90
83
|
analysis.affectedFiles.size > 0 ? [...analysis.affectedFiles] : [target.file],
|
|
91
84
|
);
|
|
92
|
-
const content = formatAffectedOutput(
|
|
85
|
+
const content = formatAffectedOutput(
|
|
86
|
+
symbolName,
|
|
87
|
+
refs,
|
|
88
|
+
analysis,
|
|
89
|
+
params,
|
|
90
|
+
prioritySignals,
|
|
91
|
+
target,
|
|
92
|
+
cwd,
|
|
93
|
+
);
|
|
93
94
|
const details: AffectedDetails = {
|
|
94
95
|
confidence: analysis.confidence,
|
|
95
96
|
directCount: refs.refs.length,
|
|
@@ -98,10 +99,7 @@ async function executeSingleAffected(
|
|
|
98
99
|
checkNext: analysis.checkNext,
|
|
99
100
|
likelyTests: analysis.likelyTests,
|
|
100
101
|
omittedCount: computeOmittedCount(analysis.externalRefs, analysis.affectedFiles.size, params),
|
|
101
|
-
nextQueries:
|
|
102
|
-
"`code_intel brief` on the most-affected module for deeper context",
|
|
103
|
-
`\`code_intel callers\` with \`symbol: "${symbolName}"\` for grouped call-site detail`,
|
|
104
|
-
],
|
|
102
|
+
nextQueries: buildAffectedNextQueries(target, symbolName, cwd),
|
|
105
103
|
prioritySignals,
|
|
106
104
|
};
|
|
107
105
|
return { content, details: { type: "affected" as const, data: details } };
|
|
@@ -160,7 +158,7 @@ async function executeFileLevelAffected(
|
|
|
160
158
|
addCheckNextSection(lines, analysis.checkNext);
|
|
161
159
|
addTestsSection(lines, analysis.likelyTests);
|
|
162
160
|
lines.push("## Next");
|
|
163
|
-
lines.push("- `
|
|
161
|
+
lines.push("- `code_brief` on the most-affected module for deeper context");
|
|
164
162
|
lines.push("- Use `file` + coordinates to inspect one exported target precisely");
|
|
165
163
|
lines.push("");
|
|
166
164
|
|
|
@@ -173,7 +171,7 @@ async function executeFileLevelAffected(
|
|
|
173
171
|
likelyTests: analysis.likelyTests,
|
|
174
172
|
omittedCount: computeOmittedCount(analysis.externalRefs, analysis.affectedFiles.size, params),
|
|
175
173
|
nextQueries: [
|
|
176
|
-
"`
|
|
174
|
+
"`code_brief` on the most-affected module for deeper context",
|
|
177
175
|
"Use `file` + coordinates to inspect one exported target precisely",
|
|
178
176
|
],
|
|
179
177
|
prioritySignals,
|
|
@@ -182,45 +180,40 @@ async function executeFileLevelAffected(
|
|
|
182
180
|
return { content: lines.join("\n"), details: { type: "affected" as const, data: details } };
|
|
183
181
|
}
|
|
184
182
|
|
|
185
|
-
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: multi-source reference gathering with fallback logic
|
|
186
183
|
async function gatherReferences(
|
|
187
184
|
target: ResolvedTarget,
|
|
188
|
-
|
|
185
|
+
_params: ActionParams,
|
|
189
186
|
cwd: string,
|
|
190
187
|
): Promise<{ refs: GatheredRef[]; confidence: ConfidenceMode; externalCount: number }> {
|
|
191
188
|
const lsp = await getSemanticService(cwd, { waitForReady: true });
|
|
189
|
+
if (!lsp) {
|
|
190
|
+
return { refs: [], confidence: "unavailable", externalCount: 0 };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const lspRefs = await lsp.references(target.file, target.position);
|
|
194
|
+
if (lspRefs === null) {
|
|
195
|
+
return { refs: [], confidence: "unavailable", externalCount: 0 };
|
|
196
|
+
}
|
|
197
|
+
|
|
192
198
|
const refs: GatheredRef[] = [];
|
|
193
199
|
let externalCount = 0;
|
|
200
|
+
const filtered = filterOutDeclaration(lspRefs, target.file, target.position);
|
|
194
201
|
|
|
195
|
-
|
|
196
|
-
const
|
|
197
|
-
if (
|
|
198
|
-
|
|
199
|
-
for (const ref of filtered) {
|
|
200
|
-
const filePath = uriToFile(ref.uri);
|
|
201
|
-
if (isInProjectPath(filePath, cwd)) {
|
|
202
|
-
refs.push({ file: path.relative(cwd, filePath), line: ref.range.start.line + 1 });
|
|
203
|
-
} else {
|
|
204
|
-
externalCount++;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return { refs, confidence: "semantic", externalCount };
|
|
202
|
+
for (const ref of lspRefs) {
|
|
203
|
+
const filePath = uriToFile(ref.uri);
|
|
204
|
+
if (!isInProjectPath(filePath, cwd)) {
|
|
205
|
+
externalCount++;
|
|
208
206
|
}
|
|
209
207
|
}
|
|
210
208
|
|
|
211
|
-
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
for (const m of matches) {
|
|
216
|
-
if (!isDeclarationMatch(m.file, m.line, target, cwd)) {
|
|
217
|
-
refs.push({ file: path.relative(cwd, path.resolve(cwd, m.file)), line: m.line });
|
|
218
|
-
}
|
|
209
|
+
for (const ref of filtered) {
|
|
210
|
+
const filePath = uriToFile(ref.uri);
|
|
211
|
+
if (isInProjectPath(filePath, cwd)) {
|
|
212
|
+
refs.push({ file: path.relative(cwd, filePath), line: ref.range.start.line + 1 });
|
|
219
213
|
}
|
|
220
|
-
return { refs, confidence: "heuristic", externalCount: 0 };
|
|
221
214
|
}
|
|
222
215
|
|
|
223
|
-
return { refs, confidence: "
|
|
216
|
+
return { refs, confidence: "semantic", externalCount };
|
|
224
217
|
}
|
|
225
218
|
|
|
226
219
|
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: impact analysis with downstream module traversal
|
|
@@ -303,6 +296,8 @@ function formatAffectedOutput(
|
|
|
303
296
|
analysis: ImpactAnalysis,
|
|
304
297
|
params: ActionParams,
|
|
305
298
|
prioritySignals: import("../prioritization-signals.ts").PrioritySignalsSummary | null,
|
|
299
|
+
target: ResolvedTarget,
|
|
300
|
+
cwd: string,
|
|
306
301
|
): string {
|
|
307
302
|
const totalRefs = result.refs.length + analysis.externalRefs;
|
|
308
303
|
const lines: string[] = [];
|
|
@@ -328,7 +323,12 @@ function formatAffectedOutput(
|
|
|
328
323
|
appendPrioritySignalsSection(lines, prioritySignals);
|
|
329
324
|
addCheckNextSection(lines, analysis.checkNext);
|
|
330
325
|
addTestsSection(lines, analysis.likelyTests);
|
|
331
|
-
addAffectedNextQueries(lines,
|
|
326
|
+
addAffectedNextQueries(lines, {
|
|
327
|
+
target,
|
|
328
|
+
symbolName,
|
|
329
|
+
showBriefQuery: analysis.checkNext.length > 0,
|
|
330
|
+
cwd,
|
|
331
|
+
});
|
|
332
332
|
|
|
333
333
|
return lines.join("\n");
|
|
334
334
|
}
|
|
@@ -416,24 +416,37 @@ function formatFileLevelAffectedHeader(
|
|
|
416
416
|
|
|
417
417
|
function addAffectedNextQueries(
|
|
418
418
|
lines: string[],
|
|
419
|
-
|
|
420
|
-
|
|
419
|
+
options: {
|
|
420
|
+
target: ResolvedTarget;
|
|
421
|
+
symbolName: string;
|
|
422
|
+
showBriefQuery: boolean;
|
|
423
|
+
cwd: string;
|
|
424
|
+
},
|
|
421
425
|
): void {
|
|
422
426
|
lines.push("## Next");
|
|
423
|
-
|
|
424
|
-
|
|
427
|
+
const nextQueries = buildAffectedNextQueries(options.target, options.symbolName, options.cwd);
|
|
428
|
+
if (options.showBriefQuery) {
|
|
429
|
+
lines.push(`- ${nextQueries[0]}`);
|
|
425
430
|
}
|
|
426
|
-
lines.push(
|
|
427
|
-
`- \`code_intel callers\` with \`symbol: "${symbolName}"\` for grouped call-site detail`,
|
|
428
|
-
);
|
|
431
|
+
lines.push(`- ${nextQueries[1]}`);
|
|
429
432
|
lines.push("");
|
|
430
433
|
}
|
|
431
434
|
|
|
432
|
-
function
|
|
433
|
-
file: string,
|
|
434
|
-
line: number,
|
|
435
|
+
function buildAffectedNextQueries(
|
|
435
436
|
target: ResolvedTarget,
|
|
437
|
+
symbolName: string,
|
|
436
438
|
cwd: string,
|
|
437
|
-
):
|
|
438
|
-
|
|
439
|
+
): [string, string] {
|
|
440
|
+
const briefQuery = "`code_brief` on the most-affected module for deeper context";
|
|
441
|
+
if (target.name) {
|
|
442
|
+
return [
|
|
443
|
+
briefQuery,
|
|
444
|
+
`\`code_relations\` with \`kind: "callers"\` and \`symbol: "${symbolName}"\` for grouped call-site detail`,
|
|
445
|
+
];
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return [
|
|
449
|
+
briefQuery,
|
|
450
|
+
`\`code_relations\` with \`kind: "callers"\`, \`file: "${path.relative(cwd, target.file)}"\`, \`line: ${target.displayLine}\`, and \`character: ${target.displayCharacter}\` for grouped call-site detail`,
|
|
451
|
+
];
|
|
439
452
|
}
|
|
@@ -6,8 +6,13 @@ import type { TreeSitterService } from "@mrclrchtr/supi-tree-sitter/api";
|
|
|
6
6
|
import { buildArchitectureModel, findModuleForPath } from "../architecture.ts";
|
|
7
7
|
import { generateFocusedBrief, generateProjectBrief } from "../brief.ts";
|
|
8
8
|
import { withStructuralSession } from "../providers/structural-provider.ts";
|
|
9
|
+
import type { CodeQueryParams as ActionParams } from "../query-params.ts";
|
|
9
10
|
import { normalizePath } from "../search-helpers.ts";
|
|
10
|
-
import
|
|
11
|
+
import {
|
|
12
|
+
type ResolvedTarget,
|
|
13
|
+
resolveSymbolTarget,
|
|
14
|
+
type TargetResolutionResult,
|
|
15
|
+
} from "../target-resolution.ts";
|
|
11
16
|
import type { CodeIntelResult } from "../types.ts";
|
|
12
17
|
|
|
13
18
|
export async function executeBriefAction(
|
|
@@ -52,14 +57,18 @@ export async function executeBriefAction(
|
|
|
52
57
|
dependencySummary: mod && model ? { moduleCount: 1, edgeCount: 0 } : null,
|
|
53
58
|
omittedCount: 0,
|
|
54
59
|
nextQueries: [
|
|
55
|
-
`\`
|
|
56
|
-
`\`
|
|
60
|
+
`\`code_relations\` with \`kind: "callers"\`, \`file: "${relPath}"\`, \`line: ${params.line}\`, and \`character: ${params.character}\` for call sites`,
|
|
61
|
+
`\`code_affected\` with \`file: "${relPath}"\`, \`line: ${params.line}\`, and \`character: ${params.character}\` for impact analysis`,
|
|
57
62
|
],
|
|
58
63
|
},
|
|
59
64
|
},
|
|
60
65
|
};
|
|
61
66
|
}
|
|
62
67
|
|
|
68
|
+
if (params.symbol) {
|
|
69
|
+
return executeSymbolBrief(params, cwd, model);
|
|
70
|
+
}
|
|
71
|
+
|
|
63
72
|
if (params.path) {
|
|
64
73
|
const result = generateFocusedBrief(model, normalizePath(params.path, cwd));
|
|
65
74
|
return { content: result.content, details: { type: "brief" as const, data: result.details } };
|
|
@@ -74,6 +83,29 @@ export async function executeBriefAction(
|
|
|
74
83
|
return { content: result.content, details: { type: "brief" as const, data: result.details } };
|
|
75
84
|
}
|
|
76
85
|
|
|
86
|
+
async function executeSymbolBrief(
|
|
87
|
+
params: ActionParams,
|
|
88
|
+
cwd: string,
|
|
89
|
+
model: NonNullable<Awaited<ReturnType<typeof buildArchitectureModel>>>,
|
|
90
|
+
): Promise<CodeIntelResult> {
|
|
91
|
+
const symbol = params.symbol ?? "";
|
|
92
|
+
const resolved = await resolveSymbolTarget(symbol, cwd, { path: params.path });
|
|
93
|
+
|
|
94
|
+
if (resolved.kind === "error") {
|
|
95
|
+
return createUnavailableSymbolBriefResult(symbol, resolved.message);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (resolved.kind === "disambiguation") {
|
|
99
|
+
return createUnavailableSymbolBriefResult(
|
|
100
|
+
symbol,
|
|
101
|
+
formatBriefDisambiguation(symbol, resolved),
|
|
102
|
+
resolved.omittedCount,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return buildResolvedSymbolBriefResult(resolved.target, cwd, model);
|
|
107
|
+
}
|
|
108
|
+
|
|
77
109
|
async function executeAnchoredBrief(
|
|
78
110
|
params: ActionParams,
|
|
79
111
|
cwd: string,
|
|
@@ -99,6 +131,63 @@ async function executeAnchoredBrief(
|
|
|
99
131
|
return lines.join("\n");
|
|
100
132
|
}
|
|
101
133
|
|
|
134
|
+
async function buildResolvedSymbolBriefResult(
|
|
135
|
+
target: ResolvedTarget,
|
|
136
|
+
cwd: string,
|
|
137
|
+
model: NonNullable<Awaited<ReturnType<typeof buildArchitectureModel>>>,
|
|
138
|
+
): Promise<CodeIntelResult> {
|
|
139
|
+
const relPath = path.relative(cwd, target.file);
|
|
140
|
+
const content = await executeResolvedSymbolBrief(target, cwd, model);
|
|
141
|
+
const mod = findModuleForPath(model, target.file);
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
content,
|
|
145
|
+
details: {
|
|
146
|
+
type: "brief" as const,
|
|
147
|
+
data: {
|
|
148
|
+
confidence: target.confidence,
|
|
149
|
+
focusTarget: `${target.name ?? relPath}:${target.displayLine}:${target.displayCharacter}`,
|
|
150
|
+
startHere: [],
|
|
151
|
+
publicSurfaces: [],
|
|
152
|
+
dependencySummary: mod ? { moduleCount: 1, edgeCount: 0 } : null,
|
|
153
|
+
omittedCount: 0,
|
|
154
|
+
nextQueries: [
|
|
155
|
+
`\`code_relations\` with \`kind: "callers"\`, \`file: "${relPath}"\`, \`line: ${target.displayLine}\`, and \`character: ${target.displayCharacter}\` for call sites`,
|
|
156
|
+
`\`code_affected\` with \`file: "${relPath}"\`, \`line: ${target.displayLine}\`, and \`character: ${target.displayCharacter}\` for impact analysis`,
|
|
157
|
+
],
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async function executeResolvedSymbolBrief(
|
|
164
|
+
target: ResolvedTarget,
|
|
165
|
+
cwd: string,
|
|
166
|
+
model: NonNullable<Awaited<ReturnType<typeof buildArchitectureModel>>>,
|
|
167
|
+
): Promise<string> {
|
|
168
|
+
const relPath = path.relative(cwd, target.file);
|
|
169
|
+
const lines: string[] = [];
|
|
170
|
+
|
|
171
|
+
lines.push(`# Symbol Brief: ${target.name ?? relPath}`);
|
|
172
|
+
lines.push("");
|
|
173
|
+
lines.push(
|
|
174
|
+
`**Resolved to:** \`${relPath}:${target.displayLine}:${target.displayCharacter}\`${target.kind ? ` (${target.kind})` : ""}`,
|
|
175
|
+
);
|
|
176
|
+
lines.push("");
|
|
177
|
+
|
|
178
|
+
await addTreeSitterContext({
|
|
179
|
+
lines,
|
|
180
|
+
relPath,
|
|
181
|
+
line1: target.displayLine,
|
|
182
|
+
char1: target.displayCharacter,
|
|
183
|
+
cwd,
|
|
184
|
+
});
|
|
185
|
+
addModuleContext(lines, model, target.file);
|
|
186
|
+
addNextQueries(lines, relPath, target.displayLine, target.displayCharacter);
|
|
187
|
+
|
|
188
|
+
return lines.join("\n");
|
|
189
|
+
}
|
|
190
|
+
|
|
102
191
|
interface TreeSitterContextInput {
|
|
103
192
|
lines: string[];
|
|
104
193
|
relPath: string;
|
|
@@ -232,10 +321,58 @@ function addModuleContext(
|
|
|
232
321
|
function addNextQueries(lines: string[], relPath: string, line1: number, char1: number): void {
|
|
233
322
|
lines.push("## Next");
|
|
234
323
|
lines.push(
|
|
235
|
-
`- \`
|
|
324
|
+
`- \`code_relations\` with \`kind: "callers"\`, \`file: "${relPath}"\`, \`line: ${line1}\`, and \`character: ${char1}\` for call sites`,
|
|
325
|
+
);
|
|
326
|
+
lines.push(
|
|
327
|
+
`- \`code_affected\` with \`file: "${relPath}"\`, \`line: ${line1}\`, and \`character: ${char1}\` for impact analysis`,
|
|
236
328
|
);
|
|
329
|
+
lines.push("");
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function createUnavailableSymbolBriefResult(
|
|
333
|
+
symbol: string,
|
|
334
|
+
content: string,
|
|
335
|
+
omittedCount = 0,
|
|
336
|
+
): CodeIntelResult {
|
|
337
|
+
return {
|
|
338
|
+
content,
|
|
339
|
+
details: {
|
|
340
|
+
type: "brief" as const,
|
|
341
|
+
data: {
|
|
342
|
+
confidence: "unavailable",
|
|
343
|
+
focusTarget: symbol,
|
|
344
|
+
startHere: [],
|
|
345
|
+
publicSurfaces: [],
|
|
346
|
+
dependencySummary: null,
|
|
347
|
+
omittedCount,
|
|
348
|
+
nextQueries: [
|
|
349
|
+
"Use `file` + coordinates for a precise symbol brief, or enable LSP and retry",
|
|
350
|
+
],
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function formatBriefDisambiguation(
|
|
357
|
+
symbol: string,
|
|
358
|
+
result: Extract<TargetResolutionResult, { kind: "disambiguation" }>,
|
|
359
|
+
): string {
|
|
360
|
+
const lines: string[] = [];
|
|
361
|
+
lines.push(`# Disambiguation needed for \`${symbol}\``);
|
|
362
|
+
lines.push("");
|
|
363
|
+
const omitNote = result.omittedCount > 0 ? ` (+${result.omittedCount} more)` : "";
|
|
237
364
|
lines.push(
|
|
238
|
-
|
|
365
|
+
`Found ${result.candidates.length} candidates${omitNote}. Rerun with anchored coordinates:`,
|
|
239
366
|
);
|
|
240
367
|
lines.push("");
|
|
368
|
+
|
|
369
|
+
for (const candidate of result.candidates) {
|
|
370
|
+
const kind = candidate.kind ? ` (${candidate.kind})` : "";
|
|
371
|
+
const container = candidate.container ? ` in ${candidate.container}` : "";
|
|
372
|
+
lines.push(
|
|
373
|
+
`${candidate.rank}. **${candidate.name}**${kind}${container} — \`${candidate.file}\`:${candidate.line}:${candidate.character}`,
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return lines.join("\n");
|
|
241
378
|
}
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
import * as path from "node:path";
|
|
6
6
|
import { withStructuralSession } from "../providers/structural-provider.ts";
|
|
7
|
+
import type { CodeQueryParams as ActionParams } from "../query-params.ts";
|
|
7
8
|
import { resolveTarget } from "../resolve-target.ts";
|
|
8
9
|
import { isResolvedTargetGroup } from "../semantic-action-helpers.ts";
|
|
9
|
-
import type { ActionParams } from "../tool-actions.ts";
|
|
10
10
|
import type { CodeIntelResult, SearchDetails } from "../types.ts";
|
|
11
11
|
|
|
12
12
|
export async function executeCalleesAction(
|
|
@@ -2,22 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { getSemanticService } from "../providers/semantic-provider.ts";
|
|
5
|
+
import type { CodeQueryParams as ActionParams } from "../query-params.ts";
|
|
5
6
|
import { resolveTarget } from "../resolve-target.ts";
|
|
6
|
-
import {
|
|
7
|
-
escapeRegex,
|
|
8
|
-
filterOutDeclaration,
|
|
9
|
-
isInProjectPath,
|
|
10
|
-
normalizePath,
|
|
11
|
-
runRipgrep,
|
|
12
|
-
uriToFile,
|
|
13
|
-
} from "../search-helpers.ts";
|
|
7
|
+
import { filterOutDeclaration, isInProjectPath, uriToFile } from "../search-helpers.ts";
|
|
14
8
|
import {
|
|
15
9
|
dedupeFileLineRefs,
|
|
16
10
|
highestConfidence,
|
|
17
11
|
isResolvedTargetGroup,
|
|
18
12
|
} from "../semantic-action-helpers.ts";
|
|
19
13
|
import type { ResolvedTarget, ResolvedTargetGroup } from "../target-resolution.ts";
|
|
20
|
-
import type { ActionParams } from "../tool-actions.ts";
|
|
21
14
|
import type { CodeIntelResult, ConfidenceMode, SearchDetails } from "../types.ts";
|
|
22
15
|
|
|
23
16
|
export async function executeCallersAction(
|
|
@@ -59,8 +52,8 @@ export async function executeCallersAction(
|
|
|
59
52
|
candidateCount: result.candidateCount,
|
|
60
53
|
omittedCount: result.externalCount,
|
|
61
54
|
nextQueries: [
|
|
62
|
-
"`
|
|
63
|
-
"
|
|
55
|
+
"`code_affected` for impact analysis",
|
|
56
|
+
"Use `code_pattern` only when you explicitly want text-search hints",
|
|
64
57
|
],
|
|
65
58
|
};
|
|
66
59
|
return { content, details: { type: "search" as const, data: details } };
|
|
@@ -76,7 +69,7 @@ export async function executeCallersAction(
|
|
|
76
69
|
scope: params.path ?? null,
|
|
77
70
|
candidateCount: 0,
|
|
78
71
|
omittedCount: 0,
|
|
79
|
-
nextQueries: ["
|
|
72
|
+
nextQueries: ["Use `code_affected` before editing a broadly referenced target"],
|
|
80
73
|
},
|
|
81
74
|
},
|
|
82
75
|
};
|
|
@@ -84,7 +77,7 @@ export async function executeCallersAction(
|
|
|
84
77
|
|
|
85
78
|
const relPath = path.relative(cwd, target.file);
|
|
86
79
|
return {
|
|
87
|
-
content: `No caller data available for ${relPath}:${target.displayLine}:${target.displayCharacter}
|
|
80
|
+
content: `No caller data available for ${relPath}:${target.displayLine}:${target.displayCharacter}.`,
|
|
88
81
|
details: {
|
|
89
82
|
type: "search" as const,
|
|
90
83
|
data: {
|
|
@@ -92,7 +85,7 @@ export async function executeCallersAction(
|
|
|
92
85
|
scope: params.path ?? null,
|
|
93
86
|
candidateCount: 0,
|
|
94
87
|
omittedCount: 0,
|
|
95
|
-
nextQueries: ["Enable LSP for semantic caller resolution
|
|
88
|
+
nextQueries: ["Enable LSP for semantic caller resolution or use `code_pattern` explicitly"],
|
|
96
89
|
},
|
|
97
90
|
},
|
|
98
91
|
};
|
|
@@ -124,8 +117,8 @@ async function executeFileLevelCallers(
|
|
|
124
117
|
|
|
125
118
|
const withRefs = perTarget.filter((entry) => entry.result.refs.length > 0);
|
|
126
119
|
const uniqueRefs = dedupeFileLineRefs(withRefs.flatMap((entry) => entry.result.refs));
|
|
127
|
-
const confidence = highestConfidence(
|
|
128
|
-
const externalCount =
|
|
120
|
+
const confidence = highestConfidence(perTarget.map((entry) => entry.result.confidence));
|
|
121
|
+
const externalCount = perTarget.reduce((sum, entry) => sum + entry.result.externalCount, 0);
|
|
129
122
|
|
|
130
123
|
const lines: string[] = [];
|
|
131
124
|
lines.push(`# Callers in \`${targetGroup.displayName}\``);
|
|
@@ -155,7 +148,7 @@ async function executeFileLevelCallers(
|
|
|
155
148
|
candidateCount: uniqueRefs.length,
|
|
156
149
|
omittedCount: externalCount,
|
|
157
150
|
nextQueries: [
|
|
158
|
-
"`
|
|
151
|
+
"`code_affected` for impact analysis",
|
|
159
152
|
"Use `file` + coordinates to drill into one symbol precisely",
|
|
160
153
|
],
|
|
161
154
|
};
|
|
@@ -163,58 +156,45 @@ async function executeFileLevelCallers(
|
|
|
163
156
|
return { content: lines.join("\n"), details: { type: "search" as const, data: details } };
|
|
164
157
|
}
|
|
165
158
|
|
|
166
|
-
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: LSP-first caller collection with fallback and declaration filtering is clearest in one helper
|
|
167
159
|
async function collectCallerRefs(
|
|
168
160
|
target: ResolvedTarget,
|
|
169
|
-
|
|
161
|
+
_params: ActionParams,
|
|
170
162
|
cwd: string,
|
|
171
163
|
): Promise<CallerCollection> {
|
|
172
164
|
const lsp = await getSemanticService(cwd, { waitForReady: true });
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const refs = await lsp.references(target.file, target.position);
|
|
176
|
-
if (refs && refs.length > 0) {
|
|
177
|
-
const filtered = filterOutDeclaration(refs, target.file, target.position);
|
|
178
|
-
const projectRefs: CallerRef[] = [];
|
|
179
|
-
let externalCount = 0;
|
|
180
|
-
for (const ref of refs) {
|
|
181
|
-
const filePath = uriToFile(ref.uri);
|
|
182
|
-
if (!isInProjectPath(filePath, cwd)) {
|
|
183
|
-
externalCount++;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
for (const ref of filtered) {
|
|
187
|
-
const filePath = uriToFile(ref.uri);
|
|
188
|
-
if (isInProjectPath(filePath, cwd)) {
|
|
189
|
-
projectRefs.push({ file: path.relative(cwd, filePath), line: ref.range.start.line + 1 });
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
if (projectRefs.length > 0) {
|
|
193
|
-
return {
|
|
194
|
-
refs: projectRefs,
|
|
195
|
-
confidence: "semantic",
|
|
196
|
-
externalCount,
|
|
197
|
-
candidateCount: projectRefs.length,
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
}
|
|
165
|
+
if (!lsp) {
|
|
166
|
+
return { refs: [], confidence: "unavailable", externalCount: 0, candidateCount: 0 };
|
|
201
167
|
}
|
|
202
168
|
|
|
203
|
-
|
|
169
|
+
const refs = await lsp.references(target.file, target.position);
|
|
170
|
+
if (refs === null) {
|
|
204
171
|
return { refs: [], confidence: "unavailable", externalCount: 0, candidateCount: 0 };
|
|
205
172
|
}
|
|
206
173
|
|
|
207
|
-
const
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
174
|
+
const filtered = filterOutDeclaration(refs, target.file, target.position);
|
|
175
|
+
const projectRefs: CallerRef[] = [];
|
|
176
|
+
let externalCount = 0;
|
|
177
|
+
|
|
178
|
+
for (const ref of refs) {
|
|
179
|
+
const filePath = uriToFile(ref.uri);
|
|
180
|
+
if (!isInProjectPath(filePath, cwd)) {
|
|
181
|
+
externalCount++;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
for (const ref of filtered) {
|
|
186
|
+
const filePath = uriToFile(ref.uri);
|
|
187
|
+
if (isInProjectPath(filePath, cwd)) {
|
|
188
|
+
projectRefs.push({ file: path.relative(cwd, filePath), line: ref.range.start.line + 1 });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
216
191
|
|
|
217
|
-
return {
|
|
192
|
+
return {
|
|
193
|
+
refs: projectRefs,
|
|
194
|
+
confidence: "semantic",
|
|
195
|
+
externalCount,
|
|
196
|
+
candidateCount: projectRefs.length,
|
|
197
|
+
};
|
|
218
198
|
}
|
|
219
199
|
|
|
220
200
|
function formatTargetCallers(
|
|
@@ -271,12 +251,3 @@ function groupRefsByFile(refs: CallerRef[], _cwd: string): Map<string, number[]>
|
|
|
271
251
|
}
|
|
272
252
|
return byFile;
|
|
273
253
|
}
|
|
274
|
-
|
|
275
|
-
function isDeclarationMatch(
|
|
276
|
-
file: string,
|
|
277
|
-
line: number,
|
|
278
|
-
target: ResolvedTarget,
|
|
279
|
-
cwd: string,
|
|
280
|
-
): boolean {
|
|
281
|
-
return path.resolve(cwd, file) === target.file && line === target.displayLine;
|
|
282
|
-
}
|