@mrclrchtr/supi-code-intelligence 1.5.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.
Files changed (80) hide show
  1. package/README.md +42 -24
  2. package/node_modules/@mrclrchtr/supi-core/package.json +6 -2
  3. package/node_modules/@mrclrchtr/supi-core/src/api.ts +12 -1
  4. package/node_modules/@mrclrchtr/supi-core/src/config/config.ts +1 -1
  5. package/node_modules/@mrclrchtr/supi-core/src/index.ts +12 -1
  6. package/node_modules/@mrclrchtr/supi-core/src/tool-framework.ts +116 -0
  7. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +6 -2
  8. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/api.ts +12 -1
  9. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config/config.ts +1 -1
  10. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/index.ts +12 -1
  11. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/tool-framework.ts +116 -0
  12. package/node_modules/@mrclrchtr/supi-lsp/package.json +10 -3
  13. package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +8 -5
  14. package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +79 -190
  15. package/node_modules/@mrclrchtr/supi-lsp/src/config/server-config.ts +38 -0
  16. package/node_modules/@mrclrchtr/supi-lsp/src/config/types.ts +61 -387
  17. package/node_modules/@mrclrchtr/supi-lsp/src/format.ts +16 -8
  18. package/node_modules/@mrclrchtr/supi-lsp/src/lsp.ts +2 -2
  19. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-project-info.ts +1 -1
  20. package/node_modules/@mrclrchtr/supi-lsp/src/pattern-matcher.ts +11 -184
  21. package/node_modules/@mrclrchtr/supi-lsp/src/session/lsp-state.ts +1 -1
  22. package/node_modules/@mrclrchtr/supi-lsp/src/tool/guidance.ts +1 -1
  23. package/node_modules/@mrclrchtr/supi-lsp/src/tool/tool-specs.ts +1 -1
  24. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +6 -2
  25. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/api.ts +12 -1
  26. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config.ts +1 -1
  27. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/index.ts +12 -1
  28. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/tool-framework.ts +116 -0
  29. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/LICENSE +21 -0
  30. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/README.md +265 -0
  31. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.cjs +4661 -0
  32. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.cjs.map +7 -0
  33. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.js +4605 -0
  34. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.js.map +7 -0
  35. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm +0 -0
  36. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm.map +57 -0
  37. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/package.json +100 -0
  38. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.cjs +4063 -0
  39. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.cjs.map +7 -0
  40. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.cts +1025 -0
  41. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.cts.map +58 -0
  42. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.ts +1025 -0
  43. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.ts.map +58 -0
  44. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.js +4007 -0
  45. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.js.map +7 -0
  46. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm +0 -0
  47. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm.map +55 -0
  48. package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +2 -2
  49. package/package.json +4 -4
  50. package/src/actions/affected-action.ts +67 -54
  51. package/src/actions/brief-action.ts +142 -5
  52. package/src/actions/callees-action.ts +1 -1
  53. package/src/actions/callers-action.ts +38 -67
  54. package/src/actions/implementations-action.ts +27 -63
  55. package/src/actions/map-action.ts +206 -0
  56. package/src/actions/pattern-action.ts +1 -1
  57. package/src/api.ts +1 -0
  58. package/src/brief-focused.ts +5 -5
  59. package/src/brief.ts +3 -3
  60. package/src/code-intelligence.ts +6 -75
  61. package/src/index.ts +1 -0
  62. package/src/pattern-structured.ts +1 -1
  63. package/src/prioritization-signals.ts +13 -26
  64. package/src/query-params.ts +15 -0
  65. package/src/resolve-target.ts +2 -2
  66. package/src/search-helpers.ts +2 -2
  67. package/src/target-resolution.ts +27 -102
  68. package/src/tool/execute-affected.ts +25 -0
  69. package/src/tool/execute-brief.ts +25 -0
  70. package/src/tool/execute-map.ts +32 -0
  71. package/src/tool/execute-pattern.ts +26 -0
  72. package/src/tool/execute-relations.ts +48 -0
  73. package/src/tool/guidance.ts +24 -13
  74. package/src/tool/register-tools.ts +32 -0
  75. package/src/tool/tool-specs.ts +184 -0
  76. package/src/tool/validation.ts +43 -0
  77. package/src/types.ts +10 -0
  78. package/src/actions/index-action.ts +0 -187
  79. package/src/tool/action-specs.ts +0 -66
  80. package/src/tool-actions.ts +0 -100
package/src/types.ts CHANGED
@@ -17,6 +17,15 @@ export interface BriefDetails {
17
17
  prioritySignals?: PrioritySignalsSummary | null;
18
18
  }
19
19
 
20
+ /** Structured details metadata for factual map results. */
21
+ export interface MapDetails {
22
+ scope: string | null;
23
+ totalFiles: number;
24
+ childDirectoryCount: number;
25
+ landmarkCount: number;
26
+ nextQueries: string[];
27
+ }
28
+
20
29
  /** Structured details metadata for relationship and pattern results. */
21
30
  export interface SearchDetails {
22
31
  confidence: ConfidenceMode;
@@ -56,6 +65,7 @@ export interface CodeIntelResult {
56
65
  content: string;
57
66
  details?:
58
67
  | { type: "brief"; data: BriefDetails }
68
+ | { type: "map"; data: MapDetails }
59
69
  | { type: "search"; data: SearchDetails }
60
70
  | { type: "affected"; data: AffectedDetails };
61
71
  }
@@ -1,187 +0,0 @@
1
- import * as fs from "node:fs";
2
- import * as path from "node:path";
3
- import type { CodeIntelResult, SearchDetails } from "../types.ts";
4
-
5
- const SOURCE_EXTENSIONS = new Map([
6
- [".ts", "TypeScript"],
7
- [".tsx", "TSX"],
8
- [".js", "JavaScript"],
9
- [".jsx", "JSX"],
10
- [".mts", "TypeScript"],
11
- [".cts", "TypeScript"],
12
- [".mjs", "JavaScript"],
13
- [".cjs", "JavaScript"],
14
- [".py", "Python"],
15
- [".pyi", "Python"],
16
- [".rs", "Rust"],
17
- [".go", "Go"],
18
- [".mod", "Go"],
19
- [".java", "Java"],
20
- [".kt", "Kotlin"],
21
- [".kts", "Kotlin"],
22
- [".rb", "Ruby"],
23
- [".php", "PHP"],
24
- [".swift", "Swift"],
25
- [".cpp", "C++"],
26
- [".hpp", "C++"],
27
- [".cc", "C++"],
28
- [".cxx", "C++"],
29
- [".hxx", "C++ Header"],
30
- [".c++", "C++"],
31
- [".h++", "C++ Header"],
32
- [".c", "C"],
33
- [".h", "C Header"],
34
- [".css", "CSS"],
35
- [".scss", "SCSS"],
36
- [".less", "Less"],
37
- [".html", "HTML"],
38
- [".htm", "HTML"],
39
- [".xhtml", "HTML"],
40
- [".json", "JSON"],
41
- [".yaml", "YAML"],
42
- [".yml", "YAML"],
43
- [".toml", "TOML"],
44
- [".md", "Markdown"],
45
- [".sh", "Shell"],
46
- [".bash", "Shell"],
47
- [".zsh", "Shell"],
48
- [".r", "R"],
49
- [".sql", "SQL"],
50
- [".cs", "C#"],
51
- ]);
52
-
53
- const LANDMARK_FILES = new Set([
54
- "package.json",
55
- "tsconfig.json",
56
- "jsconfig.json",
57
- "vite.config.ts",
58
- "vitest.config.ts",
59
- "jest.config.ts",
60
- "playwright.config.ts",
61
- "biome.json",
62
- "eslint.config.js",
63
- ".eslintrc.js",
64
- "deno.json",
65
- "deno.jsonc",
66
- "Cargo.toml",
67
- "go.mod",
68
- "pyproject.toml",
69
- "setup.py",
70
- "requirements.txt",
71
- "Makefile",
72
- "justfile",
73
- "Taskfile.yml",
74
- "Dockerfile",
75
- "docker-compose.yml",
76
- ".env.example",
77
- ".env.local.example",
78
- ]);
79
-
80
- export function executeIndexAction(cwd: string): CodeIntelResult {
81
- const stats = gatherStats(cwd);
82
- const content = formatIndex(stats, cwd);
83
- const details: SearchDetails = {
84
- confidence: "structural",
85
- scope: null,
86
- candidateCount: stats.total,
87
- omittedCount: 0,
88
- nextQueries: ["`code_intel brief` for deeper context on a module"],
89
- };
90
- return { content, details: { type: "search" as const, data: details } };
91
- }
92
-
93
- interface FileStats {
94
- byExtension: Map<string, number>;
95
- byTopDir: Map<string, number>;
96
- landmarkFiles: string[];
97
- total: number;
98
- }
99
-
100
- const SKIP_DIRS = new Set(["node_modules", "dist", "build", ".git"]);
101
-
102
- function shouldSkipEntry(entry: fs.Dirent): boolean {
103
- return entry.name.startsWith(".") || SKIP_DIRS.has(entry.name);
104
- }
105
-
106
- function gatherStats(cwd: string): FileStats {
107
- const byExtension = new Map<string, number>();
108
- const byTopDir = new Map<string, number>();
109
- const landmarkFiles: string[] = [];
110
- let total = 0;
111
-
112
- function processFile(entryRel: string, entryName: string) {
113
- total++;
114
- const ext = path.extname(entryName).toLowerCase();
115
- byExtension.set(ext, (byExtension.get(ext) ?? 0) + 1);
116
-
117
- const topDir = entryRel.split("/")[0] ?? ".";
118
- byTopDir.set(topDir, (byTopDir.get(topDir) ?? 0) + 1);
119
-
120
- if (LANDMARK_FILES.has(entryName)) {
121
- landmarkFiles.push(entryRel);
122
- }
123
- }
124
-
125
- function walk(dir: string, rel: string) {
126
- let entries: fs.Dirent[];
127
- try {
128
- entries = fs.readdirSync(dir, { withFileTypes: true });
129
- } catch {
130
- return;
131
- }
132
-
133
- for (const entry of entries) {
134
- if (shouldSkipEntry(entry)) continue;
135
-
136
- const entryRel = rel ? `${rel}/${entry.name}` : entry.name;
137
- const fullPath = path.join(dir, entry.name);
138
-
139
- if (entry.isDirectory()) {
140
- walk(fullPath, entryRel);
141
- } else {
142
- processFile(entryRel, entry.name);
143
- }
144
- }
145
- }
146
-
147
- walk(cwd, "");
148
- return { byExtension, byTopDir, landmarkFiles, total };
149
- }
150
-
151
- function formatIndex(stats: FileStats, cwd: string): string {
152
- const lines: string[] = [];
153
- const name = path.basename(cwd);
154
-
155
- lines.push(`# Project Map: ${name}`);
156
- lines.push("");
157
-
158
- lines.push(`**Source files:** ${stats.total} total`);
159
- for (const [ext, count] of [...stats.byExtension.entries()]
160
- .sort((a, b) => b[1] - a[1])
161
- .slice(0, 10)) {
162
- const label = SOURCE_EXTENSIONS.get(ext) ?? (ext || "(no extension)");
163
- lines.push(`- ${label}: ${count}`);
164
- }
165
- if (stats.byExtension.size > 10) {
166
- lines.push(`- _+${stats.byExtension.size - 10} more extensions_`);
167
- }
168
- lines.push("");
169
-
170
- if (stats.byTopDir.size > 0) {
171
- lines.push("**Top-level directories:**");
172
- for (const [dir, count] of [...stats.byTopDir.entries()].sort((a, b) => b[1] - a[1])) {
173
- lines.push(`- ${dir}/ (${count} file${count !== 1 ? "s" : ""})`);
174
- }
175
- lines.push("");
176
- }
177
-
178
- if (stats.landmarkFiles.length > 0) {
179
- lines.push("**Landmark files:**");
180
- for (const f of stats.landmarkFiles) {
181
- lines.push(`- \`${f}\``);
182
- }
183
- lines.push("");
184
- }
185
-
186
- return lines.join("\n");
187
- }
@@ -1,66 +0,0 @@
1
- /**
2
- * Single source of truth for the public `code_intel` action surface.
3
- *
4
- * The action list, prompt guidance, and router validation should derive from
5
- * these specs so the high-level orchestration tool stays internally coherent.
6
- */
7
- export const CODE_INTEL_ACTION_SPECS = [
8
- {
9
- name: "brief",
10
- promptGuideline:
11
- 'Use code_intel with `action: "brief"` for a project, package, directory, file, or anchored-position brief before opening more files.',
12
- },
13
- {
14
- name: "callers",
15
- promptGuideline:
16
- 'Use code_intel with `action: "callers"` to find who invokes a symbol or file-level surface before falling back to text search.',
17
- },
18
- {
19
- name: "callees",
20
- promptGuideline:
21
- 'Use code_intel with `action: "callees"` for outgoing calls from a function or method at a known `file`, `line`, and `character`.',
22
- },
23
- {
24
- name: "implementations",
25
- promptGuideline:
26
- 'Use code_intel with `action: "implementations"` to find which concrete types implement a declaration.',
27
- },
28
- {
29
- name: "affected",
30
- promptGuideline:
31
- 'Use code_intel with `action: "affected"` before edits for blast radius, downstream modules, risk, and likely follow-up checks or tests.',
32
- },
33
- {
34
- name: "pattern",
35
- promptGuideline:
36
- 'Use code_intel with `action: "pattern"` for bounded search within a path; `pattern` is literal by default, set `regex: true` for regex, and use `kind: "definition" | "export" | "import"` for structured search.',
37
- },
38
- {
39
- name: "index",
40
- promptGuideline:
41
- 'Use code_intel with `action: "index"` for a project map, top-level directories, language mix, or landmark files.',
42
- },
43
- ] as const;
44
-
45
- export type CodeIntelAction = (typeof CODE_INTEL_ACTION_SPECS)[number]["name"];
46
- export type CodeIntelActionSpec = (typeof CODE_INTEL_ACTION_SPECS)[number];
47
-
48
- /** Ordered action names for schemas, validation messages, and docs. */
49
- export const CODE_INTEL_ACTION_NAMES = CODE_INTEL_ACTION_SPECS.map(
50
- (spec) => spec.name,
51
- ) as readonly CodeIntelAction[];
52
-
53
- const CODE_INTEL_ACTION_NAME_SET = new Set<string>(CODE_INTEL_ACTION_NAMES);
54
-
55
- /** Check whether a runtime string is a supported `code_intel` action. */
56
- export function isCodeIntelAction(action: string): action is CodeIntelAction {
57
- return CODE_INTEL_ACTION_NAME_SET.has(action);
58
- }
59
-
60
- /** Format the public action list for validation messages and docs. */
61
- export function formatCodeIntelActionList(options?: { fenced?: boolean }): string {
62
- if (options?.fenced) {
63
- return CODE_INTEL_ACTION_NAMES.map((name) => `\`${name}\``).join(", ");
64
- }
65
- return CODE_INTEL_ACTION_NAMES.join(", ");
66
- }
@@ -1,100 +0,0 @@
1
- // Tool action router — dispatches code_intel actions to specific implementations.
2
-
3
- import * as fs from "node:fs";
4
- import { executeAffectedAction } from "./actions/affected-action.ts";
5
- import { executeBriefAction } from "./actions/brief-action.ts";
6
- import { executeCalleesAction } from "./actions/callees-action.ts";
7
- import { executeCallersAction } from "./actions/callers-action.ts";
8
- import { executeImplementationsAction } from "./actions/implementations-action.ts";
9
- import { executeIndexAction } from "./actions/index-action.ts";
10
- import { executePatternAction } from "./actions/pattern-action.ts";
11
- import { normalizePath } from "./search-helpers.ts";
12
- import {
13
- type CodeIntelAction,
14
- formatCodeIntelActionList,
15
- isCodeIntelAction,
16
- } from "./tool/action-specs.ts";
17
- import type { CodeIntelResult } from "./types.ts";
18
-
19
- export type { CodeIntelAction } from "./tool/action-specs.ts";
20
-
21
- /** Flat parameter bag shared by `code_intel` action handlers. */
22
- export interface ActionParams {
23
- action: CodeIntelAction;
24
- path?: string;
25
- file?: string;
26
- line?: number;
27
- character?: number;
28
- symbol?: string;
29
- /** Text search input for `action: "pattern"`; treated as literal unless `regex` is true. */
30
- pattern?: string;
31
- /** Opt into raw ripgrep regex semantics for `action: "pattern"`. */
32
- regex?: boolean;
33
- kind?: string;
34
- exportedOnly?: boolean;
35
- maxResults?: number;
36
- contextLines?: number;
37
- /** Aggregate counts by directory instead of line-level matches (pattern action only). */
38
- summary?: boolean;
39
- }
40
-
41
- type ActionHandler = (
42
- params: ActionParams,
43
- cwd: string,
44
- ) => CodeIntelResult | Promise<CodeIntelResult>;
45
-
46
- const ACTION_HANDLERS: Record<CodeIntelAction, ActionHandler> = {
47
- brief: executeBriefAction,
48
- callers: executeCallersAction,
49
- callees: executeCalleesAction,
50
- implementations: executeImplementationsAction,
51
- affected: executeAffectedAction,
52
- pattern: executePatternAction,
53
- index: (_params, cwd) => executeIndexAction(cwd),
54
- };
55
-
56
- /**
57
- * Main action dispatcher — validates params and routes to specific action handlers.
58
- * Returns structured content with optional metadata details per action type.
59
- */
60
- export async function executeAction(
61
- params: ActionParams,
62
- ctx: { cwd: string },
63
- ): Promise<CodeIntelResult> {
64
- const cwd = ctx.cwd;
65
- const error = validateParams(params, cwd);
66
- if (error) return { content: error, details: undefined };
67
-
68
- return ACTION_HANDLERS[params.action](params, cwd);
69
- }
70
-
71
- function validateParams(params: ActionParams, cwd: string): string | null {
72
- if (!params.action || !isCodeIntelAction(params.action)) {
73
- return `**Error:** Unknown action \`${params.action ?? "(none)"}\`. Supported: ${formatCodeIntelActionList({ fenced: true })}.`;
74
- }
75
-
76
- if (params.path && (params.line != null || params.character != null)) {
77
- return "**Error:** `line` and `character` require `file`, not `path`. Use `path` to scope/focus; use `file` to anchor a position.";
78
- }
79
-
80
- if (params.file) {
81
- const resolvedFile = normalizePath(params.file, cwd);
82
- if (fs.existsSync(resolvedFile) && fs.statSync(resolvedFile).isDirectory()) {
83
- return "**Error:** `file` points to a directory. Use `path` to scope a directory; use `file` to anchor a position in a file.";
84
- }
85
- }
86
-
87
- if ((params.line != null || params.character != null) && !params.file) {
88
- return "**Error:** `line` and `character` require `file`.";
89
- }
90
-
91
- if (
92
- params.action === "pattern" &&
93
- params.kind &&
94
- !new Set(["definition", "export", "import"]).has(params.kind)
95
- ) {
96
- return "**Error:** `pattern` action `kind` must be one of `definition`, `export`, or `import`.";
97
- }
98
-
99
- return null;
100
- }