@toolkit-cli/toolkode 1.3.7

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 (676) hide show
  1. package/AGENTS.md +69 -0
  2. package/BUN_SHELL_MIGRATION_PLAN.md +136 -0
  3. package/Dockerfile +18 -0
  4. package/README.md +15 -0
  5. package/bin/opencode +179 -0
  6. package/bin/toolkode +17 -0
  7. package/bin/toolkode.cjs +190 -0
  8. package/bunfig.toml +7 -0
  9. package/drizzle.config.ts +10 -0
  10. package/git +0 -0
  11. package/migration/20260127222353_familiar_lady_ursula/migration.sql +90 -0
  12. package/migration/20260127222353_familiar_lady_ursula/snapshot.json +796 -0
  13. package/migration/20260211171708_add_project_commands/migration.sql +1 -0
  14. package/migration/20260211171708_add_project_commands/snapshot.json +806 -0
  15. package/migration/20260213144116_wakeful_the_professor/migration.sql +11 -0
  16. package/migration/20260213144116_wakeful_the_professor/snapshot.json +897 -0
  17. package/migration/20260225215848_workspace/migration.sql +7 -0
  18. package/migration/20260225215848_workspace/snapshot.json +959 -0
  19. package/migration/20260227213759_add_session_workspace_id/migration.sql +2 -0
  20. package/migration/20260227213759_add_session_workspace_id/snapshot.json +983 -0
  21. package/migration/20260228203230_blue_harpoon/migration.sql +17 -0
  22. package/migration/20260228203230_blue_harpoon/snapshot.json +1102 -0
  23. package/migration/20260303231226_add_workspace_fields/migration.sql +5 -0
  24. package/migration/20260303231226_add_workspace_fields/snapshot.json +1013 -0
  25. package/migration/20260309230000_move_org_to_state/migration.sql +3 -0
  26. package/migration/20260309230000_move_org_to_state/snapshot.json +1156 -0
  27. package/migration/20260312043431_session_message_cursor/migration.sql +4 -0
  28. package/migration/20260312043431_session_message_cursor/snapshot.json +1168 -0
  29. package/migration/20260323234822_events/migration.sql +13 -0
  30. package/migration/20260323234822_events/snapshot.json +1271 -0
  31. package/package.json +160 -0
  32. package/parsers-config.ts +290 -0
  33. package/script/build-node.ts +54 -0
  34. package/script/build.ts +276 -0
  35. package/script/check-migrations.ts +16 -0
  36. package/script/postinstall.mjs +131 -0
  37. package/script/publish.ts +181 -0
  38. package/script/schema.ts +63 -0
  39. package/script/seed-e2e.ts +60 -0
  40. package/script/upgrade-opentui.ts +64 -0
  41. package/specs/effect-migration.md +293 -0
  42. package/specs/tui-plugins.md +389 -0
  43. package/src/account/account.sql.ts +39 -0
  44. package/src/account/index.ts +397 -0
  45. package/src/account/repo.ts +163 -0
  46. package/src/account/schema.ts +91 -0
  47. package/src/acp/README.md +174 -0
  48. package/src/acp/agent.ts +1743 -0
  49. package/src/acp/session.ts +116 -0
  50. package/src/acp/types.ts +24 -0
  51. package/src/agent/agent.ts +418 -0
  52. package/src/agent/generate.txt +75 -0
  53. package/src/agent/prompt/compaction.txt +14 -0
  54. package/src/agent/prompt/explore.txt +18 -0
  55. package/src/agent/prompt/summary.txt +11 -0
  56. package/src/agent/prompt/title.txt +44 -0
  57. package/src/auth/index.ts +115 -0
  58. package/src/bun/index.ts +128 -0
  59. package/src/bun/registry.ts +50 -0
  60. package/src/bus/bus-event.ts +40 -0
  61. package/src/bus/global.ts +10 -0
  62. package/src/bus/index.ts +184 -0
  63. package/src/channel/index.ts +231 -0
  64. package/src/cli/bootstrap.ts +17 -0
  65. package/src/cli/cmd/account.ts +257 -0
  66. package/src/cli/cmd/acp.ts +70 -0
  67. package/src/cli/cmd/agent.ts +245 -0
  68. package/src/cli/cmd/cmd.ts +7 -0
  69. package/src/cli/cmd/db.ts +119 -0
  70. package/src/cli/cmd/debug/agent.ts +167 -0
  71. package/src/cli/cmd/debug/config.ts +16 -0
  72. package/src/cli/cmd/debug/file.ts +97 -0
  73. package/src/cli/cmd/debug/index.ts +48 -0
  74. package/src/cli/cmd/debug/lsp.ts +53 -0
  75. package/src/cli/cmd/debug/ripgrep.ts +87 -0
  76. package/src/cli/cmd/debug/scrap.ts +16 -0
  77. package/src/cli/cmd/debug/skill.ts +16 -0
  78. package/src/cli/cmd/debug/snapshot.ts +52 -0
  79. package/src/cli/cmd/export.ts +89 -0
  80. package/src/cli/cmd/generate.ts +38 -0
  81. package/src/cli/cmd/github.ts +1646 -0
  82. package/src/cli/cmd/import.ts +207 -0
  83. package/src/cli/cmd/mcp.ts +754 -0
  84. package/src/cli/cmd/models.ts +78 -0
  85. package/src/cli/cmd/plug.ts +231 -0
  86. package/src/cli/cmd/pr.ts +127 -0
  87. package/src/cli/cmd/providers.ts +482 -0
  88. package/src/cli/cmd/run.ts +738 -0
  89. package/src/cli/cmd/serve.ts +42 -0
  90. package/src/cli/cmd/session.ts +159 -0
  91. package/src/cli/cmd/stats.ts +410 -0
  92. package/src/cli/cmd/tui/app.tsx +1255 -0
  93. package/src/cli/cmd/tui/attach.ts +88 -0
  94. package/src/cli/cmd/tui/component/border.tsx +21 -0
  95. package/src/cli/cmd/tui/component/dialog-agent.tsx +31 -0
  96. package/src/cli/cmd/tui/component/dialog-command.tsx +171 -0
  97. package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
  98. package/src/cli/cmd/tui/component/dialog-model.tsx +264 -0
  99. package/src/cli/cmd/tui/component/dialog-provider.tsx +334 -0
  100. package/src/cli/cmd/tui/component/dialog-session-list.tsx +108 -0
  101. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
  102. package/src/cli/cmd/tui/component/dialog-skill.tsx +36 -0
  103. package/src/cli/cmd/tui/component/dialog-stash.tsx +87 -0
  104. package/src/cli/cmd/tui/component/dialog-status.tsx +168 -0
  105. package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
  106. package/src/cli/cmd/tui/component/dialog-theme-list.tsx +50 -0
  107. package/src/cli/cmd/tui/component/dialog-variant.tsx +29 -0
  108. package/src/cli/cmd/tui/component/dialog-workspace-list.tsx +320 -0
  109. package/src/cli/cmd/tui/component/error-component.tsx +91 -0
  110. package/src/cli/cmd/tui/component/logo.tsx +86 -0
  111. package/src/cli/cmd/tui/component/plugin-route-missing.tsx +14 -0
  112. package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +667 -0
  113. package/src/cli/cmd/tui/component/prompt/frecency.tsx +90 -0
  114. package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
  115. package/src/cli/cmd/tui/component/prompt/index.tsx +1353 -0
  116. package/src/cli/cmd/tui/component/prompt/part.ts +16 -0
  117. package/src/cli/cmd/tui/component/prompt/stash.tsx +101 -0
  118. package/src/cli/cmd/tui/component/spinner.tsx +24 -0
  119. package/src/cli/cmd/tui/component/startup-loading.tsx +63 -0
  120. package/src/cli/cmd/tui/component/textarea-keybindings.ts +73 -0
  121. package/src/cli/cmd/tui/component/todo-item.tsx +32 -0
  122. package/src/cli/cmd/tui/component/workspace/dialog-session-list.tsx +151 -0
  123. package/src/cli/cmd/tui/context/args.tsx +15 -0
  124. package/src/cli/cmd/tui/context/directory.ts +13 -0
  125. package/src/cli/cmd/tui/context/exit.tsx +60 -0
  126. package/src/cli/cmd/tui/context/helper.tsx +25 -0
  127. package/src/cli/cmd/tui/context/keybind.tsx +105 -0
  128. package/src/cli/cmd/tui/context/kv.tsx +52 -0
  129. package/src/cli/cmd/tui/context/local.tsx +406 -0
  130. package/src/cli/cmd/tui/context/plugin-keybinds.ts +41 -0
  131. package/src/cli/cmd/tui/context/prompt.tsx +18 -0
  132. package/src/cli/cmd/tui/context/route.tsx +52 -0
  133. package/src/cli/cmd/tui/context/sdk.tsx +128 -0
  134. package/src/cli/cmd/tui/context/sync.tsx +504 -0
  135. package/src/cli/cmd/tui/context/theme/amber.json +245 -0
  136. package/src/cli/cmd/tui/context/theme/amiga.json +245 -0
  137. package/src/cli/cmd/tui/context/theme/atari.json +245 -0
  138. package/src/cli/cmd/tui/context/theme/aura.json +69 -0
  139. package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
  140. package/src/cli/cmd/tui/context/theme/borland.json +245 -0
  141. package/src/cli/cmd/tui/context/theme/carbonfox.json +248 -0
  142. package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +233 -0
  143. package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +233 -0
  144. package/src/cli/cmd/tui/context/theme/catppuccin.json +112 -0
  145. package/src/cli/cmd/tui/context/theme/cobalt2.json +228 -0
  146. package/src/cli/cmd/tui/context/theme/commodore.json +245 -0
  147. package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
  148. package/src/cli/cmd/tui/context/theme/dos-edit.json +245 -0
  149. package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
  150. package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
  151. package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
  152. package/src/cli/cmd/tui/context/theme/github.json +233 -0
  153. package/src/cli/cmd/tui/context/theme/gnu.json +245 -0
  154. package/src/cli/cmd/tui/context/theme/gruvbox.json +242 -0
  155. package/src/cli/cmd/tui/context/theme/hacker.json +245 -0
  156. package/src/cli/cmd/tui/context/theme/irix.json +245 -0
  157. package/src/cli/cmd/tui/context/theme/kanagawa.json +77 -0
  158. package/src/cli/cmd/tui/context/theme/lucent-orng.json +237 -0
  159. package/src/cli/cmd/tui/context/theme/mac84.json +245 -0
  160. package/src/cli/cmd/tui/context/theme/material.json +235 -0
  161. package/src/cli/cmd/tui/context/theme/matrix.json +77 -0
  162. package/src/cli/cmd/tui/context/theme/mercury.json +252 -0
  163. package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
  164. package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
  165. package/src/cli/cmd/tui/context/theme/nord.json +223 -0
  166. package/src/cli/cmd/tui/context/theme/norton.json +245 -0
  167. package/src/cli/cmd/tui/context/theme/one-dark.json +84 -0
  168. package/src/cli/cmd/tui/context/theme/opencode.json +245 -0
  169. package/src/cli/cmd/tui/context/theme/orng.json +249 -0
  170. package/src/cli/cmd/tui/context/theme/osaka-jade.json +93 -0
  171. package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
  172. package/src/cli/cmd/tui/context/theme/pine.json +245 -0
  173. package/src/cli/cmd/tui/context/theme/retrowave.json +245 -0
  174. package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
  175. package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
  176. package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
  177. package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
  178. package/src/cli/cmd/tui/context/theme/toolkode.json +245 -0
  179. package/src/cli/cmd/tui/context/theme/tron.json +245 -0
  180. package/src/cli/cmd/tui/context/theme/ubuntu.json +245 -0
  181. package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
  182. package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
  183. package/src/cli/cmd/tui/context/theme/vt100.json +245 -0
  184. package/src/cli/cmd/tui/context/theme/xcode.json +245 -0
  185. package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
  186. package/src/cli/cmd/tui/context/theme.tsx +1288 -0
  187. package/src/cli/cmd/tui/context/tui-config.tsx +9 -0
  188. package/src/cli/cmd/tui/event.ts +49 -0
  189. package/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx +152 -0
  190. package/src/cli/cmd/tui/feature-plugins/home/tips.tsx +50 -0
  191. package/src/cli/cmd/tui/feature-plugins/sidebar/agents-panel.tsx +95 -0
  192. package/src/cli/cmd/tui/feature-plugins/sidebar/btw-panel.tsx +105 -0
  193. package/src/cli/cmd/tui/feature-plugins/sidebar/commands-panel.tsx +40 -0
  194. package/src/cli/cmd/tui/feature-plugins/sidebar/context.tsx +63 -0
  195. package/src/cli/cmd/tui/feature-plugins/sidebar/files.tsx +62 -0
  196. package/src/cli/cmd/tui/feature-plugins/sidebar/footer.tsx +93 -0
  197. package/src/cli/cmd/tui/feature-plugins/sidebar/git-panel.tsx +36 -0
  198. package/src/cli/cmd/tui/feature-plugins/sidebar/loop-panel.tsx +124 -0
  199. package/src/cli/cmd/tui/feature-plugins/sidebar/lsp.tsx +66 -0
  200. package/src/cli/cmd/tui/feature-plugins/sidebar/mcp.tsx +96 -0
  201. package/src/cli/cmd/tui/feature-plugins/sidebar/session-panel.tsx +48 -0
  202. package/src/cli/cmd/tui/feature-plugins/sidebar/todo.tsx +48 -0
  203. package/src/cli/cmd/tui/feature-plugins/system/plugins.tsx +270 -0
  204. package/src/cli/cmd/tui/plugin/api.tsx +420 -0
  205. package/src/cli/cmd/tui/plugin/index.ts +3 -0
  206. package/src/cli/cmd/tui/plugin/internal.ts +37 -0
  207. package/src/cli/cmd/tui/plugin/runtime.ts +967 -0
  208. package/src/cli/cmd/tui/plugin/slots.tsx +61 -0
  209. package/src/cli/cmd/tui/routes/home.tsx +173 -0
  210. package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +65 -0
  211. package/src/cli/cmd/tui/routes/session/dialog-message.tsx +110 -0
  212. package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +26 -0
  213. package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
  214. package/src/cli/cmd/tui/routes/session/footer.tsx +91 -0
  215. package/src/cli/cmd/tui/routes/session/index.tsx +2229 -0
  216. package/src/cli/cmd/tui/routes/session/permission.tsx +685 -0
  217. package/src/cli/cmd/tui/routes/session/question.tsx +467 -0
  218. package/src/cli/cmd/tui/routes/session/sidebar.tsx +72 -0
  219. package/src/cli/cmd/tui/routes/session/subagent-footer.tsx +131 -0
  220. package/src/cli/cmd/tui/thread.ts +232 -0
  221. package/src/cli/cmd/tui/ui/dialog-alert.tsx +59 -0
  222. package/src/cli/cmd/tui/ui/dialog-confirm.tsx +89 -0
  223. package/src/cli/cmd/tui/ui/dialog-export-options.tsx +208 -0
  224. package/src/cli/cmd/tui/ui/dialog-help.tsx +40 -0
  225. package/src/cli/cmd/tui/ui/dialog-prompt.tsx +106 -0
  226. package/src/cli/cmd/tui/ui/dialog-select.tsx +402 -0
  227. package/src/cli/cmd/tui/ui/dialog.tsx +192 -0
  228. package/src/cli/cmd/tui/ui/link.tsx +28 -0
  229. package/src/cli/cmd/tui/ui/spinner.ts +368 -0
  230. package/src/cli/cmd/tui/ui/toast.tsx +100 -0
  231. package/src/cli/cmd/tui/util/clipboard.ts +192 -0
  232. package/src/cli/cmd/tui/util/editor.ts +37 -0
  233. package/src/cli/cmd/tui/util/selection.ts +25 -0
  234. package/src/cli/cmd/tui/util/signal.ts +7 -0
  235. package/src/cli/cmd/tui/util/terminal.ts +114 -0
  236. package/src/cli/cmd/tui/util/transcript.ts +98 -0
  237. package/src/cli/cmd/tui/win32.ts +129 -0
  238. package/src/cli/cmd/tui/worker.ts +204 -0
  239. package/src/cli/cmd/uninstall.ts +353 -0
  240. package/src/cli/cmd/upgrade.ts +73 -0
  241. package/src/cli/cmd/web.ts +81 -0
  242. package/src/cli/effect/prompt.ts +25 -0
  243. package/src/cli/error.ts +46 -0
  244. package/src/cli/logo.ts +7 -0
  245. package/src/cli/network.ts +60 -0
  246. package/src/cli/ui.ts +116 -0
  247. package/src/cli/upgrade.ts +31 -0
  248. package/src/command/index.ts +195 -0
  249. package/src/command/template/initialize.txt +10 -0
  250. package/src/command/template/review.txt +101 -0
  251. package/src/config/config.ts +1693 -0
  252. package/src/config/markdown.ts +99 -0
  253. package/src/config/migrate-tui-config.ts +155 -0
  254. package/src/config/paths.ts +174 -0
  255. package/src/config/tui-schema.ts +36 -0
  256. package/src/config/tui.ts +212 -0
  257. package/src/control-plane/adaptors/index.ts +20 -0
  258. package/src/control-plane/adaptors/worktree.ts +38 -0
  259. package/src/control-plane/schema.ts +17 -0
  260. package/src/control-plane/sse.ts +66 -0
  261. package/src/control-plane/types.ts +21 -0
  262. package/src/control-plane/workspace.sql.ts +17 -0
  263. package/src/control-plane/workspace.ts +154 -0
  264. package/src/cron/index.ts +241 -0
  265. package/src/cron/parse.ts +189 -0
  266. package/src/effect/cross-spawn-spawner.ts +479 -0
  267. package/src/effect/instance-registry.ts +12 -0
  268. package/src/effect/instance-state.ts +47 -0
  269. package/src/effect/run-service.ts +19 -0
  270. package/src/env/index.ts +28 -0
  271. package/src/file/ignore.ts +82 -0
  272. package/src/file/index.ts +693 -0
  273. package/src/file/protected.ts +59 -0
  274. package/src/file/ripgrep.ts +376 -0
  275. package/src/file/time.ts +128 -0
  276. package/src/file/watcher.ts +171 -0
  277. package/src/filesystem/index.ts +226 -0
  278. package/src/flag/flag.ts +157 -0
  279. package/src/format/formatter.ts +396 -0
  280. package/src/format/index.ts +199 -0
  281. package/src/global/index.ts +54 -0
  282. package/src/hooks/index.ts +302 -0
  283. package/src/id/id.ts +85 -0
  284. package/src/ide/index.ts +74 -0
  285. package/src/index.ts +243 -0
  286. package/src/installation/index.ts +363 -0
  287. package/src/lsp/client.ts +252 -0
  288. package/src/lsp/index.ts +558 -0
  289. package/src/lsp/language.ts +120 -0
  290. package/src/lsp/launch.ts +21 -0
  291. package/src/lsp/server.ts +2093 -0
  292. package/src/mcp/auth.ts +181 -0
  293. package/src/mcp/index.ts +926 -0
  294. package/src/mcp/oauth-callback.ts +215 -0
  295. package/src/mcp/oauth-provider.ts +185 -0
  296. package/src/node.ts +1 -0
  297. package/src/patch/index.ts +680 -0
  298. package/src/permission/arity.ts +163 -0
  299. package/src/permission/evaluate.ts +15 -0
  300. package/src/permission/index.ts +322 -0
  301. package/src/permission/schema.ts +17 -0
  302. package/src/plugin/codex.ts +628 -0
  303. package/src/plugin/copilot.ts +343 -0
  304. package/src/plugin/index.ts +331 -0
  305. package/src/plugin/install.ts +384 -0
  306. package/src/plugin/meta.ts +165 -0
  307. package/src/plugin/shared.ts +172 -0
  308. package/src/project/bootstrap.ts +31 -0
  309. package/src/project/instance.ts +167 -0
  310. package/src/project/project.sql.ts +16 -0
  311. package/src/project/project.ts +519 -0
  312. package/src/project/schema.ts +16 -0
  313. package/src/project/state.ts +70 -0
  314. package/src/project/vcs.ts +124 -0
  315. package/src/provider/auth.ts +252 -0
  316. package/src/provider/error.ts +197 -0
  317. package/src/provider/models.ts +138 -0
  318. package/src/provider/provider.ts +1593 -0
  319. package/src/provider/schema.ts +39 -0
  320. package/src/provider/sdk/copilot/README.md +5 -0
  321. package/src/provider/sdk/copilot/chat/convert-to-openai-compatible-chat-messages.ts +170 -0
  322. package/src/provider/sdk/copilot/chat/get-response-metadata.ts +15 -0
  323. package/src/provider/sdk/copilot/chat/map-openai-compatible-finish-reason.ts +19 -0
  324. package/src/provider/sdk/copilot/chat/openai-compatible-api-types.ts +64 -0
  325. package/src/provider/sdk/copilot/chat/openai-compatible-chat-language-model.ts +815 -0
  326. package/src/provider/sdk/copilot/chat/openai-compatible-chat-options.ts +28 -0
  327. package/src/provider/sdk/copilot/chat/openai-compatible-metadata-extractor.ts +44 -0
  328. package/src/provider/sdk/copilot/chat/openai-compatible-prepare-tools.ts +83 -0
  329. package/src/provider/sdk/copilot/copilot-provider.ts +100 -0
  330. package/src/provider/sdk/copilot/index.ts +2 -0
  331. package/src/provider/sdk/copilot/openai-compatible-error.ts +27 -0
  332. package/src/provider/sdk/copilot/responses/convert-to-openai-responses-input.ts +335 -0
  333. package/src/provider/sdk/copilot/responses/map-openai-responses-finish-reason.ts +22 -0
  334. package/src/provider/sdk/copilot/responses/openai-config.ts +18 -0
  335. package/src/provider/sdk/copilot/responses/openai-error.ts +22 -0
  336. package/src/provider/sdk/copilot/responses/openai-responses-api-types.ts +214 -0
  337. package/src/provider/sdk/copilot/responses/openai-responses-language-model.ts +1769 -0
  338. package/src/provider/sdk/copilot/responses/openai-responses-prepare-tools.ts +173 -0
  339. package/src/provider/sdk/copilot/responses/openai-responses-settings.ts +1 -0
  340. package/src/provider/sdk/copilot/responses/tool/code-interpreter.ts +87 -0
  341. package/src/provider/sdk/copilot/responses/tool/file-search.ts +127 -0
  342. package/src/provider/sdk/copilot/responses/tool/image-generation.ts +114 -0
  343. package/src/provider/sdk/copilot/responses/tool/local-shell.ts +64 -0
  344. package/src/provider/sdk/copilot/responses/tool/web-search-preview.ts +103 -0
  345. package/src/provider/sdk/copilot/responses/tool/web-search.ts +102 -0
  346. package/src/provider/toolkit-manifest.ts +110 -0
  347. package/src/provider/transform.ts +1045 -0
  348. package/src/pty/index.ts +397 -0
  349. package/src/pty/schema.ts +17 -0
  350. package/src/question/index.ts +221 -0
  351. package/src/question/schema.ts +17 -0
  352. package/src/server/error.ts +36 -0
  353. package/src/server/event.ts +7 -0
  354. package/src/server/instance.ts +285 -0
  355. package/src/server/mdns.ts +60 -0
  356. package/src/server/middleware.ts +29 -0
  357. package/src/server/projectors.ts +28 -0
  358. package/src/server/router.ts +99 -0
  359. package/src/server/routes/config.ts +92 -0
  360. package/src/server/routes/event.ts +83 -0
  361. package/src/server/routes/experimental.ts +271 -0
  362. package/src/server/routes/file.ts +197 -0
  363. package/src/server/routes/global.ts +339 -0
  364. package/src/server/routes/mcp.ts +225 -0
  365. package/src/server/routes/permission.ts +69 -0
  366. package/src/server/routes/project.ts +118 -0
  367. package/src/server/routes/provider.ts +171 -0
  368. package/src/server/routes/pty.ts +211 -0
  369. package/src/server/routes/question.ts +99 -0
  370. package/src/server/routes/session.ts +1031 -0
  371. package/src/server/routes/tui.ts +379 -0
  372. package/src/server/routes/workspace.ts +94 -0
  373. package/src/server/server.ts +312 -0
  374. package/src/session/compaction.ts +424 -0
  375. package/src/session/index.ts +882 -0
  376. package/src/session/instruction.ts +321 -0
  377. package/src/session/llm.ts +341 -0
  378. package/src/session/message-v2.ts +1030 -0
  379. package/src/session/message.ts +191 -0
  380. package/src/session/overflow.ts +22 -0
  381. package/src/session/processor.ts +554 -0
  382. package/src/session/projectors.ts +135 -0
  383. package/src/session/prompt/anthropic.txt +105 -0
  384. package/src/session/prompt/beast.txt +147 -0
  385. package/src/session/prompt/build-switch.txt +5 -0
  386. package/src/session/prompt/codex.txt +79 -0
  387. package/src/session/prompt/copilot-gpt-5.txt +143 -0
  388. package/src/session/prompt/default.txt +108 -0
  389. package/src/session/prompt/gemini.txt +155 -0
  390. package/src/session/prompt/gpt.txt +107 -0
  391. package/src/session/prompt/max-steps.txt +16 -0
  392. package/src/session/prompt/plan-reminder-anthropic.txt +67 -0
  393. package/src/session/prompt/plan.txt +26 -0
  394. package/src/session/prompt/trinity.txt +97 -0
  395. package/src/session/prompt.ts +2058 -0
  396. package/src/session/retry.ts +106 -0
  397. package/src/session/revert.ts +138 -0
  398. package/src/session/schema.ts +38 -0
  399. package/src/session/session.sql.ts +103 -0
  400. package/src/session/status.ts +102 -0
  401. package/src/session/summary.ts +170 -0
  402. package/src/session/system.ts +74 -0
  403. package/src/session/todo.ts +57 -0
  404. package/src/share/share-next.ts +288 -0
  405. package/src/share/share.sql.ts +13 -0
  406. package/src/shell/shell.ts +73 -0
  407. package/src/skill/discovery.ts +116 -0
  408. package/src/skill/index.ts +284 -0
  409. package/src/skills-marketplace/index.ts +305 -0
  410. package/src/snapshot/index.ts +489 -0
  411. package/src/sql.d.ts +4 -0
  412. package/src/storage/db.bun.ts +8 -0
  413. package/src/storage/db.node.ts +8 -0
  414. package/src/storage/db.ts +177 -0
  415. package/src/storage/json-migration.ts +425 -0
  416. package/src/storage/schema.sql.ts +10 -0
  417. package/src/storage/schema.ts +5 -0
  418. package/src/storage/storage.ts +217 -0
  419. package/src/sync/README.md +179 -0
  420. package/src/sync/event.sql.ts +16 -0
  421. package/src/sync/index.ts +263 -0
  422. package/src/sync/schema.ts +14 -0
  423. package/src/team/index.ts +428 -0
  424. package/src/tool/apply_patch.ts +281 -0
  425. package/src/tool/apply_patch.txt +33 -0
  426. package/src/tool/bash.ts +271 -0
  427. package/src/tool/bash.txt +115 -0
  428. package/src/tool/batch.ts +183 -0
  429. package/src/tool/batch.txt +24 -0
  430. package/src/tool/codesearch.ts +132 -0
  431. package/src/tool/codesearch.txt +12 -0
  432. package/src/tool/cron-create.ts +54 -0
  433. package/src/tool/cron-create.txt +16 -0
  434. package/src/tool/cron-delete.ts +29 -0
  435. package/src/tool/cron-delete.txt +1 -0
  436. package/src/tool/cron-list.ts +41 -0
  437. package/src/tool/cron-list.txt +1 -0
  438. package/src/tool/edit.ts +667 -0
  439. package/src/tool/edit.txt +10 -0
  440. package/src/tool/external-directory.ts +32 -0
  441. package/src/tool/glob.ts +78 -0
  442. package/src/tool/glob.txt +6 -0
  443. package/src/tool/grep.ts +156 -0
  444. package/src/tool/grep.txt +8 -0
  445. package/src/tool/invalid.ts +17 -0
  446. package/src/tool/ls.ts +121 -0
  447. package/src/tool/ls.txt +1 -0
  448. package/src/tool/lsp.ts +97 -0
  449. package/src/tool/lsp.txt +19 -0
  450. package/src/tool/multiedit.ts +46 -0
  451. package/src/tool/multiedit.txt +41 -0
  452. package/src/tool/plan-enter.txt +14 -0
  453. package/src/tool/plan-exit.txt +13 -0
  454. package/src/tool/plan.ts +131 -0
  455. package/src/tool/question.ts +33 -0
  456. package/src/tool/question.txt +10 -0
  457. package/src/tool/read.ts +293 -0
  458. package/src/tool/read.txt +14 -0
  459. package/src/tool/registry.ts +232 -0
  460. package/src/tool/schema.ts +17 -0
  461. package/src/tool/send-message.ts +59 -0
  462. package/src/tool/send-message.txt +7 -0
  463. package/src/tool/skill.ts +105 -0
  464. package/src/tool/task.ts +230 -0
  465. package/src/tool/task.txt +62 -0
  466. package/src/tool/team.ts +235 -0
  467. package/src/tool/team.txt +22 -0
  468. package/src/tool/todo.ts +31 -0
  469. package/src/tool/todowrite.txt +167 -0
  470. package/src/tool/tool.ts +90 -0
  471. package/src/tool/truncate.ts +144 -0
  472. package/src/tool/truncation-dir.ts +4 -0
  473. package/src/tool/webfetch.ts +206 -0
  474. package/src/tool/webfetch.txt +13 -0
  475. package/src/tool/websearch.ts +150 -0
  476. package/src/tool/websearch.txt +14 -0
  477. package/src/tool/write.ts +84 -0
  478. package/src/tool/write.txt +8 -0
  479. package/src/util/abort.ts +35 -0
  480. package/src/util/archive.ts +17 -0
  481. package/src/util/color.ts +19 -0
  482. package/src/util/context.ts +25 -0
  483. package/src/util/data-url.ts +9 -0
  484. package/src/util/defer.ts +12 -0
  485. package/src/util/effect-http-client.ts +11 -0
  486. package/src/util/effect-zod.ts +98 -0
  487. package/src/util/error.ts +77 -0
  488. package/src/util/filesystem.ts +203 -0
  489. package/src/util/flock.ts +333 -0
  490. package/src/util/fn.ts +21 -0
  491. package/src/util/format.ts +20 -0
  492. package/src/util/git.ts +35 -0
  493. package/src/util/glob.ts +34 -0
  494. package/src/util/hash.ts +7 -0
  495. package/src/util/iife.ts +3 -0
  496. package/src/util/keybind.ts +103 -0
  497. package/src/util/lazy.ts +23 -0
  498. package/src/util/locale.ts +81 -0
  499. package/src/util/lock.ts +98 -0
  500. package/src/util/log.ts +182 -0
  501. package/src/util/network.ts +9 -0
  502. package/src/util/process.ts +172 -0
  503. package/src/util/queue.ts +32 -0
  504. package/src/util/record.ts +3 -0
  505. package/src/util/rpc.ts +66 -0
  506. package/src/util/schema.ts +53 -0
  507. package/src/util/scrap.ts +10 -0
  508. package/src/util/signal.ts +12 -0
  509. package/src/util/timeout.ts +14 -0
  510. package/src/util/token.ts +7 -0
  511. package/src/util/update-schema.ts +13 -0
  512. package/src/util/which.ts +14 -0
  513. package/src/util/wildcard.ts +59 -0
  514. package/src/worktree/index.ts +638 -0
  515. package/sst-env.d.ts +10 -0
  516. package/test/AGENTS.md +81 -0
  517. package/test/account/repo.test.ts +326 -0
  518. package/test/account/service.test.ts +282 -0
  519. package/test/acp/agent-interface.test.ts +51 -0
  520. package/test/acp/event-subscription.test.ts +685 -0
  521. package/test/agent/agent.test.ts +717 -0
  522. package/test/auth/auth.test.ts +58 -0
  523. package/test/bun.test.ts +53 -0
  524. package/test/bus/bus-effect.test.ts +164 -0
  525. package/test/bus/bus-integration.test.ts +87 -0
  526. package/test/bus/bus.test.ts +219 -0
  527. package/test/cli/account.test.ts +26 -0
  528. package/test/cli/cmd/tui/prompt-part.test.ts +47 -0
  529. package/test/cli/github-action.test.ts +198 -0
  530. package/test/cli/github-remote.test.ts +80 -0
  531. package/test/cli/import.test.ts +54 -0
  532. package/test/cli/plugin-auth-picker.test.ts +120 -0
  533. package/test/cli/tui/keybind-plugin.test.ts +90 -0
  534. package/test/cli/tui/plugin-add.test.ts +61 -0
  535. package/test/cli/tui/plugin-install.test.ts +95 -0
  536. package/test/cli/tui/plugin-lifecycle.test.ts +225 -0
  537. package/test/cli/tui/plugin-loader-entrypoint.test.ts +189 -0
  538. package/test/cli/tui/plugin-loader-pure.test.ts +71 -0
  539. package/test/cli/tui/plugin-loader.test.ts +563 -0
  540. package/test/cli/tui/plugin-toggle.test.ts +157 -0
  541. package/test/cli/tui/theme-store.test.ts +51 -0
  542. package/test/cli/tui/thread.test.ts +128 -0
  543. package/test/cli/tui/transcript.test.ts +322 -0
  544. package/test/config/agent-color.test.ts +71 -0
  545. package/test/config/config.test.ts +2187 -0
  546. package/test/config/fixtures/empty-frontmatter.md +4 -0
  547. package/test/config/fixtures/frontmatter.md +28 -0
  548. package/test/config/fixtures/markdown-header.md +11 -0
  549. package/test/config/fixtures/no-frontmatter.md +1 -0
  550. package/test/config/fixtures/weird-model-id.md +13 -0
  551. package/test/config/markdown.test.ts +228 -0
  552. package/test/config/tui.test.ts +667 -0
  553. package/test/control-plane/sse.test.ts +56 -0
  554. package/test/effect/cross-spawn-spawner.test.ts +402 -0
  555. package/test/effect/instance-state.test.ts +384 -0
  556. package/test/effect/run-service.test.ts +46 -0
  557. package/test/file/fsmonitor.test.ts +62 -0
  558. package/test/file/ignore.test.ts +10 -0
  559. package/test/file/index.test.ts +946 -0
  560. package/test/file/path-traversal.test.ts +198 -0
  561. package/test/file/ripgrep.test.ts +54 -0
  562. package/test/file/time.test.ts +354 -0
  563. package/test/file/watcher.test.ts +247 -0
  564. package/test/filesystem/filesystem.test.ts +319 -0
  565. package/test/fixture/db.ts +11 -0
  566. package/test/fixture/fixture.test.ts +26 -0
  567. package/test/fixture/fixture.ts +141 -0
  568. package/test/fixture/flock-worker.ts +72 -0
  569. package/test/fixture/lsp/fake-lsp-server.js +77 -0
  570. package/test/fixture/plug-worker.ts +93 -0
  571. package/test/fixture/plugin-meta-worker.ts +26 -0
  572. package/test/fixture/skills/agents-sdk/SKILL.md +152 -0
  573. package/test/fixture/skills/agents-sdk/references/callable.md +92 -0
  574. package/test/fixture/skills/cloudflare/SKILL.md +211 -0
  575. package/test/fixture/skills/index.json +6 -0
  576. package/test/fixture/tui-plugin.ts +335 -0
  577. package/test/fixture/tui-runtime.ts +34 -0
  578. package/test/format/format.test.ts +179 -0
  579. package/test/ide/ide.test.ts +82 -0
  580. package/test/installation/installation.test.ts +151 -0
  581. package/test/keybind.test.ts +421 -0
  582. package/test/lib/effect.ts +37 -0
  583. package/test/lib/filesystem.ts +10 -0
  584. package/test/lsp/client.test.ts +95 -0
  585. package/test/lsp/index.test.ts +55 -0
  586. package/test/lsp/launch.test.ts +22 -0
  587. package/test/lsp/lifecycle.test.ts +147 -0
  588. package/test/mcp/headers.test.ts +153 -0
  589. package/test/mcp/lifecycle.test.ts +750 -0
  590. package/test/mcp/oauth-auto-connect.test.ts +199 -0
  591. package/test/mcp/oauth-browser.test.ts +249 -0
  592. package/test/memory/abort-leak.test.ts +137 -0
  593. package/test/patch/patch.test.ts +348 -0
  594. package/test/permission/arity.test.ts +33 -0
  595. package/test/permission/next.test.ts +1148 -0
  596. package/test/permission-task.test.ts +323 -0
  597. package/test/plugin/auth-override.test.ts +74 -0
  598. package/test/plugin/codex.test.ts +123 -0
  599. package/test/plugin/install-concurrency.test.ts +134 -0
  600. package/test/plugin/install.test.ts +504 -0
  601. package/test/plugin/loader-shared.test.ts +625 -0
  602. package/test/plugin/meta.test.ts +137 -0
  603. package/test/plugin/trigger.test.ts +111 -0
  604. package/test/preload.ts +90 -0
  605. package/test/project/migrate-global.test.ts +140 -0
  606. package/test/project/project.test.ts +459 -0
  607. package/test/project/state.test.ts +115 -0
  608. package/test/project/vcs.test.ts +116 -0
  609. package/test/project/worktree-remove.test.ts +96 -0
  610. package/test/project/worktree.test.ts +173 -0
  611. package/test/provider/amazon-bedrock.test.ts +447 -0
  612. package/test/provider/copilot/convert-to-copilot-messages.test.ts +523 -0
  613. package/test/provider/copilot/copilot-chat-model.test.ts +592 -0
  614. package/test/provider/gitlab-duo.test.ts +412 -0
  615. package/test/provider/provider.test.ts +2284 -0
  616. package/test/provider/transform.test.ts +2758 -0
  617. package/test/pty/pty-output-isolation.test.ts +141 -0
  618. package/test/pty/pty-session.test.ts +92 -0
  619. package/test/question/question.test.ts +453 -0
  620. package/test/server/global-session-list.test.ts +89 -0
  621. package/test/server/project-init-git.test.ts +121 -0
  622. package/test/server/session-list.test.ts +90 -0
  623. package/test/server/session-messages.test.ts +132 -0
  624. package/test/server/session-select.test.ts +78 -0
  625. package/test/session/compaction.test.ts +1094 -0
  626. package/test/session/instruction.test.ts +170 -0
  627. package/test/session/llm.test.ts +882 -0
  628. package/test/session/message-v2.test.ts +957 -0
  629. package/test/session/messages-pagination.test.ts +115 -0
  630. package/test/session/processor-effect.test.ts +838 -0
  631. package/test/session/prompt.test.ts +518 -0
  632. package/test/session/retry.test.ts +232 -0
  633. package/test/session/revert-compact.test.ts +286 -0
  634. package/test/session/session.test.ts +142 -0
  635. package/test/session/structured-output-integration.test.ts +233 -0
  636. package/test/session/structured-output.test.ts +391 -0
  637. package/test/session/system.test.ts +59 -0
  638. package/test/share/share-next.test.ts +76 -0
  639. package/test/skill/discovery.test.ts +116 -0
  640. package/test/skill/skill.test.ts +392 -0
  641. package/test/snapshot/snapshot.test.ts +1235 -0
  642. package/test/storage/db.test.ts +14 -0
  643. package/test/storage/json-migration.test.ts +849 -0
  644. package/test/sync/index.test.ts +191 -0
  645. package/test/tool/__snapshots__/tool.test.ts.snap +9 -0
  646. package/test/tool/apply_patch.test.ts +567 -0
  647. package/test/tool/bash.test.ts +403 -0
  648. package/test/tool/edit.test.ts +681 -0
  649. package/test/tool/external-directory.test.ts +128 -0
  650. package/test/tool/fixtures/large-image.png +0 -0
  651. package/test/tool/fixtures/models-api.json +38413 -0
  652. package/test/tool/grep.test.ts +111 -0
  653. package/test/tool/question.test.ts +108 -0
  654. package/test/tool/read.test.ts +509 -0
  655. package/test/tool/registry.test.ts +126 -0
  656. package/test/tool/skill.test.ts +167 -0
  657. package/test/tool/task.test.ts +49 -0
  658. package/test/tool/truncation.test.ts +161 -0
  659. package/test/tool/webfetch.test.ts +101 -0
  660. package/test/tool/write.test.ts +353 -0
  661. package/test/util/data-url.test.ts +14 -0
  662. package/test/util/effect-zod.test.ts +61 -0
  663. package/test/util/error.test.ts +38 -0
  664. package/test/util/filesystem.test.ts +558 -0
  665. package/test/util/flock.test.ts +383 -0
  666. package/test/util/format.test.ts +59 -0
  667. package/test/util/glob.test.ts +164 -0
  668. package/test/util/iife.test.ts +36 -0
  669. package/test/util/lazy.test.ts +50 -0
  670. package/test/util/lock.test.ts +72 -0
  671. package/test/util/module.test.ts +59 -0
  672. package/test/util/process.test.ts +128 -0
  673. package/test/util/timeout.test.ts +21 -0
  674. package/test/util/which.test.ts +100 -0
  675. package/test/util/wildcard.test.ts +90 -0
  676. package/tsconfig.json +23 -0
@@ -0,0 +1,232 @@
1
+ import { PlanExitTool } from "./plan"
2
+ import { QuestionTool } from "./question"
3
+ import { BashTool } from "./bash"
4
+ import { EditTool } from "./edit"
5
+ import { GlobTool } from "./glob"
6
+ import { GrepTool } from "./grep"
7
+ import { BatchTool } from "./batch"
8
+ import { ReadTool } from "./read"
9
+ import { TaskTool } from "./task"
10
+ import { TodoWriteTool } from "./todo"
11
+ import { WebFetchTool } from "./webfetch"
12
+ import { WriteTool } from "./write"
13
+ import { InvalidTool } from "./invalid"
14
+ import { SkillTool } from "./skill"
15
+ import type { Agent } from "../agent/agent"
16
+ import { Tool } from "./tool"
17
+ import { Config } from "../config/config"
18
+ import path from "path"
19
+ import { type ToolContext as PluginToolContext, type ToolDefinition } from "@toolkit-cli/plugin"
20
+ import z from "zod"
21
+ import { Plugin } from "../plugin"
22
+ import { ProviderID, type ModelID } from "../provider/schema"
23
+ import { WebSearchTool } from "./websearch"
24
+ import { CodeSearchTool } from "./codesearch"
25
+ import { Flag } from "@/flag/flag"
26
+ import { Log } from "@/util/log"
27
+ import { LspTool } from "./lsp"
28
+ import { Truncate } from "./truncate"
29
+ import { ApplyPatchTool } from "./apply_patch"
30
+ import { CronCreateTool } from "./cron-create"
31
+ import { CronListTool } from "./cron-list"
32
+ import { CronDeleteTool } from "./cron-delete"
33
+ import { Cron } from "../cron"
34
+ import { SendMessageTool } from "./send-message"
35
+ import { TeamTool } from "./team"
36
+ import { Glob } from "../util/glob"
37
+ import { pathToFileURL } from "url"
38
+ import { Effect, Layer, ServiceMap } from "effect"
39
+ import { InstanceState } from "@/effect/instance-state"
40
+ import { makeRuntime } from "@/effect/run-service"
41
+
42
+ export namespace ToolRegistry {
43
+ const log = Log.create({ service: "tool.registry" })
44
+
45
+ type State = {
46
+ custom: Tool.Info[]
47
+ }
48
+
49
+ export interface Interface {
50
+ readonly register: (tool: Tool.Info) => Effect.Effect<void>
51
+ readonly ids: () => Effect.Effect<string[]>
52
+ readonly tools: (
53
+ model: { providerID: ProviderID; modelID: ModelID },
54
+ agent?: Agent.Info,
55
+ ) => Effect.Effect<(Awaited<ReturnType<Tool.Info["init"]>> & { id: string })[]>
56
+ }
57
+
58
+ export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/ToolRegistry") {}
59
+
60
+ export const layer = Layer.effect(
61
+ Service,
62
+ Effect.gen(function* () {
63
+ const config = yield* Config.Service
64
+ const plugin = yield* Plugin.Service
65
+
66
+ const cache = yield* InstanceState.make<State>(
67
+ Effect.fn("ToolRegistry.state")(function* (ctx) {
68
+ const custom: Tool.Info[] = []
69
+
70
+ function fromPlugin(id: string, def: ToolDefinition): Tool.Info {
71
+ return {
72
+ id,
73
+ init: async (initCtx) => ({
74
+ parameters: z.object(def.args),
75
+ description: def.description,
76
+ execute: async (args, toolCtx) => {
77
+ const pluginCtx = {
78
+ ...toolCtx,
79
+ directory: ctx.directory,
80
+ worktree: ctx.worktree,
81
+ } as unknown as PluginToolContext
82
+ const result = await def.execute(args as any, pluginCtx)
83
+ const out = await Truncate.output(result, {}, initCtx?.agent)
84
+ return {
85
+ title: "",
86
+ output: out.truncated ? out.content : result,
87
+ metadata: { truncated: out.truncated, outputPath: out.truncated ? out.outputPath : undefined },
88
+ }
89
+ },
90
+ }),
91
+ }
92
+ }
93
+
94
+ const dirs = yield* config.directories()
95
+ const matches = dirs.flatMap((dir) =>
96
+ Glob.scanSync("{tool,tools}/*.{js,ts}", { cwd: dir, absolute: true, dot: true, symlink: true }),
97
+ )
98
+ if (matches.length) yield* config.waitForDependencies()
99
+ for (const match of matches) {
100
+ const namespace = path.basename(match, path.extname(match))
101
+ const mod = yield* Effect.promise(
102
+ () => import(process.platform === "win32" ? match : pathToFileURL(match).href),
103
+ )
104
+ for (const [id, def] of Object.entries<ToolDefinition>(mod)) {
105
+ custom.push(fromPlugin(id === "default" ? namespace : `${namespace}_${id}`, def))
106
+ }
107
+ }
108
+
109
+ const plugins = yield* plugin.list()
110
+ for (const p of plugins) {
111
+ for (const [id, def] of Object.entries(p.tool ?? {})) {
112
+ custom.push(fromPlugin(id, def))
113
+ }
114
+ }
115
+
116
+ return { custom }
117
+ }),
118
+ )
119
+
120
+ const all = Effect.fn("ToolRegistry.all")(function* (custom: Tool.Info[]) {
121
+ const cfg = yield* config.get()
122
+ const question = ["app", "cli", "desktop"].includes(Flag.OPENCODE_CLIENT) || Flag.OPENCODE_ENABLE_QUESTION_TOOL
123
+
124
+ return [
125
+ InvalidTool,
126
+ ...(question ? [QuestionTool] : []),
127
+ BashTool,
128
+ ReadTool,
129
+ GlobTool,
130
+ GrepTool,
131
+ EditTool,
132
+ WriteTool,
133
+ TaskTool,
134
+ WebFetchTool,
135
+ TodoWriteTool,
136
+ WebSearchTool,
137
+ CodeSearchTool,
138
+ SkillTool,
139
+ ApplyPatchTool,
140
+ SendMessageTool,
141
+ TeamTool,
142
+ ...(!Cron.isDisabled() ? [CronCreateTool, CronListTool, CronDeleteTool] : []),
143
+ ...(Flag.OPENCODE_EXPERIMENTAL_LSP_TOOL ? [LspTool] : []),
144
+ ...(cfg.experimental?.batch_tool === true ? [BatchTool] : []),
145
+ ...(Flag.OPENCODE_EXPERIMENTAL_PLAN_MODE && Flag.OPENCODE_CLIENT === "cli" ? [PlanExitTool] : []),
146
+ ...custom,
147
+ ]
148
+ })
149
+
150
+ const register = Effect.fn("ToolRegistry.register")(function* (tool: Tool.Info) {
151
+ const state = yield* InstanceState.get(cache)
152
+ const idx = state.custom.findIndex((t) => t.id === tool.id)
153
+ if (idx >= 0) {
154
+ state.custom.splice(idx, 1, tool)
155
+ return
156
+ }
157
+ state.custom.push(tool)
158
+ })
159
+
160
+ const ids = Effect.fn("ToolRegistry.ids")(function* () {
161
+ const state = yield* InstanceState.get(cache)
162
+ const tools = yield* all(state.custom)
163
+ return tools.map((t) => t.id)
164
+ })
165
+
166
+ const tools = Effect.fn("ToolRegistry.tools")(function* (
167
+ model: { providerID: ProviderID; modelID: ModelID },
168
+ agent?: Agent.Info,
169
+ ) {
170
+ const state = yield* InstanceState.get(cache)
171
+ const allTools = yield* all(state.custom)
172
+ const filtered = allTools.filter((tool) => {
173
+ if (tool.id === "codesearch" || tool.id === "websearch") {
174
+ return model.providerID === ProviderID.opencode || Flag.OPENCODE_ENABLE_EXA
175
+ }
176
+
177
+ const usePatch =
178
+ model.modelID.includes("gpt-") && !model.modelID.includes("oss") && !model.modelID.includes("gpt-4")
179
+ if (tool.id === "apply_patch") return usePatch
180
+ if (tool.id === "edit" || tool.id === "write") return !usePatch
181
+
182
+ return true
183
+ })
184
+ return yield* Effect.forEach(
185
+ filtered,
186
+ Effect.fnUntraced(function* (tool) {
187
+ using _ = log.time(tool.id)
188
+ const next = yield* Effect.promise(() => tool.init({ agent }))
189
+ const output = {
190
+ description: next.description,
191
+ parameters: next.parameters,
192
+ }
193
+ yield* plugin.trigger("tool.definition", { toolID: tool.id }, output)
194
+ return {
195
+ id: tool.id,
196
+ ...next,
197
+ description: output.description,
198
+ parameters: output.parameters,
199
+ } as Awaited<ReturnType<Tool.Info["init"]>> & { id: string }
200
+ }),
201
+ { concurrency: "unbounded" },
202
+ )
203
+ })
204
+
205
+ return Service.of({ register, ids, tools })
206
+ }),
207
+ )
208
+
209
+ export const defaultLayer = Layer.unwrap(
210
+ Effect.sync(() => layer.pipe(Layer.provide(Config.defaultLayer), Layer.provide(Plugin.defaultLayer))),
211
+ )
212
+
213
+ const { runPromise } = makeRuntime(Service, defaultLayer)
214
+
215
+ export async function register(tool: Tool.Info) {
216
+ return runPromise((svc) => svc.register(tool))
217
+ }
218
+
219
+ export async function ids() {
220
+ return runPromise((svc) => svc.ids())
221
+ }
222
+
223
+ export async function tools(
224
+ model: {
225
+ providerID: ProviderID
226
+ modelID: ModelID
227
+ },
228
+ agent?: Agent.Info,
229
+ ): Promise<(Awaited<ReturnType<Tool.Info["init"]>> & { id: string })[]> {
230
+ return runPromise((svc) => svc.tools(model, agent))
231
+ }
232
+ }
@@ -0,0 +1,17 @@
1
+ import { Schema } from "effect"
2
+ import z from "zod"
3
+
4
+ import { Identifier } from "@/id/id"
5
+ import { withStatics } from "@/util/schema"
6
+
7
+ const toolIdSchema = Schema.String.pipe(Schema.brand("ToolID"))
8
+
9
+ export type ToolID = typeof toolIdSchema.Type
10
+
11
+ export const ToolID = toolIdSchema.pipe(
12
+ withStatics((schema: typeof toolIdSchema) => ({
13
+ make: (id: string) => schema.makeUnsafe(id),
14
+ ascending: (id?: string) => schema.makeUnsafe(Identifier.ascending("tool", id)),
15
+ zod: Identifier.schema("tool").pipe(z.custom<ToolID>()),
16
+ })),
17
+ )
@@ -0,0 +1,59 @@
1
+ import z from "zod"
2
+ import { Tool } from "./tool"
3
+ import { Session } from "../session"
4
+ import { SessionID, MessageID } from "../session/schema"
5
+ import { SessionPrompt } from "../session/prompt"
6
+ import { Log } from "../util/log"
7
+ import DESCRIPTION from "./send-message.txt"
8
+
9
+ const log = Log.create({ service: "tool.send-message" })
10
+
11
+ export const SendMessageTool = Tool.define("send_message", {
12
+ description: DESCRIPTION,
13
+ parameters: z.object({
14
+ to: z.string().describe("The task_id (session ID) of the subagent to send the message to"),
15
+ message: z.string().describe("The message to send to the subagent"),
16
+ }),
17
+ async execute(params, ctx) {
18
+ const sessionID = SessionID.make(params.to)
19
+
20
+ // Verify the target session exists
21
+ const session = await Session.get(sessionID).catch(() => null)
22
+ if (!session) {
23
+ return {
24
+ title: "Agent not found",
25
+ output: `No subagent found with ID "${params.to}". Check the task_id from the original Agent invocation.`,
26
+ metadata: {},
27
+ }
28
+ }
29
+
30
+ const messageID = MessageID.ascending()
31
+ const promptParts = await SessionPrompt.resolvePromptParts(params.message)
32
+
33
+ // Resume the subagent in the background
34
+ SessionPrompt.prompt({
35
+ messageID,
36
+ sessionID,
37
+ parts: promptParts,
38
+ })
39
+ .then((result) => {
40
+ const text = result.parts.findLast((x) => x.type === "text")?.text ?? ""
41
+ log.info("resumed agent completed", { sessionID: params.to, resultLength: text.length })
42
+ })
43
+ .catch((err) => {
44
+ log.error("resumed agent failed", { sessionID: params.to, error: err })
45
+ })
46
+
47
+ return {
48
+ title: `Message sent to ${params.to}`,
49
+ output: [
50
+ `Message sent to subagent ${params.to}.`,
51
+ `The subagent is resuming in the background with its full context preserved.`,
52
+ `Session: ${session.title}`,
53
+ ].join("\n"),
54
+ metadata: {
55
+ sessionId: params.to,
56
+ },
57
+ }
58
+ },
59
+ })
@@ -0,0 +1,7 @@
1
+ Send a message to a running or stopped subagent to continue its work.
2
+
3
+ Use this tool to resume a previously spawned subagent by its session ID. The subagent resumes with its full context preserved — all previous tool calls, results, and reasoning are retained.
4
+
5
+ The "to" field should be the task_id (session ID) returned when the subagent was originally created. Each Agent invocation returns this ID.
6
+
7
+ If the subagent has stopped, it auto-resumes in the background. If it's still running, the message is queued.
@@ -0,0 +1,105 @@
1
+ import path from "path"
2
+ import { pathToFileURL } from "url"
3
+ import z from "zod"
4
+ import { Tool } from "./tool"
5
+ import { Skill } from "../skill"
6
+ import { Ripgrep } from "../file/ripgrep"
7
+ import { iife } from "@/util/iife"
8
+
9
+ export const SkillTool = Tool.define("skill", async (ctx) => {
10
+ const list = await Skill.available(ctx?.agent)
11
+
12
+ const description =
13
+ list.length === 0
14
+ ? "Load a specialized skill that provides domain-specific instructions and workflows. No skills are currently available."
15
+ : [
16
+ "Load a specialized skill that provides domain-specific instructions and workflows.",
17
+ "",
18
+ "When you recognize that a task matches one of the available skills listed below, use this tool to load the full skill instructions.",
19
+ "",
20
+ "The skill will inject detailed instructions, workflows, and access to bundled resources (scripts, references, templates) into the conversation context.",
21
+ "",
22
+ 'Tool output includes a `<skill_content name="...">` block with the loaded content.',
23
+ "",
24
+ "The following skills provide specialized sets of instructions for particular tasks",
25
+ "Invoke this tool to load a skill when a task matches one of the available skills listed below:",
26
+ "",
27
+ Skill.fmt(list, { verbose: false }),
28
+ ].join("\n")
29
+
30
+ const examples = list
31
+ .map((skill) => `'${skill.name}'`)
32
+ .slice(0, 3)
33
+ .join(", ")
34
+ const hint = examples.length > 0 ? ` (e.g., ${examples}, ...)` : ""
35
+
36
+ const parameters = z.object({
37
+ name: z.string().describe(`The name of the skill from available_skills${hint}`),
38
+ })
39
+
40
+ return {
41
+ description,
42
+ parameters,
43
+ async execute(params: z.infer<typeof parameters>, ctx) {
44
+ const skill = await Skill.get(params.name)
45
+
46
+ if (!skill) {
47
+ const available = await Skill.all().then((x) => x.map((skill) => skill.name).join(", "))
48
+ throw new Error(`Skill "${params.name}" not found. Available skills: ${available || "none"}`)
49
+ }
50
+
51
+ await ctx.ask({
52
+ permission: "skill",
53
+ patterns: [params.name],
54
+ always: [params.name],
55
+ metadata: {},
56
+ })
57
+
58
+ const dir = path.dirname(skill.location)
59
+ const base = pathToFileURL(dir).href
60
+
61
+ const limit = 10
62
+ const files = await iife(async () => {
63
+ const arr = []
64
+ for await (const file of Ripgrep.files({
65
+ cwd: dir,
66
+ follow: false,
67
+ hidden: true,
68
+ signal: ctx.abort,
69
+ })) {
70
+ if (file.includes("SKILL.md")) {
71
+ continue
72
+ }
73
+ arr.push(path.resolve(dir, file))
74
+ if (arr.length >= limit) {
75
+ break
76
+ }
77
+ }
78
+ return arr
79
+ }).then((f) => f.map((file) => `<file>${file}</file>`).join("\n"))
80
+
81
+ return {
82
+ title: `Loaded skill: ${skill.name}`,
83
+ output: [
84
+ `<skill_content name="${skill.name}">`,
85
+ `# Skill: ${skill.name}`,
86
+ "",
87
+ skill.content.trim(),
88
+ "",
89
+ `Base directory for this skill: ${base}`,
90
+ "Relative paths in this skill (e.g., scripts/, reference/) are relative to this base directory.",
91
+ "Note: file list is sampled.",
92
+ "",
93
+ "<skill_files>",
94
+ files,
95
+ "</skill_files>",
96
+ "</skill_content>",
97
+ ].join("\n"),
98
+ metadata: {
99
+ name: skill.name,
100
+ dir,
101
+ },
102
+ }
103
+ },
104
+ }
105
+ })
@@ -0,0 +1,230 @@
1
+ import { Tool } from "./tool"
2
+ import DESCRIPTION from "./task.txt"
3
+ import z from "zod"
4
+ import { Session } from "../session"
5
+ import { SessionID, MessageID } from "../session/schema"
6
+ import { MessageV2 } from "../session/message-v2"
7
+ import { Identifier } from "../id/id"
8
+ import { Agent } from "../agent/agent"
9
+ import { SessionPrompt } from "../session/prompt"
10
+ import { iife } from "@/util/iife"
11
+ import { defer } from "@/util/defer"
12
+ import { Config } from "../config/config"
13
+ import { Permission } from "@/permission"
14
+ import { Worktree } from "../worktree"
15
+ import { Instance } from "../project/instance"
16
+ import { Log } from "../util/log"
17
+
18
+ const log = Log.create({ service: "tool.task" })
19
+
20
+ const parameters = z.object({
21
+ description: z.string().describe("A short (3-5 words) description of the task"),
22
+ prompt: z.string().describe("The task for the agent to perform"),
23
+ subagent_type: z.string().describe("The type of specialized agent to use for this task"),
24
+ task_id: z
25
+ .string()
26
+ .describe(
27
+ "This should only be set if you mean to resume a previous task (you can pass a prior task_id and the task will continue the same subagent session as before instead of creating a fresh one)",
28
+ )
29
+ .optional(),
30
+ command: z.string().describe("The command that triggered this task").optional(),
31
+ run_in_background: z
32
+ .boolean()
33
+ .describe("Set to true to run this agent in the background. You will be notified when it completes.")
34
+ .optional(),
35
+ isolation: z
36
+ .enum(["worktree"])
37
+ .describe('Isolation mode. "worktree" creates a temporary git worktree so the agent works on an isolated copy of the repo.')
38
+ .optional(),
39
+ model: z
40
+ .enum(["sonnet", "opus", "haiku"])
41
+ .describe("Optional model override for this agent. If omitted, uses the agent definition's model, or inherits from the parent.")
42
+ .optional(),
43
+ })
44
+
45
+ export const TaskTool = Tool.define("task", async (ctx) => {
46
+ const agents = await Agent.list().then((x) => x.filter((a) => a.mode !== "primary"))
47
+
48
+ // Filter agents by permissions if agent provided
49
+ const caller = ctx?.agent
50
+ const accessibleAgents = caller
51
+ ? agents.filter((a) => Permission.evaluate("task", a.name, caller.permission).action !== "deny")
52
+ : agents
53
+ const list = accessibleAgents.toSorted((a, b) => a.name.localeCompare(b.name))
54
+
55
+ const description = DESCRIPTION.replace(
56
+ "{agents}",
57
+ list
58
+ .map((a) => `- ${a.name}: ${a.description ?? "This subagent should only be called manually by the user."}`)
59
+ .join("\n"),
60
+ )
61
+ return {
62
+ description,
63
+ parameters,
64
+ async execute(params: z.infer<typeof parameters>, ctx) {
65
+ const config = await Config.get()
66
+
67
+ // Skip permission check when user explicitly invoked via @ or command subtask
68
+ if (!ctx.extra?.bypassAgentCheck) {
69
+ await ctx.ask({
70
+ permission: "task",
71
+ patterns: [params.subagent_type],
72
+ always: ["*"],
73
+ metadata: {
74
+ description: params.description,
75
+ subagent_type: params.subagent_type,
76
+ },
77
+ })
78
+ }
79
+
80
+ const agent = await Agent.get(params.subagent_type)
81
+ if (!agent) throw new Error(`Unknown agent type: ${params.subagent_type} is not a valid agent type`)
82
+
83
+ const hasTaskPermission = agent.permission.some((rule) => rule.permission === "task")
84
+ const hasTodoWritePermission = agent.permission.some((rule) => rule.permission === "todowrite")
85
+
86
+ const session = await iife(async () => {
87
+ if (params.task_id) {
88
+ const found = await Session.get(SessionID.make(params.task_id)).catch(() => {})
89
+ if (found) return found
90
+ }
91
+
92
+ return await Session.create({
93
+ parentID: ctx.sessionID,
94
+ title: params.description + ` (@${agent.name} subagent)`,
95
+ permission: [
96
+ ...(hasTodoWritePermission
97
+ ? []
98
+ : [
99
+ {
100
+ permission: "todowrite" as const,
101
+ pattern: "*" as const,
102
+ action: "deny" as const,
103
+ },
104
+ ]),
105
+ ...(hasTaskPermission
106
+ ? []
107
+ : [
108
+ {
109
+ permission: "task" as const,
110
+ pattern: "*" as const,
111
+ action: "deny" as const,
112
+ },
113
+ ]),
114
+ ...(config.experimental?.primary_tools?.map((t) => ({
115
+ pattern: "*",
116
+ action: "allow" as const,
117
+ permission: t,
118
+ })) ?? []),
119
+ ],
120
+ })
121
+ })
122
+ const msg = await MessageV2.get({ sessionID: ctx.sessionID, messageID: ctx.messageID })
123
+ if (msg.info.role !== "assistant") throw new Error("Not an assistant message")
124
+
125
+ // Resolve model: CLI param > agent definition > parent model
126
+ const model = iife(() => {
127
+ if (params.model) {
128
+ // Map alias to provider/model — uses Toolkit models by default
129
+ const modelMap: Record<string, { providerID: string; modelID: string }> = {
130
+ haiku: { providerID: "toolkit", modelID: "toolkit-code-fast" },
131
+ sonnet: { providerID: "toolkit", modelID: "toolkit-base" },
132
+ opus: { providerID: "toolkit", modelID: "toolkit-code-backend" },
133
+ }
134
+ const mapped = modelMap[params.model]
135
+ if (mapped) return { providerID: mapped.providerID as any, modelID: mapped.modelID as any }
136
+ }
137
+ return agent.model ?? { modelID: msg.info.modelID, providerID: msg.info.providerID }
138
+ })
139
+
140
+ ctx.metadata({
141
+ title: params.description,
142
+ metadata: {
143
+ sessionId: session.id,
144
+ model,
145
+ background: params.run_in_background ?? false,
146
+ isolation: params.isolation,
147
+ },
148
+ })
149
+
150
+ // Build the prompt function
151
+ async function runPrompt() {
152
+ const messageID = MessageID.ascending()
153
+ const promptParts = await SessionPrompt.resolvePromptParts(params.prompt)
154
+
155
+ return SessionPrompt.prompt({
156
+ messageID,
157
+ sessionID: session.id,
158
+ model: {
159
+ modelID: model.modelID,
160
+ providerID: model.providerID,
161
+ },
162
+ agent: agent.name,
163
+ tools: {
164
+ ...(hasTodoWritePermission ? {} : { todowrite: false }),
165
+ ...(hasTaskPermission ? {} : { task: false }),
166
+ ...Object.fromEntries((config.experimental?.primary_tools ?? []).map((t) => [t, false])),
167
+ },
168
+ parts: promptParts,
169
+ })
170
+ }
171
+
172
+ // Background execution: fire and return immediately
173
+ if (params.run_in_background) {
174
+ runPrompt()
175
+ .then((result) => {
176
+ const text = result.parts.findLast((x) => x.type === "text")?.text ?? ""
177
+ log.info("background agent completed", { taskId: session.id, agent: agent.name, resultLength: text.length })
178
+ })
179
+ .catch((err) => {
180
+ log.error("background agent failed", { taskId: session.id, error: err })
181
+ })
182
+
183
+ return {
184
+ title: params.description,
185
+ metadata: {
186
+ sessionId: session.id,
187
+ model,
188
+ background: true,
189
+ },
190
+ output: [
191
+ `Background agent launched.`,
192
+ `task_id: ${session.id}`,
193
+ `agent: ${agent.name}`,
194
+ `model: ${model.providerID}/${model.modelID}`,
195
+ ``,
196
+ `The agent is working in the background. Use SendMessage with to: '${session.id}' to continue this agent.`,
197
+ ].join("\n"),
198
+ }
199
+ }
200
+
201
+ // Foreground execution
202
+ function cancel() {
203
+ SessionPrompt.cancel(session.id)
204
+ }
205
+ ctx.abort.addEventListener("abort", cancel)
206
+ using _ = defer(() => ctx.abort.removeEventListener("abort", cancel))
207
+
208
+ const result = await runPrompt()
209
+
210
+ const text = result.parts.findLast((x) => x.type === "text")?.text ?? ""
211
+
212
+ const output = [
213
+ `task_id: ${session.id} (for resuming to continue this task if needed)`,
214
+ "",
215
+ "<task_result>",
216
+ text,
217
+ "</task_result>",
218
+ ].join("\n")
219
+
220
+ return {
221
+ title: params.description,
222
+ metadata: {
223
+ sessionId: session.id,
224
+ model,
225
+ },
226
+ output,
227
+ }
228
+ },
229
+ }
230
+ })