@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.
Files changed (215) hide show
  1. package/README.md +2 -1
  2. package/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
  3. package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  4. package/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
  5. package/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
  6. package/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
  7. package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
  8. package/node_modules/@mrclrchtr/supi-core/README.md +2 -0
  9. package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  10. package/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
  11. package/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
  12. package/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
  13. package/node_modules/@mrclrchtr/supi-core/src/debug-timing.ts +34 -21
  14. package/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
  15. package/node_modules/@mrclrchtr/supi-lsp/README.md +80 -5
  16. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
  17. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  18. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
  19. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
  20. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
  21. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
  22. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +2 -0
  23. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  24. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
  25. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
  26. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
  27. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-timing.ts +34 -21
  28. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
  29. package/node_modules/@mrclrchtr/supi-lsp/package.json +7 -6
  30. package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +10 -0
  31. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-cache.ts +206 -0
  32. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-capabilities.ts +78 -0
  33. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-collection.ts +114 -0
  34. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-evidence.ts +372 -0
  35. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-host.ts +14 -0
  36. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-pull.ts +62 -0
  37. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-refresh.ts +491 -0
  38. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-request.ts +9 -0
  39. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-timing.ts +215 -0
  40. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-waiters.ts +206 -0
  41. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostics.ts +370 -266
  42. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-state.ts +52 -0
  43. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-sync.ts +185 -0
  44. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-file-state.ts +25 -0
  45. package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +467 -115
  46. package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +238 -11
  47. package/node_modules/@mrclrchtr/supi-lsp/src/config/capabilities.ts +10 -1
  48. package/node_modules/@mrclrchtr/supi-lsp/src/config/defaults.json +1 -1
  49. package/node_modules/@mrclrchtr/supi-lsp/src/debug-telemetry.ts +45 -0
  50. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/evidence.ts +38 -0
  51. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-client-state.ts +79 -9
  52. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +13 -4
  53. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +300 -24
  54. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-symbol.ts +5 -2
  55. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +464 -96
  56. package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-refactor-provider.ts +130 -0
  57. package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +45 -329
  58. package/node_modules/@mrclrchtr/supi-lsp/src/provider/refactor-planning.ts +57 -120
  59. package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-edit-normalizer.ts +320 -0
  60. package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-symbol-mapper.ts +207 -0
  61. package/node_modules/@mrclrchtr/supi-lsp/src/session/readiness.ts +72 -2
  62. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-controller.ts +151 -26
  63. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostic-surface.ts +40 -0
  64. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostics.ts +50 -0
  65. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registry.ts +136 -120
  66. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-transition-debug.ts +49 -0
  67. package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +102 -0
  68. package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +26 -6
  69. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
  70. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  71. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
  72. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
  73. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
  74. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
  75. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +2 -0
  76. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  77. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
  78. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
  79. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
  80. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-timing.ts +34 -21
  81. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
  82. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/LICENSE +21 -0
  83. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/README.md +258 -0
  84. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/babel.cjs +257 -0
  85. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/jiti.cjs +1 -0
  86. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-cli.mjs +34 -0
  87. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-hooks.mjs +124 -0
  88. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-native.mjs +121 -0
  89. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.d.mts +1 -0
  90. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.mjs +4 -0
  91. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-static.mjs +23 -0
  92. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.cjs +30 -0
  93. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.cts +8 -0
  94. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.mts +8 -0
  95. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.mjs +29 -0
  96. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/types.d.ts +420 -0
  97. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/package.json +146 -0
  98. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm +0 -0
  99. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm.map +4 -4
  100. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/package.json +1 -1
  101. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm +0 -0
  102. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm.map +4 -4
  103. package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +7 -3
  104. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/kotlin/tree-sitter-kotlin.wasm.json +1 -1
  105. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/sql/tree-sitter-sql.wasm.json +1 -1
  106. package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +0 -9
  107. package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +0 -8
  108. package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +16 -12
  109. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-controller.ts +65 -87
  110. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +47 -95
  111. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-timing.ts +147 -0
  112. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client-lifecycle.ts +39 -0
  113. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client.ts +561 -0
  114. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-message-size.ts +24 -0
  115. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-protocol.ts +452 -0
  116. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-sites.ts +4 -2
  117. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +12 -4
  118. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/exports.ts +4 -2
  119. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/imports.ts +4 -2
  120. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/node-at.ts +5 -3
  121. package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +33 -12
  122. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/blocking-test-bootstrap.mjs +34 -0
  123. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/bootstrap.mjs +8 -0
  124. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store-helpers.ts +23 -0
  125. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store.ts +400 -0
  126. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/request-control.ts +48 -0
  127. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-parser-helpers.ts +24 -0
  128. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-query-helpers.ts +43 -0
  129. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime.ts +421 -0
  130. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/service.ts +116 -0
  131. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/worker-main.ts +201 -0
  132. package/package.json +5 -5
  133. package/src/analysis/health/diagnostics.ts +236 -24
  134. package/src/analysis/health/recovery.ts +6 -2
  135. package/src/analysis/provider.ts +58 -0
  136. package/src/analysis/readiness.ts +30 -9
  137. package/src/analysis/refactor/apply.ts +59 -20
  138. package/src/analysis/refactor/mutation-authority.ts +143 -0
  139. package/src/analysis/refactor/position.ts +47 -0
  140. package/src/analysis/refactor/safety.ts +18 -10
  141. package/src/analysis/relations/callees.ts +9 -1
  142. package/src/analysis/relations/types.ts +5 -2
  143. package/src/analysis/search/ast-scan-timing.ts +9 -4
  144. package/src/analysis/search/ast-scan.ts +1 -1
  145. package/src/analysis/search/deadline.ts +2 -2
  146. package/src/analysis/search/pattern-analysis.ts +46 -32
  147. package/src/analysis/search/pattern.ts +12 -2
  148. package/src/analysis/target/anchored.ts +20 -11
  149. package/src/analysis/target/file.ts +18 -11
  150. package/src/analysis/target/identity.ts +19 -3
  151. package/src/analysis/target/symbol.ts +36 -15
  152. package/src/api.ts +4 -0
  153. package/src/diagnostics/evidence.ts +51 -0
  154. package/src/session/capability-adapter.ts +12 -3
  155. package/src/session/find-workflow.ts +17 -7
  156. package/src/session/graph/collect.ts +18 -2
  157. package/src/session/graph-workflow.ts +19 -12
  158. package/src/session/health-refresh.ts +148 -0
  159. package/src/session/health-types.ts +37 -15
  160. package/src/session/health-workflow.ts +37 -39
  161. package/src/session/inspect/collect.ts +20 -3
  162. package/src/session/inspect-workflow.ts +10 -5
  163. package/src/session/orientation/collect.ts +10 -1
  164. package/src/session/orientation/context-facts.ts +3 -1
  165. package/src/session/orientation/context-sections.ts +20 -7
  166. package/src/session/orientation/gather.ts +17 -11
  167. package/src/session/orientation-types.ts +2 -1
  168. package/src/session/orientation-workflow.ts +15 -8
  169. package/src/session/refactor-plans.ts +2 -0
  170. package/src/session/refactor-workflow.ts +59 -14
  171. package/src/session/session.ts +4 -1
  172. package/src/session/target-workflow.ts +54 -23
  173. package/src/session/workflow-control.ts +7 -3
  174. package/src/substrate/lsp/lifecycle.ts +26 -46
  175. package/src/substrate/lsp/maintenance.ts +199 -25
  176. package/src/substrate/lsp/state.ts +2 -2
  177. package/src/substrate/workspace-provider-host.ts +25 -3
  178. package/src/tool/find/execute.ts +7 -1
  179. package/src/tool/find/render.ts +20 -3
  180. package/src/tool/find/tui.ts +23 -21
  181. package/src/tool/graph/execute.ts +23 -3
  182. package/src/tool/graph/tui.ts +59 -46
  183. package/src/tool/health/execute.ts +7 -2
  184. package/src/tool/health/markdown.ts +56 -14
  185. package/src/tool/health/refresh-status.ts +105 -0
  186. package/src/tool/health/tui.ts +95 -98
  187. package/src/tool/infra/workflow-control.ts +8 -0
  188. package/src/tool/inspect/execute.ts +7 -1
  189. package/src/tool/inspect/tui.ts +26 -18
  190. package/src/tool/orientation/execute.ts +21 -3
  191. package/src/tool/orientation/tui.ts +51 -35
  192. package/src/tool/refactor-apply/execute.ts +3 -0
  193. package/src/tool/refactor-apply/tui.ts +43 -25
  194. package/src/tool/refactor-plan/execute.ts +4 -0
  195. package/src/tool/refactor-plan/tui.ts +33 -20
  196. package/src/tool/register.ts +127 -22
  197. package/src/tool/resolve/execute.ts +18 -1
  198. package/src/tool/resolve/tui.ts +42 -24
  199. package/src/tool/result/display.ts +107 -0
  200. package/src/tool/result/errors.ts +20 -17
  201. package/src/tool/result/find.ts +52 -8
  202. package/src/tool/result/graph.ts +44 -1
  203. package/src/tool/result/health.ts +53 -1
  204. package/src/tool/result/inspect.ts +113 -1
  205. package/src/tool/result/orientation.ts +66 -14
  206. package/src/tool/result/refactor.ts +36 -4
  207. package/src/tool/result/resolve.ts +44 -7
  208. package/src/tool/result/types.ts +20 -0
  209. package/src/types/execution.ts +18 -5
  210. package/src/types/index.ts +8 -1
  211. package/src/ui/status-command.ts +5 -3
  212. package/src/ui/status-overlay.ts +4 -0
  213. package/src/ui/tui/common.ts +108 -10
  214. package/src/ui/tui/display.ts +48 -0
  215. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime.ts +0 -247
@@ -0,0 +1,452 @@
1
+ // biome-ignore-all lint/style/noExcessiveLinesPerFile: one private protocol module defines and validates the full closed contract
2
+ import type { CodeRequestControl } from "@mrclrchtr/supi-code-runtime/api";
3
+ import { isDebugOperationId } from "@mrclrchtr/supi-core/debug";
4
+ import type { TreeSitterResult } from "../types.ts";
5
+ import type { StructuralTimingEvent } from "./structural-timing.ts";
6
+
7
+ /** Version of the private parent/Structural Worker message contract. */
8
+ export const STRUCTURAL_WORKER_PROTOCOL_VERSION = 1 as const;
9
+
10
+ /** Fixed internal bounds for one Structural Worker lifecycle. */
11
+ export const STRUCTURAL_WORKER_LIMITS = Object.freeze({
12
+ maxQueuedRequests: 32,
13
+ maxMessageBytes: 512 * 1024,
14
+ targetChunkBytes: 256 * 1024,
15
+ maxResultBytes: 16 * 1024 * 1024,
16
+ maxAtomicValueBytes: 256 * 1024,
17
+ hardStopGraceMs: 250,
18
+ });
19
+
20
+ export type StructuralWorkerOperation =
21
+ | { readonly operation: "canParse"; readonly file: string }
22
+ | { readonly operation: "query"; readonly file: string; readonly query: string }
23
+ | {
24
+ readonly operation: "outline" | "imports" | "exports" | "callSites";
25
+ readonly file: string;
26
+ }
27
+ | {
28
+ readonly operation: "nodeAt";
29
+ readonly file: string;
30
+ readonly line: number;
31
+ readonly character: number;
32
+ }
33
+ | {
34
+ readonly operation: "calleesAt";
35
+ readonly file: string;
36
+ readonly line: number;
37
+ readonly character: number;
38
+ readonly depth?: "direct" | "deep";
39
+ };
40
+
41
+ export interface StructuralWorkerRequestMessage {
42
+ readonly kind: "request";
43
+ readonly version: typeof STRUCTURAL_WORKER_PROTOCOL_VERSION;
44
+ readonly generation: number;
45
+ readonly requestId: string;
46
+ readonly input: StructuralWorkerOperation;
47
+ readonly operationId?: string;
48
+ readonly deadline?: number;
49
+ readonly cancellationFlag: SharedArrayBuffer;
50
+ }
51
+
52
+ export interface StructuralWorkerCancelMessage {
53
+ readonly kind: "cancel";
54
+ readonly version: typeof STRUCTURAL_WORKER_PROTOCOL_VERSION;
55
+ readonly generation: number;
56
+ readonly requestId: string;
57
+ }
58
+
59
+ export interface StructuralWorkerChunkAckMessage {
60
+ readonly kind: "chunk-ack";
61
+ readonly version: typeof STRUCTURAL_WORKER_PROTOCOL_VERSION;
62
+ readonly generation: number;
63
+ readonly requestId: string;
64
+ readonly sequence: number;
65
+ }
66
+
67
+ export type ParentToStructuralWorkerMessage =
68
+ | StructuralWorkerRequestMessage
69
+ | StructuralWorkerCancelMessage
70
+ | StructuralWorkerChunkAckMessage;
71
+
72
+ export interface StructuralWorkerReadyMessage {
73
+ readonly kind: "ready";
74
+ readonly version: typeof STRUCTURAL_WORKER_PROTOCOL_VERSION;
75
+ readonly generation: number;
76
+ }
77
+
78
+ export interface StructuralWorkerStartupFailureMessage {
79
+ readonly kind: "startup-failure";
80
+ readonly version: typeof STRUCTURAL_WORKER_PROTOCOL_VERSION;
81
+ readonly generation: number;
82
+ readonly message: string;
83
+ }
84
+
85
+ export interface StructuralWorkerChunkMessage {
86
+ readonly kind: "chunk";
87
+ readonly version: typeof STRUCTURAL_WORKER_PROTOCOL_VERSION;
88
+ readonly generation: number;
89
+ readonly requestId: string;
90
+ readonly sequence: number;
91
+ readonly final: boolean;
92
+ readonly encodedBytes: number;
93
+ readonly payload: Uint8Array;
94
+ }
95
+
96
+ export interface StructuralWorkerObservationMessage {
97
+ readonly kind: "observation";
98
+ readonly version: typeof STRUCTURAL_WORKER_PROTOCOL_VERSION;
99
+ readonly generation: number;
100
+ readonly requestId: string;
101
+ readonly observation: StructuralTimingEvent;
102
+ }
103
+
104
+ export interface StructuralWorkerTerminalMessage {
105
+ readonly kind: "terminal";
106
+ readonly version: typeof STRUCTURAL_WORKER_PROTOCOL_VERSION;
107
+ readonly generation: number;
108
+ readonly requestId: string;
109
+ readonly outcome: "completed" | "cancelled" | "timeout";
110
+ }
111
+
112
+ export type StructuralWorkerToParentMessage =
113
+ | StructuralWorkerReadyMessage
114
+ | StructuralWorkerStartupFailureMessage
115
+ | StructuralWorkerChunkMessage
116
+ | StructuralWorkerObservationMessage
117
+ | StructuralWorkerTerminalMessage;
118
+
119
+ export type StructuralProtocolValidation<T> =
120
+ | { readonly kind: "valid"; readonly message: T }
121
+ | { readonly kind: "invalid"; readonly reason: string };
122
+
123
+ /** Validate an untrusted request before the Structural Worker executes it. */
124
+ export function validateStructuralWorkerRequest(
125
+ value: unknown,
126
+ ): StructuralProtocolValidation<StructuralWorkerRequestMessage> {
127
+ if (!isRecord(value)) return invalid("Structural Worker request must be an object");
128
+ const required = ["kind", "version", "generation", "requestId", "input", "cancellationFlag"];
129
+ const allowed = new Set([...required, "operationId", "deadline"]);
130
+ if (
131
+ required.some((key) => !(key in value)) ||
132
+ Object.keys(value).some((key) => !allowed.has(key))
133
+ ) {
134
+ return invalid("Invalid structural request envelope");
135
+ }
136
+ if (
137
+ value.kind !== "request" ||
138
+ value.version !== STRUCTURAL_WORKER_PROTOCOL_VERSION ||
139
+ !isPositiveInteger(value.generation) ||
140
+ !isRequestId(value.requestId) ||
141
+ !isRecord(value.input) ||
142
+ !(value.cancellationFlag instanceof SharedArrayBuffer) ||
143
+ value.cancellationFlag.byteLength !== Int32Array.BYTES_PER_ELEMENT ||
144
+ (value.deadline !== undefined &&
145
+ (typeof value.deadline !== "number" || !Number.isFinite(value.deadline))) ||
146
+ (value.operationId !== undefined && !isDebugOperationId(value.operationId))
147
+ ) {
148
+ return invalid("Invalid structural request");
149
+ }
150
+ return valid(value as unknown as StructuralWorkerRequestMessage);
151
+ }
152
+
153
+ /** Encode one complete structural result into fixed-size binary chunks. */
154
+ export function encodeStructuralResult(result: TreeSitterResult<unknown>): Uint8Array[] {
155
+ assertPlainProtocolValue(result);
156
+ const bytes = Buffer.from(JSON.stringify(result), "utf8");
157
+ if (bytes.byteLength > STRUCTURAL_WORKER_LIMITS.maxResultBytes) {
158
+ throw new Error(
159
+ `Structural result exceeds the ${STRUCTURAL_WORKER_LIMITS.maxResultBytes}-byte limit`,
160
+ );
161
+ }
162
+ const chunks: Uint8Array[] = [];
163
+ for (
164
+ let offset = 0;
165
+ offset < bytes.byteLength;
166
+ offset += STRUCTURAL_WORKER_LIMITS.targetChunkBytes
167
+ ) {
168
+ const end = Math.min(offset + STRUCTURAL_WORKER_LIMITS.targetChunkBytes, bytes.byteLength);
169
+ chunks.push(Uint8Array.from(bytes.subarray(offset, end)));
170
+ }
171
+ return chunks.length > 0 ? chunks : [new Uint8Array()];
172
+ }
173
+
174
+ /** Reconstruct one complete structural result from validated binary chunks. */
175
+ export function decodeStructuralResult<T>(chunks: readonly Uint8Array[]): TreeSitterResult<T> {
176
+ const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
177
+ if (total > STRUCTURAL_WORKER_LIMITS.maxResultBytes) {
178
+ throw new Error(
179
+ `Structural result exceeds the ${STRUCTURAL_WORKER_LIMITS.maxResultBytes}-byte limit`,
180
+ );
181
+ }
182
+ const parsed: unknown = JSON.parse(
183
+ Buffer.concat(
184
+ chunks.map((chunk) => Buffer.from(chunk)),
185
+ total,
186
+ ).toString("utf8"),
187
+ );
188
+ assertTreeSitterResult(parsed);
189
+ return parsed as TreeSitterResult<T>;
190
+ }
191
+
192
+ /** Validate an untrusted message received from a Structural Worker. */
193
+ export function validateWorkerToParentMessage(
194
+ value: unknown,
195
+ ): StructuralProtocolValidation<StructuralWorkerToParentMessage> {
196
+ if (!isRecord(value)) return invalid("Structural Worker message must be an object");
197
+ if (value.version !== STRUCTURAL_WORKER_PROTOCOL_VERSION) {
198
+ return invalid("Unsupported Structural Worker protocol version");
199
+ }
200
+ if (!isPositiveInteger(value.generation)) return invalid("Invalid Worker generation");
201
+ switch (value.kind) {
202
+ case "ready":
203
+ return hasExactKeys(value, ["kind", "version", "generation"])
204
+ ? valid(value as unknown as StructuralWorkerReadyMessage)
205
+ : invalid("Invalid ready message");
206
+ case "startup-failure":
207
+ return hasExactKeys(value, ["kind", "version", "generation", "message"]) &&
208
+ isBoundedString(value.message, 1_024)
209
+ ? valid(value as unknown as StructuralWorkerStartupFailureMessage)
210
+ : invalid("Invalid startup failure");
211
+ case "chunk":
212
+ return validateChunk(value);
213
+ case "observation":
214
+ return validateObservation(value);
215
+ case "terminal":
216
+ return validateTerminal(value);
217
+ default:
218
+ return invalid("Unknown Structural Worker message kind");
219
+ }
220
+ }
221
+
222
+ /** Build the exact request control represented by one Worker request. */
223
+ export interface StructuralWorkerRequestControl extends CodeRequestControl {
224
+ readonly cancellationFlag: Int32Array;
225
+ }
226
+
227
+ function validateChunk(
228
+ value: Record<string, unknown>,
229
+ ): StructuralProtocolValidation<StructuralWorkerChunkMessage> {
230
+ if (
231
+ !hasExactKeys(value, [
232
+ "kind",
233
+ "version",
234
+ "generation",
235
+ "requestId",
236
+ "sequence",
237
+ "final",
238
+ "encodedBytes",
239
+ "payload",
240
+ ])
241
+ ) {
242
+ return invalid("Invalid chunk envelope");
243
+ }
244
+ if (!isRequestId(value.requestId)) return invalid("Invalid request id");
245
+ if (!Number.isSafeInteger(value.sequence) || Number(value.sequence) < 0) {
246
+ return invalid("Invalid chunk sequence");
247
+ }
248
+ if (typeof value.final !== "boolean") return invalid("Invalid final chunk marker");
249
+ if (!(value.payload instanceof Uint8Array)) return invalid("Invalid chunk payload");
250
+ if (value.encodedBytes !== value.payload.byteLength) return invalid("Invalid chunk byte count");
251
+ if (value.payload.byteLength > STRUCTURAL_WORKER_LIMITS.targetChunkBytes) {
252
+ return invalid("Structural Worker chunk exceeds the byte limit");
253
+ }
254
+ if (
255
+ estimateChunkMessageBytes(value.payload.byteLength) > STRUCTURAL_WORKER_LIMITS.maxMessageBytes
256
+ ) {
257
+ return invalid("Structural Worker message exceeds the byte limit");
258
+ }
259
+ return valid(value as unknown as StructuralWorkerChunkMessage);
260
+ }
261
+
262
+ function validateObservation(
263
+ value: Record<string, unknown>,
264
+ ): StructuralProtocolValidation<StructuralWorkerObservationMessage> {
265
+ if (!hasExactKeys(value, ["kind", "version", "generation", "requestId", "observation"])) {
266
+ return invalid("Invalid observation envelope");
267
+ }
268
+ if (!isRequestId(value.requestId)) return invalid("Invalid request id");
269
+ if (!isStructuralTimingEvent(value.observation)) return invalid("Invalid structural observation");
270
+ return valid(value as unknown as StructuralWorkerObservationMessage);
271
+ }
272
+
273
+ function validateTerminal(
274
+ value: Record<string, unknown>,
275
+ ): StructuralProtocolValidation<StructuralWorkerTerminalMessage> {
276
+ if (!hasExactKeys(value, ["kind", "version", "generation", "requestId", "outcome"])) {
277
+ return invalid("Invalid terminal envelope");
278
+ }
279
+ if (!isRequestId(value.requestId)) return invalid("Invalid request id");
280
+ if (
281
+ value.outcome !== "completed" &&
282
+ value.outcome !== "cancelled" &&
283
+ value.outcome !== "timeout"
284
+ ) {
285
+ return invalid("Invalid terminal outcome");
286
+ }
287
+ return valid(value as unknown as StructuralWorkerTerminalMessage);
288
+ }
289
+
290
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: every sanitized nested timing field is validated at one trust boundary
291
+ function isStructuralTimingEvent(value: unknown): value is StructuralTimingEvent {
292
+ if (!isRecord(value) || !isRecord(value.data) || !isRecord(value.data.timing)) return false;
293
+ const expected =
294
+ value.operationId === undefined
295
+ ? ["source", "level", "category", "message", "data"]
296
+ : ["operationId", "source", "level", "category", "message", "data"];
297
+ if (!hasExactKeys(value, expected)) return false;
298
+ if (value.operationId !== undefined && !isDebugOperationId(value.operationId)) return false;
299
+ if (value.source !== "tree-sitter" || value.level !== "debug") return false;
300
+ if (
301
+ value.category !== "structural.parse.timing" &&
302
+ value.category !== "structural.query.timing"
303
+ ) {
304
+ return false;
305
+ }
306
+ if (
307
+ !isBoundedString(value.message, 96) ||
308
+ !/^Tree-sitter (?:parse|query) [a-z-]+$/.test(value.message)
309
+ ) {
310
+ return false;
311
+ }
312
+ if (!isGrammar(value.data.grammar)) return false;
313
+ if (value.data.cache !== undefined && !isCacheObservation(value.data.cache)) return false;
314
+ const timing = value.data.timing;
315
+ if (!hasExactKeys(timing, ["durationMs", "phasesMs"]) || !isFiniteDuration(timing.durationMs)) {
316
+ return false;
317
+ }
318
+ if (!isRecord(timing.phasesMs) || Object.keys(timing.phasesMs).length > 8) return false;
319
+ if (
320
+ Object.entries(timing.phasesMs).some(
321
+ ([phase, duration]) => !/^[a-z-]{1,32}$/.test(phase) || !isFiniteDuration(duration),
322
+ )
323
+ ) {
324
+ return false;
325
+ }
326
+ return value.category === "structural.parse.timing"
327
+ ? isParseTimingData(value.data)
328
+ : isQueryTimingData(value.data);
329
+ }
330
+
331
+ function assertTreeSitterResult(value: unknown): asserts value is TreeSitterResult<unknown> {
332
+ if (!isRecord(value) || typeof value.kind !== "string")
333
+ throw new Error("Invalid structural result");
334
+ if (value.kind === "success" && "data" in value) return;
335
+ if (
336
+ value.kind === "unsupported-language" ||
337
+ value.kind === "file-access-error" ||
338
+ value.kind === "validation-error" ||
339
+ value.kind === "runtime-error"
340
+ ) {
341
+ if (typeof value.message === "string") return;
342
+ }
343
+ throw new Error("Invalid structural result");
344
+ }
345
+
346
+ function assertPlainProtocolValue(value: unknown, seen = new Set<object>()): void {
347
+ if (value === null || typeof value === "string" || typeof value === "boolean") return;
348
+ if (typeof value === "number") {
349
+ if (!Number.isFinite(value)) throw new Error("Structural result contains a non-finite number");
350
+ return;
351
+ }
352
+ if (typeof value !== "object") throw new Error("Structural result contains an unsupported value");
353
+ if (seen.has(value)) throw new Error("Structural result contains a cycle");
354
+ seen.add(value);
355
+ if (Array.isArray(value)) {
356
+ for (const item of value) assertPlainProtocolValue(item, seen);
357
+ seen.delete(value);
358
+ return;
359
+ }
360
+ if (Object.getPrototypeOf(value) !== Object.prototype) {
361
+ const size = Buffer.byteLength(JSON.stringify(value) ?? "", "utf8");
362
+ if (size > STRUCTURAL_WORKER_LIMITS.maxAtomicValueBytes) {
363
+ throw new Error("Structural result contains an oversize indivisible value");
364
+ }
365
+ throw new Error("Structural result contains a non-plain value");
366
+ }
367
+ for (const item of Object.values(value)) assertPlainProtocolValue(item, seen);
368
+ seen.delete(value);
369
+ }
370
+
371
+ function isParseTimingData(data: Record<string, unknown>): boolean {
372
+ const expected =
373
+ data.cache === undefined
374
+ ? ["operation", "grammar", "parserState", "outcome", "timing"]
375
+ : ["operation", "grammar", "parserState", "outcome", "cache", "timing"];
376
+ if (!hasExactKeys(data, expected)) return false;
377
+ return (
378
+ data.operation === "parse" &&
379
+ (data.parserState === "cold" ||
380
+ data.parserState === "initializing" ||
381
+ data.parserState === "reused") &&
382
+ ["cancelled", "completed", "file-access-error", "runtime-error", "timeout"].includes(
383
+ String(data.outcome),
384
+ )
385
+ );
386
+ }
387
+
388
+ function isQueryTimingData(data: Record<string, unknown>): boolean {
389
+ if (!hasExactKeys(data, ["operation", "grammar", "outcome", "captureCount", "cache", "timing"])) {
390
+ return false;
391
+ }
392
+ return (
393
+ data.operation === "query" &&
394
+ Number.isSafeInteger(data.captureCount) &&
395
+ Number(data.captureCount) >= 0 &&
396
+ ["cancelled", "completed", "runtime-error", "timeout", "validation-error"].includes(
397
+ String(data.outcome),
398
+ )
399
+ );
400
+ }
401
+
402
+ function isCacheObservation(value: unknown): boolean {
403
+ return (
404
+ isRecord(value) &&
405
+ hasExactKeys(value, ["state", "retained", "evictionCount"]) &&
406
+ (value.state === "hit" || value.state === "miss" || value.state === "replacement") &&
407
+ typeof value.retained === "boolean" &&
408
+ Number.isSafeInteger(value.evictionCount) &&
409
+ Number(value.evictionCount) >= 0
410
+ );
411
+ }
412
+
413
+ function isGrammar(value: unknown): boolean {
414
+ return isBoundedString(value, 16) && /^[a-z]+$/.test(value);
415
+ }
416
+
417
+ function isFiniteDuration(value: unknown): boolean {
418
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
419
+ }
420
+
421
+ function hasExactKeys(value: Record<string, unknown>, expected: readonly string[]): boolean {
422
+ const actual = Object.keys(value).sort();
423
+ return actual.length === expected.length && expected.every((key) => actual.includes(key));
424
+ }
425
+
426
+ function isBoundedString(value: unknown, maxLength: number): value is string {
427
+ return typeof value === "string" && value.length > 0 && value.length <= maxLength;
428
+ }
429
+
430
+ function estimateChunkMessageBytes(payloadBytes: number): number {
431
+ return payloadBytes + 1024;
432
+ }
433
+
434
+ function isRecord(value: unknown): value is Record<string, unknown> {
435
+ return typeof value === "object" && value !== null && !Array.isArray(value);
436
+ }
437
+
438
+ function isPositiveInteger(value: unknown): value is number {
439
+ return Number.isSafeInteger(value) && Number(value) > 0;
440
+ }
441
+
442
+ function isRequestId(value: unknown): value is string {
443
+ return typeof value === "string" && value.length > 0 && value.length <= 128;
444
+ }
445
+
446
+ function valid<T>(message: T): StructuralProtocolValidation<T> {
447
+ return { kind: "valid", message };
448
+ }
449
+
450
+ function invalid(reason: string): StructuralProtocolValidation<never> {
451
+ return { kind: "invalid", reason };
452
+ }
@@ -1,8 +1,9 @@
1
1
  /** File-wide call-site extraction using per-grammar tree-sitter queries. */
2
2
 
3
+ import type { CodeRequestControl } from "@mrclrchtr/supi-code-runtime/api";
3
4
  import { detectGrammar } from "../language.ts";
4
- import type { TreeSitterRuntime } from "../session/runtime.ts";
5
5
  import type { CallSiteMatch, GrammarId, TreeSitterResult } from "../types.ts";
6
+ import type { TreeSitterRuntime } from "../worker/runtime.ts";
6
7
 
7
8
  // ── Per-grammar call-site queries ─────────────────────────────────────
8
9
 
@@ -48,6 +49,7 @@ export function supportsCallSitesGrammar(grammarId: GrammarId): boolean {
48
49
  export async function extractCallSites(
49
50
  runtime: TreeSitterRuntime,
50
51
  filePath: string,
52
+ control?: CodeRequestControl,
51
53
  ): Promise<TreeSitterResult<CallSiteMatch[]>> {
52
54
  const grammarId = detectGrammar(filePath);
53
55
  if (!grammarId) {
@@ -67,7 +69,7 @@ export async function extractCallSites(
67
69
  };
68
70
  }
69
71
 
70
- const queryResult = await runtime.queryFile(filePath, queryStr);
72
+ const queryResult = await runtime.queryFile(filePath, queryStr, control);
71
73
  if (queryResult.kind !== "success") return queryResult;
72
74
 
73
75
  const captures = queryResult.data;
@@ -1,8 +1,9 @@
1
1
  // Structural callee extraction — enclosing-scope lookup with per-language queries.
2
2
 
3
+ import type { CodeRequestControl } from "@mrclrchtr/supi-code-runtime/api";
3
4
  import { detectGrammar } from "../language.ts";
4
- import type { TreeSitterRuntime } from "../session/runtime.ts";
5
5
  import type { GrammarId, SourceRange, TreeSitterResult } from "../types.ts";
6
+ import { queryParsedFile, type TreeSitterRuntime } from "../worker/runtime.ts";
6
7
 
7
8
  /** Result shape returned by lookupCalleesAt. */
8
9
  export interface CalleesAtResult {
@@ -174,6 +175,7 @@ export async function lookupCalleesAt(
174
175
  line: number,
175
176
  character: number,
176
177
  depth: "direct" | "deep" = "direct",
178
+ control?: CodeRequestControl,
177
179
  ): Promise<TreeSitterResult<CalleesAtResult>> {
178
180
  // Validate coordinates and grammar
179
181
  const validation = validateCalleeInput(filePath, line, character);
@@ -181,10 +183,10 @@ export async function lookupCalleesAt(
181
183
  const { grammarId } = validation;
182
184
 
183
185
  // Parse the file
184
- const parseResult = await runtime.parseFile(filePath);
186
+ const parseResult = await runtime.parseFile(filePath, control);
185
187
  if (parseResult.kind !== "success") return parseResult;
186
188
 
187
- const { tree } = parseResult.data;
189
+ const { tree, source } = parseResult.data;
188
190
 
189
191
  try {
190
192
  const scopes = ENCLOSING_SCOPE_TYPES[grammarId];
@@ -214,7 +216,13 @@ export async function lookupCalleesAt(
214
216
  };
215
217
  }
216
218
 
217
- const queryResult = await runtime.queryFile(filePath, queryStr);
219
+ const queryResult = await queryParsedFile(runtime, {
220
+ grammarId,
221
+ tree,
222
+ source,
223
+ queryString: queryStr,
224
+ control,
225
+ });
218
226
  if (queryResult.kind !== "success") {
219
227
  return {
220
228
  kind: "runtime-error",
@@ -1,16 +1,18 @@
1
1
  // Export extraction for supported files.
2
2
 
3
+ import type { CodeRequestControl } from "@mrclrchtr/supi-code-runtime/api";
3
4
  import { nodeToRange } from "../coordinates.ts";
4
- import type { TreeSitterRuntime } from "../session/runtime.ts";
5
5
  import type { SyntaxNodeLike } from "../syntax-node.ts";
6
6
  import type { ExportRecord, TreeSitterResult } from "../types.ts";
7
+ import type { TreeSitterRuntime } from "../worker/runtime.ts";
7
8
 
8
9
  /** Extract export records from a supported file. */
9
10
  export async function extractExports(
10
11
  runtime: TreeSitterRuntime,
11
12
  filePath: string,
13
+ control?: CodeRequestControl,
12
14
  ): Promise<TreeSitterResult<ExportRecord[]>> {
13
- const parseResult = await runtime.parseFile(filePath);
15
+ const parseResult = await runtime.parseFile(filePath, control);
14
16
  if (parseResult.kind !== "success") return parseResult;
15
17
 
16
18
  const { tree, source } = parseResult.data;
@@ -1,16 +1,18 @@
1
1
  // Import extraction for supported files.
2
2
 
3
+ import type { CodeRequestControl } from "@mrclrchtr/supi-code-runtime/api";
3
4
  import { nodeToRange } from "../coordinates.ts";
4
- import type { TreeSitterRuntime } from "../session/runtime.ts";
5
5
  import type { SyntaxNodeLike } from "../syntax-node.ts";
6
6
  import type { ImportRecord, TreeSitterResult } from "../types.ts";
7
+ import type { TreeSitterRuntime } from "../worker/runtime.ts";
7
8
 
8
9
  /** Extract import records from a supported file. */
9
10
  export async function extractImports(
10
11
  runtime: TreeSitterRuntime,
11
12
  filePath: string,
13
+ control?: CodeRequestControl,
12
14
  ): Promise<TreeSitterResult<ImportRecord[]>> {
13
- const parseResult = await runtime.parseFile(filePath);
15
+ const parseResult = await runtime.parseFile(filePath, control);
14
16
  if (parseResult.kind !== "success") return parseResult;
15
17
 
16
18
  const { tree, source } = parseResult.data;
@@ -1,8 +1,9 @@
1
1
  // Node-at-position lookup.
2
2
 
3
+ import type { CodeRequestControl } from "@mrclrchtr/supi-code-runtime/api";
3
4
  import { nodeToRange, publicToTreeSitter, splitSourceLines } from "../coordinates.ts";
4
- import type { TreeSitterRuntime } from "../session/runtime.ts";
5
5
  import type { NodeAtResult, SourceRange, TreeSitterResult } from "../types.ts";
6
+ import type { TreeSitterRuntime } from "../worker/runtime.ts";
6
7
 
7
8
  const MAX_ANCESTRY = 10;
8
9
 
@@ -11,8 +12,9 @@ export async function lookupNodeAt(
11
12
  runtime: TreeSitterRuntime,
12
13
  filePath: string,
13
14
  line: number,
14
- character: number,
15
+ ...position: [character: number, control?: CodeRequestControl]
15
16
  ): Promise<TreeSitterResult<NodeAtResult>> {
17
+ const [character, control] = position;
16
18
  if (!Number.isInteger(line) || line < 1) {
17
19
  return { kind: "validation-error", message: "line must be a positive 1-based integer" };
18
20
  }
@@ -20,7 +22,7 @@ export async function lookupNodeAt(
20
22
  return { kind: "validation-error", message: "character must be a positive 1-based integer" };
21
23
  }
22
24
 
23
- const parseResult = await runtime.parseFile(filePath);
25
+ const parseResult = await runtime.parseFile(filePath, control);
24
26
  if (parseResult.kind !== "success") return parseResult;
25
27
 
26
28
  const { tree, source } = parseResult.data;
@@ -1,5 +1,7 @@
1
1
  // Public tree-sitter package types.
2
2
 
3
+ import type { CodeRequestControl } from "@mrclrchtr/supi-code-runtime/api";
4
+
3
5
  /** 1-based source range compatible with LSP position convention. */
4
6
  export interface SourceRange {
5
7
  startLine: number;
@@ -73,38 +75,57 @@ export interface CallSiteMatch {
73
75
  startLine: number;
74
76
  }
75
77
 
76
- /** Shared Tree-sitter service surface, independent of lifecycle ownership. */
78
+ /**
79
+ * Shared Tree-sitter service surface, independent of lifecycle ownership.
80
+ * Optional request control cooperatively stops reads, parser progress, query
81
+ * progress, and cache publication without exposing raw WASM resources.
82
+ */
77
83
  export interface TreeSitterService {
78
84
  /** Validate that a supported file can be read and parsed; does not expose the raw tree. */
79
- canParse(file: string): Promise<TreeSitterResult<{ file: string; language: string }>>;
85
+ canParse(
86
+ file: string,
87
+ control?: CodeRequestControl,
88
+ ): Promise<TreeSitterResult<{ file: string; language: string }>>;
80
89
  /** Run a Tree-sitter query and return all captures. */
81
- query(file: string, queryString: string): Promise<TreeSitterResult<QueryCapture[]>>;
90
+ query(
91
+ file: string,
92
+ queryString: string,
93
+ control?: CodeRequestControl,
94
+ ): Promise<TreeSitterResult<QueryCapture[]>>;
82
95
  /**
83
96
  * Extract shallow declarations, including supported nested code members,
84
97
  * HTML ids, and SQL schema members.
85
98
  */
86
- outline(file: string): Promise<TreeSitterResult<OutlineItem[]>>;
99
+ outline(file: string, control?: CodeRequestControl): Promise<TreeSitterResult<OutlineItem[]>>;
87
100
  /** Extract static ES import declarations. */
88
- imports(file: string): Promise<TreeSitterResult<ImportRecord[]>>;
101
+ imports(file: string, control?: CodeRequestControl): Promise<TreeSitterResult<ImportRecord[]>>;
89
102
  /** Extract exported declarations, named exports, re-exports, and TS export assignments. */
90
- exports(file: string): Promise<TreeSitterResult<ExportRecord[]>>;
103
+ exports(file: string, control?: CodeRequestControl): Promise<TreeSitterResult<ExportRecord[]>>;
91
104
  /** Return the smallest syntax node at a 1-based UTF-16 position. */
92
- nodeAt(file: string, line: number, character: number): Promise<TreeSitterResult<NodeAtResult>>;
105
+ nodeAt(
106
+ file: string,
107
+ line: number,
108
+ character: number,
109
+ control?: CodeRequestControl,
110
+ ): Promise<TreeSitterResult<NodeAtResult>>;
93
111
  /** Extract structural outgoing calls from the enclosing scope at a position. */
94
112
  calleesAt(
95
113
  file: string,
96
114
  line: number,
97
115
  character: number,
98
- depth?: "direct" | "deep",
116
+ depthOrOptions?:
117
+ | "direct"
118
+ | "deep"
119
+ | { depth?: "direct" | "deep"; control?: CodeRequestControl },
99
120
  ): Promise<TreeSitterResult<CalleesAtResult>>;
100
121
  /** Extract all call-site identifiers in a file. */
101
- callSites(file: string): Promise<TreeSitterResult<CallSiteMatch[]>>;
122
+ callSites(file: string, control?: CodeRequestControl): Promise<TreeSitterResult<CallSiteMatch[]>>;
102
123
  }
103
124
 
104
- /** Owned Tree-sitter session that must release its runtime resources. */
125
+ /** Owned Tree-sitter session that must release its Worker resources. */
105
126
  export interface TreeSitterSession extends TreeSitterService {
106
- /** Release parser and grammar resources owned by this session. */
107
- dispose(): void;
127
+ /** Terminate and await the Structural Worker owned by this session. */
128
+ dispose(): Promise<void>;
108
129
  }
109
130
 
110
131
  /** Session-scoped shared structural service published by the extension runtime. */