ghagga-core 2.6.0 → 2.8.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/dist/agents/consensus.d.ts +2 -0
- package/dist/agents/consensus.d.ts.map +1 -1
- package/dist/agents/consensus.js +1 -0
- package/dist/agents/consensus.js.map +1 -1
- package/dist/agents/diagnostic.d.ts +2 -0
- package/dist/agents/diagnostic.d.ts.map +1 -1
- package/dist/agents/diagnostic.js +1 -0
- package/dist/agents/diagnostic.js.map +1 -1
- package/dist/agents/fan-out-lenses.d.ts +92 -0
- package/dist/agents/fan-out-lenses.d.ts.map +1 -0
- package/dist/agents/fan-out-lenses.js +424 -0
- package/dist/agents/fan-out-lenses.js.map +1 -0
- package/dist/agents/simple.d.ts +2 -0
- package/dist/agents/simple.d.ts.map +1 -1
- package/dist/agents/simple.js +1 -0
- package/dist/agents/simple.js.map +1 -1
- package/dist/agents/workflow.d.ts +2 -0
- package/dist/agents/workflow.d.ts.map +1 -1
- package/dist/agents/workflow.js +2 -1
- package/dist/agents/workflow.js.map +1 -1
- package/dist/checklist/config.d.ts +22 -0
- package/dist/checklist/config.d.ts.map +1 -0
- package/dist/checklist/config.js +85 -0
- package/dist/checklist/config.js.map +1 -0
- package/dist/checklist/context.d.ts +22 -0
- package/dist/checklist/context.d.ts.map +1 -0
- package/dist/checklist/context.js +76 -0
- package/dist/checklist/context.js.map +1 -0
- package/dist/checklist/defaults.d.ts +12 -0
- package/dist/checklist/defaults.d.ts.map +1 -0
- package/dist/checklist/defaults.js +172 -0
- package/dist/checklist/defaults.js.map +1 -0
- package/dist/checklist/index.d.ts +14 -0
- package/dist/checklist/index.d.ts.map +1 -0
- package/dist/checklist/index.js +15 -0
- package/dist/checklist/index.js.map +1 -0
- package/dist/checklist/scorer.d.ts +58 -0
- package/dist/checklist/scorer.d.ts.map +1 -0
- package/dist/checklist/scorer.js +142 -0
- package/dist/checklist/scorer.js.map +1 -0
- package/dist/checklist/types.d.ts +39 -0
- package/dist/checklist/types.d.ts.map +1 -0
- package/dist/checklist/types.js +17 -0
- package/dist/checklist/types.js.map +1 -0
- package/dist/exploitability/analyzer.d.ts +75 -0
- package/dist/exploitability/analyzer.d.ts.map +1 -0
- package/dist/exploitability/analyzer.js +299 -0
- package/dist/exploitability/analyzer.js.map +1 -0
- package/dist/exploitability/index.d.ts +10 -0
- package/dist/exploitability/index.d.ts.map +1 -0
- package/dist/exploitability/index.js +10 -0
- package/dist/exploitability/index.js.map +1 -0
- package/dist/exploitability/types.d.ts +32 -0
- package/dist/exploitability/types.d.ts.map +1 -0
- package/dist/exploitability/types.js +9 -0
- package/dist/exploitability/types.js.map +1 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/memory/context.d.ts +2 -0
- package/dist/memory/context.d.ts.map +1 -1
- package/dist/memory/context.js +2 -1
- package/dist/memory/context.js.map +1 -1
- package/dist/memory/contradiction.d.ts +46 -0
- package/dist/memory/contradiction.d.ts.map +1 -0
- package/dist/memory/contradiction.js +110 -0
- package/dist/memory/contradiction.js.map +1 -0
- package/dist/memory/decay.d.ts +25 -0
- package/dist/memory/decay.d.ts.map +1 -0
- package/dist/memory/decay.js +51 -0
- package/dist/memory/decay.js.map +1 -0
- package/dist/memory/search.d.ts.map +1 -1
- package/dist/memory/search.js +1 -0
- package/dist/memory/search.js.map +1 -1
- package/dist/memory/sqlite.d.ts +21 -0
- package/dist/memory/sqlite.d.ts.map +1 -1
- package/dist/memory/sqlite.js +82 -7
- package/dist/memory/sqlite.js.map +1 -1
- package/dist/memory/versioning.d.ts +94 -0
- package/dist/memory/versioning.d.ts.map +1 -0
- package/dist/memory/versioning.js +350 -0
- package/dist/memory/versioning.js.map +1 -0
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +117 -0
- package/dist/pipeline.js.map +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +7 -2
- package/dist/providers/index.js.map +1 -1
- package/dist/recursive/index.d.ts +45 -0
- package/dist/recursive/index.d.ts.map +1 -0
- package/dist/recursive/index.js +159 -0
- package/dist/recursive/index.js.map +1 -0
- package/dist/recursive/patch-extractor.d.ts +49 -0
- package/dist/recursive/patch-extractor.d.ts.map +1 -0
- package/dist/recursive/patch-extractor.js +133 -0
- package/dist/recursive/patch-extractor.js.map +1 -0
- package/dist/recursive/re-reviewer.d.ts +31 -0
- package/dist/recursive/re-reviewer.d.ts.map +1 -0
- package/dist/recursive/re-reviewer.js +66 -0
- package/dist/recursive/re-reviewer.js.map +1 -0
- package/dist/recursive/types.d.ts +62 -0
- package/dist/recursive/types.d.ts.map +1 -0
- package/dist/recursive/types.js +11 -0
- package/dist/recursive/types.js.map +1 -0
- package/dist/scope/context-builder.d.ts +37 -0
- package/dist/scope/context-builder.d.ts.map +1 -0
- package/dist/scope/context-builder.js +108 -0
- package/dist/scope/context-builder.js.map +1 -0
- package/dist/scope/diff-mapper.d.ts +29 -0
- package/dist/scope/diff-mapper.d.ts.map +1 -0
- package/dist/scope/diff-mapper.js +76 -0
- package/dist/scope/diff-mapper.js.map +1 -0
- package/dist/scope/extractor.d.ts +25 -0
- package/dist/scope/extractor.d.ts.map +1 -0
- package/dist/scope/extractor.js +264 -0
- package/dist/scope/extractor.js.map +1 -0
- package/dist/scope/index.d.ts +13 -0
- package/dist/scope/index.d.ts.map +1 -0
- package/dist/scope/index.js +16 -0
- package/dist/scope/index.js.map +1 -0
- package/dist/scope/parser.d.ts +47 -0
- package/dist/scope/parser.d.ts.map +1 -0
- package/dist/scope/parser.js +97 -0
- package/dist/scope/parser.js.map +1 -0
- package/dist/scope/queries.d.ts +23 -0
- package/dist/scope/queries.d.ts.map +1 -0
- package/dist/scope/queries.js +134 -0
- package/dist/scope/queries.js.map +1 -0
- package/dist/scope/types.d.ts +55 -0
- package/dist/scope/types.d.ts.map +1 -0
- package/dist/scope/types.js +8 -0
- package/dist/scope/types.js.map +1 -0
- package/dist/tools/execution.d.ts.map +1 -1
- package/dist/tools/execution.js +2 -0
- package/dist/tools/execution.js.map +1 -1
- package/dist/tools/plugins/index.d.ts +1 -0
- package/dist/tools/plugins/index.d.ts.map +1 -1
- package/dist/tools/plugins/index.js +6 -5
- package/dist/tools/plugins/index.js.map +1 -1
- package/dist/tools/plugins/sonarqube.d.ts +54 -0
- package/dist/tools/plugins/sonarqube.d.ts.map +1 -0
- package/dist/tools/plugins/sonarqube.js +145 -0
- package/dist/tools/plugins/sonarqube.js.map +1 -0
- package/dist/tools/plugins/trivy.js +1 -1
- package/dist/tools/plugins/trivy.js.map +1 -1
- package/dist/tools/types.d.ts +7 -1
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/types.d.ts +80 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch-extractor.d.ts","sourceRoot":"","sources":["../../src/recursive/patch-extractor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAIlD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,eAAe,EAAE,CAqB3E;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CA+D5F;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CAWpE"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Patch Extractor — extracts suggestion patches from review findings
|
|
3
|
+
* and applies them virtually to produce a synthetic diff.
|
|
4
|
+
*
|
|
5
|
+
* No filesystem access — operates purely on diff strings.
|
|
6
|
+
*/
|
|
7
|
+
// ─── Patch Extraction ──────────────────────────────────────────
|
|
8
|
+
/**
|
|
9
|
+
* Extract actionable patches from review findings.
|
|
10
|
+
*
|
|
11
|
+
* Only findings with both a `suggestion` and a `file` are included.
|
|
12
|
+
* Findings without a line number are included but marked as file-level.
|
|
13
|
+
*
|
|
14
|
+
* @param findings - Review findings from the AI agent
|
|
15
|
+
* @returns Array of suggestion patches ready for virtual application
|
|
16
|
+
*/
|
|
17
|
+
export function extractPatches(findings) {
|
|
18
|
+
const patches = [];
|
|
19
|
+
for (let i = 0; i < findings.length; i++) {
|
|
20
|
+
const finding = findings[i];
|
|
21
|
+
if (!finding)
|
|
22
|
+
continue;
|
|
23
|
+
if (!finding.suggestion || !finding.file)
|
|
24
|
+
continue;
|
|
25
|
+
// Skip empty/whitespace-only suggestions
|
|
26
|
+
if (finding.suggestion.trim().length === 0)
|
|
27
|
+
continue;
|
|
28
|
+
patches.push({
|
|
29
|
+
file: finding.file,
|
|
30
|
+
line: finding.line,
|
|
31
|
+
originalMessage: finding.message,
|
|
32
|
+
suggestion: finding.suggestion,
|
|
33
|
+
findingIndex: i,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return patches;
|
|
37
|
+
}
|
|
38
|
+
// ─── Virtual Patch Application ─────────────────────────────────
|
|
39
|
+
/**
|
|
40
|
+
* Apply suggestion patches to an original diff, producing a synthetic
|
|
41
|
+
* patched diff for re-review.
|
|
42
|
+
*
|
|
43
|
+
* Strategy:
|
|
44
|
+
* - For each file in the diff, collect patches targeting that file.
|
|
45
|
+
* - Sort patches by line number descending (bottom-up) to avoid offset shifts.
|
|
46
|
+
* - For each patch, find the target line in the diff's added lines (+)
|
|
47
|
+
* and append a comment showing the suggested replacement.
|
|
48
|
+
*
|
|
49
|
+
* The patched diff is a SYNTHETIC representation — it shows what the code
|
|
50
|
+
* would look like if the suggestions were applied. This is NOT a real
|
|
51
|
+
* git diff; it's a review-friendly format for the LLM to analyze.
|
|
52
|
+
*
|
|
53
|
+
* @param originalDiff - The original unified diff string
|
|
54
|
+
* @param patches - Suggestion patches to apply
|
|
55
|
+
* @returns Synthetic diff with suggestions applied
|
|
56
|
+
*/
|
|
57
|
+
export function applyVirtualPatches(originalDiff, patches) {
|
|
58
|
+
if (patches.length === 0)
|
|
59
|
+
return originalDiff;
|
|
60
|
+
// Group patches by file
|
|
61
|
+
const patchesByFile = new Map();
|
|
62
|
+
for (const patch of patches) {
|
|
63
|
+
const existing = patchesByFile.get(patch.file) ?? [];
|
|
64
|
+
existing.push(patch);
|
|
65
|
+
patchesByFile.set(patch.file, existing);
|
|
66
|
+
}
|
|
67
|
+
// Build the synthetic diff
|
|
68
|
+
const lines = originalDiff.split('\n');
|
|
69
|
+
const result = [];
|
|
70
|
+
let currentFile = null;
|
|
71
|
+
let currentFilePatches = [];
|
|
72
|
+
let lineCounter = 0; // Tracks the target-side line number in current hunk
|
|
73
|
+
for (const line of lines) {
|
|
74
|
+
// Detect file boundaries
|
|
75
|
+
const fileMatch = /^diff --git a\/.+ b\/(.+)$/.exec(line);
|
|
76
|
+
if (fileMatch?.[1]) {
|
|
77
|
+
currentFile = fileMatch[1];
|
|
78
|
+
currentFilePatches = patchesByFile.get(currentFile) ?? [];
|
|
79
|
+
lineCounter = 0;
|
|
80
|
+
}
|
|
81
|
+
// Track hunk line numbers
|
|
82
|
+
const hunkMatch = /^@@ -\d+(?:,\d+)? \+(\d+)/.exec(line);
|
|
83
|
+
if (hunkMatch?.[1]) {
|
|
84
|
+
lineCounter = parseInt(hunkMatch[1], 10) - 1;
|
|
85
|
+
}
|
|
86
|
+
// Count lines for position tracking (added or context lines increment target counter)
|
|
87
|
+
if (line.startsWith('+') && !line.startsWith('+++')) {
|
|
88
|
+
lineCounter++;
|
|
89
|
+
}
|
|
90
|
+
else if (line.startsWith('-') && !line.startsWith('---')) {
|
|
91
|
+
// Removed lines don't increment target counter
|
|
92
|
+
}
|
|
93
|
+
else if (!line.startsWith('\\') &&
|
|
94
|
+
!line.startsWith('diff ') &&
|
|
95
|
+
!line.startsWith('index ') &&
|
|
96
|
+
!line.startsWith('---') &&
|
|
97
|
+
!line.startsWith('+++') &&
|
|
98
|
+
!line.startsWith('@@')) {
|
|
99
|
+
lineCounter++;
|
|
100
|
+
}
|
|
101
|
+
result.push(line);
|
|
102
|
+
// Check if any patch targets this line
|
|
103
|
+
if (currentFile && currentFilePatches.length > 0) {
|
|
104
|
+
const matchingPatches = currentFilePatches.filter((p) => p.line === lineCounter);
|
|
105
|
+
for (const patch of matchingPatches) {
|
|
106
|
+
// Insert the suggestion as a synthetic replacement block
|
|
107
|
+
result.push(`+[SUGGESTED FIX] ${patch.suggestion}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return result.join('\n');
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Build a focused review context for re-review.
|
|
115
|
+
*
|
|
116
|
+
* Instead of passing the entire diff, build a summary of what
|
|
117
|
+
* suggestions were applied and where, so the re-review LLM
|
|
118
|
+
* can focus on validating those specific changes.
|
|
119
|
+
*
|
|
120
|
+
* @param patches - The patches that were applied
|
|
121
|
+
* @returns Context string for the re-review prompt
|
|
122
|
+
*/
|
|
123
|
+
export function buildPatchContext(patches) {
|
|
124
|
+
if (patches.length === 0)
|
|
125
|
+
return '';
|
|
126
|
+
const lines = ['## Applied Suggestions (validate these for regressions)', ''];
|
|
127
|
+
for (const patch of patches) {
|
|
128
|
+
lines.push(`- **${patch.file}${patch.line ? `:${patch.line}` : ''}**: ${patch.suggestion}`);
|
|
129
|
+
lines.push(` (Original issue: ${patch.originalMessage})`);
|
|
130
|
+
}
|
|
131
|
+
return lines.join('\n');
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=patch-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch-extractor.js","sourceRoot":"","sources":["../../src/recursive/patch-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-Reviewer — runs a lightweight review on patched diffs
|
|
3
|
+
* to detect regressions introduced by suggested fixes.
|
|
4
|
+
*/
|
|
5
|
+
import type { GenerateTextFn } from '../providers/generate-fn.js';
|
|
6
|
+
import type { ReviewFinding } from '../types.js';
|
|
7
|
+
export interface ReReviewInput {
|
|
8
|
+
/** Synthetic diff with suggestions applied */
|
|
9
|
+
patchedDiff: string;
|
|
10
|
+
/** Context about which patches were applied */
|
|
11
|
+
patchContext: string;
|
|
12
|
+
/** Generation function for the LLM call */
|
|
13
|
+
generateFn: GenerateTextFn;
|
|
14
|
+
}
|
|
15
|
+
export interface ReReviewResult {
|
|
16
|
+
/** New findings from the re-review */
|
|
17
|
+
findings: ReviewFinding[];
|
|
18
|
+
/** Tokens used for this re-review call */
|
|
19
|
+
tokensUsed: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Run a lightweight re-review on a patched diff.
|
|
23
|
+
*
|
|
24
|
+
* Uses simple mode (single LLM call) to check whether the
|
|
25
|
+
* applied suggestions introduce new problems.
|
|
26
|
+
*
|
|
27
|
+
* @param input - Patched diff and LLM config
|
|
28
|
+
* @returns New findings from the re-review
|
|
29
|
+
*/
|
|
30
|
+
export declare function runReReview(input: ReReviewInput): Promise<ReReviewResult>;
|
|
31
|
+
//# sourceMappingURL=re-reviewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"re-reviewer.d.ts","sourceRoot":"","sources":["../../src/recursive/re-reviewer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA+BjD,MAAM,WAAW,aAAa;IAC5B,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IAEpB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAC;IAErB,2CAA2C;IAC3C,UAAU,EAAE,cAAc,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,QAAQ,EAAE,aAAa,EAAE,CAAC;IAE1B,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;CACpB;AAID;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CA6B/E"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-Reviewer — runs a lightweight review on patched diffs
|
|
3
|
+
* to detect regressions introduced by suggested fixes.
|
|
4
|
+
*/
|
|
5
|
+
import { parseFindingsBlock } from '../agents/simple.js';
|
|
6
|
+
// ─── Re-Review Prompt ──────────────────────────────────────────
|
|
7
|
+
const RE_REVIEW_SYSTEM = `You are a code review validator. You are reviewing code changes that include SUGGESTED FIXES from a previous code review.
|
|
8
|
+
|
|
9
|
+
Your ONLY job is to check whether the suggested fixes introduce NEW problems:
|
|
10
|
+
- New bugs or logic errors from the fix
|
|
11
|
+
- Security issues introduced by the fix
|
|
12
|
+
- Performance regressions from the fix
|
|
13
|
+
- Breaking changes caused by the fix
|
|
14
|
+
|
|
15
|
+
DO NOT repeat the original findings. ONLY report NEW issues introduced by the suggested changes.
|
|
16
|
+
Lines marked with [SUGGESTED FIX] are the applied suggestions — focus your analysis there.
|
|
17
|
+
|
|
18
|
+
Format your response EXACTLY as:
|
|
19
|
+
|
|
20
|
+
STATUS: [PASSED or FAILED]
|
|
21
|
+
SUMMARY: [1-2 sentences about whether suggestions introduced issues]
|
|
22
|
+
FINDINGS:
|
|
23
|
+
- SEVERITY: [critical|high|medium|low|info]
|
|
24
|
+
CATEGORY: [security|performance|bug|style|error-handling|maintainability]
|
|
25
|
+
FILE: [file path]
|
|
26
|
+
LINE: [line number or "N/A"]
|
|
27
|
+
MESSAGE: [description of the NEW issue introduced by the suggestion]
|
|
28
|
+
SUGGESTION: [how to fix the regression]
|
|
29
|
+
|
|
30
|
+
If no new issues were introduced, return STATUS: PASSED with an empty FINDINGS section.`;
|
|
31
|
+
// ─── Main Function ─────────────────────────────────────────────
|
|
32
|
+
/**
|
|
33
|
+
* Run a lightweight re-review on a patched diff.
|
|
34
|
+
*
|
|
35
|
+
* Uses simple mode (single LLM call) to check whether the
|
|
36
|
+
* applied suggestions introduce new problems.
|
|
37
|
+
*
|
|
38
|
+
* @param input - Patched diff and LLM config
|
|
39
|
+
* @returns New findings from the re-review
|
|
40
|
+
*/
|
|
41
|
+
export async function runReReview(input) {
|
|
42
|
+
const { patchedDiff, patchContext, generateFn } = input;
|
|
43
|
+
const system = [RE_REVIEW_SYSTEM, patchContext].filter(Boolean).join('\n\n');
|
|
44
|
+
const prompt = `Please validate the following code changes that include applied suggestions:\n\n\`\`\`diff\n${patchedDiff}\n\`\`\``;
|
|
45
|
+
try {
|
|
46
|
+
const result = await generateFn(system, prompt);
|
|
47
|
+
// Parse findings from the response
|
|
48
|
+
const findings = parseFindingsBlock(result.text);
|
|
49
|
+
// Mark all findings as coming from recursive review
|
|
50
|
+
for (const finding of findings) {
|
|
51
|
+
finding.source = 'recursive-review';
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
findings,
|
|
55
|
+
tokensUsed: result.tokensUsed,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// Non-blocking — return empty findings on failure
|
|
60
|
+
return {
|
|
61
|
+
findings: [],
|
|
62
|
+
tokensUsed: 0,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=re-reviewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"re-reviewer.js","sourceRoot":"","sources":["../../src/recursive/re-reviewer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAIzD,kEAAkE;AAElE,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;wFAuB+D,CAAC;AAuBzF,kEAAkE;AAElE;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAoB;IACpD,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IAExD,MAAM,MAAM,GAAG,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAE7E,MAAM,MAAM,GAAG,+FAA+F,WAAW,UAAU,CAAC;IAEpI,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAEhD,mCAAmC;QACnC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAEjD,oDAAoD;QACpD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,OAAO,CAAC,MAAM,GAAG,kBAAkB,CAAC;QACtC,CAAC;QAED,OAAO;YACL,QAAQ;YACR,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,kDAAkD;QAClD,OAAO;YACL,QAAQ,EAAE,EAAE;YACZ,UAAU,EAAE,CAAC;SACd,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursive Review Loop — Types
|
|
3
|
+
*
|
|
4
|
+
* Types for the self-validating review cycle that re-reviews
|
|
5
|
+
* suggested patches to catch regressions before they reach the user.
|
|
6
|
+
*/
|
|
7
|
+
import type { ReviewFinding } from '../types.js';
|
|
8
|
+
/**
|
|
9
|
+
* A patch derived from a review finding's suggestion.
|
|
10
|
+
* Represents a single code change that the AI reviewer recommended.
|
|
11
|
+
*/
|
|
12
|
+
export interface SuggestionPatch {
|
|
13
|
+
/** File path from the finding */
|
|
14
|
+
file: string;
|
|
15
|
+
/** Line number from the finding (undefined = file-level suggestion) */
|
|
16
|
+
line: number | undefined;
|
|
17
|
+
/** The original finding message for context */
|
|
18
|
+
originalMessage: string;
|
|
19
|
+
/** The suggested fix text */
|
|
20
|
+
suggestion: string;
|
|
21
|
+
/** Index of the finding in the original results (for tracing) */
|
|
22
|
+
findingIndex: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A finding from re-review that represents a regression
|
|
26
|
+
* introduced by a suggested fix.
|
|
27
|
+
*/
|
|
28
|
+
export interface RegressionFinding extends ReviewFinding {
|
|
29
|
+
/** Always true — discriminant for regression findings */
|
|
30
|
+
isRegression: true;
|
|
31
|
+
/** The original suggestion that caused this regression */
|
|
32
|
+
originatingSuggestion: {
|
|
33
|
+
file: string;
|
|
34
|
+
line: number | undefined;
|
|
35
|
+
suggestion: string;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Report from the recursive review loop.
|
|
40
|
+
* Attached to ReviewResult when recursive review is enabled.
|
|
41
|
+
*/
|
|
42
|
+
export interface RecursiveReviewReport {
|
|
43
|
+
/** Number of re-review iterations executed (1 or 2) */
|
|
44
|
+
iterations: number;
|
|
45
|
+
/** Whether the review converged (no new issues on last iteration) */
|
|
46
|
+
converged: boolean;
|
|
47
|
+
/** Findings identified as regressions from suggested fixes */
|
|
48
|
+
regressions: RegressionFinding[];
|
|
49
|
+
/** Total new issues found across all re-review iterations */
|
|
50
|
+
totalNewIssues: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Configuration for the recursive review step.
|
|
54
|
+
* Extracted from ReviewSettings for internal use.
|
|
55
|
+
*/
|
|
56
|
+
export interface RecursiveReviewConfig {
|
|
57
|
+
/** Maximum number of re-review iterations. Default: 2 */
|
|
58
|
+
maxIterations: number;
|
|
59
|
+
}
|
|
60
|
+
/** Default configuration values */
|
|
61
|
+
export declare const DEFAULT_RECURSIVE_CONFIG: RecursiveReviewConfig;
|
|
62
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/recursive/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IAEb,uEAAuE;IACvE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzB,+CAA+C;IAC/C,eAAe,EAAE,MAAM,CAAC;IAExB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IAEnB,iEAAiE;IACjE,YAAY,EAAE,MAAM,CAAC;CACtB;AAID;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,yDAAyD;IACzD,YAAY,EAAE,IAAI,CAAC;IAEnB,0DAA0D;IAC1D,qBAAqB,EAAE;QACrB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;QACzB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAID;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IAEnB,qEAAqE;IACrE,SAAS,EAAE,OAAO,CAAC;IAEnB,8DAA8D;IAC9D,WAAW,EAAE,iBAAiB,EAAE,CAAC;IAEjC,6DAA6D;IAC7D,cAAc,EAAE,MAAM,CAAC;CACxB;AAID;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,yDAAyD;IACzD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,mCAAmC;AACnC,eAAO,MAAM,wBAAwB,EAAE,qBAEtC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursive Review Loop — Types
|
|
3
|
+
*
|
|
4
|
+
* Types for the self-validating review cycle that re-reviews
|
|
5
|
+
* suggested patches to catch regressions before they reach the user.
|
|
6
|
+
*/
|
|
7
|
+
/** Default configuration values */
|
|
8
|
+
export const DEFAULT_RECURSIVE_CONFIG = {
|
|
9
|
+
maxIterations: 2,
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/recursive/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA4EH,mCAAmC;AACnC,MAAM,CAAC,MAAM,wBAAwB,GAA0B;IAC7D,aAAa,EAAE,CAAC;CACjB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scoped Context Builder
|
|
3
|
+
*
|
|
4
|
+
* Builds a focused review context string containing only the source
|
|
5
|
+
* code of symbols affected by a diff. This dramatically reduces the
|
|
6
|
+
* number of tokens sent to the LLM for review.
|
|
7
|
+
*
|
|
8
|
+
* Pure function with no side effects.
|
|
9
|
+
*/
|
|
10
|
+
import type { ScopedFile } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Build a focused review context containing only the source code
|
|
13
|
+
* of symbols affected by diff changes.
|
|
14
|
+
*
|
|
15
|
+
* Output format:
|
|
16
|
+
* ```
|
|
17
|
+
* ## path/to/file.ts
|
|
18
|
+
*
|
|
19
|
+
* ### function foo (lines 10-25)
|
|
20
|
+
* ```ts
|
|
21
|
+
* <source lines 10-25>
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* ### class Bar (lines 30-80)
|
|
25
|
+
* ```ts
|
|
26
|
+
* <source lines 30-80>
|
|
27
|
+
* ```
|
|
28
|
+
* ---
|
|
29
|
+
* ## path/to/other.ts
|
|
30
|
+
* ...
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @param scopedFiles - Files with their affected symbols and source lines
|
|
34
|
+
* @returns Formatted review context string, or empty string if no affected symbols
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildScopedContext(scopedFiles: ScopedFile[]): string;
|
|
37
|
+
//# sourceMappingURL=context-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-builder.d.ts","sourceRoot":"","sources":["../../src/scope/context-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAe7C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,MAAM,CAepE"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scoped Context Builder
|
|
3
|
+
*
|
|
4
|
+
* Builds a focused review context string containing only the source
|
|
5
|
+
* code of symbols affected by a diff. This dramatically reduces the
|
|
6
|
+
* number of tokens sent to the LLM for review.
|
|
7
|
+
*
|
|
8
|
+
* Pure function with no side effects.
|
|
9
|
+
*/
|
|
10
|
+
// ─── Constants ────────────────────────────────────────────────
|
|
11
|
+
/** Separator between file sections in the output. */
|
|
12
|
+
const FILE_SEPARATOR = '\n---\n';
|
|
13
|
+
/** Header format for each file section. */
|
|
14
|
+
const FILE_HEADER_PREFIX = '## ';
|
|
15
|
+
/** Header format for each symbol section. */
|
|
16
|
+
const SYMBOL_HEADER_PREFIX = '### ';
|
|
17
|
+
// ─── Builder ──────────────────────────────────────────────────
|
|
18
|
+
/**
|
|
19
|
+
* Build a focused review context containing only the source code
|
|
20
|
+
* of symbols affected by diff changes.
|
|
21
|
+
*
|
|
22
|
+
* Output format:
|
|
23
|
+
* ```
|
|
24
|
+
* ## path/to/file.ts
|
|
25
|
+
*
|
|
26
|
+
* ### function foo (lines 10-25)
|
|
27
|
+
* ```ts
|
|
28
|
+
* <source lines 10-25>
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* ### class Bar (lines 30-80)
|
|
32
|
+
* ```ts
|
|
33
|
+
* <source lines 30-80>
|
|
34
|
+
* ```
|
|
35
|
+
* ---
|
|
36
|
+
* ## path/to/other.ts
|
|
37
|
+
* ...
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @param scopedFiles - Files with their affected symbols and source lines
|
|
41
|
+
* @returns Formatted review context string, or empty string if no affected symbols
|
|
42
|
+
*/
|
|
43
|
+
export function buildScopedContext(scopedFiles) {
|
|
44
|
+
if (scopedFiles.length === 0)
|
|
45
|
+
return '';
|
|
46
|
+
const sections = [];
|
|
47
|
+
for (const file of scopedFiles) {
|
|
48
|
+
if (file.symbols.length === 0)
|
|
49
|
+
continue;
|
|
50
|
+
const fileSection = buildFileSection(file);
|
|
51
|
+
if (fileSection) {
|
|
52
|
+
sections.push(fileSection);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return sections.join(FILE_SEPARATOR);
|
|
56
|
+
}
|
|
57
|
+
// ─── Internals ────────────────────────────────────────────────
|
|
58
|
+
/**
|
|
59
|
+
* Build the context section for a single file.
|
|
60
|
+
*/
|
|
61
|
+
function buildFileSection(file) {
|
|
62
|
+
const ext = inferCodeFenceLanguage(file.filePath);
|
|
63
|
+
const symbolSections = [];
|
|
64
|
+
// Deduplicate symbols by name+startLine to avoid repeating
|
|
65
|
+
// the same symbol if it appears in multiple hunks
|
|
66
|
+
const seen = new Set();
|
|
67
|
+
for (const affected of file.symbols) {
|
|
68
|
+
const { symbol } = affected;
|
|
69
|
+
const key = `${symbol.name}:${symbol.startLine}`;
|
|
70
|
+
if (seen.has(key))
|
|
71
|
+
continue;
|
|
72
|
+
seen.add(key);
|
|
73
|
+
const startIdx = Math.max(0, symbol.startLine - 1);
|
|
74
|
+
const endIdx = Math.min(file.sourceLines.length, symbol.endLine);
|
|
75
|
+
const sourceSlice = file.sourceLines.slice(startIdx, endIdx).join('\n');
|
|
76
|
+
const kindLabel = symbol.parent
|
|
77
|
+
? `${symbol.kind} ${symbol.parent}.${symbol.name}`
|
|
78
|
+
: `${symbol.kind} ${symbol.name}`;
|
|
79
|
+
const lineRange = `lines ${symbol.startLine}-${symbol.endLine}`;
|
|
80
|
+
symbolSections.push(`${SYMBOL_HEADER_PREFIX}${kindLabel} (${lineRange})\n\`\`\`${ext}\n${sourceSlice}\n\`\`\``);
|
|
81
|
+
}
|
|
82
|
+
if (symbolSections.length === 0)
|
|
83
|
+
return undefined;
|
|
84
|
+
return `${FILE_HEADER_PREFIX}${file.filePath}\n\n${symbolSections.join('\n\n')}`;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Infer the code fence language hint from a file path.
|
|
88
|
+
*/
|
|
89
|
+
function inferCodeFenceLanguage(filePath) {
|
|
90
|
+
const ext = filePath.split('.').pop()?.toLowerCase() ?? '';
|
|
91
|
+
const MAP = {
|
|
92
|
+
ts: 'ts',
|
|
93
|
+
tsx: 'tsx',
|
|
94
|
+
js: 'js',
|
|
95
|
+
jsx: 'jsx',
|
|
96
|
+
py: 'python',
|
|
97
|
+
go: 'go',
|
|
98
|
+
rs: 'rust',
|
|
99
|
+
java: 'java',
|
|
100
|
+
rb: 'ruby',
|
|
101
|
+
cs: 'csharp',
|
|
102
|
+
cpp: 'cpp',
|
|
103
|
+
c: 'c',
|
|
104
|
+
h: 'c',
|
|
105
|
+
};
|
|
106
|
+
return MAP[ext] ?? ext;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=context-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-builder.js","sourceRoot":"","sources":["../../src/scope/context-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diff-to-Symbol Mapper
|
|
3
|
+
*
|
|
4
|
+
* Maps unified diff hunks to symbol definitions, identifying
|
|
5
|
+
* which symbols were affected by code changes.
|
|
6
|
+
*
|
|
7
|
+
* Pure functions with no side effects.
|
|
8
|
+
*/
|
|
9
|
+
import type { AffectedSymbol, DiffHunk, SymbolInfo } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Parse unified diff content to extract hunk line ranges.
|
|
12
|
+
*
|
|
13
|
+
* @param diffContent - Raw unified diff content for a single file
|
|
14
|
+
* @returns Array of DiffHunk objects with line ranges
|
|
15
|
+
*/
|
|
16
|
+
export declare function parseHunks(diffContent: string): DiffHunk[];
|
|
17
|
+
/**
|
|
18
|
+
* Map diff hunks to affected symbols.
|
|
19
|
+
*
|
|
20
|
+
* A symbol is considered "affected" if any hunk's NEW side line range
|
|
21
|
+
* overlaps with the symbol's line range. We use the new side because
|
|
22
|
+
* we're analyzing the post-change source code.
|
|
23
|
+
*
|
|
24
|
+
* @param hunks - Parsed diff hunks
|
|
25
|
+
* @param symbols - Extracted symbols from the NEW version of the file
|
|
26
|
+
* @returns Array of affected symbols with their overlapping hunks
|
|
27
|
+
*/
|
|
28
|
+
export declare function mapDiffToSymbols(hunks: DiffHunk[], symbols: SymbolInfo[]): AffectedSymbol[];
|
|
29
|
+
//# sourceMappingURL=diff-mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-mapper.d.ts","sourceRoot":"","sources":["../../src/scope/diff-mapper.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAevE;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,EAAE,CAiB1D;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,cAAc,EAAE,CAqB3F"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diff-to-Symbol Mapper
|
|
3
|
+
*
|
|
4
|
+
* Maps unified diff hunks to symbol definitions, identifying
|
|
5
|
+
* which symbols were affected by code changes.
|
|
6
|
+
*
|
|
7
|
+
* Pure functions with no side effects.
|
|
8
|
+
*/
|
|
9
|
+
// ─── Hunk Parsing ──────────────────────────────────────────────
|
|
10
|
+
/**
|
|
11
|
+
* Regex to match unified diff hunk headers.
|
|
12
|
+
* Format: @@ -oldStart[,oldCount] +newStart[,newCount] @@
|
|
13
|
+
*
|
|
14
|
+
* Examples:
|
|
15
|
+
* @@ -10,5 +10,7 @@
|
|
16
|
+
* @@ -1 +1,3 @@
|
|
17
|
+
* @@ -0,0 +1,20 @@
|
|
18
|
+
*/
|
|
19
|
+
const HUNK_HEADER_RE = /^@@\s+-(\d+)(?:,(\d+))?\s+\+(\d+)(?:,(\d+))?\s+@@/;
|
|
20
|
+
/**
|
|
21
|
+
* Parse unified diff content to extract hunk line ranges.
|
|
22
|
+
*
|
|
23
|
+
* @param diffContent - Raw unified diff content for a single file
|
|
24
|
+
* @returns Array of DiffHunk objects with line ranges
|
|
25
|
+
*/
|
|
26
|
+
export function parseHunks(diffContent) {
|
|
27
|
+
const hunks = [];
|
|
28
|
+
const lines = diffContent.split('\n');
|
|
29
|
+
for (const line of lines) {
|
|
30
|
+
const match = HUNK_HEADER_RE.exec(line);
|
|
31
|
+
if (match) {
|
|
32
|
+
hunks.push({
|
|
33
|
+
oldStart: Number.parseInt(match[1], 10),
|
|
34
|
+
oldCount: match[2] !== undefined ? Number.parseInt(match[2], 10) : 1,
|
|
35
|
+
newStart: Number.parseInt(match[3], 10),
|
|
36
|
+
newCount: match[4] !== undefined ? Number.parseInt(match[4], 10) : 1,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return hunks;
|
|
41
|
+
}
|
|
42
|
+
// ─── Symbol Mapping ────────────────────────────────────────────
|
|
43
|
+
/**
|
|
44
|
+
* Map diff hunks to affected symbols.
|
|
45
|
+
*
|
|
46
|
+
* A symbol is considered "affected" if any hunk's NEW side line range
|
|
47
|
+
* overlaps with the symbol's line range. We use the new side because
|
|
48
|
+
* we're analyzing the post-change source code.
|
|
49
|
+
*
|
|
50
|
+
* @param hunks - Parsed diff hunks
|
|
51
|
+
* @param symbols - Extracted symbols from the NEW version of the file
|
|
52
|
+
* @returns Array of affected symbols with their overlapping hunks
|
|
53
|
+
*/
|
|
54
|
+
export function mapDiffToSymbols(hunks, symbols) {
|
|
55
|
+
if (hunks.length === 0 || symbols.length === 0)
|
|
56
|
+
return [];
|
|
57
|
+
const affected = [];
|
|
58
|
+
for (const symbol of symbols) {
|
|
59
|
+
const overlapping = hunks.filter((hunk) => rangesOverlap(hunk.newStart, hunk.newStart + Math.max(hunk.newCount - 1, 0), symbol.startLine, symbol.endLine));
|
|
60
|
+
if (overlapping.length > 0) {
|
|
61
|
+
affected.push({ symbol, overlappingHunks: overlapping });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return affected;
|
|
65
|
+
}
|
|
66
|
+
// ─── Helpers ───────────────────────────────────────────────────
|
|
67
|
+
/**
|
|
68
|
+
* Check if two 1-based line ranges overlap.
|
|
69
|
+
*
|
|
70
|
+
* Two ranges [a1, a2] and [b1, b2] overlap when:
|
|
71
|
+
* a1 <= b2 AND b1 <= a2
|
|
72
|
+
*/
|
|
73
|
+
function rangesOverlap(aStart, aEnd, bStart, bEnd) {
|
|
74
|
+
return aStart <= bEnd && bStart <= aEnd;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=diff-mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-mapper.js","sourceRoot":"","sources":["../../src/scope/diff-mapper.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,kEAAkE;AAElE;;;;;;;;GAQG;AACH,MAAM,cAAc,GAAG,mDAAmD,CAAC;AAE3E;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,WAAmB;IAC5C,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,IAAI,CAAC;gBACT,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC;gBACxC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC;gBACxC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;aACrE,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,kEAAkE;AAElE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAiB,EAAE,OAAqB;IACvE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE1D,MAAM,QAAQ,GAAqB,EAAE,CAAC;IAEtC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CACxC,aAAa,CACX,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC,CAAC,EAC9C,MAAM,CAAC,SAAS,EAChB,MAAM,CAAC,OAAO,CACf,CACF,CAAC;QAEF,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,kEAAkE;AAElE;;;;;GAKG;AACH,SAAS,aAAa,CACpB,MAAc,EACd,IAAY,EACZ,MAAc,EACd,IAAY;IAEZ,OAAO,MAAM,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Symbol Extractor
|
|
3
|
+
*
|
|
4
|
+
* Extracts symbol definitions (functions, classes, methods, interfaces)
|
|
5
|
+
* from source code using tree-sitter AST walking.
|
|
6
|
+
*
|
|
7
|
+
* Uses cursor-based traversal instead of S-expression queries for
|
|
8
|
+
* maximum compatibility across grammar versions.
|
|
9
|
+
*
|
|
10
|
+
* Pure function signature: (source, language, tree) => SymbolInfo[]
|
|
11
|
+
*/
|
|
12
|
+
import type { Tree } from 'web-tree-sitter';
|
|
13
|
+
import type { ScopeLanguage, SymbolInfo } from './types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Extract symbol definitions from a parsed tree-sitter tree.
|
|
16
|
+
*
|
|
17
|
+
* Walks the AST using a cursor and identifies functions, classes,
|
|
18
|
+
* methods, and interfaces based on language-specific node types.
|
|
19
|
+
*
|
|
20
|
+
* @param tree - Parsed tree-sitter tree
|
|
21
|
+
* @param language - The scope language
|
|
22
|
+
* @returns Array of extracted symbols
|
|
23
|
+
*/
|
|
24
|
+
export declare function extractSymbolsFromTree(tree: Tree, language: ScopeLanguage): SymbolInfo[];
|
|
25
|
+
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/scope/extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAQ,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAc,MAAM,YAAY,CAAC;AA+DxE;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,aAAa,GACtB,UAAU,EAAE,CAad"}
|