@nghyane/arcane 0.1.12 → 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 (333) 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/company.ts +2 -7
  30. package/src/exa/index.ts +1 -35
  31. package/src/exa/linkedin.ts +2 -7
  32. package/src/exa/mcp-client.ts +21 -11
  33. package/src/exa/render.ts +30 -190
  34. package/src/exa/researcher.ts +2 -12
  35. package/src/exa/search.ts +5 -25
  36. package/src/exa/types.ts +3 -3
  37. package/src/exec/bash-executor.ts +2 -1
  38. package/src/exec/non-interactive-env.ts +43 -0
  39. package/src/export/html/index.ts +1 -1
  40. package/src/extensibility/custom-tools/loader.ts +1 -1
  41. package/src/extensibility/custom-tools/types.ts +5 -1
  42. package/src/extensibility/custom-tools/wrapper.ts +1 -1
  43. package/src/extensibility/extensions/runner.ts +1 -1
  44. package/src/extensibility/extensions/types.ts +1 -1
  45. package/src/extensibility/extensions/wrapper.ts +7 -15
  46. package/src/extensibility/hooks/runner.ts +1 -1
  47. package/src/extensibility/hooks/types.ts +1 -1
  48. package/src/extensibility/plugins/doctor.ts +1 -1
  49. package/src/index.ts +13 -13
  50. package/src/lsp/index.ts +77 -24
  51. package/src/lsp/render.ts +34 -583
  52. package/src/lsp/types.ts +3 -3
  53. package/src/lsp/utils.ts +1 -1
  54. package/src/main.ts +1 -1
  55. package/src/mcp/tool-bridge.ts +1 -24
  56. package/src/modes/components/assistant-message.ts +7 -7
  57. package/src/modes/components/bash-execution.ts +48 -113
  58. package/src/modes/components/bordered-loader.ts +1 -1
  59. package/src/modes/components/branch-summary-message.ts +13 -10
  60. package/src/modes/components/compaction-summary-message.ts +14 -13
  61. package/src/modes/components/context-group.ts +106 -0
  62. package/src/modes/components/custom-message.ts +4 -5
  63. package/src/modes/components/diff.ts +2 -2
  64. package/src/modes/components/dynamic-border.ts +1 -1
  65. package/src/modes/components/extensions/extension-dashboard.ts +2 -2
  66. package/src/modes/components/extensions/extension-list.ts +1 -1
  67. package/src/modes/components/extensions/inspector-panel.ts +8 -3
  68. package/src/modes/components/footer.ts +2 -2
  69. package/src/modes/components/history-search.ts +1 -1
  70. package/src/modes/components/hook-editor.ts +1 -1
  71. package/src/modes/components/hook-input.ts +1 -1
  72. package/src/modes/components/hook-message.ts +4 -5
  73. package/src/modes/components/hook-selector.ts +1 -1
  74. package/src/modes/components/index.ts +0 -2
  75. package/src/modes/components/keybinding-hints.ts +1 -1
  76. package/src/modes/components/login-dialog.ts +1 -1
  77. package/src/modes/components/mcp-add-wizard.ts +1 -1
  78. package/src/modes/components/model-selector.ts +1 -1
  79. package/src/modes/components/oauth-selector.ts +1 -1
  80. package/src/modes/components/plugin-settings.ts +1 -1
  81. package/src/modes/components/python-execution.ts +49 -92
  82. package/src/modes/components/queue-mode-selector.ts +1 -1
  83. package/src/modes/components/session-selector.ts +1 -1
  84. package/src/modes/components/settings-defs.ts +5 -10
  85. package/src/modes/components/settings-selector.ts +1 -1
  86. package/src/modes/components/show-images-selector.ts +1 -1
  87. package/src/modes/components/skill-message.ts +4 -4
  88. package/src/modes/components/status-line/segments.ts +2 -2
  89. package/src/modes/components/status-line/separators.ts +1 -1
  90. package/src/modes/components/status-line-segment-editor.ts +1 -1
  91. package/src/modes/components/status-line.ts +1 -1
  92. package/src/modes/components/theme-selector.ts +1 -1
  93. package/src/modes/components/thinking-selector.ts +1 -1
  94. package/src/modes/components/todo-display.ts +2 -4
  95. package/src/modes/components/todo-reminder.ts +4 -4
  96. package/src/modes/components/tool-execution.ts +118 -440
  97. package/src/modes/components/tool-image-display.ts +107 -0
  98. package/src/modes/components/tree-selector.ts +2 -2
  99. package/src/modes/components/ttsr-notification.ts +4 -17
  100. package/src/modes/components/user-message-selector.ts +1 -1
  101. package/src/modes/components/user-message.ts +9 -10
  102. package/src/modes/components/welcome.ts +1 -1
  103. package/src/modes/controllers/command-controller.ts +1 -1
  104. package/src/modes/controllers/event-controller.ts +58 -187
  105. package/src/modes/controllers/extension-ui-controller.ts +1 -1
  106. package/src/modes/controllers/input-controller.ts +3 -1
  107. package/src/modes/controllers/mcp-command-controller.ts +1 -1
  108. package/src/modes/controllers/selector-controller.ts +3 -26
  109. package/src/modes/controllers/ssh-command-controller.ts +1 -1
  110. package/src/modes/interactive-mode.ts +3 -7
  111. package/src/modes/print-mode.ts +5 -5
  112. package/src/modes/rpc/rpc-mode.ts +1 -1
  113. package/src/modes/types.ts +1 -2
  114. package/src/modes/utils/ui-helpers.ts +34 -32
  115. package/src/patch/edit-tool.ts +742 -0
  116. package/src/patch/index.ts +32 -898
  117. package/src/patch/schemas.ts +208 -0
  118. package/src/patch/shared.ts +83 -151
  119. package/src/prompts/agents/explore.md +22 -37
  120. package/src/prompts/agents/frontmatter.md +1 -1
  121. package/src/prompts/agents/init.md +2 -2
  122. package/src/prompts/agents/librarian.md +30 -21
  123. package/src/prompts/agents/oracle.md +9 -2
  124. package/src/prompts/agents/reviewer.md +15 -49
  125. package/src/prompts/agents/task.md +17 -9
  126. package/src/prompts/compaction/branch-summary-context.md +1 -1
  127. package/src/prompts/compaction/branch-summary-preamble.md +1 -1
  128. package/src/prompts/compaction/branch-summary.md +4 -1
  129. package/src/prompts/compaction/compaction-short-summary.md +1 -1
  130. package/src/prompts/compaction/compaction-summary-context.md +1 -1
  131. package/src/prompts/compaction/compaction-summary.md +4 -1
  132. package/src/prompts/compaction/compaction-turn-prefix.md +1 -1
  133. package/src/prompts/compaction/compaction-update-summary.md +1 -1
  134. package/src/prompts/memories/consolidation.md +1 -1
  135. package/src/prompts/memories/read_path.md +1 -1
  136. package/src/prompts/memories/stage_one_input.md +1 -1
  137. package/src/prompts/memories/stage_one_system.md +1 -1
  138. package/src/prompts/review-request.md +1 -1
  139. package/src/prompts/system/agent-creation-architect.md +1 -1
  140. package/src/prompts/system/agent-creation-user.md +1 -1
  141. package/src/prompts/system/custom-system-prompt.md +1 -1
  142. package/src/prompts/system/file-operations.md +1 -1
  143. package/src/prompts/system/subagent-system-prompt.md +2 -2
  144. package/src/prompts/system/summarization-system.md +1 -1
  145. package/src/prompts/system/system-prompt.md +163 -178
  146. package/src/prompts/system/title-system.md +1 -1
  147. package/src/prompts/system/ttsr-interrupt.md +1 -1
  148. package/src/prompts/system/verification-reminder.md +6 -0
  149. package/src/prompts/system/web-search.md +1 -1
  150. package/src/sdk.ts +0 -9
  151. package/src/session/agent-session.ts +244 -1459
  152. package/src/session/auth-storage.ts +5 -0
  153. package/src/session/model-controller.ts +406 -0
  154. package/src/session/retry-utils.ts +71 -0
  155. package/src/session/session-manager.ts +22 -186
  156. package/src/session/session-types.ts +312 -0
  157. package/src/session/stats.ts +387 -0
  158. package/src/session/streaming-edit.ts +258 -0
  159. package/src/session/ttsr.ts +213 -0
  160. package/src/slash-commands/builtin-registry.ts +0 -8
  161. package/src/ssh/connection-manager.ts +1 -0
  162. package/src/stt/recorder.ts +2 -2
  163. package/src/system-prompt.ts +1 -14
  164. package/src/task/agents.ts +7 -33
  165. package/src/task/executor.ts +50 -438
  166. package/src/task/index.ts +104 -71
  167. package/src/task/progress-tracker.ts +390 -0
  168. package/src/task/render.ts +371 -187
  169. package/src/task/subprocess-tool-registry.ts +1 -1
  170. package/src/task/types.ts +14 -47
  171. package/src/tools/ask.ts +31 -42
  172. package/src/tools/bash-interactive.ts +4 -47
  173. package/src/tools/bash-interceptor.ts +2 -2
  174. package/src/tools/bash-normalize.ts +1 -1
  175. package/src/tools/bash-skill-urls.ts +2 -2
  176. package/src/tools/bash.ts +87 -136
  177. package/src/tools/browser.ts +54 -84
  178. package/src/tools/create-tools.ts +186 -0
  179. package/src/tools/default-renderer.ts +104 -0
  180. package/src/tools/explore.ts +11 -10
  181. package/src/tools/fetch.ts +24 -114
  182. package/src/tools/find.ts +48 -132
  183. package/src/tools/gemini-image.ts +5 -15
  184. package/src/tools/github.ts +450 -0
  185. package/src/tools/grep.ts +43 -179
  186. package/src/tools/index.ts +35 -198
  187. package/src/tools/json-tree.ts +3 -3
  188. package/src/tools/librarian.ts +18 -18
  189. package/src/tools/list-limit.ts +2 -2
  190. package/src/tools/notebook.ts +35 -87
  191. package/src/tools/oracle.ts +25 -25
  192. package/src/tools/output-meta.ts +89 -4
  193. package/src/tools/output-utils.ts +2 -2
  194. package/src/tools/python.ts +86 -637
  195. package/src/tools/read.ts +36 -119
  196. package/src/tools/reviewer-tool.ts +19 -21
  197. package/src/tools/search-code.ts +128 -0
  198. package/src/tools/ssh.ts +67 -126
  199. package/src/tools/subagent-tool.ts +197 -123
  200. package/src/tools/todo-write.ts +15 -31
  201. package/src/tools/tool-errors.ts +0 -30
  202. package/src/tools/undo-edit.ts +30 -67
  203. package/src/tools/write.ts +78 -127
  204. package/src/tui/code-cell.ts +4 -4
  205. package/src/tui/file-list.ts +2 -2
  206. package/src/tui/output-block.ts +1 -1
  207. package/src/tui/status-line.ts +1 -1
  208. package/src/tui/tree-list.ts +2 -2
  209. package/src/tui/types.ts +1 -1
  210. package/src/tui/utils.ts +1 -1
  211. package/src/{tools → ui}/render-utils.ts +87 -126
  212. package/src/utils/external-editor.ts +4 -4
  213. package/src/utils/file-mentions.ts +1 -1
  214. package/src/utils/index.ts +30 -0
  215. package/src/utils/tools-manager.ts +9 -19
  216. package/src/web/github-client.ts +290 -0
  217. package/src/web/scrapers/github.ts +11 -62
  218. package/src/web/search/auth.ts +1 -3
  219. package/src/web/search/index.ts +85 -49
  220. package/src/web/search/provider.ts +11 -16
  221. package/src/web/search/providers/grep.ts +160 -0
  222. package/src/web/search/render.ts +48 -235
  223. package/src/web/search/types.ts +1 -1
  224. package/src/commands/commit.ts +0 -36
  225. package/src/commit/agentic/agent.ts +0 -311
  226. package/src/commit/agentic/fallback.ts +0 -96
  227. package/src/commit/agentic/index.ts +0 -359
  228. package/src/commit/agentic/prompts/analyze-file.md +0 -22
  229. package/src/commit/agentic/prompts/session-user.md +0 -25
  230. package/src/commit/agentic/prompts/split-confirm.md +0 -1
  231. package/src/commit/agentic/prompts/system.md +0 -38
  232. package/src/commit/agentic/state.ts +0 -69
  233. package/src/commit/agentic/tools/analyze-file.ts +0 -118
  234. package/src/commit/agentic/tools/git-file-diff.ts +0 -194
  235. package/src/commit/agentic/tools/git-hunk.ts +0 -50
  236. package/src/commit/agentic/tools/git-overview.ts +0 -84
  237. package/src/commit/agentic/tools/index.ts +0 -56
  238. package/src/commit/agentic/tools/propose-changelog.ts +0 -128
  239. package/src/commit/agentic/tools/propose-commit.ts +0 -154
  240. package/src/commit/agentic/tools/recent-commits.ts +0 -81
  241. package/src/commit/agentic/tools/split-commit.ts +0 -280
  242. package/src/commit/agentic/topo-sort.ts +0 -44
  243. package/src/commit/agentic/trivial.ts +0 -51
  244. package/src/commit/agentic/validation.ts +0 -200
  245. package/src/commit/analysis/conventional.ts +0 -165
  246. package/src/commit/analysis/index.ts +0 -4
  247. package/src/commit/analysis/scope.ts +0 -242
  248. package/src/commit/analysis/summary.ts +0 -112
  249. package/src/commit/analysis/validation.ts +0 -66
  250. package/src/commit/changelog/detect.ts +0 -37
  251. package/src/commit/changelog/generate.ts +0 -110
  252. package/src/commit/changelog/index.ts +0 -234
  253. package/src/commit/changelog/parse.ts +0 -44
  254. package/src/commit/cli.ts +0 -93
  255. package/src/commit/git/diff.ts +0 -148
  256. package/src/commit/git/errors.ts +0 -9
  257. package/src/commit/git/index.ts +0 -211
  258. package/src/commit/git/operations.ts +0 -54
  259. package/src/commit/index.ts +0 -5
  260. package/src/commit/map-reduce/index.ts +0 -64
  261. package/src/commit/map-reduce/map-phase.ts +0 -178
  262. package/src/commit/map-reduce/reduce-phase.ts +0 -145
  263. package/src/commit/map-reduce/utils.ts +0 -9
  264. package/src/commit/message.ts +0 -11
  265. package/src/commit/model-selection.ts +0 -69
  266. package/src/commit/pipeline.ts +0 -243
  267. package/src/commit/prompts/analysis-system.md +0 -148
  268. package/src/commit/prompts/analysis-user.md +0 -38
  269. package/src/commit/prompts/changelog-system.md +0 -50
  270. package/src/commit/prompts/changelog-user.md +0 -18
  271. package/src/commit/prompts/file-observer-system.md +0 -24
  272. package/src/commit/prompts/file-observer-user.md +0 -8
  273. package/src/commit/prompts/reduce-system.md +0 -50
  274. package/src/commit/prompts/reduce-user.md +0 -17
  275. package/src/commit/prompts/summary-retry.md +0 -3
  276. package/src/commit/prompts/summary-system.md +0 -38
  277. package/src/commit/prompts/summary-user.md +0 -13
  278. package/src/commit/prompts/types-description.md +0 -2
  279. package/src/commit/types.ts +0 -109
  280. package/src/commit/utils/exclusions.ts +0 -42
  281. package/src/mcp/render.ts +0 -123
  282. package/src/modes/components/agent-dashboard.ts +0 -1130
  283. package/src/modes/components/codemode-group.ts +0 -369
  284. package/src/modes/components/read-tool-group.ts +0 -119
  285. package/src/modes/components/visual-truncate.ts +0 -63
  286. package/src/prompts/system/subagent-user-prompt.md +0 -8
  287. package/src/prompts/tools/ask.md +0 -44
  288. package/src/prompts/tools/bash.md +0 -24
  289. package/src/prompts/tools/browser.md +0 -33
  290. package/src/prompts/tools/calculator.md +0 -12
  291. package/src/prompts/tools/explore.md +0 -29
  292. package/src/prompts/tools/fetch.md +0 -16
  293. package/src/prompts/tools/find.md +0 -18
  294. package/src/prompts/tools/gemini-image.md +0 -23
  295. package/src/prompts/tools/grep.md +0 -28
  296. package/src/prompts/tools/hashline.md +0 -232
  297. package/src/prompts/tools/librarian.md +0 -24
  298. package/src/prompts/tools/lsp.md +0 -28
  299. package/src/prompts/tools/oracle.md +0 -26
  300. package/src/prompts/tools/patch.md +0 -74
  301. package/src/prompts/tools/python.md +0 -66
  302. package/src/prompts/tools/read.md +0 -36
  303. package/src/prompts/tools/replace.md +0 -38
  304. package/src/prompts/tools/reviewer.md +0 -41
  305. package/src/prompts/tools/ssh.md +0 -51
  306. package/src/prompts/tools/task-summary.md +0 -28
  307. package/src/prompts/tools/task.md +0 -146
  308. package/src/prompts/tools/todo-write.md +0 -65
  309. package/src/prompts/tools/undo-edit.md +0 -7
  310. package/src/prompts/tools/web-search.md +0 -19
  311. package/src/prompts/tools/write.md +0 -18
  312. package/src/task/batch.ts +0 -102
  313. package/src/task/discovery.ts +0 -126
  314. package/src/task/parallel.ts +0 -84
  315. package/src/task/template.ts +0 -32
  316. package/src/tools/calculator.ts +0 -537
  317. package/src/tools/jtd-to-typescript.ts +0 -198
  318. package/src/tools/renderers.ts +0 -60
  319. package/src/tools/tool-result.ts +0 -86
  320. /package/src/{modes/theme → theme}/dark.json +0 -0
  321. /package/src/{modes/theme → theme}/defaults/dark-catppuccin.json +0 -0
  322. /package/src/{modes/theme → theme}/defaults/dark-dracula.json +0 -0
  323. /package/src/{modes/theme → theme}/defaults/dark-gruvbox.json +0 -0
  324. /package/src/{modes/theme → theme}/defaults/dark-solarized.json +0 -0
  325. /package/src/{modes/theme → theme}/defaults/dark-tokyo-night.json +0 -0
  326. /package/src/{modes/theme → theme}/defaults/index.ts +0 -0
  327. /package/src/{modes/theme → theme}/defaults/light-catppuccin.json +0 -0
  328. /package/src/{modes/theme → theme}/defaults/light-github.json +0 -0
  329. /package/src/{modes/theme → theme}/defaults/light-solarized.json +0 -0
  330. /package/src/{modes/theme → theme}/light.json +0 -0
  331. /package/src/{modes/theme → theme}/mermaid-cache.ts +0 -0
  332. /package/src/{modes/theme → theme}/theme-schema.json +0 -0
  333. /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
+ };