@nghyane/arcane 0.1.13 → 0.1.15

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 (303) 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 +50 -112
  50. package/src/modes/components/bordered-loader.ts +1 -1
  51. package/src/modes/components/branch-summary-message.ts +16 -10
  52. package/src/modes/components/compaction-summary-message.ts +20 -12
  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 +51 -91
  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/init.md +1 -1
  113. package/src/prompts/agents/librarian.md +29 -20
  114. package/src/prompts/agents/oracle.md +9 -2
  115. package/src/prompts/agents/reviewer.md +14 -48
  116. package/src/prompts/agents/task.md +16 -8
  117. package/src/prompts/compaction/branch-summary.md +4 -1
  118. package/src/prompts/compaction/compaction-summary.md +4 -1
  119. package/src/prompts/system/subagent-system-prompt.md +1 -1
  120. package/src/prompts/system/system-prompt.md +162 -178
  121. package/src/prompts/system/verification-reminder.md +6 -0
  122. package/src/sdk.ts +0 -9
  123. package/src/session/agent-session.ts +244 -1459
  124. package/src/session/model-controller.ts +406 -0
  125. package/src/session/retry-utils.ts +71 -0
  126. package/src/session/session-manager.ts +22 -186
  127. package/src/session/session-types.ts +312 -0
  128. package/src/session/stats.ts +387 -0
  129. package/src/session/streaming-edit.ts +258 -0
  130. package/src/session/ttsr.ts +213 -0
  131. package/src/slash-commands/builtin-registry.ts +0 -8
  132. package/src/stt/recorder.ts +2 -2
  133. package/src/system-prompt.ts +1 -14
  134. package/src/task/agents.ts +7 -33
  135. package/src/task/executor.ts +50 -438
  136. package/src/task/index.ts +104 -71
  137. package/src/task/progress-tracker.ts +390 -0
  138. package/src/task/render.ts +371 -187
  139. package/src/task/subprocess-tool-registry.ts +1 -1
  140. package/src/task/types.ts +14 -47
  141. package/src/tools/ask.ts +31 -42
  142. package/src/tools/bash-interactive.ts +2 -2
  143. package/src/tools/bash-interceptor.ts +2 -2
  144. package/src/tools/bash-normalize.ts +1 -1
  145. package/src/tools/bash-skill-urls.ts +2 -2
  146. package/src/tools/bash.ts +87 -136
  147. package/src/tools/browser.ts +54 -84
  148. package/src/tools/create-tools.ts +186 -0
  149. package/src/tools/default-renderer.ts +104 -0
  150. package/src/tools/explore.ts +11 -10
  151. package/src/tools/fetch.ts +24 -114
  152. package/src/tools/find.ts +48 -132
  153. package/src/tools/gemini-image.ts +5 -15
  154. package/src/tools/github.ts +450 -0
  155. package/src/tools/grep.ts +43 -179
  156. package/src/tools/index.ts +35 -198
  157. package/src/tools/json-tree.ts +3 -3
  158. package/src/tools/librarian.ts +18 -18
  159. package/src/tools/list-limit.ts +2 -2
  160. package/src/tools/notebook.ts +35 -87
  161. package/src/tools/oracle.ts +25 -25
  162. package/src/tools/output-meta.ts +89 -4
  163. package/src/tools/output-utils.ts +2 -2
  164. package/src/tools/python.ts +86 -637
  165. package/src/tools/read.ts +36 -119
  166. package/src/tools/reviewer-tool.ts +19 -21
  167. package/src/tools/search-code.ts +128 -0
  168. package/src/tools/ssh.ts +67 -126
  169. package/src/tools/subagent-tool.ts +197 -123
  170. package/src/tools/todo-write.ts +15 -31
  171. package/src/tools/tool-errors.ts +0 -30
  172. package/src/tools/undo-edit.ts +30 -67
  173. package/src/tools/write.ts +78 -127
  174. package/src/tui/code-cell.ts +4 -4
  175. package/src/tui/file-list.ts +2 -2
  176. package/src/tui/output-block.ts +1 -1
  177. package/src/tui/status-line.ts +1 -1
  178. package/src/tui/tree-list.ts +2 -2
  179. package/src/tui/types.ts +1 -1
  180. package/src/tui/utils.ts +1 -1
  181. package/src/{tools → ui}/render-utils.ts +87 -126
  182. package/src/utils/external-editor.ts +4 -4
  183. package/src/utils/file-mentions.ts +1 -1
  184. package/src/utils/index.ts +30 -0
  185. package/src/utils/tools-manager.ts +9 -19
  186. package/src/web/github-client.ts +290 -0
  187. package/src/web/scrapers/github.ts +11 -62
  188. package/src/web/search/auth.ts +1 -3
  189. package/src/web/search/index.ts +82 -46
  190. package/src/web/search/provider.ts +11 -16
  191. package/src/web/search/providers/grep.ts +160 -0
  192. package/src/web/search/render.ts +48 -235
  193. package/src/web/search/types.ts +1 -1
  194. package/src/commands/commit.ts +0 -36
  195. package/src/commit/agentic/agent.ts +0 -311
  196. package/src/commit/agentic/fallback.ts +0 -96
  197. package/src/commit/agentic/index.ts +0 -359
  198. package/src/commit/agentic/prompts/analyze-file.md +0 -22
  199. package/src/commit/agentic/prompts/session-user.md +0 -25
  200. package/src/commit/agentic/prompts/split-confirm.md +0 -1
  201. package/src/commit/agentic/prompts/system.md +0 -38
  202. package/src/commit/agentic/state.ts +0 -69
  203. package/src/commit/agentic/tools/analyze-file.ts +0 -118
  204. package/src/commit/agentic/tools/git-file-diff.ts +0 -194
  205. package/src/commit/agentic/tools/git-hunk.ts +0 -50
  206. package/src/commit/agentic/tools/git-overview.ts +0 -84
  207. package/src/commit/agentic/tools/index.ts +0 -56
  208. package/src/commit/agentic/tools/propose-changelog.ts +0 -128
  209. package/src/commit/agentic/tools/propose-commit.ts +0 -154
  210. package/src/commit/agentic/tools/recent-commits.ts +0 -81
  211. package/src/commit/agentic/tools/split-commit.ts +0 -280
  212. package/src/commit/agentic/topo-sort.ts +0 -44
  213. package/src/commit/agentic/trivial.ts +0 -51
  214. package/src/commit/agentic/validation.ts +0 -200
  215. package/src/commit/analysis/conventional.ts +0 -165
  216. package/src/commit/analysis/index.ts +0 -4
  217. package/src/commit/analysis/scope.ts +0 -242
  218. package/src/commit/analysis/summary.ts +0 -112
  219. package/src/commit/analysis/validation.ts +0 -66
  220. package/src/commit/changelog/detect.ts +0 -37
  221. package/src/commit/changelog/generate.ts +0 -110
  222. package/src/commit/changelog/index.ts +0 -234
  223. package/src/commit/changelog/parse.ts +0 -44
  224. package/src/commit/cli.ts +0 -93
  225. package/src/commit/git/diff.ts +0 -148
  226. package/src/commit/git/errors.ts +0 -9
  227. package/src/commit/git/index.ts +0 -211
  228. package/src/commit/git/operations.ts +0 -54
  229. package/src/commit/index.ts +0 -5
  230. package/src/commit/map-reduce/index.ts +0 -64
  231. package/src/commit/map-reduce/map-phase.ts +0 -178
  232. package/src/commit/map-reduce/reduce-phase.ts +0 -145
  233. package/src/commit/map-reduce/utils.ts +0 -9
  234. package/src/commit/message.ts +0 -11
  235. package/src/commit/model-selection.ts +0 -69
  236. package/src/commit/pipeline.ts +0 -243
  237. package/src/commit/prompts/analysis-system.md +0 -148
  238. package/src/commit/prompts/analysis-user.md +0 -38
  239. package/src/commit/prompts/changelog-system.md +0 -50
  240. package/src/commit/prompts/changelog-user.md +0 -18
  241. package/src/commit/prompts/file-observer-system.md +0 -24
  242. package/src/commit/prompts/file-observer-user.md +0 -8
  243. package/src/commit/prompts/reduce-system.md +0 -50
  244. package/src/commit/prompts/reduce-user.md +0 -17
  245. package/src/commit/prompts/summary-retry.md +0 -3
  246. package/src/commit/prompts/summary-system.md +0 -38
  247. package/src/commit/prompts/summary-user.md +0 -13
  248. package/src/commit/prompts/types-description.md +0 -2
  249. package/src/commit/types.ts +0 -109
  250. package/src/commit/utils/exclusions.ts +0 -42
  251. package/src/mcp/render.ts +0 -123
  252. package/src/modes/components/agent-dashboard.ts +0 -1130
  253. package/src/modes/components/codemode-group.ts +0 -369
  254. package/src/modes/components/read-tool-group.ts +0 -119
  255. package/src/modes/components/visual-truncate.ts +0 -63
  256. package/src/prompts/system/subagent-user-prompt.md +0 -8
  257. package/src/prompts/tools/ask.md +0 -44
  258. package/src/prompts/tools/bash.md +0 -24
  259. package/src/prompts/tools/browser.md +0 -33
  260. package/src/prompts/tools/calculator.md +0 -12
  261. package/src/prompts/tools/explore.md +0 -29
  262. package/src/prompts/tools/fetch.md +0 -16
  263. package/src/prompts/tools/find.md +0 -18
  264. package/src/prompts/tools/gemini-image.md +0 -23
  265. package/src/prompts/tools/grep.md +0 -28
  266. package/src/prompts/tools/hashline.md +0 -232
  267. package/src/prompts/tools/librarian.md +0 -24
  268. package/src/prompts/tools/lsp.md +0 -28
  269. package/src/prompts/tools/oracle.md +0 -26
  270. package/src/prompts/tools/patch.md +0 -74
  271. package/src/prompts/tools/python.md +0 -66
  272. package/src/prompts/tools/read.md +0 -36
  273. package/src/prompts/tools/replace.md +0 -38
  274. package/src/prompts/tools/reviewer.md +0 -41
  275. package/src/prompts/tools/ssh.md +0 -51
  276. package/src/prompts/tools/task-summary.md +0 -28
  277. package/src/prompts/tools/task.md +0 -146
  278. package/src/prompts/tools/todo-write.md +0 -65
  279. package/src/prompts/tools/undo-edit.md +0 -7
  280. package/src/prompts/tools/web-search.md +0 -19
  281. package/src/prompts/tools/write.md +0 -18
  282. package/src/task/batch.ts +0 -102
  283. package/src/task/discovery.ts +0 -126
  284. package/src/task/parallel.ts +0 -84
  285. package/src/task/template.ts +0 -32
  286. package/src/tools/calculator.ts +0 -537
  287. package/src/tools/jtd-to-typescript.ts +0 -198
  288. package/src/tools/renderers.ts +0 -60
  289. package/src/tools/tool-result.ts +0 -86
  290. /package/src/{modes/theme → theme}/dark.json +0 -0
  291. /package/src/{modes/theme → theme}/defaults/dark-catppuccin.json +0 -0
  292. /package/src/{modes/theme → theme}/defaults/dark-dracula.json +0 -0
  293. /package/src/{modes/theme → theme}/defaults/dark-gruvbox.json +0 -0
  294. /package/src/{modes/theme → theme}/defaults/dark-solarized.json +0 -0
  295. /package/src/{modes/theme → theme}/defaults/dark-tokyo-night.json +0 -0
  296. /package/src/{modes/theme → theme}/defaults/index.ts +0 -0
  297. /package/src/{modes/theme → theme}/defaults/light-catppuccin.json +0 -0
  298. /package/src/{modes/theme → theme}/defaults/light-github.json +0 -0
  299. /package/src/{modes/theme → theme}/defaults/light-solarized.json +0 -0
  300. /package/src/{modes/theme → theme}/light.json +0 -0
  301. /package/src/{modes/theme → theme}/mermaid-cache.ts +0 -0
  302. /package/src/{modes/theme → theme}/theme-schema.json +0 -0
  303. /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,