@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
@@ -1,369 +0,0 @@
1
- import type { AgentTool } from "@nghyane/arcane-agent";
2
- import type { Component, TUI } from "@nghyane/arcane-tui";
3
- import { Text } from "@nghyane/arcane-tui";
4
- import { getSymbolTheme, theme } from "../../modes/theme/theme";
5
- import { shortenPath } from "../../tools/render-utils";
6
- import { getTreeBranch, getTreeContinuePrefix } from "../../tui";
7
- import { ToolExecutionComponent, type ToolExecutionHandle, type ToolExecutionOptions } from "./tool-execution";
8
-
9
- /** Visible width of the tree prefix added to each sub-tool line. */
10
- const TREE_PREFIX_WIDTH = 6; // 3 leading spaces + branch/continue chars + trailing space
11
-
12
- type ReadEntry = {
13
- path: string;
14
- offset?: number;
15
- limit?: number;
16
- status: "pending" | "success" | "error";
17
- text: Text;
18
- };
19
-
20
- type ToolHistoryEntry = { tool: string; args: string; status: "success" | "error" | "running" };
21
-
22
- const SUBAGENT_TOOLS = new Set(["explore", "oracle", "librarian", "code_review"]);
23
-
24
- const SUBAGENT_LABELS: Record<string, string> = {
25
- explore: "Explore",
26
- oracle: "Oracle",
27
- librarian: "Librarian",
28
- code_review: "Code Review",
29
- };
30
-
31
- class SubagentComponent implements Component, ToolExecutionHandle {
32
- #label: string;
33
- #description: string;
34
- #status: "pending" | "success" | "error" = "pending";
35
- #toolHistory: ToolHistoryEntry[] = [];
36
- #dirty = true;
37
- #cachedLines: string[] = [];
38
- #cachedWidth = 0;
39
-
40
- constructor(toolName: string, args: Record<string, unknown>) {
41
- this.#label = SUBAGENT_LABELS[toolName] ?? toolName;
42
- const raw = ((args.query ?? args.task ?? args.diff_description ?? "") as string).trim();
43
- this.#description = raw;
44
- }
45
-
46
- // --- Component ---
47
-
48
- render(width: number): string[] {
49
- if (!this.#dirty && this.#cachedWidth === width) return this.#cachedLines;
50
- this.#cachedWidth = width;
51
- this.#dirty = false;
52
-
53
- const lines: string[] = [];
54
-
55
- // Header line: ✓ Explore Find all code that references...
56
- const icon = this.#statusIcon(this.#status);
57
- const desc = this.#description ? ` ${theme.fg("dim", this.#description)}` : "";
58
- lines.push(`${icon} ${theme.fg("toolTitle", theme.bold(this.#label))}${desc}`);
59
-
60
- // Child tool history with inner tree branches
61
- for (let i = 0; i < this.#toolHistory.length; i++) {
62
- const entry = this.#toolHistory[i];
63
- const isLast = i === this.#toolHistory.length - 1;
64
- const branch = getTreeBranch(isLast, theme);
65
- const childIcon = this.#statusIcon(entry.status);
66
- const toolLabel = this.#childToolLabel(entry);
67
- const line = `${theme.fg("dim", branch)} ${childIcon} ${toolLabel}`;
68
- lines.push(line);
69
- }
70
-
71
- this.#cachedLines = lines;
72
- return lines;
73
- }
74
-
75
- invalidate(): void {
76
- this.#dirty = true;
77
- }
78
-
79
- // --- ToolExecutionHandle ---
80
-
81
- updateArgs(): void {}
82
-
83
- updateResult(result: any, isPartial?: boolean): void {
84
- if (isPartial) {
85
- const progress = result?.details?.progress as Array<{ toolHistory?: ToolHistoryEntry[] }> | undefined;
86
- if (progress?.[0]?.toolHistory) {
87
- this.#toolHistory = progress[0].toolHistory;
88
- this.#dirty = true;
89
- }
90
- return;
91
- }
92
- this.#status = result?.isError ? "error" : "success";
93
- // Final result may also carry toolHistory
94
- const progress = result?.details?.progress as Array<{ toolHistory?: ToolHistoryEntry[] }> | undefined;
95
- if (progress?.[0]?.toolHistory) {
96
- this.#toolHistory = progress[0].toolHistory;
97
- }
98
- this.#dirty = true;
99
- }
100
-
101
- setArgsComplete(): void {}
102
- setExpanded(): void {}
103
-
104
- // --- Private ---
105
-
106
- #statusIcon(status: "pending" | "success" | "error" | "running"): string {
107
- switch (status) {
108
- case "success":
109
- return theme.fg("success", theme.status.success);
110
- case "error":
111
- return theme.fg("error", theme.status.error);
112
- case "running":
113
- return theme.fg("dim", theme.status.pending);
114
- default:
115
- return theme.fg("dim", theme.status.pending);
116
- }
117
- }
118
-
119
- #childToolLabel(entry: ToolHistoryEntry): string {
120
- const name = theme.fg("toolTitle", theme.bold(this.#prettyToolName(entry.tool)));
121
- const args = entry.args ? ` ${theme.fg("dim", entry.args)}` : "";
122
- return `${name}${args}`;
123
- }
124
-
125
- #prettyToolName(name: string): string {
126
- // Capitalize first letter: grep → Grep, read → Read
127
- return name.charAt(0).toUpperCase() + name.slice(1);
128
- }
129
- }
130
-
131
- export class CodeModeGroupComponent implements Component, ToolExecutionHandle {
132
- #header: Text;
133
- #logsText: Text;
134
- #orderedSubTools: Component[] = [];
135
- #entries = new Map<string, { toolCallId: string; component: ToolExecutionComponent }>();
136
- #readEntries = new Map<string, ReadEntry>();
137
- #intent = "";
138
- #expanded = false;
139
- #logs: string[] = [];
140
- #done = false;
141
- #ui: TUI;
142
- #spinnerFrames: string[];
143
- #spinnerFrame = 0;
144
- #spinnerInterval?: NodeJS.Timeout;
145
-
146
- constructor(ui: TUI) {
147
- this.#ui = ui;
148
- this.#header = new Text("", 0, 0);
149
- this.#logsText = new Text("", 0, 0);
150
- this.#spinnerFrames = getSymbolTheme().spinnerFrames;
151
- this.#startSpinner();
152
- this.#updateHeader();
153
- }
154
-
155
- // --- Component ---
156
-
157
- render(width: number): string[] {
158
- const lines: string[] = [];
159
-
160
- // Spacer
161
- lines.push("");
162
-
163
- // Header
164
- lines.push(...this.#header.render(width));
165
-
166
- // Sub-tools with tree connectors
167
- const subToolWidth = Math.max(1, width - TREE_PREFIX_WIDTH);
168
- for (let i = 0; i < this.#orderedSubTools.length; i++) {
169
- const isLast = i === this.#orderedSubTools.length - 1;
170
- const tool = this.#orderedSubTools[i];
171
- const toolLines = tool.render(subToolWidth);
172
-
173
- const branch = getTreeBranch(isLast, theme);
174
- const cont = getTreeContinuePrefix(isLast, theme);
175
- const branchPfx = ` ${theme.fg("dim", branch)} `;
176
- const contPfx = ` ${theme.fg("dim", cont)}`;
177
-
178
- let firstContent = true;
179
- const contentLines: string[] = [];
180
- for (const line of toolLines) {
181
- // Skip leading empty lines (from Spacer(1) in ToolExecutionComponent)
182
- if (firstContent && !line.trim()) continue;
183
-
184
- if (firstContent) {
185
- contentLines.push(`${branchPfx}${line}`);
186
- firstContent = false;
187
- } else {
188
- contentLines.push(line.trim() ? `${contPfx}${line}` : "");
189
- }
190
- }
191
- // Only emit if the sub-tool produced visible content
192
- if (!firstContent) {
193
- lines.push(...contentLines);
194
- }
195
- }
196
-
197
- // Logs
198
- lines.push(...this.#logsText.render(width));
199
-
200
- return lines;
201
- }
202
-
203
- invalidate(): void {
204
- this.#header.invalidate?.();
205
- this.#logsText.invalidate?.();
206
- for (const tool of this.#orderedSubTools) {
207
- tool.invalidate?.();
208
- }
209
- }
210
-
211
- // --- ToolExecutionHandle (no-ops on the group itself) ---
212
-
213
- updateArgs(_args: any, _toolCallId?: string): void {}
214
-
215
- updateResult(
216
- _result: {
217
- content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;
218
- details?: any;
219
- isError?: boolean;
220
- },
221
- _isPartial?: boolean,
222
- _toolCallId?: string,
223
- ): void {}
224
-
225
- setArgsComplete(_toolCallId?: string): void {}
226
-
227
- setExpanded(expanded: boolean): void {
228
- this.#expanded = expanded;
229
- for (const entry of this.#entries.values()) {
230
- entry.component.setExpanded(expanded);
231
- }
232
- }
233
-
234
- // --- Sub-tool management ---
235
-
236
- addSubTool(
237
- toolCallId: string,
238
- toolName: string,
239
- args: any,
240
- tool: AgentTool | undefined,
241
- options: ToolExecutionOptions,
242
- ui: TUI,
243
- cwd: string,
244
- ): ToolExecutionHandle {
245
- if (toolName === "read") {
246
- return this.#addReadItem(toolCallId, args);
247
- }
248
- if (SUBAGENT_TOOLS.has(toolName)) {
249
- const component = new SubagentComponent(toolName, args as Record<string, unknown>);
250
- this.#orderedSubTools.push(component);
251
- return component;
252
- }
253
-
254
- const component = new ToolExecutionComponent(toolName, args, options, tool, ui, cwd, { compact: true });
255
- component.setExpanded(this.#expanded);
256
- this.#entries.set(toolCallId, { toolCallId, component });
257
- this.#orderedSubTools.push(component);
258
- return component;
259
- }
260
-
261
- getSubTool(toolCallId: string): ToolExecutionHandle | undefined {
262
- return this.#entries.get(toolCallId)?.component;
263
- }
264
-
265
- // --- Read items (flat, no sub-tree) ---
266
-
267
- #addReadItem(toolCallId: string, args: any): ToolExecutionHandle {
268
- const readArgs = args as { path?: string; file_path?: string; offset?: number; limit?: number };
269
- const text = new Text("", 0, 0);
270
- const entry: ReadEntry = {
271
- path: readArgs.file_path || readArgs.path || "",
272
- offset: readArgs.offset,
273
- limit: readArgs.limit,
274
- status: "pending",
275
- text,
276
- };
277
- this.#readEntries.set(toolCallId, entry);
278
- this.#orderedSubTools.push(text);
279
- this.#updateReadDisplay(entry);
280
-
281
- return {
282
- updateArgs: (newArgs: any, _toolCallId?: string) => {
283
- const a = newArgs as { path?: string; file_path?: string; offset?: number; limit?: number };
284
- entry.path = a.file_path || a.path || entry.path;
285
- entry.offset = a.offset ?? entry.offset;
286
- entry.limit = a.limit ?? entry.limit;
287
- this.#updateReadDisplay(entry);
288
- },
289
- updateResult: (result: any, isPartial?: boolean, _toolCallId?: string) => {
290
- if (isPartial) return;
291
- entry.status = result.isError ? "error" : "success";
292
- this.#updateReadDisplay(entry);
293
- },
294
- setArgsComplete: () => {},
295
- setExpanded: () => {},
296
- };
297
- }
298
-
299
- #updateReadDisplay(entry: ReadEntry): void {
300
- const statusIcon =
301
- entry.status === "success"
302
- ? theme.fg("success", theme.status.success)
303
- : entry.status === "error"
304
- ? theme.fg("error", theme.status.error)
305
- : theme.fg("dim", theme.status.pending);
306
- const filePath = shortenPath(entry.path);
307
- let pathDisplay = filePath ? theme.fg("accent", filePath) : theme.fg("toolOutput", "…");
308
- if (entry.offset !== undefined || entry.limit !== undefined) {
309
- const startLine = entry.offset ?? 1;
310
- const endLine = entry.limit !== undefined ? startLine + entry.limit - 1 : "";
311
- pathDisplay += theme.fg("warning", `:${startLine}${endLine ? `-${endLine}` : ""}`);
312
- }
313
- entry.text.setText(`${statusIcon} ${theme.fg("toolTitle", theme.bold("Read"))} ${pathDisplay}`.trimEnd());
314
- }
315
-
316
- // --- Public setters ---
317
-
318
- setIntent(intent: string): void {
319
- this.#intent = intent;
320
- this.#updateHeader();
321
- }
322
-
323
- setLogs(logs: string[]): void {
324
- this.#logs = logs;
325
- this.#updateLogs();
326
- }
327
-
328
- setDone(): void {
329
- this.#done = true;
330
- this.#stopSpinner();
331
- this.#updateHeader();
332
- }
333
-
334
- // --- Rendering ---
335
-
336
- #updateHeader(): void {
337
- const icon = this.#done
338
- ? theme.fg("success", theme.status.success)
339
- : theme.fg("accent", this.#spinnerFrames[this.#spinnerFrame] ?? theme.format.bullet);
340
- const intent = this.#intent || "Running";
341
- this.#header.setText(` ${icon} ${theme.fg("muted", intent)}`);
342
- }
343
-
344
- #startSpinner(): void {
345
- if (this.#spinnerInterval) return;
346
- this.#spinnerInterval = setInterval(() => {
347
- if (this.#done) return;
348
- this.#spinnerFrame = (this.#spinnerFrame + 1) % this.#spinnerFrames.length;
349
- this.#updateHeader();
350
- this.#ui.requestRender();
351
- }, 80);
352
- }
353
-
354
- #stopSpinner(): void {
355
- if (this.#spinnerInterval) {
356
- clearInterval(this.#spinnerInterval);
357
- this.#spinnerInterval = undefined;
358
- }
359
- }
360
-
361
- #updateLogs(): void {
362
- if (this.#logs.length === 0) {
363
- this.#logsText.setText("");
364
- return;
365
- }
366
- const lines = this.#logs.map(log => ` ${theme.tree.vertical} ${theme.fg("dim", log)}`);
367
- this.#logsText.setText(lines.join("\n"));
368
- }
369
- }
@@ -1,119 +0,0 @@
1
- import { Container, Text } from "@nghyane/arcane-tui";
2
- import { theme } from "../../modes/theme/theme";
3
- import { shortenPath } from "../../tools/render-utils";
4
- import type { ToolExecutionHandle } from "./tool-execution";
5
-
6
- type ReadRenderArgs = {
7
- path?: string;
8
- file_path?: string;
9
- offset?: number;
10
- limit?: number;
11
- };
12
-
13
- type ReadEntry = {
14
- toolCallId: string;
15
- path: string;
16
- offset?: number;
17
- limit?: number;
18
- status: "pending" | "success" | "error";
19
- };
20
-
21
- export class ReadToolGroupComponent extends Container implements ToolExecutionHandle {
22
- #entries = new Map<string, ReadEntry>();
23
- #text: Text;
24
-
25
- constructor() {
26
- super();
27
- this.#text = new Text("", 0, 0);
28
- this.addChild(this.#text);
29
- this.#updateDisplay();
30
- }
31
-
32
- updateArgs(args: ReadRenderArgs, toolCallId?: string): void {
33
- if (!toolCallId) return;
34
- const rawPath = args.file_path || args.path || "";
35
- const entry: ReadEntry = this.#entries.get(toolCallId) ?? {
36
- toolCallId,
37
- path: rawPath,
38
- offset: args.offset,
39
- limit: args.limit,
40
- status: "pending",
41
- };
42
- entry.path = rawPath;
43
- entry.offset = args.offset;
44
- entry.limit = args.limit;
45
- this.#entries.set(toolCallId, entry);
46
- this.#updateDisplay();
47
- }
48
-
49
- updateResult(
50
- result: { content: Array<{ type: string; text?: string }>; details?: unknown; isError?: boolean },
51
- isPartial = false,
52
- toolCallId?: string,
53
- ): void {
54
- if (!toolCallId) return;
55
- const entry = this.#entries.get(toolCallId);
56
- if (!entry) return;
57
- if (isPartial) return;
58
- entry.status = result.isError ? "error" : "success";
59
- this.#updateDisplay();
60
- }
61
-
62
- setArgsComplete(_toolCallId?: string): void {
63
- this.#updateDisplay();
64
- }
65
-
66
- setExpanded(_expanded: boolean): void {
67
- this.#updateDisplay();
68
- }
69
-
70
- #updateDisplay(): void {
71
- const entries = [...this.#entries.values()];
72
-
73
- if (entries.length === 0) {
74
- this.#text.setText(` ${theme.format.bullet} ${theme.fg("toolTitle", theme.bold("Read"))}`);
75
- return;
76
- }
77
-
78
- if (entries.length === 1) {
79
- const entry = entries[0];
80
- const statusSymbol = this.#formatStatus(entry.status);
81
- const pathDisplay = this.#formatPath(entry);
82
- this.#text.setText(` ${statusSymbol} ${theme.fg("toolTitle", theme.bold("Read"))} ${pathDisplay}`.trimEnd());
83
- return;
84
- }
85
-
86
- const header = `${theme.fg("toolTitle", theme.bold("Read"))}${theme.fg("dim", ` (${entries.length})`)}`;
87
- const lines = [` ${theme.format.bullet} ${header}`];
88
- const total = entries.length;
89
- for (const [index, entry] of entries.entries()) {
90
- const connector = index === total - 1 ? theme.tree.last : theme.tree.branch;
91
- const statusSymbol = this.#formatStatus(entry.status);
92
- const pathDisplay = this.#formatPath(entry);
93
- lines.push(` ${theme.fg("dim", connector)} ${statusSymbol} ${pathDisplay}`.trimEnd());
94
- }
95
-
96
- this.#text.setText(lines.join("\n"));
97
- }
98
-
99
- #formatPath(entry: ReadEntry): string {
100
- const filePath = shortenPath(entry.path);
101
- let pathDisplay = filePath ? theme.fg("accent", filePath) : theme.fg("toolOutput", "…");
102
- if (entry.offset !== undefined || entry.limit !== undefined) {
103
- const startLine = entry.offset ?? 1;
104
- const endLine = entry.limit !== undefined ? startLine + entry.limit - 1 : "";
105
- pathDisplay += theme.fg("warning", `:${startLine}${endLine ? `-${endLine}` : ""}`);
106
- }
107
- return pathDisplay;
108
- }
109
-
110
- #formatStatus(status: ReadEntry["status"]): string {
111
- if (status === "success") {
112
- return theme.fg("success", theme.status.success);
113
- }
114
- if (status === "error") {
115
- return theme.fg("error", theme.status.error);
116
- }
117
- return theme.fg("dim", theme.status.pending);
118
- }
119
- }
@@ -1,63 +0,0 @@
1
- /**
2
- * Shared utility for truncating text to visual lines (accounting for line wrapping).
3
- * Used by both tool-execution.ts and bash-execution.ts for consistent behavior.
4
- */
5
- import { Text } from "@nghyane/arcane-tui";
6
-
7
- export interface VisualTruncateResult {
8
- /** The visual lines to display */
9
- visualLines: string[];
10
- /** Number of visual lines that were skipped (hidden) */
11
- skippedCount: number;
12
- }
13
-
14
- const textCache = new Map<number, Text>();
15
-
16
- function getCachedText(paddingX: number): Text {
17
- let text = textCache.get(paddingX);
18
- if (!text) {
19
- text = new Text("", paddingX, 0);
20
- textCache.set(paddingX, text);
21
- }
22
- return text;
23
- }
24
-
25
- /**
26
- * Truncate text to a maximum number of visual lines (from the end).
27
- * This accounts for line wrapping based on terminal width.
28
- *
29
- * @param text - The text content (may contain newlines)
30
- * @param maxVisualLines - Maximum number of visual lines to show
31
- * @param width - Terminal/render width
32
- * @param paddingX - Horizontal padding for Text component (default 0).
33
- * Use 0 when result will be placed in a Box (Box adds its own padding).
34
- * Use 1 when result will be placed in a plain Container.
35
- * @returns The truncated visual lines and count of skipped lines
36
- */
37
- export function truncateToVisualLines(
38
- text: string,
39
- maxVisualLines: number,
40
- width: number,
41
- paddingX: number = 0,
42
- ): VisualTruncateResult {
43
- if (!text) {
44
- return { visualLines: [], skippedCount: 0 };
45
- }
46
-
47
- // Create a temporary Text component to render and get visual lines
48
- const tempText = getCachedText(paddingX);
49
- if (tempText.getText() !== text) {
50
- tempText.setText(text);
51
- }
52
- const allVisualLines = tempText.render(width);
53
-
54
- if (allVisualLines.length <= maxVisualLines) {
55
- return { visualLines: allVisualLines, skippedCount: 0 };
56
- }
57
-
58
- // Take the last N visual lines
59
- const truncatedLines = allVisualLines.slice(-maxVisualLines);
60
- const skippedCount = allVisualLines.length - maxVisualLines;
61
-
62
- return { visualLines: truncatedLines, skippedCount };
63
- }
@@ -1,8 +0,0 @@
1
- {{#if context}}
2
- <swarm_context>{{context}}</swarm_context>
3
-
4
- # Your Assignment
5
- {{assignment}}
6
- {{else}}
7
- {{assignment}}
8
- {{/if}}
@@ -1,44 +0,0 @@
1
- # Ask
2
-
3
- Ask user when you need clarification or input during task execution.
4
-
5
- <conditions>
6
- - Multiple approaches exist with significantly different tradeoffs user should weigh
7
- </conditions>
8
-
9
- <instruction>
10
- - Use `recommended: <index>` to mark default (0-indexed); " (Recommended)" added automatically
11
- - Use `questions` for multiple related questions instead of asking one at a time
12
- - Set `multi: true` on question to allow multiple selections
13
- </instruction>
14
-
15
- <output>
16
- Returns selected option(s) as text. For multi-part questions, returns map of question IDs to selected values.
17
- </output>
18
-
19
- <caution>
20
- - Provide 2-5 concise, distinct options
21
- </caution>
22
-
23
- <critical>
24
- **Default to action. Do NOT ask unless you are genuinely blocked and user preference is required to avoid a wrong outcome.**
25
- 1. **Resolve ambiguity yourself** using repo conventions, existing patterns, and reasonable defaults.
26
- 2. **Exhaust existing sources** (code, configs, docs, history) before asking anything.
27
- 3. **If multiple choices are acceptable**, pick the most conservative/standard option and proceed; state the choice.
28
- 4. **Only ask when options have materially different tradeoffs and the user must decide.**
29
- **Do NOT include "Other" option in your options array.** UI automatically adds "Other (type your own)" to every question; adding your own creates duplicates.
30
- </critical>
31
-
32
- <example name="single">
33
- question: "Which authentication method should this API use?"
34
- options: [{"label": "JWT"}, {"label": "OAuth2"}, {"label": "Session cookies"}]
35
- recommended: 0
36
- </example>
37
-
38
- <example name="multi-part">
39
- questions: [
40
- {"id": "auth", "question": "Which auth method?", "options": [{"label": "JWT"}, {"label": "OAuth2"}], "recommended": 0},
41
- {"id": "cache", "question": "Enable caching?", "options": [{"label": "Yes"}, {"label": "No"}]},
42
- {"id": "features", "question": "Which features to include?", "options": [{"label": "Logging"}, {"label": "Metrics"}, {"label": "Tracing"}], "multi": true}
43
- ]
44
- </example>
@@ -1,24 +0,0 @@
1
- # Bash
2
-
3
- Executes bash command in shell session for terminal operations like git, bun, cargo, python.
4
-
5
- <instruction>
6
- - Use `cwd` parameter to set working directory instead of `cd dir && ...`
7
- - Use `;` only when later commands should run regardless of earlier failures
8
- - `skill://` URIs are auto-resolved to filesystem paths before execution
9
- - `python skill://my-skill/scripts/init.py` runs the script from the skill directory
10
- - `skill://<name>/<relative-path>` resolves within the skill's base directory
11
- - `agent://`, `artifact://`, `plan://`, `memory://`, `rule://`, and `docs://` URIs are also auto-resolved to filesystem paths before execution
12
- </instruction>
13
-
14
- <output>
15
- Returns the output, and an exit code from command execution.
16
- - If output truncated, full output stored under $ARTIFACTS and referenced as `artifact://<id>` in metadata
17
- - Exit codes shown on non-zero exit
18
- </output>
19
-
20
- <critical>
21
- - Do NOT use Bash for these operations like read, grep, find, edit, write, where specialized tools exist.
22
- - Do NOT use `2>&1` pattern, stdout and stderr are already merged.
23
- - Do NOT use `| head -n 50` or `| tail -n 100` pattern, use `head` and `tail` parameters instead.
24
- </critical>
@@ -1,33 +0,0 @@
1
- # Browser
2
-
3
- Use this tool to navigate, click, type, scroll, drag, query DOM content, and capture screenshots.
4
-
5
- <instruction>
6
- - Use `action: "open"` to start a new headless browser session (or implicitly launch on first action)
7
- - Use `action: "goto"` with `url` to navigate
8
- - Use `action: "observe"` to capture a numbered accessibility snapshot with URL/title/viewport/scroll info
9
- - Prefer `click_id`, `type_id`, or `fill_id` actions using the returned `element_id` values
10
- - Optional flags: `include_all` to include non-interactive nodes, `viewport_only` to limit to visible elements
11
- - Use `action: "click"`, `"type"`, `"fill"`, `"press"`, `"scroll"`, or `"drag"` for selector-based interactions
12
- - Prefer ARIA or text selectors (e.g. `p-aria/[name="Sign in"]`, `p-text/Continue`) over brittle CSS
13
- - Use `action: "click_id"`, `"type_id"`, or `"fill_id"` to interact with observed elements without selectors
14
- - Use `action: "wait_for_selector"` before interacting when the page is dynamic
15
- - Use `action: "evaluate"` with `script` to run a JavaScript expression in the page context
16
- - Use `action: "get_text"`, `"get_html"`, or `"get_attribute"` for DOM queries
17
- - For batch queries, pass `args: [{ selector, attribute? }]` to get an array of results (attribute required for `get_attribute`)
18
- - Use `action: "extract_readable"` to return reader-mode content (title/byline/excerpt/text or markdown)
19
- - Set `format` to `"markdown"` (default) or `"text"`
20
- - Use `action: "screenshot"` to capture images (optionally with `selector` to capture a single element)
21
- - Use `action: "close"` to release the browser when done
22
- </instruction>
23
-
24
- <critical>
25
- **Default to `observe`, not `screenshot`.**
26
- - `observe` is cheaper, faster, and returns structured data — use it to understand page state, find elements, and plan interactions.
27
- - Only use `screenshot` when visual appearance matters (verifying layout, debugging CSS, capturing a visual artifact for the user).
28
- - Never screenshot just to "see what's on the page" — `observe` gives you that with element IDs you can act on immediately.
29
- </critical>
30
-
31
- <output>
32
- Returns text output for navigation and DOM queries, and image output for screenshots. Screenshots can optionally be saved to disk via the `path` parameter.
33
- </output>
@@ -1,12 +0,0 @@
1
- # Calculator
2
-
3
- Basic calculations.
4
-
5
- <instruction>
6
- - Supports +, -, *, /, %, ** and parentheses
7
- - Supports decimal, hex (0x), binary (0b), and octal (0o) literals
8
- </instruction>
9
-
10
- <output>
11
- Returns each calculation result with its prefix and suffix applied.
12
- </output>