@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
@@ -3,9 +3,9 @@ import * as path from "node:path";
3
3
  import { type Component, padding, truncateToWidth, visibleWidth } from "@nghyane/arcane-tui";
4
4
  import { isEnoent } from "@nghyane/arcane-utils";
5
5
  import { getProjectDir } from "@nghyane/arcane-utils/dirs";
6
- import { theme } from "../../modes/theme/theme";
7
6
  import type { AgentSession } from "../../session/agent-session";
8
- import { shortenPath } from "../../tools/render-utils";
7
+ import { theme } from "../../theme/theme";
8
+ import { shortenPath } from "../../ui/render-utils";
9
9
 
10
10
  /**
11
11
  * Sanitize text for display in a single-line status.
@@ -10,8 +10,8 @@ import {
10
10
  truncateToWidth,
11
11
  visibleWidth,
12
12
  } from "@nghyane/arcane-tui";
13
- import { theme } from "../../modes/theme/theme";
14
13
  import type { HistoryEntry, HistoryStorage } from "../../session/history-storage";
14
+ import { theme } from "../../theme/theme";
15
15
  import { DynamicBorder } from "./dynamic-border";
16
16
 
17
17
  class HistoryResultsList implements Component {
@@ -3,7 +3,7 @@
3
3
  * Supports Ctrl+G for external editor.
4
4
  */
5
5
  import { Container, Editor, matchesKey, Spacer, Text, type TUI } from "@nghyane/arcane-tui";
6
- import { getEditorTheme, theme } from "../../modes/theme/theme";
6
+ import { getEditorTheme, theme } from "../../theme/theme";
7
7
  import { getEditorCommand, openInEditor } from "../../utils/external-editor";
8
8
  import { DynamicBorder } from "./dynamic-border";
9
9
 
@@ -2,7 +2,7 @@
2
2
  * Simple text input component for hooks.
3
3
  */
4
4
  import { Container, Input, matchesKey, Spacer, Text, type TUI } from "@nghyane/arcane-tui";
5
- import { theme } from "../../modes/theme/theme";
5
+ import { theme } from "../../theme/theme";
6
6
  import { CountdownTimer } from "./countdown-timer";
7
7
  import { DynamicBorder } from "./dynamic-border";
8
8
 
@@ -1,16 +1,16 @@
1
1
  import type { TextContent } from "@nghyane/arcane-ai";
2
2
  import type { Component } from "@nghyane/arcane-tui";
3
- import { Box, Container, Markdown, Spacer, Text } from "@nghyane/arcane-tui";
3
+ import { Container, LeftBorderBox, Markdown, Spacer, Text } from "@nghyane/arcane-tui";
4
4
  import type { HookMessageRenderer } from "../../extensibility/hooks/types";
5
- import { getMarkdownTheme, theme } from "../../modes/theme/theme";
6
5
  import type { HookMessage } from "../../session/messages";
6
+ import { getMarkdownTheme, theme } from "../../theme/theme";
7
7
 
8
8
  /**
9
9
  * Component that renders a custom message entry from hooks.
10
10
  * Uses distinct styling to differentiate from user messages.
11
11
  */
12
12
  export class HookMessageComponent extends Container {
13
- #box: Box;
13
+ #box: LeftBorderBox;
14
14
  #customComponent?: Component;
15
15
  #expanded = false;
16
16
 
@@ -22,8 +22,7 @@ export class HookMessageComponent extends Container {
22
22
 
23
23
  this.addChild(new Spacer(1));
24
24
 
25
- // Create box with purple background (used for default rendering)
26
- this.#box = new Box(1, 1, t => theme.bg("customMessageBg", t));
25
+ this.#box = new LeftBorderBox(1, 1, s => theme.fg("dim", s));
27
26
 
28
27
  this.#rebuild();
29
28
  }
@@ -3,7 +3,7 @@
3
3
  * Displays a list of string options with keyboard navigation.
4
4
  */
5
5
  import { Container, matchesKey, padding, Spacer, Text, type TUI, visibleWidth } from "@nghyane/arcane-tui";
6
- import { theme } from "../../modes/theme/theme";
6
+ import { theme } from "../../theme/theme";
7
7
  import { CountdownTimer } from "./countdown-timer";
8
8
  import { DynamicBorder } from "./dynamic-border";
9
9
 
@@ -19,7 +19,6 @@ export { LoginDialogComponent } from "./login-dialog";
19
19
  export { ModelSelectorComponent } from "./model-selector";
20
20
  export { OAuthSelectorComponent } from "./oauth-selector";
21
21
  export { QueueModeSelectorComponent } from "./queue-mode-selector";
22
- export { ReadToolGroupComponent } from "./read-tool-group";
23
22
  export { SessionSelectorComponent } from "./session-selector";
24
23
  export {
25
24
  type SettingsCallbacks,
@@ -37,5 +36,4 @@ export { TreeSelectorComponent } from "./tree-selector";
37
36
  export { TtsrNotificationComponent } from "./ttsr-notification";
38
37
  export { UserMessageComponent } from "./user-message";
39
38
  export { UserMessageSelectorComponent } from "./user-message-selector";
40
- export { truncateToVisualLines, type VisualTruncateResult } from "./visual-truncate";
41
39
  export { type LspServerInfo, type RecentSession, WelcomeComponent } from "./welcome";
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { type EditorAction, getEditorKeybindings, type KeyId } from "@nghyane/arcane-tui";
5
5
  import type { AppAction, KeybindingsManager } from "../../config/keybindings";
6
- import { theme } from "../../modes/theme/theme";
6
+ import { theme } from "../../theme/theme";
7
7
 
8
8
  /**
9
9
  * Format keys array as display string (e.g., ["ctrl+c", "escape"] -> "ctrl+c/escape").
@@ -1,6 +1,6 @@
1
1
  import { getOAuthProviders } from "@nghyane/arcane-ai";
2
2
  import { Container, getEditorKeybindings, Input, Spacer, Text, type TUI } from "@nghyane/arcane-tui";
3
- import { theme } from "../../modes/theme/theme";
3
+ import { theme } from "../../theme/theme";
4
4
  import { openPath } from "../../utils/open";
5
5
  import { DynamicBorder } from "./dynamic-border";
6
6
 
@@ -16,7 +16,7 @@ import {
16
16
  import { validateServerName } from "../../mcp/config-writer";
17
17
  import { analyzeAuthError, discoverOAuthEndpoints } from "../../mcp/oauth-discovery";
18
18
  import type { MCPHttpServerConfig, MCPServerConfig, MCPSseServerConfig, MCPStdioServerConfig } from "../../mcp/types";
19
- import { theme } from "../theme/theme";
19
+ import { theme } from "../../theme/theme";
20
20
  import { DynamicBorder } from "./dynamic-border";
21
21
 
22
22
  type TransportType = "stdio" | "http" | "sse";
@@ -14,7 +14,7 @@ import {
14
14
  import { MODEL_ROLE_IDS, MODEL_ROLES, type ModelRegistry, type ModelRole } from "../../config/model-registry";
15
15
  import { parseModelString } from "../../config/model-resolver";
16
16
  import type { Settings } from "../../config/settings";
17
- import { type ThemeColor, theme } from "../../modes/theme/theme";
17
+ import { type ThemeColor, theme } from "../../theme/theme";
18
18
  import { fuzzyFilter } from "../../utils/fuzzy";
19
19
  import { DynamicBorder } from "./dynamic-border";
20
20
 
@@ -1,7 +1,7 @@
1
1
  import { getOAuthProviders, type OAuthProviderInfo } from "@nghyane/arcane-ai";
2
2
  import { Container, matchesKey, Spacer, TruncatedText } from "@nghyane/arcane-tui";
3
- import { theme } from "../../modes/theme/theme";
4
3
  import type { AuthStorage } from "../../session/auth-storage";
4
+ import { theme } from "../../theme/theme";
5
5
  import { DynamicBorder } from "./dynamic-border";
6
6
  /**
7
7
  * Component that renders an OAuth provider selector.
@@ -19,7 +19,7 @@ import {
19
19
  } from "@nghyane/arcane-tui";
20
20
  import { PluginManager } from "../../extensibility/plugins/manager";
21
21
  import type { InstalledPlugin, PluginSettingSchema } from "../../extensibility/plugins/types";
22
- import { getSelectListTheme, getSettingsListTheme, theme } from "../../modes/theme/theme";
22
+ import { getSelectListTheme, getSettingsListTheme, theme } from "../../theme/theme";
23
23
  import { DynamicBorder } from "./dynamic-border";
24
24
 
25
25
  // =============================================================================
@@ -1,17 +1,16 @@
1
1
  /**
2
2
  * Component for displaying user-initiated Python execution with streaming output.
3
- * Shares the same kernel session as the agent's Python tool.
3
+ * Tree-style output: tail 4 lines on success, all on error.
4
4
  */
5
5
 
6
6
  import { sanitizeText } from "@nghyane/arcane-natives";
7
7
  import { Container, Loader, Spacer, Text, type TUI } from "@nghyane/arcane-tui";
8
- import { getSymbolTheme, highlightCode, theme } from "../../modes/theme/theme";
9
- import { formatBytes } from "../../session/streaming-output";
8
+ import { getSymbolTheme, theme } from "../../theme/theme";
10
9
  import type { TruncationMeta } from "../../tools/output-meta";
11
- import { DynamicBorder } from "./dynamic-border";
12
- import { truncateToVisualLines } from "./visual-truncate";
10
+ import { renderStatusLine } from "../../tui/status-line";
11
+ import { formatCount, replaceTabs } from "../../ui/render-utils";
13
12
 
14
- const PREVIEW_LINES = 20;
13
+ const TAIL_LINES = 4;
15
14
  const MAX_DISPLAY_LINE_CHARS = 4000;
16
15
 
17
16
  export class PythonExecutionComponent extends Container {
@@ -21,45 +20,36 @@ export class PythonExecutionComponent extends Container {
21
20
  #loader: Loader;
22
21
  #truncation?: TruncationMeta;
23
22
  #expanded = false;
24
- #contentContainer: Container;
25
-
26
- #formatHeader(colorKey: "dim" | "pythonMode"): Text {
27
- const prompt = theme.fg(colorKey, theme.bold(">>>"));
28
- const continuation = theme.fg(colorKey, " ");
29
- const codeLines = highlightCode(this.code, "python");
30
- const headerLines = codeLines.map((line, index) =>
31
- index === 0 ? `${prompt} ${line}` : `${continuation}${line}`,
32
- );
33
- return new Text(headerLines.join("\n"), 1, 0);
34
- }
23
+ #headerText: Text;
24
+ #bodyText: Text;
35
25
 
36
26
  constructor(
37
27
  private readonly code: string,
38
28
  ui: TUI,
39
- private readonly excludeFromContext = false,
29
+ _excludeFromContext = false,
40
30
  ) {
41
31
  super();
42
-
43
- const colorKey = this.excludeFromContext ? "dim" : "pythonMode";
44
- const borderColor = (str: string) => theme.fg(colorKey, str);
45
-
46
32
  this.addChild(new Spacer(1));
47
- this.addChild(new DynamicBorder(borderColor));
48
33
 
49
- this.#contentContainer = new Container();
50
- this.addChild(this.#contentContainer);
51
- this.#contentContainer.addChild(this.#formatHeader(colorKey));
34
+ const codePreview = code.split("\n")[0].slice(0, 60);
35
+ this.#headerText = new Text(
36
+ renderStatusLine({ icon: "running", title: "Python", description: `>>> ${codePreview}` }, theme),
37
+ 1,
38
+ 0,
39
+ );
40
+ this.addChild(this.#headerText);
41
+
42
+ this.#bodyText = new Text("", 1, 0);
43
+ this.addChild(this.#bodyText);
52
44
 
53
45
  this.#loader = new Loader(
54
46
  ui,
55
- spinner => theme.fg(colorKey, spinner),
47
+ spinner => theme.fg("accent", spinner),
56
48
  text => theme.fg("muted", text),
57
- `Running (esc to cancel)`,
49
+ "Running\u2026 (esc to cancel)",
58
50
  getSymbolTheme().spinnerFrames,
59
51
  );
60
- this.#contentContainer.addChild(this.#loader);
61
-
62
- this.addChild(new DynamicBorder(borderColor));
52
+ this.addChild(this.#loader);
63
53
  }
64
54
 
65
55
  setExpanded(expanded: boolean): void {
@@ -74,7 +64,6 @@ export class PythonExecutionComponent extends Container {
74
64
 
75
65
  appendOutput(chunk: string): void {
76
66
  const clean = sanitizeText(chunk);
77
-
78
67
  const newLines = clean.split("\n").map(line => this.#clampDisplayLine(line));
79
68
  if (this.#outputLines.length > 0 && newLines.length > 0) {
80
69
  this.#outputLines[this.#outputLines.length - 1] = this.#clampDisplayLine(
@@ -84,7 +73,6 @@ export class PythonExecutionComponent extends Container {
84
73
  } else {
85
74
  this.#outputLines.push(...newLines);
86
75
  }
87
-
88
76
  this.#updateDisplay();
89
77
  }
90
78
 
@@ -103,82 +91,51 @@ export class PythonExecutionComponent extends Container {
103
91
  if (options?.output !== undefined) {
104
92
  this.#setOutput(options.output);
105
93
  }
106
-
107
94
  this.#loader.stop();
108
95
  this.#updateDisplay();
109
96
  }
110
97
 
111
98
  #updateDisplay(): void {
112
- const availableLines = this.#outputLines;
113
- const previewLogicalLines = availableLines.slice(-PREVIEW_LINES);
114
- const hiddenLineCount = availableLines.length - previewLogicalLines.length;
115
-
116
- this.#contentContainer.clear();
117
-
118
- const colorKey = this.excludeFromContext ? "dim" : "pythonMode";
119
- this.#contentContainer.addChild(this.#formatHeader(colorKey));
120
-
121
- if (availableLines.length > 0) {
122
- if (this.#expanded) {
123
- const displayText = availableLines.map(line => theme.fg("muted", line)).join("\n");
124
- this.#contentContainer.addChild(new Text(`\n${displayText}`, 1, 0));
125
- } else {
126
- const styledOutput = previewLogicalLines.map(line => theme.fg("muted", line)).join("\n");
127
- const previewText = `\n${styledOutput}`;
128
- this.#contentContainer.addChild({
129
- render: (width: number) => {
130
- const { visualLines } = truncateToVisualLines(previewText, PREVIEW_LINES, width, 1);
131
- return visualLines;
132
- },
133
- invalidate: () => {},
134
- });
135
- }
99
+ const isError = this.#status === "error";
100
+ const isDone = this.#status !== "running";
101
+ const lines = this.#outputLines.filter(l => l.trim());
102
+ const total = lines.length;
103
+
104
+ if (isDone) {
105
+ const icon = isError ? "error" : this.#status === "cancelled" ? "warning" : "success";
106
+ const codePreview = this.code.split("\n")[0].slice(0, 60);
107
+ const meta: string[] = [];
108
+ if (isError && this.#exitCode !== undefined) meta.push(`exit ${this.#exitCode}`);
109
+ if (total > 0) meta.push(formatCount("line", total));
110
+ this.#headerText.setText(
111
+ renderStatusLine({ icon, title: "Python", description: `>>> ${codePreview}`, meta }, theme),
112
+ );
136
113
  }
137
114
 
138
- if (this.#status === "running") {
139
- this.#contentContainer.addChild(this.#loader);
140
- } else {
141
- const statusParts: string[] = [];
115
+ const bodyLines: string[] = [];
116
+ if (total > 0) {
117
+ const showAll = isError || this.#expanded;
118
+ const displayLines = showAll ? lines : lines.slice(-TAIL_LINES);
119
+ const skipped = total - displayLines.length;
142
120
 
143
- if (hiddenLineCount > 0) {
144
- statusParts.push(theme.fg("dim", `… ${hiddenLineCount} more lines (ctrl+o to expand)`));
121
+ if (skipped > 0) {
122
+ bodyLines.push(theme.fg("dim", `\u2026 (${skipped} earlier lines)`));
145
123
  }
146
-
147
- if (this.#status === "cancelled") {
148
- statusParts.push(theme.fg("warning", "(cancelled)"));
149
- } else if (this.#status === "error") {
150
- statusParts.push(theme.fg("error", `(exit ${this.#exitCode})`));
124
+ for (let i = 0; i < displayLines.length; i++) {
125
+ bodyLines.push(theme.fg("toolOutput", replaceTabs(displayLines[i])));
151
126
  }
152
-
153
127
  if (this.#truncation) {
154
- const warnings: string[] = [];
155
- if (this.#truncation.artifactId) {
156
- warnings.push(`Full output: artifact://${this.#truncation.artifactId}`);
157
- }
158
- if (this.#truncation.truncatedBy === "lines") {
159
- warnings.push(
160
- `Truncated: showing ${this.#truncation.outputLines} of ${this.#truncation.totalLines} lines`,
161
- );
162
- } else {
163
- warnings.push(
164
- `Truncated: ${this.#truncation.outputLines} lines shown (${formatBytes(this.#truncation.outputBytes)} limit)`,
165
- );
166
- }
167
- statusParts.push(theme.fg("warning", warnings.join(". ")));
168
- }
169
-
170
- if (statusParts.length > 0) {
171
- this.#contentContainer.addChild(new Text(`\n${statusParts.join("\n")}`, 1, 0));
128
+ bodyLines.push(theme.fg("warning", "output truncated"));
172
129
  }
173
130
  }
131
+
132
+ this.#bodyText.setText(bodyLines.length > 0 ? bodyLines.join("\n") : "");
174
133
  }
175
134
 
176
135
  #clampDisplayLine(line: string): string {
177
- if (line.length <= MAX_DISPLAY_LINE_CHARS) {
178
- return line;
179
- }
136
+ if (line.length <= MAX_DISPLAY_LINE_CHARS) return line;
180
137
  const omitted = line.length - MAX_DISPLAY_LINE_CHARS;
181
- return `${line.slice(0, MAX_DISPLAY_LINE_CHARS)} [${omitted} chars omitted]`;
138
+ return `${line.slice(0, MAX_DISPLAY_LINE_CHARS)}\u2026 [${omitted} chars omitted]`;
182
139
  }
183
140
 
184
141
  #setOutput(output: string): void {
@@ -1,5 +1,5 @@
1
1
  import { Container, type SelectItem, SelectList } from "@nghyane/arcane-tui";
2
- import { getSelectListTheme } from "../../modes/theme/theme";
2
+ import { getSelectListTheme } from "../../theme/theme";
3
3
  import { DynamicBorder } from "./dynamic-border";
4
4
 
5
5
  /**
@@ -9,8 +9,8 @@ import {
9
9
  truncateToWidth,
10
10
  visibleWidth,
11
11
  } from "@nghyane/arcane-tui";
12
- import { theme } from "../../modes/theme/theme";
13
12
  import type { SessionInfo } from "../../session/session-manager";
13
+ import { theme } from "../../theme/theme";
14
14
  import { fuzzyFilter } from "../../utils/fuzzy";
15
15
  import { DynamicBorder } from "./dynamic-border";
16
16
 
@@ -74,16 +74,11 @@ const OPTION_PROVIDERS: Partial<Record<SettingPath, OptionProvider>> = {
74
74
  { value: "5", label: "5 retries" },
75
75
  { value: "10", label: "10 retries" },
76
76
  ],
77
- // Task max concurrency
78
- "task.maxConcurrency": [
79
- { value: "0", label: "Unlimited" },
80
- { value: "1", label: "1 task" },
81
- { value: "2", label: "2 tasks" },
82
- { value: "4", label: "4 tasks" },
83
- { value: "8", label: "8 tasks" },
84
- { value: "16", label: "16 tasks" },
85
- { value: "32", label: "32 tasks" },
86
- { value: "64", label: "64 tasks" },
77
+ // Verification max reminders
78
+ "verification.maxReminders": [
79
+ { value: "1", label: "1 reminder" },
80
+ { value: "2", label: "2 reminders" },
81
+ { value: "3", label: "3 reminders" },
87
82
  ],
88
83
  // Todo max reminders
89
84
  "todo.reminders.max": [
@@ -20,7 +20,7 @@ import type {
20
20
  StatusLineSeparatorStyle,
21
21
  } from "../../config/settings-schema";
22
22
  import { SETTING_TABS, TAB_METADATA } from "../../config/settings-schema";
23
- import { getCurrentThemeName, getSelectListTheme, getSettingsListTheme, theme } from "../../modes/theme/theme";
23
+ import { getCurrentThemeName, getSelectListTheme, getSettingsListTheme, theme } from "../../theme/theme";
24
24
  import { DynamicBorder } from "./dynamic-border";
25
25
  import { PluginSettingsComponent } from "./plugin-settings";
26
26
  import { getSettingsForTab, type SettingDef } from "./settings-defs";
@@ -1,5 +1,5 @@
1
1
  import { Container, type SelectItem, SelectList } from "@nghyane/arcane-tui";
2
- import { getSelectListTheme } from "../../modes/theme/theme";
2
+ import { getSelectListTheme } from "../../theme/theme";
3
3
  import { DynamicBorder } from "./dynamic-border";
4
4
 
5
5
  /**
@@ -1,11 +1,11 @@
1
1
  import type { TextContent } from "@nghyane/arcane-ai";
2
2
  import type { Component } from "@nghyane/arcane-tui";
3
- import { Box, Container, Markdown, Spacer, Text } from "@nghyane/arcane-tui";
4
- import { getMarkdownTheme, theme } from "../../modes/theme/theme";
3
+ import { Container, LeftBorderBox, Markdown, Spacer, Text } from "@nghyane/arcane-tui";
5
4
  import type { CustomMessage, SkillPromptDetails } from "../../session/messages";
5
+ import { getMarkdownTheme, theme } from "../../theme/theme";
6
6
 
7
7
  export class SkillMessageComponent extends Container {
8
- #box: Box;
8
+ #box: LeftBorderBox;
9
9
  #contentComponent?: Component;
10
10
  #expanded = false;
11
11
 
@@ -13,7 +13,7 @@ export class SkillMessageComponent extends Container {
13
13
  super();
14
14
  this.addChild(new Spacer(1));
15
15
 
16
- this.#box = new Box(1, 1, t => theme.bg("customMessageBg", t));
16
+ this.#box = new LeftBorderBox(1, 1, s => theme.fg("dim", s));
17
17
  this.#rebuild();
18
18
  }
19
19
 
@@ -1,7 +1,7 @@
1
1
  import * as os from "node:os";
2
2
  import { getProjectDir } from "@nghyane/arcane-utils/dirs";
3
- import { theme } from "../../../modes/theme/theme";
4
- import { shortenPath } from "../../../tools/render-utils";
3
+ import { theme } from "../../../theme/theme";
4
+ import { shortenPath } from "../../../ui/render-utils";
5
5
  import type { RenderedSegment, SegmentContext, StatusLineSegment, StatusLineSegmentId } from "./types";
6
6
 
7
7
  export type { SegmentContext } from "./types";
@@ -1,4 +1,4 @@
1
- import type { Theme } from "../../../modes/theme/theme";
1
+ import type { Theme } from "../../../theme/theme";
2
2
  import type { SeparatorDef, StatusLineSeparatorStyle } from "./types";
3
3
 
4
4
  function trimSep(value: string): string {
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import { Container, matchesKey, padding } from "@nghyane/arcane-tui";
12
12
  import type { StatusLineSegmentId } from "../../config/settings-schema";
13
- import { theme } from "../../modes/theme/theme";
13
+ import { theme } from "../../theme/theme";
14
14
  import { ALL_SEGMENT_IDS } from "./status-line/segments";
15
15
 
16
16
  // Segment display names and short descriptions
@@ -6,8 +6,8 @@ import { getProjectDir } from "@nghyane/arcane-utils/dirs";
6
6
  import { $ } from "bun";
7
7
  import { settings } from "../../config/settings";
8
8
  import type { StatusLinePreset, StatusLineSegmentId, StatusLineSeparatorStyle } from "../../config/settings-schema";
9
- import { theme } from "../../modes/theme/theme";
10
9
  import type { AgentSession } from "../../session/agent-session";
10
+ import { theme } from "../../theme/theme";
11
11
  import { getPreset } from "./status-line/presets";
12
12
  import { renderSegment, type SegmentContext } from "./status-line/segments";
13
13
  import { getSeparator } from "./status-line/separators";
@@ -1,5 +1,5 @@
1
1
  import { Container, type SelectItem, SelectList } from "@nghyane/arcane-tui";
2
- import { getSelectListTheme } from "../../modes/theme/theme";
2
+ import { getSelectListTheme } from "../../theme/theme";
3
3
  import { DynamicBorder } from "./dynamic-border";
4
4
 
5
5
  /**
@@ -1,6 +1,6 @@
1
1
  import type { ThinkingLevel } from "@nghyane/arcane-agent";
2
2
  import { Container, type SelectItem, SelectList } from "@nghyane/arcane-tui";
3
- import { getSelectListTheme } from "../../modes/theme/theme";
3
+ import { getSelectListTheme } from "../../theme/theme";
4
4
  import { DynamicBorder } from "./dynamic-border";
5
5
 
6
6
  const LEVEL_DESCRIPTIONS: Record<ThinkingLevel, string> = {
@@ -1,8 +1,8 @@
1
1
  import * as path from "node:path";
2
2
  import { Ellipsis, Text, truncateToWidth } from "@nghyane/arcane-tui";
3
3
  import { logger } from "@nghyane/arcane-utils";
4
- import { theme } from "../../modes/theme/theme";
5
4
  import type { TodoItem } from "../../modes/types";
5
+ import { theme } from "../../theme/theme";
6
6
  import { Hasher, type RenderCache } from "../../tui";
7
7
 
8
8
  const TODO_FILE_NAME = "todos.json";
@@ -13,10 +13,8 @@ interface TodoFile {
13
13
  }
14
14
 
15
15
  async function loadTodoFile(filePath: string): Promise<TodoFile | null> {
16
- const file = Bun.file(filePath);
17
- if (!(await file.exists())) return null;
18
16
  try {
19
- const text = await file.text();
17
+ const text = await Bun.file(filePath).text();
20
18
  const data = JSON.parse(text) as TodoFile;
21
19
  if (!data || !Array.isArray(data.todos)) return null;
22
20
  return data;
@@ -1,5 +1,5 @@
1
- import { Box, Container, Spacer, Text } from "@nghyane/arcane-tui";
2
- import { theme } from "../../modes/theme/theme";
1
+ import { Container, LeftBorderBox, Spacer, Text } from "@nghyane/arcane-tui";
2
+ import { theme } from "../../theme/theme";
3
3
  import type { TodoItem } from "../../tools/todo-write";
4
4
 
5
5
  /**
@@ -7,7 +7,7 @@ import type { TodoItem } from "../../tools/todo-write";
7
7
  * Shows when the agent stops with incomplete todos.
8
8
  */
9
9
  export class TodoReminderComponent extends Container {
10
- #box: Box;
10
+ #box: LeftBorderBox;
11
11
 
12
12
  constructor(
13
13
  private readonly todos: TodoItem[],
@@ -18,7 +18,7 @@ export class TodoReminderComponent extends Container {
18
18
 
19
19
  this.addChild(new Spacer(1));
20
20
 
21
- this.#box = new Box(1, 1, t => theme.inverse(theme.fg("warning", t)));
21
+ this.#box = new LeftBorderBox(1, 1, s => theme.fg("warning", s));
22
22
  this.addChild(this.#box);
23
23
 
24
24
  this.#rebuild();