@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
@@ -16,12 +16,10 @@ import type {
16
16
  default as Puppeteer,
17
17
  SerializedAXNode,
18
18
  } from "puppeteer";
19
- import { renderPromptTemplate } from "../config/prompt-templates";
20
- import browserDescription from "../prompts/tools/browser.md" with { type: "text" };
21
19
  import type { ToolSession } from "../sdk";
22
20
  import { formatDimensionNote, resizeImage } from "../utils/image-resize";
23
21
  import { htmlToBasicMarkdown } from "../web/scrapers/types";
24
- import type { OutputMeta } from "./output-meta";
22
+ import { type OutputMeta, toolResult } from "./output-meta";
25
23
  import stealthTamperingScript from "./puppeteer/00_stealth_tampering.txt" with { type: "text" };
26
24
  import stealthActivityScript from "./puppeteer/01_stealth_activity.txt" with { type: "text" };
27
25
  import stealthHairlineScript from "./puppeteer/02_stealth_hairline.txt" with { type: "text" };
@@ -37,7 +35,6 @@ import stealthHardwareScript from "./puppeteer/11_stealth_hardware.txt" with { t
37
35
  import stealthCodecsScript from "./puppeteer/12_stealth_codecs.txt" with { type: "text" };
38
36
  import stealthWorkerScript from "./puppeteer/13_stealth_worker.txt" with { type: "text" };
39
37
  import { ToolAbortError, ToolError, throwIfAborted } from "./tool-errors";
40
- import { toolResult } from "./tool-result";
41
38
 
42
39
  /**
43
40
  * Lazy-import puppeteer from a safe CWD so cosmiconfig doesn't choke
@@ -312,95 +309,70 @@ function resolvePageClient(page: Page): PuppeteerCdpClient | null {
312
309
 
313
310
  const puppeteerGetArgsSchema = Type.Array(
314
311
  Type.Object({
315
- selector: Type.String({
316
- description:
317
- "Selector for the target element (CSS, or puppeteer query handler like aria/, text/, xpath/, pierce/; also accepts legacy p- prefixes)",
318
- }),
319
- attribute: Type.Optional(Type.String({ description: "Attribute name (get_attribute)" })),
312
+ selector: Type.String({ description: "CSS selector" }),
313
+ attribute: Type.Optional(Type.String({ description: "Attribute to retrieve" })),
320
314
  }),
321
- { description: "Batch arguments for get_* actions", minItems: 1 },
315
+ { minItems: 1 },
322
316
  );
323
317
 
324
318
  const browserSchema = Type.Object({
325
- action: StringEnum(
326
- [
327
- "open",
328
- "goto",
329
- "observe",
330
- "click",
331
- "click_id",
332
- "type",
333
- "type_id",
334
- "fill",
335
- "fill_id",
336
- "press",
337
- "scroll",
338
- "drag",
339
- "wait_for_selector",
340
- "evaluate",
341
- "get_text",
342
- "get_html",
343
- "get_attribute",
344
- "extract_readable",
345
- "screenshot",
346
- "close",
347
- ],
348
- { description: "Action to perform" },
349
- ),
350
- url: Type.Optional(Type.String({ description: "URL to navigate to (goto)" })),
351
- selector: Type.Optional(
352
- Type.String({
353
- description:
354
- "Selector for the target element (CSS, or puppeteer query handler like aria/, text/, xpath/, pierce/; also accepts legacy p- prefixes)",
355
- }),
356
- ),
357
- element_id: Type.Optional(Type.Number({ description: "Element ID from observe" })),
358
- include_all: Type.Optional(Type.Boolean({ description: "Include non-interactive nodes in observe" })),
359
- viewport_only: Type.Optional(Type.Boolean({ description: "Limit observe output to elements in the viewport" })),
319
+ action: StringEnum([
320
+ "open",
321
+ "goto",
322
+ "observe",
323
+ "click",
324
+ "click_id",
325
+ "type",
326
+ "type_id",
327
+ "fill",
328
+ "fill_id",
329
+ "press",
330
+ "scroll",
331
+ "drag",
332
+ "wait_for_selector",
333
+ "evaluate",
334
+ "get_text",
335
+ "get_html",
336
+ "get_attribute",
337
+ "extract_readable",
338
+ "screenshot",
339
+ "close",
340
+ ]),
341
+ url: Type.Optional(Type.String({ description: "URL to navigate to" })),
342
+ selector: Type.Optional(Type.String({ description: "CSS selector for target element" })),
343
+ element_id: Type.Optional(Type.Number({ description: "Observed element ID from observe action" })),
344
+ include_all: Type.Optional(Type.Boolean({ description: "Include all elements, not just interactive ones" })),
345
+ viewport_only: Type.Optional(Type.Boolean({ description: "Only observe elements in the visible viewport" })),
360
346
  args: Type.Optional(puppeteerGetArgsSchema),
361
- script: Type.Optional(Type.String({ description: "JavaScript to evaluate (evaluate)" })),
362
- text: Type.Optional(Type.String({ description: "Text to type (type)" })),
363
- value: Type.Optional(Type.String({ description: "Value to set (fill)" })),
364
- attribute: Type.Optional(Type.String({ description: "Attribute name to read (get_attribute)" })),
365
- key: Type.Optional(Type.String({ description: "Keyboard key to press (press)" })),
366
- timeout: Type.Optional(Type.Number({ description: "Timeout in seconds (default: 30)" })),
347
+ script: Type.Optional(Type.String({ description: "JavaScript to evaluate in page context" })),
348
+ text: Type.Optional(Type.String({ description: "Text to type" })),
349
+ value: Type.Optional(Type.String({ description: "Value to fill into input" })),
350
+ attribute: Type.Optional(Type.String({ description: "Attribute name to retrieve" })),
351
+ key: Type.Optional(Type.String({ description: "Key to press (e.g. Enter, Escape)" })),
352
+ timeout: Type.Optional(Type.Number({ description: "Timeout in milliseconds" })),
367
353
  wait_until: Type.Optional(
368
354
  StringEnum(["load", "domcontentloaded", "networkidle0", "networkidle2"], {
369
- description: "Navigation wait condition (goto)",
370
- }),
371
- ),
372
- full_page: Type.Optional(Type.Boolean({ description: "Capture full page screenshot (screenshot)" })),
373
- format: Type.Optional(
374
- StringEnum(["text", "markdown"], {
375
- description: "Output format for extract_readable (text/markdown)",
355
+ description: "Navigation wait condition",
376
356
  }),
377
357
  ),
378
- path: Type.Optional(Type.String({ description: "Optional path to save screenshot (relative to cwd)" })),
358
+ full_page: Type.Optional(Type.Boolean({ description: "Capture full page screenshot" })),
359
+ format: Type.Optional(StringEnum(["text", "markdown"], { description: "Output format for content extraction" })),
360
+ path: Type.Optional(Type.String({ description: "File path for screenshot output" })),
379
361
  viewport: Type.Optional(
380
362
  Type.Object({
381
- width: Type.Number({ description: "Viewport width in pixels" }),
382
- height: Type.Number({ description: "Viewport height in pixels" }),
383
- deviceScaleFactor: Type.Optional(Type.Number({ description: "Device scale factor" })),
384
- }),
385
- ),
386
- delta_x: Type.Optional(Type.Number({ description: "Scroll delta X (scroll)" })),
387
- delta_y: Type.Optional(Type.Number({ description: "Scroll delta Y (scroll)" })),
388
- from_selector: Type.Optional(
389
- Type.String({
390
- description:
391
- "Drag start selector (CSS, or puppeteer query handler like aria/, text/, xpath/, pierce/; also accepts legacy p- prefixes)",
392
- }),
393
- ),
394
- to_selector: Type.Optional(
395
- Type.String({
396
- description:
397
- "Drag end selector (CSS, or puppeteer query handler like aria/, text/, xpath/, pierce/; also accepts legacy p- prefixes)",
363
+ width: Type.Number(),
364
+ height: Type.Number(),
365
+ deviceScaleFactor: Type.Optional(Type.Number()),
398
366
  }),
399
367
  ),
368
+ delta_x: Type.Optional(Type.Number({ description: "Horizontal scroll or drag distance" })),
369
+ delta_y: Type.Optional(Type.Number({ description: "Vertical scroll or drag distance" })),
370
+ from_selector: Type.Optional(Type.String({ description: "Drag source selector" })),
371
+ to_selector: Type.Optional(Type.String({ description: "Drag target selector" })),
400
372
  });
401
373
 
402
374
  /** Input schema for the Puppeteer tool. */
403
- export type BrowserParams = Static<typeof browserSchema>;
375
+ type BrowserParams = Static<typeof browserSchema>;
404
376
 
405
377
  /** Details describing a Puppeteer tool execution result. */
406
378
  export interface BrowserToolDetails {
@@ -418,7 +390,7 @@ export interface BrowserToolDetails {
418
390
  meta?: OutputMeta;
419
391
  }
420
392
 
421
- export interface ObservationEntry {
393
+ interface ObservationEntry {
422
394
  id: number;
423
395
  role: string;
424
396
  name?: string;
@@ -428,7 +400,7 @@ export interface ObservationEntry {
428
400
  states: string[];
429
401
  }
430
402
 
431
- export interface Observation {
403
+ interface Observation {
432
404
  url: string;
433
405
  title?: string;
434
406
  viewport: { width: number; height: number; deviceScaleFactor?: number };
@@ -443,7 +415,7 @@ export interface Observation {
443
415
  elements: ObservationEntry[];
444
416
  }
445
417
 
446
- export interface ReadableResult {
418
+ interface ReadableResult {
447
419
  url: string;
448
420
  title?: string;
449
421
  byline?: string;
@@ -482,7 +454,7 @@ function formatEvaluateResult(value: unknown): string {
482
454
  export class BrowserTool implements AgentTool<typeof browserSchema, BrowserToolDetails> {
483
455
  readonly name = "puppeteer";
484
456
  readonly label = "Puppeteer";
485
- readonly description: string;
457
+ description = "Control a headless browser for web interaction";
486
458
  readonly parameters = browserSchema;
487
459
  #browser: Browser | null = null;
488
460
  #page: Page | null = null;
@@ -493,9 +465,7 @@ export class BrowserTool implements AgentTool<typeof browserSchema, BrowserToolD
493
465
  readonly #elementCache = new Map<number, ElementHandle>();
494
466
  readonly #patchedClients = new WeakSet<object>();
495
467
 
496
- constructor(private readonly session: ToolSession) {
497
- this.description = renderPromptTemplate(browserDescription, {});
498
- }
468
+ constructor(private readonly session: ToolSession) {}
499
469
 
500
470
  async #closeBrowser(): Promise<void> {
501
471
  await this.#clearElementCache();
@@ -0,0 +1,186 @@
1
+ import type { AgentTool } from "@nghyane/arcane-agent";
2
+ import { $env, logger } from "@nghyane/arcane-utils";
3
+ import { getPreludeDocs, warmPythonEnvironment } from "../ipy/executor";
4
+ import { checkPythonKernelAvailability } from "../ipy/kernel";
5
+ import { LspTool } from "../lsp";
6
+ import { EditTool } from "../patch";
7
+ import { TaskTool } from "../task";
8
+ import { time } from "../utils/timings";
9
+ import { SearchTool } from "../web/search";
10
+ import { AskTool } from "./ask";
11
+ import { BashTool } from "./bash";
12
+ import { BrowserTool } from "./browser";
13
+ import { exploreConfig } from "./explore";
14
+ import { FetchTool } from "./fetch";
15
+ import { FindTool } from "./find";
16
+ import { GitHubTool } from "./github";
17
+ import { GrepTool } from "./grep";
18
+ import type { ToolSession } from "./index";
19
+ import { librarianConfig } from "./librarian";
20
+ import { NotebookTool } from "./notebook";
21
+ import { oracleConfig } from "./oracle";
22
+ import { wrapToolWithMetaNotice } from "./output-meta";
23
+ import { PythonTool } from "./python";
24
+ import { ReadTool } from "./read";
25
+ import { reviewerConfig } from "./reviewer-tool";
26
+ import { SearchCodeTool } from "./search-code";
27
+ import { loadSshTool } from "./ssh";
28
+ import { SubagentTool } from "./subagent-tool";
29
+ import { TodoWriteTool } from "./todo-write";
30
+ import { UndoEditTool } from "./undo-edit";
31
+ import { WriteTool } from "./write";
32
+
33
+ type ToolFactory = (session: ToolSession) => AgentTool<any, any, any> | null | Promise<AgentTool<any, any, any> | null>;
34
+
35
+ export const BUILTIN_TOOLS: Record<string, ToolFactory> = {
36
+ ask: AskTool.createIf,
37
+ bash: s => new BashTool(s),
38
+ python: s => new PythonTool(s),
39
+ ssh: loadSshTool,
40
+ edit: s => new EditTool(s),
41
+ find: s => new FindTool(s),
42
+ explore: s => new SubagentTool(s, exploreConfig),
43
+ github: s => new GitHubTool(s),
44
+ grep: s => new GrepTool(s),
45
+ librarian: s => new SubagentTool(s, librarianConfig),
46
+ lsp: LspTool.createIf,
47
+ notebook: s => new NotebookTool(s),
48
+ oracle: s => new SubagentTool(s, oracleConfig),
49
+ read: s => new ReadTool(s),
50
+ browser: s => new BrowserTool(s),
51
+ task: TaskTool.create,
52
+ code_review: s => new SubagentTool(s, reviewerConfig),
53
+ todo_write: s => new TodoWriteTool(s),
54
+ undo_edit: s => new UndoEditTool(s),
55
+ fetch: s => new FetchTool(s),
56
+ web_search: () => new SearchTool(),
57
+ search_code: () => new SearchCodeTool(),
58
+ write: s => new WriteTool(s),
59
+ };
60
+
61
+ export type ToolName = keyof typeof BUILTIN_TOOLS;
62
+
63
+ type PythonToolMode = "ipy-only" | "bash-only" | "both";
64
+
65
+ /**
66
+ * Parse ARCANE_PY environment variable to determine Python tool mode.
67
+ * Returns null if not set or invalid.
68
+ *
69
+ * Values:
70
+ * - "0" or "bash" \u2192 bash-only
71
+ * - "1" or "py" \u2192 ipy-only
72
+ * - "mix" or "both" \u2192 both
73
+ */
74
+ function getPythonModeFromEnv(): PythonToolMode | null {
75
+ const value = $env.ARCANE_PY?.toLowerCase();
76
+ if (!value) return null;
77
+
78
+ switch (value) {
79
+ case "0":
80
+ case "bash":
81
+ return "bash-only";
82
+ case "1":
83
+ case "py":
84
+ return "ipy-only";
85
+ case "mix":
86
+ case "both":
87
+ return "both";
88
+ default:
89
+ return null;
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Create tools from BUILTIN_TOOLS registry.
95
+ */
96
+ export async function createTools(session: ToolSession, toolNames?: string[]): Promise<AgentTool[]> {
97
+ time("createTools:start");
98
+ const enableLsp = session.enableLsp ?? true;
99
+ const requestedTools = toolNames && toolNames.length > 0 ? [...new Set(toolNames)] : undefined;
100
+ const pythonMode = getPythonModeFromEnv() ?? session.settings.get("python.toolMode");
101
+ const skipPythonPreflight = session.skipPythonPreflight === true;
102
+ let pythonAvailable = true;
103
+ const shouldCheckPython =
104
+ !skipPythonPreflight &&
105
+ pythonMode !== "bash-only" &&
106
+ (requestedTools === undefined || requestedTools.includes("python"));
107
+ const isTestEnv = Bun.env.BUN_ENV === "test" || Bun.env.NODE_ENV === "test";
108
+ const skipPythonWarm = isTestEnv || $env.ARCANE_PYTHON_SKIP_CHECK === "1";
109
+ if (shouldCheckPython) {
110
+ const availability = await checkPythonKernelAvailability(session.cwd);
111
+ time("createTools:pythonCheck");
112
+ pythonAvailable = availability.ok;
113
+ if (!availability.ok) {
114
+ logger.warn("Python kernel unavailable, falling back to bash", {
115
+ reason: availability.reason,
116
+ });
117
+ } else if (!skipPythonWarm && getPreludeDocs().length === 0) {
118
+ const sessionFile = session.getSessionFile?.() ?? undefined;
119
+ const warmSessionId = sessionFile ? `session:${sessionFile}:cwd:${session.cwd}` : `cwd:${session.cwd}`;
120
+ try {
121
+ await warmPythonEnvironment(session.cwd, warmSessionId, session.settings.get("python.sharedGateway"));
122
+ time("createTools:warmPython");
123
+ } catch (err) {
124
+ logger.warn("Failed to warm Python environment", {
125
+ error: err instanceof Error ? err.message : String(err),
126
+ });
127
+ }
128
+ }
129
+ }
130
+
131
+ const effectiveMode = pythonAvailable ? pythonMode : "bash-only";
132
+ const allowBash = effectiveMode !== "ipy-only";
133
+ const allowPython = effectiveMode !== "bash-only";
134
+ if (
135
+ requestedTools &&
136
+ allowBash &&
137
+ !allowPython &&
138
+ requestedTools.includes("python") &&
139
+ !requestedTools.includes("bash")
140
+ ) {
141
+ requestedTools.push("bash");
142
+ }
143
+ const allTools: Record<string, ToolFactory> = { ...BUILTIN_TOOLS };
144
+ const isToolAllowed = (name: string) => {
145
+ if (name === "lsp") return enableLsp;
146
+ if (name === "bash") return allowBash;
147
+ if (name === "python") return allowPython;
148
+ if (name === "todo_write") return session.settings.get("todo.enabled");
149
+ if (name === "find") return session.settings.get("find.enabled");
150
+ if (name === "grep") return session.settings.get("grep.enabled");
151
+ if (name === "notebook") return session.settings.get("notebook.enabled");
152
+ if (name === "fetch") return session.settings.get("fetch.enabled");
153
+ if (name === "web_search") return session.settings.get("web_search.enabled");
154
+ if (name === "lsp") return session.settings.get("lsp.enabled");
155
+ if (name === "browser") return session.settings.get("browser.enabled");
156
+ if (name === "librarian") return session.settings.get("librarian.enabled");
157
+ if (name === "oracle") return session.settings.get("oracle.enabled");
158
+ if (name === "github") return session.settings.get("github.enabled");
159
+ if (name === "search_code") return session.isSubagent;
160
+ if (name === "task") {
161
+ return !session.isSubagent;
162
+ }
163
+ return true;
164
+ };
165
+
166
+ const filteredRequestedTools = requestedTools?.filter(name => name in allTools && isToolAllowed(name));
167
+
168
+ const entries =
169
+ filteredRequestedTools !== undefined
170
+ ? filteredRequestedTools.map(name => [name, allTools[name]] as const)
171
+ : [...Object.entries(BUILTIN_TOOLS).filter(([name]) => isToolAllowed(name))];
172
+
173
+ const results = await Promise.all(
174
+ entries.map(async ([name, factory]) => {
175
+ if (filteredRequestedTools && !filteredRequestedTools.includes(name)) {
176
+ return null;
177
+ }
178
+ const tool = await factory(session);
179
+ time(`createTools:${name}`);
180
+ return tool ? wrapToolWithMetaNotice(tool) : null;
181
+ }),
182
+ );
183
+ const tools = results.filter((r): r is AgentTool => r !== null);
184
+
185
+ return tools;
186
+ }
@@ -0,0 +1,104 @@
1
+ import type { Component } from "@nghyane/arcane-tui";
2
+ import { Text } from "@nghyane/arcane-tui";
3
+ import type { RenderResultOptions } from "../extensibility/custom-tools/types";
4
+ import type { Theme } from "../theme/theme";
5
+ import { renderStatusLine } from "../tui";
6
+ import { formatMoreItems, PREVIEW_LIMITS, TRUNCATE_LENGTHS, truncateToWidth } from "../ui/render-utils";
7
+ import {
8
+ formatArgsInline,
9
+ JSON_TREE_MAX_DEPTH_COLLAPSED,
10
+ JSON_TREE_MAX_DEPTH_EXPANDED,
11
+ JSON_TREE_MAX_LINES_COLLAPSED,
12
+ JSON_TREE_MAX_LINES_EXPANDED,
13
+ JSON_TREE_SCALAR_LEN_COLLAPSED,
14
+ JSON_TREE_SCALAR_LEN_EXPANDED,
15
+ renderJsonTreeLines,
16
+ } from "./json-tree";
17
+
18
+ function asRecord(value: unknown): Record<string, unknown> | null {
19
+ if (value !== null && value !== undefined && typeof value === "object") {
20
+ return value as Record<string, unknown>;
21
+ }
22
+ return null;
23
+ }
24
+
25
+ export interface DefaultRenderer {
26
+ renderCall: (args: unknown, options: RenderResultOptions, theme: Theme) => Component;
27
+ renderResult: (
28
+ result: { content: Array<{ type: string; text?: string }>; details?: unknown; isError?: boolean },
29
+ options: RenderResultOptions,
30
+ theme: Theme,
31
+ args?: unknown,
32
+ ) => Component;
33
+ }
34
+
35
+ export const defaultRenderer: DefaultRenderer = {
36
+ renderCall(args: unknown, options: RenderResultOptions, theme: Theme): Component {
37
+ const label = options.label ?? "Tool";
38
+ const lines: string[] = [];
39
+ lines.push(renderStatusLine({ icon: "pending", title: label }, theme));
40
+
41
+ const argsObject = asRecord(args);
42
+ if (argsObject && Object.keys(argsObject).length > 0) {
43
+ const preview = formatArgsInline(argsObject, TRUNCATE_LENGTHS.SUBAGENT_ERROR);
44
+ if (preview) {
45
+ lines.push(theme.fg("dim", preview));
46
+ }
47
+ }
48
+ return new Text(lines.join("\n"), 0, 0);
49
+ },
50
+
51
+ renderResult(
52
+ result: { content: Array<{ type: string; text?: string }>; details?: unknown; isError?: boolean },
53
+ options: RenderResultOptions & { renderContext?: Record<string, unknown> },
54
+ theme: Theme,
55
+ _args?: unknown,
56
+ ): Component {
57
+ const { expanded = false, isPartial = false } = options;
58
+ const label = options.label ?? "Tool";
59
+ const lines: string[] = [];
60
+ const icon = isPartial ? "pending" : result.isError ? "error" : "success";
61
+ lines.push(renderStatusLine({ icon, title: label }, theme));
62
+
63
+ // Output
64
+ const textContent = (result.content?.find(c => c.type === "text")?.text ?? "").trimEnd();
65
+ if (!textContent) {
66
+ lines.push(theme.fg("dim", "(no output)"));
67
+ return new Text(lines.join("\n"), 0, 0);
68
+ }
69
+
70
+ // Try JSON tree
71
+ if (textContent.startsWith("{") || textContent.startsWith("[")) {
72
+ try {
73
+ const parsed = JSON.parse(textContent);
74
+ const maxDepth = expanded ? JSON_TREE_MAX_DEPTH_EXPANDED : JSON_TREE_MAX_DEPTH_COLLAPSED;
75
+ const maxLines = expanded ? JSON_TREE_MAX_LINES_EXPANDED : JSON_TREE_MAX_LINES_COLLAPSED;
76
+ const maxScalarLen = expanded ? JSON_TREE_SCALAR_LEN_EXPANDED : JSON_TREE_SCALAR_LEN_COLLAPSED;
77
+ const tree = renderJsonTreeLines(parsed, theme, maxDepth, maxLines, maxScalarLen);
78
+ if (tree.lines.length > 0) {
79
+ lines.push(...tree.lines);
80
+ if (tree.truncated) {
81
+ lines.push(theme.fg("dim", "…"));
82
+ }
83
+ return new Text(lines.join("\n"), 0, 0);
84
+ }
85
+ } catch {
86
+ // Fall through to raw output
87
+ }
88
+ }
89
+
90
+ // Raw output
91
+ const outputLines = textContent.split("\n");
92
+ const maxOutputLines = expanded ? PREVIEW_LIMITS.OUTPUT_EXPANDED : PREVIEW_LIMITS.OUTPUT_COLLAPSED;
93
+ const displayLines = outputLines.slice(0, maxOutputLines);
94
+ for (const line of displayLines) {
95
+ lines.push(theme.fg("toolOutput", truncateToWidth(line, TRUNCATE_LENGTHS.CONTENT)));
96
+ }
97
+ if (outputLines.length > maxOutputLines) {
98
+ const remaining = outputLines.length - maxOutputLines;
99
+ lines.push(theme.fg("dim", formatMoreItems(remaining, "line")));
100
+ }
101
+
102
+ return new Text(lines.join("\n"), 0, 0);
103
+ },
104
+ };
@@ -1,23 +1,24 @@
1
1
  import { Type } from "@sinclair/typebox";
2
- import exploreDescription from "../prompts/tools/explore.md" with { type: "text" };
3
- import { createSubagentTool } from "./subagent-tool";
2
+ import type { SubagentConfig } from "./subagent-tool";
4
3
 
5
4
  const schema = Type.Object({
6
- query: Type.String({
7
- description:
8
- "The search query describing what to find. Be specific — include technical terms, file types, or expected code patterns.",
9
- }),
5
+ query: Type.String({ description: "What to search for in the codebase" }),
10
6
  });
11
7
 
12
- export const ExploreTool = createSubagentTool({
8
+ export const exploreConfig: SubagentConfig<typeof schema.properties> = {
13
9
  name: "explore",
14
10
  label: "Explore",
15
11
  agent: "explore",
16
12
  schema,
17
- descriptionTemplate: exploreDescription,
18
13
  progressText: "Searching codebase...",
19
14
  tmpPrefix: "arc-explore-",
20
15
  buildTask: p => p.query as string,
21
- buildDescription: p => `Explore: ${(p.query as string).slice(0, 60)}`,
16
+ buildDescription: p => String(p.query ?? "").slice(0, 80),
17
+ toolDescription: [
18
+ "Intelligently search the codebase. Use for complex, multi-step search tasks where you need to find code based on functionality or concepts rather than exact matches. Chains multiple grep/find/read calls internally.",
19
+ 'WHEN TO USE: Locate code by behavior or concept; chain multiple searches; correlate several areas of the codebase; filter broad terms ("config", "cache", "auth") by context; answer questions like "Where do we validate JWT headers?".',
20
+ "WHEN NOT TO USE: Exact file path known (use read tool); specific symbol lookup (use lsp tool); single exact text match (use grep tool); remote repos (use librarian tool).",
21
+ 'PROMPTING: Be specific and goal-oriented. Name concrete artifacts, patterns, or APIs to narrow scope. State explicit success criteria so the agent knows when to stop. Good: "Find all JWT verification calls, return file paths and line numbers." Bad: "auth search".',
22
+ ].join(" "),
22
23
  passContext: false,
23
- });
24
+ };