@mrclrchtr/supi-code-intelligence 4.9.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
- package/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
- package/node_modules/@mrclrchtr/supi-core/README.md +2 -0
- package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
- package/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
- package/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
- package/node_modules/@mrclrchtr/supi-core/src/debug-timing.ts +34 -21
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
- package/node_modules/@mrclrchtr/supi-lsp/README.md +80 -5
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
- 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/api.ts +9 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +2 -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/config/config.ts +31 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-timing.ts +34 -21
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
- package/node_modules/@mrclrchtr/supi-lsp/package.json +7 -6
- package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +10 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-cache.ts +206 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-capabilities.ts +78 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-collection.ts +114 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-evidence.ts +372 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-host.ts +14 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-pull.ts +62 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-refresh.ts +491 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-request.ts +9 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-timing.ts +215 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-waiters.ts +206 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostics.ts +370 -266
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-state.ts +52 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-sync.ts +185 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-file-state.ts +25 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +467 -115
- package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +238 -11
- package/node_modules/@mrclrchtr/supi-lsp/src/config/capabilities.ts +10 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/config/defaults.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/debug-telemetry.ts +45 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/evidence.ts +38 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-client-state.ts +79 -9
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +13 -4
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +300 -24
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-symbol.ts +5 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +464 -96
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-refactor-provider.ts +130 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +45 -329
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/refactor-planning.ts +57 -120
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-edit-normalizer.ts +320 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-symbol-mapper.ts +207 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/readiness.ts +72 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-controller.ts +151 -26
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostic-surface.ts +40 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostics.ts +50 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registry.ts +136 -120
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-transition-debug.ts +49 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +102 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +26 -6
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
- 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/api.ts +9 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +2 -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/config/config.ts +31 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-timing.ts +34 -21
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/LICENSE +21 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/README.md +258 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/babel.cjs +257 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/jiti.cjs +1 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-cli.mjs +34 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-hooks.mjs +124 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-native.mjs +121 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.d.mts +1 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.mjs +4 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-static.mjs +23 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.cjs +30 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.cts +8 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.mts +8 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.mjs +29 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/types.d.ts +420 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/package.json +146 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm +0 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm.map +4 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm +0 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm.map +4 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +7 -3
- 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 +0 -9
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +0 -8
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +16 -12
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-controller.ts +65 -87
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +47 -95
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-timing.ts +147 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client-lifecycle.ts +39 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client.ts +561 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-message-size.ts +24 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-protocol.ts +452 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-sites.ts +4 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +12 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/exports.ts +4 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/imports.ts +4 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/node-at.ts +5 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +33 -12
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/blocking-test-bootstrap.mjs +34 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/bootstrap.mjs +8 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store-helpers.ts +23 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store.ts +400 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/request-control.ts +48 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-parser-helpers.ts +24 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-query-helpers.ts +43 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime.ts +421 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/service.ts +116 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/worker-main.ts +201 -0
- package/package.json +5 -5
- package/src/analysis/health/diagnostics.ts +236 -24
- package/src/analysis/health/recovery.ts +6 -2
- package/src/analysis/provider.ts +58 -0
- package/src/analysis/readiness.ts +30 -9
- package/src/analysis/refactor/apply.ts +59 -20
- package/src/analysis/refactor/mutation-authority.ts +143 -0
- package/src/analysis/refactor/position.ts +47 -0
- package/src/analysis/refactor/safety.ts +18 -10
- package/src/analysis/relations/callees.ts +9 -1
- package/src/analysis/relations/types.ts +5 -2
- package/src/analysis/search/ast-scan-timing.ts +9 -4
- package/src/analysis/search/ast-scan.ts +1 -1
- package/src/analysis/search/deadline.ts +2 -2
- package/src/analysis/search/pattern-analysis.ts +46 -32
- package/src/analysis/search/pattern.ts +12 -2
- package/src/analysis/target/anchored.ts +20 -11
- package/src/analysis/target/file.ts +18 -11
- package/src/analysis/target/identity.ts +19 -3
- package/src/analysis/target/symbol.ts +36 -15
- package/src/api.ts +4 -0
- package/src/diagnostics/evidence.ts +51 -0
- package/src/session/capability-adapter.ts +12 -3
- package/src/session/find-workflow.ts +17 -7
- package/src/session/graph/collect.ts +18 -2
- package/src/session/graph-workflow.ts +19 -12
- package/src/session/health-refresh.ts +148 -0
- package/src/session/health-types.ts +37 -15
- package/src/session/health-workflow.ts +37 -39
- package/src/session/inspect/collect.ts +20 -3
- package/src/session/inspect-workflow.ts +10 -5
- package/src/session/orientation/collect.ts +10 -1
- package/src/session/orientation/context-facts.ts +3 -1
- package/src/session/orientation/context-sections.ts +20 -7
- package/src/session/orientation/gather.ts +17 -11
- package/src/session/orientation-types.ts +2 -1
- package/src/session/orientation-workflow.ts +15 -8
- package/src/session/refactor-plans.ts +2 -0
- package/src/session/refactor-workflow.ts +59 -14
- package/src/session/session.ts +4 -1
- package/src/session/target-workflow.ts +54 -23
- package/src/session/workflow-control.ts +7 -3
- package/src/substrate/lsp/lifecycle.ts +26 -46
- package/src/substrate/lsp/maintenance.ts +199 -25
- package/src/substrate/lsp/state.ts +2 -2
- package/src/substrate/workspace-provider-host.ts +25 -3
- package/src/tool/find/execute.ts +7 -1
- package/src/tool/find/render.ts +20 -3
- package/src/tool/find/tui.ts +23 -21
- package/src/tool/graph/execute.ts +23 -3
- package/src/tool/graph/tui.ts +59 -46
- package/src/tool/health/execute.ts +7 -2
- package/src/tool/health/markdown.ts +56 -14
- package/src/tool/health/refresh-status.ts +105 -0
- package/src/tool/health/tui.ts +95 -98
- package/src/tool/infra/workflow-control.ts +8 -0
- package/src/tool/inspect/execute.ts +7 -1
- package/src/tool/inspect/tui.ts +26 -18
- package/src/tool/orientation/execute.ts +21 -3
- package/src/tool/orientation/tui.ts +51 -35
- package/src/tool/refactor-apply/execute.ts +3 -0
- package/src/tool/refactor-apply/tui.ts +43 -25
- package/src/tool/refactor-plan/execute.ts +4 -0
- package/src/tool/refactor-plan/tui.ts +33 -20
- package/src/tool/register.ts +127 -22
- package/src/tool/resolve/execute.ts +18 -1
- package/src/tool/resolve/tui.ts +42 -24
- package/src/tool/result/display.ts +107 -0
- package/src/tool/result/errors.ts +20 -17
- package/src/tool/result/find.ts +52 -8
- package/src/tool/result/graph.ts +44 -1
- package/src/tool/result/health.ts +53 -1
- package/src/tool/result/inspect.ts +113 -1
- package/src/tool/result/orientation.ts +66 -14
- package/src/tool/result/refactor.ts +36 -4
- package/src/tool/result/resolve.ts +44 -7
- package/src/tool/result/types.ts +20 -0
- package/src/types/execution.ts +18 -5
- package/src/types/index.ts +8 -1
- package/src/ui/status-command.ts +5 -3
- package/src/ui/status-overlay.ts +4 -0
- package/src/ui/tui/common.ts +108 -10
- package/src/ui/tui/display.ts +48 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime.ts +0 -247
|
@@ -30,7 +30,8 @@ export async function runFindWorkflow(
|
|
|
30
30
|
const scope = resolveScopeSet(request.scope ? [...request.scope] : undefined, deps.cwd);
|
|
31
31
|
if (scope.kind === "error") return { kind: "invalid-input", message: scope.reason };
|
|
32
32
|
|
|
33
|
-
throwIfAborted(
|
|
33
|
+
if (mode === "ast") control?.signal?.throwIfAborted();
|
|
34
|
+
else throwIfAborted(control);
|
|
34
35
|
reportProgress(control, {
|
|
35
36
|
intent: "find",
|
|
36
37
|
phase: mode,
|
|
@@ -69,9 +70,11 @@ async function runSemanticSearch(options: {
|
|
|
69
70
|
control?: WorkflowControl;
|
|
70
71
|
}): Promise<FindWorkflowOutcome> {
|
|
71
72
|
const { query, scopePaths, scopeLabel, maxResults, deps, control } = options;
|
|
72
|
-
const readiness = await deps.capability.ensureSemanticReadiness(
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
const readiness = await deps.capability.ensureSemanticReadiness(
|
|
74
|
+
deps.cwd,
|
|
75
|
+
{ kind: "workspace" },
|
|
76
|
+
control,
|
|
77
|
+
);
|
|
75
78
|
if (readiness.kind === "timeout") {
|
|
76
79
|
return { kind: "unavailable", reason: "Semantic readiness timed out." };
|
|
77
80
|
}
|
|
@@ -82,7 +85,10 @@ async function runSemanticSearch(options: {
|
|
|
82
85
|
if (!provider?.workspaceSymbols) {
|
|
83
86
|
return { kind: "unavailable", reason: "No semantic workspace-symbol provider is active." };
|
|
84
87
|
}
|
|
85
|
-
const result = await provider.workspaceSymbols(query);
|
|
88
|
+
const result = await provider.workspaceSymbols(query, control);
|
|
89
|
+
// A cancellation that landed during the request must not publish symbols
|
|
90
|
+
// the caller no longer awaits.
|
|
91
|
+
throwIfAborted(control);
|
|
86
92
|
if (result.kind === "unavailable") {
|
|
87
93
|
return { kind: "unavailable", reason: result.reason };
|
|
88
94
|
}
|
|
@@ -120,13 +126,17 @@ async function runAstSearch(options: {
|
|
|
120
126
|
if (!provider) {
|
|
121
127
|
return { kind: "unavailable", reason: "No structural provider is active." };
|
|
122
128
|
}
|
|
123
|
-
throwIfAborted(
|
|
129
|
+
control?.signal?.throwIfAborted();
|
|
124
130
|
const outcome = await getStructuredPatternMatches({
|
|
125
131
|
params: { pattern: query, kind: input.kind },
|
|
126
132
|
roots: scopePaths,
|
|
127
133
|
cwd: deps.cwd,
|
|
128
134
|
structural: provider,
|
|
129
|
-
control: {
|
|
135
|
+
control: {
|
|
136
|
+
operationId: control?.operationId,
|
|
137
|
+
signal: control?.signal,
|
|
138
|
+
deadline: control?.deadline,
|
|
139
|
+
},
|
|
130
140
|
});
|
|
131
141
|
if (outcome.kind === "invalid-input") return outcome;
|
|
132
142
|
if (outcome.kind === "unavailable") return outcome;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/** Presentation-neutral relation collection used by the session-owned graph workflow. */
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
type CodeRequestControl,
|
|
5
|
+
isCodeRequestInterruption,
|
|
6
|
+
unavailableCodeQuery,
|
|
7
|
+
} from "@mrclrchtr/supi-code-runtime/api";
|
|
3
8
|
import type { CodeProvider } from "../../analysis/provider.ts";
|
|
4
9
|
import {
|
|
5
10
|
readNextEnclosingScope,
|
|
@@ -25,6 +30,7 @@ export interface CollectRelationOptions {
|
|
|
25
30
|
semanticReadinessError: string | null;
|
|
26
31
|
anchorKind: AnchorKind;
|
|
27
32
|
calleeDepth?: "direct" | "deep";
|
|
33
|
+
requestControl?: CodeRequestControl;
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
/** Collect one evidence-backed graph relation without rendering it. */
|
|
@@ -46,6 +52,7 @@ export async function collectRelation(
|
|
|
46
52
|
return collectImplementationsRelation(options);
|
|
47
53
|
}
|
|
48
54
|
} catch (error) {
|
|
55
|
+
if (isCodeRequestInterruption(error, options.requestControl)) throw error;
|
|
49
56
|
return {
|
|
50
57
|
kind: "unavailable",
|
|
51
58
|
rel: relation,
|
|
@@ -61,7 +68,11 @@ async function collectReferences(options: CollectRelationOptions): Promise<Graph
|
|
|
61
68
|
|
|
62
69
|
const result = await collectCallers(options.file, options.position, options.displayName, {
|
|
63
70
|
cwd: options.cwd,
|
|
64
|
-
provider: {
|
|
71
|
+
provider: {
|
|
72
|
+
references: async (file, position) =>
|
|
73
|
+
options.provider?.references(file, position, options.requestControl) ??
|
|
74
|
+
unavailableCodeQuery("References unavailable"),
|
|
75
|
+
},
|
|
65
76
|
});
|
|
66
77
|
if (result.confidence === "unavailable") {
|
|
67
78
|
return { kind: "unavailable", rel: "references", message: "References unavailable" };
|
|
@@ -118,6 +129,7 @@ async function collectCalleesRelation(options: CollectRelationOptions): Promise<
|
|
|
118
129
|
{ cwd: options.cwd, provider: { calleesAt: options.provider.calleesAt } },
|
|
119
130
|
undefined,
|
|
120
131
|
options.calleeDepth ?? "direct",
|
|
132
|
+
options.requestControl,
|
|
121
133
|
);
|
|
122
134
|
if (result.confidence === "unavailable") {
|
|
123
135
|
return { kind: "unavailable", rel: "callees", message: "Callees unavailable" };
|
|
@@ -161,7 +173,11 @@ async function collectImplementationsRelation(
|
|
|
161
173
|
|
|
162
174
|
const result = await collectImplementations(options.file, options.position, options.displayName, {
|
|
163
175
|
cwd: options.cwd,
|
|
164
|
-
provider: {
|
|
176
|
+
provider: {
|
|
177
|
+
implementation: async (file, position) =>
|
|
178
|
+
options.provider?.implementation(file, position, options.requestControl) ??
|
|
179
|
+
unavailableCodeQuery("Implementations unavailable"),
|
|
180
|
+
},
|
|
165
181
|
});
|
|
166
182
|
if (result.confidence === "unavailable") {
|
|
167
183
|
return { kind: "unavailable", rel: "implements", message: "Implementations unavailable" };
|
|
@@ -54,7 +54,9 @@ export async function runGraphWorkflow(
|
|
|
54
54
|
maxResults: request.maxResults,
|
|
55
55
|
},
|
|
56
56
|
deps,
|
|
57
|
+
control,
|
|
57
58
|
);
|
|
59
|
+
throwIfAborted(control);
|
|
58
60
|
if (targetOutcome.kind === "target-group") {
|
|
59
61
|
return {
|
|
60
62
|
kind: "invalid-input",
|
|
@@ -64,12 +66,13 @@ export async function runGraphWorkflow(
|
|
|
64
66
|
if (targetOutcome.kind !== "resolved") return targetOutcome;
|
|
65
67
|
|
|
66
68
|
const entry = targetOutcome.entry;
|
|
67
|
-
const semanticReadinessError = await getSemanticReadinessError(
|
|
69
|
+
const semanticReadinessError = await getSemanticReadinessError({
|
|
68
70
|
relations,
|
|
69
|
-
entry.file,
|
|
70
|
-
deps.capability,
|
|
71
|
-
deps.cwd,
|
|
72
|
-
|
|
71
|
+
file: entry.file,
|
|
72
|
+
capability: deps.capability,
|
|
73
|
+
cwd: deps.cwd,
|
|
74
|
+
control,
|
|
75
|
+
});
|
|
73
76
|
const provider = deps.capability.getProvider(deps.cwd);
|
|
74
77
|
const maxResults = request.maxResults ?? 8;
|
|
75
78
|
const displayName =
|
|
@@ -94,9 +97,11 @@ export async function runGraphWorkflow(
|
|
|
94
97
|
semanticReadinessError,
|
|
95
98
|
anchorKind: entry.anchorKind,
|
|
96
99
|
calleeDepth: request.calleeDepth,
|
|
100
|
+
requestControl: control,
|
|
97
101
|
}),
|
|
98
102
|
);
|
|
99
103
|
}
|
|
104
|
+
throwIfAborted(control);
|
|
100
105
|
|
|
101
106
|
if (sections.length > 0 && sections.every((section) => section.kind === "unavailable")) {
|
|
102
107
|
return {
|
|
@@ -127,16 +132,18 @@ function normalizeRelations(
|
|
|
127
132
|
return requested as readonly GraphRelationKind[];
|
|
128
133
|
}
|
|
129
134
|
|
|
130
|
-
async function getSemanticReadinessError(
|
|
131
|
-
relations: readonly GraphRelationKind[]
|
|
132
|
-
file: string
|
|
133
|
-
capability: CapabilityAdapter
|
|
134
|
-
cwd: string
|
|
135
|
-
|
|
135
|
+
async function getSemanticReadinessError(options: {
|
|
136
|
+
relations: readonly GraphRelationKind[];
|
|
137
|
+
file: string;
|
|
138
|
+
capability: CapabilityAdapter;
|
|
139
|
+
cwd: string;
|
|
140
|
+
control?: WorkflowControl;
|
|
141
|
+
}): Promise<string | null> {
|
|
142
|
+
const { relations, file, capability, cwd, control } = options;
|
|
136
143
|
if (!relations.some((relation) => relation === "references" || relation === "implements")) {
|
|
137
144
|
return null;
|
|
138
145
|
}
|
|
139
|
-
const readiness = await capability.ensureSemanticReadiness(cwd, { kind: "file", file });
|
|
146
|
+
const readiness = await capability.ensureSemanticReadiness(cwd, { kind: "file", file }, control);
|
|
140
147
|
if (readiness.kind === "ready") return null;
|
|
141
148
|
if (readiness.kind === "timeout") {
|
|
142
149
|
return "Semantic readiness timed out. Retry shortly or inspect code_health.";
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type CodeRequestControl,
|
|
3
|
+
isCodeRequestInterruption,
|
|
4
|
+
} from "@mrclrchtr/supi-code-runtime/api";
|
|
5
|
+
import type { WorkspaceLspRuntime } from "@mrclrchtr/supi-lsp/api";
|
|
6
|
+
import { recoverDiagnosticRuntime } from "../analysis/health/recovery.ts";
|
|
7
|
+
import { mergeDiagnosticEvidence } from "../diagnostics/evidence.ts";
|
|
8
|
+
import { refreshFileLspMaintenance, refreshLspMaintenance } from "../substrate/lsp/maintenance.ts";
|
|
9
|
+
import type { HealthDiagnosticScope, HealthRefreshAttempt } from "./health-types.ts";
|
|
10
|
+
|
|
11
|
+
interface HealthRefreshAttemptOptions {
|
|
12
|
+
readonly runtime: WorkspaceLspRuntime;
|
|
13
|
+
readonly diagnosticsScope: HealthDiagnosticScope;
|
|
14
|
+
readonly attemptedAt: number;
|
|
15
|
+
readonly cwd: string;
|
|
16
|
+
readonly sentinelSnapshot: Map<string, number>;
|
|
17
|
+
readonly control?: CodeRequestControl;
|
|
18
|
+
readonly reportRecoveryProgress?: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Run one file- or workspace-scoped health refresh attempt. */
|
|
22
|
+
export async function collectHealthRefreshAttempt(
|
|
23
|
+
options: HealthRefreshAttemptOptions,
|
|
24
|
+
): Promise<HealthRefreshAttempt> {
|
|
25
|
+
if (options.diagnosticsScope.kind === "file") {
|
|
26
|
+
return collectFileRefreshAttempt(options, options.diagnosticsScope);
|
|
27
|
+
}
|
|
28
|
+
return collectWorkspaceRefreshAttempt(options);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function collectFileRefreshAttempt(
|
|
32
|
+
options: HealthRefreshAttemptOptions,
|
|
33
|
+
scope: Extract<HealthDiagnosticScope, { kind: "file" }>,
|
|
34
|
+
): Promise<Extract<HealthRefreshAttempt, { kind: "completed" }>> {
|
|
35
|
+
const maintenance = await refreshFileLspMaintenance({
|
|
36
|
+
runtime: options.runtime,
|
|
37
|
+
cwd: options.cwd,
|
|
38
|
+
sentinelSnapshot: options.sentinelSnapshot,
|
|
39
|
+
filePath: scope.path,
|
|
40
|
+
control: options.control,
|
|
41
|
+
});
|
|
42
|
+
updateSentinelSnapshot(options.sentinelSnapshot, maintenance.snapshot);
|
|
43
|
+
const readiness = await options.runtime.waitUntilReadyForFile(
|
|
44
|
+
scope.path,
|
|
45
|
+
undefined,
|
|
46
|
+
options.control,
|
|
47
|
+
);
|
|
48
|
+
return {
|
|
49
|
+
kind: "completed",
|
|
50
|
+
attemptedAt: options.attemptedAt,
|
|
51
|
+
elapsedMs: Date.now() - options.attemptedAt,
|
|
52
|
+
requestedDiagnosticScope: scope,
|
|
53
|
+
operationScope: "file-runtime",
|
|
54
|
+
attemptedActiveClients: readiness.kind === "ready" ? 1 : 0,
|
|
55
|
+
restartedClients: 0,
|
|
56
|
+
staleAssessment: {
|
|
57
|
+
scope: "file",
|
|
58
|
+
suspected: null,
|
|
59
|
+
matchedFileCount: maintenance.matchedStaleFileCount,
|
|
60
|
+
warning: null,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function collectWorkspaceRefreshAttempt(
|
|
66
|
+
options: HealthRefreshAttemptOptions,
|
|
67
|
+
): Promise<HealthRefreshAttempt> {
|
|
68
|
+
const maintenance = await refreshLspMaintenance(
|
|
69
|
+
options.runtime,
|
|
70
|
+
options.cwd,
|
|
71
|
+
options.sentinelSnapshot,
|
|
72
|
+
options.control,
|
|
73
|
+
);
|
|
74
|
+
updateSentinelSnapshot(options.sentinelSnapshot, maintenance.snapshot);
|
|
75
|
+
if (maintenance.failureReason) {
|
|
76
|
+
return {
|
|
77
|
+
kind: "failed",
|
|
78
|
+
attemptedAt: options.attemptedAt,
|
|
79
|
+
elapsedMs: Date.now() - options.attemptedAt,
|
|
80
|
+
requestedDiagnosticScope: options.diagnosticsScope,
|
|
81
|
+
operationScope: "workspace-runtime",
|
|
82
|
+
diagnosticEvidence: maintenance.diagnosticEvidence,
|
|
83
|
+
reason: maintenance.failureReason,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const recovery = await recoverDiagnosticRuntime({
|
|
89
|
+
service: options.runtime,
|
|
90
|
+
control: options.control,
|
|
91
|
+
progress: options.reportRecoveryProgress,
|
|
92
|
+
});
|
|
93
|
+
const diagnosticEvidence = mergeDiagnosticEvidence(
|
|
94
|
+
maintenance.diagnosticEvidence,
|
|
95
|
+
recovery.diagnosticEvidence,
|
|
96
|
+
options.cwd,
|
|
97
|
+
);
|
|
98
|
+
if (recovery.refreshFailureReason) {
|
|
99
|
+
return {
|
|
100
|
+
kind: "failed",
|
|
101
|
+
attemptedAt: options.attemptedAt,
|
|
102
|
+
elapsedMs: Date.now() - options.attemptedAt,
|
|
103
|
+
requestedDiagnosticScope: options.diagnosticsScope,
|
|
104
|
+
operationScope: "workspace-runtime",
|
|
105
|
+
diagnosticEvidence,
|
|
106
|
+
reason: recovery.refreshFailureReason,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
kind: "completed",
|
|
111
|
+
attemptedAt: options.attemptedAt,
|
|
112
|
+
elapsedMs: Date.now() - options.attemptedAt,
|
|
113
|
+
requestedDiagnosticScope: options.diagnosticsScope,
|
|
114
|
+
operationScope: "workspace-runtime",
|
|
115
|
+
attemptedActiveClients: recovery.attemptedClients,
|
|
116
|
+
restartedClients: recovery.restartedClients,
|
|
117
|
+
diagnosticEvidence,
|
|
118
|
+
staleAssessment: {
|
|
119
|
+
scope: "workspace",
|
|
120
|
+
suspected: recovery.staleAssessment.suspected,
|
|
121
|
+
matchedFileCount: recovery.staleAssessment.matchedFiles.length,
|
|
122
|
+
warning: recovery.staleAssessment.warning,
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
} catch (error) {
|
|
126
|
+
// Cancellation must propagate; a cancelled caller no longer awaits a
|
|
127
|
+
// recorded failed attempt.
|
|
128
|
+
if (isCodeRequestInterruption(error, options.control)) throw error;
|
|
129
|
+
return {
|
|
130
|
+
kind: "failed",
|
|
131
|
+
attemptedAt: options.attemptedAt,
|
|
132
|
+
elapsedMs: Date.now() - options.attemptedAt,
|
|
133
|
+
requestedDiagnosticScope: options.diagnosticsScope,
|
|
134
|
+
operationScope: "workspace-runtime",
|
|
135
|
+
diagnosticEvidence: maintenance.diagnosticEvidence,
|
|
136
|
+
reason: errorMessage(error),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function updateSentinelSnapshot(target: Map<string, number>, next: Map<string, number>): void {
|
|
142
|
+
target.clear();
|
|
143
|
+
for (const [key, value] of next) target.set(key, value);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function errorMessage(error: unknown): string {
|
|
147
|
+
return error instanceof Error && error.message ? error.message : "Diagnostic refresh failed.";
|
|
148
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DiagnosticEvidenceSummary } from "@mrclrchtr/supi-lsp/api";
|
|
1
2
|
import type { CapabilityWarningReport } from "../analysis/capability/capability-warnings.ts";
|
|
2
3
|
|
|
3
4
|
export type HealthSection = "diagnostics" | "servers";
|
|
@@ -53,46 +54,67 @@ export type HealthDiagnosticObservation =
|
|
|
53
54
|
readonly kind: "completed";
|
|
54
55
|
readonly scope: HealthDiagnosticScope;
|
|
55
56
|
readonly entries: readonly HealthDiagnosticEntry[];
|
|
57
|
+
readonly evidence: DiagnosticEvidenceSummary;
|
|
56
58
|
}
|
|
57
59
|
| {
|
|
58
60
|
readonly kind: "partial";
|
|
59
61
|
readonly scope: HealthDiagnosticScope;
|
|
60
62
|
readonly entries: readonly HealthDiagnosticEntry[];
|
|
63
|
+
readonly evidence: DiagnosticEvidenceSummary;
|
|
61
64
|
readonly reason: string;
|
|
62
65
|
}
|
|
63
66
|
| {
|
|
64
67
|
readonly kind: "unavailable";
|
|
65
68
|
readonly scope: HealthDiagnosticScope;
|
|
66
69
|
readonly entries: readonly HealthDiagnosticEntry[];
|
|
70
|
+
readonly evidence: DiagnosticEvidenceSummary;
|
|
67
71
|
readonly reason: string;
|
|
68
72
|
};
|
|
69
73
|
|
|
70
|
-
/** Bounded stale-diagnostic metadata from
|
|
74
|
+
/** Bounded stale-diagnostic metadata from one refresh attempt. */
|
|
71
75
|
export interface HealthStaleAssessment {
|
|
72
|
-
readonly
|
|
76
|
+
readonly scope: "file" | "workspace";
|
|
77
|
+
readonly suspected: boolean | null;
|
|
73
78
|
readonly matchedFileCount: number;
|
|
74
79
|
readonly warning: string | null;
|
|
75
80
|
}
|
|
76
81
|
|
|
77
|
-
|
|
82
|
+
export type HealthRefreshOperationScope = "file-runtime" | "workspace-runtime";
|
|
83
|
+
|
|
84
|
+
/** Shared facts for one completed refresh or file-maintenance attempt. */
|
|
85
|
+
interface CompletedHealthRefreshAttempt {
|
|
86
|
+
readonly kind: "completed";
|
|
87
|
+
readonly attemptedAt: number;
|
|
88
|
+
/** Wall-clock duration of the attempt, for telemetry. */
|
|
89
|
+
readonly elapsedMs: number;
|
|
90
|
+
/** The diagnostic evidence scope requested by the caller, not the runtime operation scope. */
|
|
91
|
+
readonly requestedDiagnosticScope: HealthDiagnosticScope;
|
|
92
|
+
/** Active clients targeted by the best-effort operation; this is not a confirmed-success count. */
|
|
93
|
+
readonly attemptedActiveClients: number;
|
|
94
|
+
readonly restartedClients: number;
|
|
95
|
+
readonly staleAssessment: HealthStaleAssessment;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** A diagnostic refresh attempt against an explicit LSP runtime scope. */
|
|
78
99
|
export type HealthRefreshAttempt =
|
|
79
|
-
| {
|
|
80
|
-
readonly kind: "completed";
|
|
81
|
-
readonly attemptedAt: number;
|
|
82
|
-
/** The diagnostic evidence scope requested by the caller, not the runtime operation scope. */
|
|
83
|
-
readonly requestedDiagnosticScope: HealthDiagnosticScope;
|
|
84
|
-
/** Recovery always operates against the workspace runtime. */
|
|
100
|
+
| (CompletedHealthRefreshAttempt & {
|
|
85
101
|
readonly operationScope: "workspace-runtime";
|
|
86
|
-
/**
|
|
87
|
-
readonly
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
102
|
+
/** Final document-level evidence from the refresh or recovery pass. */
|
|
103
|
+
readonly diagnosticEvidence: DiagnosticEvidenceSummary;
|
|
104
|
+
})
|
|
105
|
+
| (CompletedHealthRefreshAttempt & {
|
|
106
|
+
/** File maintenance does not claim a workspace diagnostic refresh. */
|
|
107
|
+
readonly operationScope: "file-runtime";
|
|
108
|
+
})
|
|
91
109
|
| {
|
|
92
110
|
readonly kind: "failed";
|
|
93
111
|
readonly attemptedAt: number;
|
|
112
|
+
/** Wall-clock duration of the attempt, for telemetry. */
|
|
113
|
+
readonly elapsedMs: number;
|
|
94
114
|
readonly requestedDiagnosticScope: HealthDiagnosticScope;
|
|
95
|
-
readonly operationScope:
|
|
115
|
+
readonly operationScope: HealthRefreshOperationScope;
|
|
116
|
+
/** Evidence collected before the operation failed, when available. */
|
|
117
|
+
readonly diagnosticEvidence?: DiagnosticEvidenceSummary;
|
|
96
118
|
readonly reason: string;
|
|
97
119
|
};
|
|
98
120
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** Session-owned workspace health workflow. */
|
|
2
2
|
|
|
3
3
|
import type { CapabilityState } from "@mrclrchtr/supi-code-runtime/api";
|
|
4
|
+
import { isCodeRequestInterruption } from "@mrclrchtr/supi-code-runtime/api";
|
|
4
5
|
import type {
|
|
5
6
|
LspRuntimeController,
|
|
6
7
|
WorkspaceLspRuntime,
|
|
@@ -15,11 +16,11 @@ import {
|
|
|
15
16
|
diagnosticScope,
|
|
16
17
|
isScopedFile,
|
|
17
18
|
} from "../analysis/health/diagnostics.ts";
|
|
18
|
-
import { describeStructuralState
|
|
19
|
+
import { describeStructuralState } from "../analysis/health/recovery.ts";
|
|
19
20
|
import { collectServers } from "../analysis/health/signals.ts";
|
|
20
21
|
import { resolveScope } from "../analysis/search/paths.ts";
|
|
21
|
-
import { refreshLspMaintenance } from "../substrate/lsp/maintenance.ts";
|
|
22
22
|
import type { CapabilityAdapter } from "./capability-adapter.ts";
|
|
23
|
+
import { collectHealthRefreshAttempt } from "./health-refresh.ts";
|
|
23
24
|
import type {
|
|
24
25
|
HealthData,
|
|
25
26
|
HealthDiagnosticScope,
|
|
@@ -63,10 +64,11 @@ export async function runHealthWorkflow(
|
|
|
63
64
|
phase: "collection",
|
|
64
65
|
message: "Collecting workspace health evidence",
|
|
65
66
|
});
|
|
66
|
-
|
|
67
67
|
const lspState = deps.capability.getLspRuntimeState(deps.cwd);
|
|
68
68
|
const capabilityStates = deps.capability.getCapabilityStates(deps.cwd);
|
|
69
69
|
const runtime = lspState.kind === "ready" ? lspState.runtime : null;
|
|
70
|
+
const evidenceRuntime =
|
|
71
|
+
lspState.kind === "ready" || lspState.kind === "inactive" ? lspState.runtime : null;
|
|
70
72
|
const serverInventoryAvailable = lspState.kind === "ready" || lspState.kind === "disabled";
|
|
71
73
|
|
|
72
74
|
const diagnosticsScope = diagnosticScope(scopeFilter);
|
|
@@ -85,18 +87,29 @@ export async function runHealthWorkflow(
|
|
|
85
87
|
scopeFilter,
|
|
86
88
|
lspState,
|
|
87
89
|
capabilityState: capabilityStates.semantic,
|
|
90
|
+
control,
|
|
88
91
|
});
|
|
89
92
|
const semanticReady = semanticState?.kind === "ready";
|
|
90
93
|
throwIfAborted(control);
|
|
91
94
|
|
|
92
95
|
const diagnostics = await collectDiagnostics({
|
|
93
96
|
service: semanticReady ? runtime : null,
|
|
97
|
+
evidenceService: evidenceRuntime,
|
|
94
98
|
included,
|
|
95
99
|
scope: diagnosticsScope,
|
|
96
100
|
cwd: deps.cwd,
|
|
97
101
|
unavailableReason: diagnosticUnavailableReason(semanticState),
|
|
98
102
|
detailed: level === "detailed",
|
|
103
|
+
requestControl: control,
|
|
104
|
+
refreshEvidence:
|
|
105
|
+
(refresh.kind === "completed" || refresh.kind === "failed") &&
|
|
106
|
+
refresh.operationScope === "workspace-runtime"
|
|
107
|
+
? refresh.diagnosticEvidence
|
|
108
|
+
: undefined,
|
|
99
109
|
});
|
|
110
|
+
// A cancellation that landed during diagnostic resolution must not produce
|
|
111
|
+
// a completed health result the caller no longer awaits.
|
|
112
|
+
throwIfAborted(control);
|
|
100
113
|
const servers = collectServers(runtime, included);
|
|
101
114
|
const capabilityWarnings = collectCapabilityWarnings(semanticRequested, deps);
|
|
102
115
|
|
|
@@ -113,9 +126,9 @@ export async function runHealthWorkflow(
|
|
|
113
126
|
capabilityWarnings: capabilityWarnings?.hasWarnings ? capabilityWarnings : undefined,
|
|
114
127
|
};
|
|
115
128
|
|
|
129
|
+
throwIfAborted(control);
|
|
116
130
|
return { kind: "completed", data };
|
|
117
131
|
}
|
|
118
|
-
|
|
119
132
|
function healthNeedsSemantic(included: readonly HealthSection[]): boolean {
|
|
120
133
|
return included.includes("diagnostics") || included.includes("servers");
|
|
121
134
|
}
|
|
@@ -126,6 +139,7 @@ interface SemanticHealthStateOptions {
|
|
|
126
139
|
scopeFilter: string | null;
|
|
127
140
|
lspState: WorkspaceLspRuntimeState;
|
|
128
141
|
capabilityState: CapabilityState;
|
|
142
|
+
control?: WorkflowControl;
|
|
129
143
|
}
|
|
130
144
|
|
|
131
145
|
async function establishSemanticHealthState(
|
|
@@ -133,7 +147,11 @@ async function establishSemanticHealthState(
|
|
|
133
147
|
): Promise<SemanticHealthState | null> {
|
|
134
148
|
if (!options.requested) return null;
|
|
135
149
|
if (options.runtime && isScopedFile(options.scopeFilter)) {
|
|
136
|
-
const readiness = await options.runtime.waitUntilReadyForFile(
|
|
150
|
+
const readiness = await options.runtime.waitUntilReadyForFile(
|
|
151
|
+
options.scopeFilter,
|
|
152
|
+
undefined,
|
|
153
|
+
options.control,
|
|
154
|
+
);
|
|
137
155
|
if (readiness.kind === "ready") return { kind: "ready" };
|
|
138
156
|
if (readiness.kind === "timeout") {
|
|
139
157
|
return { kind: "pending", reason: "File semantic readiness timed out" };
|
|
@@ -231,54 +249,39 @@ async function collectRefreshState(options: RefreshStateOptions): Promise<Health
|
|
|
231
249
|
}
|
|
232
250
|
|
|
233
251
|
const attemptedAt = Date.now();
|
|
252
|
+
const operationScope = diagnosticsScope.kind === "file" ? "file-runtime" : "workspace-runtime";
|
|
234
253
|
try {
|
|
235
254
|
reportProgress(options.control, {
|
|
236
255
|
intent: "health",
|
|
237
256
|
phase: "maintenance",
|
|
238
257
|
message: "Refreshing LSP state and sentinel snapshot",
|
|
239
258
|
});
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
// Recovery still gets a chance to restart a failed routed client.
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const recovery = await recoverDiagnosticRuntime({
|
|
253
|
-
service: runtime,
|
|
254
|
-
progress: () =>
|
|
259
|
+
const attempt = await collectHealthRefreshAttempt({
|
|
260
|
+
runtime,
|
|
261
|
+
diagnosticsScope,
|
|
262
|
+
attemptedAt,
|
|
263
|
+
cwd: options.deps.cwd,
|
|
264
|
+
sentinelSnapshot: options.deps.sentinelSnapshot,
|
|
265
|
+
control: options.control,
|
|
266
|
+
reportRecoveryProgress: () =>
|
|
255
267
|
reportProgress(options.control, {
|
|
256
268
|
intent: "health",
|
|
257
269
|
phase: "recovery",
|
|
258
270
|
message: "Refreshing diagnostics and recovery state",
|
|
259
271
|
}),
|
|
260
272
|
});
|
|
261
|
-
const attempt: HealthRefreshAttempt = {
|
|
262
|
-
kind: "completed",
|
|
263
|
-
attemptedAt,
|
|
264
|
-
requestedDiagnosticScope: diagnosticsScope,
|
|
265
|
-
operationScope: "workspace-runtime",
|
|
266
|
-
attemptedActiveClients: recovery.attemptedClients,
|
|
267
|
-
restartedClients: recovery.restartedClients,
|
|
268
|
-
staleAssessment: {
|
|
269
|
-
suspected: recovery.staleAssessment.suspected,
|
|
270
|
-
matchedFileCount: recovery.staleAssessment.matchedFiles.length,
|
|
271
|
-
warning: recovery.staleAssessment.warning,
|
|
272
|
-
},
|
|
273
|
-
};
|
|
274
273
|
deps.trackRefreshAttempt(attempt);
|
|
275
274
|
return attempt;
|
|
276
275
|
} catch (error) {
|
|
276
|
+
// Cancellation must propagate; a cancelled caller no longer awaits a
|
|
277
|
+
// recorded failed attempt or the refresh data it would carry.
|
|
278
|
+
if (isCodeRequestInterruption(error, options.control)) throw error;
|
|
277
279
|
const attempt: HealthRefreshAttempt = {
|
|
278
280
|
kind: "failed",
|
|
279
281
|
attemptedAt,
|
|
282
|
+
elapsedMs: Date.now() - attemptedAt,
|
|
280
283
|
requestedDiagnosticScope: diagnosticsScope,
|
|
281
|
-
operationScope
|
|
284
|
+
operationScope,
|
|
282
285
|
reason: errorMessage(error),
|
|
283
286
|
};
|
|
284
287
|
deps.trackRefreshAttempt(attempt);
|
|
@@ -286,11 +289,6 @@ async function collectRefreshState(options: RefreshStateOptions): Promise<Health
|
|
|
286
289
|
}
|
|
287
290
|
}
|
|
288
291
|
|
|
289
|
-
function updateSentinelSnapshot(target: Map<string, number>, next: Map<string, number>): void {
|
|
290
|
-
target.clear();
|
|
291
|
-
for (const [key, value] of next) target.set(key, value);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
292
|
function refreshUnavailableReason(lspState: WorkspaceLspRuntimeState): string {
|
|
295
293
|
switch (lspState.kind) {
|
|
296
294
|
case "unavailable":
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
type CodePosition,
|
|
5
|
+
type CodeRequestControl,
|
|
6
|
+
isCodeRequestInterruption,
|
|
5
7
|
mapCodeQueryResult,
|
|
6
8
|
type OutlineData,
|
|
7
9
|
type SemanticProvider,
|
|
@@ -27,6 +29,7 @@ export interface InspectCollectionInput {
|
|
|
27
29
|
readonly line: number;
|
|
28
30
|
readonly character: number;
|
|
29
31
|
readonly lineCount: number;
|
|
32
|
+
readonly requestControl?: CodeRequestControl;
|
|
30
33
|
readonly structural: StructuralProvider | null;
|
|
31
34
|
readonly semantic: SemanticProvider | null;
|
|
32
35
|
readonly semanticUnavailableReason: string;
|
|
@@ -50,7 +53,12 @@ async function collectNode(
|
|
|
50
53
|
): Promise<InspectObservation<InspectNode | null>> {
|
|
51
54
|
if (!input.structural) return unavailableCodeQuery("No structural node provider is active.");
|
|
52
55
|
try {
|
|
53
|
-
const result = await input.structural.nodeAt(
|
|
56
|
+
const result = await input.structural.nodeAt(
|
|
57
|
+
input.file,
|
|
58
|
+
input.line,
|
|
59
|
+
input.character,
|
|
60
|
+
input.requestControl,
|
|
61
|
+
);
|
|
54
62
|
if (result.kind !== "success") return unavailableCodeQuery(result.message);
|
|
55
63
|
return {
|
|
56
64
|
kind: "completed",
|
|
@@ -65,6 +73,7 @@ async function collectNode(
|
|
|
65
73
|
},
|
|
66
74
|
};
|
|
67
75
|
} catch (error) {
|
|
76
|
+
if (isCodeRequestInterruption(error, input.requestControl)) throw error;
|
|
68
77
|
return unavailableCodeQuery(failureReason("Structural node lookup", error));
|
|
69
78
|
}
|
|
70
79
|
}
|
|
@@ -74,7 +83,7 @@ async function collectEnclosingSymbol(
|
|
|
74
83
|
): Promise<InspectObservation<InspectEnclosingSymbol | null>> {
|
|
75
84
|
if (!input.structural) return unavailableCodeQuery("No structural outline provider is active.");
|
|
76
85
|
try {
|
|
77
|
-
const result = await input.structural.outline(input.file);
|
|
86
|
+
const result = await input.structural.outline(input.file, input.requestControl);
|
|
78
87
|
if (result.kind !== "success") return unavailableCodeQuery(result.message);
|
|
79
88
|
return {
|
|
80
89
|
kind: "completed",
|
|
@@ -84,6 +93,7 @@ async function collectEnclosingSymbol(
|
|
|
84
93
|
}),
|
|
85
94
|
};
|
|
86
95
|
} catch (error) {
|
|
96
|
+
if (isCodeRequestInterruption(error, input.requestControl)) throw error;
|
|
87
97
|
return unavailableCodeQuery(failureReason("Structural outline lookup", error));
|
|
88
98
|
}
|
|
89
99
|
}
|
|
@@ -98,6 +108,7 @@ async function collectHover(
|
|
|
98
108
|
(hover) => hover?.contents ?? null,
|
|
99
109
|
);
|
|
100
110
|
} catch (error) {
|
|
111
|
+
if (isCodeRequestInterruption(error, input.requestControl)) throw error;
|
|
101
112
|
return unavailableCodeQuery(failureReason("Hover lookup", error));
|
|
102
113
|
}
|
|
103
114
|
}
|
|
@@ -131,6 +142,7 @@ async function collectDefinition(
|
|
|
131
142
|
? { kind: "partial", data: definitions, reason: reasons.join(" ") }
|
|
132
143
|
: { kind: "completed", data: definitions };
|
|
133
144
|
} catch (error) {
|
|
145
|
+
if (isCodeRequestInterruption(error, input.requestControl)) throw error;
|
|
134
146
|
return unavailableCodeQuery(failureReason("Definition lookup", error));
|
|
135
147
|
}
|
|
136
148
|
}
|
|
@@ -142,7 +154,11 @@ async function collectDiagnostics(
|
|
|
142
154
|
return unavailableCodeQuery(lspUnavailableReason(input.lspState));
|
|
143
155
|
}
|
|
144
156
|
try {
|
|
145
|
-
const result = await input.lspState.runtime.fileDiagnostics(
|
|
157
|
+
const result = await input.lspState.runtime.fileDiagnostics(
|
|
158
|
+
input.file,
|
|
159
|
+
4,
|
|
160
|
+
input.requestControl,
|
|
161
|
+
);
|
|
146
162
|
if (result.kind === "unavailable") return result;
|
|
147
163
|
const diagnostics = result.data
|
|
148
164
|
.filter((diagnostic) => diagnosticOverlapsWindow(diagnostic.range, input))
|
|
@@ -159,6 +175,7 @@ async function collectDiagnostics(
|
|
|
159
175
|
? { kind: "partial", data: diagnostics, reason: result.reason }
|
|
160
176
|
: { kind: "completed", data: diagnostics };
|
|
161
177
|
} catch (error) {
|
|
178
|
+
if (isCodeRequestInterruption(error, input.requestControl)) throw error;
|
|
162
179
|
return unavailableCodeQuery(failureReason("Diagnostic lookup", error));
|
|
163
180
|
}
|
|
164
181
|
}
|