@mrclrchtr/supi-code-intelligence 4.10.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 (203) 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/settings/settings-registry.ts +3 -0
  14. package/node_modules/@mrclrchtr/supi-lsp/README.md +80 -5
  15. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
  16. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  17. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
  18. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
  19. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
  20. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
  21. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +2 -0
  22. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  23. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
  24. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
  25. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
  26. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
  27. package/node_modules/@mrclrchtr/supi-lsp/package.json +7 -6
  28. package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +10 -0
  29. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-cache.ts +206 -0
  30. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-capabilities.ts +78 -0
  31. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-collection.ts +114 -0
  32. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-evidence.ts +372 -0
  33. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-host.ts +14 -0
  34. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-pull.ts +62 -0
  35. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-refresh.ts +491 -0
  36. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-request.ts +9 -0
  37. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-timing.ts +71 -11
  38. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-waiters.ts +206 -0
  39. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostics.ts +365 -297
  40. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-state.ts +52 -0
  41. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-sync.ts +185 -0
  42. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-file-state.ts +25 -0
  43. package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +467 -115
  44. package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +161 -33
  45. package/node_modules/@mrclrchtr/supi-lsp/src/config/capabilities.ts +10 -1
  46. package/node_modules/@mrclrchtr/supi-lsp/src/config/defaults.json +1 -1
  47. package/node_modules/@mrclrchtr/supi-lsp/src/debug-telemetry.ts +45 -0
  48. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/evidence.ts +38 -0
  49. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-client-state.ts +79 -9
  50. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +13 -4
  51. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +300 -24
  52. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-symbol.ts +5 -2
  53. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +464 -96
  54. package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-refactor-provider.ts +130 -0
  55. package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +45 -329
  56. package/node_modules/@mrclrchtr/supi-lsp/src/provider/refactor-planning.ts +57 -120
  57. package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-edit-normalizer.ts +320 -0
  58. package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-symbol-mapper.ts +207 -0
  59. package/node_modules/@mrclrchtr/supi-lsp/src/session/readiness.ts +72 -2
  60. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-controller.ts +151 -26
  61. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostic-surface.ts +40 -0
  62. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostics.ts +50 -0
  63. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registry.ts +136 -120
  64. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-transition-debug.ts +49 -0
  65. package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +102 -0
  66. package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +17 -7
  67. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
  68. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  69. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
  70. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
  71. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
  72. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
  73. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +2 -0
  74. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  75. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
  76. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
  77. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
  78. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
  79. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/LICENSE +21 -0
  80. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/README.md +258 -0
  81. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/babel.cjs +257 -0
  82. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/jiti.cjs +1 -0
  83. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-cli.mjs +34 -0
  84. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-hooks.mjs +124 -0
  85. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-native.mjs +121 -0
  86. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.d.mts +1 -0
  87. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.mjs +4 -0
  88. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-static.mjs +23 -0
  89. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.cjs +30 -0
  90. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.cts +8 -0
  91. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.mts +8 -0
  92. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.mjs +29 -0
  93. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/types.d.ts +420 -0
  94. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/package.json +146 -0
  95. package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +6 -3
  96. package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +0 -9
  97. package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +0 -8
  98. package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +16 -12
  99. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-controller.ts +65 -87
  100. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +47 -95
  101. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-timing.ts +147 -0
  102. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client-lifecycle.ts +39 -0
  103. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client.ts +561 -0
  104. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-message-size.ts +24 -0
  105. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-protocol.ts +452 -0
  106. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-sites.ts +4 -2
  107. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +12 -4
  108. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/exports.ts +4 -2
  109. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/imports.ts +4 -2
  110. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/node-at.ts +5 -3
  111. package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +33 -12
  112. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/blocking-test-bootstrap.mjs +34 -0
  113. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/bootstrap.mjs +8 -0
  114. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store-helpers.ts +23 -0
  115. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store.ts +400 -0
  116. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/request-control.ts +48 -0
  117. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-parser-helpers.ts +24 -0
  118. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-query-helpers.ts +43 -0
  119. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime.ts +421 -0
  120. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/service.ts +116 -0
  121. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/worker-main.ts +201 -0
  122. package/package.json +5 -5
  123. package/src/analysis/health/diagnostics.ts +236 -24
  124. package/src/analysis/health/recovery.ts +6 -2
  125. package/src/analysis/provider.ts +58 -0
  126. package/src/analysis/readiness.ts +30 -9
  127. package/src/analysis/refactor/apply.ts +45 -1
  128. package/src/analysis/refactor/mutation-authority.ts +143 -0
  129. package/src/analysis/relations/callees.ts +9 -1
  130. package/src/analysis/relations/types.ts +5 -2
  131. package/src/analysis/search/ast-scan-timing.ts +9 -2
  132. package/src/analysis/search/ast-scan.ts +1 -1
  133. package/src/analysis/search/deadline.ts +2 -2
  134. package/src/analysis/search/pattern-analysis.ts +46 -32
  135. package/src/analysis/search/pattern.ts +12 -2
  136. package/src/analysis/target/anchored.ts +20 -11
  137. package/src/analysis/target/file.ts +18 -11
  138. package/src/analysis/target/identity.ts +19 -3
  139. package/src/analysis/target/symbol.ts +36 -15
  140. package/src/api.ts +4 -0
  141. package/src/diagnostics/evidence.ts +51 -0
  142. package/src/session/capability-adapter.ts +12 -3
  143. package/src/session/find-workflow.ts +17 -7
  144. package/src/session/graph/collect.ts +18 -2
  145. package/src/session/graph-workflow.ts +19 -12
  146. package/src/session/health-refresh.ts +148 -0
  147. package/src/session/health-types.ts +37 -15
  148. package/src/session/health-workflow.ts +37 -39
  149. package/src/session/inspect/collect.ts +20 -3
  150. package/src/session/inspect-workflow.ts +10 -5
  151. package/src/session/orientation/collect.ts +10 -1
  152. package/src/session/orientation/context-facts.ts +3 -1
  153. package/src/session/orientation/context-sections.ts +20 -7
  154. package/src/session/orientation/gather.ts +17 -11
  155. package/src/session/orientation-types.ts +2 -1
  156. package/src/session/orientation-workflow.ts +15 -8
  157. package/src/session/refactor-plans.ts +2 -0
  158. package/src/session/refactor-workflow.ts +59 -14
  159. package/src/session/session.ts +4 -1
  160. package/src/session/target-workflow.ts +54 -23
  161. package/src/session/workflow-control.ts +7 -3
  162. package/src/substrate/lsp/lifecycle.ts +26 -46
  163. package/src/substrate/lsp/maintenance.ts +199 -25
  164. package/src/substrate/lsp/state.ts +2 -2
  165. package/src/substrate/workspace-provider-host.ts +25 -3
  166. package/src/tool/find/execute.ts +7 -1
  167. package/src/tool/find/render.ts +20 -3
  168. package/src/tool/find/tui.ts +23 -21
  169. package/src/tool/graph/execute.ts +23 -3
  170. package/src/tool/graph/tui.ts +59 -46
  171. package/src/tool/health/execute.ts +7 -2
  172. package/src/tool/health/markdown.ts +56 -14
  173. package/src/tool/health/refresh-status.ts +105 -0
  174. package/src/tool/health/tui.ts +95 -98
  175. package/src/tool/infra/workflow-control.ts +8 -0
  176. package/src/tool/inspect/execute.ts +7 -1
  177. package/src/tool/inspect/tui.ts +26 -18
  178. package/src/tool/orientation/execute.ts +21 -3
  179. package/src/tool/orientation/tui.ts +51 -35
  180. package/src/tool/refactor-apply/execute.ts +3 -0
  181. package/src/tool/refactor-apply/tui.ts +43 -25
  182. package/src/tool/refactor-plan/execute.ts +4 -0
  183. package/src/tool/refactor-plan/tui.ts +33 -20
  184. package/src/tool/register.ts +127 -22
  185. package/src/tool/resolve/execute.ts +18 -1
  186. package/src/tool/resolve/tui.ts +42 -24
  187. package/src/tool/result/display.ts +107 -0
  188. package/src/tool/result/errors.ts +20 -17
  189. package/src/tool/result/find.ts +52 -8
  190. package/src/tool/result/graph.ts +44 -1
  191. package/src/tool/result/health.ts +53 -1
  192. package/src/tool/result/inspect.ts +113 -1
  193. package/src/tool/result/orientation.ts +66 -14
  194. package/src/tool/result/refactor.ts +36 -4
  195. package/src/tool/result/resolve.ts +44 -7
  196. package/src/tool/result/types.ts +20 -0
  197. package/src/types/execution.ts +18 -5
  198. package/src/types/index.ts +8 -1
  199. package/src/ui/status-command.ts +5 -3
  200. package/src/ui/status-overlay.ts +4 -0
  201. package/src/ui/tui/common.ts +108 -10
  202. package/src/ui/tui/display.ts +48 -0
  203. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime.ts +0 -351
@@ -9,12 +9,14 @@
9
9
 
10
10
  import * as fs from "node:fs";
11
11
  import * as path from "node:path";
12
- import type {
13
- CodeResult,
14
- CodeSymbol,
15
- NodeAtData,
16
- SemanticProvider,
17
- StructuralProvider,
12
+ import {
13
+ type CodeRequestControl,
14
+ type CodeResult,
15
+ type CodeSymbol,
16
+ isCodeRequestInterruption,
17
+ type NodeAtData,
18
+ type SemanticProvider,
19
+ type StructuralProvider,
18
20
  } from "@mrclrchtr/supi-code-runtime/api";
19
21
  import type { AnchorKind } from "../../session/target-store.ts";
20
22
  import type { AnchoredResolutionMetadata, AnchoredResolutionSource } from "../../types/index.ts";
@@ -217,17 +219,20 @@ async function candidatesFromSymbols(
217
219
  }
218
220
 
219
221
  /** Layer 1: match the coordinate against LSP document symbols. Returns null to fall through. */
222
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: layered anchored resolution keeps layer-1 symbol matching and identity resolution together.
220
223
  async function resolveFromSemantic(
221
224
  file: string,
222
225
  requested: Anchor,
223
226
  provider: AnchoredResolverProvider,
227
+ control?: CodeRequestControl,
224
228
  ): Promise<TargetOutcome | null> {
225
229
  if (!provider.documentSymbols) return null;
226
230
  let symbols: CodeSymbol[] = [];
227
231
  try {
228
232
  const result = await provider.documentSymbols(file);
229
233
  if (result.kind !== "unavailable") symbols = result.data;
230
- } catch {
234
+ } catch (error) {
235
+ if (isCodeRequestInterruption(error, control)) throw error;
231
236
  symbols = [];
232
237
  }
233
238
  if (symbols.length === 0) return null;
@@ -241,7 +246,7 @@ async function resolveFromSemantic(
241
246
  }
242
247
 
243
248
  const structural = provider.nodeAt ? { nodeAt: provider.nodeAt } : undefined;
244
- const resolveIdentity = createCodeSymbolIdentityResolver(file, symbols, structural);
249
+ const resolveIdentity = createCodeSymbolIdentityResolver(file, symbols, structural, control);
245
250
  if (exact.length === 1) {
246
251
  return resolvedFromSymbol(file, exact[0], {
247
252
  snapped: false,
@@ -268,12 +273,14 @@ async function resolveFromStructural(
268
273
  file: string,
269
274
  requested: Anchor,
270
275
  provider: AnchoredResolverProvider,
276
+ control?: CodeRequestControl,
271
277
  ): Promise<TargetOutcome | null> {
272
278
  if (!provider.nodeAt) return null;
273
279
  let nodeResult: CodeResult<NodeAtData> | null = null;
274
280
  try {
275
281
  nodeResult = await provider.nodeAt(file, requested.line, requested.character);
276
- } catch {
282
+ } catch (error) {
283
+ if (isCodeRequestInterruption(error, control)) throw error;
277
284
  nodeResult = null;
278
285
  }
279
286
  if (nodeResult?.kind !== "success") return null;
@@ -351,11 +358,13 @@ async function resolveFromStructural(
351
358
  * This does not perform heuristic global text search and does not silently
352
359
  * treat declaration anchors as name anchors (ADR 0003).
353
360
  */
361
+ // biome-ignore lint/complexity/useMaxParams: anchored resolution is a stable public resolver boundary with fixed positional fields.
354
362
  export async function resolveAnchoredSymbolTarget(
355
363
  file: string,
356
364
  line: number,
357
365
  character: number,
358
366
  provider: AnchoredResolverProvider | null,
367
+ control?: CodeRequestControl,
359
368
  ): Promise<TargetOutcome> {
360
369
  if (!fs.existsSync(file)) {
361
370
  return { kind: "error", message: `File not found: \`${file}\`` };
@@ -369,9 +378,9 @@ export async function resolveAnchoredSymbolTarget(
369
378
 
370
379
  const requested: Anchor = { line, character };
371
380
  if (provider) {
372
- const semantic = await resolveFromSemantic(file, requested, provider);
381
+ const semantic = await resolveFromSemantic(file, requested, provider, control);
373
382
  if (semantic) return semantic;
374
- const structural = await resolveFromStructural(file, requested, provider);
383
+ const structural = await resolveFromStructural(file, requested, provider, control);
375
384
  if (structural) return structural;
376
385
  }
377
386
 
@@ -9,12 +9,14 @@
9
9
 
10
10
  import * as fs from "node:fs";
11
11
  import * as path from "node:path";
12
- import type {
13
- DeclarationNesting,
14
- DocumentCodeSymbol,
15
- OutlineData,
16
- SemanticProvider as SemanticSubstrate,
17
- StructuralProvider as StructuralSubstrate,
12
+ import {
13
+ type CodeRequestControl,
14
+ type DeclarationNesting,
15
+ type DocumentCodeSymbol,
16
+ isCodeRequestInterruption,
17
+ type OutlineData,
18
+ type SemanticProvider as SemanticSubstrate,
19
+ type StructuralProvider as StructuralSubstrate,
18
20
  } from "@mrclrchtr/supi-code-runtime/api";
19
21
  import type { AnchorKind } from "../../session/target-store.ts";
20
22
  import { normalizePath } from "../search/paths.ts";
@@ -80,6 +82,7 @@ export async function resolveFileTargetGroup(
80
82
  semantic?: SemanticSubstrate;
81
83
  structural?: StructuralSubstrate;
82
84
  } = {},
85
+ control?: CodeRequestControl,
83
86
  ): Promise<
84
87
  | { kind: "resolved"; group: ResolvedTargetGroupData }
85
88
  | { kind: "invalid-input"; message: string }
@@ -90,8 +93,8 @@ export async function resolveFileTargetGroup(
90
93
  const resolvedFile = validation.file;
91
94
 
92
95
  const [semantic, structural] = await Promise.all([
93
- discoverSemantic(resolvedFile, deps.semantic, deps.structural),
94
- discoverStructural(resolvedFile, deps.structural),
96
+ discoverSemantic(resolvedFile, deps.semantic, deps.structural, control),
97
+ discoverStructural(resolvedFile, deps.structural, control),
95
98
  ]);
96
99
  if (!semantic.available && !structural.available) {
97
100
  const displayFile = path.relative(cwd, resolvedFile) || file;
@@ -148,6 +151,7 @@ async function discoverSemantic(
148
151
  file: string,
149
152
  semantic: SemanticSubstrate | undefined,
150
153
  structural: StructuralSubstrate | undefined,
154
+ control?: CodeRequestControl,
151
155
  ): Promise<DiscoveryResult> {
152
156
  if (!semantic) return { available: false, targets: [] };
153
157
  try {
@@ -158,12 +162,13 @@ async function discoverSemantic(
158
162
  targets: await Promise.all(
159
163
  result.data.map(async (symbol) => {
160
164
  const target = targetFromSymbol(file, symbol);
161
- const refined = await refineTypeAliasIdentity(target, structural);
165
+ const refined = await refineTypeAliasIdentity(target, structural, control);
162
166
  return { ...refined, nesting: target.nesting };
163
167
  }),
164
168
  ),
165
169
  };
166
- } catch {
170
+ } catch (error) {
171
+ if (isCodeRequestInterruption(error, control)) throw error;
167
172
  return { available: false, targets: [] };
168
173
  }
169
174
  }
@@ -196,13 +201,15 @@ function normalizeNesting(value: unknown): DeclarationNesting {
196
201
  async function discoverStructural(
197
202
  file: string,
198
203
  structural: StructuralSubstrate | undefined,
204
+ control?: CodeRequestControl,
199
205
  ): Promise<DiscoveryResult> {
200
206
  if (!structural) return { available: false, targets: [] };
201
207
  try {
202
208
  const result = await structural.outline(file);
203
209
  if (result.kind !== "success") return { available: false, targets: [] };
204
210
  return { available: true, targets: flattenOutline(file, result.data) };
205
- } catch {
211
+ } catch (error) {
212
+ if (isCodeRequestInterruption(error, control)) throw error;
206
213
  return { available: false, targets: [] };
207
214
  }
208
215
  }
@@ -1,5 +1,10 @@
1
1
  import { resolve } from "node:path";
2
- import type { CodeSymbol, StructuralProvider } from "@mrclrchtr/supi-code-runtime/api";
2
+ import {
3
+ type CodeRequestControl,
4
+ type CodeSymbol,
5
+ isCodeRequestInterruption,
6
+ type StructuralProvider,
7
+ } from "@mrclrchtr/supi-code-runtime/api";
3
8
  import type { ResolvedTargetData, TargetOutcome } from "./types.ts";
4
9
 
5
10
  /**
@@ -45,6 +50,7 @@ export interface DeclarationOccurrenceIdentity extends DeclarationIdentityResult
45
50
  export async function resolveDeclarationIdentityKind(
46
51
  observation: DeclarationIdentityObservation,
47
52
  structural: Pick<StructuralProvider, "nodeAt"> | undefined,
53
+ control?: CodeRequestControl,
48
54
  ): Promise<DeclarationIdentityResult> {
49
55
  const identityKind = canonicalDeclarationKind(observation.providerKind);
50
56
  if (
@@ -69,7 +75,8 @@ export async function resolveDeclarationIdentityKind(
69
75
  return exactNameAnchor && isTypeAlias
70
76
  ? { identityKind: "type", structuralEvidence: true }
71
77
  : { identityKind, structuralEvidence: false };
72
- } catch {
78
+ } catch (error) {
79
+ if (isCodeRequestInterruption(error, control)) throw error;
73
80
  return { identityKind, structuralEvidence: false };
74
81
  }
75
82
  }
@@ -82,6 +89,7 @@ export function createCodeSymbolIdentityResolver(
82
89
  file: string,
83
90
  allSymbols: readonly CodeSymbol[],
84
91
  structural: Pick<StructuralProvider, "nodeAt"> | undefined,
92
+ control?: CodeRequestControl,
85
93
  ): (symbol: CodeSymbol) => Promise<DeclarationOccurrenceIdentity> {
86
94
  const identities = new Map<CodeSymbol, Promise<DeclarationIdentityResult>>();
87
95
  const occurrences = new Map<CodeSymbol, Promise<DeclarationOccurrenceIdentity>>();
@@ -97,6 +105,7 @@ export function createCodeSymbolIdentityResolver(
97
105
  nameAnchor: symbol.nameAnchor ?? null,
98
106
  },
99
107
  structural,
108
+ control,
100
109
  );
101
110
  identities.set(symbol, identity);
102
111
  return identity;
@@ -147,6 +156,7 @@ function compareCodeSymbolDeclarations(left: CodeSymbol, right: CodeSymbol): num
147
156
  export async function refineTypeAliasIdentity(
148
157
  target: ResolvedTargetData,
149
158
  structural: Pick<StructuralProvider, "nodeAt"> | undefined,
159
+ control?: CodeRequestControl,
150
160
  ): Promise<ResolvedTargetData> {
151
161
  if (target.identityKind !== undefined) return target;
152
162
  const identity = await resolveDeclarationIdentityKind(
@@ -160,6 +170,7 @@ export async function refineTypeAliasIdentity(
160
170
  : null,
161
171
  },
162
172
  structural,
173
+ control,
163
174
  );
164
175
  return {
165
176
  ...target,
@@ -173,9 +184,13 @@ export async function refineTargetOutcomeIdentity(
173
184
  outcome: TargetOutcome,
174
185
  cwd: string,
175
186
  structural: Pick<StructuralProvider, "nodeAt"> | undefined,
187
+ control?: CodeRequestControl,
176
188
  ): Promise<TargetOutcome> {
177
189
  if (outcome.kind === "resolved") {
178
- return { kind: "resolved", target: await refineTypeAliasIdentity(outcome.target, structural) };
190
+ return {
191
+ kind: "resolved",
192
+ target: await refineTypeAliasIdentity(outcome.target, structural, control),
193
+ };
179
194
  }
180
195
  if (outcome.kind !== "disambiguation" && outcome.kind !== "kind-mismatch") return outcome;
181
196
 
@@ -195,6 +210,7 @@ export async function refineTargetOutcomeIdentity(
195
210
  : null,
196
211
  },
197
212
  structural,
213
+ control,
198
214
  );
199
215
  return {
200
216
  candidate: {
@@ -7,9 +7,11 @@
7
7
  */
8
8
 
9
9
  import * as path from "node:path";
10
- import type {
11
- CodeSymbol,
12
- SemanticProvider as SemanticSubstrate,
10
+ import {
11
+ type CodeRequestControl,
12
+ type CodeSymbol,
13
+ isCodeRequestInterruption,
14
+ type SemanticProvider as SemanticSubstrate,
13
15
  } from "@mrclrchtr/supi-code-runtime/api";
14
16
  import { isWithinOrEqual } from "@mrclrchtr/supi-core/project";
15
17
  import type { TargetSymbolKind } from "../../session/target-input.ts";
@@ -59,6 +61,7 @@ function anchorOf(s: CodeSymbol): CodeSymbol["declarationAnchor"] {
59
61
  async function refineResolvedSymbolAnchor(
60
62
  workspaceSymbol: CodeSymbol,
61
63
  semantic: SemanticSubstrate,
64
+ control?: CodeRequestControl,
62
65
  ): Promise<CodeSymbol> {
63
66
  try {
64
67
  const result = await semantic.documentSymbols(workspaceSymbol.file);
@@ -84,7 +87,8 @@ async function refineResolvedSymbolAnchor(
84
87
  }
85
88
 
86
89
  return refined;
87
- } catch {
90
+ } catch (error) {
91
+ if (isCodeRequestInterruption(error, control)) throw error;
88
92
  return workspaceSymbol;
89
93
  }
90
94
  }
@@ -107,6 +111,7 @@ export async function resolveSymbolTarget(
107
111
  kind?: TargetSymbolKind;
108
112
  exportedOnly?: boolean;
109
113
  maxResults?: number;
114
+ control?: CodeRequestControl;
110
115
  },
111
116
  ): Promise<TargetOutcome> {
112
117
  const result = await semantic.workspaceSymbols(symbol);
@@ -150,12 +155,25 @@ export async function resolveSymbolTarget(
150
155
  cwd,
151
156
  maxResults: options.maxResults,
152
157
  requestedKind,
158
+ control: options.control,
153
159
  });
154
160
  }
155
- return resolveCandidates(exactKind, semantic, cwd, options.maxResults);
161
+ return resolveCandidates({
162
+ candidates: exactKind,
163
+ semantic,
164
+ cwd,
165
+ maxResults: options.maxResults,
166
+ control: options.control,
167
+ });
156
168
  }
157
169
 
158
- return resolveCandidates(eligible, semantic, cwd, options?.maxResults);
170
+ return resolveCandidates({
171
+ candidates: eligible,
172
+ semantic,
173
+ cwd,
174
+ maxResults: options?.maxResults,
175
+ control: options?.control,
176
+ });
159
177
  }
160
178
 
161
179
  function providerKindMatches(reported: string, requested: TargetSymbolKind): boolean {
@@ -166,18 +184,20 @@ function normalizeProviderKind(kind: string): string {
166
184
  return kind.replace(/[\s_-]/g, "").toLowerCase();
167
185
  }
168
186
 
169
- async function resolveCandidates(
170
- candidates: readonly CodeSymbol[],
171
- semantic: SemanticSubstrate,
172
- cwd: string,
173
- maxResults?: number,
174
- ): Promise<TargetOutcome> {
187
+ async function resolveCandidates(options: {
188
+ candidates: readonly CodeSymbol[];
189
+ semantic: SemanticSubstrate;
190
+ cwd: string;
191
+ maxResults?: number;
192
+ control?: CodeRequestControl;
193
+ }): Promise<TargetOutcome> {
194
+ const { candidates, semantic, cwd, maxResults, control } = options;
175
195
  const ranged = candidates.filter(
176
196
  (candidate) =>
177
197
  candidate.declarationAnchor.line > 0 || candidate.declarationAnchor.character > 0,
178
198
  );
179
199
  if (ranged.length === 1) {
180
- return resolvedTarget(await refineResolvedSymbolAnchor(ranged[0], semantic));
200
+ return resolvedTarget(await refineResolvedSymbolAnchor(ranged[0], semantic, control));
181
201
  }
182
202
  return buildCandidateOutcome({
183
203
  kind: "disambiguation",
@@ -185,6 +205,7 @@ async function resolveCandidates(
185
205
  semantic,
186
206
  cwd,
187
207
  maxResults,
208
+ control,
188
209
  });
189
210
  }
190
211
 
@@ -220,7 +241,7 @@ type CandidateOutcomeOptions = CandidateOutcomeBase &
220
241
  (
221
242
  | { kind: "disambiguation"; requestedKind?: never }
222
243
  | { kind: "kind-mismatch"; requestedKind: TargetSymbolKind }
223
- );
244
+ ) & { control?: CodeRequestControl };
224
245
 
225
246
  /**
226
247
  * Refine only bounded visible candidates to name anchors while retaining the
@@ -234,7 +255,7 @@ async function buildCandidateOutcome(
234
255
  const refined = await Promise.all(
235
256
  options.candidates
236
257
  .slice(0, cap)
237
- .map((candidate) => refineResolvedSymbolAnchor(candidate, options.semantic)),
258
+ .map((candidate) => refineResolvedSymbolAnchor(candidate, options.semantic, options.control)),
238
259
  );
239
260
  const common = {
240
261
  candidates: toDisambiguationCandidates(refined, options.cwd),
package/src/api.ts CHANGED
@@ -57,6 +57,7 @@ export type { TargetSymbolKind } from "./session/target-input.ts";
57
57
  // Code-intelligence-specific result types.
58
58
  export type {
59
59
  CodeIntelResult,
60
+ CodeIntelResultDetails,
60
61
  ContextDetails,
61
62
  DisambiguationCandidate,
62
63
  HealthDetails,
@@ -65,4 +66,7 @@ export type {
65
66
  OrientationSectionDetails,
66
67
  ResolveDetails,
67
68
  SearchDetails,
69
+ ToolDisplaySection,
70
+ ToolOutputTruncationDetails,
71
+ ToolResultStatus,
68
72
  } from "./types/index.ts";
@@ -0,0 +1,51 @@
1
+ import * as path from "node:path";
2
+ import type {
3
+ DiagnosticEvidenceDocument,
4
+ DiagnosticEvidenceStatus,
5
+ DiagnosticEvidenceSummary,
6
+ } from "@mrclrchtr/supi-lsp/api";
7
+
8
+ /** Merge file-local diagnostic evidence without inventing coverage. */
9
+ export function mergeDiagnosticEvidence(
10
+ previous: DiagnosticEvidenceSummary,
11
+ latest: DiagnosticEvidenceSummary,
12
+ cwd?: string,
13
+ policy: "latest" | "conservative" = "latest",
14
+ ): DiagnosticEvidenceSummary {
15
+ const byFile = new Map<string, DiagnosticEvidenceDocument>();
16
+ for (const document of [...previous.documents, ...latest.documents]) {
17
+ const file = cwd ? path.relative(cwd, path.resolve(cwd, document.file)) : document.file;
18
+ const next = { file, status: document.status };
19
+ const previousDocument = byFile.get(file);
20
+ if (
21
+ !previousDocument ||
22
+ policy === "latest" ||
23
+ evidenceStatusRank(next.status) > evidenceStatusRank(previousDocument.status)
24
+ ) {
25
+ byFile.set(file, next);
26
+ }
27
+ }
28
+ const documents = Array.from(byFile.values()).sort((a, b) => a.file.localeCompare(b.file));
29
+ const counts = {
30
+ requested: documents.length,
31
+ confirmed: 0,
32
+ unconfirmed: 0,
33
+ failed: 0,
34
+ removed: 0,
35
+ };
36
+ for (const document of documents) counts[document.status]++;
37
+ return { ...counts, documents };
38
+ }
39
+
40
+ function evidenceStatusRank(status: DiagnosticEvidenceStatus): number {
41
+ switch (status) {
42
+ case "confirmed":
43
+ return 1;
44
+ case "unconfirmed":
45
+ return 2;
46
+ case "failed":
47
+ return 3;
48
+ case "removed":
49
+ return 4;
50
+ }
51
+ }
@@ -9,6 +9,7 @@
9
9
 
10
10
  import {
11
11
  type CapabilityState,
12
+ type CodeRequestControl,
12
13
  getDefaultWorkspaceRuntime,
13
14
  type SemanticProvider,
14
15
  type StructuralProvider,
@@ -67,7 +68,11 @@ export interface CapabilityAdapter {
67
68
  * the target workflow can decide whether to proceed, return a
68
69
  * timeout note, or return an unavailable result.
69
70
  */
70
- ensureSemanticReadiness(cwd: string, scope: ReadinessScope): Promise<ReadinessOutcome>;
71
+ ensureSemanticReadiness(
72
+ cwd: string,
73
+ scope: ReadinessScope,
74
+ control?: CodeRequestControl,
75
+ ): Promise<ReadinessOutcome>;
71
76
  }
72
77
 
73
78
  // ── Production adapter ────────────────────────────────────────────────
@@ -107,8 +112,12 @@ export class WorkspaceCapabilityAdapter implements CapabilityAdapter {
107
112
  return null;
108
113
  }
109
114
 
110
- async ensureSemanticReadiness(cwd: string, scope: ReadinessScope): Promise<ReadinessOutcome> {
111
- const result = await ensureSemanticReadiness(cwd, scope);
115
+ async ensureSemanticReadiness(
116
+ cwd: string,
117
+ scope: ReadinessScope,
118
+ control?: CodeRequestControl,
119
+ ): Promise<ReadinessOutcome> {
120
+ const result = await ensureSemanticReadiness(cwd, scope, undefined, control);
112
121
  return result;
113
122
  }
114
123
 
@@ -30,7 +30,8 @@ export async function runFindWorkflow(
30
30
  const scope = resolveScopeSet(request.scope ? [...request.scope] : undefined, deps.cwd);
31
31
  if (scope.kind === "error") return { kind: "invalid-input", message: scope.reason };
32
32
 
33
- throwIfAborted(control);
33
+ if (mode === "ast") control?.signal?.throwIfAborted();
34
+ else throwIfAborted(control);
34
35
  reportProgress(control, {
35
36
  intent: "find",
36
37
  phase: mode,
@@ -69,9 +70,11 @@ async function runSemanticSearch(options: {
69
70
  control?: WorkflowControl;
70
71
  }): Promise<FindWorkflowOutcome> {
71
72
  const { query, scopePaths, scopeLabel, maxResults, deps, control } = options;
72
- const readiness = await deps.capability.ensureSemanticReadiness(deps.cwd, {
73
- kind: "workspace",
74
- });
73
+ const readiness = await deps.capability.ensureSemanticReadiness(
74
+ deps.cwd,
75
+ { kind: "workspace" },
76
+ control,
77
+ );
75
78
  if (readiness.kind === "timeout") {
76
79
  return { kind: "unavailable", reason: "Semantic readiness timed out." };
77
80
  }
@@ -82,7 +85,10 @@ async function runSemanticSearch(options: {
82
85
  if (!provider?.workspaceSymbols) {
83
86
  return { kind: "unavailable", reason: "No semantic workspace-symbol provider is active." };
84
87
  }
85
- const result = await provider.workspaceSymbols(query);
88
+ const result = await provider.workspaceSymbols(query, control);
89
+ // A cancellation that landed during the request must not publish symbols
90
+ // the caller no longer awaits.
91
+ throwIfAborted(control);
86
92
  if (result.kind === "unavailable") {
87
93
  return { kind: "unavailable", reason: result.reason };
88
94
  }
@@ -120,13 +126,17 @@ async function runAstSearch(options: {
120
126
  if (!provider) {
121
127
  return { kind: "unavailable", reason: "No structural provider is active." };
122
128
  }
123
- throwIfAborted(control);
129
+ control?.signal?.throwIfAborted();
124
130
  const outcome = await getStructuredPatternMatches({
125
131
  params: { pattern: query, kind: input.kind },
126
132
  roots: scopePaths,
127
133
  cwd: deps.cwd,
128
134
  structural: provider,
129
- control: { signal: control?.signal },
135
+ control: {
136
+ operationId: control?.operationId,
137
+ signal: control?.signal,
138
+ deadline: control?.deadline,
139
+ },
130
140
  });
131
141
  if (outcome.kind === "invalid-input") return outcome;
132
142
  if (outcome.kind === "unavailable") return outcome;
@@ -1,5 +1,10 @@
1
1
  /** Presentation-neutral relation collection used by the session-owned graph workflow. */
2
2
 
3
+ import {
4
+ type CodeRequestControl,
5
+ isCodeRequestInterruption,
6
+ unavailableCodeQuery,
7
+ } from "@mrclrchtr/supi-code-runtime/api";
3
8
  import type { CodeProvider } from "../../analysis/provider.ts";
4
9
  import {
5
10
  readNextEnclosingScope,
@@ -25,6 +30,7 @@ export interface CollectRelationOptions {
25
30
  semanticReadinessError: string | null;
26
31
  anchorKind: AnchorKind;
27
32
  calleeDepth?: "direct" | "deep";
33
+ requestControl?: CodeRequestControl;
28
34
  }
29
35
 
30
36
  /** Collect one evidence-backed graph relation without rendering it. */
@@ -46,6 +52,7 @@ export async function collectRelation(
46
52
  return collectImplementationsRelation(options);
47
53
  }
48
54
  } catch (error) {
55
+ if (isCodeRequestInterruption(error, options.requestControl)) throw error;
49
56
  return {
50
57
  kind: "unavailable",
51
58
  rel: relation,
@@ -61,7 +68,11 @@ async function collectReferences(options: CollectRelationOptions): Promise<Graph
61
68
 
62
69
  const result = await collectCallers(options.file, options.position, options.displayName, {
63
70
  cwd: options.cwd,
64
- provider: { references: options.provider.references },
71
+ provider: {
72
+ references: async (file, position) =>
73
+ options.provider?.references(file, position, options.requestControl) ??
74
+ unavailableCodeQuery("References unavailable"),
75
+ },
65
76
  });
66
77
  if (result.confidence === "unavailable") {
67
78
  return { kind: "unavailable", rel: "references", message: "References unavailable" };
@@ -118,6 +129,7 @@ async function collectCalleesRelation(options: CollectRelationOptions): Promise<
118
129
  { cwd: options.cwd, provider: { calleesAt: options.provider.calleesAt } },
119
130
  undefined,
120
131
  options.calleeDepth ?? "direct",
132
+ options.requestControl,
121
133
  );
122
134
  if (result.confidence === "unavailable") {
123
135
  return { kind: "unavailable", rel: "callees", message: "Callees unavailable" };
@@ -161,7 +173,11 @@ async function collectImplementationsRelation(
161
173
 
162
174
  const result = await collectImplementations(options.file, options.position, options.displayName, {
163
175
  cwd: options.cwd,
164
- provider: { implementation: options.provider.implementation },
176
+ provider: {
177
+ implementation: async (file, position) =>
178
+ options.provider?.implementation(file, position, options.requestControl) ??
179
+ unavailableCodeQuery("Implementations unavailable"),
180
+ },
165
181
  });
166
182
  if (result.confidence === "unavailable") {
167
183
  return { kind: "unavailable", rel: "implements", message: "Implementations unavailable" };
@@ -54,7 +54,9 @@ export async function runGraphWorkflow(
54
54
  maxResults: request.maxResults,
55
55
  },
56
56
  deps,
57
+ control,
57
58
  );
59
+ throwIfAborted(control);
58
60
  if (targetOutcome.kind === "target-group") {
59
61
  return {
60
62
  kind: "invalid-input",
@@ -64,12 +66,13 @@ export async function runGraphWorkflow(
64
66
  if (targetOutcome.kind !== "resolved") return targetOutcome;
65
67
 
66
68
  const entry = targetOutcome.entry;
67
- const semanticReadinessError = await getSemanticReadinessError(
69
+ const semanticReadinessError = await getSemanticReadinessError({
68
70
  relations,
69
- entry.file,
70
- deps.capability,
71
- deps.cwd,
72
- );
71
+ file: entry.file,
72
+ capability: deps.capability,
73
+ cwd: deps.cwd,
74
+ control,
75
+ });
73
76
  const provider = deps.capability.getProvider(deps.cwd);
74
77
  const maxResults = request.maxResults ?? 8;
75
78
  const displayName =
@@ -94,9 +97,11 @@ export async function runGraphWorkflow(
94
97
  semanticReadinessError,
95
98
  anchorKind: entry.anchorKind,
96
99
  calleeDepth: request.calleeDepth,
100
+ requestControl: control,
97
101
  }),
98
102
  );
99
103
  }
104
+ throwIfAborted(control);
100
105
 
101
106
  if (sections.length > 0 && sections.every((section) => section.kind === "unavailable")) {
102
107
  return {
@@ -127,16 +132,18 @@ function normalizeRelations(
127
132
  return requested as readonly GraphRelationKind[];
128
133
  }
129
134
 
130
- async function getSemanticReadinessError(
131
- relations: readonly GraphRelationKind[],
132
- file: string,
133
- capability: CapabilityAdapter,
134
- cwd: string,
135
- ): Promise<string | null> {
135
+ async function getSemanticReadinessError(options: {
136
+ relations: readonly GraphRelationKind[];
137
+ file: string;
138
+ capability: CapabilityAdapter;
139
+ cwd: string;
140
+ control?: WorkflowControl;
141
+ }): Promise<string | null> {
142
+ const { relations, file, capability, cwd, control } = options;
136
143
  if (!relations.some((relation) => relation === "references" || relation === "implements")) {
137
144
  return null;
138
145
  }
139
- const readiness = await capability.ensureSemanticReadiness(cwd, { kind: "file", file });
146
+ const readiness = await capability.ensureSemanticReadiness(cwd, { kind: "file", file }, control);
140
147
  if (readiness.kind === "ready") return null;
141
148
  if (readiness.kind === "timeout") {
142
149
  return "Semantic readiness timed out. Retry shortly or inspect code_health.";