@mrclrchtr/supi-code-intelligence 2.1.0 → 2.2.1
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 +17 -3
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/README.md +9 -8
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -3
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +0 -5
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/scoped-settings-list.ts +372 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-action-menu.ts +101 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +13 -7
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-schema.ts +464 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-submenus.ts +124 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +50 -309
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +2 -5
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings.ts +17 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +2 -2
- package/node_modules/@mrclrchtr/supi-core/README.md +9 -8
- package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -3
- package/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +0 -5
- package/node_modules/@mrclrchtr/supi-core/src/settings/scoped-settings-list.ts +372 -0
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-action-menu.ts +101 -0
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +13 -7
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-schema.ts +464 -0
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-submenus.ts +124 -0
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +50 -309
- package/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +2 -5
- package/node_modules/@mrclrchtr/supi-core/src/settings.ts +17 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/README.md +9 -8
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -3
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +0 -5
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/scoped-settings-list.ts +372 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-action-menu.ts +101 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +13 -7
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-schema.ts +464 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-submenus.ts +124 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +50 -309
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +2 -5
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings.ts +17 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +2 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +9 -8
- 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/config.ts +2 -3
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +0 -5
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/scoped-settings-list.ts +372 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-action-menu.ts +101 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +13 -7
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-schema.ts +464 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-submenus.ts +124 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +50 -309
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +2 -5
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings.ts +17 -1
- package/node_modules/@mrclrchtr/supi-lsp/package.json +3 -3
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +49 -12
- package/node_modules/@mrclrchtr/supi-lsp/src/config/lsp-settings.ts +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/README.md +9 -8
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +0 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/scoped-settings-list.ts +372 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-action-menu.ts +101 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +13 -7
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-schema.ts +464 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-submenus.ts +124 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +50 -309
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +2 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings.ts +17 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +2 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +9 -8
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +0 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/scoped-settings-list.ts +372 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-action-menu.ts +101 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +13 -7
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-schema.ts +464 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-submenus.ts +124 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +50 -309
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +2 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings.ts +17 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +3 -3
- package/package.json +5 -5
- package/src/analysis/instruction-files.ts +194 -0
- package/src/app/app.ts +6 -1
- package/src/config.ts +42 -0
- package/src/extension.ts +27 -0
- package/src/session/session.ts +67 -0
- package/src/substrate/lsp/diagnostic-injection.ts +0 -15
- package/src/substrate/lsp/settings.ts +101 -179
- package/src/tool/guidance.ts +27 -38
- package/src/tool/orientation/mode.ts +53 -2
- package/src/tool/result/types.ts +3 -0
- package/src/tool/schemas.ts +22 -32
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +0 -207
- package/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +0 -207
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +0 -207
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +0 -207
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +0 -207
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +0 -207
package/src/app/app.ts
CHANGED
|
@@ -77,8 +77,9 @@ export function createCodeIntelligenceApp(pi: ExtensionAPI): CodeIntelligenceApp
|
|
|
77
77
|
pi.on("session_start", (_event, ctx) => {
|
|
78
78
|
const session = manager.getOrCreateSession(ctx.cwd);
|
|
79
79
|
|
|
80
|
-
// Check if the branch already contains an overview
|
|
80
|
+
// Check if the branch already contains an overview and restore branch-local instruction state.
|
|
81
81
|
const branch = ctx.sessionManager.getBranch();
|
|
82
|
+
session.reconstructInstructionState(branch);
|
|
82
83
|
for (const entry of branch) {
|
|
83
84
|
if (
|
|
84
85
|
entry.type === "custom_message" &&
|
|
@@ -90,6 +91,10 @@ export function createCodeIntelligenceApp(pi: ExtensionAPI): CodeIntelligenceApp
|
|
|
90
91
|
}
|
|
91
92
|
});
|
|
92
93
|
|
|
94
|
+
pi.on("session_compact", (_event, ctx) => {
|
|
95
|
+
manager.getSession(ctx.cwd)?.resetSurfacedInstructionDirs();
|
|
96
|
+
});
|
|
97
|
+
|
|
93
98
|
pi.on("session_shutdown", () => {
|
|
94
99
|
// Clear per-session stores before releasing sessions
|
|
95
100
|
for (const session of manager.allSessions()) {
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Code Intelligence configuration and settings registration.
|
|
2
|
+
|
|
3
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
import { loadSupiConfig } from "@mrclrchtr/supi-core/config";
|
|
5
|
+
import { registerDeclarativeSettings } from "@mrclrchtr/supi-core/settings";
|
|
6
|
+
|
|
7
|
+
const CODE_INTELLIGENCE_SECTION = "code-intelligence";
|
|
8
|
+
|
|
9
|
+
/** User-facing configuration for the code-intelligence extension. */
|
|
10
|
+
export interface CodeIntelligenceConfig extends Record<string, unknown> {
|
|
11
|
+
/** Ordered directory-local instruction file names to surface during directory orientation. */
|
|
12
|
+
instructionFileNames: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Default code-intelligence configuration. */
|
|
16
|
+
export const CODE_INTELLIGENCE_DEFAULTS: CodeIntelligenceConfig = {
|
|
17
|
+
instructionFileNames: ["CLAUDE.md", "AGENTS.md"],
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/** Load merged code-intelligence configuration for a workspace. */
|
|
21
|
+
export function loadCodeIntelligenceConfig(cwd: string, homeDir?: string): CodeIntelligenceConfig {
|
|
22
|
+
return loadSupiConfig(CODE_INTELLIGENCE_SECTION, cwd, CODE_INTELLIGENCE_DEFAULTS, { homeDir });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Register code-intelligence settings with the shared SuPi settings registry. */
|
|
26
|
+
export function registerCodeIntelligenceSettings(pi: ExtensionAPI, homeDir?: string): void {
|
|
27
|
+
registerDeclarativeSettings(pi, {
|
|
28
|
+
id: CODE_INTELLIGENCE_SECTION,
|
|
29
|
+
label: "Code Intelligence",
|
|
30
|
+
section: CODE_INTELLIGENCE_SECTION,
|
|
31
|
+
defaults: CODE_INTELLIGENCE_DEFAULTS,
|
|
32
|
+
fields: [
|
|
33
|
+
{
|
|
34
|
+
kind: "stringList" as const,
|
|
35
|
+
key: "instructionFileNames",
|
|
36
|
+
label: "Instruction File Names",
|
|
37
|
+
description: "Directory-local instruction file names shown by directory orientation",
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
...(homeDir ? { homeDir } : {}),
|
|
41
|
+
});
|
|
42
|
+
}
|
package/src/extension.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
gatherCoverageEvalInput,
|
|
9
9
|
} from "./analysis/coverage/coverage-warnings.ts";
|
|
10
10
|
import { createCodeIntelligenceApp } from "./app/app.ts";
|
|
11
|
+
import { registerCodeIntelligenceSettings } from "./config.ts";
|
|
11
12
|
import type { WorkspaceCodeIntelligenceSession } from "./session/session.ts";
|
|
12
13
|
import { registerDiagnosticInjectionHandlers } from "./substrate/lsp/diagnostic-injection.ts";
|
|
13
14
|
import { registerLspSessionLifecycle } from "./substrate/lsp/lifecycle.ts";
|
|
@@ -38,6 +39,7 @@ export default function codeIntelligenceExtension(
|
|
|
38
39
|
const tsState = createTsAdapterState();
|
|
39
40
|
|
|
40
41
|
// ── Substrate wiring ──────────────────────────────────────────────
|
|
42
|
+
registerCodeIntelligenceSettings(pi);
|
|
41
43
|
registerLspSettings(pi);
|
|
42
44
|
registerLspSessionLifecycle(pi, lspState);
|
|
43
45
|
registerLspAwareToolOverrides(pi, lspState);
|
|
@@ -64,6 +66,12 @@ export default function codeIntelligenceExtension(
|
|
|
64
66
|
registerCiStatusCommand(pi);
|
|
65
67
|
registerLspFooterContribution(lspState);
|
|
66
68
|
|
|
69
|
+
// ── Native context path capture for instruction-file dedup ─────────
|
|
70
|
+
pi.on("before_agent_start", (event, ctx) => {
|
|
71
|
+
const session = app.getSession(ctx.cwd) ?? app.createSession(ctx.cwd);
|
|
72
|
+
session.captureNativeInstructionPaths(event.systemPromptOptions.contextFiles ?? []);
|
|
73
|
+
});
|
|
74
|
+
|
|
67
75
|
// ── Coverage warning emission ─────────────────────────────────────
|
|
68
76
|
pi.on(
|
|
69
77
|
"before_agent_start",
|
|
@@ -129,4 +137,23 @@ export default function codeIntelligenceExtension(
|
|
|
129
137
|
};
|
|
130
138
|
},
|
|
131
139
|
);
|
|
140
|
+
|
|
141
|
+
// ── Process-exit safety net ─────────────────────────────────────────
|
|
142
|
+
//
|
|
143
|
+
// If the Node process exits without `session_shutdown` firing (crash,
|
|
144
|
+
// unhandled rejection, SIGINT), make a best-effort synchronous attempt
|
|
145
|
+
// to terminate the LSP and Tree-sitter controller trees.
|
|
146
|
+
//
|
|
147
|
+
// `process.on("exit")` handlers are synchronous — we cannot await
|
|
148
|
+
// controller shutdown, but `process.kill(-pid, "SIGTERM")` fires
|
|
149
|
+
// synchronously and the SIGKILL escalation in LspClient is handled
|
|
150
|
+
// by the kernel after process termination.
|
|
151
|
+
let cleaningUp = false;
|
|
152
|
+
process.once("exit", () => {
|
|
153
|
+
if (cleaningUp) return;
|
|
154
|
+
cleaningUp = true;
|
|
155
|
+
// Fire and forget — the critical kill calls are synchronous.
|
|
156
|
+
void lspState.controller?.shutdown();
|
|
157
|
+
void tsState.controller?.shutdown();
|
|
158
|
+
});
|
|
132
159
|
}
|
package/src/session/session.ts
CHANGED
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
* @mrclrchtr/supi-code-intelligence — internal, not exported via api.ts
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
+
import * as path from "node:path";
|
|
19
|
+
import type { SessionEntry } from "@earendil-works/pi-coding-agent";
|
|
18
20
|
import {
|
|
19
21
|
getDefaultWorkspaceRuntime,
|
|
20
22
|
type SemanticProvider,
|
|
@@ -104,6 +106,12 @@ export class WorkspaceCodeIntelligenceSession {
|
|
|
104
106
|
*/
|
|
105
107
|
readonly coverageWarningState = new CoverageWarningState();
|
|
106
108
|
|
|
109
|
+
/** Absolute instruction files already loaded by PI's native context-file mechanism. */
|
|
110
|
+
readonly nativeInstructionPaths = new Set<string>();
|
|
111
|
+
|
|
112
|
+
/** Absolute directories whose instruction files were already surfaced by code_orientation. */
|
|
113
|
+
readonly surfacedInstructionDirs = new Set<string>();
|
|
114
|
+
|
|
107
115
|
/**
|
|
108
116
|
* Optional LSP controller reference — attached by LSP lifecycle module
|
|
109
117
|
* for coverage evaluation and server management.
|
|
@@ -142,6 +150,38 @@ export class WorkspaceCodeIntelligenceSession {
|
|
|
142
150
|
});
|
|
143
151
|
}
|
|
144
152
|
|
|
153
|
+
// ── Instruction-file state ───────────────────────────────────────
|
|
154
|
+
|
|
155
|
+
/** Remember instruction/context file paths already loaded by PI natively. */
|
|
156
|
+
captureNativeInstructionPaths(files: Array<{ path: string }>): void {
|
|
157
|
+
for (const file of files) {
|
|
158
|
+
this.nativeInstructionPaths.add(path.resolve(this.cwd, file.path));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Mark directory-local instruction files as surfaced after a successful orientation render. */
|
|
163
|
+
markInstructionDirsSurfaced(directories: string[]): void {
|
|
164
|
+
for (const directory of directories) {
|
|
165
|
+
this.surfacedInstructionDirs.add(path.resolve(this.cwd, directory));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Clear instruction-file dedup state after compaction. */
|
|
170
|
+
resetSurfacedInstructionDirs(): void {
|
|
171
|
+
this.surfacedInstructionDirs.clear();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Reconstruct surfaced instruction directories from branch tool-result details after compaction. */
|
|
175
|
+
reconstructInstructionState(branch: SessionEntry[]): void {
|
|
176
|
+
this.surfacedInstructionDirs.clear();
|
|
177
|
+
const entries = entriesAfterLatestCompaction(branch);
|
|
178
|
+
for (const entry of entries) {
|
|
179
|
+
for (const directory of extractInstructionDirectories(entry)) {
|
|
180
|
+
this.surfacedInstructionDirs.add(path.resolve(this.cwd, directory));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
145
185
|
// ── Provider access ───────────────────────────────────────────────
|
|
146
186
|
|
|
147
187
|
/**
|
|
@@ -290,7 +330,34 @@ export class WorkspaceCodeIntelligenceSession {
|
|
|
290
330
|
clearStores(): void {
|
|
291
331
|
this.#refactorPlans.clear();
|
|
292
332
|
this.#workflowTargets.clear();
|
|
333
|
+
this.surfacedInstructionDirs.clear();
|
|
334
|
+
this.nativeInstructionPaths.clear();
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function entriesAfterLatestCompaction(branch: SessionEntry[]): SessionEntry[] {
|
|
339
|
+
let start = 0;
|
|
340
|
+
for (let i = 0; i < branch.length; i++) {
|
|
341
|
+
if (branch[i]?.type === "compaction") start = i + 1;
|
|
293
342
|
}
|
|
343
|
+
return branch.slice(start);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function extractInstructionDirectories(entry: SessionEntry): string[] {
|
|
347
|
+
if (entry.type !== "message" || entry.message.role !== "toolResult") return [];
|
|
348
|
+
if (entry.message.toolName !== "code_orientation") return [];
|
|
349
|
+
|
|
350
|
+
const details = entry.message.details as
|
|
351
|
+
| { type?: string; data?: { instructions?: { files?: Array<{ directory?: unknown }> } } }
|
|
352
|
+
| undefined;
|
|
353
|
+
if (details?.type !== "context") return [];
|
|
354
|
+
|
|
355
|
+
const files = details.data?.instructions?.files;
|
|
356
|
+
if (!Array.isArray(files)) return [];
|
|
357
|
+
|
|
358
|
+
return files
|
|
359
|
+
.map((file) => file.directory)
|
|
360
|
+
.filter((directory): directory is string => typeof directory === "string");
|
|
294
361
|
}
|
|
295
362
|
|
|
296
363
|
// ── Standalone target-id expansion helper ─────────────────────────────
|
|
@@ -12,9 +12,6 @@ import {
|
|
|
12
12
|
import type { LspAdapterState } from "./state.ts";
|
|
13
13
|
import { diagnosticMessageString } from "./utils.ts";
|
|
14
14
|
|
|
15
|
-
// LSP_TOOL_NAMES removed — lsp_* tools are no longer registered (TNDM-A9AQF4)
|
|
16
|
-
const LSP_TOOL_NAMES: readonly string[] = [];
|
|
17
|
-
|
|
18
15
|
export function registerDiagnosticInjectionHandlers(
|
|
19
16
|
pi: ExtensionAPI,
|
|
20
17
|
state: LspAdapterState,
|
|
@@ -22,21 +19,9 @@ export function registerDiagnosticInjectionHandlers(
|
|
|
22
19
|
pi.on("before_agent_start", async (_event, _ctx: ExtensionContext) => {
|
|
23
20
|
const manager = state.controller?.manager;
|
|
24
21
|
if (!manager || !state.lspActive) {
|
|
25
|
-
const activeTools = pi.getActiveTools();
|
|
26
|
-
const nextTools = activeTools.filter(
|
|
27
|
-
(t: string) => !LSP_TOOL_NAMES.includes(t as (typeof LSP_TOOL_NAMES)[number]),
|
|
28
|
-
);
|
|
29
|
-
if (nextTools.length !== activeTools.length) {
|
|
30
|
-
pi.setActiveTools(nextTools);
|
|
31
|
-
}
|
|
32
22
|
return;
|
|
33
23
|
}
|
|
34
24
|
|
|
35
|
-
const missing = LSP_TOOL_NAMES.filter((name) => !pi.getActiveTools().includes(name));
|
|
36
|
-
if (missing.length > 0) {
|
|
37
|
-
pi.setActiveTools([...pi.getActiveTools(), ...missing]);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
25
|
// Sentinel refresh: detect lockfile/tsconfig/d.ts changes from outside write/edit
|
|
41
26
|
applySentinelChanges(state, manager);
|
|
42
27
|
|
|
@@ -4,26 +4,21 @@
|
|
|
4
4
|
// are deprecated and ignored. Per-language disable via
|
|
5
5
|
// `lsp.servers.<language>.enabled: false` is the only supported opt-out.
|
|
6
6
|
//
|
|
7
|
-
//
|
|
8
|
-
// - severity
|
|
9
|
-
// -
|
|
10
|
-
// -
|
|
7
|
+
// Uses the declarative settings schema with:
|
|
8
|
+
// - severity: number with labeled values
|
|
9
|
+
// - exclude: stringList
|
|
10
|
+
// - disabled_servers: custom submenu that writes per-language disable config
|
|
11
11
|
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
type ExtensionAPI,
|
|
15
|
-
getSettingsListTheme,
|
|
16
|
-
} from "@earendil-works/pi-coding-agent";
|
|
17
|
-
import type { SettingItem } from "@earendil-works/pi-tui";
|
|
12
|
+
import { type ExtensionAPI, getSettingsListTheme } from "@earendil-works/pi-coding-agent";
|
|
13
|
+
import type { Component, SettingItem } from "@earendil-works/pi-tui";
|
|
18
14
|
import { Container, Key, matchesKey, SettingsList, Text } from "@earendil-works/pi-tui";
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
import { loadSupiConfigSectionForScope, writeSupiConfig } from "@mrclrchtr/supi-core/config";
|
|
22
17
|
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
} from "@mrclrchtr/supi-core/
|
|
18
|
+
registerDeclarativeSettings,
|
|
19
|
+
type SettingsScope,
|
|
20
|
+
type ValueSource,
|
|
21
|
+
} from "@mrclrchtr/supi-core/settings";
|
|
27
22
|
import { type LspSettings, loadConfig } from "@mrclrchtr/supi-lsp/api";
|
|
28
23
|
|
|
29
24
|
const LSP_DEFAULTS: LspSettings = {
|
|
@@ -33,21 +28,6 @@ const LSP_DEFAULTS: LspSettings = {
|
|
|
33
28
|
exclude: [],
|
|
34
29
|
};
|
|
35
30
|
|
|
36
|
-
function severityLabel(severity: number): string {
|
|
37
|
-
switch (severity) {
|
|
38
|
-
case 1:
|
|
39
|
-
return "errors";
|
|
40
|
-
case 2:
|
|
41
|
-
return "warnings";
|
|
42
|
-
case 3:
|
|
43
|
-
return "info";
|
|
44
|
-
case 4:
|
|
45
|
-
return "hints";
|
|
46
|
-
default:
|
|
47
|
-
return "errors";
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
31
|
/** Discover configured servers from the defaults + effective LSP config. */
|
|
52
32
|
function getConfiguredServers(cwd: string): string[] {
|
|
53
33
|
try {
|
|
@@ -63,12 +43,10 @@ function getConfiguredServers(cwd: string): string[] {
|
|
|
63
43
|
* configured disabled servers from the persisted config.
|
|
64
44
|
*/
|
|
65
45
|
function getDisabledServersFromConfig(scope: SettingsScope, cwd: string): Set<string> {
|
|
66
|
-
const section =
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
{ scope },
|
|
71
|
-
);
|
|
46
|
+
const section = loadSupiConfigSectionForScope("lsp", cwd, {
|
|
47
|
+
scope,
|
|
48
|
+
});
|
|
49
|
+
if (!section) return new Set();
|
|
72
50
|
const servers = section.servers as Record<string, { enabled?: boolean }> | undefined;
|
|
73
51
|
const disabled = new Set<string>();
|
|
74
52
|
if (servers) {
|
|
@@ -79,75 +57,11 @@ function getDisabledServersFromConfig(scope: SettingsScope, cwd: string): Set<st
|
|
|
79
57
|
return disabled;
|
|
80
58
|
}
|
|
81
59
|
|
|
82
|
-
export function registerLspSettings(pi: ExtensionAPI): void {
|
|
83
|
-
registerConfigSettings(pi, {
|
|
84
|
-
id: "lsp",
|
|
85
|
-
label: "LSP",
|
|
86
|
-
section: "lsp",
|
|
87
|
-
defaults: LSP_DEFAULTS,
|
|
88
|
-
buildItems: (settings, scope, cwd) => buildLspSettingItems(settings, scope, cwd),
|
|
89
|
-
// biome-ignore lint/complexity/useMaxParams: registerConfigSettings callback signature
|
|
90
|
-
persistChange: (_scope, _cwd, settingId, value, helpers) => {
|
|
91
|
-
switch (settingId) {
|
|
92
|
-
case "severity": {
|
|
93
|
-
const num = Number.parseInt(value.split(" ")[0] ?? "1", 10);
|
|
94
|
-
helpers.set("severity", Number.isNaN(num) ? 1 : num);
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
case "exclude": {
|
|
98
|
-
const patterns = value
|
|
99
|
-
.split(",")
|
|
100
|
-
.map((s) => s.trim())
|
|
101
|
-
.filter(Boolean);
|
|
102
|
-
if (patterns.length > 0) helpers.set("exclude", patterns);
|
|
103
|
-
else helpers.unset("exclude");
|
|
104
|
-
break;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function buildLspSettingItems(
|
|
112
|
-
settings: LspSettings,
|
|
113
|
-
scope: "project" | "global",
|
|
114
|
-
cwd: string,
|
|
115
|
-
): SettingItem[] {
|
|
116
|
-
return [
|
|
117
|
-
{
|
|
118
|
-
id: "severity",
|
|
119
|
-
label: "Inline Severity",
|
|
120
|
-
description: "Minimum diagnostic severity to show inline (1=errors, 4=hints)",
|
|
121
|
-
currentValue: `${settings.severity} (${severityLabel(settings.severity)})`,
|
|
122
|
-
values: ["1 (errors)", "2 (warnings)", "3 (info)", "4 (hints)"],
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
id: "disabled_servers",
|
|
126
|
-
label: "Disabled Servers",
|
|
127
|
-
description: "Press Enter to choose which language servers to disable",
|
|
128
|
-
currentValue: renderDisabledServersLabel(scope, cwd),
|
|
129
|
-
submenu: (_currentValue, done) => createDisabledServersSubmenu(scope, cwd, done),
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
id: "exclude",
|
|
133
|
-
label: "Exclude Patterns",
|
|
134
|
-
description: "Gitignore patterns to suppress LSP diagnostics",
|
|
135
|
-
currentValue: settings.exclude.length > 0 ? settings.exclude.join(", ") : "none",
|
|
136
|
-
submenu: (_currentValue, done) => createExcludeSubmenu(scope, cwd, settings, done),
|
|
137
|
-
},
|
|
138
|
-
];
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function renderDisabledServersLabel(scope: SettingsScope, cwd: string): string {
|
|
142
|
-
const disabled = getDisabledServersFromConfig(scope, cwd);
|
|
143
|
-
return disabled.size > 0 ? [...disabled].sort().join(", ") : "none disabled";
|
|
144
|
-
}
|
|
145
|
-
|
|
146
60
|
function createDisabledServersSubmenu(
|
|
147
61
|
scope: SettingsScope,
|
|
148
62
|
cwd: string,
|
|
149
|
-
done: (
|
|
150
|
-
) {
|
|
63
|
+
done: (selectedValue?: string) => void,
|
|
64
|
+
): Component {
|
|
151
65
|
const allServers = getConfiguredServers(cwd);
|
|
152
66
|
const disabledServers = getDisabledServersFromConfig(scope, cwd);
|
|
153
67
|
|
|
@@ -160,14 +74,7 @@ function createDisabledServersSubmenu(
|
|
|
160
74
|
|
|
161
75
|
let dirty = false;
|
|
162
76
|
const container = new Container();
|
|
163
|
-
|
|
164
|
-
container.addChild(header);
|
|
165
|
-
const footer = new Text(
|
|
166
|
-
"Marking a server as disabled writes lsp.servers.<lang>.enabled: false for this scope",
|
|
167
|
-
0,
|
|
168
|
-
0,
|
|
169
|
-
);
|
|
170
|
-
container.addChild(footer);
|
|
77
|
+
container.addChild(new Text(" Disabled Servers — per-language opt-out", 1, 0));
|
|
171
78
|
|
|
172
79
|
const settingsList = new SettingsList(
|
|
173
80
|
items,
|
|
@@ -184,26 +91,22 @@ function createDisabledServersSubmenu(
|
|
|
184
91
|
{ enableSearch: true },
|
|
185
92
|
);
|
|
186
93
|
container.addChild(settingsList);
|
|
94
|
+
container.addChild(new Text(" esc save and close", 1, 0));
|
|
187
95
|
|
|
188
96
|
return {
|
|
189
97
|
render: (width: number) => container.render(width),
|
|
190
98
|
invalidate: () => container.invalidate(),
|
|
191
|
-
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: single event handler
|
|
99
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: single event handler for the submenu
|
|
192
100
|
handleInput: (data: string) => {
|
|
193
101
|
if (matchesKey(data, Key.escape)) {
|
|
194
102
|
if (!dirty) {
|
|
195
103
|
done();
|
|
196
|
-
return
|
|
104
|
+
return;
|
|
197
105
|
}
|
|
198
106
|
// Write per-language enabled/disabled into lsp.servers
|
|
199
|
-
const currentSection =
|
|
200
|
-
"lsp",
|
|
201
|
-
cwd,
|
|
202
|
-
{ servers: {} as Record<string, { enabled?: boolean }> },
|
|
203
|
-
{ scope },
|
|
204
|
-
);
|
|
107
|
+
const currentSection = loadSupiConfigSectionForScope("lsp", cwd, { scope });
|
|
205
108
|
const servers =
|
|
206
|
-
(currentSection
|
|
109
|
+
(currentSection?.servers as Record<string, Record<string, unknown>> | undefined) ?? {};
|
|
207
110
|
|
|
208
111
|
for (const item of items) {
|
|
209
112
|
if (item.currentValue === "disabled") {
|
|
@@ -212,7 +115,6 @@ function createDisabledServersSubmenu(
|
|
|
212
115
|
const srv = servers[item.id];
|
|
213
116
|
if (srv) {
|
|
214
117
|
delete srv.enabled;
|
|
215
|
-
// If only `enabled` was the property, remove the whole entry
|
|
216
118
|
if (Object.keys(srv).length === 0) {
|
|
217
119
|
delete servers[item.id];
|
|
218
120
|
}
|
|
@@ -221,70 +123,90 @@ function createDisabledServersSubmenu(
|
|
|
221
123
|
}
|
|
222
124
|
|
|
223
125
|
writeSupiConfig({ section: "lsp", scope, cwd }, { servers });
|
|
224
|
-
done();
|
|
225
|
-
return
|
|
126
|
+
done("saved");
|
|
127
|
+
return;
|
|
226
128
|
}
|
|
227
129
|
settingsList.handleInput?.(data);
|
|
228
|
-
return true;
|
|
229
130
|
},
|
|
230
131
|
};
|
|
231
132
|
}
|
|
232
133
|
|
|
233
|
-
function
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
134
|
+
export function registerLspSettings(pi: ExtensionAPI): void {
|
|
135
|
+
registerDeclarativeSettings(pi, {
|
|
136
|
+
id: "lsp",
|
|
137
|
+
label: "LSP",
|
|
138
|
+
section: "lsp",
|
|
139
|
+
defaults: LSP_DEFAULTS,
|
|
140
|
+
fields: [
|
|
141
|
+
{
|
|
142
|
+
kind: "number" as const,
|
|
143
|
+
key: "severity",
|
|
144
|
+
label: "Inline Severity",
|
|
145
|
+
description: "Minimum diagnostic severity to show inline (1=errors, 4=hints)",
|
|
146
|
+
values: ["1", "2", "3", "4"],
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
kind: "stringList" as const,
|
|
150
|
+
key: "exclude",
|
|
151
|
+
label: "Exclude Patterns",
|
|
152
|
+
description: "Gitignore patterns to suppress LSP diagnostics (comma-separated)",
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
kind: "custom" as const,
|
|
156
|
+
key: "disabled_servers",
|
|
157
|
+
label: "Disabled Servers",
|
|
158
|
+
description: "Press Enter to choose which language servers to disable",
|
|
159
|
+
resolve: (scope, cwd) => {
|
|
160
|
+
const scopedDisabled = getDisabledServersFromConfig(scope, cwd);
|
|
161
|
+
const otherScope = scope === "project" ? "global" : "project";
|
|
162
|
+
const otherDisabled =
|
|
163
|
+
scope === "project" ? getDisabledServersFromConfig("global", cwd) : new Set<string>();
|
|
164
|
+
|
|
165
|
+
// Effective disabled servers = union of both scopes (since either disables)
|
|
166
|
+
const effectiveDisabled = new Set([...scopedDisabled, ...otherDisabled]);
|
|
167
|
+
const label =
|
|
168
|
+
effectiveDisabled.size > 0 ? [...effectiveDisabled].sort().join(", ") : "none disabled";
|
|
169
|
+
|
|
170
|
+
// Source: where the override comes from
|
|
171
|
+
let source: ValueSource;
|
|
172
|
+
if (scopedDisabled.size > 0) {
|
|
173
|
+
source = scope;
|
|
174
|
+
} else if (otherDisabled.size > 0) {
|
|
175
|
+
source = otherScope as ValueSource;
|
|
176
|
+
} else {
|
|
177
|
+
source = "default";
|
|
178
|
+
}
|
|
257
179
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
const idx = items.findIndex((i) => i.id === id);
|
|
264
|
-
if (idx >= 0 && items[idx].currentValue !== newValue) {
|
|
265
|
-
dirty = true;
|
|
266
|
-
items[idx].currentValue = newValue;
|
|
267
|
-
}
|
|
268
|
-
},
|
|
269
|
-
() => {},
|
|
270
|
-
);
|
|
271
|
-
container.addChild(settingsList);
|
|
180
|
+
let inheritanceSource: "global" | "default" | undefined;
|
|
181
|
+
if (scope === "project" && source === "project") {
|
|
182
|
+
inheritanceSource =
|
|
183
|
+
getDisabledServersFromConfig("global", cwd).size > 0 ? "global" : "default";
|
|
184
|
+
}
|
|
272
185
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
186
|
+
return { displayValue: label, source, inheritanceSource };
|
|
187
|
+
},
|
|
188
|
+
submenu: (_currentValue, done, scope, cwd) =>
|
|
189
|
+
createDisabledServersSubmenu(scope, cwd, done),
|
|
190
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: custom field persist handler orchestrates nested config writes
|
|
191
|
+
persist: (scope, cwd, action, _helpers) => {
|
|
192
|
+
if (action.kind === "inherit" || action.kind === "resetToDefault") {
|
|
193
|
+
// Clear all per-server enable/disable entries for this scope
|
|
194
|
+
const currentSection = loadSupiConfigSectionForScope("lsp", cwd, { scope });
|
|
195
|
+
const servers =
|
|
196
|
+
(currentSection?.servers as Record<string, Record<string, unknown>> | undefined) ??
|
|
197
|
+
{};
|
|
198
|
+
for (const name of Object.keys(servers)) {
|
|
199
|
+
const srv = servers[name];
|
|
200
|
+
if (srv) {
|
|
201
|
+
delete srv.enabled;
|
|
202
|
+
if (Object.keys(srv).length === 0) delete servers[name];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
writeSupiConfig({ section: "lsp", scope, cwd }, { servers });
|
|
206
|
+
}
|
|
207
|
+
// Explicit set actions are handled entirely inside the submenu
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
});
|
|
290
212
|
}
|