easc-cli 1.1.28

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 (404) hide show
  1. package/AGENTS.md +27 -0
  2. package/Dockerfile +18 -0
  3. package/README.md +15 -0
  4. package/bin/opencode +108 -0
  5. package/bunfig.toml +7 -0
  6. package/package.json +132 -0
  7. package/parsers-config.ts +253 -0
  8. package/script/build.ts +172 -0
  9. package/script/deploy.ts +64 -0
  10. package/script/postinstall.mjs +125 -0
  11. package/script/publish-registries.ts +187 -0
  12. package/script/publish.ts +70 -0
  13. package/script/schema.ts +47 -0
  14. package/script/seed-e2e.ts +50 -0
  15. package/src/acp/README.md +164 -0
  16. package/src/acp/agent.ts +1285 -0
  17. package/src/acp/session.ts +105 -0
  18. package/src/acp/types.ts +22 -0
  19. package/src/agent/agent.ts +332 -0
  20. package/src/agent/generate.txt +75 -0
  21. package/src/agent/prompt/compaction.txt +12 -0
  22. package/src/agent/prompt/explore.txt +18 -0
  23. package/src/agent/prompt/summary.txt +11 -0
  24. package/src/agent/prompt/title.txt +43 -0
  25. package/src/auth/eliseart.ts +76 -0
  26. package/src/auth/index.ts +73 -0
  27. package/src/bun/index.ts +134 -0
  28. package/src/bus/bus-event.ts +43 -0
  29. package/src/bus/global.ts +10 -0
  30. package/src/bus/index.ts +105 -0
  31. package/src/cli/bootstrap.ts +17 -0
  32. package/src/cli/cmd/account.ts +81 -0
  33. package/src/cli/cmd/acp.ts +69 -0
  34. package/src/cli/cmd/agent.ts +257 -0
  35. package/src/cli/cmd/auth.ts +427 -0
  36. package/src/cli/cmd/cmd.ts +7 -0
  37. package/src/cli/cmd/debug/agent.ts +166 -0
  38. package/src/cli/cmd/debug/config.ts +16 -0
  39. package/src/cli/cmd/debug/file.ts +97 -0
  40. package/src/cli/cmd/debug/index.ts +48 -0
  41. package/src/cli/cmd/debug/lsp.ts +52 -0
  42. package/src/cli/cmd/debug/ripgrep.ts +87 -0
  43. package/src/cli/cmd/debug/scrap.ts +16 -0
  44. package/src/cli/cmd/debug/skill.ts +16 -0
  45. package/src/cli/cmd/debug/snapshot.ts +52 -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 +1548 -0
  49. package/src/cli/cmd/import.ts +98 -0
  50. package/src/cli/cmd/mcp.ts +827 -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 +407 -0
  54. package/src/cli/cmd/serve.ts +20 -0
  55. package/src/cli/cmd/session.ts +135 -0
  56. package/src/cli/cmd/stats.ts +402 -0
  57. package/src/cli/cmd/tui/app.tsx +774 -0
  58. package/src/cli/cmd/tui/attach.ts +31 -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 +148 -0
  62. package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
  63. package/src/cli/cmd/tui/component/dialog-model.tsx +234 -0
  64. package/src/cli/cmd/tui/component/dialog-provider.tsx +256 -0
  65. package/src/cli/cmd/tui/component/dialog-session-list.tsx +114 -0
  66. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
  67. package/src/cli/cmd/tui/component/dialog-stash.tsx +87 -0
  68. package/src/cli/cmd/tui/component/dialog-status.tsx +164 -0
  69. package/src/cli/cmd/tui/component/dialog-supabase.tsx +102 -0
  70. package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
  71. package/src/cli/cmd/tui/component/dialog-theme-list.tsx +50 -0
  72. package/src/cli/cmd/tui/component/logo.tsx +88 -0
  73. package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +653 -0
  74. package/src/cli/cmd/tui/component/prompt/frecency.tsx +89 -0
  75. package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
  76. package/src/cli/cmd/tui/component/prompt/index.tsx +1182 -0
  77. package/src/cli/cmd/tui/component/prompt/stash.tsx +101 -0
  78. package/src/cli/cmd/tui/component/spinner.tsx +16 -0
  79. package/src/cli/cmd/tui/component/textarea-keybindings.ts +73 -0
  80. package/src/cli/cmd/tui/component/tips.tsx +153 -0
  81. package/src/cli/cmd/tui/component/todo-item.tsx +32 -0
  82. package/src/cli/cmd/tui/context/args.tsx +14 -0
  83. package/src/cli/cmd/tui/context/directory.ts +13 -0
  84. package/src/cli/cmd/tui/context/exit.tsx +23 -0
  85. package/src/cli/cmd/tui/context/helper.tsx +25 -0
  86. package/src/cli/cmd/tui/context/keybind.tsx +101 -0
  87. package/src/cli/cmd/tui/context/kv.tsx +52 -0
  88. package/src/cli/cmd/tui/context/local.tsx +402 -0
  89. package/src/cli/cmd/tui/context/prompt.tsx +18 -0
  90. package/src/cli/cmd/tui/context/route.tsx +46 -0
  91. package/src/cli/cmd/tui/context/sdk.tsx +94 -0
  92. package/src/cli/cmd/tui/context/sync.tsx +445 -0
  93. package/src/cli/cmd/tui/context/theme/aura.json +69 -0
  94. package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
  95. package/src/cli/cmd/tui/context/theme/carbonfox.json +248 -0
  96. package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +233 -0
  97. package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +233 -0
  98. package/src/cli/cmd/tui/context/theme/catppuccin.json +112 -0
  99. package/src/cli/cmd/tui/context/theme/cobalt2.json +228 -0
  100. package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
  101. package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
  102. package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
  103. package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
  104. package/src/cli/cmd/tui/context/theme/github.json +233 -0
  105. package/src/cli/cmd/tui/context/theme/gruvbox.json +95 -0
  106. package/src/cli/cmd/tui/context/theme/kanagawa.json +77 -0
  107. package/src/cli/cmd/tui/context/theme/lucent-orng.json +237 -0
  108. package/src/cli/cmd/tui/context/theme/material.json +235 -0
  109. package/src/cli/cmd/tui/context/theme/matrix.json +77 -0
  110. package/src/cli/cmd/tui/context/theme/mercury.json +252 -0
  111. package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
  112. package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
  113. package/src/cli/cmd/tui/context/theme/nord.json +223 -0
  114. package/src/cli/cmd/tui/context/theme/one-dark.json +84 -0
  115. package/src/cli/cmd/tui/context/theme/orng.json +249 -0
  116. package/src/cli/cmd/tui/context/theme/osaka-jade.json +93 -0
  117. package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
  118. package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
  119. package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
  120. package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
  121. package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
  122. package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
  123. package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
  124. package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
  125. package/src/cli/cmd/tui/context/theme.tsx +1152 -0
  126. package/src/cli/cmd/tui/event.ts +48 -0
  127. package/src/cli/cmd/tui/routes/home.tsx +140 -0
  128. package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +64 -0
  129. package/src/cli/cmd/tui/routes/session/dialog-message.tsx +109 -0
  130. package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +26 -0
  131. package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
  132. package/src/cli/cmd/tui/routes/session/dialog-tool.tsx +63 -0
  133. package/src/cli/cmd/tui/routes/session/footer.tsx +129 -0
  134. package/src/cli/cmd/tui/routes/session/header.tsx +136 -0
  135. package/src/cli/cmd/tui/routes/session/index.tsx +2132 -0
  136. package/src/cli/cmd/tui/routes/session/permission.tsx +495 -0
  137. package/src/cli/cmd/tui/routes/session/question.tsx +435 -0
  138. package/src/cli/cmd/tui/routes/session/sidebar.tsx +313 -0
  139. package/src/cli/cmd/tui/thread.ts +165 -0
  140. package/src/cli/cmd/tui/ui/dialog-alert.tsx +57 -0
  141. package/src/cli/cmd/tui/ui/dialog-confirm.tsx +83 -0
  142. package/src/cli/cmd/tui/ui/dialog-export-options.tsx +204 -0
  143. package/src/cli/cmd/tui/ui/dialog-help.tsx +38 -0
  144. package/src/cli/cmd/tui/ui/dialog-prompt.tsx +77 -0
  145. package/src/cli/cmd/tui/ui/dialog-select.tsx +376 -0
  146. package/src/cli/cmd/tui/ui/dialog.tsx +167 -0
  147. package/src/cli/cmd/tui/ui/link.tsx +28 -0
  148. package/src/cli/cmd/tui/ui/spinner.ts +368 -0
  149. package/src/cli/cmd/tui/ui/toast.tsx +100 -0
  150. package/src/cli/cmd/tui/util/clipboard.ts +160 -0
  151. package/src/cli/cmd/tui/util/editor.ts +32 -0
  152. package/src/cli/cmd/tui/util/signal.ts +7 -0
  153. package/src/cli/cmd/tui/util/terminal.ts +114 -0
  154. package/src/cli/cmd/tui/util/transcript.ts +98 -0
  155. package/src/cli/cmd/tui/worker.ts +152 -0
  156. package/src/cli/cmd/uninstall.ts +357 -0
  157. package/src/cli/cmd/upgrade.ts +73 -0
  158. package/src/cli/cmd/web.ts +81 -0
  159. package/src/cli/error.ts +57 -0
  160. package/src/cli/network.ts +53 -0
  161. package/src/cli/ui.ts +84 -0
  162. package/src/cli/upgrade.ts +25 -0
  163. package/src/command/index.ts +131 -0
  164. package/src/command/template/initialize.txt +10 -0
  165. package/src/command/template/review.txt +99 -0
  166. package/src/config/config.ts +1361 -0
  167. package/src/config/markdown.ts +93 -0
  168. package/src/env/index.ts +26 -0
  169. package/src/file/ignore.ts +83 -0
  170. package/src/file/index.ts +411 -0
  171. package/src/file/ripgrep.ts +407 -0
  172. package/src/file/time.ts +64 -0
  173. package/src/file/watcher.ts +127 -0
  174. package/src/flag/flag.ts +54 -0
  175. package/src/format/formatter.ts +342 -0
  176. package/src/format/index.ts +137 -0
  177. package/src/global/index.ts +55 -0
  178. package/src/id/id.ts +83 -0
  179. package/src/ide/index.ts +76 -0
  180. package/src/index.ts +162 -0
  181. package/src/installation/index.ts +246 -0
  182. package/src/lsp/client.ts +252 -0
  183. package/src/lsp/index.ts +485 -0
  184. package/src/lsp/language.ts +119 -0
  185. package/src/lsp/server.ts +2046 -0
  186. package/src/mcp/auth.ts +135 -0
  187. package/src/mcp/index.ts +931 -0
  188. package/src/mcp/oauth-callback.ts +200 -0
  189. package/src/mcp/oauth-provider.ts +154 -0
  190. package/src/patch/index.ts +680 -0
  191. package/src/permission/arity.ts +163 -0
  192. package/src/permission/index.ts +210 -0
  193. package/src/permission/next.ts +269 -0
  194. package/src/plugin/codex.ts +493 -0
  195. package/src/plugin/copilot.ts +269 -0
  196. package/src/plugin/index.ts +135 -0
  197. package/src/project/bootstrap.ts +35 -0
  198. package/src/project/instance.ts +91 -0
  199. package/src/project/project.ts +339 -0
  200. package/src/project/state.ts +66 -0
  201. package/src/project/vcs.ts +76 -0
  202. package/src/provider/auth.ts +147 -0
  203. package/src/provider/models-macro.ts +11 -0
  204. package/src/provider/models.ts +112 -0
  205. package/src/provider/provider.ts +1391 -0
  206. package/src/provider/sdk/openai-compatible/src/README.md +5 -0
  207. package/src/provider/sdk/openai-compatible/src/index.ts +2 -0
  208. package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +100 -0
  209. package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +303 -0
  210. package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +22 -0
  211. package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +18 -0
  212. package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +22 -0
  213. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +207 -0
  214. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +1732 -0
  215. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +177 -0
  216. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +1 -0
  217. package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +88 -0
  218. package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +128 -0
  219. package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +115 -0
  220. package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +65 -0
  221. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +104 -0
  222. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +103 -0
  223. package/src/provider/transform.ts +733 -0
  224. package/src/pty/index.ts +232 -0
  225. package/src/question/index.ts +171 -0
  226. package/src/scheduler/index.ts +61 -0
  227. package/src/server/error.ts +36 -0
  228. package/src/server/event.ts +7 -0
  229. package/src/server/mdns.ts +59 -0
  230. package/src/server/routes/config.ts +92 -0
  231. package/src/server/routes/experimental.ts +208 -0
  232. package/src/server/routes/file.ts +197 -0
  233. package/src/server/routes/global.ts +135 -0
  234. package/src/server/routes/mcp.ts +361 -0
  235. package/src/server/routes/permission.ts +68 -0
  236. package/src/server/routes/project.ts +82 -0
  237. package/src/server/routes/provider.ts +165 -0
  238. package/src/server/routes/pty.ts +169 -0
  239. package/src/server/routes/question.ts +98 -0
  240. package/src/server/routes/session.ts +935 -0
  241. package/src/server/routes/tui.ts +379 -0
  242. package/src/server/server.ts +573 -0
  243. package/src/session/compaction.ts +225 -0
  244. package/src/session/index.ts +488 -0
  245. package/src/session/llm.ts +279 -0
  246. package/src/session/message-v2.ts +702 -0
  247. package/src/session/message.ts +189 -0
  248. package/src/session/processor.ts +406 -0
  249. package/src/session/prompt/anthropic-20250930.txt +166 -0
  250. package/src/session/prompt/anthropic.txt +105 -0
  251. package/src/session/prompt/anthropic_spoof.txt +1 -0
  252. package/src/session/prompt/beast.txt +147 -0
  253. package/src/session/prompt/build-switch.txt +5 -0
  254. package/src/session/prompt/codex_header.txt +79 -0
  255. package/src/session/prompt/copilot-gpt-5.txt +143 -0
  256. package/src/session/prompt/gemini.txt +155 -0
  257. package/src/session/prompt/max-steps.txt +16 -0
  258. package/src/session/prompt/plan-reminder-anthropic.txt +67 -0
  259. package/src/session/prompt/plan.txt +26 -0
  260. package/src/session/prompt/qwen.txt +109 -0
  261. package/src/session/prompt.ts +1820 -0
  262. package/src/session/retry.ts +90 -0
  263. package/src/session/revert.ts +108 -0
  264. package/src/session/status.ts +76 -0
  265. package/src/session/summary.ts +150 -0
  266. package/src/session/system.ts +152 -0
  267. package/src/session/todo.ts +37 -0
  268. package/src/share/share-next.ts +200 -0
  269. package/src/share/share.ts +92 -0
  270. package/src/shell/shell.ts +67 -0
  271. package/src/skill/index.ts +1 -0
  272. package/src/skill/skill.ts +136 -0
  273. package/src/snapshot/index.ts +236 -0
  274. package/src/storage/storage.ts +227 -0
  275. package/src/tool/apply_patch.ts +269 -0
  276. package/src/tool/apply_patch.txt +33 -0
  277. package/src/tool/bash.ts +259 -0
  278. package/src/tool/bash.txt +115 -0
  279. package/src/tool/batch.ts +175 -0
  280. package/src/tool/batch.txt +24 -0
  281. package/src/tool/codesearch.ts +132 -0
  282. package/src/tool/codesearch.txt +12 -0
  283. package/src/tool/edit.ts +645 -0
  284. package/src/tool/edit.txt +10 -0
  285. package/src/tool/external-directory.ts +32 -0
  286. package/src/tool/glob.ts +77 -0
  287. package/src/tool/glob.txt +6 -0
  288. package/src/tool/grep.ts +154 -0
  289. package/src/tool/grep.txt +8 -0
  290. package/src/tool/invalid.ts +17 -0
  291. package/src/tool/ls.ts +121 -0
  292. package/src/tool/ls.txt +1 -0
  293. package/src/tool/lsp.ts +96 -0
  294. package/src/tool/lsp.txt +19 -0
  295. package/src/tool/multiedit.ts +46 -0
  296. package/src/tool/multiedit.txt +41 -0
  297. package/src/tool/plan-enter.txt +14 -0
  298. package/src/tool/plan-exit.txt +13 -0
  299. package/src/tool/plan.ts +130 -0
  300. package/src/tool/question.ts +33 -0
  301. package/src/tool/question.txt +10 -0
  302. package/src/tool/read.ts +202 -0
  303. package/src/tool/read.txt +12 -0
  304. package/src/tool/registry.ts +163 -0
  305. package/src/tool/skill.ts +75 -0
  306. package/src/tool/task.ts +188 -0
  307. package/src/tool/task.txt +60 -0
  308. package/src/tool/todo.ts +53 -0
  309. package/src/tool/todoread.txt +14 -0
  310. package/src/tool/todowrite.txt +167 -0
  311. package/src/tool/tool.ts +88 -0
  312. package/src/tool/truncation.ts +106 -0
  313. package/src/tool/webfetch.ts +182 -0
  314. package/src/tool/webfetch.txt +13 -0
  315. package/src/tool/websearch.ts +150 -0
  316. package/src/tool/websearch.txt +14 -0
  317. package/src/tool/write.ts +80 -0
  318. package/src/tool/write.txt +8 -0
  319. package/src/util/archive.ts +16 -0
  320. package/src/util/color.ts +19 -0
  321. package/src/util/context.ts +25 -0
  322. package/src/util/defer.ts +12 -0
  323. package/src/util/eventloop.ts +20 -0
  324. package/src/util/filesystem.ts +93 -0
  325. package/src/util/fn.ts +11 -0
  326. package/src/util/format.ts +20 -0
  327. package/src/util/iife.ts +3 -0
  328. package/src/util/keybind.ts +103 -0
  329. package/src/util/lazy.ts +18 -0
  330. package/src/util/locale.ts +81 -0
  331. package/src/util/lock.ts +98 -0
  332. package/src/util/log.ts +180 -0
  333. package/src/util/queue.ts +32 -0
  334. package/src/util/rpc.ts +66 -0
  335. package/src/util/scrap.ts +10 -0
  336. package/src/util/signal.ts +12 -0
  337. package/src/util/timeout.ts +14 -0
  338. package/src/util/token.ts +7 -0
  339. package/src/util/wildcard.ts +56 -0
  340. package/src/worktree/index.ts +424 -0
  341. package/sst-env.d.ts +9 -0
  342. package/test/acp/event-subscription.test.ts +436 -0
  343. package/test/agent/agent.test.ts +638 -0
  344. package/test/bun.test.ts +53 -0
  345. package/test/cli/github-action.test.ts +129 -0
  346. package/test/cli/github-remote.test.ts +80 -0
  347. package/test/cli/tui/transcript.test.ts +297 -0
  348. package/test/config/agent-color.test.ts +66 -0
  349. package/test/config/config.test.ts +1414 -0
  350. package/test/config/fixtures/empty-frontmatter.md +4 -0
  351. package/test/config/fixtures/frontmatter.md +28 -0
  352. package/test/config/fixtures/no-frontmatter.md +1 -0
  353. package/test/config/markdown.test.ts +192 -0
  354. package/test/file/ignore.test.ts +10 -0
  355. package/test/file/path-traversal.test.ts +198 -0
  356. package/test/fixture/fixture.ts +45 -0
  357. package/test/fixture/lsp/fake-lsp-server.js +77 -0
  358. package/test/ide/ide.test.ts +82 -0
  359. package/test/keybind.test.ts +421 -0
  360. package/test/lsp/client.test.ts +95 -0
  361. package/test/mcp/headers.test.ts +153 -0
  362. package/test/mcp/oauth-browser.test.ts +261 -0
  363. package/test/patch/patch.test.ts +348 -0
  364. package/test/permission/arity.test.ts +33 -0
  365. package/test/permission/next.test.ts +652 -0
  366. package/test/permission-task.test.ts +319 -0
  367. package/test/plugin/codex.test.ts +123 -0
  368. package/test/preload.ts +65 -0
  369. package/test/project/project.test.ts +120 -0
  370. package/test/provider/amazon-bedrock.test.ts +268 -0
  371. package/test/provider/gitlab-duo.test.ts +286 -0
  372. package/test/provider/provider.test.ts +2149 -0
  373. package/test/provider/transform.test.ts +1596 -0
  374. package/test/question/question.test.ts +300 -0
  375. package/test/scheduler.test.ts +73 -0
  376. package/test/server/session-list.test.ts +39 -0
  377. package/test/server/session-select.test.ts +78 -0
  378. package/test/session/compaction.test.ts +293 -0
  379. package/test/session/llm.test.ts +90 -0
  380. package/test/session/message-v2.test.ts +662 -0
  381. package/test/session/retry.test.ts +131 -0
  382. package/test/session/revert-compact.test.ts +285 -0
  383. package/test/session/session.test.ts +71 -0
  384. package/test/skill/skill.test.ts +185 -0
  385. package/test/snapshot/snapshot.test.ts +939 -0
  386. package/test/tool/__snapshots__/tool.test.ts.snap +9 -0
  387. package/test/tool/apply_patch.test.ts +499 -0
  388. package/test/tool/bash.test.ts +320 -0
  389. package/test/tool/external-directory.test.ts +126 -0
  390. package/test/tool/fixtures/large-image.png +0 -0
  391. package/test/tool/fixtures/models-api.json +33453 -0
  392. package/test/tool/grep.test.ts +109 -0
  393. package/test/tool/question.test.ts +105 -0
  394. package/test/tool/read.test.ts +332 -0
  395. package/test/tool/registry.test.ts +76 -0
  396. package/test/tool/truncation.test.ts +159 -0
  397. package/test/util/filesystem.test.ts +39 -0
  398. package/test/util/format.test.ts +59 -0
  399. package/test/util/iife.test.ts +36 -0
  400. package/test/util/lazy.test.ts +50 -0
  401. package/test/util/lock.test.ts +72 -0
  402. package/test/util/timeout.test.ts +21 -0
  403. package/test/util/wildcard.test.ts +75 -0
  404. package/tsconfig.json +16 -0
@@ -0,0 +1,361 @@
1
+ import { Hono } from "hono"
2
+ import { describeRoute, validator, resolver } from "hono-openapi"
3
+ import z from "zod"
4
+ import { MCP } from "../../mcp"
5
+ import { Config } from "../../config/config"
6
+ import { Instance } from "../../project/instance"
7
+ import { errors } from "../error"
8
+ import { lazy } from "../../util/lazy"
9
+
10
+ export const McpRoutes = lazy(() =>
11
+ new Hono()
12
+ .get(
13
+ "/",
14
+ describeRoute({
15
+ summary: "Get MCP status",
16
+ description: "Get the status of all Model Context Protocol (MCP) servers.",
17
+ operationId: "mcp.status",
18
+ responses: {
19
+ 200: {
20
+ description: "MCP server status",
21
+ content: {
22
+ "application/json": {
23
+ schema: resolver(z.record(z.string(), MCP.Status)),
24
+ },
25
+ },
26
+ },
27
+ },
28
+ }),
29
+ async (c) => {
30
+ return c.json(await MCP.status())
31
+ },
32
+ )
33
+ .post(
34
+ "/",
35
+ describeRoute({
36
+ summary: "Add MCP server",
37
+ description: "Dynamically add a new Model Context Protocol (MCP) server to the system.",
38
+ operationId: "mcp.add",
39
+ responses: {
40
+ 200: {
41
+ description: "MCP server added successfully",
42
+ content: {
43
+ "application/json": {
44
+ schema: resolver(z.record(z.string(), MCP.Status)),
45
+ },
46
+ },
47
+ },
48
+ ...errors(400),
49
+ },
50
+ }),
51
+ validator(
52
+ "json",
53
+ z.object({
54
+ name: z.string(),
55
+ config: Config.Mcp,
56
+ }),
57
+ ),
58
+ async (c) => {
59
+ const { name, config } = c.req.valid("json")
60
+ const result = await MCP.add(name, config)
61
+ return c.json(result.status)
62
+ },
63
+ )
64
+ .post(
65
+ "/:name/auth",
66
+ describeRoute({
67
+ summary: "Start MCP OAuth",
68
+ description: "Start OAuth authentication flow for a Model Context Protocol (MCP) server.",
69
+ operationId: "mcp.auth.start",
70
+ responses: {
71
+ 200: {
72
+ description: "OAuth flow started",
73
+ content: {
74
+ "application/json": {
75
+ schema: resolver(
76
+ z.object({
77
+ authorizationUrl: z.string().describe("URL to open in browser for authorization"),
78
+ }),
79
+ ),
80
+ },
81
+ },
82
+ },
83
+ ...errors(400, 404),
84
+ },
85
+ }),
86
+ async (c) => {
87
+ const name = c.req.param("name")
88
+ const supportsOAuth = await MCP.supportsOAuth(name)
89
+ if (!supportsOAuth) {
90
+ return c.json({ error: `MCP server ${name} does not support OAuth` }, 400)
91
+ }
92
+ const result = await MCP.startAuth(name)
93
+ return c.json(result)
94
+ },
95
+ )
96
+ .post(
97
+ "/:name/auth/callback",
98
+ describeRoute({
99
+ summary: "Complete MCP OAuth",
100
+ description:
101
+ "Complete OAuth authentication for a Model Context Protocol (MCP) server using the authorization code.",
102
+ operationId: "mcp.auth.callback",
103
+ responses: {
104
+ 200: {
105
+ description: "OAuth authentication completed",
106
+ content: {
107
+ "application/json": {
108
+ schema: resolver(MCP.Status),
109
+ },
110
+ },
111
+ },
112
+ ...errors(400, 404),
113
+ },
114
+ }),
115
+ validator(
116
+ "json",
117
+ z.object({
118
+ code: z.string().describe("Authorization code from OAuth callback"),
119
+ }),
120
+ ),
121
+ async (c) => {
122
+ const name = c.req.param("name")
123
+ const { code } = c.req.valid("json")
124
+ const status = await MCP.finishAuth(name, code)
125
+ return c.json(status)
126
+ },
127
+ )
128
+ .post(
129
+ "/:name/auth/authenticate",
130
+ describeRoute({
131
+ summary: "Authenticate MCP OAuth",
132
+ description: "Start OAuth flow and wait for callback (opens browser)",
133
+ operationId: "mcp.auth.authenticate",
134
+ responses: {
135
+ 200: {
136
+ description: "OAuth authentication completed",
137
+ content: {
138
+ "application/json": {
139
+ schema: resolver(MCP.Status),
140
+ },
141
+ },
142
+ },
143
+ ...errors(400, 404),
144
+ },
145
+ }),
146
+ async (c) => {
147
+ const name = c.req.param("name")
148
+ const supportsOAuth = await MCP.supportsOAuth(name)
149
+ if (!supportsOAuth) {
150
+ return c.json({ error: `MCP server ${name} does not support OAuth` }, 400)
151
+ }
152
+ const status = await MCP.authenticate(name)
153
+ return c.json(status)
154
+ },
155
+ )
156
+ .delete(
157
+ "/:name/auth",
158
+ describeRoute({
159
+ summary: "Remove MCP OAuth",
160
+ description: "Remove OAuth credentials for an MCP server",
161
+ operationId: "mcp.auth.remove",
162
+ responses: {
163
+ 200: {
164
+ description: "OAuth credentials removed",
165
+ content: {
166
+ "application/json": {
167
+ schema: resolver(z.object({ success: z.literal(true) })),
168
+ },
169
+ },
170
+ },
171
+ ...errors(404),
172
+ },
173
+ }),
174
+ async (c) => {
175
+ const name = c.req.param("name")
176
+ await MCP.removeAuth(name)
177
+ return c.json({ success: true as const })
178
+ },
179
+ )
180
+ .post(
181
+ "/:name/connect",
182
+ describeRoute({
183
+ description: "Connect an MCP server",
184
+ operationId: "mcp.connect",
185
+ responses: {
186
+ 200: {
187
+ description: "MCP server connected successfully",
188
+ content: {
189
+ "application/json": {
190
+ schema: resolver(z.boolean()),
191
+ },
192
+ },
193
+ },
194
+ },
195
+ }),
196
+ validator("param", z.object({ name: z.string() })),
197
+ async (c) => {
198
+ const { name } = c.req.valid("param")
199
+ await MCP.connect(name)
200
+ return c.json(true)
201
+ },
202
+ )
203
+ .post(
204
+ "/:name/disconnect",
205
+ describeRoute({
206
+ description: "Disconnect an MCP server",
207
+ operationId: "mcp.disconnect",
208
+ responses: {
209
+ 200: {
210
+ description: "MCP server disconnected successfully",
211
+ content: {
212
+ "application/json": {
213
+ schema: resolver(z.boolean()),
214
+ },
215
+ },
216
+ },
217
+ },
218
+ }),
219
+ validator("param", z.object({ name: z.string() })),
220
+ async (c) => {
221
+ const { name } = c.req.valid("param")
222
+ await MCP.disconnect(name)
223
+ return c.json(true)
224
+ },
225
+ )
226
+ .get(
227
+ "/supabase/projects",
228
+ describeRoute({
229
+ summary: "List Supabase projects",
230
+ description: "Fetch list of Supabase projects using the configured ACCESS_TOKEN",
231
+ operationId: "mcp.supabase.projects",
232
+ responses: {
233
+ 200: {
234
+ description: "List of projects",
235
+ },
236
+ },
237
+ }),
238
+ async (c) => {
239
+ try {
240
+ const cfg = await Config.get()
241
+ let token = process.env.SUPABASE_ACCESS_TOKEN
242
+ if (!token && cfg.mcp) {
243
+ for (const mcp of Object.values(cfg.mcp)) {
244
+ if (
245
+ typeof mcp === "object" &&
246
+ "type" in mcp &&
247
+ mcp.type === "local" &&
248
+ (mcp as any).environment?.["SUPABASE_ACCESS_TOKEN"]
249
+ ) {
250
+ token = (mcp as any).environment["SUPABASE_ACCESS_TOKEN"]
251
+ break
252
+ }
253
+ }
254
+ }
255
+
256
+ if (!token) {
257
+ return c.json({ error: "Supabase token not found" }, 400)
258
+ }
259
+
260
+ const response = await fetch("https://api.supabase.com/v1/projects", {
261
+ headers: { Authorization: `Bearer ${token}` },
262
+ })
263
+
264
+ if (!response.ok) {
265
+ return c.json({ error: "Failed to fetch from Supabase" }, response.status as any)
266
+ }
267
+
268
+ return c.json(await response.json())
269
+ } catch (e) {
270
+ return c.json({ error: String(e) }, 500)
271
+ }
272
+ },
273
+ )
274
+ .post(
275
+ "/supabase/select",
276
+ describeRoute({
277
+ summary: "Select Supabase project",
278
+ description: "Update configuration with selected Supabase project ID",
279
+ operationId: "mcp.supabase.select",
280
+ responses: {
281
+ 200: {
282
+ description: "Success",
283
+ },
284
+ },
285
+ }),
286
+ validator(
287
+ "json",
288
+ z.object({
289
+ projectId: z.string(),
290
+ }),
291
+ ),
292
+ async (c) => {
293
+ try {
294
+ const { projectId } = c.req.valid("json")
295
+ const workspace = Instance.directory
296
+ const updates = ["supabase", "eliseartee"]
297
+
298
+ // Try opencode.json first, then config.json
299
+ let projectFile = `${workspace}/opencode.json`
300
+ if (!(await Bun.file(projectFile).exists())) {
301
+ projectFile = `${workspace}/config.json`
302
+ }
303
+
304
+ const file = Bun.file(projectFile)
305
+ let configToUpdate: any = {}
306
+ if (await file.exists()) {
307
+ try {
308
+ configToUpdate = await file.json()
309
+ } catch {
310
+ // ignore parse error, maybe partial
311
+ }
312
+ }
313
+
314
+ if (!configToUpdate.mcp) configToUpdate.mcp = {}
315
+
316
+ for (const name of updates) {
317
+ // Update in the config object
318
+ if (!configToUpdate.mcp[name]) {
319
+ // If it doesn't exist, we might want to skip or create it
320
+ // For now, let's only update if it exists or if we can find it in memory
321
+ continue
322
+ }
323
+
324
+ const entry = configToUpdate.mcp[name]
325
+ if (entry.type === "local" && Array.isArray(entry.command)) {
326
+ const newCommand = [...entry.command]
327
+ const refIndex = newCommand.indexOf("--project-ref")
328
+ if (refIndex !== -1 && refIndex + 1 < newCommand.length) {
329
+ newCommand[refIndex + 1] = projectId
330
+ } else {
331
+ newCommand.push("--project-ref", projectId)
332
+ }
333
+ entry.command = newCommand
334
+ }
335
+
336
+ // Also update in-memory runtime
337
+ const currentCfg = await Config.get()
338
+ const currentMcp = currentCfg.mcp?.[name] as any
339
+ if (currentMcp && currentMcp.type === "local" && Array.isArray(currentMcp.command)) {
340
+ const newCommand = [...currentMcp.command]
341
+ const refIndex = newCommand.indexOf("--project-ref")
342
+ if (refIndex !== -1 && refIndex + 1 < newCommand.length) {
343
+ newCommand[refIndex + 1] = projectId
344
+ } else {
345
+ newCommand.push("--project-ref", projectId)
346
+ }
347
+ currentMcp.command = newCommand
348
+ await MCP.add(name, currentMcp)
349
+ }
350
+ }
351
+
352
+ await Bun.write(projectFile, JSON.stringify(configToUpdate, null, 2))
353
+ await Instance.dispose()
354
+
355
+ return c.json({ success: true })
356
+ } catch (e) {
357
+ return c.json({ error: String(e) }, 500)
358
+ }
359
+ },
360
+ ),
361
+ )
@@ -0,0 +1,68 @@
1
+ import { Hono } from "hono"
2
+ import { describeRoute, validator, resolver } from "hono-openapi"
3
+ import z from "zod"
4
+ import { PermissionNext } from "@/permission/next"
5
+ import { errors } from "../error"
6
+ import { lazy } from "../../util/lazy"
7
+
8
+ export const PermissionRoutes = lazy(() =>
9
+ new Hono()
10
+ .post(
11
+ "/:requestID/reply",
12
+ describeRoute({
13
+ summary: "Respond to permission request",
14
+ description: "Approve or deny a permission request from the AI assistant.",
15
+ operationId: "permission.reply",
16
+ responses: {
17
+ 200: {
18
+ description: "Permission processed successfully",
19
+ content: {
20
+ "application/json": {
21
+ schema: resolver(z.boolean()),
22
+ },
23
+ },
24
+ },
25
+ ...errors(400, 404),
26
+ },
27
+ }),
28
+ validator(
29
+ "param",
30
+ z.object({
31
+ requestID: z.string(),
32
+ }),
33
+ ),
34
+ validator("json", z.object({ reply: PermissionNext.Reply, message: z.string().optional() })),
35
+ async (c) => {
36
+ const params = c.req.valid("param")
37
+ const json = c.req.valid("json")
38
+ await PermissionNext.reply({
39
+ requestID: params.requestID,
40
+ reply: json.reply,
41
+ message: json.message,
42
+ })
43
+ return c.json(true)
44
+ },
45
+ )
46
+ .get(
47
+ "/",
48
+ describeRoute({
49
+ summary: "List pending permissions",
50
+ description: "Get all pending permission requests across all sessions.",
51
+ operationId: "permission.list",
52
+ responses: {
53
+ 200: {
54
+ description: "List of pending permissions",
55
+ content: {
56
+ "application/json": {
57
+ schema: resolver(PermissionNext.Request.array()),
58
+ },
59
+ },
60
+ },
61
+ },
62
+ }),
63
+ async (c) => {
64
+ const permissions = await PermissionNext.list()
65
+ return c.json(permissions)
66
+ },
67
+ ),
68
+ )
@@ -0,0 +1,82 @@
1
+ import { Hono } from "hono"
2
+ import { describeRoute, validator } from "hono-openapi"
3
+ import { resolver } from "hono-openapi"
4
+ import { Instance } from "../../project/instance"
5
+ import { Project } from "../../project/project"
6
+ import z from "zod"
7
+ import { errors } from "../error"
8
+ import { lazy } from "../../util/lazy"
9
+
10
+ export const ProjectRoutes = lazy(() =>
11
+ new Hono()
12
+ .get(
13
+ "/",
14
+ describeRoute({
15
+ summary: "List all projects",
16
+ description: "Get a list of projects that have been opened with OpenCode.",
17
+ operationId: "project.list",
18
+ responses: {
19
+ 200: {
20
+ description: "List of projects",
21
+ content: {
22
+ "application/json": {
23
+ schema: resolver(Project.Info.array()),
24
+ },
25
+ },
26
+ },
27
+ },
28
+ }),
29
+ async (c) => {
30
+ const projects = await Project.list()
31
+ return c.json(projects)
32
+ },
33
+ )
34
+ .get(
35
+ "/current",
36
+ describeRoute({
37
+ summary: "Get current project",
38
+ description: "Retrieve the currently active project that OpenCode is working with.",
39
+ operationId: "project.current",
40
+ responses: {
41
+ 200: {
42
+ description: "Current project information",
43
+ content: {
44
+ "application/json": {
45
+ schema: resolver(Project.Info),
46
+ },
47
+ },
48
+ },
49
+ },
50
+ }),
51
+ async (c) => {
52
+ return c.json(Instance.project)
53
+ },
54
+ )
55
+ .patch(
56
+ "/:projectID",
57
+ describeRoute({
58
+ summary: "Update project",
59
+ description: "Update project properties such as name, icon and color.",
60
+ operationId: "project.update",
61
+ responses: {
62
+ 200: {
63
+ description: "Updated project information",
64
+ content: {
65
+ "application/json": {
66
+ schema: resolver(Project.Info),
67
+ },
68
+ },
69
+ },
70
+ ...errors(400, 404),
71
+ },
72
+ }),
73
+ validator("param", z.object({ projectID: z.string() })),
74
+ validator("json", Project.update.schema.omit({ projectID: true })),
75
+ async (c) => {
76
+ const projectID = c.req.valid("param").projectID
77
+ const body = c.req.valid("json")
78
+ const project = await Project.update({ ...body, projectID })
79
+ return c.json(project)
80
+ },
81
+ ),
82
+ )
@@ -0,0 +1,165 @@
1
+ import { Hono } from "hono"
2
+ import { describeRoute, validator, resolver } from "hono-openapi"
3
+ import z from "zod"
4
+ import { Config } from "../../config/config"
5
+ import { Provider } from "../../provider/provider"
6
+ import { ModelsDev } from "../../provider/models"
7
+ import { ProviderAuth } from "../../provider/auth"
8
+ import { mapValues } from "remeda"
9
+ import { errors } from "../error"
10
+ import { lazy } from "../../util/lazy"
11
+
12
+ export const ProviderRoutes = lazy(() =>
13
+ new Hono()
14
+ .get(
15
+ "/",
16
+ describeRoute({
17
+ summary: "List providers",
18
+ description: "Get a list of all available AI providers, including both available and connected ones.",
19
+ operationId: "provider.list",
20
+ responses: {
21
+ 200: {
22
+ description: "List of providers",
23
+ content: {
24
+ "application/json": {
25
+ schema: resolver(
26
+ z.object({
27
+ all: ModelsDev.Provider.array(),
28
+ default: z.record(z.string(), z.string()),
29
+ connected: z.array(z.string()),
30
+ }),
31
+ ),
32
+ },
33
+ },
34
+ },
35
+ },
36
+ }),
37
+ async (c) => {
38
+ const config = await Config.get()
39
+ const disabled = new Set(config.disabled_providers ?? [])
40
+ const enabled = config.enabled_providers ? new Set(config.enabled_providers) : undefined
41
+
42
+ const allProviders = await ModelsDev.get()
43
+ const filteredProviders: Record<string, (typeof allProviders)[string]> = {}
44
+ for (const [key, value] of Object.entries(allProviders)) {
45
+ if ((enabled ? enabled.has(key) : true) && !disabled.has(key)) {
46
+ filteredProviders[key] = value
47
+ }
48
+ }
49
+
50
+ const connected = await Provider.list()
51
+ const providers = Object.assign(
52
+ mapValues(filteredProviders, (x) => Provider.fromModelsDevProvider(x)),
53
+ connected,
54
+ )
55
+ return c.json({
56
+ all: Object.values(providers),
57
+ default: mapValues(providers, (item) => Provider.sort(Object.values(item.models))[0].id),
58
+ connected: Object.keys(connected),
59
+ })
60
+ },
61
+ )
62
+ .get(
63
+ "/auth",
64
+ describeRoute({
65
+ summary: "Get provider auth methods",
66
+ description: "Retrieve available authentication methods for all AI providers.",
67
+ operationId: "provider.auth",
68
+ responses: {
69
+ 200: {
70
+ description: "Provider auth methods",
71
+ content: {
72
+ "application/json": {
73
+ schema: resolver(z.record(z.string(), z.array(ProviderAuth.Method))),
74
+ },
75
+ },
76
+ },
77
+ },
78
+ }),
79
+ async (c) => {
80
+ return c.json(await ProviderAuth.methods())
81
+ },
82
+ )
83
+ .post(
84
+ "/:providerID/oauth/authorize",
85
+ describeRoute({
86
+ summary: "OAuth authorize",
87
+ description: "Initiate OAuth authorization for a specific AI provider to get an authorization URL.",
88
+ operationId: "provider.oauth.authorize",
89
+ responses: {
90
+ 200: {
91
+ description: "Authorization URL and method",
92
+ content: {
93
+ "application/json": {
94
+ schema: resolver(ProviderAuth.Authorization.optional()),
95
+ },
96
+ },
97
+ },
98
+ ...errors(400),
99
+ },
100
+ }),
101
+ validator(
102
+ "param",
103
+ z.object({
104
+ providerID: z.string().meta({ description: "Provider ID" }),
105
+ }),
106
+ ),
107
+ validator(
108
+ "json",
109
+ z.object({
110
+ method: z.number().meta({ description: "Auth method index" }),
111
+ }),
112
+ ),
113
+ async (c) => {
114
+ const providerID = c.req.valid("param").providerID
115
+ const { method } = c.req.valid("json")
116
+ const result = await ProviderAuth.authorize({
117
+ providerID,
118
+ method,
119
+ })
120
+ return c.json(result)
121
+ },
122
+ )
123
+ .post(
124
+ "/:providerID/oauth/callback",
125
+ describeRoute({
126
+ summary: "OAuth callback",
127
+ description: "Handle the OAuth callback from a provider after user authorization.",
128
+ operationId: "provider.oauth.callback",
129
+ responses: {
130
+ 200: {
131
+ description: "OAuth callback processed successfully",
132
+ content: {
133
+ "application/json": {
134
+ schema: resolver(z.boolean()),
135
+ },
136
+ },
137
+ },
138
+ ...errors(400),
139
+ },
140
+ }),
141
+ validator(
142
+ "param",
143
+ z.object({
144
+ providerID: z.string().meta({ description: "Provider ID" }),
145
+ }),
146
+ ),
147
+ validator(
148
+ "json",
149
+ z.object({
150
+ method: z.number().meta({ description: "Auth method index" }),
151
+ code: z.string().optional().meta({ description: "OAuth authorization code" }),
152
+ }),
153
+ ),
154
+ async (c) => {
155
+ const providerID = c.req.valid("param").providerID
156
+ const { method, code } = c.req.valid("json")
157
+ await ProviderAuth.callback({
158
+ providerID,
159
+ method,
160
+ code,
161
+ })
162
+ return c.json(true)
163
+ },
164
+ ),
165
+ )