@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
@@ -1,55 +1,73 @@
1
- /**
2
- * TUI renderer for code_refactor_apply — renderCall + renderResult.
3
- *
4
- * Has a custom result renderer (not using renderSimpleResult) because
5
- * its compact view shows success/error status rather than a count badge.
6
- */
1
+ /** TUI renderer for code_refactor_apply. */
7
2
  import type { Theme } from "@earendil-works/pi-coding-agent";
8
- import { Container, Text } from "@earendil-works/pi-tui";
3
+ import { Container, Spacer, Text } from "@earendil-works/pi-tui";
9
4
  import {
5
+ formatCallValue,
10
6
  type ResultOptios,
7
+ renderDomainError,
8
+ renderDomainResult,
9
+ renderExecutionError,
11
10
  renderMarkdownDetail,
12
11
  renderPartial,
12
+ renderToolDisplaySections,
13
+ renderTruncationDisclosure,
14
+ type ToolRendererContext,
13
15
  type ToolResult,
14
16
  } from "../../ui/tui/common.ts";
15
17
 
16
- /** ── renderCall ────────────────────────────────────────────────── */
17
-
18
- export function renderRefactorApplyCall(_args: unknown, theme: Theme, _context: unknown): Text {
19
- return new Text(
20
- `${theme.fg("toolTitle", "code_refactor_apply")} ${theme.fg("accent", "apply plan")}`,
21
- 0,
22
- 0,
23
- );
18
+ /** Render the compact code_refactor_apply call header. */
19
+ export function renderRefactorApplyCall(
20
+ args: unknown,
21
+ theme: Theme,
22
+ _context: ToolRendererContext | undefined,
23
+ ): Text {
24
+ const params = (args ?? {}) as { planId?: unknown };
25
+ const planId = formatCallValue(params.planId);
26
+ const suffix = planId ? ` ${theme.fg("accent", planId)}` : "";
27
+ return new Text(`${theme.fg("toolTitle", "code_refactor_apply")}${suffix}`, 0, 0);
24
28
  }
25
29
 
26
- /** ── renderResult ──────────────────────────────────────────────── */
27
-
30
+ /** Render code_refactor_apply progress, status, and structured result details. */
28
31
  export function renderRefactorApplyResult(
29
32
  result: ToolResult,
30
33
  options: ResultOptios,
31
34
  theme: Theme,
32
- _context: unknown,
35
+ context: ToolRendererContext | undefined,
33
36
  ): Container | Text {
34
- if (options.isPartial) {
35
- return renderPartial("Applying…", theme);
36
- }
37
+ if (options.isPartial) return renderPartial("Applying…", theme);
38
+
39
+ const executionError = renderExecutionError(context, "code_refactor_apply failed", theme);
40
+ if (executionError) return executionError;
41
+ const domainError = renderDomainError(result, theme);
42
+ if (domainError) return renderDomainResult(result, options, theme, domainError);
37
43
 
38
44
  if (!options.expanded) {
39
45
  const applied =
40
- !result.isError &&
41
- result.details?.type === "search" &&
42
- result.details.data.confidence === "semantic";
43
- return new Text(
46
+ result.details?.status === "completed" ||
47
+ (result.details?.status === undefined && result.details?.data?.confidence === "semantic");
48
+ const status = new Text(
44
49
  applied
45
50
  ? theme.fg("success", theme.bold("Plan applied"))
46
51
  : theme.fg("error", "Refactor apply failed"),
47
52
  0,
48
53
  0,
49
54
  );
55
+ const truncation = renderTruncationDisclosure(result, theme);
56
+ if (!truncation) return status;
57
+ const container = new Container();
58
+ container.addChild(status);
59
+ container.addChild(new Spacer(1));
60
+ container.addChild(truncation);
61
+ return container;
50
62
  }
51
63
 
52
64
  const container = new Container();
65
+ renderToolDisplaySections(container, result.details?.displaySections, theme);
66
+ const truncation = renderTruncationDisclosure(result, theme);
67
+ if (truncation) {
68
+ container.addChild(new Spacer(1));
69
+ container.addChild(truncation);
70
+ }
53
71
  renderMarkdownDetail(container, result, theme);
54
72
  return container;
55
73
  }
@@ -29,6 +29,7 @@ export async function executeRefactorPlanTool(
29
29
  if (outcome.kind === "invalid-input") {
30
30
  return searchErrorResult(`**Error:** ${outcome.message}`, {
31
31
  nextQueries: ["Fix the target or operation and retry"],
32
+ message: outcome.message,
32
33
  });
33
34
  }
34
35
  if (outcome.kind === "ambiguous") {
@@ -40,6 +41,7 @@ export async function executeRefactorPlanTool(
40
41
  .join("\n");
41
42
  return searchErrorResult(`**Refactor ambiguous:**\n${candidates}`, {
42
43
  nextQueries: ["Use a precise target handle or anchor"],
44
+ message: "The refactor target is ambiguous.",
43
45
  });
44
46
  }
45
47
 
@@ -49,6 +51,8 @@ export async function executeRefactorPlanTool(
49
51
  details: {
50
52
  type: "search",
51
53
  data: assembly.details,
54
+ status: "completed",
55
+ displaySections: assembly.displaySections,
52
56
  },
53
57
  };
54
58
  }
@@ -1,41 +1,54 @@
1
- /**
2
- * TUI renderer for code_refactor_plan — renderCall + renderResult.
3
- */
1
+ /** TUI renderer for code_refactor_plan. */
4
2
  import type { Theme } from "@earendil-works/pi-coding-agent";
5
3
  import { Text } from "@earendil-works/pi-tui";
6
- import { type ResultOptios, renderSimpleResult, type ToolResult } from "../../ui/tui/common.ts";
4
+ import {
5
+ formatCallPath,
6
+ formatCallValue,
7
+ type ResultOptios,
8
+ renderSimpleResult,
9
+ type ToolRendererContext,
10
+ type ToolResult,
11
+ } from "../../ui/tui/common.ts";
7
12
 
8
- /** ── renderCall ────────────────────────────────────────────────── */
9
-
10
- export function renderRefactorPlanCall(args: unknown, theme: Theme, _context: unknown): Text {
13
+ /** Render the compact code_refactor_plan call header. */
14
+ export function renderRefactorPlanCall(
15
+ args: unknown,
16
+ theme: Theme,
17
+ _context: ToolRendererContext | undefined,
18
+ ): Text {
11
19
  const params = (args ?? {}) as {
12
- operation?: Record<string, { newName?: string }>;
13
- target?: { anchor?: { file: string }; handle?: string };
20
+ operation?: Record<string, { newName?: unknown } | undefined>;
21
+ target?: { anchor?: { file?: unknown }; handle?: unknown };
14
22
  };
15
23
 
16
24
  let content = theme.fg("toolTitle", "code_refactor_plan");
17
25
  const operation = params.operation ? Object.entries(params.operation)[0] : undefined;
18
26
  if (operation) {
19
- content += ` ${theme.fg("accent", operation[0])}`;
20
- if (operation[1].newName) content += ` ${theme.fg("muted", operation[1].newName)}`;
27
+ content += ` ${theme.fg("accent", formatCallValue(operation[0], 40) ?? "operation")}`;
28
+ const newName =
29
+ operation[1] && typeof operation[1] === "object"
30
+ ? formatCallValue(operation[1].newName)
31
+ : null;
32
+ if (newName) content += ` ${theme.fg("muted", newName)}`;
21
33
  }
22
- if (params.target?.anchor) {
23
- const file = params.target.anchor.file.split("/").pop() ?? params.target.anchor.file;
24
- content += ` ${theme.fg("muted", file)}`;
25
- } else if (params.target?.handle) {
26
- content += ` ${theme.fg("muted", params.target.handle)}`;
34
+
35
+ const anchorFile = formatCallPath(params.target?.anchor?.file);
36
+ if (anchorFile) {
37
+ content += ` ${theme.fg("muted", anchorFile)}`;
38
+ } else {
39
+ const handle = formatCallValue(params.target?.handle);
40
+ if (handle) content += ` ${theme.fg("muted", handle)}`;
27
41
  }
28
42
 
29
43
  return new Text(content, 0, 0);
30
44
  }
31
45
 
32
- /** ── renderResult ──────────────────────────────────────────────── */
33
-
46
+ /** Render code_refactor_plan progress, status, and structured result details. */
34
47
  export function renderRefactorPlanResult(
35
48
  result: ToolResult,
36
49
  options: ResultOptios,
37
50
  theme: Theme,
38
- _context: unknown,
51
+ context: ToolRendererContext | undefined,
39
52
  ): ReturnType<typeof renderSimpleResult> {
40
- return renderSimpleResult(result, options, theme, "Planning…");
53
+ return renderSimpleResult(result, options, theme, "Planning…", context);
41
54
  }
@@ -1,9 +1,13 @@
1
+ import { createHmac, randomBytes } from "node:crypto";
1
2
  import { mkdtempSync, writeFileSync } from "node:fs";
2
3
  import { tmpdir } from "node:os";
3
4
  import { join } from "node:path";
4
5
  import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
5
6
  import type { Component } from "@earendil-works/pi-tui";
7
+ import { recordDebugEvent, startDebugTimer } from "@mrclrchtr/supi-core/debug";
8
+ import { truncateIdentity } from "@mrclrchtr/supi-lsp/debug-telemetry";
6
9
  import type { WorkspaceCodeIntelligenceSession } from "../session/session.ts";
10
+ import type { CodeIntelResult, ToolOutputTruncationDetails } from "../types/index.ts";
7
11
  import { renderFindCall, renderFindResult } from "./find/tui.ts";
8
12
  import { renderGraphCall, renderGraphResult } from "./graph/tui.ts";
9
13
  import {
@@ -76,6 +80,72 @@ function getToolRenderer(name: string): ToolRenderer {
76
80
  */
77
81
  const registeredPis = new WeakSet<object>();
78
82
 
83
+ type CodeOperationOutcome = "completed" | "failed" | "canceled";
84
+
85
+ function createDebugOperationId(secret: Buffer, toolCallId: string): string {
86
+ const digest = createHmac("sha256", secret).update(toolCallId).digest().subarray(0, 16);
87
+ return `op-${digest.toString("base64url")}`;
88
+ }
89
+
90
+ function recordCodeOperationBoundary(
91
+ category: "code-operation.start" | "code-operation.finish",
92
+ operationId: string,
93
+ tool: string,
94
+ options: { cwd: string; outcome?: CodeOperationOutcome },
95
+ ): void {
96
+ recordDebugEvent({
97
+ operationId,
98
+ source: "code-intelligence",
99
+ level: "debug",
100
+ category,
101
+ message:
102
+ category === "code-operation.start" ? "Code operation started" : "Code operation finished",
103
+ cwd: truncateIdentity(options.cwd),
104
+ data: options.outcome ? { tool, outcome: options.outcome } : { tool },
105
+ });
106
+ }
107
+
108
+ function recordCodeWorkflowTiming(
109
+ timer: ReturnType<typeof startDebugTimer>,
110
+ operationId: string,
111
+ tool: string,
112
+ options: { cwd: string; outcome: CodeOperationOutcome },
113
+ ): void {
114
+ timer.finish(
115
+ {
116
+ operationId,
117
+ source: "code-intelligence",
118
+ level: "debug",
119
+ category: "workflow.timing",
120
+ message: "Code workflow finished",
121
+ cwd: truncateIdentity(options.cwd),
122
+ data: { tool, outcome: options.outcome },
123
+ },
124
+ "workflow",
125
+ );
126
+ }
127
+
128
+ function withTruncationDetails(
129
+ details: CodeIntelResult["details"],
130
+ truncation: ToolOutputTruncationDetails,
131
+ ): CodeIntelResult["details"] {
132
+ return details ? { ...details, truncation } : details;
133
+ }
134
+
135
+ function terminalCodeOperationOutcome(
136
+ error: unknown,
137
+ signal: AbortSignal | undefined,
138
+ ): CodeOperationOutcome {
139
+ if (signal?.aborted) return "canceled";
140
+ if (
141
+ error instanceof Error &&
142
+ (error.name === "AbortError" || error.name === "CodeRequestDeadlineError")
143
+ ) {
144
+ return "canceled";
145
+ }
146
+ return "failed";
147
+ }
148
+
79
149
  export function registerCodeIntelligenceTools(
80
150
  pi: ExtensionAPI,
81
151
  getOrCreateSession: (cwd: string) => WorkspaceCodeIntelligenceSession,
@@ -89,6 +159,7 @@ export function registerCodeIntelligenceTools(
89
159
  // ponytail: WeakSet on pi identity; getAllTools() is not callable during load.
90
160
  if (registeredPis.has(pi)) return;
91
161
  registeredPis.add(pi);
162
+ const operationSecret = randomBytes(32);
92
163
 
93
164
  for (const spec of specs) {
94
165
  const surface = promptSurfaces[spec.name];
@@ -100,33 +171,67 @@ export function registerCodeIntelligenceTools(
100
171
  promptGuidelines: surface.promptGuidelines,
101
172
  parameters: spec.parameters,
102
173
  // biome-ignore lint/complexity/useMaxParams: pi ToolDefinition.execute signature
103
- execute: async (_toolCallId, params, signal, onUpdate, ctx: ExtensionContext) => {
104
- const session = getOrCreateSession(ctx.cwd);
105
- session.setProjectTrusted(ctx.isProjectTrusted());
106
- const { content, details } = await spec.run(params, {
174
+ execute: async (toolCallId, params, signal, onUpdate, ctx: ExtensionContext) => {
175
+ const operationId = createDebugOperationId(operationSecret, toolCallId);
176
+ const workflowTimer = startDebugTimer();
177
+ recordCodeOperationBoundary("code-operation.start", operationId, spec.name, {
107
178
  cwd: ctx.cwd,
108
- signal,
109
- onUpdate,
110
- session,
111
- });
112
- const { text, truncated } = truncateToolContent(content, {
113
- maxLines: spec.maxLines,
114
- maxBytes: spec.maxBytes,
115
179
  });
116
- if (truncated && content.length > 0) {
117
- const dir = mkdtempSync(join(tmpdir(), "supi-ci-"));
118
- const spillPath = join(dir, `${spec.name}-output.md`);
119
- writeFileSync(spillPath, content, "utf-8");
120
- const notice = `\n_Full output saved to: \`${spillPath}\`_`;
180
+ try {
181
+ const session = getOrCreateSession(ctx.cwd);
182
+ session.setProjectTrusted(ctx.isProjectTrusted());
183
+ const { content, details } = await spec.run(params, {
184
+ cwd: ctx.cwd,
185
+ operationId,
186
+ signal,
187
+ onUpdate,
188
+ session,
189
+ });
190
+ recordCodeWorkflowTiming(workflowTimer, operationId, spec.name, {
191
+ cwd: ctx.cwd,
192
+ outcome: "completed",
193
+ });
194
+ const { text, truncated } = truncateToolContent(content, {
195
+ maxLines: spec.maxLines,
196
+ maxBytes: spec.maxBytes,
197
+ });
198
+ if (truncated && content.length > 0) {
199
+ const dir = mkdtempSync(join(tmpdir(), "supi-ci-"));
200
+ const spillPath = join(dir, `${spec.name}-output.md`);
201
+ writeFileSync(spillPath, content, "utf-8");
202
+ const notice = `\n_Full output saved to: \`${spillPath}\`_`;
203
+ recordCodeOperationBoundary("code-operation.finish", operationId, spec.name, {
204
+ cwd: ctx.cwd,
205
+ outcome: "completed",
206
+ });
207
+ return {
208
+ content: [{ type: "text" as const, text: text + notice }],
209
+ details: withTruncationDetails(details, {
210
+ truncated: true,
211
+ fullOutputPath: spillPath,
212
+ }),
213
+ };
214
+ }
215
+ recordCodeOperationBoundary("code-operation.finish", operationId, spec.name, {
216
+ cwd: ctx.cwd,
217
+ outcome: "completed",
218
+ });
121
219
  return {
122
- content: [{ type: "text" as const, text: text + notice }],
123
- details,
220
+ content: [{ type: "text" as const, text }],
221
+ details: withTruncationDetails(details, { truncated: false }),
124
222
  };
223
+ } catch (error) {
224
+ const outcome = terminalCodeOperationOutcome(error, signal);
225
+ recordCodeWorkflowTiming(workflowTimer, operationId, spec.name, {
226
+ cwd: ctx.cwd,
227
+ outcome,
228
+ });
229
+ recordCodeOperationBoundary("code-operation.finish", operationId, spec.name, {
230
+ cwd: ctx.cwd,
231
+ outcome,
232
+ });
233
+ throw error;
125
234
  }
126
- return {
127
- content: [{ type: "text" as const, text }],
128
- details,
129
- };
130
235
  },
131
236
  ...getToolRenderer(spec.name),
132
237
  });
@@ -31,6 +31,23 @@ export async function executeResolveTool(
31
31
 
32
32
  return {
33
33
  content,
34
- details: { type: "resolve", data: assembly.details },
34
+ details: {
35
+ type: "resolve",
36
+ data: assembly.details,
37
+ status:
38
+ outcome.kind === "resolved" || outcome.kind === "target-group"
39
+ ? "completed"
40
+ : outcome.kind === "disambiguation" || outcome.kind === "kind-mismatch"
41
+ ? "disambiguation"
42
+ : "invalid-input",
43
+ ...(outcome.kind === "invalid-input"
44
+ ? { message: outcome.message }
45
+ : outcome.kind === "disambiguation"
46
+ ? { message: "Multiple target matches require one candidate." }
47
+ : outcome.kind === "kind-mismatch"
48
+ ? { message: `No target matched provider kind ${outcome.requestedKind}.` }
49
+ : {}),
50
+ displaySections: assembly.displaySections,
51
+ },
35
52
  };
36
53
  }
@@ -1,42 +1,60 @@
1
- /**
2
- * TUI renderer for code_resolve — renderCall + renderResult.
3
- */
1
+ /** TUI renderer for code_resolve. */
4
2
  import type { Theme } from "@earendil-works/pi-coding-agent";
5
3
  import { Text } from "@earendil-works/pi-tui";
6
- import { type ResultOptios, renderSimpleResult, type ToolResult } from "../../ui/tui/common.ts";
4
+ import {
5
+ formatCallPath,
6
+ formatCallValue,
7
+ type ResultOptios,
8
+ renderSimpleResult,
9
+ type ToolRendererContext,
10
+ type ToolResult,
11
+ } from "../../ui/tui/common.ts";
7
12
  import type { CodeResolveToolParams } from "./execute.ts";
8
13
 
9
- /** ── renderCall ────────────────────────────────────────────────── */
10
-
11
- export function renderResolveCall(args: unknown, theme: Theme, _context: unknown): Text {
12
- const params = (args ?? {}) as CodeResolveToolParams;
13
-
14
+ /** Render the compact code_resolve call header. */
15
+ export function renderResolveCall(
16
+ args: unknown,
17
+ theme: Theme,
18
+ _context: ToolRendererContext | undefined,
19
+ ): Text {
20
+ const params = (args ?? {}) as Partial<CodeResolveToolParams>;
14
21
  let content = theme.fg("toolTitle", "code_resolve");
22
+ const target = params.target;
23
+ if (!target || typeof target !== "object") return new Text(content, 0, 0);
15
24
 
16
- if ("symbol" in params.target) {
17
- content += ` ${theme.fg("accent", params.target.symbol.query)}`;
18
- if (params.target.symbol.symbolKind) {
19
- content += theme.fg("dim", ` [${params.target.symbol.symbolKind}]`);
20
- }
21
- } else if ("anchor" in params.target) {
22
- const point = params.target.anchor;
23
- const file = point.file.split("/").pop() ?? point.file;
24
- content += ` ${theme.fg("accent", file)}${theme.fg("warning", `:${point.line}`)}`;
25
- } else if ("file" in params.target) {
26
- const file = params.target.file.split("/").pop() ?? params.target.file;
27
- content += ` ${theme.fg("accent", file)}`;
25
+ const targetRecord = target as unknown as Record<string, unknown>;
26
+ if (targetRecord.symbol && typeof targetRecord.symbol === "object") {
27
+ content += renderResolveSymbol(targetRecord.symbol, theme);
28
+ } else if (targetRecord.anchor && typeof targetRecord.anchor === "object") {
29
+ content += renderResolveAnchor(targetRecord.anchor, theme);
30
+ } else {
31
+ const file = formatCallPath(targetRecord.file);
32
+ if (file) content += ` ${theme.fg("accent", file)}`;
28
33
  }
29
34
 
30
35
  return new Text(content, 0, 0);
31
36
  }
32
37
 
33
- /** ── renderResult ──────────────────────────────────────────────── */
38
+ function renderResolveSymbol(value: object, theme: Theme): string {
39
+ const symbol = value as { query?: unknown; symbolKind?: unknown };
40
+ const query = formatCallValue(symbol.query);
41
+ const kind = formatCallValue(symbol.symbolKind, 30);
42
+ return `${query ? ` ${theme.fg("accent", query)}` : ""}${kind ? theme.fg("dim", ` [${kind}]`) : ""}`;
43
+ }
44
+
45
+ function renderResolveAnchor(value: object, theme: Theme): string {
46
+ const point = value as { file?: unknown; line?: unknown };
47
+ const file = formatCallPath(point.file);
48
+ const line = typeof point.line === "number" ? `:${point.line}` : "";
49
+ return file ? ` ${theme.fg("accent", file)}${theme.fg("warning", line)}` : "";
50
+ }
34
51
 
52
+ /** Render code_resolve progress, status, and structured result details. */
35
53
  export function renderResolveResult(
36
54
  result: ToolResult,
37
55
  options: ResultOptios,
38
56
  theme: Theme,
39
- _context: unknown,
57
+ context: ToolRendererContext | undefined,
40
58
  ): ReturnType<typeof renderSimpleResult> {
41
- return renderSimpleResult(result, options, theme, "Resolving…");
59
+ return renderSimpleResult(result, options, theme, "Resolving…", context);
42
60
  }
@@ -0,0 +1,107 @@
1
+ import type { ToolDisplaySection } from "./types.ts";
2
+
3
+ /** Maximum number of rows shown for one expanded TUI section. */
4
+ export const MAX_TUI_DISPLAY_ITEMS = 20;
5
+
6
+ /** Maximum visible characters kept in one structured TUI row. */
7
+ export const MAX_TUI_DISPLAY_LINE_LENGTH = 240;
8
+
9
+ /** Inputs for one bounded structured TUI section. */
10
+ export interface ToolDisplaySectionInput<T> {
11
+ key: string;
12
+ title: string;
13
+ items: readonly T[];
14
+ format: (item: T) => string;
15
+ totalCount?: number | null;
16
+ omittedCount?: number | null;
17
+ partialReason?: string | null;
18
+ maxItems?: number;
19
+ }
20
+
21
+ /** Build a bounded, serializable TUI section from collected facts. */
22
+ export function createToolDisplaySection<T>(input: ToolDisplaySectionInput<T>): ToolDisplaySection {
23
+ const maxItems = Math.max(0, input.maxItems ?? MAX_TUI_DISPLAY_ITEMS);
24
+ const items = input.items.slice(0, maxItems);
25
+ const lines = items.map((item) => truncateDisplayText(input.format(item)));
26
+ const displayOmittedCount = Math.max(0, input.items.length - items.length);
27
+ let totalCount: number | null;
28
+ if (input.totalCount === undefined) totalCount = input.items.length;
29
+ else totalCount = input.totalCount;
30
+ const omittedCount =
31
+ totalCount === null
32
+ ? input.omittedCount === null || input.omittedCount === undefined
33
+ ? displayOmittedCount || null
34
+ : input.omittedCount + displayOmittedCount
35
+ : Math.max(0, totalCount - lines.length);
36
+
37
+ return {
38
+ key: input.key,
39
+ title: input.title,
40
+ lines,
41
+ shownCount: lines.length,
42
+ totalCount,
43
+ omittedCount,
44
+ partialReason: input.partialReason ?? null,
45
+ };
46
+ }
47
+
48
+ /** Keep structured TUI rows readable without parsing or emitting Markdown. */
49
+ export function truncateDisplayText(
50
+ value: string,
51
+ maxLength = MAX_TUI_DISPLAY_LINE_LENGTH,
52
+ ): string {
53
+ const limit = Math.max(1, maxLength);
54
+ return value
55
+ .split("\n")
56
+ .map((line) => {
57
+ if (line.length <= limit) return line;
58
+ return `${line.slice(0, Math.max(0, limit - 1))}…`;
59
+ })
60
+ .join("\n");
61
+ }
62
+
63
+ /** Read valid structured TUI sections from persisted tool details. */
64
+ export function readToolDisplaySections(value: unknown): ToolDisplaySection[] {
65
+ if (!Array.isArray(value)) return [];
66
+ return value.flatMap((entry) => {
67
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) return [];
68
+ const record = entry as Record<string, unknown>;
69
+ if (
70
+ typeof record.key !== "string" ||
71
+ typeof record.title !== "string" ||
72
+ !Array.isArray(record.lines) ||
73
+ !record.lines.every((line) => typeof line === "string") ||
74
+ !isCount(record.shownCount) ||
75
+ !isNullableCount(record.totalCount) ||
76
+ !isNullableCount(record.omittedCount) ||
77
+ !isNullableString(record.partialReason)
78
+ ) {
79
+ return [];
80
+ }
81
+ return [
82
+ {
83
+ key: record.key,
84
+ title: record.title,
85
+ lines: record.lines
86
+ .slice(0, MAX_TUI_DISPLAY_ITEMS)
87
+ .map((line) => truncateDisplayText(line)),
88
+ shownCount: record.shownCount,
89
+ totalCount: record.totalCount,
90
+ omittedCount: record.omittedCount,
91
+ partialReason: record.partialReason,
92
+ },
93
+ ];
94
+ });
95
+ }
96
+
97
+ function isCount(value: unknown): value is number {
98
+ return typeof value === "number" && Number.isInteger(value) && value >= 0;
99
+ }
100
+
101
+ function isNullableCount(value: unknown): value is number | null {
102
+ return value === null || isCount(value);
103
+ }
104
+
105
+ function isNullableString(value: unknown): value is string | null {
106
+ return value === null || typeof value === "string";
107
+ }