@mrclrchtr/supi-lsp 1.16.0 → 2.0.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/README.md +44 -56
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +6 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +3 -2
- package/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +7 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +56 -2
- package/node_modules/@mrclrchtr/supi-code-runtime/src/evidence-badge.ts +40 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/index.ts +5 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +76 -3
- package/node_modules/@mrclrchtr/supi-code-runtime/src/workspace/runtime.ts +37 -2
- package/node_modules/@mrclrchtr/supi-core/package.json +6 -1
- package/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
- package/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
- package/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
- package/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
- package/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
- package/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
- package/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
- package/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
- package/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
- package/node_modules/vscode-languageserver-protocol/lib/common/protocol.diagnostic.d.ts +21 -2
- package/node_modules/vscode-languageserver-protocol/lib/common/protocol.diagnostic.js +1 -0
- package/node_modules/vscode-languageserver-protocol/lib/common/protocol.inlineValue.d.ts +2 -1
- package/node_modules/vscode-languageserver-protocol/package.json +1 -1
- package/package.json +4 -31
- package/src/api.ts +27 -0
- package/src/client/client-refresh.ts +5 -0
- package/src/client/client.ts +246 -1
- package/src/client/transport.ts +4 -0
- package/src/config/capabilities.ts +3 -0
- package/src/config/config.ts +4 -2
- package/src/config/lsp-settings.ts +102 -0
- package/src/config/server-actions.ts +59 -0
- package/src/config/server-config.ts +4 -0
- package/src/index.ts +11 -0
- package/src/manager/capability-index.ts +1 -1
- package/src/manager/manager-project-info.ts +2 -1
- package/src/manager/manager.ts +115 -26
- package/src/provider/lsp-semantic-provider.ts +177 -134
- package/src/provider/refactor-planning.ts +214 -0
- package/src/session/runtime-controller.ts +320 -0
- package/src/session/runtime-registration.ts +26 -5
- package/src/session/service-registry.ts +81 -4
- package/src/summary.ts +2 -0
- package/src/extension.ts +0 -1
- package/src/format.ts +0 -373
- package/src/handlers/diagnostic-injection.ts +0 -182
- package/src/handlers/session-lifecycle.ts +0 -149
- package/src/handlers/status-command.ts +0 -38
- package/src/handlers/workspace-recovery.ts +0 -92
- package/src/lsp.ts +0 -37
- package/src/session/lsp-state.ts +0 -93
- package/src/session/settings-registration.ts +0 -296
- package/src/session/tree-persist.ts +0 -75
- package/src/tool/guidance.ts +0 -69
- package/src/tool/names.ts +0 -27
- package/src/tool/overrides.ts +0 -204
- package/src/tool/register-tools.ts +0 -69
- package/src/tool/service-actions.ts +0 -399
- package/src/tool/tool-specs.ts +0 -248
- package/src/ui/renderer.ts +0 -120
- package/src/ui/ui.ts +0 -360
- package/src/workspace-change.ts +0 -40
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
// supi-core settings-ui domain — settings TUI components (imports pi-tui at runtime, heavy).
|
|
2
|
-
export {
|
|
2
|
+
export {
|
|
3
|
+
createInputSubmenu,
|
|
4
|
+
createModelPickerSubmenu,
|
|
5
|
+
openSettingsOverlay,
|
|
6
|
+
} from "./settings/settings-ui.ts";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared UI constants for SuPi extensions.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** Braille spinner frames used across SuPi extensions for animated loaders. */
|
|
8
|
+
export const BRAILLE_SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
9
|
+
|
|
10
|
+
/** Tick interval (ms) shared by all braille-spinner consumers. */
|
|
11
|
+
export const SPINNER_INTERVAL_MS = 80;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight status-bar spinner for SuPi extensions.
|
|
3
|
+
*
|
|
4
|
+
* Manages a setInterval-based animated spinner that writes to
|
|
5
|
+
* `ctx.ui.setStatus`. Each tick advances the frame and re-renders
|
|
6
|
+
* with the current message.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
12
|
+
import { BRAILLE_SPINNER_FRAMES, SPINNER_INTERVAL_MS } from "./spinner-frames.ts";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Manages an animated braille spinner on the status bar.
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* ```ts
|
|
19
|
+
* const spinner = new StatusSpinner(ctx, "my-package");
|
|
20
|
+
* spinner.start("generating…");
|
|
21
|
+
* // later
|
|
22
|
+
* spinner.stop();
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export class StatusSpinner {
|
|
26
|
+
private interval: ReturnType<typeof setInterval> | null = null;
|
|
27
|
+
private frame = 0;
|
|
28
|
+
private currentMessage = "";
|
|
29
|
+
|
|
30
|
+
constructor(
|
|
31
|
+
private ctx: ExtensionContext,
|
|
32
|
+
private source: string,
|
|
33
|
+
private frames: readonly string[] = BRAILLE_SPINNER_FRAMES,
|
|
34
|
+
) {}
|
|
35
|
+
|
|
36
|
+
/** Start the spinner with the given message. Overwrites any active spinner. */
|
|
37
|
+
start(message: string): void {
|
|
38
|
+
this.stop();
|
|
39
|
+
this.currentMessage = message;
|
|
40
|
+
this.render();
|
|
41
|
+
|
|
42
|
+
this.interval = setInterval(() => {
|
|
43
|
+
this.frame++;
|
|
44
|
+
this.render();
|
|
45
|
+
}, SPINNER_INTERVAL_MS);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Update the display message without resetting the spinner. */
|
|
49
|
+
update(message: string): void {
|
|
50
|
+
this.currentMessage = message;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Stop the spinner and clear the status. */
|
|
54
|
+
stop(): void {
|
|
55
|
+
if (this.interval !== null) {
|
|
56
|
+
clearInterval(this.interval);
|
|
57
|
+
this.interval = null;
|
|
58
|
+
}
|
|
59
|
+
this.ctx.ui.setStatus(this.source, "");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ── Private ──────────────────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
private render(): void {
|
|
65
|
+
const icon = this.frames[this.frame % this.frames.length];
|
|
66
|
+
this.ctx.ui.setStatus(this.source, `${icon} ${this.currentMessage}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-code-runtime",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "SuPi code-runtime — shared workspace context, capability contracts, and canonical types for the code-understanding stack",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -23,12 +23,13 @@
|
|
|
23
23
|
"workspace-context",
|
|
24
24
|
"provider-api"
|
|
25
25
|
],
|
|
26
|
+
"type": "module",
|
|
26
27
|
"files": [
|
|
27
28
|
"src/**/*.ts",
|
|
28
29
|
"!__tests__"
|
|
29
30
|
],
|
|
30
31
|
"dependencies": {
|
|
31
|
-
"@mrclrchtr/supi-core": "
|
|
32
|
+
"@mrclrchtr/supi-core": "2.0.0"
|
|
32
33
|
},
|
|
33
34
|
"bundledDependencies": [
|
|
34
35
|
"@mrclrchtr/supi-core"
|
|
@@ -13,9 +13,13 @@ export type {
|
|
|
13
13
|
StructuralProvider,
|
|
14
14
|
StructuralResult,
|
|
15
15
|
} from "./capability/types.ts";
|
|
16
|
+
// Evidence display
|
|
17
|
+
export { type EvidenceBadgeInput, formatEvidenceBadge } from "./evidence-badge.ts";
|
|
16
18
|
// Shared canonical types
|
|
17
19
|
export type {
|
|
20
|
+
CalleeDepth,
|
|
18
21
|
CalleesData,
|
|
22
|
+
CallSite,
|
|
19
23
|
CodeLocation,
|
|
20
24
|
CodePosition,
|
|
21
25
|
CodeResult,
|
|
@@ -27,10 +31,13 @@ export type {
|
|
|
27
31
|
ImportData,
|
|
28
32
|
NodeAtData,
|
|
29
33
|
OutlineData,
|
|
34
|
+
RefactorOperation,
|
|
35
|
+
RefactorRequest,
|
|
30
36
|
RefactorResult,
|
|
31
37
|
SourceRange,
|
|
32
38
|
WorkspaceEdit,
|
|
33
39
|
} from "./types.ts";
|
|
40
|
+
export { normalizeRefactorOperation } from "./types.ts";
|
|
34
41
|
export type { WorkspaceContext } from "./workspace/context.ts";
|
|
35
42
|
// Workspace context
|
|
36
43
|
export { createWorkspaceContext } from "./workspace/context.ts";
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type {
|
|
8
|
+
CalleeDepth,
|
|
8
9
|
CalleesData,
|
|
10
|
+
CallSite,
|
|
9
11
|
CodeLocation,
|
|
10
12
|
CodePosition,
|
|
11
13
|
CodeResult,
|
|
@@ -14,7 +16,9 @@ import type {
|
|
|
14
16
|
ImportData,
|
|
15
17
|
NodeAtData,
|
|
16
18
|
OutlineData,
|
|
19
|
+
RefactorRequest,
|
|
17
20
|
RefactorResult,
|
|
21
|
+
SourceRange,
|
|
18
22
|
} from "../types.ts";
|
|
19
23
|
|
|
20
24
|
// ── Availability state ─────────────────────────────────────────────────
|
|
@@ -49,17 +53,60 @@ export interface SemanticProvider {
|
|
|
49
53
|
documentSymbols(filePath: string): Promise<CodeSymbol[] | null>;
|
|
50
54
|
workspaceSymbols(query: string): Promise<CodeSymbol[] | null>;
|
|
51
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Optional definition capability. Returns the definition location(s) for
|
|
58
|
+
* the symbol at the given position. When the provider cannot produce
|
|
59
|
+
* definition info, returns `null`.
|
|
60
|
+
*/
|
|
61
|
+
definition?(filePath: string, position: CodePosition): Promise<CodeLocation[] | null>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Optional hover capability. Returns a simplified type/signature info
|
|
65
|
+
* shape that does not depend on vscode-languageserver-types. When the
|
|
66
|
+
* provider cannot produce hover info (unavailable, unsupported file,
|
|
67
|
+
* no result at the given position), returns `null`.
|
|
68
|
+
*/
|
|
69
|
+
hover?(
|
|
70
|
+
filePath: string,
|
|
71
|
+
position: CodePosition,
|
|
72
|
+
): Promise<{ contents: string; range?: SourceRange } | null>;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Optional operation-aware refactor capability.
|
|
76
|
+
*
|
|
77
|
+
* This is the preferred planning entrypoint for higher-level tools because it
|
|
78
|
+
* lets the provider choose the honest substrate path per operation (rename,
|
|
79
|
+
* organize imports, dead-code cleanup, etc.) without exposing that branching
|
|
80
|
+
* to callers.
|
|
81
|
+
*/
|
|
82
|
+
refactor?(request: RefactorRequest): Promise<RefactorResult>;
|
|
83
|
+
|
|
52
84
|
/**
|
|
53
85
|
* Optional rename capability. When present, the provider supports
|
|
54
|
-
* precise semantic rename operations.
|
|
86
|
+
* precise semantic symbol-rename operations.
|
|
87
|
+
*
|
|
88
|
+
* Kept as a low-level substrate helper for compatibility while the public
|
|
89
|
+
* tool surface still exposes a legacy `rename` alias.
|
|
55
90
|
*/
|
|
56
91
|
rename?(file: string, position: CodePosition, newName: string): Promise<RefactorResult>;
|
|
57
92
|
|
|
58
93
|
/**
|
|
59
94
|
* Optional code actions capability. When present, the provider
|
|
60
95
|
* supports code-action-based refactors.
|
|
96
|
+
*
|
|
97
|
+
* Kept as a low-level substrate helper and for lightweight introspection.
|
|
61
98
|
*/
|
|
62
99
|
codeActions?(file: string, position: CodePosition): Promise<RefactorResult[]>;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Optional lightweight code action titles for display purposes.
|
|
103
|
+
* Returns simplified title/kind pairs at the given position.
|
|
104
|
+
* When the provider cannot produce code actions, returns `null`.
|
|
105
|
+
*/
|
|
106
|
+
codeActionTitles?(
|
|
107
|
+
file: string,
|
|
108
|
+
position: CodePosition,
|
|
109
|
+
): Promise<Array<{ title: string; kind?: string }> | null>;
|
|
63
110
|
}
|
|
64
111
|
|
|
65
112
|
/**
|
|
@@ -70,11 +117,18 @@ export interface SemanticProvider {
|
|
|
70
117
|
* and runtime error states.
|
|
71
118
|
*/
|
|
72
119
|
export interface StructuralProvider {
|
|
73
|
-
calleesAt(
|
|
120
|
+
calleesAt(
|
|
121
|
+
file: string,
|
|
122
|
+
line: number,
|
|
123
|
+
character: number,
|
|
124
|
+
depth?: CalleeDepth,
|
|
125
|
+
): Promise<CodeResult<CalleesData>>;
|
|
74
126
|
exports(file: string): Promise<CodeResult<ExportData[]>>;
|
|
75
127
|
outline(file: string): Promise<CodeResult<OutlineData[]>>;
|
|
76
128
|
imports(file: string): Promise<CodeResult<ImportData[]>>;
|
|
77
129
|
nodeAt(file: string, line: number, character: number): Promise<CodeResult<NodeAtData>>;
|
|
130
|
+
/** Find all call-site identifiers in a file. Returns name + start line for each match. */
|
|
131
|
+
callSites(file: string): Promise<CodeResult<CallSite[]>>;
|
|
78
132
|
}
|
|
79
133
|
|
|
80
134
|
/** Convenience alias for `CodeResult` used in structural contexts. */
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TUI-facing evidence badge string formatter.
|
|
3
|
+
*
|
|
4
|
+
* Pure string formatting — no pi-tui dependency. Consumes evidence
|
|
5
|
+
* completeness metadata and produces compact human-readable badges.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** Metadata describing how many evidence atoms were shown vs exist. */
|
|
9
|
+
export interface EvidenceBadgeInput {
|
|
10
|
+
shownCount: number;
|
|
11
|
+
totalCount: number | null;
|
|
12
|
+
omittedCount: number | null;
|
|
13
|
+
partialReason: string | null;
|
|
14
|
+
/** Human-readable label for the badge, e.g. "references", "symbols". */
|
|
15
|
+
label: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Format a compact evidence completeness badge.
|
|
20
|
+
*
|
|
21
|
+
* | Input | Output |
|
|
22
|
+
* |------------------------------------------------------|---------------------------------------|
|
|
23
|
+
* | shown=12, total=12, omitted=0, label="references" | `12 references` |
|
|
24
|
+
* | shown=8, total=20, omitted=12, label="symbols" | `8 of 20 symbols (12 omitted)` |
|
|
25
|
+
* | shown=5, total=null, reason="timeout", label="matches" | `5 matches — timeout` |
|
|
26
|
+
*/
|
|
27
|
+
export function formatEvidenceBadge(input: EvidenceBadgeInput): string {
|
|
28
|
+
const { shownCount, totalCount, omittedCount, partialReason, label } = input;
|
|
29
|
+
|
|
30
|
+
if (totalCount === null) {
|
|
31
|
+
const reasonSuffix = partialReason ? ` — ${partialReason}` : "";
|
|
32
|
+
return `${shownCount} ${label}${reasonSuffix}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (omittedCount !== null && omittedCount > 0) {
|
|
36
|
+
return `${shownCount} of ${totalCount} ${label} (${omittedCount} omitted)`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return `${shownCount} ${label}`;
|
|
40
|
+
}
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
export type {
|
|
9
|
+
CalleeDepth,
|
|
9
10
|
CalleesData,
|
|
11
|
+
CallSite,
|
|
10
12
|
CapabilityState,
|
|
11
13
|
CodeLocation,
|
|
12
14
|
CodePosition,
|
|
@@ -17,6 +19,8 @@ export type {
|
|
|
17
19
|
ImportData,
|
|
18
20
|
NodeAtData,
|
|
19
21
|
OutlineData,
|
|
22
|
+
RefactorOperation,
|
|
23
|
+
RefactorRequest,
|
|
20
24
|
SemanticProvider,
|
|
21
25
|
SourceRange,
|
|
22
26
|
StructuralProvider,
|
|
@@ -27,5 +31,6 @@ export type {
|
|
|
27
31
|
export {
|
|
28
32
|
createWorkspaceContext,
|
|
29
33
|
getDefaultWorkspaceRuntime,
|
|
34
|
+
normalizeRefactorOperation,
|
|
30
35
|
WorkspaceRuntime,
|
|
31
36
|
} from "./api.ts";
|
|
@@ -28,13 +28,29 @@ export interface CodeLocation {
|
|
|
28
28
|
|
|
29
29
|
// ── Symbol types ───────────────────────────────────────────────────────
|
|
30
30
|
|
|
31
|
-
/** A
|
|
31
|
+
/** A 1-based source position used as a symbol anchor. */
|
|
32
|
+
export interface SymbolAnchor {
|
|
33
|
+
line: number;
|
|
34
|
+
character: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A discovered symbol / declaration.
|
|
39
|
+
*
|
|
40
|
+
* Per ADR 0003, anchors are split so position-strict substrates
|
|
41
|
+
* (structural callee lookup, LSP `rename`) cannot silently consume a
|
|
42
|
+
* declaration anchor (the `export` keyword) as if it were the identifier.
|
|
43
|
+
* - `declarationAnchor` is always present (the defining node start).
|
|
44
|
+
* - `nameAnchor` is best-effort (the identifier token), present when the
|
|
45
|
+
* provider can derive it (LSP `selectionRange`, or a tree-sitter snap).
|
|
46
|
+
* Strict consumers must prefer it and hard-fail when it is absent.
|
|
47
|
+
*/
|
|
32
48
|
export interface CodeSymbol {
|
|
33
49
|
name: string;
|
|
34
50
|
kind: string;
|
|
35
51
|
file: string;
|
|
36
|
-
|
|
37
|
-
|
|
52
|
+
declarationAnchor: SymbolAnchor;
|
|
53
|
+
nameAnchor?: SymbolAnchor;
|
|
38
54
|
container?: string | null;
|
|
39
55
|
}
|
|
40
56
|
|
|
@@ -125,6 +141,44 @@ export interface WorkspaceEdit {
|
|
|
125
141
|
edits: FileEdit[];
|
|
126
142
|
}
|
|
127
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Supported refactor operation names for the current semantic planning path.
|
|
146
|
+
*
|
|
147
|
+
* `rename` is kept as a legacy alias for the public rename-only surface.
|
|
148
|
+
*/
|
|
149
|
+
export type RefactorOperation =
|
|
150
|
+
| "rename"
|
|
151
|
+
| "rename_symbol"
|
|
152
|
+
| "extract_function"
|
|
153
|
+
| "extract_variable"
|
|
154
|
+
| "rename_file"
|
|
155
|
+
| "move_file"
|
|
156
|
+
| "update_imports"
|
|
157
|
+
| "delete_dead_code";
|
|
158
|
+
|
|
159
|
+
/** Normalize legacy refactor aliases to their canonical operation names. */
|
|
160
|
+
export function normalizeRefactorOperation(
|
|
161
|
+
operation: RefactorOperation,
|
|
162
|
+
): Exclude<RefactorOperation, "rename"> {
|
|
163
|
+
return operation === "rename" ? "rename_symbol" : operation;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Operation-aware refactor planning request.
|
|
168
|
+
*
|
|
169
|
+
* Consumers provide a target file/position plus operation-specific options.
|
|
170
|
+
* File/resource operations remain requestable so providers can reject them
|
|
171
|
+
* explicitly and honestly until shared workspace-edit resource ops exist.
|
|
172
|
+
*/
|
|
173
|
+
export interface RefactorRequest {
|
|
174
|
+
operation: RefactorOperation;
|
|
175
|
+
file: string;
|
|
176
|
+
position: CodePosition;
|
|
177
|
+
range?: SourceRange;
|
|
178
|
+
newName?: string;
|
|
179
|
+
destination?: string;
|
|
180
|
+
}
|
|
181
|
+
|
|
128
182
|
/**
|
|
129
183
|
* A disambiguation candidate when a refactor target is ambiguous.
|
|
130
184
|
*/
|
|
@@ -149,7 +203,26 @@ export type RefactorResult =
|
|
|
149
203
|
|
|
150
204
|
// ── Structural data shapes (value types, range-flattened) ──────────────
|
|
151
205
|
|
|
206
|
+
/** Callee collection depth. */
|
|
207
|
+
export type CalleeDepth = "direct" | "deep";
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Structural outgoing calls from the enclosing executable scope at a
|
|
211
|
+
* position. Callee names are source-shape facts, not resolved symbol
|
|
212
|
+
* identities.
|
|
213
|
+
*
|
|
214
|
+
* In `direct` depth, nested function/callback scopes are excluded from the
|
|
215
|
+
* outer scope. In `deep` depth, all callees within the enclosing scope are
|
|
216
|
+
* included, including those inside nested scopes.
|
|
217
|
+
*/
|
|
152
218
|
export interface CalleesData {
|
|
153
219
|
enclosingScope: { name: string; startLine: number; endLine: number };
|
|
154
220
|
callees: Array<{ name: string; startLine: number }>;
|
|
221
|
+
depth: CalleeDepth;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** A single call-site match with name and start line. */
|
|
225
|
+
export interface CallSite {
|
|
226
|
+
name: string;
|
|
227
|
+
startLine: number;
|
|
155
228
|
}
|
|
@@ -48,7 +48,12 @@ function createDefaultCapabilities(): WorkspaceCapabilities {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
function hasRefactorCapability(provider: SemanticProvider | null): boolean {
|
|
51
|
-
return !!(
|
|
51
|
+
return !!(
|
|
52
|
+
provider &&
|
|
53
|
+
(provider.refactor !== undefined ||
|
|
54
|
+
provider.rename !== undefined ||
|
|
55
|
+
provider.codeActions !== undefined)
|
|
56
|
+
);
|
|
52
57
|
}
|
|
53
58
|
|
|
54
59
|
// ── Runtime ────────────────────────────────────────────────────────────
|
|
@@ -78,7 +83,27 @@ export class WorkspaceRuntime {
|
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
/**
|
|
81
|
-
* Register a semantic provider for a workspace.
|
|
86
|
+
* Register a semantic provider for a workspace in pending state.
|
|
87
|
+
*
|
|
88
|
+
* Use this when the provider object exists and can accept calls, but the
|
|
89
|
+
* underlying semantic substrate is still warming (for example, an LSP server
|
|
90
|
+
* that has started but has not finished initial indexing yet).
|
|
91
|
+
*/
|
|
92
|
+
registerSemanticPending(cwd: string, provider: SemanticProvider): void {
|
|
93
|
+
const refactorAvailable = hasRefactorCapability(provider);
|
|
94
|
+
const existing = this.#workspaces.get(cwd);
|
|
95
|
+
if (existing) {
|
|
96
|
+
existing.semantic = { state: { kind: "pending" }, provider, refactorAvailable };
|
|
97
|
+
} else {
|
|
98
|
+
this.#workspaces.set(cwd, {
|
|
99
|
+
semantic: { state: { kind: "pending" }, provider, refactorAvailable },
|
|
100
|
+
structural: createDefaultCapabilities().structural,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Register a semantic provider for a workspace as ready.
|
|
82
107
|
* Replaces any existing semantic provider for the same cwd
|
|
83
108
|
* without affecting the structural provider.
|
|
84
109
|
*/
|
|
@@ -95,6 +120,16 @@ export class WorkspaceRuntime {
|
|
|
95
120
|
}
|
|
96
121
|
}
|
|
97
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Promote an already-registered semantic provider from pending to ready.
|
|
125
|
+
* If no semantic provider is registered for the workspace, this is a no-op.
|
|
126
|
+
*/
|
|
127
|
+
markSemanticReady(cwd: string): void {
|
|
128
|
+
const ws = this.#workspaces.get(cwd);
|
|
129
|
+
if (!ws || ws.semantic.provider === null) return;
|
|
130
|
+
ws.semantic.state = { kind: "ready" };
|
|
131
|
+
}
|
|
132
|
+
|
|
98
133
|
/**
|
|
99
134
|
* Register a structural provider for a workspace.
|
|
100
135
|
* Replaces any existing structural provider for the same cwd
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "SuPi core — shared infrastructure for SuPi extensions (XML context tags, config system)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"settings",
|
|
24
24
|
"configuration"
|
|
25
25
|
],
|
|
26
|
+
"type": "module",
|
|
26
27
|
"files": [
|
|
27
28
|
"src/**/*.ts",
|
|
28
29
|
"!__tests__"
|
|
@@ -49,12 +50,14 @@
|
|
|
49
50
|
},
|
|
50
51
|
"main": "src/api.ts",
|
|
51
52
|
"exports": {
|
|
53
|
+
"./abort-utils": "./src/abort-utils.ts",
|
|
52
54
|
"./api": "./src/api.ts",
|
|
53
55
|
"./config": "./src/config.ts",
|
|
54
56
|
"./context": "./src/context.ts",
|
|
55
57
|
"./debug": "./src/debug-registry.ts",
|
|
56
58
|
"./footer-registry": "./src/footer-registry.ts",
|
|
57
59
|
"./llm": "./src/llm.ts",
|
|
60
|
+
"./model-selection": "./src/model-selection.ts",
|
|
58
61
|
"./package.json": "./package.json",
|
|
59
62
|
"./path": "./src/path.ts",
|
|
60
63
|
"./report": "./src/report.ts",
|
|
@@ -63,6 +66,8 @@
|
|
|
63
66
|
"./session": "./src/session.ts",
|
|
64
67
|
"./settings": "./src/settings.ts",
|
|
65
68
|
"./settings-ui": "./src/settings-ui.ts",
|
|
69
|
+
"./spinner-frames": "./src/spinner-frames.ts",
|
|
70
|
+
"./status-spinner": "./src/status-spinner.ts",
|
|
66
71
|
"./terminal": "./src/terminal.ts",
|
|
67
72
|
"./tool-framework": "./src/tool-framework.ts",
|
|
68
73
|
"./types": "./src/types.ts"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abort controller/signal utility helpers.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Combine a caller-provided abort controller with a generation timeout signal.
|
|
9
|
+
*
|
|
10
|
+
* Returns the combined signal and a cleanup function that removes both
|
|
11
|
+
* event listeners. Callers must invoke cleanup in a `finally` block
|
|
12
|
+
* to avoid listener leaks.
|
|
13
|
+
*/
|
|
14
|
+
export function combineAbortSignals(
|
|
15
|
+
abort: AbortController,
|
|
16
|
+
timeoutMs: number,
|
|
17
|
+
): { signal: AbortSignal; cleanup: () => void } {
|
|
18
|
+
const timeoutSignal = AbortSignal.timeout(timeoutMs);
|
|
19
|
+
const combinedController = new AbortController();
|
|
20
|
+
const onAbort = () => combinedController.abort();
|
|
21
|
+
abort.signal.addEventListener("abort", onAbort, { once: true });
|
|
22
|
+
timeoutSignal.addEventListener("abort", onAbort, { once: true });
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
signal: combinedController.signal,
|
|
26
|
+
cleanup: () => {
|
|
27
|
+
abort.signal.removeEventListener("abort", onAbort);
|
|
28
|
+
timeoutSignal.removeEventListener("abort", onAbort);
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
// For lighter imports, use one of the domain subpaths directly
|
|
7
7
|
// (e.g. @mrclrchtr/supi-core/config, @mrclrchtr/supi-core/context).
|
|
8
8
|
|
|
9
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
10
|
+
export * from "./abort-utils.ts";
|
|
9
11
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
10
12
|
export * from "./config.ts";
|
|
11
13
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
@@ -17,6 +19,8 @@ export * from "./footer-registry.ts";
|
|
|
17
19
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
18
20
|
export * from "./llm.ts";
|
|
19
21
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
22
|
+
export * from "./model-selection.ts";
|
|
23
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
20
24
|
export * from "./path.ts";
|
|
21
25
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
22
26
|
export * from "./project.ts";
|
|
@@ -29,6 +33,10 @@ export * from "./settings.ts";
|
|
|
29
33
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
30
34
|
export * from "./settings-ui.ts";
|
|
31
35
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
36
|
+
export * from "./spinner-frames.ts";
|
|
37
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
38
|
+
export * from "./status-spinner.ts";
|
|
39
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
32
40
|
export * from "./terminal.ts";
|
|
33
41
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
34
42
|
export * from "./tool-framework.ts";
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// to enable auto-generated persistChange. When all items have a configType,
|
|
6
6
|
// the persistChange callback can be omitted.
|
|
7
7
|
|
|
8
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
8
9
|
import type { SettingItem } from "@earendil-works/pi-tui";
|
|
9
10
|
import type { SettingsScope } from "../settings/settings-registry.ts";
|
|
10
11
|
import { registerSettings } from "../settings/settings-registry.ts";
|
|
@@ -60,7 +61,12 @@ export interface ConfigSettingsOptions<T> {
|
|
|
60
61
|
* persistChange handling. When ALL items declare a configType,
|
|
61
62
|
* the `persistChange` callback can be omitted.
|
|
62
63
|
*/
|
|
63
|
-
buildItems: (
|
|
64
|
+
buildItems: (
|
|
65
|
+
settings: T,
|
|
66
|
+
scope: SettingsScope,
|
|
67
|
+
cwd: string,
|
|
68
|
+
ctx?: ExtensionContext,
|
|
69
|
+
) => ConfigSettingItem[];
|
|
64
70
|
/**
|
|
65
71
|
* Handle a settings change with scoped persistence helpers.
|
|
66
72
|
*
|
|
@@ -141,12 +147,12 @@ export function registerConfigSettings<T>(options: ConfigSettingsOptions<T>): vo
|
|
|
141
147
|
registerSettings({
|
|
142
148
|
id: options.id,
|
|
143
149
|
label: options.label,
|
|
144
|
-
loadValues: (scope, cwd) => {
|
|
150
|
+
loadValues: (scope, cwd, ctx) => {
|
|
145
151
|
const settings = loadSupiConfigForScope(options.section, cwd, options.defaults, {
|
|
146
152
|
scope,
|
|
147
153
|
homeDir: options.homeDir,
|
|
148
154
|
});
|
|
149
|
-
const items = options.buildItems(settings, scope, cwd);
|
|
155
|
+
const items = options.buildItems(settings, scope, cwd, ctx);
|
|
150
156
|
cachedItems = items;
|
|
151
157
|
return items;
|
|
152
158
|
},
|
|
@@ -173,7 +179,7 @@ export function registerConfigSettings<T>(options: ConfigSettingsOptions<T>): vo
|
|
|
173
179
|
}
|
|
174
180
|
|
|
175
181
|
// Auto-generate when all items are declarative
|
|
176
|
-
const items = cachedItems ?? options.buildItems(options.defaults, scope, cwd);
|
|
182
|
+
const items = cachedItems ?? options.buildItems(options.defaults, scope, cwd, undefined);
|
|
177
183
|
if (areAllItemsDeclarative(items)) {
|
|
178
184
|
autoPersistChange(settingId, value, helpers, items);
|
|
179
185
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { createRegistry } from "./registry-utils.ts";
|
|
9
9
|
|
|
10
10
|
/** Where the contribution should appear in the footer. */
|
|
11
|
-
export type FooterPlacement = "stats" | "status";
|
|
11
|
+
export type FooterPlacement = "stats" | "stats-end" | "status";
|
|
12
12
|
|
|
13
13
|
/** A single footer contribution registered by an extension. */
|
|
14
14
|
export interface FooterContribution {
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
// For lighter imports, use one of the domain subpaths directly
|
|
7
7
|
// (e.g. @mrclrchtr/supi-core/config, @mrclrchtr/supi-core/context).
|
|
8
8
|
|
|
9
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
10
|
+
export * from "./abort-utils.ts";
|
|
9
11
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
10
12
|
export * from "./config.ts";
|
|
11
13
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
@@ -15,6 +17,8 @@ export * from "./debug-registry.ts";
|
|
|
15
17
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
16
18
|
export * from "./footer-registry.ts";
|
|
17
19
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
20
|
+
export * from "./model-selection.ts";
|
|
21
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
18
22
|
export * from "./path.ts";
|
|
19
23
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
20
24
|
export * from "./project.ts";
|
|
@@ -27,6 +31,8 @@ export * from "./settings.ts";
|
|
|
27
31
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
28
32
|
export * from "./settings-ui.ts";
|
|
29
33
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
34
|
+
export * from "./status-spinner.ts";
|
|
35
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
30
36
|
export * from "./terminal.ts";
|
|
31
37
|
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
32
38
|
export * from "./tool-framework.ts";
|