@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
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import type { MessagePort } from "node:worker_threads";
|
|
2
|
+
import { isCodeRequestDeadlineError } from "@mrclrchtr/supi-code-runtime/api";
|
|
3
|
+
import type { StructuralTimingEvent } from "../session/structural-timing.ts";
|
|
4
|
+
import { assertStructuralProtocolMessageSize } from "../session/structural-worker-message-size.ts";
|
|
5
|
+
import {
|
|
6
|
+
encodeStructuralResult,
|
|
7
|
+
type ParentToStructuralWorkerMessage,
|
|
8
|
+
STRUCTURAL_WORKER_PROTOCOL_VERSION,
|
|
9
|
+
type StructuralWorkerChunkAckMessage,
|
|
10
|
+
type StructuralWorkerRequestMessage,
|
|
11
|
+
validateStructuralWorkerRequest,
|
|
12
|
+
} from "../session/structural-worker-protocol.ts";
|
|
13
|
+
import type { TreeSitterResult } from "../types.ts";
|
|
14
|
+
import type { StructuralRequestControl } from "./request-control.ts";
|
|
15
|
+
import { TreeSitterRuntime } from "./runtime.ts";
|
|
16
|
+
import { StructuralWorkerService } from "./service.ts";
|
|
17
|
+
|
|
18
|
+
interface WorkerBootstrapData {
|
|
19
|
+
readonly cwd: string;
|
|
20
|
+
readonly generation: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface ActiveWorkerRequest {
|
|
24
|
+
readonly message: StructuralWorkerRequestMessage;
|
|
25
|
+
readonly control: StructuralRequestControl;
|
|
26
|
+
readonly abortController: AbortController;
|
|
27
|
+
chunks: Uint8Array[];
|
|
28
|
+
nextSequence: number;
|
|
29
|
+
awaitingAck: boolean;
|
|
30
|
+
outcome: "completed" | "cancelled" | "timeout";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Start the package-private Structural Worker implementation. */
|
|
34
|
+
// biome-ignore lint/complexity/noExcessiveLinesPerFunction: one Worker loop owns active request and chunk acknowledgement state
|
|
35
|
+
export async function runStructuralWorker(
|
|
36
|
+
parentPort: MessagePort,
|
|
37
|
+
workerData: WorkerBootstrapData,
|
|
38
|
+
): Promise<void> {
|
|
39
|
+
const runtime = new TreeSitterRuntime(workerData.cwd, (event) => forwardObservation(event));
|
|
40
|
+
const service = new StructuralWorkerService(runtime);
|
|
41
|
+
let active: ActiveWorkerRequest | null = null;
|
|
42
|
+
|
|
43
|
+
const post = (message: unknown) => {
|
|
44
|
+
assertStructuralProtocolMessageSize(message);
|
|
45
|
+
parentPort.postMessage(message);
|
|
46
|
+
};
|
|
47
|
+
const forwardObservation = (observation: StructuralTimingEvent) => {
|
|
48
|
+
if (!active) return;
|
|
49
|
+
post({
|
|
50
|
+
kind: "observation",
|
|
51
|
+
version: STRUCTURAL_WORKER_PROTOCOL_VERSION,
|
|
52
|
+
generation: workerData.generation,
|
|
53
|
+
requestId: active.message.requestId,
|
|
54
|
+
observation,
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: protocol dispatch keeps request, cancel, and acknowledgement validation together
|
|
59
|
+
parentPort.on("message", (message: ParentToStructuralWorkerMessage) => {
|
|
60
|
+
if (message.version !== STRUCTURAL_WORKER_PROTOCOL_VERSION) return;
|
|
61
|
+
if (message.generation !== workerData.generation) return;
|
|
62
|
+
if (message.kind === "cancel") {
|
|
63
|
+
if (active?.message.requestId === message.requestId) active.abortController.abort();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (message.kind === "chunk-ack") {
|
|
67
|
+
if (active?.message.requestId === message.requestId) sendNextChunk(message);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (message.kind !== "request" || active) return;
|
|
71
|
+
const validation = validateStructuralWorkerRequest(message);
|
|
72
|
+
if (validation.kind === "invalid") return;
|
|
73
|
+
void execute(validation.message);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
await runtime.ensureGrammarParser("javascript");
|
|
78
|
+
post({
|
|
79
|
+
kind: "ready",
|
|
80
|
+
version: STRUCTURAL_WORKER_PROTOCOL_VERSION,
|
|
81
|
+
generation: workerData.generation,
|
|
82
|
+
});
|
|
83
|
+
} catch (error) {
|
|
84
|
+
post({
|
|
85
|
+
kind: "startup-failure",
|
|
86
|
+
version: STRUCTURAL_WORKER_PROTOCOL_VERSION,
|
|
87
|
+
generation: workerData.generation,
|
|
88
|
+
message: error instanceof Error ? error.message : "Structural Worker startup failed",
|
|
89
|
+
});
|
|
90
|
+
runtime.dispose();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: one terminal boundary classifies every operation result and interruption
|
|
94
|
+
async function execute(message: StructuralWorkerRequestMessage): Promise<void> {
|
|
95
|
+
const abortController = new AbortController();
|
|
96
|
+
const cancellationFlag = new Int32Array(message.cancellationFlag);
|
|
97
|
+
const control: StructuralRequestControl = {
|
|
98
|
+
operationId: message.operationId,
|
|
99
|
+
signal: abortController.signal,
|
|
100
|
+
deadline: message.deadline,
|
|
101
|
+
cancellationFlag,
|
|
102
|
+
};
|
|
103
|
+
active = {
|
|
104
|
+
message,
|
|
105
|
+
control,
|
|
106
|
+
abortController,
|
|
107
|
+
chunks: [],
|
|
108
|
+
nextSequence: 0,
|
|
109
|
+
awaitingAck: false,
|
|
110
|
+
outcome: "completed",
|
|
111
|
+
};
|
|
112
|
+
let result: TreeSitterResult<unknown>;
|
|
113
|
+
try {
|
|
114
|
+
result = await service.execute(message.input, control);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
const timedOut =
|
|
117
|
+
isCodeRequestDeadlineError(error) ||
|
|
118
|
+
(message.deadline !== undefined && Date.now() >= message.deadline);
|
|
119
|
+
const cancelled = abortController.signal.aborted || Atomics.load(cancellationFlag, 0) !== 0;
|
|
120
|
+
active.outcome = timedOut ? "timeout" : cancelled ? "cancelled" : "completed";
|
|
121
|
+
result = {
|
|
122
|
+
kind: "runtime-error",
|
|
123
|
+
message: timedOut
|
|
124
|
+
? "Structural request deadline exceeded"
|
|
125
|
+
: cancelled
|
|
126
|
+
? "Structural request cancelled"
|
|
127
|
+
: error instanceof Error
|
|
128
|
+
? error.message
|
|
129
|
+
: "Structural Worker operation failed",
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (!active || active.message.requestId !== message.requestId) return;
|
|
133
|
+
try {
|
|
134
|
+
active.chunks = encodeStructuralResult(result);
|
|
135
|
+
} catch (error) {
|
|
136
|
+
active.chunks = encodeStructuralResult({
|
|
137
|
+
kind: "runtime-error",
|
|
138
|
+
message: error instanceof Error ? error.message : "Structural result encoding failed",
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
sendChunk();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function sendNextChunk(message: StructuralWorkerChunkAckMessage): void {
|
|
145
|
+
if (!active?.awaitingAck || message.sequence !== active.nextSequence - 1) return;
|
|
146
|
+
active.awaitingAck = false;
|
|
147
|
+
if (active.nextSequence >= active.chunks.length) {
|
|
148
|
+
postTerminal();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
sendChunk();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function sendChunk(): void {
|
|
155
|
+
if (!active || active.awaitingAck) return;
|
|
156
|
+
updateInterruptionOutcome(active);
|
|
157
|
+
const sequence = active.nextSequence;
|
|
158
|
+
const payload = active.chunks[sequence];
|
|
159
|
+
if (!payload) {
|
|
160
|
+
postTerminal();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
active.nextSequence += 1;
|
|
164
|
+
active.awaitingAck = true;
|
|
165
|
+
post({
|
|
166
|
+
kind: "chunk",
|
|
167
|
+
version: STRUCTURAL_WORKER_PROTOCOL_VERSION,
|
|
168
|
+
generation: workerData.generation,
|
|
169
|
+
requestId: active.message.requestId,
|
|
170
|
+
sequence,
|
|
171
|
+
final: active.nextSequence === active.chunks.length,
|
|
172
|
+
encodedBytes: payload.byteLength,
|
|
173
|
+
payload,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function postTerminal(): void {
|
|
178
|
+
if (!active) return;
|
|
179
|
+
updateInterruptionOutcome(active);
|
|
180
|
+
post({
|
|
181
|
+
kind: "terminal",
|
|
182
|
+
version: STRUCTURAL_WORKER_PROTOCOL_VERSION,
|
|
183
|
+
generation: workerData.generation,
|
|
184
|
+
requestId: active.message.requestId,
|
|
185
|
+
outcome: active.outcome,
|
|
186
|
+
});
|
|
187
|
+
active = null;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function updateInterruptionOutcome(request: ActiveWorkerRequest): void {
|
|
191
|
+
if (request.message.deadline !== undefined && Date.now() >= request.message.deadline) {
|
|
192
|
+
request.outcome = "timeout";
|
|
193
|
+
} else if (
|
|
194
|
+
request.abortController.signal.aborted ||
|
|
195
|
+
(request.control.cancellationFlag !== undefined &&
|
|
196
|
+
Atomics.load(request.control.cancellationFlag, 0) !== 0)
|
|
197
|
+
) {
|
|
198
|
+
request.outcome = "cancelled";
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-code-intelligence",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "LSP and AST navigation, search, diagnostics, and refactoring",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"yaml": "^2.9.0",
|
|
38
|
-
"@mrclrchtr/supi-
|
|
39
|
-
"@mrclrchtr/supi-
|
|
40
|
-
"@mrclrchtr/supi-tree-sitter": "
|
|
41
|
-
"@mrclrchtr/supi-
|
|
38
|
+
"@mrclrchtr/supi-core": "5.0.0",
|
|
39
|
+
"@mrclrchtr/supi-lsp": "5.0.0",
|
|
40
|
+
"@mrclrchtr/supi-tree-sitter": "5.0.0",
|
|
41
|
+
"@mrclrchtr/supi-code-runtime": "5.0.0"
|
|
42
42
|
},
|
|
43
43
|
"bundledDependencies": [
|
|
44
44
|
"@mrclrchtr/supi-code-runtime",
|
|
@@ -2,9 +2,19 @@
|
|
|
2
2
|
// Extracted from orchestrate.ts.
|
|
3
3
|
|
|
4
4
|
import { existsSync, statSync } from "node:fs";
|
|
5
|
-
import { resolve } from "node:path";
|
|
5
|
+
import { relative, resolve } from "node:path";
|
|
6
|
+
import {
|
|
7
|
+
type CodeRequestControl,
|
|
8
|
+
isCodeRequestInterruption,
|
|
9
|
+
} from "@mrclrchtr/supi-code-runtime/api";
|
|
6
10
|
import { isWithinOrEqual } from "@mrclrchtr/supi-core/api";
|
|
7
|
-
import type {
|
|
11
|
+
import type {
|
|
12
|
+
Diagnostic,
|
|
13
|
+
DiagnosticEvidenceDocument,
|
|
14
|
+
DiagnosticEvidenceSummary,
|
|
15
|
+
WorkspaceLspRuntime,
|
|
16
|
+
} from "@mrclrchtr/supi-lsp/api";
|
|
17
|
+
import { mergeDiagnosticEvidence } from "../../diagnostics/evidence.ts";
|
|
8
18
|
import type {
|
|
9
19
|
HealthDiagnosticEntry,
|
|
10
20
|
HealthDiagnosticMessage,
|
|
@@ -28,60 +38,117 @@ export function diagnosticScope(scopeFilter: string | null): HealthDiagnosticSco
|
|
|
28
38
|
|
|
29
39
|
interface CollectDiagnosticsOptions {
|
|
30
40
|
readonly service: WorkspaceLspRuntime | null;
|
|
41
|
+
/** Runtime used for evidence snapshots when semantic operations are unavailable. */
|
|
42
|
+
readonly evidenceService?: WorkspaceLspRuntime | null;
|
|
31
43
|
readonly included: readonly HealthSection[];
|
|
32
44
|
readonly scope: HealthDiagnosticScope;
|
|
33
45
|
readonly cwd: string;
|
|
34
46
|
readonly unavailableReason: string;
|
|
35
47
|
/** Collect individual messages per file (detailed level). */
|
|
36
48
|
readonly detailed?: boolean;
|
|
49
|
+
readonly requestControl?: CodeRequestControl;
|
|
50
|
+
/** Final evidence from an explicit workspace refresh, when one ran. */
|
|
51
|
+
readonly refreshEvidence?: DiagnosticEvidenceSummary;
|
|
37
52
|
}
|
|
38
53
|
|
|
39
54
|
/** Collect diagnostics without widening the requested evidence scope. */
|
|
40
55
|
export async function collectDiagnostics(
|
|
41
56
|
options: CollectDiagnosticsOptions,
|
|
42
57
|
): Promise<HealthDiagnosticObservation> {
|
|
43
|
-
const { service, included, scope, cwd, unavailableReason, detailed } = options;
|
|
58
|
+
const { service, included, scope, cwd, unavailableReason, detailed, requestControl } = options;
|
|
44
59
|
if (!included.includes("diagnostics")) return { kind: "not-requested", entries: [] };
|
|
45
|
-
if (!service)
|
|
60
|
+
if (!service) {
|
|
61
|
+
return unavailableDiagnostics(
|
|
62
|
+
scope,
|
|
63
|
+
unavailableReason,
|
|
64
|
+
unavailableScopeEvidence(scope, options.refreshEvidence, options.evidenceService, cwd),
|
|
65
|
+
);
|
|
66
|
+
}
|
|
46
67
|
|
|
47
68
|
return scope.kind === "file"
|
|
48
|
-
? collectScopedFileDiagnostics(service, scope, detailed)
|
|
49
|
-
: collectTrackedFileDiagnostics(
|
|
69
|
+
? collectScopedFileDiagnostics(service, scope, detailed, requestControl)
|
|
70
|
+
: collectTrackedFileDiagnostics({
|
|
71
|
+
service,
|
|
72
|
+
scope,
|
|
73
|
+
cwd,
|
|
74
|
+
detailed,
|
|
75
|
+
refreshEvidence: options.refreshEvidence,
|
|
76
|
+
});
|
|
50
77
|
}
|
|
51
78
|
|
|
52
79
|
async function collectScopedFileDiagnostics(
|
|
53
80
|
service: WorkspaceLspRuntime,
|
|
54
81
|
scope: Extract<HealthDiagnosticScope, { kind: "file" }>,
|
|
55
82
|
detailed?: boolean,
|
|
83
|
+
requestControl?: CodeRequestControl,
|
|
56
84
|
): Promise<HealthDiagnosticObservation> {
|
|
57
85
|
try {
|
|
58
|
-
const result = await service.fileDiagnostics(scope.path, 4);
|
|
59
|
-
if (result.kind === "unavailable")
|
|
86
|
+
const result = await service.fileDiagnostics(scope.path, 4, requestControl);
|
|
87
|
+
if (result.kind === "unavailable") {
|
|
88
|
+
return unavailableDiagnostics(scope, result.reason, unavailableFileEvidence(scope.path));
|
|
89
|
+
}
|
|
60
90
|
|
|
61
91
|
const entries = toFileDiagnosticEntries(scope.path, result.data, detailed);
|
|
62
92
|
return result.kind === "partial"
|
|
63
|
-
? {
|
|
64
|
-
|
|
93
|
+
? {
|
|
94
|
+
kind: "partial",
|
|
95
|
+
scope,
|
|
96
|
+
entries,
|
|
97
|
+
evidence: singleFileEvidence(scope.path, "unconfirmed"),
|
|
98
|
+
reason: result.reason,
|
|
99
|
+
}
|
|
100
|
+
: {
|
|
101
|
+
kind: "completed",
|
|
102
|
+
scope,
|
|
103
|
+
entries,
|
|
104
|
+
evidence: singleFileEvidence(scope.path, "confirmed"),
|
|
105
|
+
};
|
|
65
106
|
} catch (error) {
|
|
66
|
-
|
|
107
|
+
if (isCodeRequestInterruption(error, requestControl)) throw error;
|
|
108
|
+
return unavailableDiagnostics(
|
|
109
|
+
scope,
|
|
110
|
+
errorMessage(error, "File diagnostic request failed."),
|
|
111
|
+
unavailableFileEvidence(scope.path),
|
|
112
|
+
);
|
|
67
113
|
}
|
|
68
114
|
}
|
|
69
115
|
|
|
116
|
+
interface TrackedFileDiagnosticOptions {
|
|
117
|
+
readonly service: WorkspaceLspRuntime;
|
|
118
|
+
readonly scope: Extract<HealthDiagnosticScope, { kind: "tracked-files" }>;
|
|
119
|
+
readonly cwd: string;
|
|
120
|
+
readonly detailed?: boolean;
|
|
121
|
+
readonly refreshEvidence?: DiagnosticEvidenceSummary;
|
|
122
|
+
}
|
|
123
|
+
|
|
70
124
|
function collectTrackedFileDiagnostics(
|
|
71
|
-
|
|
72
|
-
scope: Extract<HealthDiagnosticScope, { kind: "tracked-files" }>,
|
|
73
|
-
cwd: string,
|
|
74
|
-
detailed?: boolean,
|
|
125
|
+
options: TrackedFileDiagnosticOptions,
|
|
75
126
|
): HealthDiagnosticObservation {
|
|
127
|
+
const { service, scope, cwd, detailed, refreshEvidence } = options;
|
|
76
128
|
try {
|
|
77
|
-
const
|
|
129
|
+
const snapshot = detailed
|
|
78
130
|
? collectWorkspaceDiagnosticsDetailed(service, scope.filter, cwd)
|
|
79
131
|
: collectWorkspaceDiagnostics(service, scope.filter, cwd);
|
|
80
|
-
|
|
132
|
+
const sourceEvidence = mergeEvidence(refreshEvidence, snapshot.evidence, cwd);
|
|
133
|
+
const scopedEvidence = selectTrackedFileEvidence(sourceEvidence, scope.filter, cwd);
|
|
134
|
+
const evidence = ensureEvidenceCoversEntries(scopedEvidence, snapshot.entries, cwd);
|
|
135
|
+
return evidenceIsComplete(evidence, snapshot.entries.length > 0, snapshot.current)
|
|
136
|
+
? { kind: "completed", scope, entries: snapshot.entries, evidence }
|
|
137
|
+
: {
|
|
138
|
+
kind: "partial",
|
|
139
|
+
scope,
|
|
140
|
+
entries: snapshot.entries,
|
|
141
|
+
evidence,
|
|
142
|
+
reason: diagnosticEvidenceReason(evidence),
|
|
143
|
+
};
|
|
81
144
|
} catch (error) {
|
|
145
|
+
const evidence = options.refreshEvidence
|
|
146
|
+
? selectTrackedFileEvidence(options.refreshEvidence, scope.filter, cwd)
|
|
147
|
+
: emptyEvidence();
|
|
82
148
|
return unavailableDiagnostics(
|
|
83
149
|
scope,
|
|
84
150
|
errorMessage(error, "Tracked-file diagnostic snapshot is unavailable."),
|
|
151
|
+
evidence,
|
|
85
152
|
);
|
|
86
153
|
}
|
|
87
154
|
}
|
|
@@ -105,18 +172,22 @@ function collectWorkspaceDiagnostics(
|
|
|
105
172
|
service: WorkspaceLspRuntime,
|
|
106
173
|
scopeFilter: string | null,
|
|
107
174
|
cwd: string,
|
|
108
|
-
):
|
|
175
|
+
): {
|
|
176
|
+
entries: HealthDiagnosticEntry[];
|
|
177
|
+
current: boolean;
|
|
178
|
+
evidence: DiagnosticEvidenceSummary;
|
|
179
|
+
} {
|
|
109
180
|
const summary = service.getWorkspaceDiagnosticSummary();
|
|
110
181
|
const result: HealthDiagnosticEntry[] = [];
|
|
111
182
|
|
|
112
|
-
for (const entry of summary) {
|
|
183
|
+
for (const entry of summary.entries) {
|
|
113
184
|
const filePath = resolve(cwd, entry.file);
|
|
114
185
|
if (scopeFilter && !isWithinOrEqual(scopeFilter, filePath)) continue;
|
|
115
186
|
if (!hasIssueCounts(entry.errors, entry.warnings)) continue;
|
|
116
187
|
result.push({ file: filePath, errors: entry.errors, warnings: entry.warnings });
|
|
117
188
|
}
|
|
118
189
|
|
|
119
|
-
return result;
|
|
190
|
+
return { entries: result, current: summary.current, evidence: summary.evidence };
|
|
120
191
|
}
|
|
121
192
|
|
|
122
193
|
/** Detailed workspace path: full diagnostics with messages, capped per file. */
|
|
@@ -124,18 +195,22 @@ function collectWorkspaceDiagnosticsDetailed(
|
|
|
124
195
|
service: WorkspaceLspRuntime,
|
|
125
196
|
scopeFilter: string | null,
|
|
126
197
|
cwd: string,
|
|
127
|
-
):
|
|
198
|
+
): {
|
|
199
|
+
entries: HealthDiagnosticEntry[];
|
|
200
|
+
current: boolean;
|
|
201
|
+
evidence: DiagnosticEvidenceSummary;
|
|
202
|
+
} {
|
|
128
203
|
const outstanding = service.getOutstandingDiagnostics(2);
|
|
129
204
|
const result: HealthDiagnosticEntry[] = [];
|
|
130
205
|
|
|
131
|
-
for (const { file, diagnostics } of outstanding) {
|
|
206
|
+
for (const { file, diagnostics } of outstanding.entries) {
|
|
132
207
|
const filePath = resolve(cwd, file);
|
|
133
208
|
if (scopeFilter && !isWithinOrEqual(scopeFilter, filePath)) continue;
|
|
134
209
|
const entries = toFileDiagnosticEntries(filePath, diagnostics, true);
|
|
135
210
|
result.push(...entries);
|
|
136
211
|
}
|
|
137
212
|
|
|
138
|
-
return result;
|
|
213
|
+
return { entries: result, current: outstanding.current, evidence: outstanding.evidence };
|
|
139
214
|
}
|
|
140
215
|
|
|
141
216
|
// ── Message extraction ────────────────────────────────────────────────
|
|
@@ -159,11 +234,49 @@ function extractMessages(
|
|
|
159
234
|
}));
|
|
160
235
|
}
|
|
161
236
|
|
|
237
|
+
function unavailableScopeEvidence(
|
|
238
|
+
scope: HealthDiagnosticScope,
|
|
239
|
+
refreshEvidence: DiagnosticEvidenceSummary | undefined,
|
|
240
|
+
evidenceService: WorkspaceLspRuntime | null | undefined,
|
|
241
|
+
cwd: string,
|
|
242
|
+
): DiagnosticEvidenceSummary {
|
|
243
|
+
const runtimeEvidence = readRuntimeEvidence(evidenceService);
|
|
244
|
+
const knownEvidence = refreshEvidence
|
|
245
|
+
? mergeDiagnosticEvidence(refreshEvidence, runtimeEvidence, cwd, "conservative")
|
|
246
|
+
: runtimeEvidence;
|
|
247
|
+
if (knownEvidence.requested === 0 && knownEvidence.documents.length === 0) {
|
|
248
|
+
return scope.kind === "file" ? unavailableFileEvidence(scope.path) : emptyEvidence();
|
|
249
|
+
}
|
|
250
|
+
const scoped = selectTrackedFileEvidence(
|
|
251
|
+
knownEvidence,
|
|
252
|
+
scope.kind === "file" ? scope.path : scope.filter,
|
|
253
|
+
cwd,
|
|
254
|
+
);
|
|
255
|
+
if (scoped.requested > 0) return scoped;
|
|
256
|
+
return scope.kind === "file" ? unavailableFileEvidence(scope.path) : scoped;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function unavailableFileEvidence(file: string): DiagnosticEvidenceSummary {
|
|
260
|
+
return singleFileEvidence(file, existsSync(file) ? "failed" : "removed");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function readRuntimeEvidence(
|
|
264
|
+
service: WorkspaceLspRuntime | null | undefined,
|
|
265
|
+
): DiagnosticEvidenceSummary {
|
|
266
|
+
if (!service) return emptyEvidence();
|
|
267
|
+
try {
|
|
268
|
+
return service.getWorkspaceDiagnosticSummary().evidence;
|
|
269
|
+
} catch {
|
|
270
|
+
return emptyEvidence();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
162
274
|
function unavailableDiagnostics(
|
|
163
275
|
scope: HealthDiagnosticScope,
|
|
164
276
|
reason: string,
|
|
277
|
+
evidence: DiagnosticEvidenceSummary = emptyEvidence(),
|
|
165
278
|
): HealthDiagnosticObservation {
|
|
166
|
-
return { kind: "unavailable", scope, entries: [], reason };
|
|
279
|
+
return { kind: "unavailable", scope, entries: [], evidence, reason };
|
|
167
280
|
}
|
|
168
281
|
|
|
169
282
|
function errorMessage(error: unknown, fallback: string): string {
|
|
@@ -174,6 +287,105 @@ function hasIssueCounts(errors: number, warnings: number): boolean {
|
|
|
174
287
|
return errors > 0 || warnings > 0;
|
|
175
288
|
}
|
|
176
289
|
|
|
290
|
+
function emptyEvidence(): DiagnosticEvidenceSummary {
|
|
291
|
+
return {
|
|
292
|
+
requested: 0,
|
|
293
|
+
confirmed: 0,
|
|
294
|
+
unconfirmed: 0,
|
|
295
|
+
failed: 0,
|
|
296
|
+
removed: 0,
|
|
297
|
+
documents: [],
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function singleFileEvidence(
|
|
302
|
+
file: string,
|
|
303
|
+
status: DiagnosticEvidenceDocument["status"],
|
|
304
|
+
): DiagnosticEvidenceSummary {
|
|
305
|
+
return {
|
|
306
|
+
requested: 1,
|
|
307
|
+
confirmed: status === "confirmed" ? 1 : 0,
|
|
308
|
+
unconfirmed: status === "unconfirmed" ? 1 : 0,
|
|
309
|
+
failed: status === "failed" ? 1 : 0,
|
|
310
|
+
removed: status === "removed" ? 1 : 0,
|
|
311
|
+
documents: [{ file, status }],
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function mergeEvidence(
|
|
316
|
+
refreshEvidence: DiagnosticEvidenceSummary | undefined,
|
|
317
|
+
snapshotEvidence: DiagnosticEvidenceSummary,
|
|
318
|
+
cwd: string,
|
|
319
|
+
): DiagnosticEvidenceSummary {
|
|
320
|
+
return refreshEvidence
|
|
321
|
+
? mergeDiagnosticEvidence(refreshEvidence, snapshotEvidence, cwd, "conservative")
|
|
322
|
+
: snapshotEvidence;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function selectTrackedFileEvidence(
|
|
326
|
+
evidence: DiagnosticEvidenceSummary,
|
|
327
|
+
scopeFilter: string | null,
|
|
328
|
+
cwd: string,
|
|
329
|
+
): DiagnosticEvidenceSummary {
|
|
330
|
+
if (evidence.documents.length === 0) return evidence;
|
|
331
|
+
|
|
332
|
+
const documents = evidence.documents.filter((document) => {
|
|
333
|
+
if (scopeFilter === null) return true;
|
|
334
|
+
return isWithinOrEqual(scopeFilter, resolve(cwd, document.file));
|
|
335
|
+
});
|
|
336
|
+
return summarizeEvidence(documents);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function ensureEvidenceCoversEntries(
|
|
340
|
+
evidence: DiagnosticEvidenceSummary,
|
|
341
|
+
entries: readonly HealthDiagnosticEntry[],
|
|
342
|
+
cwd: string,
|
|
343
|
+
): DiagnosticEvidenceSummary {
|
|
344
|
+
if (entries.length === 0) return evidence;
|
|
345
|
+
const documents = [...evidence.documents];
|
|
346
|
+
const knownFiles = new Set(documents.map((document) => resolve(cwd, document.file)));
|
|
347
|
+
for (const entry of entries) {
|
|
348
|
+
const file = resolve(cwd, entry.file);
|
|
349
|
+
if (knownFiles.has(file)) continue;
|
|
350
|
+
knownFiles.add(file);
|
|
351
|
+
documents.push({ file: relative(cwd, file), status: "unconfirmed" });
|
|
352
|
+
}
|
|
353
|
+
return summarizeEvidence(documents);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function summarizeEvidence(
|
|
357
|
+
documents: readonly DiagnosticEvidenceDocument[],
|
|
358
|
+
): DiagnosticEvidenceSummary {
|
|
359
|
+
const counts = {
|
|
360
|
+
requested: documents.length,
|
|
361
|
+
confirmed: 0,
|
|
362
|
+
unconfirmed: 0,
|
|
363
|
+
failed: 0,
|
|
364
|
+
removed: 0,
|
|
365
|
+
};
|
|
366
|
+
for (const document of documents) counts[document.status]++;
|
|
367
|
+
return { ...counts, documents: [...documents] };
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function evidenceIsComplete(
|
|
371
|
+
evidence: DiagnosticEvidenceSummary,
|
|
372
|
+
hasDiagnosticEntries: boolean,
|
|
373
|
+
snapshotCurrent: boolean,
|
|
374
|
+
): boolean {
|
|
375
|
+
if (!snapshotCurrent && evidence.requested === 0) return false;
|
|
376
|
+
if (evidence.requested === 0) return !hasDiagnosticEntries;
|
|
377
|
+
return (
|
|
378
|
+
evidence.confirmed === evidence.requested &&
|
|
379
|
+
evidence.unconfirmed === 0 &&
|
|
380
|
+
evidence.failed === 0 &&
|
|
381
|
+
evidence.removed === 0
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function diagnosticEvidenceReason(evidence: DiagnosticEvidenceSummary): string {
|
|
386
|
+
return `Diagnostic evidence is partial: ${evidence.requested} requested, ${evidence.confirmed} confirmed, ${evidence.unconfirmed} unconfirmed, ${evidence.failed} failed, ${evidence.removed} removed.`;
|
|
387
|
+
}
|
|
388
|
+
|
|
177
389
|
export function isDirectory(filePath: string): boolean {
|
|
178
390
|
try {
|
|
179
391
|
return statSync(filePath).isDirectory();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Recovery and state description helpers for code_health.
|
|
2
2
|
// Extracted from orchestrate.ts.
|
|
3
3
|
|
|
4
|
-
import type { CapabilityState } from "@mrclrchtr/supi-code-runtime/api";
|
|
4
|
+
import type { CapabilityState, CodeRequestControl } from "@mrclrchtr/supi-code-runtime/api";
|
|
5
5
|
import type { RecoverDiagnosticsResult, WorkspaceLspRuntime } from "@mrclrchtr/supi-lsp/api";
|
|
6
6
|
|
|
7
7
|
// ── Recovery ──────────────────────────────────────────────────────────
|
|
@@ -9,6 +9,7 @@ import type { RecoverDiagnosticsResult, WorkspaceLspRuntime } from "@mrclrchtr/s
|
|
|
9
9
|
interface RecoverOptions {
|
|
10
10
|
service: WorkspaceLspRuntime;
|
|
11
11
|
progress?: () => void;
|
|
12
|
+
control?: CodeRequestControl;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
/** Run the runtime's best-effort recovery and preserve its established outcome. */
|
|
@@ -16,7 +17,10 @@ export async function recoverDiagnosticRuntime(
|
|
|
16
17
|
opts: RecoverOptions,
|
|
17
18
|
): Promise<RecoverDiagnosticsResult> {
|
|
18
19
|
opts.progress?.();
|
|
19
|
-
return opts.service.recoverDiagnostics({
|
|
20
|
+
return opts.service.recoverDiagnostics({
|
|
21
|
+
restartIfStillStale: true,
|
|
22
|
+
control: opts.control,
|
|
23
|
+
});
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
// ── State description helpers ─────────────────────────────────────────
|
package/src/analysis/provider.ts
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import {
|
|
14
|
+
type CodeRequestControl,
|
|
14
15
|
getDefaultWorkspaceRuntime,
|
|
15
16
|
type SemanticProvider,
|
|
16
17
|
type StructuralProvider,
|
|
@@ -85,6 +86,54 @@ export function getCodeProviderState(cwd: string): CodeProviderState {
|
|
|
85
86
|
/** Alias for getCodeProviderState — kept for backward compatibility. */
|
|
86
87
|
export const getCodeProvider = getCodeProviderState;
|
|
87
88
|
|
|
89
|
+
/** Bind one exact request-control value to every semantic provider operation. */
|
|
90
|
+
export function withSemanticRequestControl<T extends SemanticProvider>(
|
|
91
|
+
provider: T | null,
|
|
92
|
+
control: CodeRequestControl | undefined,
|
|
93
|
+
): T | null {
|
|
94
|
+
if (!provider || !control) return provider;
|
|
95
|
+
return {
|
|
96
|
+
...provider,
|
|
97
|
+
references: (file, position) => provider.references(file, position, control),
|
|
98
|
+
implementation: (file, position) => provider.implementation(file, position, control),
|
|
99
|
+
documentSymbols: (file) => provider.documentSymbols(file, control),
|
|
100
|
+
workspaceSymbols: (query) => provider.workspaceSymbols(query, control),
|
|
101
|
+
hover: provider.hover
|
|
102
|
+
? (file, position) => provider.hover?.(file, position, control)
|
|
103
|
+
: undefined,
|
|
104
|
+
definition: provider.definition
|
|
105
|
+
? (file, position) => provider.definition?.(file, position, control)
|
|
106
|
+
: undefined,
|
|
107
|
+
refactor: provider.refactor ? (request) => provider.refactor?.(request, control) : undefined,
|
|
108
|
+
rename: provider.rename
|
|
109
|
+
? (file, position, newName) => provider.rename?.(file, position, newName, control)
|
|
110
|
+
: undefined,
|
|
111
|
+
codeActions: provider.codeActions
|
|
112
|
+
? (file, position) => provider.codeActions?.(file, position, control)
|
|
113
|
+
: undefined,
|
|
114
|
+
} as T;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Bind one exact request-control value to every structural provider operation. */
|
|
118
|
+
export function withStructuralRequestControl<T extends StructuralProvider>(
|
|
119
|
+
provider: T | null,
|
|
120
|
+
control: CodeRequestControl | undefined,
|
|
121
|
+
): T | null {
|
|
122
|
+
if (!provider || !control) return provider;
|
|
123
|
+
return {
|
|
124
|
+
...provider,
|
|
125
|
+
calleesAt: (file, line, character, depthOrOptions) => {
|
|
126
|
+
const depth = typeof depthOrOptions === "string" ? depthOrOptions : depthOrOptions?.depth;
|
|
127
|
+
return provider.calleesAt(file, line, character, { depth, control });
|
|
128
|
+
},
|
|
129
|
+
exports: (file) => provider.exports(file, control),
|
|
130
|
+
outline: (file) => provider.outline(file, control),
|
|
131
|
+
imports: (file) => provider.imports(file, control),
|
|
132
|
+
nodeAt: (file, line, character) => provider.nodeAt(file, line, character, control),
|
|
133
|
+
callSites: (file) => provider.callSites(file, control),
|
|
134
|
+
} as T;
|
|
135
|
+
}
|
|
136
|
+
|
|
88
137
|
/**
|
|
89
138
|
* Create a single CodeProvider that delegates semantic methods to the
|
|
90
139
|
* semantic (LSP) provider and structural methods to the structural
|
|
@@ -138,6 +187,15 @@ function createCompositeProvider(
|
|
|
138
187
|
semantic?.definition?.(...args) ?? unavailableCodeQuery("Semantic definition unavailable")
|
|
139
188
|
);
|
|
140
189
|
},
|
|
190
|
+
async refactor(...args: Parameters<NonNullable<SemanticProvider["refactor"]>>) {
|
|
191
|
+
const result = await semantic?.refactor?.(...args);
|
|
192
|
+
return (
|
|
193
|
+
result ?? {
|
|
194
|
+
kind: "unavailable" as const,
|
|
195
|
+
reason: "Refactor not available",
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
},
|
|
141
199
|
async codeActions(...args: Parameters<NonNullable<SemanticProvider["codeActions"]>>) {
|
|
142
200
|
return semantic?.codeActions?.(...args) ?? [];
|
|
143
201
|
},
|