lsp-intelligence 0.1.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.
Files changed (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +250 -0
  3. package/dist/engine/DocumentManager.d.ts +20 -0
  4. package/dist/engine/DocumentManager.js +73 -0
  5. package/dist/engine/DocumentManager.js.map +1 -0
  6. package/dist/engine/LspEngine.d.ts +50 -0
  7. package/dist/engine/LspEngine.js +339 -0
  8. package/dist/engine/LspEngine.js.map +1 -0
  9. package/dist/engine/positions.d.ts +31 -0
  10. package/dist/engine/positions.js +55 -0
  11. package/dist/engine/positions.js.map +1 -0
  12. package/dist/engine/types.d.ts +61 -0
  13. package/dist/engine/types.js +33 -0
  14. package/dist/engine/types.js.map +1 -0
  15. package/dist/format/markdown.d.ts +5 -0
  16. package/dist/format/markdown.js +90 -0
  17. package/dist/format/markdown.js.map +1 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.js +87 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/tools/composites/batchQuery.d.ts +1 -0
  22. package/dist/tools/composites/batchQuery.js +40 -0
  23. package/dist/tools/composites/batchQuery.js.map +1 -0
  24. package/dist/tools/composites/explainError.d.ts +1 -0
  25. package/dist/tools/composites/explainError.js +56 -0
  26. package/dist/tools/composites/explainError.js.map +1 -0
  27. package/dist/tools/composites/findTestFiles.d.ts +1 -0
  28. package/dist/tools/composites/findTestFiles.js +57 -0
  29. package/dist/tools/composites/findTestFiles.js.map +1 -0
  30. package/dist/tools/composites/impactTrace.d.ts +1 -0
  31. package/dist/tools/composites/impactTrace.js +149 -0
  32. package/dist/tools/composites/impactTrace.js.map +1 -0
  33. package/dist/tools/composites/inspectSymbol.d.ts +1 -0
  34. package/dist/tools/composites/inspectSymbol.js +60 -0
  35. package/dist/tools/composites/inspectSymbol.js.map +1 -0
  36. package/dist/tools/composites/semanticDiff.d.ts +1 -0
  37. package/dist/tools/composites/semanticDiff.js +135 -0
  38. package/dist/tools/composites/semanticDiff.js.map +1 -0
  39. package/dist/tools/context/gatherContext.d.ts +1 -0
  40. package/dist/tools/context/gatherContext.js +153 -0
  41. package/dist/tools/context/gatherContext.js.map +1 -0
  42. package/dist/tools/context/outline.d.ts +1 -0
  43. package/dist/tools/context/outline.js +56 -0
  44. package/dist/tools/context/outline.js.map +1 -0
  45. package/dist/tools/live/autoImport.d.ts +1 -0
  46. package/dist/tools/live/autoImport.js +123 -0
  47. package/dist/tools/live/autoImport.js.map +1 -0
  48. package/dist/tools/live/findUnusedExports.d.ts +1 -0
  49. package/dist/tools/live/findUnusedExports.js +69 -0
  50. package/dist/tools/live/findUnusedExports.js.map +1 -0
  51. package/dist/tools/live/liveDiagnostics.d.ts +1 -0
  52. package/dist/tools/live/liveDiagnostics.js +38 -0
  53. package/dist/tools/live/liveDiagnostics.js.map +1 -0
  54. package/dist/tools/primitives/callHierarchy.d.ts +1 -0
  55. package/dist/tools/primitives/callHierarchy.js +61 -0
  56. package/dist/tools/primitives/callHierarchy.js.map +1 -0
  57. package/dist/tools/primitives/completions.d.ts +1 -0
  58. package/dist/tools/primitives/completions.js +31 -0
  59. package/dist/tools/primitives/completions.js.map +1 -0
  60. package/dist/tools/primitives/diagnostics.d.ts +1 -0
  61. package/dist/tools/primitives/diagnostics.js +32 -0
  62. package/dist/tools/primitives/diagnostics.js.map +1 -0
  63. package/dist/tools/primitives/documentSymbols.d.ts +1 -0
  64. package/dist/tools/primitives/documentSymbols.js +42 -0
  65. package/dist/tools/primitives/documentSymbols.js.map +1 -0
  66. package/dist/tools/primitives/fileExports.d.ts +1 -0
  67. package/dist/tools/primitives/fileExports.js +69 -0
  68. package/dist/tools/primitives/fileExports.js.map +1 -0
  69. package/dist/tools/primitives/fileImports.d.ts +1 -0
  70. package/dist/tools/primitives/fileImports.js +58 -0
  71. package/dist/tools/primitives/fileImports.js.map +1 -0
  72. package/dist/tools/primitives/findImplementations.d.ts +1 -0
  73. package/dist/tools/primitives/findImplementations.js +36 -0
  74. package/dist/tools/primitives/findImplementations.js.map +1 -0
  75. package/dist/tools/primitives/findReferences.d.ts +1 -0
  76. package/dist/tools/primitives/findReferences.js +42 -0
  77. package/dist/tools/primitives/findReferences.js.map +1 -0
  78. package/dist/tools/primitives/gotoDefinition.d.ts +1 -0
  79. package/dist/tools/primitives/gotoDefinition.js +37 -0
  80. package/dist/tools/primitives/gotoDefinition.js.map +1 -0
  81. package/dist/tools/primitives/gotoTypeDefinition.d.ts +1 -0
  82. package/dist/tools/primitives/gotoTypeDefinition.js +35 -0
  83. package/dist/tools/primitives/gotoTypeDefinition.js.map +1 -0
  84. package/dist/tools/primitives/hover.d.ts +1 -0
  85. package/dist/tools/primitives/hover.js +37 -0
  86. package/dist/tools/primitives/hover.js.map +1 -0
  87. package/dist/tools/primitives/rename.d.ts +1 -0
  88. package/dist/tools/primitives/rename.js +56 -0
  89. package/dist/tools/primitives/rename.js.map +1 -0
  90. package/dist/tools/primitives/typeHierarchy.d.ts +1 -0
  91. package/dist/tools/primitives/typeHierarchy.js +49 -0
  92. package/dist/tools/primitives/typeHierarchy.js.map +1 -0
  93. package/dist/tools/primitives/workspaceSymbols.d.ts +1 -0
  94. package/dist/tools/primitives/workspaceSymbols.js +32 -0
  95. package/dist/tools/primitives/workspaceSymbols.js.map +1 -0
  96. package/dist/tools/registry.d.ts +19 -0
  97. package/dist/tools/registry.js +19 -0
  98. package/dist/tools/registry.js.map +1 -0
  99. package/package.json +39 -0
@@ -0,0 +1,135 @@
1
+ import { z } from 'zod';
2
+ import { execSync } from 'child_process';
3
+ import { defineTool } from '../registry.js';
4
+ import { relativePath } from '../../engine/positions.js';
5
+ import { LspError, LspErrorCode, DEFAULT_TIMEOUTS } from '../../engine/types.js';
6
+ function parseDiffHunks(diff, workspaceRoot) {
7
+ const hunks = [];
8
+ let currentFile = '';
9
+ for (const line of diff.split('\n')) {
10
+ // +++ b/path/to/file.ts
11
+ const fileMatch = line.match(/^\+\+\+ b\/(.+)/);
12
+ if (fileMatch) {
13
+ currentFile = `${workspaceRoot}/${fileMatch[1]}`;
14
+ continue;
15
+ }
16
+ // @@ -old,count +new,count @@
17
+ const hunkMatch = line.match(/^@@ .+ \+(\d+)(?:,(\d+))? @@/);
18
+ if (hunkMatch && currentFile.match(/\.tsx?$/)) {
19
+ const start = parseInt(hunkMatch[1]);
20
+ const count = parseInt(hunkMatch[2] ?? '1');
21
+ hunks.push({ file: currentFile, startLine: start, endLine: start + count - 1 });
22
+ }
23
+ }
24
+ return hunks;
25
+ }
26
+ function findSymbolAtLine(symbols, line0) {
27
+ for (const sym of symbols) {
28
+ if (line0 >= sym.range.start.line && line0 <= sym.range.end.line) {
29
+ // Check children for more specific match
30
+ if (sym.children) {
31
+ const child = findSymbolAtLine(sym.children, line0);
32
+ if (child)
33
+ return child;
34
+ }
35
+ return sym;
36
+ }
37
+ }
38
+ return null;
39
+ }
40
+ const SYMBOL_KINDS = {
41
+ 5: 'Class', 6: 'Method', 10: 'Enum', 11: 'Interface',
42
+ 12: 'Function', 13: 'Variable', 14: 'Constant',
43
+ };
44
+ export const semanticDiff = defineTool({
45
+ name: 'semantic_diff',
46
+ description: 'Analyze git diff semantically: identify changed symbols and their blast radius. Answers "what did I change and what might break?" Requires git.',
47
+ schema: z.object({
48
+ base: z.string().optional().describe('Base ref to diff against. Defaults to merge-base with main branch.'),
49
+ verbosity: z.enum(['summary', 'normal', 'detailed']).default('normal'),
50
+ }),
51
+ async handler(params, engine) {
52
+ if (!engine.gitAvailable) {
53
+ throw new LspError(LspErrorCode.GIT_UNAVAILABLE, 'Git is not available in this workspace.');
54
+ }
55
+ const timeout = DEFAULT_TIMEOUTS.composite;
56
+ // Determine base ref
57
+ let base = params.base;
58
+ if (!base) {
59
+ try {
60
+ base = execSync('git merge-base HEAD main', { cwd: engine.workspaceRoot, encoding: 'utf-8' }).trim();
61
+ }
62
+ catch {
63
+ try {
64
+ base = execSync('git merge-base HEAD master', { cwd: engine.workspaceRoot, encoding: 'utf-8' }).trim();
65
+ }
66
+ catch {
67
+ base = 'HEAD~1';
68
+ }
69
+ }
70
+ }
71
+ // Get diff
72
+ let diff;
73
+ try {
74
+ diff = execSync(`git diff ${base} --unified=0`, { cwd: engine.workspaceRoot, encoding: 'utf-8' });
75
+ }
76
+ catch {
77
+ return 'No changes found or invalid base ref.';
78
+ }
79
+ if (!diff.trim())
80
+ return 'No changes found.';
81
+ const hunks = parseDiffHunks(diff, engine.workspaceRoot);
82
+ if (hunks.length === 0)
83
+ return 'No TypeScript file changes found.';
84
+ // For each changed hunk, identify the symbol
85
+ const changedSymbols = [];
86
+ const processedFiles = new Set();
87
+ for (const hunk of hunks) {
88
+ if (processedFiles.has(hunk.file))
89
+ continue;
90
+ try {
91
+ const { uri } = await engine.prepareFile(hunk.file);
92
+ const symbols = await engine.request('textDocument/documentSymbol', { textDocument: { uri } }, timeout);
93
+ if (symbols) {
94
+ // Find symbols affected by this hunk
95
+ for (let line = hunk.startLine - 1; line <= hunk.endLine - 1; line++) {
96
+ const sym = findSymbolAtLine(symbols, line);
97
+ if (sym && !changedSymbols.some((s) => s.name === sym.name && s.file === hunk.file)) {
98
+ // Get reference count for blast radius
99
+ const refs = await engine.request('textDocument/references', {
100
+ textDocument: { uri },
101
+ position: sym.selectionRange.start,
102
+ context: { includeDeclaration: false },
103
+ }, timeout).catch(() => null);
104
+ changedSymbols.push({
105
+ name: sym.name,
106
+ kind: SYMBOL_KINDS[sym.kind] ?? 'Unknown',
107
+ file: relativePath(hunk.file, engine.workspaceRoot),
108
+ refCount: refs?.length ?? 0,
109
+ });
110
+ }
111
+ }
112
+ }
113
+ }
114
+ catch { }
115
+ processedFiles.add(hunk.file);
116
+ }
117
+ if (changedSymbols.length === 0)
118
+ return 'No identifiable symbol changes found in diff.';
119
+ const totalRefs = changedSymbols.reduce((s, c) => s + c.refCount, 0);
120
+ const lines = [`# Semantic Diff\n`];
121
+ lines.push(`${changedSymbols.length} symbols changed, ${totalRefs} total references affected\n`);
122
+ for (const sym of changedSymbols.sort((a, b) => b.refCount - a.refCount)) {
123
+ const risk = sym.refCount > 10 ? '🔴' : sym.refCount > 3 ? '🟡' : '🟢';
124
+ lines.push(`${risk} **${sym.name}** (${sym.kind}) — ${sym.file}`);
125
+ if (sym.refCount > 0) {
126
+ lines.push(` → ${sym.refCount} references may need updating`);
127
+ }
128
+ else {
129
+ lines.push(` → No external references (safe to change)`);
130
+ }
131
+ }
132
+ return lines.join('\n');
133
+ },
134
+ });
135
+ //# sourceMappingURL=semanticDiff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semanticDiff.js","sourceRoot":"","sources":["../../../src/tools/composites/semanticDiff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAa,YAAY,EAAa,MAAM,2BAA2B,CAAC;AAE/E,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAQjF,SAAS,cAAc,CAAC,IAAY,EAAE,aAAqB;IACzD,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,IAAI,WAAW,GAAG,EAAE,CAAC;IAErB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,wBAAwB;QACxB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAChD,IAAI,SAAS,EAAE,CAAC;YACd,WAAW,GAAG,GAAG,aAAa,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,SAAS;QACX,CAAC;QACD,8BAA8B;QAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC7D,IAAI,SAAS,IAAI,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;YAC5C,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAyB,EAAE,KAAa;IAChE,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACjE,yCAAyC;YACzC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;gBACpD,IAAI,KAAK;oBAAE,OAAO,KAAK,CAAC;YAC1B,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,YAAY,GAA2B;IAC3C,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW;IACpD,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU;CAC/C,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;IACrC,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,iJAAiJ;IAC9J,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oEAAoE,CAAC;QAC1G,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;KACvE,CAAC;IACF,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM;QAC1B,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YACzB,MAAM,IAAI,QAAQ,CAAC,YAAY,CAAC,eAAe,EAAE,yCAAyC,CAAC,CAAC;QAC9F,CAAC;QAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC;QAE3C,qBAAqB;QACrB,IAAI,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,CAAC;gBACH,IAAI,GAAG,QAAQ,CAAC,0BAA0B,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACvG,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC;oBACH,IAAI,GAAG,QAAQ,CAAC,4BAA4B,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzG,CAAC;gBAAC,MAAM,CAAC;oBACP,IAAI,GAAG,QAAQ,CAAC;gBAClB,CAAC;YACH,CAAC;QACH,CAAC;QAED,WAAW;QACX,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,QAAQ,CAAC,YAAY,IAAI,cAAc,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QACpG,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,uCAAuC,CAAC;QACjD,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,OAAO,mBAAmB,CAAC;QAE7C,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;QACzD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,mCAAmC,CAAC;QAEnE,6CAA6C;QAC7C,MAAM,cAAc,GAAqE,EAAE,CAAC;QAC5F,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;QAEzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,SAAS;YAE5C,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACpD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,OAAO,CAClC,6BAA6B,EAAE,EAAE,YAAY,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,CAClE,CAAC;gBAEF,IAAI,OAAO,EAAE,CAAC;oBACZ,qCAAqC;oBACrC,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC;wBACrE,MAAM,GAAG,GAAG,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;wBAC5C,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;4BACpF,uCAAuC;4BACvC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAC/B,yBAAyB,EAAE;gCACzB,YAAY,EAAE,EAAE,GAAG,EAAE;gCACrB,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,KAAK;gCAClC,OAAO,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE;6BACvC,EAAE,OAAO,CACX,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;4BAEpB,cAAc,CAAC,IAAI,CAAC;gCAClB,IAAI,EAAE,GAAG,CAAC,IAAI;gCACd,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,SAAS;gCACzC,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,aAAa,CAAC;gCACnD,QAAQ,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;6BAC5B,CAAC,CAAC;wBACL,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YACV,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,+CAA+C,CAAC;QAExF,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACrE,MAAM,KAAK,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,qBAAqB,SAAS,8BAA8B,CAAC,CAAC;QAEjG,KAAK,MAAM,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzE,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YACvE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,MAAM,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YAClE,IAAI,GAAG,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,QAAQ,+BAA+B,CAAC,CAAC;YACjE,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const gatherContext: import("../registry.js").ToolDef;
@@ -0,0 +1,153 @@
1
+ import { z } from 'zod';
2
+ import * as fs from 'fs';
3
+ import { defineTool } from '../registry.js';
4
+ import { relativePath, uriToPath } from '../../engine/positions.js';
5
+ import { formatHover } from '../../format/markdown.js';
6
+ import { DEFAULT_TIMEOUTS } from '../../engine/types.js';
7
+ function estimateTokens(text) {
8
+ return Math.ceil(text.length / 3.0);
9
+ }
10
+ function extractSymbolBody(content, startLine, endLine) {
11
+ const lines = content.split('\n');
12
+ return lines.slice(startLine, endLine + 1).map((l, i) => `${startLine + i + 1}| ${l}`).join('\n');
13
+ }
14
+ export const gatherContext = defineTool({
15
+ name: 'gather_context',
16
+ description: 'Build minimal, complete context for a task. Given entry symbols, traces the impact graph, extracts only relevant code, and returns a token-budgeted context with must-modify / verify-only / skip classification.',
17
+ schema: z.object({
18
+ symbols: z.array(z.string()).describe('Entry point symbol names'),
19
+ max_tokens: z.number().default(100000).describe('Token budget for the output. Default is generous — the agent should adjust based on remaining context window.'),
20
+ depth: z.number().default(2).describe('How many levels of references to follow'),
21
+ }),
22
+ async handler(params, engine) {
23
+ const timeout = DEFAULT_TIMEOUTS.context;
24
+ const nodes = [];
25
+ let tokensUsed = 0;
26
+ // Phase 1: Resolve entry points
27
+ const entries = [];
28
+ for (const sym of params.symbols) {
29
+ try {
30
+ const resolved = await engine.resolveSymbol(sym);
31
+ entries.push({ uri: resolved.uri, position: resolved.position, name: resolved.name ?? sym });
32
+ }
33
+ catch { }
34
+ }
35
+ if (entries.length === 0)
36
+ return 'Error: Could not resolve any of the provided symbols.';
37
+ // Phase 2: Build impact graph (simplified BFS)
38
+ const visited = new Set();
39
+ const fileSymbols = new Map();
40
+ for (const entry of entries) {
41
+ const queue = [
42
+ { uri: entry.uri, position: entry.position, depth: 0 },
43
+ ];
44
+ while (queue.length > 0) {
45
+ const current = queue.shift();
46
+ if (current.depth > params.depth)
47
+ continue;
48
+ const key = `${current.uri}:${current.position.line}`;
49
+ if (visited.has(key))
50
+ continue;
51
+ visited.add(key);
52
+ const file = uriToPath(current.uri);
53
+ const existing = fileSymbols.get(file);
54
+ if (!existing || existing.depth > current.depth) {
55
+ fileSymbols.set(file, { depth: current.depth, symbols: [entry.name] });
56
+ }
57
+ // Find references at this position
58
+ if (current.depth < params.depth) {
59
+ const refs = await engine.request('textDocument/references', {
60
+ textDocument: { uri: current.uri },
61
+ position: current.position,
62
+ context: { includeDeclaration: false },
63
+ }, timeout).catch(() => null);
64
+ if (refs) {
65
+ for (const ref of refs.slice(0, 20)) { // limit BFS breadth
66
+ queue.push({ uri: ref.uri, position: ref.range.start, depth: current.depth + 1 });
67
+ }
68
+ }
69
+ }
70
+ }
71
+ }
72
+ // Phase 3: Classify and budget
73
+ const sorted = [...fileSymbols.entries()].sort((a, b) => a[1].depth - b[1].depth);
74
+ const sections = {
75
+ mustModify: [],
76
+ verifyOnly: [],
77
+ skip: [],
78
+ };
79
+ for (const [file, info] of sorted) {
80
+ const rel = relativePath(file, engine.workspaceRoot);
81
+ const isTest = /\.(spec|test|stories)\.(ts|tsx)$/.test(file);
82
+ if (isTest) {
83
+ sections.skip.push(rel);
84
+ continue;
85
+ }
86
+ const category = info.depth === 0 ? 'must-modify' : info.depth === 1 ? 'verify-only' : 'skip';
87
+ if (category === 'must-modify' && tokensUsed < params.max_tokens) {
88
+ // Full function bodies for must-modify
89
+ try {
90
+ const content = fs.readFileSync(file, 'utf-8');
91
+ const uri = `file://${file}`;
92
+ const symbols = await engine.request('textDocument/documentSymbol', { textDocument: { uri } }, timeout).catch(() => null);
93
+ if (symbols && symbols.length > 0) {
94
+ // Find the relevant symbol(s)
95
+ for (const sym of symbols) {
96
+ const body = extractSymbolBody(content, sym.range.start.line, Math.min(sym.range.end.line, sym.range.start.line + 30));
97
+ const tokens = estimateTokens(body);
98
+ if (tokensUsed + tokens <= params.max_tokens) {
99
+ sections.mustModify.push(`### ${rel}: ${sym.name}\n\`\`\`\n${body}\n\`\`\``);
100
+ tokensUsed += tokens;
101
+ }
102
+ }
103
+ }
104
+ }
105
+ catch { }
106
+ }
107
+ else if (category === 'verify-only' && tokensUsed < params.max_tokens) {
108
+ // Signatures only for verify
109
+ try {
110
+ const uri = `file://${file}`;
111
+ await engine.prepareFile(file);
112
+ const hover = await engine.request('textDocument/hover', {
113
+ textDocument: { uri },
114
+ position: { line: 0, character: 0 },
115
+ }, 5000).catch(() => null);
116
+ const sig = hover ? formatHover(hover) : '';
117
+ const sigText = sig ? ` ${sig.substring(0, 100)}` : '';
118
+ const tokens = estimateTokens(rel + sigText);
119
+ if (tokensUsed + tokens <= params.max_tokens) {
120
+ sections.verifyOnly.push(`- ${rel}${sigText}`);
121
+ tokensUsed += tokens;
122
+ }
123
+ }
124
+ catch {
125
+ sections.verifyOnly.push(`- ${rel}`);
126
+ }
127
+ }
128
+ else {
129
+ sections.skip.push(rel);
130
+ }
131
+ }
132
+ // Phase 4: Format output
133
+ const entryNames = params.symbols.join(', ');
134
+ const lines = [`# Context for: ${entryNames}\n`];
135
+ lines.push(`${visited.size} symbols traced, ~${tokensUsed} tokens used of ${params.max_tokens} budget\n`);
136
+ if (sections.mustModify.length > 0) {
137
+ lines.push(`## Must modify (${sections.mustModify.length} sections)\n`);
138
+ lines.push(sections.mustModify.join('\n\n'));
139
+ lines.push('');
140
+ }
141
+ if (sections.verifyOnly.length > 0) {
142
+ lines.push(`\n## Verify only (${sections.verifyOnly.length} files)\n`);
143
+ lines.push(sections.verifyOnly.join('\n'));
144
+ lines.push('');
145
+ }
146
+ if (sections.skip.length > 0) {
147
+ lines.push(`\n## Skip (${sections.skip.length} files — update after implementation)\n`);
148
+ lines.push(sections.skip.map((f) => `- ${f}`).join('\n'));
149
+ }
150
+ return lines.join('\n');
151
+ },
152
+ });
153
+ //# sourceMappingURL=gatherContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gatherContext.js","sourceRoot":"","sources":["../../../src/tools/context/gatherContext.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const outline: import("../registry.js").ToolDef;
@@ -0,0 +1,56 @@
1
+ import { z } from 'zod';
2
+ import { defineTool } from '../registry.js';
3
+ import { relativePath } from '../../engine/positions.js';
4
+ import { formatHover } from '../../format/markdown.js';
5
+ import { DEFAULT_TIMEOUTS } from '../../engine/types.js';
6
+ const SYMBOL_KINDS = {
7
+ 5: 'class', 6: 'method', 7: 'property', 10: 'enum', 11: 'interface',
8
+ 12: 'function', 13: 'variable', 14: 'constant', 22: 'enum member',
9
+ };
10
+ export const outline = defineTool({
11
+ name: 'outline',
12
+ description: 'Get a file\'s structure with type signatures — understand a file in 50 tokens instead of reading 2000 lines. Shows classes, functions, interfaces with their signatures.',
13
+ schema: z.object({
14
+ file_path: z.string().describe('Absolute file path'),
15
+ include_signatures: z.boolean().default(true).describe('Include type signatures from hover'),
16
+ }),
17
+ async handler(params, engine) {
18
+ const { uri } = await engine.prepareFile(params.file_path);
19
+ const timeout = DEFAULT_TIMEOUTS.context;
20
+ const symbols = await engine.request('textDocument/documentSymbol', { textDocument: { uri } }, timeout);
21
+ if (!symbols || symbols.length === 0)
22
+ return 'No symbols found.';
23
+ const rel = relativePath(params.file_path, engine.workspaceRoot);
24
+ const lines = [`# ${rel}\n`];
25
+ async function renderSymbol(sym, indent) {
26
+ const kind = SYMBOL_KINDS[sym.kind] ?? 'unknown';
27
+ const prefix = indent === 0 ? '' : ' '.repeat(indent) + '├── ';
28
+ let sig = '';
29
+ if (params.include_signatures && indent < 2) {
30
+ // Get hover for type signature (only top-level + 1 depth to limit requests)
31
+ const hover = await engine.request('textDocument/hover', {
32
+ textDocument: { uri },
33
+ position: sym.selectionRange.start,
34
+ }, 5000).catch(() => null);
35
+ if (hover) {
36
+ const hoverText = formatHover(hover);
37
+ // Extract just the signature line (first code block content)
38
+ const sigMatch = hoverText.match(/```\w*\n([^\n]+)/);
39
+ if (sigMatch)
40
+ sig = ` — \`${sigMatch[1].trim()}\``;
41
+ }
42
+ }
43
+ lines.push(`${prefix}**${sym.name}** (${kind})${sig}`);
44
+ if (sym.children) {
45
+ for (const child of sym.children) {
46
+ await renderSymbol(child, indent + 1);
47
+ }
48
+ }
49
+ }
50
+ for (const sym of symbols) {
51
+ await renderSymbol(sym, 0);
52
+ }
53
+ return lines.join('\n');
54
+ },
55
+ });
56
+ //# sourceMappingURL=outline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outline.js","sourceRoot":"","sources":["../../../src/tools/context/outline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const autoImport: import("../registry.js").ToolDef;
@@ -0,0 +1,123 @@
1
+ import { z } from 'zod';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import { defineTool } from '../registry.js';
5
+ import { relativePath, uriToPath } from '../../engine/positions.js';
6
+ import { DEFAULT_TIMEOUTS } from '../../engine/types.js';
7
+ /**
8
+ * Read tsconfig.json paths from a directory, walking up to find the nearest one.
9
+ */
10
+ function findTsConfigPaths(startDir, workspaceRoot) {
11
+ let dir = startDir;
12
+ while (dir.startsWith(workspaceRoot)) {
13
+ const tsconfigPath = path.join(dir, 'tsconfig.json');
14
+ if (fs.existsSync(tsconfigPath)) {
15
+ try {
16
+ const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, 'utf-8'));
17
+ if (tsconfig.compilerOptions?.paths) {
18
+ return tsconfig.compilerOptions.paths;
19
+ }
20
+ }
21
+ catch { }
22
+ }
23
+ const parent = path.dirname(dir);
24
+ if (parent === dir)
25
+ break;
26
+ dir = parent;
27
+ }
28
+ return null;
29
+ }
30
+ /**
31
+ * Match a source file path against tsconfig paths to find the alias.
32
+ * E.g., paths: { "@myorg/core/*": ["../core/src/*"] }
33
+ * sourcePath: /repo/packages/core/src/sdk.ts
34
+ * tsconfigDir: /repo/packages/app
35
+ * → returns "@myorg/core/sdk"
36
+ */
37
+ function resolveAlias(sourcePath, paths, tsconfigDir) {
38
+ for (const [alias, targets] of Object.entries(paths)) {
39
+ for (const target of targets) {
40
+ // Resolve the target relative to the tsconfig directory
41
+ const resolvedTarget = path.resolve(tsconfigDir, target.replace(/\/?\*$/, ''));
42
+ if (sourcePath.startsWith(resolvedTarget)) {
43
+ const remainder = sourcePath
44
+ .slice(resolvedTarget.length)
45
+ .replace(/^\//, '')
46
+ .replace(/\/index\.tsx?$/, '')
47
+ .replace(/\.tsx?$/, '');
48
+ const aliasBase = alias.replace(/\/?\*$/, '');
49
+ return remainder ? `${aliasBase}/${remainder}` : aliasBase;
50
+ }
51
+ }
52
+ }
53
+ return null;
54
+ }
55
+ export const autoImport = defineTool({
56
+ name: 'auto_import',
57
+ description: 'Resolve the correct import path for a symbol name. Uses tsconfig paths when available. Eliminates wrong import paths — the most common agent mistake.',
58
+ schema: z.object({
59
+ symbol: z.string().describe('Symbol name to import, e.g. "UserService"'),
60
+ from_file: z.string().optional().describe('File that needs the import (for tsconfig paths resolution)'),
61
+ }),
62
+ async handler(params, engine) {
63
+ const resolved = await engine.resolveSymbol(params.symbol);
64
+ const defUri = resolved.uri;
65
+ const defPath = uriToPath(defUri);
66
+ // Follow to the actual definition (not re-export)
67
+ const def = await engine.request('textDocument/definition', {
68
+ textDocument: { uri: defUri },
69
+ position: resolved.position,
70
+ }, DEFAULT_TIMEOUTS.live).catch(() => null);
71
+ const sourcePath = def
72
+ ? uriToPath(Array.isArray(def) ? def[0].uri : def.uri)
73
+ : defPath;
74
+ const rel = relativePath(sourcePath, engine.workspaceRoot);
75
+ let importPath = rel;
76
+ // Strategy 1: Use tsconfig paths (most accurate — respects aliases)
77
+ const fromDir = params.from_file
78
+ ? path.dirname(params.from_file)
79
+ : engine.workspaceRoot;
80
+ const tsconfigPaths = findTsConfigPaths(fromDir, engine.workspaceRoot);
81
+ if (tsconfigPaths) {
82
+ const tsconfigDir = findTsConfigDir(fromDir, engine.workspaceRoot);
83
+ if (tsconfigDir) {
84
+ const alias = resolveAlias(sourcePath, tsconfigPaths, tsconfigDir);
85
+ if (alias)
86
+ importPath = alias;
87
+ }
88
+ }
89
+ // Strategy 2: Fall back to package.json name
90
+ if (importPath === rel) {
91
+ const pkgMatch = sourcePath.match(/\/(packages|apps|libs|modules|services)\/([^/]+)\//);
92
+ if (pkgMatch) {
93
+ const pkgDir = sourcePath.substring(0, sourcePath.indexOf(`/${pkgMatch[1]}/${pkgMatch[2]}/`) + `/${pkgMatch[1]}/${pkgMatch[2]}`.length + 1);
94
+ const pkgJsonPath = path.join(pkgDir, 'package.json');
95
+ try {
96
+ const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
97
+ if (pkgJson.name) {
98
+ const afterPkg = sourcePath.replace(pkgDir, '');
99
+ const cleanPath = afterPkg.replace(/^\/src/, '').replace(/\/index\.tsx?$/, '').replace(/\.tsx?$/, '');
100
+ importPath = !cleanPath || cleanPath === '/'
101
+ ? pkgJson.name
102
+ : `${pkgJson.name}${cleanPath}`;
103
+ }
104
+ }
105
+ catch { }
106
+ }
107
+ }
108
+ return `# Auto Import: ${params.symbol}\n\n\`\`\`typescript\nimport { ${params.symbol} } from "${importPath}";\n\`\`\`\n\nSource: ${rel}`;
109
+ },
110
+ });
111
+ function findTsConfigDir(startDir, workspaceRoot) {
112
+ let dir = startDir;
113
+ while (dir.startsWith(workspaceRoot)) {
114
+ if (fs.existsSync(path.join(dir, 'tsconfig.json')))
115
+ return dir;
116
+ const parent = path.dirname(dir);
117
+ if (parent === dir)
118
+ break;
119
+ dir = parent;
120
+ }
121
+ return null;
122
+ }
123
+ //# sourceMappingURL=autoImport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoImport.js","sourceRoot":"","sources":["../../../src/tools/live/autoImport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const findUnusedExports: import("../registry.js").ToolDef;
@@ -0,0 +1,69 @@
1
+ import { z } from 'zod';
2
+ import * as fs from 'fs';
3
+ import { defineTool } from '../registry.js';
4
+ import { relativePath, getPackageName } from '../../engine/positions.js';
5
+ import { DEFAULT_TIMEOUTS } from '../../engine/types.js';
6
+ export const findUnusedExports = defineTool({
7
+ name: 'find_unused_exports',
8
+ description: 'Find exported symbols with zero cross-package importers. Identifies dead code that can safely be removed.',
9
+ schema: z.object({
10
+ file_path: z.string().describe('Absolute file path to check'),
11
+ }),
12
+ async handler(params, engine) {
13
+ const { uri } = await engine.prepareFile(params.file_path);
14
+ const content = fs.readFileSync(params.file_path, 'utf-8');
15
+ const lines = content.split('\n');
16
+ const timeout = DEFAULT_TIMEOUTS.live;
17
+ const symbols = await engine.request('textDocument/documentSymbol', { textDocument: { uri } }, timeout);
18
+ if (!symbols)
19
+ return 'Could not get symbols for this file.';
20
+ const currentPkg = getPackageName(params.file_path);
21
+ const unused = [];
22
+ const KINDS = { 5: 'Class', 10: 'Enum', 11: 'Interface', 12: 'Function', 13: 'Variable', 14: 'Constant' };
23
+ const checkSymbol = async (sym) => {
24
+ const lineText = lines[sym.range.start.line] ?? '';
25
+ if (!lineText.includes('export'))
26
+ return;
27
+ const refs = await engine.request('textDocument/references', {
28
+ textDocument: { uri },
29
+ position: sym.selectionRange.start,
30
+ context: { includeDeclaration: false },
31
+ }, timeout).catch(() => null);
32
+ if (!refs || refs.length === 0) {
33
+ unused.push({
34
+ name: sym.name,
35
+ kind: KINDS[sym.kind] ?? 'Unknown',
36
+ line: sym.range.start.line + 1,
37
+ });
38
+ return;
39
+ }
40
+ // Check if all references are within the same package
41
+ if (currentPkg) {
42
+ const crossPkg = refs.filter((r) => {
43
+ const refPkg = getPackageName(r.uri);
44
+ return refPkg && refPkg !== currentPkg;
45
+ });
46
+ if (crossPkg.length === 0) {
47
+ unused.push({
48
+ name: sym.name,
49
+ kind: KINDS[sym.kind] ?? 'Unknown',
50
+ line: sym.range.start.line + 1,
51
+ });
52
+ }
53
+ }
54
+ };
55
+ for (const sym of symbols) {
56
+ await checkSymbol(sym);
57
+ }
58
+ const rel = relativePath(params.file_path, engine.workspaceRoot);
59
+ if (unused.length === 0)
60
+ return `✅ ${rel} — all exports are used cross-package.`;
61
+ const result = [`# Unused Exports: ${rel}\n\n${unused.length} exports with no cross-package importers\n`];
62
+ for (const u of unused) {
63
+ result.push(`- L${u.line}: **${u.name}** (${u.kind})`);
64
+ }
65
+ result.push('\n*These may be safe to remove or make package-private.*');
66
+ return result.join('\n');
67
+ },
68
+ });
69
+ //# sourceMappingURL=findUnusedExports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findUnusedExports.js","sourceRoot":"","sources":["../../../src/tools/live/findUnusedExports.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const liveDiagnostics: import("../registry.js").ToolDef;