rird 1.0.200

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 (350) hide show
  1. package/AGENTS.md +27 -0
  2. package/Dockerfile +18 -0
  3. package/README.md +15 -0
  4. package/bin/opencode +336 -0
  5. package/bin/pty-wrapper.js +285 -0
  6. package/bunfig.toml +4 -0
  7. package/facebook_ads_library.png +0 -0
  8. package/nul`nif +0 -0
  9. package/package.json +111 -0
  10. package/parsers-config.ts +239 -0
  11. package/rird-1.0.199.tgz +0 -0
  12. package/script/build-windows.ts +54 -0
  13. package/script/build.ts +167 -0
  14. package/script/postinstall.mjs +544 -0
  15. package/script/publish-registries.ts +187 -0
  16. package/script/publish.ts +72 -0
  17. package/script/schema.ts +47 -0
  18. package/src/acp/README.md +164 -0
  19. package/src/acp/agent.ts +1063 -0
  20. package/src/acp/session.ts +101 -0
  21. package/src/acp/types.ts +22 -0
  22. package/src/agent/agent.ts +367 -0
  23. package/src/agent/generate.txt +75 -0
  24. package/src/agent/prompt/compaction.txt +12 -0
  25. package/src/agent/prompt/explore.txt +18 -0
  26. package/src/agent/prompt/summary.txt +10 -0
  27. package/src/agent/prompt/title.txt +36 -0
  28. package/src/auth/index.ts +70 -0
  29. package/src/bun/index.ts +114 -0
  30. package/src/bus/bus-event.ts +43 -0
  31. package/src/bus/global.ts +10 -0
  32. package/src/bus/index.ts +105 -0
  33. package/src/cli/bootstrap.ts +17 -0
  34. package/src/cli/cmd/acp.ts +88 -0
  35. package/src/cli/cmd/agent.ts +256 -0
  36. package/src/cli/cmd/auth.ts +391 -0
  37. package/src/cli/cmd/cmd.ts +7 -0
  38. package/src/cli/cmd/debug/config.ts +15 -0
  39. package/src/cli/cmd/debug/file.ts +91 -0
  40. package/src/cli/cmd/debug/index.ts +43 -0
  41. package/src/cli/cmd/debug/lsp.ts +48 -0
  42. package/src/cli/cmd/debug/ripgrep.ts +83 -0
  43. package/src/cli/cmd/debug/scrap.ts +15 -0
  44. package/src/cli/cmd/debug/skill.ts +15 -0
  45. package/src/cli/cmd/debug/snapshot.ts +48 -0
  46. package/src/cli/cmd/export.ts +88 -0
  47. package/src/cli/cmd/generate.ts +38 -0
  48. package/src/cli/cmd/github.ts +1400 -0
  49. package/src/cli/cmd/import.ts +98 -0
  50. package/src/cli/cmd/mcp.ts +654 -0
  51. package/src/cli/cmd/models.ts +77 -0
  52. package/src/cli/cmd/pr.ts +112 -0
  53. package/src/cli/cmd/run.ts +368 -0
  54. package/src/cli/cmd/serve.ts +31 -0
  55. package/src/cli/cmd/session.ts +106 -0
  56. package/src/cli/cmd/stats.ts +298 -0
  57. package/src/cli/cmd/tui/app.tsx +696 -0
  58. package/src/cli/cmd/tui/attach.ts +30 -0
  59. package/src/cli/cmd/tui/component/border.tsx +21 -0
  60. package/src/cli/cmd/tui/component/dialog-agent.tsx +31 -0
  61. package/src/cli/cmd/tui/component/dialog-command.tsx +124 -0
  62. package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
  63. package/src/cli/cmd/tui/component/dialog-model.tsx +245 -0
  64. package/src/cli/cmd/tui/component/dialog-provider.tsx +224 -0
  65. package/src/cli/cmd/tui/component/dialog-session-list.tsx +102 -0
  66. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
  67. package/src/cli/cmd/tui/component/dialog-stash.tsx +86 -0
  68. package/src/cli/cmd/tui/component/dialog-status.tsx +162 -0
  69. package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
  70. package/src/cli/cmd/tui/component/dialog-theme-list.tsx +50 -0
  71. package/src/cli/cmd/tui/component/did-you-know.tsx +85 -0
  72. package/src/cli/cmd/tui/component/logo.tsx +35 -0
  73. package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +574 -0
  74. package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
  75. package/src/cli/cmd/tui/component/prompt/index.tsx +1090 -0
  76. package/src/cli/cmd/tui/component/prompt/stash.tsx +101 -0
  77. package/src/cli/cmd/tui/component/tips.ts +27 -0
  78. package/src/cli/cmd/tui/component/todo-item.tsx +32 -0
  79. package/src/cli/cmd/tui/context/args.tsx +14 -0
  80. package/src/cli/cmd/tui/context/directory.ts +13 -0
  81. package/src/cli/cmd/tui/context/exit.tsx +23 -0
  82. package/src/cli/cmd/tui/context/helper.tsx +25 -0
  83. package/src/cli/cmd/tui/context/keybind.tsx +101 -0
  84. package/src/cli/cmd/tui/context/kv.tsx +49 -0
  85. package/src/cli/cmd/tui/context/local.tsx +354 -0
  86. package/src/cli/cmd/tui/context/prompt.tsx +18 -0
  87. package/src/cli/cmd/tui/context/route.tsx +46 -0
  88. package/src/cli/cmd/tui/context/sdk.tsx +74 -0
  89. package/src/cli/cmd/tui/context/sync.tsx +372 -0
  90. package/src/cli/cmd/tui/context/theme/aura.json +69 -0
  91. package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
  92. package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +233 -0
  93. package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +233 -0
  94. package/src/cli/cmd/tui/context/theme/catppuccin.json +112 -0
  95. package/src/cli/cmd/tui/context/theme/cobalt2.json +228 -0
  96. package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
  97. package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
  98. package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
  99. package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
  100. package/src/cli/cmd/tui/context/theme/github.json +233 -0
  101. package/src/cli/cmd/tui/context/theme/gruvbox.json +95 -0
  102. package/src/cli/cmd/tui/context/theme/kanagawa.json +77 -0
  103. package/src/cli/cmd/tui/context/theme/lucent-orng.json +227 -0
  104. package/src/cli/cmd/tui/context/theme/material.json +235 -0
  105. package/src/cli/cmd/tui/context/theme/matrix.json +77 -0
  106. package/src/cli/cmd/tui/context/theme/mercury.json +252 -0
  107. package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
  108. package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
  109. package/src/cli/cmd/tui/context/theme/nord.json +223 -0
  110. package/src/cli/cmd/tui/context/theme/one-dark.json +84 -0
  111. package/src/cli/cmd/tui/context/theme/orng.json +245 -0
  112. package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
  113. package/src/cli/cmd/tui/context/theme/rird.json +245 -0
  114. package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
  115. package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
  116. package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
  117. package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
  118. package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
  119. package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
  120. package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
  121. package/src/cli/cmd/tui/context/theme.tsx +1109 -0
  122. package/src/cli/cmd/tui/event.ts +40 -0
  123. package/src/cli/cmd/tui/routes/home.tsx +138 -0
  124. package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +64 -0
  125. package/src/cli/cmd/tui/routes/session/dialog-message.tsx +109 -0
  126. package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +26 -0
  127. package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
  128. package/src/cli/cmd/tui/routes/session/footer.tsx +88 -0
  129. package/src/cli/cmd/tui/routes/session/header.tsx +125 -0
  130. package/src/cli/cmd/tui/routes/session/index.tsx +1864 -0
  131. package/src/cli/cmd/tui/routes/session/sidebar.tsx +318 -0
  132. package/src/cli/cmd/tui/spawn.ts +60 -0
  133. package/src/cli/cmd/tui/thread.ts +142 -0
  134. package/src/cli/cmd/tui/ui/dialog-alert.tsx +57 -0
  135. package/src/cli/cmd/tui/ui/dialog-confirm.tsx +83 -0
  136. package/src/cli/cmd/tui/ui/dialog-help.tsx +38 -0
  137. package/src/cli/cmd/tui/ui/dialog-prompt.tsx +77 -0
  138. package/src/cli/cmd/tui/ui/dialog-select.tsx +332 -0
  139. package/src/cli/cmd/tui/ui/dialog.tsx +170 -0
  140. package/src/cli/cmd/tui/ui/spinner.ts +368 -0
  141. package/src/cli/cmd/tui/ui/toast.tsx +100 -0
  142. package/src/cli/cmd/tui/util/clipboard.ts +127 -0
  143. package/src/cli/cmd/tui/util/editor.ts +32 -0
  144. package/src/cli/cmd/tui/util/terminal.ts +114 -0
  145. package/src/cli/cmd/tui/worker.ts +63 -0
  146. package/src/cli/cmd/uninstall.ts +344 -0
  147. package/src/cli/cmd/upgrade.ts +100 -0
  148. package/src/cli/cmd/web.ts +84 -0
  149. package/src/cli/error.ts +56 -0
  150. package/src/cli/ui.ts +84 -0
  151. package/src/cli/upgrade.ts +25 -0
  152. package/src/command/index.ts +80 -0
  153. package/src/command/template/initialize.txt +10 -0
  154. package/src/command/template/review.txt +97 -0
  155. package/src/config/config.ts +995 -0
  156. package/src/config/markdown.ts +41 -0
  157. package/src/env/index.ts +26 -0
  158. package/src/file/ignore.ts +83 -0
  159. package/src/file/index.ts +328 -0
  160. package/src/file/ripgrep.ts +393 -0
  161. package/src/file/time.ts +64 -0
  162. package/src/file/watcher.ts +103 -0
  163. package/src/flag/flag.ts +46 -0
  164. package/src/format/formatter.ts +315 -0
  165. package/src/format/index.ts +137 -0
  166. package/src/global/index.ts +52 -0
  167. package/src/id/id.ts +73 -0
  168. package/src/ide/index.ts +76 -0
  169. package/src/index.ts +240 -0
  170. package/src/installation/index.ts +239 -0
  171. package/src/lsp/client.ts +229 -0
  172. package/src/lsp/index.ts +485 -0
  173. package/src/lsp/language.ts +116 -0
  174. package/src/lsp/server.ts +1895 -0
  175. package/src/mcp/auth.ts +135 -0
  176. package/src/mcp/index.ts +690 -0
  177. package/src/mcp/oauth-callback.ts +200 -0
  178. package/src/mcp/oauth-provider.ts +154 -0
  179. package/src/patch/index.ts +622 -0
  180. package/src/permission/index.ts +199 -0
  181. package/src/plugin/index.ts +91 -0
  182. package/src/project/bootstrap.ts +31 -0
  183. package/src/project/instance.ts +78 -0
  184. package/src/project/project.ts +221 -0
  185. package/src/project/state.ts +65 -0
  186. package/src/project/vcs.ts +76 -0
  187. package/src/provider/auth.ts +143 -0
  188. package/src/provider/models-macro.ts +11 -0
  189. package/src/provider/models.ts +106 -0
  190. package/src/provider/provider.ts +1071 -0
  191. package/src/provider/sdk/openai-compatible/src/README.md +5 -0
  192. package/src/provider/sdk/openai-compatible/src/index.ts +2 -0
  193. package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +100 -0
  194. package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +303 -0
  195. package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +22 -0
  196. package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +18 -0
  197. package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +22 -0
  198. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +207 -0
  199. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +1713 -0
  200. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +177 -0
  201. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +1 -0
  202. package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +88 -0
  203. package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +128 -0
  204. package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +115 -0
  205. package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +65 -0
  206. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +104 -0
  207. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +103 -0
  208. package/src/provider/transform.ts +455 -0
  209. package/src/pty/index.ts +231 -0
  210. package/src/security/guardrails.test.ts +341 -0
  211. package/src/security/guardrails.ts +558 -0
  212. package/src/security/index.ts +19 -0
  213. package/src/server/error.ts +36 -0
  214. package/src/server/project.ts +79 -0
  215. package/src/server/server.ts +2642 -0
  216. package/src/server/tui.ts +71 -0
  217. package/src/session/compaction.ts +223 -0
  218. package/src/session/index.ts +461 -0
  219. package/src/session/llm.ts +201 -0
  220. package/src/session/message-v2.ts +690 -0
  221. package/src/session/message.ts +189 -0
  222. package/src/session/processor.ts +409 -0
  223. package/src/session/prompt/act-switch.txt +5 -0
  224. package/src/session/prompt/anthropic-20250930.txt +166 -0
  225. package/src/session/prompt/anthropic.txt +85 -0
  226. package/src/session/prompt/anthropic_spoof.txt +1 -0
  227. package/src/session/prompt/beast.txt +103 -0
  228. package/src/session/prompt/codex.txt +304 -0
  229. package/src/session/prompt/copilot-gpt-5.txt +138 -0
  230. package/src/session/prompt/gemini.txt +85 -0
  231. package/src/session/prompt/max-steps.txt +16 -0
  232. package/src/session/prompt/plan-reminder-anthropic.txt +35 -0
  233. package/src/session/prompt/plan.txt +24 -0
  234. package/src/session/prompt/polaris.txt +84 -0
  235. package/src/session/prompt/qwen.txt +106 -0
  236. package/src/session/prompt.ts +1509 -0
  237. package/src/session/retry.ts +86 -0
  238. package/src/session/revert.ts +108 -0
  239. package/src/session/sensitive-filter.test.ts +327 -0
  240. package/src/session/sensitive-filter.ts +466 -0
  241. package/src/session/status.ts +76 -0
  242. package/src/session/summary.ts +194 -0
  243. package/src/session/system.ts +120 -0
  244. package/src/session/todo.ts +37 -0
  245. package/src/share/share-next.ts +194 -0
  246. package/src/share/share.ts +87 -0
  247. package/src/shell/shell.ts +67 -0
  248. package/src/skill/index.ts +1 -0
  249. package/src/skill/skill.ts +83 -0
  250. package/src/snapshot/index.ts +197 -0
  251. package/src/storage/storage.ts +226 -0
  252. package/src/tests/agent.test.ts +308 -0
  253. package/src/tests/build-guards.test.ts +267 -0
  254. package/src/tests/config.test.ts +664 -0
  255. package/src/tests/tool-registry.test.ts +589 -0
  256. package/src/tool/bash.ts +317 -0
  257. package/src/tool/bash.txt +158 -0
  258. package/src/tool/batch.ts +175 -0
  259. package/src/tool/batch.txt +24 -0
  260. package/src/tool/codesearch.ts +168 -0
  261. package/src/tool/codesearch.txt +12 -0
  262. package/src/tool/edit.ts +675 -0
  263. package/src/tool/edit.txt +10 -0
  264. package/src/tool/glob.ts +65 -0
  265. package/src/tool/glob.txt +6 -0
  266. package/src/tool/grep.ts +121 -0
  267. package/src/tool/grep.txt +8 -0
  268. package/src/tool/invalid.ts +17 -0
  269. package/src/tool/ls.ts +110 -0
  270. package/src/tool/ls.txt +1 -0
  271. package/src/tool/lsp-diagnostics.ts +26 -0
  272. package/src/tool/lsp-diagnostics.txt +1 -0
  273. package/src/tool/lsp-hover.ts +31 -0
  274. package/src/tool/lsp-hover.txt +1 -0
  275. package/src/tool/lsp.ts +87 -0
  276. package/src/tool/lsp.txt +19 -0
  277. package/src/tool/multiedit.ts +46 -0
  278. package/src/tool/multiedit.txt +41 -0
  279. package/src/tool/patch.ts +233 -0
  280. package/src/tool/patch.txt +1 -0
  281. package/src/tool/read.ts +219 -0
  282. package/src/tool/read.txt +12 -0
  283. package/src/tool/registry.ts +162 -0
  284. package/src/tool/skill.ts +100 -0
  285. package/src/tool/task.ts +136 -0
  286. package/src/tool/task.txt +51 -0
  287. package/src/tool/todo.ts +39 -0
  288. package/src/tool/todoread.txt +14 -0
  289. package/src/tool/todowrite.txt +167 -0
  290. package/src/tool/tool.ts +71 -0
  291. package/src/tool/webfetch.ts +198 -0
  292. package/src/tool/webfetch.txt +13 -0
  293. package/src/tool/websearch.ts +180 -0
  294. package/src/tool/websearch.txt +11 -0
  295. package/src/tool/write.ts +110 -0
  296. package/src/tool/write.txt +8 -0
  297. package/src/util/archive.ts +16 -0
  298. package/src/util/color.ts +19 -0
  299. package/src/util/context.ts +25 -0
  300. package/src/util/defer.ts +12 -0
  301. package/src/util/eventloop.ts +20 -0
  302. package/src/util/filesystem.ts +83 -0
  303. package/src/util/fn.ts +11 -0
  304. package/src/util/iife.ts +3 -0
  305. package/src/util/keybind.ts +102 -0
  306. package/src/util/lazy.ts +11 -0
  307. package/src/util/license.ts +325 -0
  308. package/src/util/locale.ts +81 -0
  309. package/src/util/lock.ts +98 -0
  310. package/src/util/log.ts +180 -0
  311. package/src/util/queue.ts +32 -0
  312. package/src/util/rpc.ts +42 -0
  313. package/src/util/scrap.ts +10 -0
  314. package/src/util/signal.ts +12 -0
  315. package/src/util/timeout.ts +14 -0
  316. package/src/util/token.ts +7 -0
  317. package/src/util/wildcard.ts +54 -0
  318. package/sst-env.d.ts +9 -0
  319. package/test/agent/agent.test.ts +146 -0
  320. package/test/bun.test.ts +53 -0
  321. package/test/cli/github-remote.test.ts +80 -0
  322. package/test/config/agent-color.test.ts +66 -0
  323. package/test/config/config.test.ts +535 -0
  324. package/test/config/markdown.test.ts +89 -0
  325. package/test/file/ignore.test.ts +10 -0
  326. package/test/fixture/fixture.ts +36 -0
  327. package/test/fixture/lsp/fake-lsp-server.js +77 -0
  328. package/test/ide/ide.test.ts +82 -0
  329. package/test/keybind.test.ts +421 -0
  330. package/test/lsp/client.test.ts +95 -0
  331. package/test/mcp/headers.test.ts +153 -0
  332. package/test/patch/patch.test.ts +348 -0
  333. package/test/preload.ts +57 -0
  334. package/test/project/project.test.ts +72 -0
  335. package/test/provider/provider.test.ts +1809 -0
  336. package/test/provider/transform.test.ts +411 -0
  337. package/test/session/retry.test.ts +111 -0
  338. package/test/session/session.test.ts +71 -0
  339. package/test/skill/skill.test.ts +131 -0
  340. package/test/snapshot/snapshot.test.ts +939 -0
  341. package/test/tool/__snapshots__/tool.test.ts.snap +9 -0
  342. package/test/tool/bash.test.ts +434 -0
  343. package/test/tool/grep.test.ts +108 -0
  344. package/test/tool/patch.test.ts +259 -0
  345. package/test/tool/read.test.ts +42 -0
  346. package/test/util/iife.test.ts +36 -0
  347. package/test/util/lazy.test.ts +50 -0
  348. package/test/util/timeout.test.ts +21 -0
  349. package/test/util/wildcard.test.ts +55 -0
  350. package/tsconfig.json +16 -0
@@ -0,0 +1,589 @@
1
+ import { describe, test, expect } from "bun:test"
2
+ import z from "zod"
3
+ import { Tool } from "../tool/tool"
4
+ import { BashTool } from "../tool/bash"
5
+ import { ReadTool } from "../tool/read"
6
+ import { WriteTool } from "../tool/write"
7
+ import { EditTool } from "../tool/edit"
8
+ import { GlobTool } from "../tool/glob"
9
+ import { GrepTool } from "../tool/grep"
10
+ import { ListTool } from "../tool/ls"
11
+ import { TaskTool } from "../tool/task"
12
+ import { TodoWriteTool, TodoReadTool } from "../tool/todo"
13
+ import { WebFetchTool } from "../tool/webfetch"
14
+ import { BatchTool } from "../tool/batch"
15
+ import { WebSearchTool } from "../tool/websearch"
16
+ import { CodeSearchTool } from "../tool/codesearch"
17
+ import { SkillTool } from "../tool/skill"
18
+ import { LspTool } from "../tool/lsp"
19
+
20
+ // Core tools that must always be present (using actual tool IDs)
21
+ const REQUIRED_TOOL_IDS = [
22
+ "bash",
23
+ "read",
24
+ "write",
25
+ "edit",
26
+ "glob",
27
+ "grep",
28
+ "list",
29
+ "task",
30
+ "todowrite",
31
+ "todoread",
32
+ ]
33
+
34
+ // All tools in the registry
35
+ const ALL_TOOLS = [
36
+ BashTool,
37
+ ReadTool,
38
+ WriteTool,
39
+ EditTool,
40
+ GlobTool,
41
+ GrepTool,
42
+ ListTool,
43
+ TaskTool,
44
+ TodoWriteTool,
45
+ TodoReadTool,
46
+ WebFetchTool,
47
+ BatchTool,
48
+ WebSearchTool,
49
+ CodeSearchTool,
50
+ SkillTool,
51
+ LspTool,
52
+ ]
53
+
54
+ describe("Tool definitions", () => {
55
+ test("all required tools are present", () => {
56
+ const toolIds = ALL_TOOLS.map((t) => t.id)
57
+
58
+ for (const required of REQUIRED_TOOL_IDS) {
59
+ expect(toolIds).toContain(required)
60
+ }
61
+ })
62
+
63
+ test("all tool IDs are unique", () => {
64
+ const toolIds = ALL_TOOLS.map((t) => t.id)
65
+ const uniqueIds = new Set(toolIds)
66
+
67
+ expect(uniqueIds.size).toBe(toolIds.length)
68
+ })
69
+
70
+ test("all tools have string IDs", () => {
71
+ for (const tool of ALL_TOOLS) {
72
+ expect(typeof tool.id).toBe("string")
73
+ expect(tool.id.length).toBeGreaterThan(0)
74
+ }
75
+ })
76
+
77
+ test("all tools have init function", () => {
78
+ for (const tool of ALL_TOOLS) {
79
+ expect(typeof tool.init).toBe("function")
80
+ }
81
+ })
82
+ })
83
+
84
+ describe("Tool ID verification", () => {
85
+ test("BashTool has correct id", () => {
86
+ expect(BashTool.id).toBe("bash")
87
+ })
88
+
89
+ test("ReadTool has correct id", () => {
90
+ expect(ReadTool.id).toBe("read")
91
+ })
92
+
93
+ test("WriteTool has correct id", () => {
94
+ expect(WriteTool.id).toBe("write")
95
+ })
96
+
97
+ test("EditTool has correct id", () => {
98
+ expect(EditTool.id).toBe("edit")
99
+ })
100
+
101
+ test("GlobTool has correct id", () => {
102
+ expect(GlobTool.id).toBe("glob")
103
+ })
104
+
105
+ test("GrepTool has correct id", () => {
106
+ expect(GrepTool.id).toBe("grep")
107
+ })
108
+
109
+ test("ListTool has correct id", () => {
110
+ expect(ListTool.id).toBe("list")
111
+ })
112
+
113
+ test("TaskTool has correct id", () => {
114
+ expect(TaskTool.id).toBe("task")
115
+ })
116
+
117
+ test("TodoWriteTool has correct id", () => {
118
+ expect(TodoWriteTool.id).toBe("todowrite")
119
+ })
120
+
121
+ test("TodoReadTool has correct id", () => {
122
+ expect(TodoReadTool.id).toBe("todoread")
123
+ })
124
+
125
+ test("WebFetchTool has correct id", () => {
126
+ expect(WebFetchTool.id).toBe("webfetch")
127
+ })
128
+
129
+ test("BatchTool has correct id", () => {
130
+ expect(BatchTool.id).toBe("batch")
131
+ })
132
+
133
+ test("WebSearchTool has correct id", () => {
134
+ expect(WebSearchTool.id).toBe("websearch")
135
+ })
136
+
137
+ test("CodeSearchTool has correct id", () => {
138
+ expect(CodeSearchTool.id).toBe("codesearch")
139
+ })
140
+
141
+ test("SkillTool has correct id", () => {
142
+ expect(SkillTool.id).toBe("skill")
143
+ })
144
+
145
+ test("LspTool has correct id", () => {
146
+ expect(LspTool.id).toBe("lsp")
147
+ })
148
+ })
149
+
150
+ describe("Tool.Info structure", () => {
151
+ test("Tool.Info has id property of type string", () => {
152
+ const tool = Tool.define("test-id", {
153
+ description: "Test",
154
+ parameters: z.object({}),
155
+ execute: async () => ({ title: "", output: "", metadata: {} }),
156
+ })
157
+
158
+ expect(typeof tool.id).toBe("string")
159
+ expect(tool.id).toBe("test-id")
160
+ })
161
+
162
+ test("Tool.Info has init method", () => {
163
+ const tool = Tool.define("test-init", {
164
+ description: "Test",
165
+ parameters: z.object({}),
166
+ execute: async () => ({ title: "", output: "", metadata: {} }),
167
+ })
168
+
169
+ expect(typeof tool.init).toBe("function")
170
+ })
171
+ })
172
+
173
+ describe("Tool.define helper", () => {
174
+ test("creates tool with correct id", () => {
175
+ const tool = Tool.define("test-tool", {
176
+ description: "Test tool",
177
+ parameters: z.object({
178
+ input: z.string(),
179
+ }),
180
+ execute: async () => ({
181
+ title: "Test",
182
+ output: "output",
183
+ metadata: {},
184
+ }),
185
+ })
186
+
187
+ expect(tool.id).toBe("test-tool")
188
+ })
189
+
190
+ test("created tool has init function", () => {
191
+ const tool = Tool.define("test-tool-2", {
192
+ description: "Test tool 2",
193
+ parameters: z.object({}),
194
+ execute: async () => ({
195
+ title: "Test",
196
+ output: "output",
197
+ metadata: {},
198
+ }),
199
+ })
200
+
201
+ expect(typeof tool.init).toBe("function")
202
+ })
203
+
204
+ test("init returns description and parameters", async () => {
205
+ const tool = Tool.define("test-tool-3", {
206
+ description: "My description",
207
+ parameters: z.object({
208
+ foo: z.string(),
209
+ }),
210
+ execute: async () => ({
211
+ title: "Test",
212
+ output: "output",
213
+ metadata: {},
214
+ }),
215
+ })
216
+
217
+ const toolInfo = await tool.init()
218
+
219
+ expect(toolInfo.description).toBe("My description")
220
+ expect(toolInfo.parameters).toBeDefined()
221
+ })
222
+
223
+ test("init returns execute function", async () => {
224
+ const tool = Tool.define("test-exec", {
225
+ description: "Test",
226
+ parameters: z.object({}),
227
+ execute: async () => ({
228
+ title: "Test",
229
+ output: "output",
230
+ metadata: {},
231
+ }),
232
+ })
233
+
234
+ const toolInfo = await tool.init()
235
+ expect(typeof toolInfo.execute).toBe("function")
236
+ })
237
+
238
+ test("tool validates parameters on execute - rejects invalid args", async () => {
239
+ const tool = Tool.define("validation-test", {
240
+ description: "Validation test",
241
+ parameters: z.object({
242
+ required: z.string(),
243
+ }),
244
+ execute: async (args) => ({
245
+ title: "Test",
246
+ output: args.required,
247
+ metadata: {},
248
+ }),
249
+ })
250
+
251
+ const toolInfo = await tool.init()
252
+
253
+ const ctx = {
254
+ sessionID: "test",
255
+ messageID: "msg",
256
+ agent: "act",
257
+ abort: AbortSignal.any([]),
258
+ metadata: () => {},
259
+ }
260
+
261
+ // Invalid args should throw
262
+ let threw = false
263
+ try {
264
+ await toolInfo.execute({} as any, ctx)
265
+ } catch (e) {
266
+ threw = true
267
+ expect((e as Error).message).toContain("validation-test")
268
+ }
269
+ expect(threw).toBe(true)
270
+ })
271
+
272
+ test("tool accepts valid parameters", async () => {
273
+ const tool = Tool.define("valid-test", {
274
+ description: "Valid test",
275
+ parameters: z.object({
276
+ input: z.string(),
277
+ }),
278
+ execute: async (args) => ({
279
+ title: "Test",
280
+ output: args.input,
281
+ metadata: { echo: args.input },
282
+ }),
283
+ })
284
+
285
+ const toolInfo = await tool.init()
286
+
287
+ const ctx = {
288
+ sessionID: "test",
289
+ messageID: "msg",
290
+ agent: "act",
291
+ abort: AbortSignal.any([]),
292
+ metadata: () => {},
293
+ }
294
+
295
+ const result = await toolInfo.execute({ input: "hello" }, ctx)
296
+ expect(result.output).toBe("hello")
297
+ expect(result.metadata.echo).toBe("hello")
298
+ })
299
+ })
300
+
301
+ describe("Tool parameters schema structure", () => {
302
+ test("Tool.define creates ZodObject parameters", async () => {
303
+ const tool = Tool.define("zod-test", {
304
+ description: "Test",
305
+ parameters: z.object({
306
+ field1: z.string(),
307
+ field2: z.number().optional(),
308
+ }),
309
+ execute: async () => ({ title: "", output: "", metadata: {} }),
310
+ })
311
+
312
+ const toolInfo = await tool.init()
313
+ expect(toolInfo.parameters instanceof z.ZodType).toBe(true)
314
+ })
315
+
316
+ test("parameters can have descriptions", async () => {
317
+ const tool = Tool.define("desc-test", {
318
+ description: "Test",
319
+ parameters: z.object({
320
+ path: z.string().describe("The file path"),
321
+ content: z.string().describe("The file content"),
322
+ }),
323
+ execute: async () => ({ title: "", output: "", metadata: {} }),
324
+ })
325
+
326
+ const toolInfo = await tool.init()
327
+ const shape = (toolInfo.parameters as z.ZodObject<any>).shape
328
+
329
+ expect(shape.path).toBeDefined()
330
+ expect(shape.content).toBeDefined()
331
+ })
332
+
333
+ test("parameters can have optional fields", async () => {
334
+ const tool = Tool.define("optional-test", {
335
+ description: "Test",
336
+ parameters: z.object({
337
+ required: z.string(),
338
+ optional: z.number().optional(),
339
+ }),
340
+ execute: async (args) => ({
341
+ title: "",
342
+ output: args.required,
343
+ metadata: { hasOptional: args.optional !== undefined },
344
+ }),
345
+ })
346
+
347
+ const toolInfo = await tool.init()
348
+
349
+ const ctx = {
350
+ sessionID: "test",
351
+ messageID: "msg",
352
+ agent: "act",
353
+ abort: AbortSignal.any([]),
354
+ metadata: () => {},
355
+ }
356
+
357
+ // Works without optional field
358
+ const result1 = await toolInfo.execute({ required: "test" }, ctx)
359
+ expect(result1.metadata.hasOptional).toBe(false)
360
+
361
+ // Works with optional field
362
+ const result2 = await toolInfo.execute({ required: "test", optional: 42 }, ctx)
363
+ expect(result2.metadata.hasOptional).toBe(true)
364
+ })
365
+ })
366
+
367
+ describe("Tool execution result structure", () => {
368
+ test("execute returns title", async () => {
369
+ const tool = Tool.define("title-test", {
370
+ description: "Test",
371
+ parameters: z.object({}),
372
+ execute: async () => ({
373
+ title: "My Title",
374
+ output: "",
375
+ metadata: {},
376
+ }),
377
+ })
378
+
379
+ const toolInfo = await tool.init()
380
+ const ctx = {
381
+ sessionID: "test",
382
+ messageID: "msg",
383
+ agent: "act",
384
+ abort: AbortSignal.any([]),
385
+ metadata: () => {},
386
+ }
387
+
388
+ const result = await toolInfo.execute({}, ctx)
389
+ expect(result.title).toBe("My Title")
390
+ })
391
+
392
+ test("execute returns output", async () => {
393
+ const tool = Tool.define("output-test", {
394
+ description: "Test",
395
+ parameters: z.object({}),
396
+ execute: async () => ({
397
+ title: "",
398
+ output: "This is the output",
399
+ metadata: {},
400
+ }),
401
+ })
402
+
403
+ const toolInfo = await tool.init()
404
+ const ctx = {
405
+ sessionID: "test",
406
+ messageID: "msg",
407
+ agent: "act",
408
+ abort: AbortSignal.any([]),
409
+ metadata: () => {},
410
+ }
411
+
412
+ const result = await toolInfo.execute({}, ctx)
413
+ expect(result.output).toBe("This is the output")
414
+ })
415
+
416
+ test("execute returns metadata", async () => {
417
+ const tool = Tool.define("metadata-test", {
418
+ description: "Test",
419
+ parameters: z.object({}),
420
+ execute: async () => ({
421
+ title: "",
422
+ output: "",
423
+ metadata: {
424
+ custom: "value",
425
+ count: 42,
426
+ },
427
+ }),
428
+ })
429
+
430
+ const toolInfo = await tool.init()
431
+ const ctx = {
432
+ sessionID: "test",
433
+ messageID: "msg",
434
+ agent: "act",
435
+ abort: AbortSignal.any([]),
436
+ metadata: () => {},
437
+ }
438
+
439
+ const result = await toolInfo.execute({}, ctx)
440
+ expect(result.metadata.custom).toBe("value")
441
+ expect(result.metadata.count).toBe(42)
442
+ })
443
+
444
+ test("execute can return attachments", async () => {
445
+ const tool = Tool.define("attach-test", {
446
+ description: "Test",
447
+ parameters: z.object({}),
448
+ execute: async () => ({
449
+ title: "",
450
+ output: "",
451
+ metadata: {},
452
+ attachments: [
453
+ {
454
+ id: "part1",
455
+ sessionID: "test",
456
+ messageID: "msg",
457
+ type: "file" as const,
458
+ mime: "image/png",
459
+ url: "data:image/png;base64,abc",
460
+ },
461
+ ],
462
+ }),
463
+ })
464
+
465
+ const toolInfo = await tool.init()
466
+ const ctx = {
467
+ sessionID: "test",
468
+ messageID: "msg",
469
+ agent: "act",
470
+ abort: AbortSignal.any([]),
471
+ metadata: () => {},
472
+ }
473
+
474
+ const result = await toolInfo.execute({}, ctx)
475
+ expect(result.attachments).toBeDefined()
476
+ expect(result.attachments?.length).toBe(1)
477
+ expect(result.attachments?.[0].type).toBe("file")
478
+ })
479
+ })
480
+
481
+ describe("Tool context structure", () => {
482
+ test("context has required fields", async () => {
483
+ let receivedCtx: any = null
484
+
485
+ const tool = Tool.define("ctx-test", {
486
+ description: "Test",
487
+ parameters: z.object({}),
488
+ execute: async (_args, ctx) => {
489
+ receivedCtx = ctx
490
+ return { title: "", output: "", metadata: {} }
491
+ },
492
+ })
493
+
494
+ const toolInfo = await tool.init()
495
+ const ctx = {
496
+ sessionID: "session123",
497
+ messageID: "msg456",
498
+ agent: "plan",
499
+ abort: AbortSignal.any([]),
500
+ callID: "call789",
501
+ metadata: () => {},
502
+ }
503
+
504
+ await toolInfo.execute({}, ctx)
505
+
506
+ expect(receivedCtx.sessionID).toBe("session123")
507
+ expect(receivedCtx.messageID).toBe("msg456")
508
+ expect(receivedCtx.agent).toBe("plan")
509
+ expect(receivedCtx.callID).toBe("call789")
510
+ expect(receivedCtx.abort).toBeDefined()
511
+ expect(typeof receivedCtx.metadata).toBe("function")
512
+ })
513
+
514
+ test("context extra field is optional", async () => {
515
+ let receivedCtx: any = null
516
+
517
+ const tool = Tool.define("extra-test", {
518
+ description: "Test",
519
+ parameters: z.object({}),
520
+ execute: async (_args, ctx) => {
521
+ receivedCtx = ctx
522
+ return { title: "", output: "", metadata: {} }
523
+ },
524
+ })
525
+
526
+ const toolInfo = await tool.init()
527
+
528
+ // Without extra
529
+ const ctx1 = {
530
+ sessionID: "test",
531
+ messageID: "msg",
532
+ agent: "act",
533
+ abort: AbortSignal.any([]),
534
+ metadata: () => {},
535
+ }
536
+
537
+ await toolInfo.execute({}, ctx1)
538
+ expect(receivedCtx.extra).toBeUndefined()
539
+
540
+ // With extra
541
+ const ctx2 = {
542
+ sessionID: "test",
543
+ messageID: "msg",
544
+ agent: "act",
545
+ abort: AbortSignal.any([]),
546
+ metadata: () => {},
547
+ extra: { bypassCwdCheck: true },
548
+ }
549
+
550
+ await toolInfo.execute({}, ctx2)
551
+ expect(receivedCtx.extra).toBeDefined()
552
+ expect(receivedCtx.extra.bypassCwdCheck).toBe(true)
553
+ })
554
+ })
555
+
556
+ describe("Tool formatValidationError", () => {
557
+ test("custom validation error formatter is used", async () => {
558
+ const tool = Tool.define("format-error-test", {
559
+ description: "Test",
560
+ parameters: z.object({
561
+ required: z.string(),
562
+ }),
563
+ execute: async () => ({ title: "", output: "", metadata: {} }),
564
+ formatValidationError: (error) => {
565
+ // Access issues array which exists on ZodError
566
+ return `Custom error: ${error.issues.length} validation issues`
567
+ },
568
+ })
569
+
570
+ const toolInfo = await tool.init()
571
+ const ctx = {
572
+ sessionID: "test",
573
+ messageID: "msg",
574
+ agent: "act",
575
+ abort: AbortSignal.any([]),
576
+ metadata: () => {},
577
+ }
578
+
579
+ let errorMessage = ""
580
+ try {
581
+ await toolInfo.execute({} as any, ctx)
582
+ } catch (e) {
583
+ errorMessage = (e as Error).message
584
+ }
585
+
586
+ expect(errorMessage).toContain("Custom error:")
587
+ expect(errorMessage).toContain("validation issues")
588
+ })
589
+ })