@mrclrchtr/supi-code-intelligence 1.4.0 → 1.5.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/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/api.ts +2 -0
- package/node_modules/@mrclrchtr/supi-core/src/index.ts +2 -0
- package/node_modules/@mrclrchtr/supi-core/src/path-utils.ts +40 -0
- package/node_modules/@mrclrchtr/supi-core/src/registry-utils.ts +42 -10
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/api.ts +2 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/index.ts +2 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/path-utils.ts +40 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/registry-utils.ts +42 -10
- package/node_modules/@mrclrchtr/supi-lsp/package.json +2 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-project-info.ts +2 -16
- package/node_modules/@mrclrchtr/supi-lsp/src/session/service-registry.ts +5 -21
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/guidance.ts +15 -75
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/register-tools.ts +13 -166
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/tool-specs.ts +248 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/utils.ts +5 -34
- package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +18 -6
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +107 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +44 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/api.ts +85 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +76 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config.ts +186 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/context/context-messages.ts +119 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/context/context-provider-registry.ts +36 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/context/context-tag.ts +31 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +255 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/extension.ts +1 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/index.ts +85 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/path-utils.ts +40 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/project-roots.ts +170 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/registry-utils.ts +86 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/session-utils.ts +29 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-command.ts +15 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +41 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +226 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/terminal.ts +60 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +8 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +5 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +5 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime.ts +3 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/service-registry.ts +30 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +16 -8
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/action-specs.ts +92 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/guidance.ts +12 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tree-sitter.ts +111 -61
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +13 -2
- package/package.json +4 -4
- package/src/actions/brief-action.ts +5 -5
- package/src/code-intelligence.ts +3 -10
- package/src/pattern-structured.ts +1 -1
- package/src/providers/structural-provider.ts +15 -3
- package/src/search-helpers.ts +4 -15
- package/src/tool/action-specs.ts +66 -0
- package/src/tool/guidance.ts +4 -7
- package/src/tool-actions.ts +23 -40
|
@@ -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
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
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` —
|
|
79
|
-
- `src/
|
|
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
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# @mrclrchtr/supi-core
|
|
2
|
+
|
|
3
|
+
Shared infrastructure for SuPi extensions.
|
|
4
|
+
|
|
5
|
+
This package is mainly for extension authors. It gives you a common config system, settings plumbing, context helpers, registries, and a small extension surface that registers `/supi-settings`.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
### As a dependency for another extension
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add @mrclrchtr/supi-core
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### As a pi package
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pi install npm:@mrclrchtr/supi-core
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Installing it as a pi package adds the minimal `/supi-settings` extension surface.
|
|
22
|
+
|
|
23
|
+
## Package surfaces
|
|
24
|
+
|
|
25
|
+
- `@mrclrchtr/supi-core/api` — reusable helpers for other packages and extensions
|
|
26
|
+
- `@mrclrchtr/supi-core/extension` — minimal pi extension that registers `/supi-settings`
|
|
27
|
+
|
|
28
|
+
## What you get from the API
|
|
29
|
+
|
|
30
|
+
### Config helpers
|
|
31
|
+
|
|
32
|
+
- `loadSupiConfig()` — merged config with resolution order `defaults <- global <- project`
|
|
33
|
+
- `loadSupiConfigForScope()` — load one scope at a time for settings UIs
|
|
34
|
+
- `writeSupiConfig()` — persist values
|
|
35
|
+
- `removeSupiConfigKey()` — remove a key or override
|
|
36
|
+
|
|
37
|
+
Config file locations:
|
|
38
|
+
|
|
39
|
+
- global: `~/.pi/agent/supi/config.json`
|
|
40
|
+
- project: `.pi/supi/config.json`
|
|
41
|
+
|
|
42
|
+
### Settings helpers
|
|
43
|
+
|
|
44
|
+
- `registerSettings()` — register an arbitrary settings section
|
|
45
|
+
- `registerConfigSettings()` — register a config-backed settings section with scoped persistence helpers
|
|
46
|
+
- `registerSettingsCommand()` — register `/supi-settings`
|
|
47
|
+
- `openSettingsOverlay()` — open the shared settings UI directly
|
|
48
|
+
- `createInputSubmenu()` — helper for simple text-entry submenus
|
|
49
|
+
|
|
50
|
+
The built-in settings UI supports:
|
|
51
|
+
|
|
52
|
+
- project/global scope toggle
|
|
53
|
+
- grouped extension sections
|
|
54
|
+
- searchable setting lists
|
|
55
|
+
|
|
56
|
+
### Context helpers
|
|
57
|
+
|
|
58
|
+
- `wrapExtensionContext()` — wrap injected text in SuPi's `<extension-context>` tag
|
|
59
|
+
- `findLastUserMessageIndex()`
|
|
60
|
+
- `getContextToken()`
|
|
61
|
+
- `getPromptContent()`
|
|
62
|
+
- `pruneAndReorderContextMessages()`
|
|
63
|
+
- `restorePromptContent()`
|
|
64
|
+
|
|
65
|
+
### Shared registries
|
|
66
|
+
|
|
67
|
+
- context-provider registry for `/supi-context`
|
|
68
|
+
- debug-event registry for producers that want shared debug capture
|
|
69
|
+
- settings registry used by `/supi-settings`
|
|
70
|
+
|
|
71
|
+
### Project and session helpers
|
|
72
|
+
|
|
73
|
+
- project-root detection and directory walking helpers such as `findProjectRoot()` and `walkProject()`
|
|
74
|
+
- active-branch session helper: `getActiveBranchEntries()`
|
|
75
|
+
- terminal helpers such as `formatTitle()`, `signalWaiting()`, and `signalDone()`
|
|
76
|
+
|
|
77
|
+
## Example
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { loadSupiConfig, registerConfigSettings, wrapExtensionContext } from "@mrclrchtr/supi-core/api";
|
|
81
|
+
|
|
82
|
+
const config = loadSupiConfig("my-extension", process.cwd(), {
|
|
83
|
+
enabled: true,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
registerConfigSettings({
|
|
87
|
+
id: "my-extension",
|
|
88
|
+
label: "My Extension",
|
|
89
|
+
section: "my-extension",
|
|
90
|
+
defaults: { enabled: true },
|
|
91
|
+
buildItems: () => [],
|
|
92
|
+
persistChange: () => {},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const message = wrapExtensionContext("my-extension", "hello", {
|
|
96
|
+
file: "CLAUDE.md",
|
|
97
|
+
turn: 1,
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Source
|
|
102
|
+
|
|
103
|
+
- `src/api.ts` — exported library surface
|
|
104
|
+
- `src/extension.ts` — minimal `/supi-settings` entrypoint
|
|
105
|
+
- `src/config.ts` — shared config loading and writing
|
|
106
|
+
- `src/config-settings.ts` — config-backed settings registration helper
|
|
107
|
+
- `src/settings-ui.ts` — shared settings overlay
|
package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mrclrchtr/supi-core",
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "SuPi core — shared infrastructure for SuPi extensions (XML context tags, config system)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/mrclrchtr/supi.git"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"pi",
|
|
15
|
+
"pi-coding-agent"
|
|
16
|
+
],
|
|
17
|
+
"files": [
|
|
18
|
+
"src/**/*.ts",
|
|
19
|
+
"!__tests__"
|
|
20
|
+
],
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
23
|
+
"@earendil-works/pi-tui": "*"
|
|
24
|
+
},
|
|
25
|
+
"peerDependenciesMeta": {
|
|
26
|
+
"@earendil-works/pi-coding-agent": {
|
|
27
|
+
"optional": true
|
|
28
|
+
},
|
|
29
|
+
"@earendil-works/pi-tui": {
|
|
30
|
+
"optional": true
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"main": "src/api.ts",
|
|
34
|
+
"exports": {
|
|
35
|
+
"./api": "./src/api.ts",
|
|
36
|
+
"./extension": "./src/extension.ts",
|
|
37
|
+
"./package.json": "./package.json"
|
|
38
|
+
},
|
|
39
|
+
"pi": {
|
|
40
|
+
"extensions": [
|
|
41
|
+
"./src/extension.ts"
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
}
|