@mrclrchtr/supi-code-intelligence 6.0.1 → 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 +2 -2
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +5 -0
- 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 +26 -4
- 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-code-runtime/src/capability/types.ts +5 -0
- 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/node_modules/vscode-jsonrpc/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-protocol/lib/common/protocol.colorProvider.d.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-protocol/lib/common/protocol.d.ts +2 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-protocol/lib/common/protocol.fileOperations.d.ts +9 -9
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-protocol/package.json +3 -3
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-types/lib/esm/main.d.ts +2 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-types/lib/esm/main.js +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-types/lib/umd/main.d.ts +2 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-types/lib/umd/main.js +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-types/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/package.json +4 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +14 -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 +23 -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 +8 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/config/tsconfig-scope.ts +4 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/config/types.ts +1 -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 +12 -6
- 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 +849 -117
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +6 -4
- 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-diagnostic-surface.ts +10 -0
- 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 +118 -27
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-transition-debug.ts +7 -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 +33 -5
- 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-code-runtime/src/capability/types.ts +5 -0
- 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/resources/grammars/kotlin/tree-sitter-kotlin.wasm.json +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/sql/tree-sitter-sql.wasm.json +1 -1
- 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/health/recovery.ts +4 -0
- package/src/analysis/health/server-status.ts +64 -0
- package/src/analysis/health/signals.ts +1 -0
- package/src/analysis/provider.ts +2 -1
- package/src/analysis/search/ast-scan-timing.ts +4 -2
- package/src/analysis/search/ast-scan.ts +1 -1
- package/src/analysis/target/symbol.ts +28 -16
- package/src/analysis/target/types.ts +1 -0
- package/src/api.ts +1 -0
- package/src/extension.ts +4 -2
- package/src/session/find-workflow.ts +5 -12
- package/src/session/health-refresh.ts +30 -4
- package/src/session/health-types.ts +27 -2
- package/src/session/health-workflow.ts +5 -1
- 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/session/semantic-demand.ts +36 -0
- package/src/session/target-workflow.ts +9 -12
- 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/guidance.ts +2 -2
- package/src/tool/code_health/markdown.ts +81 -69
- 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 +15 -5
- package/src/tool/code_health/spec.ts +2 -1
- package/src/tool/code_health/tui.ts +42 -8
- 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/result/errors.ts +1 -0
- package/src/tool/result/types.ts +6 -0
- package/src/tool/schemas.ts +21 -11
- package/src/ui/footer.ts +7 -5
- package/src/ui/status-command.ts +31 -0
- package/src/ui/status-overlay.ts +69 -23
- 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
|
@@ -150,7 +150,7 @@ export async function enumerateAstFiles(
|
|
|
150
150
|
class AstFileEnumerator {
|
|
151
151
|
readonly #operations: AstScanOperations;
|
|
152
152
|
readonly #now: () => number;
|
|
153
|
-
readonly #grammarExtensions = new Set(getSupportedExtensions());
|
|
153
|
+
readonly #grammarExtensions: ReadonlySet<string> = new Set(getSupportedExtensions());
|
|
154
154
|
readonly #operationExtensions: ReadonlySet<string>;
|
|
155
155
|
readonly #files = new Set<string>();
|
|
156
156
|
readonly #visitedDirectories = new Set<string>();
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import * as path from "node:path";
|
|
10
10
|
import {
|
|
11
|
+
type CodeQueryResult,
|
|
11
12
|
type CodeRequestControl,
|
|
12
13
|
type CodeSymbol,
|
|
13
14
|
isCodeRequestInterruption,
|
|
@@ -114,33 +115,27 @@ export async function resolveSymbolTarget(
|
|
|
114
115
|
control?: CodeRequestControl;
|
|
115
116
|
},
|
|
116
117
|
): Promise<TargetOutcome> {
|
|
117
|
-
const
|
|
118
|
+
const scopePath = options?.path ? normalizePath(options.path, cwd) : null;
|
|
119
|
+
const result = await semantic.workspaceSymbols(
|
|
120
|
+
symbol,
|
|
121
|
+
options?.control,
|
|
122
|
+
scopePath ? [scopePath] : undefined,
|
|
123
|
+
);
|
|
118
124
|
if (result.kind === "unavailable") {
|
|
119
125
|
return {
|
|
120
|
-
kind: "
|
|
121
|
-
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
if (result.data.length === 0) {
|
|
125
|
-
return {
|
|
126
|
-
kind: "error",
|
|
127
|
-
message: `Symbol not found: \`${symbol}\`. Try \`code_resolve\` to search for it, or use an anchor target (file/line/character) if you know the location.`,
|
|
126
|
+
kind: "unavailable",
|
|
127
|
+
reason: `Symbol discovery for \`${symbol}\` is unavailable: ${result.reason}`,
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
|
+
if (result.data.length === 0) return emptySymbolOutcome(symbol, result, options?.path);
|
|
130
131
|
|
|
131
|
-
const scopePath = options?.path ? normalizePath(options.path, cwd) : null;
|
|
132
132
|
const scoped = result.data.filter((candidate) =>
|
|
133
133
|
scopePath ? isWithinOrEqual(scopePath, candidate.file) : true,
|
|
134
134
|
);
|
|
135
135
|
const eligible = options?.exportedOnly
|
|
136
136
|
? scoped.filter((candidate) => !NON_EXPORTED_KINDS.has(candidate.kind))
|
|
137
137
|
: scoped;
|
|
138
|
-
if (eligible.length === 0)
|
|
139
|
-
return {
|
|
140
|
-
kind: "error",
|
|
141
|
-
message: `Symbol not found: \`${symbol}\`${scopePath ? ` in path \`${options?.path}\`` : ""}. Try \`code_resolve\` to search for it, or use an anchor target (file/line/character) if you know the location.`,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
138
|
+
if (eligible.length === 0) return emptySymbolOutcome(symbol, result, options?.path);
|
|
144
139
|
|
|
145
140
|
const requestedKind = options?.kind;
|
|
146
141
|
if (requestedKind) {
|
|
@@ -248,6 +243,23 @@ type CandidateOutcomeOptions = CandidateOutcomeBase &
|
|
|
248
243
|
* exact provider result count for omission disclosure. No candidate is
|
|
249
244
|
* promoted when the requested provider kind did not match.
|
|
250
245
|
*/
|
|
246
|
+
function emptySymbolOutcome(
|
|
247
|
+
symbol: string,
|
|
248
|
+
result: Exclude<CodeQueryResult<CodeSymbol[]>, { kind: "unavailable" }>,
|
|
249
|
+
scope?: string,
|
|
250
|
+
): TargetOutcome {
|
|
251
|
+
if (result.kind === "partial") {
|
|
252
|
+
return {
|
|
253
|
+
kind: "unavailable",
|
|
254
|
+
reason: `Symbol discovery for \`${symbol}\` is incomplete: ${result.reason}`,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
kind: "error",
|
|
259
|
+
message: `Symbol not found: \`${symbol}\`${scope ? ` in path \`${scope}\`` : ""}. Try \`code_resolve\` to search for it, or use an anchor target (file/line/character) if you know the location.`,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
251
263
|
async function buildCandidateOutcome(
|
|
252
264
|
options: CandidateOutcomeOptions,
|
|
253
265
|
): Promise<Extract<TargetOutcome, { kind: "disambiguation" | "kind-mismatch" }>> {
|
package/src/api.ts
CHANGED
package/src/extension.ts
CHANGED
|
@@ -6,8 +6,10 @@ import type {
|
|
|
6
6
|
ExtensionAPI,
|
|
7
7
|
ExtensionContext,
|
|
8
8
|
} from "@earendil-works/pi-coding-agent";
|
|
9
|
-
import {
|
|
10
|
-
|
|
9
|
+
import {
|
|
10
|
+
recordDebugEvent,
|
|
11
|
+
truncateDebugIdentity as truncateIdentity,
|
|
12
|
+
} from "@mrclrchtr/supi-core/debug";
|
|
11
13
|
import { buildArchitectureModel } from "./analysis/architecture/discovery.ts";
|
|
12
14
|
import { createCodeIntelligenceApp } from "./app/app.ts";
|
|
13
15
|
import { registerCodeIntelligenceSettings, resolveOverviewEnabled } from "./config.ts";
|
|
@@ -9,6 +9,7 @@ import { isCodeFindAstKind } from "../tool/code_find/ast-kinds.ts";
|
|
|
9
9
|
import type { CapabilityAdapter } from "./capability-adapter.ts";
|
|
10
10
|
import type { FindWorkflowInput, FindWorkflowOutcome } from "./find-types.ts";
|
|
11
11
|
import { parseFindWorkflowInput } from "./input/workflows.ts";
|
|
12
|
+
import { resolveWorkspaceSemanticDemand } from "./semantic-demand.ts";
|
|
12
13
|
import { reportProgress, throwIfAborted, type WorkflowControl } from "./workflow-control.ts";
|
|
13
14
|
|
|
14
15
|
export interface FindWorkflowDeps {
|
|
@@ -71,22 +72,14 @@ async function runSemanticSearch(options: {
|
|
|
71
72
|
control?: WorkflowControl;
|
|
72
73
|
}): Promise<FindWorkflowOutcome> {
|
|
73
74
|
const { query, scopePaths, scopeLabel, maxResults, deps, control } = options;
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
{ kind: "workspace" },
|
|
77
|
-
control,
|
|
78
|
-
);
|
|
79
|
-
if (readiness.kind === "timeout") {
|
|
75
|
+
const semanticDemand = await resolveWorkspaceSemanticDemand(deps.capability, deps.cwd, control);
|
|
76
|
+
if (semanticDemand.kind === "timeout") {
|
|
80
77
|
return { kind: "unavailable", reason: SEMANTIC_READINESS_TIMEOUT_REASON };
|
|
81
78
|
}
|
|
82
|
-
if (
|
|
79
|
+
if (semanticDemand.kind === "unavailable") return semanticDemand;
|
|
83
80
|
throwIfAborted(control);
|
|
84
81
|
|
|
85
|
-
const
|
|
86
|
-
if (!provider?.workspaceSymbols) {
|
|
87
|
-
return { kind: "unavailable", reason: "No semantic workspace-symbol provider is active." };
|
|
88
|
-
}
|
|
89
|
-
const result = await provider.workspaceSymbols(query, control);
|
|
82
|
+
const result = await semanticDemand.provider.workspaceSymbols(query, control, scopePaths);
|
|
90
83
|
// A cancellation that landed during the request must not publish symbols
|
|
91
84
|
// the caller no longer awaits.
|
|
92
85
|
throwIfAborted(control);
|
|
@@ -2,11 +2,19 @@ import {
|
|
|
2
2
|
type CodeRequestControl,
|
|
3
3
|
isCodeRequestInterruption,
|
|
4
4
|
} from "@mrclrchtr/supi-code-runtime/api";
|
|
5
|
-
import
|
|
5
|
+
import {
|
|
6
|
+
emptyProcessCrashRecoverySummary,
|
|
7
|
+
type WorkspaceDiagnosticReport,
|
|
8
|
+
type WorkspaceLspRuntime,
|
|
9
|
+
} from "@mrclrchtr/supi-lsp/api";
|
|
6
10
|
import { recoverDiagnosticRuntime } from "../analysis/health/recovery.ts";
|
|
7
11
|
import { mergeDiagnosticEvidence } from "../diagnostics/evidence.ts";
|
|
8
12
|
import { refreshFileLspMaintenance, refreshLspMaintenance } from "../substrate/lsp/maintenance.ts";
|
|
9
|
-
import type {
|
|
13
|
+
import type {
|
|
14
|
+
HealthDiagnosticScope,
|
|
15
|
+
HealthFileReadiness,
|
|
16
|
+
HealthRefreshAttempt,
|
|
17
|
+
} from "./health-types.ts";
|
|
10
18
|
|
|
11
19
|
interface HealthRefreshAttemptOptions {
|
|
12
20
|
readonly runtime: WorkspaceLspRuntime;
|
|
@@ -51,6 +59,8 @@ async function collectFileRefreshAttempt(
|
|
|
51
59
|
undefined,
|
|
52
60
|
options.control,
|
|
53
61
|
);
|
|
62
|
+
const fileReadiness: HealthFileReadiness =
|
|
63
|
+
readiness.kind === "ready" ? "ready" : readiness.kind === "timeout" ? "pending" : "unavailable";
|
|
54
64
|
return {
|
|
55
65
|
attempt: {
|
|
56
66
|
kind: "completed",
|
|
@@ -59,7 +69,9 @@ async function collectFileRefreshAttempt(
|
|
|
59
69
|
requestedDiagnosticScope: scope,
|
|
60
70
|
operationScope: "file-runtime",
|
|
61
71
|
attemptedActiveClients: readiness.kind === "ready" ? 1 : 0,
|
|
72
|
+
fileReadiness,
|
|
62
73
|
restartedClients: 0,
|
|
74
|
+
processCrashRecovery: readiness.processCrashRecovery ?? emptyProcessCrashRecoverySummary(),
|
|
63
75
|
staleAssessment: {
|
|
64
76
|
scope: "file",
|
|
65
77
|
suspected: null,
|
|
@@ -105,9 +117,13 @@ async function collectWorkspaceRefreshAttempt(
|
|
|
105
117
|
service: options.runtime,
|
|
106
118
|
control: options.control,
|
|
107
119
|
progress: options.reportRecoveryProgress,
|
|
108
|
-
// The maintenance pass already refreshed every
|
|
109
|
-
// evidence
|
|
120
|
+
// The maintenance pass already refreshed every running route. Reuse its
|
|
121
|
+
// evidence unless process-crash demand restores a required route; the
|
|
122
|
+
// runtime then performs a fresh pass that includes the replacement.
|
|
110
123
|
initialEvidence: maintenance.diagnosticEvidence,
|
|
124
|
+
processCrashDemand: {
|
|
125
|
+
...(workspaceScope?.filter ? { scopes: [workspaceScope.filter] } : {}),
|
|
126
|
+
},
|
|
111
127
|
});
|
|
112
128
|
const diagnosticEvidence = mergeDiagnosticEvidence(
|
|
113
129
|
maintenance.diagnosticEvidence,
|
|
@@ -122,7 +138,16 @@ async function collectWorkspaceRefreshAttempt(
|
|
|
122
138
|
elapsedMs: Date.now() - options.attemptedAt,
|
|
123
139
|
requestedDiagnosticScope: options.diagnosticsScope,
|
|
124
140
|
operationScope: "workspace-runtime",
|
|
141
|
+
attemptedActiveClients: recovery.attemptedClients,
|
|
142
|
+
restartedClients: recovery.restartedClients,
|
|
143
|
+
staleAssessment: {
|
|
144
|
+
scope: "workspace",
|
|
145
|
+
suspected: recovery.staleAssessment.suspected,
|
|
146
|
+
matchedFileCount: recovery.staleAssessment.matchedFiles.length,
|
|
147
|
+
warning: recovery.staleAssessment.warning,
|
|
148
|
+
},
|
|
125
149
|
diagnosticEvidence,
|
|
150
|
+
processCrashRecovery: recovery.processCrashRecovery,
|
|
126
151
|
reason: recovery.refreshFailureReason,
|
|
127
152
|
},
|
|
128
153
|
diagnosticReport: recovery.diagnosticReport,
|
|
@@ -137,6 +162,7 @@ async function collectWorkspaceRefreshAttempt(
|
|
|
137
162
|
operationScope: "workspace-runtime",
|
|
138
163
|
attemptedActiveClients: recovery.attemptedClients,
|
|
139
164
|
restartedClients: recovery.restartedClients,
|
|
165
|
+
processCrashRecovery: recovery.processCrashRecovery,
|
|
140
166
|
diagnosticEvidence,
|
|
141
167
|
staleAssessment: {
|
|
142
168
|
scope: "workspace",
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
DiagnosticEvidenceSummary,
|
|
3
|
+
FileScopeDecision,
|
|
4
|
+
ProcessCrashRecoverySummary,
|
|
5
|
+
ProjectServerInfo,
|
|
6
|
+
ProjectServerStatusReason,
|
|
7
|
+
} from "@mrclrchtr/supi-lsp/api";
|
|
2
8
|
import type { CapabilityWarningReport } from "../analysis/capability/capability-warnings.ts";
|
|
3
9
|
|
|
4
10
|
export type HealthSection = "diagnostics" | "servers";
|
|
@@ -22,7 +28,8 @@ export interface HealthServerInfo {
|
|
|
22
28
|
readonly name: string;
|
|
23
29
|
readonly root: string;
|
|
24
30
|
readonly fileTypes: readonly string[];
|
|
25
|
-
readonly status:
|
|
31
|
+
readonly status: ProjectServerInfo["status"];
|
|
32
|
+
readonly statusReason?: ProjectServerStatusReason;
|
|
26
33
|
readonly ready: boolean;
|
|
27
34
|
}
|
|
28
35
|
|
|
@@ -87,6 +94,9 @@ export interface HealthStaleAssessment {
|
|
|
87
94
|
|
|
88
95
|
export type HealthRefreshOperationScope = "file-runtime" | "workspace-runtime";
|
|
89
96
|
|
|
97
|
+
/** Readiness result for a file-scoped maintenance attempt. */
|
|
98
|
+
export type HealthFileReadiness = "ready" | "pending" | "unavailable";
|
|
99
|
+
|
|
90
100
|
/** Shared facts for one completed refresh or file-maintenance attempt. */
|
|
91
101
|
interface CompletedHealthRefreshAttempt {
|
|
92
102
|
readonly kind: "completed";
|
|
@@ -97,7 +107,12 @@ interface CompletedHealthRefreshAttempt {
|
|
|
97
107
|
readonly requestedDiagnosticScope: HealthDiagnosticScope;
|
|
98
108
|
/** Active clients targeted by the best-effort operation; this is not a confirmed-success count. */
|
|
99
109
|
readonly attemptedActiveClients: number;
|
|
110
|
+
/** File readiness after the bounded wait, when this is file-scoped. */
|
|
111
|
+
readonly fileReadiness?: HealthFileReadiness;
|
|
112
|
+
/** Clients restarted by stale-diagnostic recovery. */
|
|
100
113
|
readonly restartedClients: number;
|
|
114
|
+
/** Separate outcome for process-crash route recovery. */
|
|
115
|
+
readonly processCrashRecovery: ProcessCrashRecoverySummary;
|
|
101
116
|
readonly staleAssessment: HealthStaleAssessment;
|
|
102
117
|
}
|
|
103
118
|
|
|
@@ -119,8 +134,18 @@ export type HealthRefreshAttempt =
|
|
|
119
134
|
readonly elapsedMs: number;
|
|
120
135
|
readonly requestedDiagnosticScope: HealthDiagnosticScope;
|
|
121
136
|
readonly operationScope: HealthRefreshOperationScope;
|
|
137
|
+
/** Active clients targeted before the operation failed, when available. */
|
|
138
|
+
readonly attemptedActiveClients?: number;
|
|
139
|
+
/** Clients restarted by stale-diagnostic recovery, when available. */
|
|
140
|
+
readonly restartedClients?: number;
|
|
141
|
+
/** Stale-diagnostic assessment, when the recovery pass returned one. */
|
|
142
|
+
readonly staleAssessment?: HealthStaleAssessment;
|
|
122
143
|
/** Evidence collected before the operation failed, when available. */
|
|
123
144
|
readonly diagnosticEvidence?: DiagnosticEvidenceSummary;
|
|
145
|
+
/** Process-crash outcome, when the recovery pass returned one. */
|
|
146
|
+
readonly processCrashRecovery?: ProcessCrashRecoverySummary;
|
|
147
|
+
/** File readiness outcome, when a file-scoped attempt failed. */
|
|
148
|
+
readonly fileReadiness?: HealthFileReadiness;
|
|
124
149
|
readonly reason: string;
|
|
125
150
|
};
|
|
126
151
|
|
|
@@ -59,6 +59,7 @@ export async function runHealthWorkflow(
|
|
|
59
59
|
if (prepared.kind === "invalid-input") return prepared;
|
|
60
60
|
const { request, scopeFilter, included, level } = prepared.value;
|
|
61
61
|
const semanticRequested = healthNeedsSemantic(included);
|
|
62
|
+
const fileReadinessRequested = included.includes("diagnostics");
|
|
62
63
|
throwIfAborted(control);
|
|
63
64
|
|
|
64
65
|
reportProgress(control, {
|
|
@@ -85,6 +86,7 @@ export async function runHealthWorkflow(
|
|
|
85
86
|
});
|
|
86
87
|
const semanticState = await establishSemanticHealthState({
|
|
87
88
|
requested: semanticRequested,
|
|
89
|
+
fileReadinessRequested,
|
|
88
90
|
runtime,
|
|
89
91
|
scopeFilter,
|
|
90
92
|
lspState,
|
|
@@ -139,6 +141,8 @@ function healthNeedsSemantic(included: readonly HealthSection[]): boolean {
|
|
|
139
141
|
|
|
140
142
|
interface SemanticHealthStateOptions {
|
|
141
143
|
requested: boolean;
|
|
144
|
+
/** Whether this call requests file-routed evidence rather than passive inventory. */
|
|
145
|
+
fileReadinessRequested: boolean;
|
|
142
146
|
runtime: WorkspaceLspRuntime | null;
|
|
143
147
|
scopeFilter: string | null;
|
|
144
148
|
lspState: WorkspaceLspRuntimeState;
|
|
@@ -150,7 +154,7 @@ async function establishSemanticHealthState(
|
|
|
150
154
|
options: SemanticHealthStateOptions,
|
|
151
155
|
): Promise<SemanticHealthState | null> {
|
|
152
156
|
if (!options.requested) return null;
|
|
153
|
-
if (options.runtime && isScopedFile(options.scopeFilter)) {
|
|
157
|
+
if (options.fileReadinessRequested && options.runtime && isScopedFile(options.scopeFilter)) {
|
|
154
158
|
const readiness = await options.runtime.waitUntilReadyForFile(
|
|
155
159
|
options.scopeFilter,
|
|
156
160
|
undefined,
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/** Runtime parsers for health and refactor session workflows. */
|
|
2
2
|
|
|
3
3
|
import type { HealthSection, HealthWorkflowInput } from "../health-types.ts";
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import {
|
|
5
|
+
PUBLIC_REFACTOR_OPERATION_NAMES,
|
|
6
|
+
type PublicSourceRange,
|
|
7
|
+
type RefactorApplyWorkflowInput,
|
|
8
|
+
type RefactorOperationInput,
|
|
9
|
+
type RefactorPlanWorkflowInput,
|
|
9
10
|
} from "../refactor-types.ts";
|
|
10
11
|
import type { RefactorTargetInput } from "../target-input.ts";
|
|
11
12
|
import {
|
|
@@ -94,22 +95,23 @@ export function parseRefactorPlanWorkflowInput(
|
|
|
94
95
|
function parseRefactorOperation(value: unknown): InputValidation<RefactorOperationInput> {
|
|
95
96
|
const record = requireRecord(value, "operation");
|
|
96
97
|
if (record.kind === "invalid-input") return record;
|
|
97
|
-
const keysError = requireOnlyKeys(
|
|
98
|
-
record.value,
|
|
99
|
-
["rename_symbol", "extract_function", "extract_variable"],
|
|
100
|
-
"operation",
|
|
101
|
-
);
|
|
98
|
+
const keysError = requireOnlyKeys(record.value, PUBLIC_REFACTOR_OPERATION_NAMES, "operation");
|
|
102
99
|
if (keysError) return invalid(keysError);
|
|
103
|
-
const selected = (
|
|
104
|
-
(key) => record.value[key] !== undefined,
|
|
105
|
-
);
|
|
100
|
+
const selected = PUBLIC_REFACTOR_OPERATION_NAMES.filter((key) => record.value[key] !== undefined);
|
|
106
101
|
if (selected.length !== 1) return invalid("Select exactly one refactor operation.");
|
|
107
102
|
|
|
108
103
|
const name = selected[0];
|
|
109
104
|
const payload = requireRecord(record.value[name], `operation.${name}`);
|
|
110
105
|
if (payload.kind === "invalid-input") return payload;
|
|
111
106
|
if (name === "rename_symbol") return parseRenameOperation(payload.value);
|
|
112
|
-
|
|
107
|
+
if (name === "extract_function" || name === "extract_variable") {
|
|
108
|
+
return parseExtractOperation(name, payload.value);
|
|
109
|
+
}
|
|
110
|
+
const payloadError = requireOnlyKeys(payload.value, [], `operation.${name}`);
|
|
111
|
+
if (payloadError) return invalid(payloadError);
|
|
112
|
+
return name === "update_imports"
|
|
113
|
+
? valid({ update_imports: {} })
|
|
114
|
+
: valid({ delete_dead_code: {} });
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
function parseRenameOperation(
|
|
@@ -3,6 +3,17 @@ import type { ApplyResult } from "../analysis/refactor/apply.ts";
|
|
|
3
3
|
import type { RefactorPlan } from "./refactor-plans.ts";
|
|
4
4
|
import type { RefactorTargetInput, SourcePointInput } from "./target-input.ts";
|
|
5
5
|
|
|
6
|
+
/** Public refactor operations exposed by code_refactor_plan. */
|
|
7
|
+
export const PUBLIC_REFACTOR_OPERATION_NAMES = [
|
|
8
|
+
"rename_symbol",
|
|
9
|
+
"extract_function",
|
|
10
|
+
"extract_variable",
|
|
11
|
+
"update_imports",
|
|
12
|
+
"delete_dead_code",
|
|
13
|
+
] as const;
|
|
14
|
+
|
|
15
|
+
export type PublicRefactorOperationName = (typeof PUBLIC_REFACTOR_OPERATION_NAMES)[number];
|
|
16
|
+
|
|
6
17
|
export interface PublicSourceRange {
|
|
7
18
|
readonly start: Omit<SourcePointInput, "file">;
|
|
8
19
|
readonly end: Omit<SourcePointInput, "file">;
|
|
@@ -21,7 +32,9 @@ export type RefactorOperationInput =
|
|
|
21
32
|
readonly newName: string;
|
|
22
33
|
readonly range: PublicSourceRange;
|
|
23
34
|
};
|
|
24
|
-
}
|
|
35
|
+
}
|
|
36
|
+
| { readonly update_imports: Record<string, never> }
|
|
37
|
+
| { readonly delete_dead_code: Record<string, never> };
|
|
25
38
|
|
|
26
39
|
export interface RefactorPlanWorkflowInput {
|
|
27
40
|
readonly target: RefactorTargetInput;
|
|
@@ -26,13 +26,14 @@ import {
|
|
|
26
26
|
isPlanFresh,
|
|
27
27
|
type RefactorPlan,
|
|
28
28
|
} from "./refactor-plans.ts";
|
|
29
|
-
import
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
import {
|
|
30
|
+
PUBLIC_REFACTOR_OPERATION_NAMES,
|
|
31
|
+
type PublicSourceRange,
|
|
32
|
+
type RefactorApplyWorkflowInput,
|
|
33
|
+
type RefactorApplyWorkflowOutcome,
|
|
34
|
+
type RefactorOperationInput,
|
|
35
|
+
type RefactorPlanWorkflowInput,
|
|
36
|
+
type RefactorPlanWorkflowOutcome,
|
|
36
37
|
} from "./refactor-types.ts";
|
|
37
38
|
import { resolveTargetWorkflow, type TargetWorkflowDeps } from "./target-workflow.ts";
|
|
38
39
|
import { reportProgress, throwIfAborted, type WorkflowControl } from "./workflow-control.ts";
|
|
@@ -208,13 +209,11 @@ function parseOperation(input: RefactorOperationInput):
|
|
|
208
209
|
| {
|
|
209
210
|
kind: "ok";
|
|
210
211
|
operation: RefactorOperation;
|
|
211
|
-
newName
|
|
212
|
+
newName?: string;
|
|
212
213
|
range?: PublicSourceRange;
|
|
213
214
|
}
|
|
214
215
|
| { kind: "invalid-input"; message: string } {
|
|
215
|
-
const keys =
|
|
216
|
-
(key) => key in input,
|
|
217
|
-
);
|
|
216
|
+
const keys = PUBLIC_REFACTOR_OPERATION_NAMES.filter((key) => key in input);
|
|
218
217
|
if (keys.length !== 1) {
|
|
219
218
|
return { kind: "invalid-input", message: "Select exactly one refactor operation." };
|
|
220
219
|
}
|
|
@@ -233,11 +232,17 @@ function parseOperation(input: RefactorOperationInput):
|
|
|
233
232
|
range: input.extract_function.range,
|
|
234
233
|
};
|
|
235
234
|
}
|
|
235
|
+
if ("extract_variable" in input) {
|
|
236
|
+
return {
|
|
237
|
+
kind: "ok",
|
|
238
|
+
operation: "extract_variable",
|
|
239
|
+
newName: input.extract_variable.newName,
|
|
240
|
+
range: input.extract_variable.range,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
236
243
|
return {
|
|
237
244
|
kind: "ok",
|
|
238
|
-
operation: "
|
|
239
|
-
newName: input.extract_variable.newName,
|
|
240
|
-
range: input.extract_variable.range,
|
|
245
|
+
operation: "update_imports" in input ? "update_imports" : "delete_dead_code",
|
|
241
246
|
};
|
|
242
247
|
}
|
|
243
248
|
|
|
@@ -265,13 +270,13 @@ async function planWithProvider(
|
|
|
265
270
|
file: string;
|
|
266
271
|
position: { line: number; character: number };
|
|
267
272
|
range?: SourceRange;
|
|
268
|
-
newName
|
|
273
|
+
newName?: string;
|
|
269
274
|
},
|
|
270
275
|
control?: WorkflowControl,
|
|
271
276
|
): Promise<RefactorResult> {
|
|
272
277
|
if (!provider) return { kind: "unavailable", reason: "No semantic provider is active." };
|
|
273
278
|
if (provider.refactor) return provider.refactor(request, control);
|
|
274
|
-
if (request.operation === "rename_symbol" && provider.rename) {
|
|
279
|
+
if (request.operation === "rename_symbol" && request.newName !== undefined && provider.rename) {
|
|
275
280
|
return provider.rename(request.file, request.position, request.newName, control);
|
|
276
281
|
}
|
|
277
282
|
return {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { CodeRequestControl, SemanticProvider } from "@mrclrchtr/supi-code-runtime/api";
|
|
2
|
+
import type { CapabilityAdapter, ReadinessOutcome } from "./capability-adapter.ts";
|
|
3
|
+
|
|
4
|
+
export type WorkspaceSemanticDemandState =
|
|
5
|
+
| { kind: "ready"; provider: SemanticProvider }
|
|
6
|
+
| Exclude<ReadinessOutcome, { kind: "ready" }>;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Wait for normal workspace startup, but let a registered provider proceed
|
|
10
|
+
* when known crashed routes make readiness recoverable only through demand.
|
|
11
|
+
*/
|
|
12
|
+
export async function resolveWorkspaceSemanticDemand(
|
|
13
|
+
capability: CapabilityAdapter,
|
|
14
|
+
cwd: string,
|
|
15
|
+
control?: CodeRequestControl,
|
|
16
|
+
): Promise<WorkspaceSemanticDemandState> {
|
|
17
|
+
let provider = capability.getSemanticProvider(cwd);
|
|
18
|
+
const readiness = await capability.ensureSemanticReadiness(cwd, { kind: "workspace" }, control);
|
|
19
|
+
if (readiness.kind === "timeout") return readiness;
|
|
20
|
+
if (readiness.kind === "unavailable" && !hasProcessCrashRoute(capability, cwd)) {
|
|
21
|
+
return readiness;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
provider ??= capability.getSemanticProvider(cwd);
|
|
25
|
+
return provider
|
|
26
|
+
? { kind: "ready", provider }
|
|
27
|
+
: { kind: "unavailable", reason: "No semantic workspace-symbol provider is active." };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function hasProcessCrashRoute(capability: CapabilityAdapter, cwd: string): boolean {
|
|
31
|
+
const lspState = capability.getLspRuntimeState(cwd);
|
|
32
|
+
return (
|
|
33
|
+
lspState.kind === "ready" &&
|
|
34
|
+
lspState.runtime.getProjectServers().some((server) => server.statusReason !== undefined)
|
|
35
|
+
);
|
|
36
|
+
}
|
|
@@ -23,6 +23,7 @@ import type {
|
|
|
23
23
|
} from "../analysis/target/types.ts";
|
|
24
24
|
import type { CapabilityAdapter } from "./capability-adapter.ts";
|
|
25
25
|
import { parseTargetInput } from "./input/common.ts";
|
|
26
|
+
import { resolveWorkspaceSemanticDemand } from "./semantic-demand.ts";
|
|
26
27
|
import { registerTargetCandidates, type TargetWorkflowCandidate } from "./target-candidates.ts";
|
|
27
28
|
import type { TargetInput, TargetSymbolKind } from "./target-input.ts";
|
|
28
29
|
import {
|
|
@@ -201,22 +202,15 @@ async function resolveSymbolWorkflow(
|
|
|
201
202
|
scope = resolved.path;
|
|
202
203
|
}
|
|
203
204
|
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
{ kind: "workspace" },
|
|
207
|
-
control,
|
|
208
|
-
);
|
|
209
|
-
if (readiness.kind === "timeout") {
|
|
205
|
+
const semanticDemand = await resolveWorkspaceSemanticDemand(deps.capability, deps.cwd, control);
|
|
206
|
+
if (semanticDemand.kind === "timeout") {
|
|
210
207
|
return { kind: "unavailable", reason: "LSP readiness timed out. Retry shortly." };
|
|
211
208
|
}
|
|
212
|
-
if (
|
|
213
|
-
return { kind: "unavailable", reason:
|
|
209
|
+
if (semanticDemand.kind === "unavailable") {
|
|
210
|
+
return { kind: "unavailable", reason: semanticDemand.reason };
|
|
214
211
|
}
|
|
215
212
|
|
|
216
|
-
const provider = withSemanticRequestControl(
|
|
217
|
-
deps.capability.getSemanticProvider(deps.cwd),
|
|
218
|
-
control,
|
|
219
|
-
);
|
|
213
|
+
const provider = withSemanticRequestControl(semanticDemand.provider, control);
|
|
220
214
|
if (!provider) {
|
|
221
215
|
return {
|
|
222
216
|
kind: "unavailable",
|
|
@@ -291,6 +285,9 @@ function toWorkflowOutcome(
|
|
|
291
285
|
policy: TargetWorkflowPolicy,
|
|
292
286
|
deps: TargetWorkflowDeps,
|
|
293
287
|
): TargetWorkflowOutcome {
|
|
288
|
+
if (outcome.kind === "unavailable") {
|
|
289
|
+
return { kind: "unavailable", reason: outcome.reason };
|
|
290
|
+
}
|
|
294
291
|
if (outcome.kind === "error") {
|
|
295
292
|
return { kind: "invalid-input", message: outcome.message };
|
|
296
293
|
}
|
|
@@ -45,7 +45,6 @@ export function registerLspSessionLifecycle(
|
|
|
45
45
|
await state.providerLease?.release();
|
|
46
46
|
state.providerLease = null;
|
|
47
47
|
state.controller = null;
|
|
48
|
-
state.lspActive = false;
|
|
49
48
|
state.sentinelSnapshot = new Map();
|
|
50
49
|
|
|
51
50
|
const lease = await acquireWorkspaceProviderHost(ctx.cwd, {
|
|
@@ -53,7 +52,6 @@ export function registerLspSessionLifecycle(
|
|
|
53
52
|
});
|
|
54
53
|
state.providerLease = lease;
|
|
55
54
|
state.controller = lease.lspController;
|
|
56
|
-
state.lspActive = lease.lspController?.kind === "ready";
|
|
57
55
|
state.sentinelSnapshot = lease.sentinelSnapshot;
|
|
58
56
|
await onStarted?.(ctx);
|
|
59
57
|
startLifecycleSubscription();
|
|
@@ -64,7 +62,6 @@ export function registerLspSessionLifecycle(
|
|
|
64
62
|
await state.providerLease?.release();
|
|
65
63
|
state.providerLease = null;
|
|
66
64
|
state.controller = null;
|
|
67
|
-
state.lspActive = false;
|
|
68
65
|
state.sentinelSnapshot = new Map();
|
|
69
66
|
dispatchStateChange();
|
|
70
67
|
});
|
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
isLikelyStaleDiagnostic,
|
|
25
25
|
isProjectConfigFileName,
|
|
26
26
|
raceRequestControl,
|
|
27
|
-
syncWorkspaceSentinelSnapshot,
|
|
28
27
|
type WorkspaceLspRuntime,
|
|
29
28
|
} from "@mrclrchtr/supi-lsp/api";
|
|
30
29
|
import { mergeDiagnosticEvidence } from "../../diagnostics/evidence.ts";
|
|
@@ -56,7 +55,7 @@ export async function refreshLspMaintenance(
|
|
|
56
55
|
sentinelSnapshot: Map<string, number>,
|
|
57
56
|
options: LspMaintenanceOptions = {},
|
|
58
57
|
): Promise<WorkspaceLspMaintenanceResult> {
|
|
59
|
-
const { snapshot } = await synchronizeSentinels(runtime,
|
|
58
|
+
const { snapshot } = await synchronizeSentinels(runtime, sentinelSnapshot, options);
|
|
60
59
|
let diagnosticEvidence = emptyEvidence();
|
|
61
60
|
let failureReason: string | undefined;
|
|
62
61
|
|
|
@@ -115,7 +114,7 @@ export async function refreshFileLspMaintenance(options: {
|
|
|
115
114
|
const { runtime, cwd, sentinelSnapshot, filePath, control } = options;
|
|
116
115
|
// A cancelled caller stops before any maintenance work starts.
|
|
117
116
|
throwIfCodeRequestInterrupted(control);
|
|
118
|
-
const { snapshot } = await synchronizeSentinels(runtime,
|
|
117
|
+
const { snapshot } = await synchronizeSentinels(runtime, sentinelSnapshot);
|
|
119
118
|
const target = nodePath.resolve(filePath);
|
|
120
119
|
const stale = confirmedOutstandingDiagnostics(runtime, cwd).some(
|
|
121
120
|
(entry) =>
|
|
@@ -149,12 +148,11 @@ export async function refreshFileLspMaintenance(options: {
|
|
|
149
148
|
*/
|
|
150
149
|
async function synchronizeSentinels(
|
|
151
150
|
runtime: WorkspaceLspRuntime,
|
|
152
|
-
cwd: string,
|
|
153
151
|
sentinelSnapshot: Map<string, number>,
|
|
154
152
|
options: LspMaintenanceOptions = {},
|
|
155
153
|
) {
|
|
156
154
|
const primed = sentinelSnapshot.size > 0;
|
|
157
|
-
const state = syncWorkspaceSentinelSnapshot(
|
|
155
|
+
const state = runtime.syncWorkspaceSentinelSnapshot(sentinelSnapshot, {
|
|
158
156
|
includeSourceFiles: true,
|
|
159
157
|
});
|
|
160
158
|
|
|
@@ -193,6 +191,7 @@ async function trackCreatedSourceFiles(
|
|
|
193
191
|
if (change.type !== FileChangeType.Created) continue;
|
|
194
192
|
const filePath = uriToFile(change.uri);
|
|
195
193
|
if (scope && !isWithinOrEqual(scope, filePath)) continue;
|
|
194
|
+
if (!runtime.isSupportedSourceFile(filePath)) continue;
|
|
196
195
|
// Best-effort: a file no client can serve stays untracked and is
|
|
197
196
|
// simply absent from evidence until a later explicit request.
|
|
198
197
|
await runtime.trackFile(filePath);
|