@mrclrchtr/supi-code-intelligence 1.4.0 → 1.6.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 (57) hide show
  1. package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  2. package/node_modules/@mrclrchtr/supi-core/src/api.ts +2 -0
  3. package/node_modules/@mrclrchtr/supi-core/src/index.ts +2 -0
  4. package/node_modules/@mrclrchtr/supi-core/src/path-utils.ts +40 -0
  5. package/node_modules/@mrclrchtr/supi-core/src/registry-utils.ts +42 -10
  6. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  7. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/api.ts +2 -0
  8. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/index.ts +2 -0
  9. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/path-utils.ts +40 -0
  10. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/registry-utils.ts +42 -10
  11. package/node_modules/@mrclrchtr/supi-lsp/package.json +3 -2
  12. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-project-info.ts +2 -16
  13. package/node_modules/@mrclrchtr/supi-lsp/src/pattern-matcher.ts +11 -184
  14. package/node_modules/@mrclrchtr/supi-lsp/src/session/service-registry.ts +5 -21
  15. package/node_modules/@mrclrchtr/supi-lsp/src/tool/guidance.ts +15 -75
  16. package/node_modules/@mrclrchtr/supi-lsp/src/tool/register-tools.ts +13 -166
  17. package/node_modules/@mrclrchtr/supi-lsp/src/tool/tool-specs.ts +248 -0
  18. package/node_modules/@mrclrchtr/supi-lsp/src/utils.ts +5 -34
  19. package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +18 -6
  20. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +107 -0
  21. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +44 -0
  22. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/api.ts +85 -0
  23. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +76 -0
  24. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config.ts +186 -0
  25. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/context/context-messages.ts +119 -0
  26. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/context/context-provider-registry.ts +36 -0
  27. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/context/context-tag.ts +31 -0
  28. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +255 -0
  29. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/extension.ts +1 -0
  30. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/index.ts +85 -0
  31. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/path-utils.ts +40 -0
  32. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/project-roots.ts +170 -0
  33. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/registry-utils.ts +86 -0
  34. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/session-utils.ts +29 -0
  35. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-command.ts +15 -0
  36. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +41 -0
  37. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +226 -0
  38. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/terminal.ts +60 -0
  39. package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +8 -3
  40. package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +5 -1
  41. package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +5 -1
  42. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime.ts +3 -2
  43. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/service-registry.ts +30 -0
  44. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +16 -8
  45. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/action-specs.ts +92 -0
  46. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/guidance.ts +12 -3
  47. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tree-sitter.ts +111 -61
  48. package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +13 -2
  49. package/package.json +4 -4
  50. package/src/actions/brief-action.ts +5 -5
  51. package/src/code-intelligence.ts +3 -10
  52. package/src/pattern-structured.ts +1 -1
  53. package/src/providers/structural-provider.ts +15 -3
  54. package/src/search-helpers.ts +4 -15
  55. package/src/tool/action-specs.ts +66 -0
  56. package/src/tool/guidance.ts +4 -7
  57. package/src/tool-actions.ts +23 -40
@@ -2,15 +2,8 @@
2
2
 
3
3
  import * as path from "node:path";
4
4
  import type { ProjectServerInfo } from "../config/types.ts";
5
- import {
6
- LSP_DIAGNOSTICS_TOOL,
7
- LSP_DOCUMENT_SYMBOLS_TOOL,
8
- LSP_LOOKUP_TOOL,
9
- LSP_RECOVER_TOOL,
10
- LSP_REFACTOR_TOOL,
11
- LSP_WORKSPACE_SYMBOLS_TOOL,
12
- type LspToolName,
13
- } from "./names.ts";
5
+ import { LSP_LOOKUP_TOOL, type LspToolName } from "./names.ts";
6
+ import { LSP_TOOL_DEFINITION_SPECS } from "./tool-specs.ts";
14
7
 
15
8
  export interface LspToolPromptSurface {
16
9
  description: string;
@@ -20,33 +13,6 @@ export interface LspToolPromptSurface {
20
13
 
21
14
  export type LspToolPromptSurfaceMap = Record<LspToolName, LspToolPromptSurface>;
22
15
 
23
- const LOOKUP_GUIDELINES = [
24
- 'Use lsp_lookup with `kind: "hover"` for semantic type or symbol information at a known `file`, `line`, and `character`.',
25
- 'Use lsp_lookup with `kind: "definition"`, `"references"`, or `"implementation"` for semantic navigation at a known position.',
26
- "Use lsp_lookup after code_intel or tree_sitter has already narrowed the target file and position.",
27
- ];
28
-
29
- const DOCUMENT_SYMBOL_GUIDELINES = [
30
- "Use lsp_document_symbols(file) for semantic declarations in one supported file.",
31
- ];
32
-
33
- const WORKSPACE_SYMBOL_GUIDELINES = [
34
- "Use lsp_workspace_symbols(query) for semantic symbol-name lookup across the current project.",
35
- ];
36
-
37
- const DIAGNOSTICS_GUIDELINES = [
38
- "Use lsp_diagnostics(file?) when you need current diagnostics for one file or a workspace-level summary.",
39
- ];
40
-
41
- const REFACTOR_GUIDELINES = [
42
- 'Use lsp_refactor with `kind: "rename"` for semantic rename planning at a known `file`, `line`, and `character`.',
43
- 'Use lsp_refactor with `kind: "code_actions"` for semantic fixes or refactors at a known position.',
44
- ];
45
-
46
- const RECOVER_GUIDELINES = [
47
- "Use lsp_recover() when diagnostics look stale after workspace-level changes or generated-file updates.",
48
- ];
49
-
50
16
  export const defaultLspToolPromptSurfaces = buildLspToolPromptSurfaces([], ".");
51
17
 
52
18
  export function buildLspToolPromptSurfaces(
@@ -55,45 +21,19 @@ export function buildLspToolPromptSurfaces(
55
21
  ): LspToolPromptSurfaceMap {
56
22
  const coverageGuidelines = buildCoverageGuidelines(servers, cwd);
57
23
 
58
- return {
59
- [LSP_LOOKUP_TOOL]: {
60
- description:
61
- "Language Server Protocol lookup tool — semantic hover, definition, references, and implementation for supported files. Use lsp_lookup when you know the file and 1-based line/character position and need semantic drill-down rather than text search.",
62
- promptSnippet:
63
- "lsp_lookup — semantic hover/definition/references/implementation at a known file position",
64
- promptGuidelines: [...LOOKUP_GUIDELINES, ...coverageGuidelines],
65
- },
66
- [LSP_DOCUMENT_SYMBOLS_TOOL]: {
67
- description:
68
- "Language Server Protocol document symbols tool — list semantic declarations in one supported file. Use lsp_document_symbols when you need a symbol-aware outline rather than raw text structure.",
69
- promptSnippet: "lsp_document_symbols — semantic declarations for one supported file",
70
- promptGuidelines: DOCUMENT_SYMBOL_GUIDELINES,
71
- },
72
- [LSP_WORKSPACE_SYMBOLS_TOOL]: {
73
- description:
74
- "Language Server Protocol workspace symbols tool — semantic symbol-name lookup across the current project. Use lsp_workspace_symbols to find declarations by name before opening a specific file.",
75
- promptSnippet: "lsp_workspace_symbols — semantic symbol-name lookup across the project",
76
- promptGuidelines: WORKSPACE_SYMBOL_GUIDELINES,
77
- },
78
- [LSP_DIAGNOSTICS_TOOL]: {
79
- description:
80
- "Language Server Protocol diagnostics tool — current diagnostics for one file or a workspace summary. Use lsp_diagnostics for semantic compiler or language-server issues instead of guessing from text alone.",
81
- promptSnippet: "lsp_diagnostics — current diagnostics for one file or the workspace",
82
- promptGuidelines: DIAGNOSTICS_GUIDELINES,
83
- },
84
- [LSP_REFACTOR_TOOL]: {
85
- description:
86
- "Language Server Protocol refactor tool — semantic rename planning and code actions at a known file position. Use lsp_refactor when you need language-server-backed edits or quick-fix suggestions.",
87
- promptSnippet: "lsp_refactor — semantic rename planning and code actions at a known position",
88
- promptGuidelines: REFACTOR_GUIDELINES,
89
- },
90
- [LSP_RECOVER_TOOL]: {
91
- description:
92
- "Language Server Protocol recover tool — refresh diagnostics after workspace changes and stale language-server state. Use lsp_recover when new files, generated types, or config updates leave diagnostics out of sync.",
93
- promptSnippet: "lsp_recover — refresh stale diagnostics after workspace changes",
94
- promptGuidelines: RECOVER_GUIDELINES,
95
- },
96
- };
24
+ return Object.fromEntries(
25
+ LSP_TOOL_DEFINITION_SPECS.map((spec) => [
26
+ spec.name,
27
+ {
28
+ description: spec.description,
29
+ promptSnippet: spec.promptSnippet,
30
+ promptGuidelines:
31
+ "includeCoverageGuidelines" in spec && spec.includeCoverageGuidelines
32
+ ? [...spec.basePromptGuidelines, ...coverageGuidelines]
33
+ : [...spec.basePromptGuidelines],
34
+ } satisfies LspToolPromptSurface,
35
+ ]),
36
+ ) as LspToolPromptSurfaceMap;
97
37
  }
98
38
 
99
39
  function buildCoverageGuidelines(servers: ProjectServerInfo[], cwd: string): string[] {
@@ -1,160 +1,22 @@
1
- import { StringEnum } from "@earendil-works/pi-ai";
2
1
  import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
3
- import { Type } from "typebox";
4
2
  import { getSessionLspService } from "../session/service-registry.ts";
5
3
  import type { LspToolPromptSurfaceMap } from "./guidance.ts";
6
- import {
7
- LSP_DIAGNOSTICS_TOOL,
8
- LSP_DOCUMENT_SYMBOLS_TOOL,
9
- LSP_LOOKUP_TOOL,
10
- LSP_RECOVER_TOOL,
11
- LSP_REFACTOR_TOOL,
12
- LSP_WORKSPACE_SYMBOLS_TOOL,
13
- } from "./names.ts";
14
- import {
15
- executeDiagnostics,
16
- executeDocumentSymbols,
17
- executeLookup,
18
- executeRecover,
19
- executeRefactor,
20
- executeWorkspaceSymbols,
21
- } from "./service-actions.ts";
22
-
23
- const FileParam = Type.String({ description: "File path (relative or absolute)" });
24
- const LineParam = Type.Number({ description: "1-based line number", minimum: 1 });
25
- const CharacterParam = Type.Number({ description: "1-based column number", minimum: 1 });
26
- const QueryParam = Type.String({ description: "Symbol query string" });
27
- const NewNameParam = Type.String({ description: "New name for rename" });
28
-
29
- const LookupKindEnum = StringEnum(["hover", "definition", "references", "implementation"] as const);
30
-
31
- const RefactorKindEnum = StringEnum(["rename", "code_actions"] as const);
32
-
33
- const LookupParameters = Type.Object(
34
- {
35
- kind: LookupKindEnum,
36
- file: FileParam,
37
- line: LineParam,
38
- character: CharacterParam,
39
- },
40
- { additionalProperties: false },
41
- );
42
-
43
- const DocumentSymbolsParameters = Type.Object(
44
- {
45
- file: FileParam,
46
- },
47
- { additionalProperties: false },
48
- );
49
-
50
- const WorkspaceSymbolsParameters = Type.Object(
51
- {
52
- query: QueryParam,
53
- },
54
- { additionalProperties: false },
55
- );
56
-
57
- const DiagnosticsParameters = Type.Object(
58
- {
59
- file: Type.Optional(FileParam),
60
- },
61
- { additionalProperties: false },
62
- );
63
-
64
- const RefactorParameters = Type.Object(
65
- {
66
- kind: RefactorKindEnum,
67
- file: FileParam,
68
- line: LineParam,
69
- character: CharacterParam,
70
- newName: Type.Optional(NewNameParam),
71
- },
72
- { additionalProperties: false },
73
- );
74
-
75
- const RecoverParameters = Type.Object({}, { additionalProperties: false });
4
+ import { LSP_TOOL_DEFINITION_SPECS } from "./tool-specs.ts";
76
5
 
77
6
  /** Register the expert LSP toolset. Tools are re-registered on session_start to refresh guidance. */
78
7
  export function registerLspTools(pi: ExtensionAPI, promptSurfaces: LspToolPromptSurfaceMap): void {
79
- const lookupSurface = promptSurfaces[LSP_LOOKUP_TOOL];
80
- pi.registerTool({
81
- name: LSP_LOOKUP_TOOL,
82
- label: "LSP Lookup",
83
- description: lookupSurface.description,
84
- promptSnippet: lookupSurface.promptSnippet,
85
- promptGuidelines: lookupSurface.promptGuidelines,
86
- parameters: LookupParameters,
87
- execute: createToolExecutor((service, cwd, params) =>
88
- executeLookup(service, cwd, params as Parameters<typeof executeLookup>[2]),
89
- ),
90
- });
91
-
92
- const documentSymbolsSurface = promptSurfaces[LSP_DOCUMENT_SYMBOLS_TOOL];
93
- pi.registerTool({
94
- name: LSP_DOCUMENT_SYMBOLS_TOOL,
95
- label: "LSP Document Symbols",
96
- description: documentSymbolsSurface.description,
97
- promptSnippet: documentSymbolsSurface.promptSnippet,
98
- promptGuidelines: documentSymbolsSurface.promptGuidelines,
99
- parameters: DocumentSymbolsParameters,
100
- execute: createToolExecutor((service, cwd, params) =>
101
- executeDocumentSymbols(service, cwd, params as Parameters<typeof executeDocumentSymbols>[2]),
102
- ),
103
- });
104
-
105
- const workspaceSymbolsSurface = promptSurfaces[LSP_WORKSPACE_SYMBOLS_TOOL];
106
- pi.registerTool({
107
- name: LSP_WORKSPACE_SYMBOLS_TOOL,
108
- label: "LSP Workspace Symbols",
109
- description: workspaceSymbolsSurface.description,
110
- promptSnippet: workspaceSymbolsSurface.promptSnippet,
111
- promptGuidelines: workspaceSymbolsSurface.promptGuidelines,
112
- parameters: WorkspaceSymbolsParameters,
113
- execute: createToolExecutor((service, cwd, params) =>
114
- executeWorkspaceSymbols(
115
- service,
116
- cwd,
117
- params as Parameters<typeof executeWorkspaceSymbols>[2],
118
- ),
119
- ),
120
- });
121
-
122
- const diagnosticsSurface = promptSurfaces[LSP_DIAGNOSTICS_TOOL];
123
- pi.registerTool({
124
- name: LSP_DIAGNOSTICS_TOOL,
125
- label: "LSP Diagnostics",
126
- description: diagnosticsSurface.description,
127
- promptSnippet: diagnosticsSurface.promptSnippet,
128
- promptGuidelines: diagnosticsSurface.promptGuidelines,
129
- parameters: DiagnosticsParameters,
130
- execute: createToolExecutor((service, cwd, params) =>
131
- executeDiagnostics(service, cwd, params as Parameters<typeof executeDiagnostics>[2]),
132
- ),
133
- });
134
-
135
- const refactorSurface = promptSurfaces[LSP_REFACTOR_TOOL];
136
- pi.registerTool({
137
- name: LSP_REFACTOR_TOOL,
138
- label: "LSP Refactor",
139
- description: refactorSurface.description,
140
- promptSnippet: refactorSurface.promptSnippet,
141
- promptGuidelines: refactorSurface.promptGuidelines,
142
- parameters: RefactorParameters,
143
- execute: createToolExecutor((service, cwd, params) =>
144
- executeRefactor(service, cwd, params as Parameters<typeof executeRefactor>[2]),
145
- ),
146
- });
147
-
148
- const recoverSurface = promptSurfaces[LSP_RECOVER_TOOL];
149
- pi.registerTool({
150
- name: LSP_RECOVER_TOOL,
151
- label: "LSP Recover",
152
- description: recoverSurface.description,
153
- promptSnippet: recoverSurface.promptSnippet,
154
- promptGuidelines: recoverSurface.promptGuidelines,
155
- parameters: RecoverParameters,
156
- execute: createRecoverToolExecutor(),
157
- });
8
+ for (const spec of LSP_TOOL_DEFINITION_SPECS) {
9
+ const surface = promptSurfaces[spec.name];
10
+ pi.registerTool({
11
+ name: spec.name,
12
+ label: spec.label,
13
+ description: surface.description,
14
+ promptSnippet: surface.promptSnippet,
15
+ promptGuidelines: surface.promptGuidelines,
16
+ parameters: spec.parameters,
17
+ execute: createToolExecutor(spec.run),
18
+ });
19
+ }
158
20
  }
159
21
 
160
22
  function getReadyService(cwd: string) {
@@ -201,21 +63,6 @@ function createToolExecutor(
201
63
  };
202
64
  }
203
65
 
204
- function createRecoverToolExecutor() {
205
- // biome-ignore lint/complexity/useMaxParams: pi ToolDefinition.execute signature
206
- return async (
207
- _toolCallId: string,
208
- _params: unknown,
209
- _signal: AbortSignal | undefined,
210
- _onUpdate: unknown,
211
- ctx: ExtensionContext,
212
- ) => {
213
- const service = getReadyService(ctx.cwd);
214
- const text = service ? await executeRecover(service) : describeUnavailableService(ctx.cwd);
215
- return makeTextResult(text);
216
- };
217
- }
218
-
219
66
  function makeTextResult(text: string) {
220
67
  return {
221
68
  content: [{ type: "text" as const, text }],
@@ -0,0 +1,248 @@
1
+ import { StringEnum } from "@earendil-works/pi-ai";
2
+ import { type TSchema, Type } from "typebox";
3
+ import type { ServerCapabilities } from "../config/types.ts";
4
+ import type { SessionLspService } from "../session/service-registry.ts";
5
+ import {
6
+ LSP_DIAGNOSTICS_TOOL,
7
+ LSP_DOCUMENT_SYMBOLS_TOOL,
8
+ LSP_LOOKUP_TOOL,
9
+ LSP_RECOVER_TOOL,
10
+ LSP_REFACTOR_TOOL,
11
+ LSP_WORKSPACE_SYMBOLS_TOOL,
12
+ type LspToolName,
13
+ } from "./names.ts";
14
+ import {
15
+ executeDiagnostics,
16
+ executeDocumentSymbols,
17
+ executeLookup,
18
+ executeRecover,
19
+ executeRefactor,
20
+ executeWorkspaceSymbols,
21
+ } from "./service-actions.ts";
22
+
23
+ const FileParam = Type.String({ description: "File path (relative or absolute)" });
24
+ const LineParam = Type.Number({ description: "1-based line number", minimum: 1 });
25
+ const CharacterParam = Type.Number({ description: "1-based column number", minimum: 1 });
26
+ const QueryParam = Type.String({ description: "Symbol query string" });
27
+ const NewNameParam = Type.String({ description: "New name for rename" });
28
+
29
+ export const LSP_LOOKUP_KIND_NAMES = [
30
+ "hover",
31
+ "definition",
32
+ "references",
33
+ "implementation",
34
+ ] as const;
35
+ export const LSP_REFACTOR_KIND_NAMES = ["rename", "code_actions"] as const;
36
+
37
+ const LookupKindEnum = StringEnum(LSP_LOOKUP_KIND_NAMES);
38
+ const RefactorKindEnum = StringEnum(LSP_REFACTOR_KIND_NAMES);
39
+
40
+ const LookupParameters = Type.Object(
41
+ {
42
+ kind: LookupKindEnum,
43
+ file: FileParam,
44
+ line: LineParam,
45
+ character: CharacterParam,
46
+ },
47
+ { additionalProperties: false },
48
+ );
49
+
50
+ const DocumentSymbolsParameters = Type.Object(
51
+ {
52
+ file: FileParam,
53
+ },
54
+ { additionalProperties: false },
55
+ );
56
+
57
+ const WorkspaceSymbolsParameters = Type.Object(
58
+ {
59
+ query: QueryParam,
60
+ },
61
+ { additionalProperties: false },
62
+ );
63
+
64
+ const DiagnosticsParameters = Type.Object(
65
+ {
66
+ file: Type.Optional(FileParam),
67
+ },
68
+ { additionalProperties: false },
69
+ );
70
+
71
+ const RefactorParameters = Type.Object(
72
+ {
73
+ kind: RefactorKindEnum,
74
+ file: FileParam,
75
+ line: LineParam,
76
+ character: CharacterParam,
77
+ newName: Type.Optional(NewNameParam),
78
+ },
79
+ { additionalProperties: false },
80
+ );
81
+
82
+ const RecoverParameters = Type.Object({}, { additionalProperties: false });
83
+
84
+ export interface LspToolDefinitionSpec {
85
+ name: LspToolName;
86
+ label: string;
87
+ description: string;
88
+ promptSnippet: string;
89
+ basePromptGuidelines: string[];
90
+ parameters: TSchema;
91
+ run: (service: SessionLspService, cwd: string, params: unknown) => Promise<string>;
92
+ includeCoverageGuidelines?: boolean;
93
+ }
94
+
95
+ export const LSP_TOOL_DEFINITION_SPECS = [
96
+ {
97
+ name: LSP_LOOKUP_TOOL,
98
+ label: "LSP Lookup",
99
+ description:
100
+ "Language Server Protocol lookup tool — semantic hover, definition, references, and implementation for supported files. Use lsp_lookup when you know the file and 1-based line/character position and need semantic drill-down rather than text search.",
101
+ promptSnippet:
102
+ "lsp_lookup — semantic hover/definition/references/implementation at a known file position",
103
+ basePromptGuidelines: [
104
+ 'Use lsp_lookup with `kind: "hover"` for semantic type or symbol information at a known `file`, `line`, and `character`.',
105
+ 'Use lsp_lookup with `kind: "definition"`, `"references"`, or `"implementation"` for semantic navigation at a known position.',
106
+ "Use lsp_lookup after code_intel or tree_sitter has already narrowed the target file and position.",
107
+ ],
108
+ parameters: LookupParameters,
109
+ run: (service, cwd, params) =>
110
+ executeLookup(service, cwd, params as Parameters<typeof executeLookup>[2]),
111
+ includeCoverageGuidelines: true,
112
+ },
113
+ {
114
+ name: LSP_DOCUMENT_SYMBOLS_TOOL,
115
+ label: "LSP Document Symbols",
116
+ description:
117
+ "Language Server Protocol document symbols tool — list semantic declarations in one supported file. Use lsp_document_symbols when you need a symbol-aware outline rather than raw text structure.",
118
+ promptSnippet: "lsp_document_symbols — semantic declarations for one supported file",
119
+ basePromptGuidelines: [
120
+ "Use lsp_document_symbols(file) for semantic declarations in one supported file.",
121
+ ],
122
+ parameters: DocumentSymbolsParameters,
123
+ run: (service, cwd, params) =>
124
+ executeDocumentSymbols(service, cwd, params as Parameters<typeof executeDocumentSymbols>[2]),
125
+ },
126
+ {
127
+ name: LSP_WORKSPACE_SYMBOLS_TOOL,
128
+ label: "LSP Workspace Symbols",
129
+ description:
130
+ "Language Server Protocol workspace symbols tool — semantic symbol-name lookup across the current project. Use lsp_workspace_symbols to find declarations by name before opening a specific file.",
131
+ promptSnippet: "lsp_workspace_symbols — semantic symbol-name lookup across the project",
132
+ basePromptGuidelines: [
133
+ "Use lsp_workspace_symbols(query) for semantic symbol-name lookup across the current project.",
134
+ ],
135
+ parameters: WorkspaceSymbolsParameters,
136
+ run: (service, cwd, params) =>
137
+ executeWorkspaceSymbols(
138
+ service,
139
+ cwd,
140
+ params as Parameters<typeof executeWorkspaceSymbols>[2],
141
+ ),
142
+ },
143
+ {
144
+ name: LSP_DIAGNOSTICS_TOOL,
145
+ label: "LSP Diagnostics",
146
+ description:
147
+ "Language Server Protocol diagnostics tool — current diagnostics for one file or a workspace summary. Use lsp_diagnostics for semantic compiler or language-server issues instead of guessing from text alone.",
148
+ promptSnippet: "lsp_diagnostics — current diagnostics for one file or the workspace",
149
+ basePromptGuidelines: [
150
+ "Use lsp_diagnostics(file?) when you need current diagnostics for one file or a workspace-level summary.",
151
+ ],
152
+ parameters: DiagnosticsParameters,
153
+ run: (service, cwd, params) =>
154
+ executeDiagnostics(service, cwd, params as Parameters<typeof executeDiagnostics>[2]),
155
+ },
156
+ {
157
+ name: LSP_REFACTOR_TOOL,
158
+ label: "LSP Refactor",
159
+ description:
160
+ "Language Server Protocol refactor tool — semantic rename planning and code actions at a known file position. Use lsp_refactor when you need language-server-backed edits or quick-fix suggestions.",
161
+ promptSnippet: "lsp_refactor — semantic rename planning and code actions at a known position",
162
+ basePromptGuidelines: [
163
+ 'Use lsp_refactor with `kind: "rename"` for semantic rename planning at a known `file`, `line`, and `character`.',
164
+ 'Use lsp_refactor with `kind: "code_actions"` for semantic fixes or refactors at a known position.',
165
+ ],
166
+ parameters: RefactorParameters,
167
+ run: (service, cwd, params) =>
168
+ executeRefactor(service, cwd, params as Parameters<typeof executeRefactor>[2]),
169
+ },
170
+ {
171
+ name: LSP_RECOVER_TOOL,
172
+ label: "LSP Recover",
173
+ description:
174
+ "Language Server Protocol recover tool — refresh diagnostics after workspace changes and stale language-server state. Use lsp_recover when new files, generated types, or config updates leave diagnostics out of sync.",
175
+ promptSnippet: "lsp_recover — refresh stale diagnostics after workspace changes",
176
+ basePromptGuidelines: [
177
+ "Use lsp_recover() when diagnostics look stale after workspace-level changes or generated-file updates.",
178
+ ],
179
+ parameters: RecoverParameters,
180
+ run: (service) => executeRecover(service),
181
+ },
182
+ ] as const satisfies readonly LspToolDefinitionSpec[];
183
+
184
+ const LSP_TOOL_SPEC_MAP = new Map<LspToolName, LspToolDefinitionSpec>(
185
+ LSP_TOOL_DEFINITION_SPECS.map((spec) => [spec.name, spec]),
186
+ );
187
+
188
+ export function getLspToolDefinitionSpec(toolName: LspToolName): LspToolDefinitionSpec {
189
+ const spec = LSP_TOOL_SPEC_MAP.get(toolName);
190
+ if (!spec) {
191
+ throw new Error(`Unknown LSP tool: ${toolName}`);
192
+ }
193
+ return spec;
194
+ }
195
+
196
+ interface LspServerSupportedActionSpec {
197
+ label: string;
198
+ isSupported: (capabilities: ServerCapabilities | null | undefined) => boolean;
199
+ }
200
+
201
+ const LSP_SERVER_SUPPORTED_ACTION_SPECS: readonly LspServerSupportedActionSpec[] = [
202
+ {
203
+ label: "diagnostics [optional file]",
204
+ isSupported: () => true,
205
+ },
206
+ {
207
+ label: "hover(file,line,char)",
208
+ isSupported: (capabilities) => Boolean(capabilities?.hoverProvider),
209
+ },
210
+ {
211
+ label: "definition(file,line,char)",
212
+ isSupported: (capabilities) => Boolean(capabilities?.definitionProvider),
213
+ },
214
+ {
215
+ label: "references(file,line,char)",
216
+ isSupported: (capabilities) => Boolean(capabilities?.referencesProvider),
217
+ },
218
+ {
219
+ label: "implementation(file,line,char)",
220
+ isSupported: (capabilities) => Boolean(capabilities?.implementationProvider),
221
+ },
222
+ {
223
+ label: "symbols(file)",
224
+ isSupported: (capabilities) => Boolean(capabilities?.documentSymbolProvider),
225
+ },
226
+ {
227
+ label: "workspace_symbols(query)",
228
+ isSupported: (capabilities) => Boolean(capabilities?.workspaceSymbolProvider),
229
+ },
230
+ {
231
+ label: "rename(file,line,char,newName)",
232
+ isSupported: (capabilities) => Boolean(capabilities?.renameProvider),
233
+ },
234
+ {
235
+ label: "code_actions(file,line,char)",
236
+ isSupported: (capabilities) => Boolean(capabilities?.codeActionProvider),
237
+ },
238
+ ] as const;
239
+
240
+ export function getSupportedLspServerActions(
241
+ capabilities: ServerCapabilities | null | undefined,
242
+ ): string[] {
243
+ if (!capabilities) return [];
244
+
245
+ return LSP_SERVER_SUPPORTED_ACTION_SPECS.filter((spec) => spec.isSupported(capabilities)).map(
246
+ (spec) => spec.label,
247
+ );
248
+ }
@@ -2,41 +2,12 @@
2
2
 
3
3
  import * as fs from "node:fs";
4
4
  import * as path from "node:path";
5
- // ── URI Handling ──────────────────────────────────────────────────────
6
5
 
7
- /** Convert a file path to a file:// URI. */
8
- export function fileToUri(filePath: string): string {
9
- const resolved = path.resolve(filePath);
10
- if (process.platform === "win32") {
11
- return `file:///${resolved.replace(/\\/g, "/")}`;
12
- }
13
- return `file://${resolved}`;
14
- }
15
-
16
- /** Convert a file:// URI to a file path. */
17
- export function uriToFile(uri: string): string {
18
- if (!uri.startsWith("file://")) return uri;
19
- let filePath = decodeURIComponent(uri.slice(7));
20
- if (
21
- process.platform === "win32" &&
22
- filePath.startsWith("/") &&
23
- /^[A-Za-z]:/.test(filePath.slice(1))
24
- ) {
25
- filePath = filePath.slice(1);
26
- }
27
- return filePath;
28
- }
29
-
30
- /**
31
- * Resolve a tool-style file path against the active session cwd.
32
- *
33
- * Built-in pi file tools accept a leading `@` prefix in path arguments, so LSP
34
- * helpers strip that prefix as well before resolving relative paths.
35
- */
36
- export function resolveSessionPath(cwd: string, filePath: string): string {
37
- const normalizedPath = filePath.startsWith("@") ? filePath.slice(1) : filePath;
38
- return path.resolve(cwd, normalizedPath);
39
- }
6
+ export {
7
+ fileToUri,
8
+ resolveToolPath as resolveSessionPath,
9
+ uriToFile,
10
+ } from "@mrclrchtr/supi-core/api";
40
11
 
41
12
  // ── Language ID Detection ─────────────────────────────────────────────
42
13
 
@@ -33,7 +33,7 @@ After install, pi gets one tool:
33
33
  | `query` | Run a custom Tree-sitter query against a file | Any supported grammar |
34
34
  | `callees` | Find outgoing calls from the enclosing function or method at a position | Supported for most grammars, but not all |
35
35
 
36
- Coordinates use **1-based** line and character columns. Character positions use UTF-16 code units.
36
+ Coordinates use **1-based** line and character columns. Character positions use UTF-16 code units. Relative paths resolve from the session cwd, and a leading `@` on file paths is stripped.
37
37
 
38
38
  ## Supported file families
39
39
 
@@ -54,10 +54,10 @@ The current tool description covers:
54
54
 
55
55
  ## Package surfaces
56
56
 
57
- - `@mrclrchtr/supi-tree-sitter/api` — reusable parsing session factory and shared result types
57
+ - `@mrclrchtr/supi-tree-sitter/api` — reusable parsing session factory, shared session-scoped structural service access, and shared result types
58
58
  - `@mrclrchtr/supi-tree-sitter/extension` — pi extension entrypoint
59
59
 
60
- Example:
60
+ Owned session example:
61
61
 
62
62
  ```ts
63
63
  import { createTreeSitterSession } from "@mrclrchtr/supi-tree-sitter/api";
@@ -71,9 +71,21 @@ const callees = await session.calleesAt("src/index.ts", 42, 10);
71
71
  session.dispose();
72
72
  ```
73
73
 
74
+ Shared session-scoped service example:
75
+
76
+ ```ts
77
+ import { getSessionTreeSitterService } from "@mrclrchtr/supi-tree-sitter/api";
78
+
79
+ const state = getSessionTreeSitterService("/project");
80
+ if (state.kind === "ready") {
81
+ const outline = await state.service.outline("src/index.ts");
82
+ }
83
+ ```
84
+
74
85
  ## Source
75
86
 
76
87
  - `src/tree-sitter.ts` — tool registration and action handling
77
- - `src/runtime.ts` — parser and query runtime
78
- - `src/session.ts` — reusable session API
79
- - `src/outline.ts`, `src/imports.ts`, `src/exports.ts`, `src/node-at.ts`, `src/callees.ts` — structural analyses
88
+ - `src/session/runtime.ts` — parser and query runtime
89
+ - `src/session/session.ts` — runtime-backed service helpers and owned session API
90
+ - `src/session/service-registry.ts` — shared session-scoped structural service registry
91
+ - `src/tool/outline.ts`, `src/tool/imports.ts`, `src/tool/exports.ts`, `src/tool/node-at.ts`, `src/tool/callees.ts` — structural analyses