@nghyane/arcane 0.1.13 → 0.1.14

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 (323) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/package.json +21 -70
  3. package/scripts/format-prompts.ts +1 -3
  4. package/src/cli/args.ts +2 -7
  5. package/src/cli/config-cli.ts +1 -1
  6. package/src/cli/plugin-cli.ts +1 -1
  7. package/src/cli/setup-cli.ts +1 -1
  8. package/src/cli/update-cli.ts +1 -1
  9. package/src/cli/web-search-cli.ts +1 -1
  10. package/src/cli.ts +0 -1
  11. package/src/commands/config.ts +1 -1
  12. package/src/commands/grep.ts +1 -1
  13. package/src/commands/jupyter.ts +1 -1
  14. package/src/commands/plugin.ts +1 -1
  15. package/src/commands/setup.ts +1 -1
  16. package/src/commands/shell.ts +1 -1
  17. package/src/commands/ssh.ts +1 -1
  18. package/src/commands/stats.ts +1 -1
  19. package/src/commands/update.ts +1 -1
  20. package/src/config/model-registry.ts +3 -4
  21. package/src/config/model-resolver.ts +36 -9
  22. package/src/config/prompt-templates.ts +1 -9
  23. package/src/config/settings-schema.ts +32 -88
  24. package/src/config/settings.ts +3 -4
  25. package/src/debug/index.ts +1 -1
  26. package/src/debug/log-formatting.ts +1 -1
  27. package/src/debug/log-viewer.ts +2 -2
  28. package/src/discovery/helpers.ts +13 -3
  29. package/src/exa/index.ts +1 -35
  30. package/src/exa/render.ts +30 -190
  31. package/src/export/html/index.ts +1 -1
  32. package/src/extensibility/custom-tools/loader.ts +1 -1
  33. package/src/extensibility/custom-tools/types.ts +5 -1
  34. package/src/extensibility/custom-tools/wrapper.ts +1 -1
  35. package/src/extensibility/extensions/runner.ts +1 -1
  36. package/src/extensibility/extensions/types.ts +1 -1
  37. package/src/extensibility/extensions/wrapper.ts +7 -15
  38. package/src/extensibility/hooks/runner.ts +1 -1
  39. package/src/extensibility/hooks/types.ts +1 -1
  40. package/src/extensibility/plugins/doctor.ts +1 -1
  41. package/src/index.ts +13 -13
  42. package/src/lsp/index.ts +77 -24
  43. package/src/lsp/render.ts +34 -583
  44. package/src/lsp/types.ts +3 -3
  45. package/src/lsp/utils.ts +1 -1
  46. package/src/main.ts +1 -1
  47. package/src/mcp/tool-bridge.ts +1 -24
  48. package/src/modes/components/assistant-message.ts +7 -7
  49. package/src/modes/components/bash-execution.ts +48 -113
  50. package/src/modes/components/bordered-loader.ts +1 -1
  51. package/src/modes/components/branch-summary-message.ts +13 -10
  52. package/src/modes/components/compaction-summary-message.ts +14 -13
  53. package/src/modes/components/context-group.ts +106 -0
  54. package/src/modes/components/custom-message.ts +4 -5
  55. package/src/modes/components/diff.ts +2 -2
  56. package/src/modes/components/dynamic-border.ts +1 -1
  57. package/src/modes/components/extensions/extension-dashboard.ts +1 -1
  58. package/src/modes/components/extensions/extension-list.ts +1 -1
  59. package/src/modes/components/extensions/inspector-panel.ts +1 -1
  60. package/src/modes/components/footer.ts +2 -2
  61. package/src/modes/components/history-search.ts +1 -1
  62. package/src/modes/components/hook-editor.ts +1 -1
  63. package/src/modes/components/hook-input.ts +1 -1
  64. package/src/modes/components/hook-message.ts +4 -5
  65. package/src/modes/components/hook-selector.ts +1 -1
  66. package/src/modes/components/index.ts +0 -2
  67. package/src/modes/components/keybinding-hints.ts +1 -1
  68. package/src/modes/components/login-dialog.ts +1 -1
  69. package/src/modes/components/mcp-add-wizard.ts +1 -1
  70. package/src/modes/components/model-selector.ts +1 -1
  71. package/src/modes/components/oauth-selector.ts +1 -1
  72. package/src/modes/components/plugin-settings.ts +1 -1
  73. package/src/modes/components/python-execution.ts +49 -92
  74. package/src/modes/components/queue-mode-selector.ts +1 -1
  75. package/src/modes/components/session-selector.ts +1 -1
  76. package/src/modes/components/settings-defs.ts +5 -10
  77. package/src/modes/components/settings-selector.ts +1 -1
  78. package/src/modes/components/show-images-selector.ts +1 -1
  79. package/src/modes/components/skill-message.ts +4 -4
  80. package/src/modes/components/status-line/segments.ts +2 -2
  81. package/src/modes/components/status-line/separators.ts +1 -1
  82. package/src/modes/components/status-line-segment-editor.ts +1 -1
  83. package/src/modes/components/status-line.ts +1 -1
  84. package/src/modes/components/theme-selector.ts +1 -1
  85. package/src/modes/components/thinking-selector.ts +1 -1
  86. package/src/modes/components/todo-display.ts +2 -4
  87. package/src/modes/components/todo-reminder.ts +4 -4
  88. package/src/modes/components/tool-execution.ts +118 -440
  89. package/src/modes/components/tool-image-display.ts +107 -0
  90. package/src/modes/components/tree-selector.ts +2 -2
  91. package/src/modes/components/ttsr-notification.ts +4 -17
  92. package/src/modes/components/user-message-selector.ts +1 -1
  93. package/src/modes/components/user-message.ts +9 -10
  94. package/src/modes/components/welcome.ts +1 -1
  95. package/src/modes/controllers/command-controller.ts +1 -1
  96. package/src/modes/controllers/event-controller.ts +58 -187
  97. package/src/modes/controllers/extension-ui-controller.ts +1 -1
  98. package/src/modes/controllers/input-controller.ts +3 -1
  99. package/src/modes/controllers/mcp-command-controller.ts +1 -1
  100. package/src/modes/controllers/selector-controller.ts +3 -26
  101. package/src/modes/controllers/ssh-command-controller.ts +1 -1
  102. package/src/modes/interactive-mode.ts +3 -7
  103. package/src/modes/print-mode.ts +5 -5
  104. package/src/modes/rpc/rpc-mode.ts +1 -1
  105. package/src/modes/types.ts +1 -2
  106. package/src/modes/utils/ui-helpers.ts +34 -32
  107. package/src/patch/edit-tool.ts +742 -0
  108. package/src/patch/index.ts +32 -898
  109. package/src/patch/schemas.ts +208 -0
  110. package/src/patch/shared.ts +83 -151
  111. package/src/prompts/agents/explore.md +22 -37
  112. package/src/prompts/agents/frontmatter.md +1 -1
  113. package/src/prompts/agents/init.md +2 -2
  114. package/src/prompts/agents/librarian.md +30 -21
  115. package/src/prompts/agents/oracle.md +9 -2
  116. package/src/prompts/agents/reviewer.md +15 -49
  117. package/src/prompts/agents/task.md +17 -9
  118. package/src/prompts/compaction/branch-summary-context.md +1 -1
  119. package/src/prompts/compaction/branch-summary-preamble.md +1 -1
  120. package/src/prompts/compaction/branch-summary.md +4 -1
  121. package/src/prompts/compaction/compaction-short-summary.md +1 -1
  122. package/src/prompts/compaction/compaction-summary-context.md +1 -1
  123. package/src/prompts/compaction/compaction-summary.md +4 -1
  124. package/src/prompts/compaction/compaction-turn-prefix.md +1 -1
  125. package/src/prompts/compaction/compaction-update-summary.md +1 -1
  126. package/src/prompts/memories/consolidation.md +1 -1
  127. package/src/prompts/memories/read_path.md +1 -1
  128. package/src/prompts/memories/stage_one_input.md +1 -1
  129. package/src/prompts/memories/stage_one_system.md +1 -1
  130. package/src/prompts/review-request.md +1 -1
  131. package/src/prompts/system/agent-creation-architect.md +1 -1
  132. package/src/prompts/system/agent-creation-user.md +1 -1
  133. package/src/prompts/system/custom-system-prompt.md +1 -1
  134. package/src/prompts/system/file-operations.md +1 -1
  135. package/src/prompts/system/subagent-system-prompt.md +2 -2
  136. package/src/prompts/system/summarization-system.md +1 -1
  137. package/src/prompts/system/system-prompt.md +163 -178
  138. package/src/prompts/system/title-system.md +1 -1
  139. package/src/prompts/system/ttsr-interrupt.md +1 -1
  140. package/src/prompts/system/verification-reminder.md +6 -0
  141. package/src/prompts/system/web-search.md +1 -1
  142. package/src/sdk.ts +0 -9
  143. package/src/session/agent-session.ts +244 -1459
  144. package/src/session/model-controller.ts +406 -0
  145. package/src/session/retry-utils.ts +71 -0
  146. package/src/session/session-manager.ts +22 -186
  147. package/src/session/session-types.ts +312 -0
  148. package/src/session/stats.ts +387 -0
  149. package/src/session/streaming-edit.ts +258 -0
  150. package/src/session/ttsr.ts +213 -0
  151. package/src/slash-commands/builtin-registry.ts +0 -8
  152. package/src/stt/recorder.ts +2 -2
  153. package/src/system-prompt.ts +1 -14
  154. package/src/task/agents.ts +7 -33
  155. package/src/task/executor.ts +50 -438
  156. package/src/task/index.ts +104 -71
  157. package/src/task/progress-tracker.ts +390 -0
  158. package/src/task/render.ts +371 -187
  159. package/src/task/subprocess-tool-registry.ts +1 -1
  160. package/src/task/types.ts +14 -47
  161. package/src/tools/ask.ts +31 -42
  162. package/src/tools/bash-interactive.ts +2 -2
  163. package/src/tools/bash-interceptor.ts +2 -2
  164. package/src/tools/bash-normalize.ts +1 -1
  165. package/src/tools/bash-skill-urls.ts +2 -2
  166. package/src/tools/bash.ts +87 -136
  167. package/src/tools/browser.ts +54 -84
  168. package/src/tools/create-tools.ts +186 -0
  169. package/src/tools/default-renderer.ts +104 -0
  170. package/src/tools/explore.ts +11 -10
  171. package/src/tools/fetch.ts +24 -114
  172. package/src/tools/find.ts +48 -132
  173. package/src/tools/gemini-image.ts +5 -15
  174. package/src/tools/github.ts +450 -0
  175. package/src/tools/grep.ts +43 -179
  176. package/src/tools/index.ts +35 -198
  177. package/src/tools/json-tree.ts +3 -3
  178. package/src/tools/librarian.ts +18 -18
  179. package/src/tools/list-limit.ts +2 -2
  180. package/src/tools/notebook.ts +35 -87
  181. package/src/tools/oracle.ts +25 -25
  182. package/src/tools/output-meta.ts +89 -4
  183. package/src/tools/output-utils.ts +2 -2
  184. package/src/tools/python.ts +86 -637
  185. package/src/tools/read.ts +36 -119
  186. package/src/tools/reviewer-tool.ts +19 -21
  187. package/src/tools/search-code.ts +128 -0
  188. package/src/tools/ssh.ts +67 -126
  189. package/src/tools/subagent-tool.ts +197 -123
  190. package/src/tools/todo-write.ts +15 -31
  191. package/src/tools/tool-errors.ts +0 -30
  192. package/src/tools/undo-edit.ts +30 -67
  193. package/src/tools/write.ts +78 -127
  194. package/src/tui/code-cell.ts +4 -4
  195. package/src/tui/file-list.ts +2 -2
  196. package/src/tui/output-block.ts +1 -1
  197. package/src/tui/status-line.ts +1 -1
  198. package/src/tui/tree-list.ts +2 -2
  199. package/src/tui/types.ts +1 -1
  200. package/src/tui/utils.ts +1 -1
  201. package/src/{tools → ui}/render-utils.ts +87 -126
  202. package/src/utils/external-editor.ts +4 -4
  203. package/src/utils/file-mentions.ts +1 -1
  204. package/src/utils/index.ts +30 -0
  205. package/src/utils/tools-manager.ts +9 -19
  206. package/src/web/github-client.ts +290 -0
  207. package/src/web/scrapers/github.ts +11 -62
  208. package/src/web/search/auth.ts +1 -3
  209. package/src/web/search/index.ts +82 -46
  210. package/src/web/search/provider.ts +11 -16
  211. package/src/web/search/providers/grep.ts +160 -0
  212. package/src/web/search/render.ts +48 -235
  213. package/src/web/search/types.ts +1 -1
  214. package/src/commands/commit.ts +0 -36
  215. package/src/commit/agentic/agent.ts +0 -311
  216. package/src/commit/agentic/fallback.ts +0 -96
  217. package/src/commit/agentic/index.ts +0 -359
  218. package/src/commit/agentic/prompts/analyze-file.md +0 -22
  219. package/src/commit/agentic/prompts/session-user.md +0 -25
  220. package/src/commit/agentic/prompts/split-confirm.md +0 -1
  221. package/src/commit/agentic/prompts/system.md +0 -38
  222. package/src/commit/agentic/state.ts +0 -69
  223. package/src/commit/agentic/tools/analyze-file.ts +0 -118
  224. package/src/commit/agentic/tools/git-file-diff.ts +0 -194
  225. package/src/commit/agentic/tools/git-hunk.ts +0 -50
  226. package/src/commit/agentic/tools/git-overview.ts +0 -84
  227. package/src/commit/agentic/tools/index.ts +0 -56
  228. package/src/commit/agentic/tools/propose-changelog.ts +0 -128
  229. package/src/commit/agentic/tools/propose-commit.ts +0 -154
  230. package/src/commit/agentic/tools/recent-commits.ts +0 -81
  231. package/src/commit/agentic/tools/split-commit.ts +0 -280
  232. package/src/commit/agentic/topo-sort.ts +0 -44
  233. package/src/commit/agentic/trivial.ts +0 -51
  234. package/src/commit/agentic/validation.ts +0 -200
  235. package/src/commit/analysis/conventional.ts +0 -165
  236. package/src/commit/analysis/index.ts +0 -4
  237. package/src/commit/analysis/scope.ts +0 -242
  238. package/src/commit/analysis/summary.ts +0 -112
  239. package/src/commit/analysis/validation.ts +0 -66
  240. package/src/commit/changelog/detect.ts +0 -37
  241. package/src/commit/changelog/generate.ts +0 -110
  242. package/src/commit/changelog/index.ts +0 -234
  243. package/src/commit/changelog/parse.ts +0 -44
  244. package/src/commit/cli.ts +0 -93
  245. package/src/commit/git/diff.ts +0 -148
  246. package/src/commit/git/errors.ts +0 -9
  247. package/src/commit/git/index.ts +0 -211
  248. package/src/commit/git/operations.ts +0 -54
  249. package/src/commit/index.ts +0 -5
  250. package/src/commit/map-reduce/index.ts +0 -64
  251. package/src/commit/map-reduce/map-phase.ts +0 -178
  252. package/src/commit/map-reduce/reduce-phase.ts +0 -145
  253. package/src/commit/map-reduce/utils.ts +0 -9
  254. package/src/commit/message.ts +0 -11
  255. package/src/commit/model-selection.ts +0 -69
  256. package/src/commit/pipeline.ts +0 -243
  257. package/src/commit/prompts/analysis-system.md +0 -148
  258. package/src/commit/prompts/analysis-user.md +0 -38
  259. package/src/commit/prompts/changelog-system.md +0 -50
  260. package/src/commit/prompts/changelog-user.md +0 -18
  261. package/src/commit/prompts/file-observer-system.md +0 -24
  262. package/src/commit/prompts/file-observer-user.md +0 -8
  263. package/src/commit/prompts/reduce-system.md +0 -50
  264. package/src/commit/prompts/reduce-user.md +0 -17
  265. package/src/commit/prompts/summary-retry.md +0 -3
  266. package/src/commit/prompts/summary-system.md +0 -38
  267. package/src/commit/prompts/summary-user.md +0 -13
  268. package/src/commit/prompts/types-description.md +0 -2
  269. package/src/commit/types.ts +0 -109
  270. package/src/commit/utils/exclusions.ts +0 -42
  271. package/src/mcp/render.ts +0 -123
  272. package/src/modes/components/agent-dashboard.ts +0 -1130
  273. package/src/modes/components/codemode-group.ts +0 -369
  274. package/src/modes/components/read-tool-group.ts +0 -119
  275. package/src/modes/components/visual-truncate.ts +0 -63
  276. package/src/prompts/system/subagent-user-prompt.md +0 -8
  277. package/src/prompts/tools/ask.md +0 -44
  278. package/src/prompts/tools/bash.md +0 -24
  279. package/src/prompts/tools/browser.md +0 -33
  280. package/src/prompts/tools/calculator.md +0 -12
  281. package/src/prompts/tools/explore.md +0 -29
  282. package/src/prompts/tools/fetch.md +0 -16
  283. package/src/prompts/tools/find.md +0 -18
  284. package/src/prompts/tools/gemini-image.md +0 -23
  285. package/src/prompts/tools/grep.md +0 -28
  286. package/src/prompts/tools/hashline.md +0 -232
  287. package/src/prompts/tools/librarian.md +0 -24
  288. package/src/prompts/tools/lsp.md +0 -28
  289. package/src/prompts/tools/oracle.md +0 -26
  290. package/src/prompts/tools/patch.md +0 -74
  291. package/src/prompts/tools/python.md +0 -66
  292. package/src/prompts/tools/read.md +0 -36
  293. package/src/prompts/tools/replace.md +0 -38
  294. package/src/prompts/tools/reviewer.md +0 -41
  295. package/src/prompts/tools/ssh.md +0 -51
  296. package/src/prompts/tools/task-summary.md +0 -28
  297. package/src/prompts/tools/task.md +0 -146
  298. package/src/prompts/tools/todo-write.md +0 -65
  299. package/src/prompts/tools/undo-edit.md +0 -7
  300. package/src/prompts/tools/web-search.md +0 -19
  301. package/src/prompts/tools/write.md +0 -18
  302. package/src/task/batch.ts +0 -102
  303. package/src/task/discovery.ts +0 -126
  304. package/src/task/parallel.ts +0 -84
  305. package/src/task/template.ts +0 -32
  306. package/src/tools/calculator.ts +0 -537
  307. package/src/tools/jtd-to-typescript.ts +0 -198
  308. package/src/tools/renderers.ts +0 -60
  309. package/src/tools/tool-result.ts +0 -86
  310. /package/src/{modes/theme → theme}/dark.json +0 -0
  311. /package/src/{modes/theme → theme}/defaults/dark-catppuccin.json +0 -0
  312. /package/src/{modes/theme → theme}/defaults/dark-dracula.json +0 -0
  313. /package/src/{modes/theme → theme}/defaults/dark-gruvbox.json +0 -0
  314. /package/src/{modes/theme → theme}/defaults/dark-solarized.json +0 -0
  315. /package/src/{modes/theme → theme}/defaults/dark-tokyo-night.json +0 -0
  316. /package/src/{modes/theme → theme}/defaults/index.ts +0 -0
  317. /package/src/{modes/theme → theme}/defaults/light-catppuccin.json +0 -0
  318. /package/src/{modes/theme → theme}/defaults/light-github.json +0 -0
  319. /package/src/{modes/theme → theme}/defaults/light-solarized.json +0 -0
  320. /package/src/{modes/theme → theme}/light.json +0 -0
  321. /package/src/{modes/theme → theme}/mermaid-cache.ts +0 -0
  322. /package/src/{modes/theme → theme}/theme-schema.json +0 -0
  323. /package/src/{modes/theme → theme}/theme.ts +0 -0
package/src/lsp/render.ts CHANGED
@@ -1,26 +1,11 @@
1
1
  /**
2
2
  * LSP Tool TUI Rendering
3
- *
4
- * Renders LSP tool calls and results in the TUI with:
5
- * - Syntax-highlighted hover information
6
- * - Color-coded diagnostics by severity
7
- * - Grouped references and symbols
8
- * - Collapsible/expandable views
9
3
  */
10
4
  import type { RenderResultOptions } from "@nghyane/arcane-agent";
11
- import { type HighlightColors, highlightCode as nativeHighlightCode, supportsLanguage } from "@nghyane/arcane-natives";
12
5
  import { type Component, Text } from "@nghyane/arcane-tui";
13
- import { getLanguageFromPath, type Theme } from "../modes/theme/theme";
14
- import {
15
- formatExpandHint,
16
- formatMoreItems,
17
- formatStatusIcon,
18
- shortenPath,
19
- TRUNCATE_LENGTHS,
20
- truncateToWidth,
21
- } from "../tools/render-utils";
6
+ import type { Theme } from "../theme/theme";
22
7
  import { renderStatusLine } from "../tui";
23
- import { CachedOutputBlock } from "../tui/output-block";
8
+ import { formatCount, formatErrorMessage, shortenPath, TRUNCATE_LENGTHS, truncateToWidth } from "../ui/render-utils";
24
9
  import type { LspParams, LspToolDetails } from "./types";
25
10
 
26
11
  // =============================================================================
@@ -97,593 +82,59 @@ export function renderCall(args: LspParams, _options: RenderResultOptions, theme
97
82
  // =============================================================================
98
83
 
99
84
  /**
100
- * Render LSP tool result with intelligent formatting based on result type.
101
- * Detects hover, diagnostics, references, symbols, etc. and formats accordingly.
85
+ * Render LSP tool result as a single dim status line.
102
86
  */
103
87
  export function renderResult(
104
88
  result: { content: Array<{ type: string; text?: string }>; details?: LspToolDetails; isError?: boolean },
105
- options: RenderResultOptions,
89
+ _options: RenderResultOptions,
106
90
  theme: Theme,
107
91
  args?: LspParams & { file?: string; files?: string[] },
108
92
  ): Component {
109
93
  const content = result.content?.[0];
110
- if (!content || content.type !== "text" || !("text" in content) || !content.text) {
111
- const icon = formatStatusIcon("warning", theme, options.spinnerFrame);
112
- const header = `${icon} LSP`;
113
- return new Text([header, theme.fg("dim", "No result")].join("\n"), 0, 0);
94
+ const text = content?.type === "text" ? (content.text ?? "") : "";
95
+
96
+ if (result.isError || text.startsWith("Error:")) {
97
+ const errorText = result.content?.find(c => c.type === "text")?.text || "Unknown error";
98
+ return new Text(formatErrorMessage(errorText, theme), 0, 0);
114
99
  }
115
100
 
116
- const text = content.text;
117
- const lines = text.split("\n");
101
+ const request = args ?? result.details?.request;
102
+ const action = (request?.action ?? result.details?.action ?? "request").replace(/_/g, " ");
103
+ const meta: string[] = [];
118
104
 
119
- // Static type detection (result content doesn't change between renders)
120
- const codeBlockMatch = text.match(/```(\w*)\n([\s\S]*?)```/);
105
+ // Extract counts from result text
121
106
  const errorMatch = text.match(/(\d+)\s+error\(s\)/);
122
107
  const warningMatch = text.match(/(\d+)\s+warning\(s\)/);
123
108
  const refMatch = text.match(/(\d+)\s+reference\(s\)/);
124
- const symbolsMatch = text.match(/Symbols in (.+):/);
125
- const hasStatusError = text.includes(theme.status.error);
109
+ const renameMatch = text.match(/Applied.*?(\d+)\s+file/);
126
110
 
127
- // Static request info
128
- const request = args ?? result.details?.request;
129
- const requestLines: string[] = [];
111
+ let description = "";
130
112
  if (request?.file) {
131
- requestLines.push(theme.fg("toolOutput", request.file));
113
+ description = shortenPath(request.file);
114
+ if (request.line !== undefined) description += `:${request.line}`;
132
115
  } else if (request?.files?.length === 1) {
133
- requestLines.push(theme.fg("toolOutput", request.files[0]));
116
+ description = shortenPath(request.files[0]);
134
117
  } else if (request?.files?.length) {
135
- requestLines.push(theme.fg("dim", `${request.files.length} file(s)`));
136
- }
137
- if (request?.line !== undefined) {
138
- const col = request.column !== undefined ? `:${request.column}` : "";
139
- requestLines.push(theme.fg("dim", `line ${request.line}${col}`));
140
- }
141
- if (request?.end_line !== undefined) {
142
- const endCol = request.end_character !== undefined ? `:${request.end_character}` : "";
143
- requestLines.push(theme.fg("dim", `end ${request.end_line}${endCol}`));
144
- }
145
- if (request?.query) requestLines.push(theme.fg("dim", `query: ${request.query}`));
146
- if (request?.new_name) requestLines.push(theme.fg("dim", `new name: ${request.new_name}`));
147
- if (request?.apply !== undefined) requestLines.push(theme.fg("dim", `apply: ${request.apply ? "true" : "false"}`));
148
- if (request?.include_declaration !== undefined) {
149
- requestLines.push(theme.fg("dim", `include declaration: ${request.include_declaration ? "true" : "false"}`));
150
- }
151
-
152
- const outputBlock = new CachedOutputBlock();
153
-
154
- return {
155
- render(width: number): string[] {
156
- // Read mutable state at render time
157
- const { expanded, isPartial, spinnerFrame } = options;
158
-
159
- // Determine label, state, bodyLines based on type + current expanded
160
- let label = "Result";
161
- let state: "success" | "warning" | "error" = "success";
162
- let bodyLines: string[] = [];
163
-
164
- if (codeBlockMatch) {
165
- label = "Hover";
166
- bodyLines = renderHover(codeBlockMatch, text, lines, expanded, theme);
167
- } else if (errorMatch || warningMatch || hasStatusError) {
168
- label = "Diagnostics";
169
- const errorCount = errorMatch ? Number.parseInt(errorMatch[1], 10) : 0;
170
- const warnCount = warningMatch ? Number.parseInt(warningMatch[1], 10) : 0;
171
- state = errorCount > 0 ? "error" : warnCount > 0 ? "warning" : "success";
172
- bodyLines = renderDiagnostics(errorMatch, warningMatch, lines, expanded, theme);
173
- } else if (refMatch) {
174
- label = "References";
175
- bodyLines = renderReferences(refMatch, lines, expanded, theme);
176
- } else if (symbolsMatch) {
177
- label = "Symbols";
178
- bodyLines = renderSymbols(symbolsMatch, lines, expanded, theme);
179
- } else {
180
- label = "Response";
181
- bodyLines = renderGeneric(text, lines, expanded, theme);
182
- }
183
-
184
- const actionLabel = (request?.action ?? result.details?.action ?? label.toLowerCase()).replace(/_/g, " ");
185
- const status = isPartial ? "running" : result.isError ? "error" : "success";
186
- const icon = formatStatusIcon(status, theme, spinnerFrame);
187
- const header = `${icon} LSP ${actionLabel}`;
188
-
189
- return outputBlock.render(
190
- {
191
- header,
192
- state,
193
- sections: [
194
- ...(requestLines.length > 0 ? [{ lines: requestLines }] : []),
195
- { label: theme.fg("toolTitle", "Response"), lines: bodyLines },
196
- ],
197
- width,
198
- applyBg: false,
199
- },
200
- theme,
201
- );
202
- },
203
- invalidate() {
204
- outputBlock.invalidate();
205
- },
206
- };
207
- }
208
-
209
- // =============================================================================
210
- // Hover Rendering
211
- // =============================================================================
212
-
213
- /**
214
- * Render hover information with syntax-highlighted code blocks.
215
- */
216
- function renderHover(
217
- codeBlockMatch: RegExpMatchArray,
218
- fullText: string,
219
- _lines: string[],
220
- expanded: boolean,
221
- theme: Theme,
222
- ): string[] {
223
- const lang = codeBlockMatch[1] || "";
224
- const code = codeBlockMatch[2].trim();
225
- const codeStart = codeBlockMatch.index ?? 0;
226
- const beforeCode = fullText.slice(0, codeStart).trimEnd();
227
- const afterCode = fullText.slice(fullText.indexOf("```", 3) + 3).trim();
228
-
229
- const codeLines = highlightCode(code, lang, theme);
230
- const icon = theme.styledSymbol("status.info", "accent");
231
- const langLabel = lang ? theme.fg("mdCodeBlockBorder", ` ${lang}`) : "";
232
-
233
- if (expanded) {
234
- const h = theme.boxSharp.horizontal;
235
- const v = theme.boxSharp.vertical;
236
- const top = `${theme.boxSharp.topLeft}${h.repeat(3)}`;
237
- const bottom = `${theme.boxSharp.bottomLeft}${h.repeat(3)}`;
238
- let output = `${icon}${langLabel}`;
239
- if (beforeCode) {
240
- for (const line of beforeCode.split("\n")) {
241
- output += `\n ${theme.fg("muted", line)}`;
242
- }
243
- }
244
- output += `\n ${theme.fg("mdCodeBlockBorder", top)}`;
245
- for (const line of codeLines) {
246
- output += `\n ${theme.fg("mdCodeBlockBorder", v)} ${line}`;
247
- }
248
- output += `\n ${theme.fg("mdCodeBlockBorder", bottom)}`;
249
- if (afterCode) {
250
- output += `\n ${theme.fg("muted", afterCode)}`;
251
- }
252
- return output.split("\n");
253
- }
254
-
255
- // Collapsed view
256
- const firstCodeLine = codeLines[0] || "";
257
- const hasMore = codeLines.length > 1 || Boolean(afterCode) || Boolean(beforeCode);
258
- const expandHint = formatExpandHint(theme, expanded, hasMore);
259
-
260
- let output = `${icon}${langLabel}${expandHint}`;
261
- if (beforeCode) {
262
- const preview = truncateToWidth(beforeCode, TRUNCATE_LENGTHS.TITLE);
263
- output += `\n ${theme.fg("dim", theme.tree.branch)} ${theme.fg("muted", preview)}`;
264
- }
265
- const h = theme.boxSharp.horizontal;
266
- const v = theme.boxSharp.vertical;
267
- const bottom = `${theme.boxSharp.bottomLeft}${h.repeat(3)}`;
268
- output += `\n ${theme.fg("mdCodeBlockBorder", v)} ${firstCodeLine}`;
269
-
270
- if (codeLines.length > 1) {
271
- output += `\n ${theme.fg("mdCodeBlockBorder", v)} ${theme.fg("muted", `… ${codeLines.length - 1} more lines`)}`;
272
- }
273
-
274
- if (afterCode) {
275
- const docPreview = truncateToWidth(afterCode, TRUNCATE_LENGTHS.TITLE);
276
- output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", docPreview)}`;
277
- } else {
278
- output += `\n ${theme.fg("mdCodeBlockBorder", bottom)}`;
279
- }
280
-
281
- return output.split("\n");
282
- }
283
-
284
- /**
285
- * Syntax highlight code using native highlighter.
286
- */
287
- function highlightCode(codeText: string, language: string, theme: Theme): string[] {
288
- const validLang = language && supportsLanguage(language) ? language : undefined;
289
- try {
290
- const colors: HighlightColors = {
291
- comment: theme.getFgAnsi("syntaxComment"),
292
- keyword: theme.getFgAnsi("syntaxKeyword"),
293
- function: theme.getFgAnsi("syntaxFunction"),
294
- variable: theme.getFgAnsi("syntaxVariable"),
295
- string: theme.getFgAnsi("syntaxString"),
296
- number: theme.getFgAnsi("syntaxNumber"),
297
- type: theme.getFgAnsi("syntaxType"),
298
- operator: theme.getFgAnsi("syntaxOperator"),
299
- punctuation: theme.getFgAnsi("syntaxPunctuation"),
300
- inserted: theme.getFgAnsi("toolDiffAdded"),
301
- deleted: theme.getFgAnsi("toolDiffRemoved"),
302
- };
303
- return nativeHighlightCode(codeText, validLang, colors).split("\n");
304
- } catch {
305
- return codeText.split("\n");
306
- }
307
- }
308
-
309
- // =============================================================================
310
- // Diagnostics Rendering
311
- // =============================================================================
312
-
313
- function formatDiagnosticLocation(file: string, line: string | number, col: string | number, theme: Theme): string {
314
- const lang = getLanguageFromPath(file);
315
- const icon = theme.fg("muted", theme.getLangIcon(lang));
316
- return `${icon} ${file}:${line}:${col}`;
317
- }
318
-
319
- /**
320
- * Render diagnostics with color-coded severity.
321
- */
322
- function renderDiagnostics(
323
- errorMatch: RegExpMatchArray | null,
324
- warningMatch: RegExpMatchArray | null,
325
- lines: string[],
326
- expanded: boolean,
327
- theme: Theme,
328
- ): string[] {
329
- const errorCount = errorMatch ? Number.parseInt(errorMatch[1], 10) : 0;
330
- const warnCount = warningMatch ? Number.parseInt(warningMatch[1], 10) : 0;
331
-
332
- const icon =
333
- errorCount > 0
334
- ? theme.styledSymbol("status.error", "error")
335
- : warnCount > 0
336
- ? theme.styledSymbol("status.warning", "warning")
337
- : theme.styledSymbol("status.success", "success");
338
-
339
- const meta: string[] = [];
340
- if (errorCount > 0) meta.push(`${errorCount} error${errorCount !== 1 ? "s" : ""}`);
341
- if (warnCount > 0) meta.push(`${warnCount} warning${warnCount !== 1 ? "s" : ""}`);
342
- if (meta.length === 0) meta.push("No issues");
343
-
344
- const diagLines = lines.filter(l => l.includes(theme.status.error) || /:\d+:\d+/.test(l));
345
- const parsedDiagnostics = diagLines
346
- .map(line => parseDiagnosticLine(line))
347
- .filter((diag): diag is ParsedDiagnostic => diag !== null);
348
- const fallbackDiagnostics: RawDiagnostic[] = diagLines.map(line => ({ raw: line.trim() }));
349
-
350
- if (expanded) {
351
- let output = `${icon} ${theme.fg("dim", meta.join(theme.sep.dot))}`;
352
- const items: DiagnosticItem[] = parsedDiagnostics.length > 0 ? parsedDiagnostics : fallbackDiagnostics;
353
- for (let i = 0; i < items.length; i++) {
354
- const item = items[i];
355
- const isLast = i === items.length - 1;
356
- const branch = isLast ? theme.tree.last : theme.tree.branch;
357
- const detailPrefix = isLast ? " " : `${theme.tree.vertical} `;
358
- if ("raw" in item) {
359
- output += `\n ${theme.fg("dim", branch)} ${theme.fg("muted", item.raw)}`;
360
- continue;
361
- }
362
- const severityColor = severityToColor(item.severity);
363
- const location = formatDiagnosticLocation(item.file, item.line, item.col, theme);
364
- output += `\n ${theme.fg("dim", branch)} ${theme.fg(severityColor, location)} ${theme.fg(
365
- "dim",
366
- `[${item.severity}]`,
367
- )}`;
368
- if (item.message) {
369
- output += `\n ${theme.fg("dim", detailPrefix)}${theme.fg(
370
- "muted",
371
- truncateToWidth(item.message, TRUNCATE_LENGTHS.LINE),
372
- )}`;
373
- }
374
- }
375
- return output.split("\n");
376
- }
377
-
378
- // Collapsed view
379
- const previewItems: DiagnosticItem[] =
380
- parsedDiagnostics.length > 0 ? parsedDiagnostics.slice(0, 3) : fallbackDiagnostics.slice(0, 3);
381
- const remaining =
382
- (parsedDiagnostics.length > 0 ? parsedDiagnostics.length : fallbackDiagnostics.length) - previewItems.length;
383
- const expandHint = formatExpandHint(theme, expanded, remaining > 0);
384
- let output = `${icon} ${theme.fg("dim", meta.join(theme.sep.dot))}${expandHint}`;
385
- for (let i = 0; i < previewItems.length; i++) {
386
- const item = previewItems[i];
387
- const isLast = i === previewItems.length - 1 && remaining <= 0;
388
- const branch = isLast ? theme.tree.last : theme.tree.branch;
389
- if ("raw" in item) {
390
- output += `\n ${theme.fg("dim", branch)} ${theme.fg("muted", item.raw)}`;
391
- continue;
392
- }
393
- const severityColor = severityToColor(item.severity);
394
- const location = formatDiagnosticLocation(item.file, item.line, item.col, theme);
395
- const message = item.message
396
- ? ` ${theme.fg("muted", truncateToWidth(item.message, TRUNCATE_LENGTHS.CONTENT))}`
397
- : "";
398
- output += `\n ${theme.fg("dim", branch)} ${theme.fg(severityColor, location)}${message}`;
399
- }
400
- if (remaining > 0) {
401
- output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", `… ${remaining} more`)}`;
402
- }
403
-
404
- return output.split("\n");
405
- }
406
-
407
- // =============================================================================
408
- // References Rendering
409
- // =============================================================================
410
-
411
- /**
412
- * Render references grouped by file.
413
- */
414
- function renderReferences(refMatch: RegExpMatchArray, lines: string[], expanded: boolean, theme: Theme): string[] {
415
- const refCount = Number.parseInt(refMatch[1], 10);
416
- const icon =
417
- refCount > 0 ? theme.styledSymbol("status.success", "success") : theme.styledSymbol("status.warning", "warning");
418
-
419
- const locLines = lines.filter(l => /^\s*\S+:\d+:\d+/.test(l));
420
-
421
- // Group by file
422
- const byFile = new Map<string, Array<[string, string]>>();
423
- for (const loc of locLines) {
424
- const match = loc.trim().match(/^(.+):(\d+):(\d+)$/);
425
- if (match) {
426
- const [, file, line, col] = match;
427
- if (!byFile.has(file)) byFile.set(file, []);
428
- byFile.get(file)!.push([line, col]);
429
- }
118
+ description = `${request.files.length} files`;
430
119
  }
431
120
 
432
- const files = Array.from(byFile.keys());
433
-
434
- const renderGrouped = (maxFiles: number, maxLocsPerFile: number, showHint: boolean): string => {
435
- const expandHint = formatExpandHint(theme, undefined, showHint);
436
- let output = `${icon} ${theme.fg("dim", `${refCount} found`)}${expandHint}`;
437
-
438
- const filesToShow = files.slice(0, maxFiles);
439
- for (let fi = 0; fi < filesToShow.length; fi++) {
440
- const file = filesToShow[fi];
441
- const locs = byFile.get(file)!;
442
- const isLastFile = fi === filesToShow.length - 1 && files.length <= maxFiles;
443
- const fileBranch = isLastFile ? theme.tree.last : theme.tree.branch;
444
- const fileCont = isLastFile ? " " : `${theme.tree.vertical} `;
445
-
446
- const fileMeta = `${locs.length} reference${locs.length !== 1 ? "s" : ""}`;
447
- output += `\n ${theme.fg("dim", fileBranch)} ${theme.fg("accent", file)} ${theme.fg("dim", fileMeta)}`;
448
-
449
- if (maxLocsPerFile > 0) {
450
- const locsToShow = locs.slice(0, maxLocsPerFile);
451
- for (let li = 0; li < locsToShow.length; li++) {
452
- const [line, col] = locsToShow[li];
453
- const isLastLoc = li === locsToShow.length - 1 && locs.length <= maxLocsPerFile;
454
- const locBranch = isLastLoc ? theme.tree.last : theme.tree.branch;
455
- const locCont = isLastLoc ? " " : `${theme.tree.vertical} `;
456
- output += `\n ${theme.fg("dim", fileCont)}${theme.fg("dim", locBranch)} ${theme.fg(
457
- "muted",
458
- `line ${line}, col ${col}`,
459
- )}`;
460
- if (expanded) {
461
- const context = `at ${file}:${line}:${col}`;
462
- output += `\n ${theme.fg("dim", fileCont)}${theme.fg("dim", locCont)}${theme.fg(
463
- "muted",
464
- truncateToWidth(context, TRUNCATE_LENGTHS.LINE),
465
- )}`;
466
- }
467
- }
468
- if (locs.length > maxLocsPerFile) {
469
- output += `\n ${theme.fg("dim", fileCont)}${theme.fg("dim", theme.tree.last)} ${theme.fg(
470
- "muted",
471
- `… ${locs.length - maxLocsPerFile} more`,
472
- )}`;
473
- }
474
- }
475
- }
476
-
477
- if (files.length > maxFiles) {
478
- output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg(
479
- "muted",
480
- formatMoreItems(files.length - maxFiles, "file"),
481
- )}`;
482
- }
483
-
484
- return output;
485
- };
486
-
487
- if (expanded) {
488
- return renderGrouped(files.length, 3, false).split("\n");
121
+ if (errorMatch) meta.push(`${errorMatch[1]} errors`);
122
+ if (warningMatch) meta.push(`${warningMatch[1]} warnings`);
123
+ if (refMatch) {
124
+ meta.push(formatCount("ref", Number.parseInt(refMatch[1], 10)));
125
+ const fileSet = new Set(
126
+ text
127
+ .split("\n")
128
+ .map(l => l.match(/^\s*(\S+):\d+:\d+/)?.[1])
129
+ .filter(Boolean),
130
+ );
131
+ if (fileSet.size > 0) meta.push(formatCount("file", fileSet.size));
489
132
  }
133
+ if (renameMatch) meta.push(`${renameMatch[1]} files`);
134
+ if (request?.new_name && request?.query) meta.push(`${request.query} → ${request.new_name}`);
490
135
 
491
- return renderGrouped(3, 1, true).split("\n");
136
+ return new Text(renderStatusLine({ icon: "success", title: `LSP ${action}`, description, meta }, theme), 0, 0);
492
137
  }
493
138
 
494
139
  // =============================================================================
495
- // Symbols Rendering
496
- // =============================================================================
497
-
498
- /**
499
- * Render document symbols in a hierarchical tree.
500
- */
501
- function renderSymbols(symbolsMatch: RegExpMatchArray, lines: string[], expanded: boolean, theme: Theme): string[] {
502
- const fileName = symbolsMatch[1];
503
- const icon = theme.styledSymbol("status.info", "accent");
504
-
505
- interface SymbolInfo {
506
- name: string;
507
- line: string;
508
- indent: number;
509
- icon: string;
510
- }
511
-
512
- const symbolLines = lines.filter(l => l.includes("@") && l.includes("line"));
513
- const symbols: SymbolInfo[] = [];
514
-
515
- for (const line of symbolLines) {
516
- const indent = line.match(/^(\s*)/)?.[1].length ?? 0;
517
- const symMatch = line.trim().match(/^(\S+)\s+(.+?)\s*@\s*line\s*(\d+)/);
518
- if (symMatch) {
519
- symbols.push({ icon: symMatch[1], name: symMatch[2], line: symMatch[3], indent });
520
- }
521
- }
522
-
523
- const isLastSibling = (i: number): boolean => {
524
- const myIndent = symbols[i].indent;
525
- for (let j = i + 1; j < symbols.length; j++) {
526
- const nextIndent = symbols[j].indent;
527
- if (nextIndent === myIndent) return false;
528
- if (nextIndent < myIndent) return true;
529
- }
530
- return true;
531
- };
532
-
533
- const getPrefix = (i: number): string => {
534
- const myIndent = symbols[i].indent;
535
- if (myIndent === 0) return " ";
536
-
537
- let prefix = " ";
538
- for (let level = 2; level <= myIndent; level += 2) {
539
- let ancestorIdx = -1;
540
- for (let j = i - 1; j >= 0; j--) {
541
- if (symbols[j].indent === level - 2) {
542
- ancestorIdx = j;
543
- break;
544
- }
545
- }
546
- if (ancestorIdx >= 0 && isLastSibling(ancestorIdx)) {
547
- prefix += " ";
548
- } else {
549
- prefix += `${theme.tree.vertical} `;
550
- }
551
- }
552
- return prefix;
553
- };
554
-
555
- const topLevelCount = symbols.filter(s => s.indent === 0).length;
556
-
557
- if (expanded) {
558
- let output = `${icon} ${theme.fg("dim", `in ${fileName}`)}`;
559
-
560
- for (let i = 0; i < symbols.length; i++) {
561
- const sym = symbols[i];
562
- const prefix = getPrefix(i);
563
- const isLast = isLastSibling(i);
564
- const branch = isLast ? theme.tree.last : theme.tree.branch;
565
- const detailPrefix = isLast ? " " : `${theme.tree.vertical} `;
566
- output += `\n${prefix}${theme.fg("dim", branch)} ${theme.fg("accent", sym.icon)} ${theme.fg("accent", sym.name)}`;
567
- output += `\n${prefix}${theme.fg("dim", detailPrefix)}${theme.fg("muted", `line ${sym.line}`)}`;
568
- }
569
- return output.split("\n");
570
- }
571
-
572
- // Collapsed: show first 3 top-level symbols
573
- const topLevel = symbols.filter(s => s.indent === 0).slice(0, 3);
574
- const hasMoreSymbols = symbols.length > topLevel.length;
575
- const expandHint = formatExpandHint(theme, expanded, hasMoreSymbols);
576
- let output = `${icon} ${theme.fg("dim", `in ${fileName}`)}${expandHint}`;
577
- for (let i = 0; i < topLevel.length; i++) {
578
- const sym = topLevel[i];
579
- const isLast = i === topLevel.length - 1 && topLevelCount <= 3;
580
- const branch = isLast ? theme.tree.last : theme.tree.branch;
581
- output += `\n ${theme.fg("dim", branch)} ${theme.fg("accent", sym.icon)} ${theme.fg("accent", sym.name)} ${theme.fg(
582
- "muted",
583
- `line ${sym.line}`,
584
- )}`;
585
- }
586
- if (topLevelCount > 3) {
587
- output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", `… ${topLevelCount - 3} more`)}`;
588
- }
589
-
590
- return output.split("\n");
591
- }
592
-
593
- // =============================================================================
594
- // Generic Rendering
595
- // =============================================================================
596
-
597
- /**
598
- * Generic fallback rendering for unknown result types.
599
- */
600
- function renderGeneric(text: string, lines: string[], expanded: boolean, theme: Theme): string[] {
601
- const hasError = text.includes("Error:") || text.includes(theme.status.error);
602
- const hasSuccess = text.includes(theme.status.success) || text.includes("Applied");
603
-
604
- const icon =
605
- hasError && !hasSuccess
606
- ? theme.styledSymbol("status.error", "error")
607
- : hasSuccess && !hasError
608
- ? theme.styledSymbol("status.success", "success")
609
- : theme.styledSymbol("status.info", "accent");
610
-
611
- if (expanded) {
612
- let output = `${icon} ${theme.fg("dim", "Output")}`;
613
- for (let i = 0; i < lines.length; i++) {
614
- const isLast = i === lines.length - 1;
615
- const branch = isLast ? theme.tree.last : theme.tree.branch;
616
- output += `\n ${theme.fg("dim", branch)} ${lines[i]}`;
617
- }
618
- return output.split("\n");
619
- }
620
-
621
- const firstLine = lines[0] || "No output";
622
- const expandHint = formatExpandHint(theme, expanded, lines.length > 1);
623
- let output = `${icon} ${theme.fg("dim", truncateToWidth(firstLine, TRUNCATE_LENGTHS.TITLE))}${expandHint}`;
624
-
625
- if (lines.length > 1) {
626
- const previewLines = lines.slice(1, 4);
627
- for (let i = 0; i < previewLines.length; i++) {
628
- const isLast = i === previewLines.length - 1 && lines.length <= 4;
629
- const branch = isLast ? theme.tree.last : theme.tree.branch;
630
- output += `\n ${theme.fg("dim", branch)} ${theme.fg(
631
- "dim",
632
- truncateToWidth(previewLines[i].trim(), TRUNCATE_LENGTHS.CONTENT),
633
- )}`;
634
- }
635
- if (lines.length > 4) {
636
- output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg(
637
- "muted",
638
- formatMoreItems(lines.length - 4, "line"),
639
- )}`;
640
- }
641
- }
642
-
643
- return output.split("\n");
644
- }
645
-
646
- // =============================================================================
647
- // Parsing Helpers
648
- // =============================================================================
649
-
650
- interface ParsedDiagnostic {
651
- file: string;
652
- line: string;
653
- col: string;
654
- severity: string;
655
- message: string;
656
- }
657
-
658
- interface RawDiagnostic {
659
- raw: string;
660
- }
661
-
662
- type DiagnosticItem = ParsedDiagnostic | RawDiagnostic;
663
-
664
- function parseDiagnosticLine(line: string): ParsedDiagnostic | null {
665
- const match = line.trim().match(/^(.*):(\d+):(\d+)\s+\[(\w+)\]\s*(.*)$/);
666
- if (!match) return null;
667
- const [, file, lineNum, colNum, severity, message] = match;
668
- return { file, line: lineNum, col: colNum, severity: severity.toLowerCase(), message };
669
- }
670
-
671
- function severityToColor(severity: string): "error" | "warning" | "accent" | "dim" {
672
- switch (severity) {
673
- case "error":
674
- return "error";
675
- case "warning":
676
- return "warning";
677
- case "info":
678
- return "accent";
679
- default:
680
- return "dim";
681
- }
682
- }
683
-
684
- export const lspToolRenderer = {
685
- renderCall,
686
- renderResult,
687
- mergeCallAndResult: true,
688
- inline: true,
689
- };
140
+ // Hover Rendering
package/src/lsp/types.ts CHANGED
@@ -10,14 +10,14 @@ export const lspSchema = Type.Object({
10
10
  action: StringEnum(["diagnostics", "definition", "references", "hover", "symbols", "rename", "status", "reload"], {
11
11
  description: "LSP operation",
12
12
  }),
13
- files: Type.Optional(Type.Array(Type.String({ description: "File path" }))),
14
- file: Type.Optional(Type.String({ description: "File path" })),
13
+ files: Type.Optional(Type.Array(Type.String(), { description: "File paths for diagnostics" })),
14
+ file: Type.Optional(Type.String({ description: "File path for symbol operations" })),
15
15
  line: Type.Optional(Type.Number({ description: "Line number (1-indexed)" })),
16
16
  column: Type.Optional(Type.Number({ description: "Column number (1-indexed)" })),
17
17
  end_line: Type.Optional(Type.Number({ description: "End line for range (1-indexed)" })),
18
18
  end_character: Type.Optional(Type.Number({ description: "End column for range (1-indexed)" })),
19
19
  query: Type.Optional(Type.String({ description: "Search query or SSR pattern" })),
20
- new_name: Type.Optional(Type.String({ description: "New name for rename" })),
20
+ new_name: Type.Optional(Type.String({ description: "New name for rename operation" })),
21
21
  apply: Type.Optional(Type.Boolean({ description: "Apply edits (default: true)" })),
22
22
  include_declaration: Type.Optional(Type.Boolean({ description: "Include declaration in refs (default: true)" })),
23
23
  });
package/src/lsp/utils.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import path from "node:path";
2
- import { type Theme, theme } from "../modes/theme/theme";
2
+ import { type Theme, theme } from "../theme/theme";
3
3
  import type {
4
4
  Diagnostic,
5
5
  DiagnosticSeverity,