@mrclrchtr/supi-code-intelligence 6.1.0 → 6.2.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 +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/debug-identity.ts +11 -0
- package/node_modules/@mrclrchtr/supi-core/src/debug.ts +5 -0
- package/node_modules/@mrclrchtr/supi-lsp/README.md +21 -3
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- 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/debug-identity.ts +11 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug.ts +5 -0
- package/node_modules/@mrclrchtr/supi-lsp/package.json +4 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +12 -7
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-cache.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-capabilities.ts +0 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-publication.ts +6 -3
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-refresh.ts +2 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-timing.ts +5 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostics.ts +2 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +17 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +40 -18
- package/node_modules/@mrclrchtr/supi-lsp/src/config/config.ts +164 -30
- package/node_modules/@mrclrchtr/supi-lsp/src/config/lsp-settings.ts +9 -87
- package/node_modules/@mrclrchtr/supi-lsp/src/config/server-config.ts +0 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/config/tsconfig-scope.ts +4 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/config/types.ts +0 -29
- package/node_modules/@mrclrchtr/supi-lsp/src/debug-telemetry.ts +7 -21
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostic-severity.ts +6 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostic-summary.ts +11 -14
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/evidence.ts +0 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/stale-diagnostics.ts +0 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/workspace-sentinels.ts +29 -49
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-client-state.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +4 -8
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-helpers.ts +1 -9
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-project-info.ts +6 -3
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +9 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-symbol.ts +26 -41
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +275 -99
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +4 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-symbol-mapper.ts +59 -28
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-controller.ts +27 -19
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostics.ts +26 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registration.ts +0 -17
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registry.ts +83 -19
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-transition-debug.ts +5 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/session/scanner.ts +24 -21
- package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +29 -3
- package/node_modules/@mrclrchtr/supi-lsp/src/summary.ts +19 -40
- package/node_modules/@mrclrchtr/supi-lsp/src/utils.ts +13 -19
- package/node_modules/@mrclrchtr/supi-lsp/src/workspace-path-policy.ts +287 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +6 -18
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- 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/debug-identity.ts +11 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug.ts +5 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +3 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +1 -11
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/coordinates.ts +19 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/language.ts +5 -23
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/operation-support.ts +3 -21
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +5 -9
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-controller.ts +10 -20
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +7 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client.ts +9 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-protocol.ts +134 -9
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-name.ts +96 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-sites.ts +11 -12
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +39 -56
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/exports.ts +9 -7
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/js-binding-pattern.ts +26 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/node-at.ts +2 -21
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/outline-html-sql.ts +144 -12
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/outline.ts +50 -37
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/scope.ts +138 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +0 -7
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store.ts +1 -14
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime.ts +0 -10
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/service.ts +6 -8
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/worker-main.ts +34 -10
- package/package.json +5 -5
- package/src/analysis/capability/capability-warnings.ts +4 -22
- package/src/analysis/search/ast-scan-timing.ts +4 -2
- package/src/analysis/search/ast-scan.ts +1 -1
- package/src/api.ts +1 -0
- package/src/extension.ts +4 -2
- package/src/session/health-refresh.ts +24 -2
- package/src/session/health-types.ts +19 -0
- package/src/session/input/health-refactor.ts +16 -14
- package/src/session/refactor-types.ts +14 -1
- package/src/session/refactor-workflow.ts +21 -16
- package/src/substrate/lsp/lifecycle.ts +0 -3
- package/src/substrate/lsp/maintenance.ts +4 -5
- package/src/substrate/lsp/settings.ts +6 -9
- package/src/substrate/lsp/state.ts +0 -2
- package/src/substrate/workspace-provider-host.ts +2 -2
- package/src/tool/code_health/file-scope-markdown.ts +43 -0
- package/src/tool/code_health/markdown.ts +66 -66
- package/src/tool/code_health/refresh-outcome.ts +46 -0
- package/src/tool/code_health/refresh-status.ts +166 -23
- package/src/tool/code_health/result.ts +1 -0
- package/src/tool/code_health/tui.ts +18 -5
- package/src/tool/code_refactor_apply/guidance.ts +3 -2
- package/src/tool/code_refactor_plan/guidance.ts +1 -1
- package/src/tool/register.ts +5 -2
- package/src/tool/schemas.ts +21 -11
- package/node_modules/@mrclrchtr/supi-lsp/src/config/server-actions.ts +0 -59
- package/node_modules/@mrclrchtr/supi-lsp/src/pattern-matcher.ts +0 -24
- package/node_modules/@mrclrchtr/supi-tree-sitter/scripts/generate-kotlin-wasm.mjs +0 -132
- package/node_modules/@mrclrchtr/supi-tree-sitter/scripts/generate-sql-wasm.mjs +0 -158
- package/node_modules/@mrclrchtr/supi-tree-sitter/scripts/vendor-wasm.mjs +0 -167
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +0 -42
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-registration.ts +0 -37
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/service-registry.ts +0 -30
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/structure.ts +0 -8
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
+
import { fileToUri, uriToFile } from "@mrclrchtr/supi-core/path";
|
|
3
4
|
import { FileChangeType, type FileEvent } from "../config/types.ts";
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
type AutomaticLspPathPolicy,
|
|
7
|
+
createDefaultAutomaticLspPathPolicy,
|
|
8
|
+
walkAutomaticLspTree,
|
|
9
|
+
} from "../workspace-path-policy.ts";
|
|
5
10
|
|
|
6
|
-
const IGNORED_DIRECTORIES = new Set(["node_modules", ".pnpm", ".git", "dist", "coverage"]);
|
|
7
11
|
const ROOT_LOCKFILES = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lockb"];
|
|
8
12
|
|
|
9
13
|
export interface WorkspaceSentinelScanOptions {
|
|
@@ -13,6 +17,8 @@ export interface WorkspaceSentinelScanOptions {
|
|
|
13
17
|
* the diff then reports them as `sourceChanges` so the caller can pull them.
|
|
14
18
|
*/
|
|
15
19
|
includeSourceFiles?: boolean;
|
|
20
|
+
/** Runtime-owned automatic path policy. */
|
|
21
|
+
policy?: AutomaticLspPathPolicy;
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
/** Build a fresh snapshot of workspace sentinel files and their mtimes. */
|
|
@@ -25,11 +31,19 @@ export function scanWorkspaceSentinels(
|
|
|
25
31
|
|
|
26
32
|
if (!fs.existsSync(resolvedCwd)) return snapshot;
|
|
27
33
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
const policy = options.policy ?? createDefaultAutomaticLspPathPolicy(resolvedCwd);
|
|
35
|
+
walkAutomaticLspTree(policy, resolvedCwd, Number.MAX_SAFE_INTEGER, (directory, entries) => {
|
|
36
|
+
for (const entry of entries) {
|
|
37
|
+
if (!entry.isFile() && !entry.isSymbolicLink()) continue;
|
|
38
|
+
const filePath = path.join(directory, entry.name);
|
|
39
|
+
if (!options.includeSourceFiles && !isWorkspaceSentinelPath(filePath, resolvedCwd)) continue;
|
|
40
|
+
try {
|
|
41
|
+
snapshot.set(filePath, fs.statSync(filePath).mtimeMs);
|
|
42
|
+
} catch {
|
|
43
|
+
// File deleted between readdir and stat — skip.
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
33
47
|
|
|
34
48
|
return snapshot;
|
|
35
49
|
}
|
|
@@ -60,6 +74,13 @@ export function diffWorkspaceSentinelSnapshot(
|
|
|
60
74
|
return changes.sort((a, b) => a.uri.localeCompare(b.uri));
|
|
61
75
|
}
|
|
62
76
|
|
|
77
|
+
/** One policy-filtered workspace inventory refresh. */
|
|
78
|
+
export interface WorkspaceSentinelSyncResult {
|
|
79
|
+
snapshot: Map<string, number>;
|
|
80
|
+
changes: FileEvent[];
|
|
81
|
+
sourceChanges: FileEvent[];
|
|
82
|
+
}
|
|
83
|
+
|
|
63
84
|
/**
|
|
64
85
|
* Refresh a previous snapshot and return the new snapshot plus change events.
|
|
65
86
|
*
|
|
@@ -72,7 +93,7 @@ export function syncWorkspaceSentinelSnapshot(
|
|
|
72
93
|
cwd: string,
|
|
73
94
|
previous: Map<string, number>,
|
|
74
95
|
options: WorkspaceSentinelScanOptions = {},
|
|
75
|
-
):
|
|
96
|
+
): WorkspaceSentinelSyncResult {
|
|
76
97
|
const snapshot = scanWorkspaceSentinels(cwd, options);
|
|
77
98
|
const changes = diffWorkspaceSentinelSnapshot(previous, snapshot);
|
|
78
99
|
if (!options.includeSourceFiles) return { snapshot, changes, sourceChanges: [] };
|
|
@@ -91,47 +112,6 @@ export function syncWorkspaceSentinelSnapshot(
|
|
|
91
112
|
};
|
|
92
113
|
}
|
|
93
114
|
|
|
94
|
-
/** Determine whether a file path should trigger workspace recovery. */
|
|
95
|
-
export function isWorkspaceRecoveryTrigger(filePath: string, cwd: string): boolean {
|
|
96
|
-
const root = path.resolve(cwd);
|
|
97
|
-
return isWorkspaceSentinelPath(path.resolve(root, filePath), root);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function walkWorkspace(
|
|
101
|
-
root: string,
|
|
102
|
-
directory: string,
|
|
103
|
-
snapshot: Map<string, number>,
|
|
104
|
-
includeSourceFiles: boolean,
|
|
105
|
-
): void {
|
|
106
|
-
let entries: fs.Dirent[];
|
|
107
|
-
try {
|
|
108
|
-
entries = fs.readdirSync(directory, { withFileTypes: true });
|
|
109
|
-
} catch {
|
|
110
|
-
// Permission error or deleted directory — skip it rather than
|
|
111
|
-
// failing the entire scan. A partial snapshot still detects
|
|
112
|
-
// changes in accessible subtrees.
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
for (const entry of entries) {
|
|
117
|
-
if (entry.isDirectory()) {
|
|
118
|
-
if (IGNORED_DIRECTORIES.has(entry.name)) continue;
|
|
119
|
-
walkWorkspace(root, path.join(directory, entry.name), snapshot, includeSourceFiles);
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (!entry.isFile()) continue;
|
|
124
|
-
|
|
125
|
-
const filePath = path.join(directory, entry.name);
|
|
126
|
-
if (!includeSourceFiles && !isWorkspaceSentinelPath(filePath, root)) continue;
|
|
127
|
-
try {
|
|
128
|
-
snapshot.set(filePath, fs.statSync(filePath).mtimeMs);
|
|
129
|
-
} catch {
|
|
130
|
-
// File deleted between readdir and stat — skip.
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
115
|
function isWorkspaceSentinelPath(filePath: string, root: string): boolean {
|
|
136
116
|
const name = path.basename(filePath);
|
|
137
117
|
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
type CodeRequestControl,
|
|
4
4
|
isCodeRequestInterruption,
|
|
5
5
|
} from "@mrclrchtr/supi-code-runtime/api";
|
|
6
|
+
import { uriToFile } from "@mrclrchtr/supi-core/path";
|
|
6
7
|
import type { LspClient } from "../client/client.ts";
|
|
7
8
|
import { getDiagnosticFileState } from "../client/client-file-state.ts";
|
|
8
9
|
import {
|
|
@@ -10,7 +11,6 @@ import {
|
|
|
10
11
|
type DiagnosticEvidenceSummary,
|
|
11
12
|
summarizeDiagnosticEvidence,
|
|
12
13
|
} from "../diagnostics/evidence.ts";
|
|
13
|
-
import { uriToFile } from "../utils.ts";
|
|
14
14
|
|
|
15
15
|
export function closeFileAcrossClients(clients: Iterable<LspClient>, filePath: string): void {
|
|
16
16
|
const resolvedPath = path.resolve(filePath);
|
|
@@ -7,9 +7,8 @@ import {
|
|
|
7
7
|
import type { LspClient } from "../client/client.ts";
|
|
8
8
|
import type { DiagnosticEntry } from "../client/client-document-state.ts";
|
|
9
9
|
import type { Diagnostic } from "../config/types.ts";
|
|
10
|
+
import { effectiveDiagnosticSeverity } from "../diagnostics/diagnostic-severity.ts";
|
|
10
11
|
import { relativeFilePathFromUri } from "../diagnostics/diagnostic-summary.ts";
|
|
11
|
-
import { shouldIgnoreLspPath } from "../summary.ts";
|
|
12
|
-
import { isExcludedByPattern } from "./manager-helpers.ts";
|
|
13
12
|
|
|
14
13
|
/** Sync one file and return diagnostics up to the supplied severity threshold. */
|
|
15
14
|
export async function syncClientFileAndGetDiagnostics(
|
|
@@ -30,7 +29,7 @@ export async function syncClientFileAndGetDiagnostics(
|
|
|
30
29
|
export function collectOutstandingDiagnosticsDetailed(
|
|
31
30
|
clientEntries: Iterable<ReadonlyArray<DiagnosticEntry>>,
|
|
32
31
|
cwd: string,
|
|
33
|
-
|
|
32
|
+
includeFile: (file: string) => boolean,
|
|
34
33
|
maxSeverity: number,
|
|
35
34
|
): Array<{ file: string; diagnostics: Diagnostic[] }> {
|
|
36
35
|
const fileDiags = new Map<string, Diagnostic[]>();
|
|
@@ -38,8 +37,7 @@ export function collectOutstandingDiagnosticsDetailed(
|
|
|
38
37
|
for (const entries of clientEntries) {
|
|
39
38
|
for (const entry of entries) {
|
|
40
39
|
const file = relativeFilePathFromUri(entry.uri, cwd);
|
|
41
|
-
if (
|
|
42
|
-
if (isExcludedByPattern(file, excludePatterns)) continue;
|
|
40
|
+
if (!includeFile(file)) continue;
|
|
43
41
|
const filtered = filterDiagnosticsBySeverity(entry.diagnostics, maxSeverity);
|
|
44
42
|
if (filtered.length === 0) continue;
|
|
45
43
|
const existing = fileDiags.get(file) ?? [];
|
|
@@ -53,7 +51,5 @@ export function collectOutstandingDiagnosticsDetailed(
|
|
|
53
51
|
}
|
|
54
52
|
|
|
55
53
|
function filterDiagnosticsBySeverity(diagnostics: Diagnostic[], maxSeverity: number): Diagnostic[] {
|
|
56
|
-
return diagnostics.filter(
|
|
57
|
-
(diagnostic) => diagnostic.severity !== undefined && diagnostic.severity <= maxSeverity,
|
|
58
|
-
);
|
|
54
|
+
return diagnostics.filter((diagnostic) => effectiveDiagnosticSeverity(diagnostic) <= maxSeverity);
|
|
59
55
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
|
+
import { resolveToolPath as resolveSessionPath } from "@mrclrchtr/supi-core/path";
|
|
2
3
|
import * as projectRoots from "@mrclrchtr/supi-core/project";
|
|
3
|
-
import { isGlobMatch } from "../pattern-matcher.ts";
|
|
4
|
-
import { resolveSessionPath } from "../utils.ts";
|
|
5
4
|
|
|
6
5
|
/** Unique key for a client identified by server name and root. */
|
|
7
6
|
export function clientKey(serverName: string, root: string): string {
|
|
@@ -32,10 +31,3 @@ export function rememberKnownRoot(
|
|
|
32
31
|
const roots = knownRoots.get(serverName) ?? [];
|
|
33
32
|
knownRoots.set(serverName, projectRoots.mergeKnownRoots(roots, root));
|
|
34
33
|
}
|
|
35
|
-
|
|
36
|
-
/** Check if a file path matches any user-configured exclude pattern. */
|
|
37
|
-
export function isExcludedByPattern(file: string, excludePatterns: string[]): boolean {
|
|
38
|
-
return (
|
|
39
|
-
excludePatterns.length > 0 && excludePatterns.some((pattern) => isGlobMatch(file, pattern))
|
|
40
|
-
);
|
|
41
|
-
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { LspClient } from "../client/client.ts";
|
|
2
|
-
import { getSupportedLspServerActions } from "../config/server-actions.ts";
|
|
3
2
|
import type { ProjectServerInfo, ProjectServerStatusReason } from "../config/server-config.ts";
|
|
4
3
|
import { displayRelativeFilePath } from "../summary.ts";
|
|
5
4
|
|
|
@@ -10,6 +9,8 @@ interface ProjectServerInfoInput {
|
|
|
10
9
|
client: LspClient | undefined;
|
|
11
10
|
unavailableReason?: "missing-command" | "start-failed" | "runtime-error";
|
|
12
11
|
statusReason?: ProjectServerStatusReason;
|
|
12
|
+
/** Filter files from ambient project status without changing explicit routing. */
|
|
13
|
+
includeOpenFile?: (file: string) => boolean;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export function buildProjectServerInfo(
|
|
@@ -32,8 +33,10 @@ export function buildProjectServerInfo(
|
|
|
32
33
|
fileTypes: input.fileTypes,
|
|
33
34
|
status,
|
|
34
35
|
...(input.statusReason ? { statusReason: input.statusReason } : {}),
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
openFiles:
|
|
37
|
+
input.client?.openFiles
|
|
38
|
+
.filter((file) => input.includeOpenFile?.(file) ?? true)
|
|
39
|
+
.map((file) => displayRelativeFilePath(file, cwd)) ?? [],
|
|
37
40
|
ready: input.client?.ready ?? false,
|
|
38
41
|
};
|
|
39
42
|
}
|
|
@@ -16,12 +16,19 @@ import {
|
|
|
16
16
|
assessStaleDiagnostics,
|
|
17
17
|
type StaleDiagnosticAssessment,
|
|
18
18
|
} from "../diagnostics/stale-diagnostics.ts";
|
|
19
|
-
import
|
|
19
|
+
import {
|
|
20
|
+
emptyProcessCrashRecoverySummary,
|
|
21
|
+
type ProcessCrashRecoverySummary,
|
|
22
|
+
type WorkspaceDiagnosticReport,
|
|
23
|
+
} from "../session/runtime-diagnostics.ts";
|
|
20
24
|
|
|
21
25
|
export interface WorkspaceRecoveryResult {
|
|
22
26
|
/** Active clients targeted by the best-effort refresh, not confirmed successful refreshes. */
|
|
23
27
|
attemptedClients: number;
|
|
28
|
+
/** Clients restarted by stale-diagnostic recovery, not process-crash recovery. */
|
|
24
29
|
restartedClients: number;
|
|
30
|
+
/** No process-crash demand is handled by this generic recovery pass. */
|
|
31
|
+
processCrashRecovery: ProcessCrashRecoverySummary;
|
|
25
32
|
/** Server names of the active clients targeted by this pass, for telemetry identity. */
|
|
26
33
|
attemptedServers: string[];
|
|
27
34
|
/** Server names of the clients restarted during this pass, for telemetry identity. */
|
|
@@ -157,6 +164,7 @@ export async function recoverWorkspaceDiagnostics(
|
|
|
157
164
|
return {
|
|
158
165
|
attemptedClients,
|
|
159
166
|
restartedClients,
|
|
167
|
+
processCrashRecovery: emptyProcessCrashRecoverySummary(),
|
|
160
168
|
attemptedServers,
|
|
161
169
|
restartedServers: restartServerNames,
|
|
162
170
|
...(restartReason ? { restartReason } : {}),
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
1
|
import * as path from "node:path";
|
|
3
2
|
import {
|
|
4
3
|
type CodeQueryResult,
|
|
@@ -7,7 +6,6 @@ import {
|
|
|
7
6
|
partialCodeQuery,
|
|
8
7
|
unavailableCodeQuery,
|
|
9
8
|
} from "@mrclrchtr/supi-code-runtime/api";
|
|
10
|
-
import { walkProject } from "@mrclrchtr/supi-core/project";
|
|
11
9
|
import type { LspClient } from "../client/client.ts";
|
|
12
10
|
import type {
|
|
13
11
|
DocumentSymbol,
|
|
@@ -15,10 +13,14 @@ import type {
|
|
|
15
13
|
SymbolInformation,
|
|
16
14
|
WorkspaceSymbol,
|
|
17
15
|
} from "../config/types.ts";
|
|
16
|
+
import {
|
|
17
|
+
type AutomaticLspPathPolicy,
|
|
18
|
+
createDefaultAutomaticLspPathPolicy,
|
|
19
|
+
walkAutomaticLspTree,
|
|
20
|
+
} from "../workspace-path-policy.ts";
|
|
18
21
|
|
|
19
22
|
type WorkspaceSymbolLike = SymbolInformation | WorkspaceSymbol;
|
|
20
23
|
|
|
21
|
-
const SKIP_DIRS = new Set(["node_modules", ".git", ".pnpm", "dist", "build", "coverage"]);
|
|
22
24
|
const DEFAULT_WARM_FILE_DEPTH = 4;
|
|
23
25
|
const DEFAULT_MARKER_SCAN_DEPTH = 6;
|
|
24
26
|
|
|
@@ -30,6 +32,8 @@ export interface WorkspaceSymbolWarmTarget {
|
|
|
30
32
|
export interface WorkspaceSymbolWarmOptions {
|
|
31
33
|
maxFileDepth?: number;
|
|
32
34
|
maxMarkerDepth?: number;
|
|
35
|
+
/** Runtime-owned automatic path policy. */
|
|
36
|
+
policy?: AutomaticLspPathPolicy;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
export function getWorkspaceSymbolWarmPosition(
|
|
@@ -98,14 +102,6 @@ export function workspaceSymbolCollectionResult(
|
|
|
98
102
|
return completedCodeQuery(collection.results);
|
|
99
103
|
}
|
|
100
104
|
|
|
101
|
-
export async function managerWorkspaceSymbol(
|
|
102
|
-
clients: Iterable<LspClient>,
|
|
103
|
-
query: string,
|
|
104
|
-
control?: CodeRequestControl,
|
|
105
|
-
): Promise<CodeQueryResult<WorkspaceSymbolLike[]>> {
|
|
106
|
-
return workspaceSymbolCollectionResult(await collectWorkspaceSymbols(clients, query, control));
|
|
107
|
-
}
|
|
108
|
-
|
|
109
105
|
export function findWorkspaceSymbolWarmTargets(
|
|
110
106
|
root: string,
|
|
111
107
|
rootMarkers: string[],
|
|
@@ -116,12 +112,13 @@ export function findWorkspaceSymbolWarmTargets(
|
|
|
116
112
|
const allowed = new Set(fileTypes.map((fileType) => fileType.toLowerCase()));
|
|
117
113
|
const maxFileDepth = options.maxFileDepth ?? DEFAULT_WARM_FILE_DEPTH;
|
|
118
114
|
const maxMarkerDepth = options.maxMarkerDepth ?? DEFAULT_MARKER_SCAN_DEPTH;
|
|
115
|
+
const policy = options.policy ?? createDefaultAutomaticLspPathPolicy(resolvedRoot);
|
|
119
116
|
if (allowed.size === 0) return [];
|
|
120
117
|
|
|
121
|
-
const markerRoots = collectMarkerRoots(resolvedRoot, rootMarkers, maxMarkerDepth);
|
|
118
|
+
const markerRoots = collectMarkerRoots(resolvedRoot, rootMarkers, maxMarkerDepth, policy);
|
|
122
119
|
const targets = markerRoots
|
|
123
120
|
.map((entry) => {
|
|
124
|
-
const file = findWarmFileRecursive(entry.root, allowed, maxFileDepth);
|
|
121
|
+
const file = findWarmFileRecursive(entry.root, allowed, maxFileDepth, policy);
|
|
125
122
|
return file ? { projectRoot: entry.root, file, priority: entry.priority } : null;
|
|
126
123
|
})
|
|
127
124
|
.filter((entry): entry is { projectRoot: string; file: string; priority: number } =>
|
|
@@ -137,7 +134,7 @@ export function findWorkspaceSymbolWarmTargets(
|
|
|
137
134
|
|
|
138
135
|
if (targets.length > 0) return targets;
|
|
139
136
|
|
|
140
|
-
const fallback = findWarmFileRecursive(resolvedRoot, allowed, maxFileDepth);
|
|
137
|
+
const fallback = findWarmFileRecursive(resolvedRoot, allowed, maxFileDepth, policy);
|
|
141
138
|
return fallback ? [{ projectRoot: resolvedRoot, file: fallback }] : [];
|
|
142
139
|
}
|
|
143
140
|
|
|
@@ -150,13 +147,15 @@ function collectMarkerRoots(
|
|
|
150
147
|
root: string,
|
|
151
148
|
rootMarkers: string[],
|
|
152
149
|
maxDepth: number,
|
|
150
|
+
policy: AutomaticLspPathPolicy,
|
|
153
151
|
): MarkerRootEntry[] {
|
|
154
152
|
if (rootMarkers.length === 0) return [];
|
|
155
153
|
|
|
156
154
|
const markerIndex = new Map(rootMarkers.map((marker, index) => [marker, index]));
|
|
157
155
|
const matches = new Map<string, number>();
|
|
158
156
|
|
|
159
|
-
|
|
157
|
+
walkAutomaticLspTree(policy, root, maxDepth, (directory, entries) => {
|
|
158
|
+
const entryNames = new Set(entries.map((entry) => entry.name));
|
|
160
159
|
const matchedPriority = rootMarkers.reduce<number | null>((best, marker) => {
|
|
161
160
|
if (!entryNames.has(marker)) return best;
|
|
162
161
|
const next = markerIndex.get(marker) ?? Number.MAX_SAFE_INTEGER;
|
|
@@ -181,31 +180,17 @@ function findWarmFileRecursive(
|
|
|
181
180
|
directory: string,
|
|
182
181
|
allowed: Set<string>,
|
|
183
182
|
depth: number,
|
|
183
|
+
policy: AutomaticLspPathPolicy,
|
|
184
184
|
): string | null {
|
|
185
|
-
let
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const ext = path.extname(entry.name).slice(1).toLowerCase();
|
|
197
|
-
if (!allowed.has(ext)) continue;
|
|
198
|
-
return path.join(directory, entry.name);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (depth <= 0) return null;
|
|
202
|
-
|
|
203
|
-
for (const entry of sortedEntries) {
|
|
204
|
-
if (!entry.isDirectory()) continue;
|
|
205
|
-
if (SKIP_DIRS.has(entry.name)) continue;
|
|
206
|
-
const nested = findWarmFileRecursive(path.join(directory, entry.name), allowed, depth - 1);
|
|
207
|
-
if (nested) return nested;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return null;
|
|
185
|
+
let warmFile: string | null = null;
|
|
186
|
+
walkAutomaticLspTree(policy, directory, depth, (currentDirectory, entries) => {
|
|
187
|
+
for (const entry of entries) {
|
|
188
|
+
if (!entry.isFile() && !entry.isSymbolicLink()) continue;
|
|
189
|
+
if (!allowed.has(path.extname(entry.name).slice(1).toLowerCase())) continue;
|
|
190
|
+
warmFile = path.join(currentDirectory, entry.name);
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
return false;
|
|
194
|
+
});
|
|
195
|
+
return warmFile;
|
|
211
196
|
}
|