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,300 @@
1
+ import { test, expect } from "bun:test"
2
+ import { Question } from "../../src/question"
3
+ import { Instance } from "../../src/project/instance"
4
+ import { tmpdir } from "../fixture/fixture"
5
+
6
+ test("ask - returns pending promise", async () => {
7
+ await using tmp = await tmpdir({ git: true })
8
+ await Instance.provide({
9
+ directory: tmp.path,
10
+ fn: async () => {
11
+ const promise = Question.ask({
12
+ sessionID: "ses_test",
13
+ questions: [
14
+ {
15
+ question: "What would you like to do?",
16
+ header: "Action",
17
+ options: [
18
+ { label: "Option 1", description: "First option" },
19
+ { label: "Option 2", description: "Second option" },
20
+ ],
21
+ },
22
+ ],
23
+ })
24
+ expect(promise).toBeInstanceOf(Promise)
25
+ },
26
+ })
27
+ })
28
+
29
+ test("ask - adds to pending list", async () => {
30
+ await using tmp = await tmpdir({ git: true })
31
+ await Instance.provide({
32
+ directory: tmp.path,
33
+ fn: async () => {
34
+ const questions = [
35
+ {
36
+ question: "What would you like to do?",
37
+ header: "Action",
38
+ options: [
39
+ { label: "Option 1", description: "First option" },
40
+ { label: "Option 2", description: "Second option" },
41
+ ],
42
+ },
43
+ ]
44
+
45
+ Question.ask({
46
+ sessionID: "ses_test",
47
+ questions,
48
+ })
49
+
50
+ const pending = await Question.list()
51
+ expect(pending.length).toBe(1)
52
+ expect(pending[0].questions).toEqual(questions)
53
+ },
54
+ })
55
+ })
56
+
57
+ // reply tests
58
+
59
+ test("reply - resolves the pending ask with answers", async () => {
60
+ await using tmp = await tmpdir({ git: true })
61
+ await Instance.provide({
62
+ directory: tmp.path,
63
+ fn: async () => {
64
+ const questions = [
65
+ {
66
+ question: "What would you like to do?",
67
+ header: "Action",
68
+ options: [
69
+ { label: "Option 1", description: "First option" },
70
+ { label: "Option 2", description: "Second option" },
71
+ ],
72
+ },
73
+ ]
74
+
75
+ const askPromise = Question.ask({
76
+ sessionID: "ses_test",
77
+ questions,
78
+ })
79
+
80
+ const pending = await Question.list()
81
+ const requestID = pending[0].id
82
+
83
+ await Question.reply({
84
+ requestID,
85
+ answers: [["Option 1"]],
86
+ })
87
+
88
+ const answers = await askPromise
89
+ expect(answers).toEqual([["Option 1"]])
90
+ },
91
+ })
92
+ })
93
+
94
+ test("reply - removes from pending list", async () => {
95
+ await using tmp = await tmpdir({ git: true })
96
+ await Instance.provide({
97
+ directory: tmp.path,
98
+ fn: async () => {
99
+ Question.ask({
100
+ sessionID: "ses_test",
101
+ questions: [
102
+ {
103
+ question: "What would you like to do?",
104
+ header: "Action",
105
+ options: [
106
+ { label: "Option 1", description: "First option" },
107
+ { label: "Option 2", description: "Second option" },
108
+ ],
109
+ },
110
+ ],
111
+ })
112
+
113
+ const pending = await Question.list()
114
+ expect(pending.length).toBe(1)
115
+
116
+ await Question.reply({
117
+ requestID: pending[0].id,
118
+ answers: [["Option 1"]],
119
+ })
120
+
121
+ const pendingAfter = await Question.list()
122
+ expect(pendingAfter.length).toBe(0)
123
+ },
124
+ })
125
+ })
126
+
127
+ test("reply - does nothing for unknown requestID", async () => {
128
+ await using tmp = await tmpdir({ git: true })
129
+ await Instance.provide({
130
+ directory: tmp.path,
131
+ fn: async () => {
132
+ await Question.reply({
133
+ requestID: "que_unknown",
134
+ answers: [["Option 1"]],
135
+ })
136
+ // Should not throw
137
+ },
138
+ })
139
+ })
140
+
141
+ // reject tests
142
+
143
+ test("reject - throws RejectedError", async () => {
144
+ await using tmp = await tmpdir({ git: true })
145
+ await Instance.provide({
146
+ directory: tmp.path,
147
+ fn: async () => {
148
+ const askPromise = Question.ask({
149
+ sessionID: "ses_test",
150
+ questions: [
151
+ {
152
+ question: "What would you like to do?",
153
+ header: "Action",
154
+ options: [
155
+ { label: "Option 1", description: "First option" },
156
+ { label: "Option 2", description: "Second option" },
157
+ ],
158
+ },
159
+ ],
160
+ })
161
+
162
+ const pending = await Question.list()
163
+ await Question.reject(pending[0].id)
164
+
165
+ await expect(askPromise).rejects.toBeInstanceOf(Question.RejectedError)
166
+ },
167
+ })
168
+ })
169
+
170
+ test("reject - removes from pending list", async () => {
171
+ await using tmp = await tmpdir({ git: true })
172
+ await Instance.provide({
173
+ directory: tmp.path,
174
+ fn: async () => {
175
+ const askPromise = Question.ask({
176
+ sessionID: "ses_test",
177
+ questions: [
178
+ {
179
+ question: "What would you like to do?",
180
+ header: "Action",
181
+ options: [
182
+ { label: "Option 1", description: "First option" },
183
+ { label: "Option 2", description: "Second option" },
184
+ ],
185
+ },
186
+ ],
187
+ })
188
+
189
+ const pending = await Question.list()
190
+ expect(pending.length).toBe(1)
191
+
192
+ await Question.reject(pending[0].id)
193
+ askPromise.catch(() => {}) // Ignore rejection
194
+
195
+ const pendingAfter = await Question.list()
196
+ expect(pendingAfter.length).toBe(0)
197
+ },
198
+ })
199
+ })
200
+
201
+ test("reject - does nothing for unknown requestID", async () => {
202
+ await using tmp = await tmpdir({ git: true })
203
+ await Instance.provide({
204
+ directory: tmp.path,
205
+ fn: async () => {
206
+ await Question.reject("que_unknown")
207
+ // Should not throw
208
+ },
209
+ })
210
+ })
211
+
212
+ // multiple questions tests
213
+
214
+ test("ask - handles multiple questions", async () => {
215
+ await using tmp = await tmpdir({ git: true })
216
+ await Instance.provide({
217
+ directory: tmp.path,
218
+ fn: async () => {
219
+ const questions = [
220
+ {
221
+ question: "What would you like to do?",
222
+ header: "Action",
223
+ options: [
224
+ { label: "Build", description: "Build the project" },
225
+ { label: "Test", description: "Run tests" },
226
+ ],
227
+ },
228
+ {
229
+ question: "Which environment?",
230
+ header: "Env",
231
+ options: [
232
+ { label: "Dev", description: "Development" },
233
+ { label: "Prod", description: "Production" },
234
+ ],
235
+ },
236
+ ]
237
+
238
+ const askPromise = Question.ask({
239
+ sessionID: "ses_test",
240
+ questions,
241
+ })
242
+
243
+ const pending = await Question.list()
244
+
245
+ await Question.reply({
246
+ requestID: pending[0].id,
247
+ answers: [["Build"], ["Dev"]],
248
+ })
249
+
250
+ const answers = await askPromise
251
+ expect(answers).toEqual([["Build"], ["Dev"]])
252
+ },
253
+ })
254
+ })
255
+
256
+ // list tests
257
+
258
+ test("list - returns all pending requests", async () => {
259
+ await using tmp = await tmpdir({ git: true })
260
+ await Instance.provide({
261
+ directory: tmp.path,
262
+ fn: async () => {
263
+ Question.ask({
264
+ sessionID: "ses_test1",
265
+ questions: [
266
+ {
267
+ question: "Question 1?",
268
+ header: "Q1",
269
+ options: [{ label: "A", description: "A" }],
270
+ },
271
+ ],
272
+ })
273
+
274
+ Question.ask({
275
+ sessionID: "ses_test2",
276
+ questions: [
277
+ {
278
+ question: "Question 2?",
279
+ header: "Q2",
280
+ options: [{ label: "B", description: "B" }],
281
+ },
282
+ ],
283
+ })
284
+
285
+ const pending = await Question.list()
286
+ expect(pending.length).toBe(2)
287
+ },
288
+ })
289
+ })
290
+
291
+ test("list - returns empty when no pending", async () => {
292
+ await using tmp = await tmpdir({ git: true })
293
+ await Instance.provide({
294
+ directory: tmp.path,
295
+ fn: async () => {
296
+ const pending = await Question.list()
297
+ expect(pending.length).toBe(0)
298
+ },
299
+ })
300
+ })
@@ -0,0 +1,73 @@
1
+ import { describe, expect, test } from "bun:test"
2
+ import { Scheduler } from "../src/scheduler"
3
+ import { Instance } from "../src/project/instance"
4
+ import { tmpdir } from "./fixture/fixture"
5
+
6
+ describe("Scheduler.register", () => {
7
+ const hour = 60 * 60 * 1000
8
+
9
+ test("defaults to instance scope per directory", async () => {
10
+ await using one = await tmpdir({ git: true })
11
+ await using two = await tmpdir({ git: true })
12
+ const runs = { count: 0 }
13
+ const id = "scheduler.instance." + Math.random().toString(36).slice(2)
14
+ const task = {
15
+ id,
16
+ interval: hour,
17
+ run: async () => {
18
+ runs.count += 1
19
+ },
20
+ }
21
+
22
+ await Instance.provide({
23
+ directory: one.path,
24
+ fn: async () => {
25
+ Scheduler.register(task)
26
+ await Instance.dispose()
27
+ },
28
+ })
29
+ expect(runs.count).toBe(1)
30
+
31
+ await Instance.provide({
32
+ directory: two.path,
33
+ fn: async () => {
34
+ Scheduler.register(task)
35
+ await Instance.dispose()
36
+ },
37
+ })
38
+ expect(runs.count).toBe(2)
39
+ })
40
+
41
+ test("global scope runs once across instances", async () => {
42
+ await using one = await tmpdir({ git: true })
43
+ await using two = await tmpdir({ git: true })
44
+ const runs = { count: 0 }
45
+ const id = "scheduler.global." + Math.random().toString(36).slice(2)
46
+ const task = {
47
+ id,
48
+ interval: hour,
49
+ run: async () => {
50
+ runs.count += 1
51
+ },
52
+ scope: "global" as const,
53
+ }
54
+
55
+ await Instance.provide({
56
+ directory: one.path,
57
+ fn: async () => {
58
+ Scheduler.register(task)
59
+ await Instance.dispose()
60
+ },
61
+ })
62
+ expect(runs.count).toBe(1)
63
+
64
+ await Instance.provide({
65
+ directory: two.path,
66
+ fn: async () => {
67
+ Scheduler.register(task)
68
+ await Instance.dispose()
69
+ },
70
+ })
71
+ expect(runs.count).toBe(1)
72
+ })
73
+ })
@@ -0,0 +1,39 @@
1
+ import { describe, expect, test } from "bun:test"
2
+ import path from "path"
3
+ import { Instance } from "../../src/project/instance"
4
+ import { Server } from "../../src/server/server"
5
+ import { Session } from "../../src/session"
6
+ import { Log } from "../../src/util/log"
7
+
8
+ const projectRoot = path.join(__dirname, "../..")
9
+ Log.init({ print: false })
10
+
11
+ describe("session.list", () => {
12
+ test("filters by directory", async () => {
13
+ await Instance.provide({
14
+ directory: projectRoot,
15
+ fn: async () => {
16
+ const app = Server.App()
17
+
18
+ const first = await Session.create({})
19
+
20
+ const otherDir = path.join(projectRoot, "..", "__session_list_other")
21
+ const second = await Instance.provide({
22
+ directory: otherDir,
23
+ fn: async () => Session.create({}),
24
+ })
25
+
26
+ const response = await app.request(`/session?directory=${encodeURIComponent(projectRoot)}`)
27
+ expect(response.status).toBe(200)
28
+
29
+ const body = (await response.json()) as unknown[]
30
+ const ids = body
31
+ .map((s) => (typeof s === "object" && s && "id" in s ? (s as { id: string }).id : undefined))
32
+ .filter((x): x is string => typeof x === "string")
33
+
34
+ expect(ids).toContain(first.id)
35
+ expect(ids).not.toContain(second.id)
36
+ },
37
+ })
38
+ })
39
+ })
@@ -0,0 +1,78 @@
1
+ import { describe, expect, test } from "bun:test"
2
+ import path from "path"
3
+ import { Session } from "../../src/session"
4
+ import { Log } from "../../src/util/log"
5
+ import { Instance } from "../../src/project/instance"
6
+ import { Server } from "../../src/server/server"
7
+
8
+ const projectRoot = path.join(__dirname, "../..")
9
+ Log.init({ print: false })
10
+
11
+ describe("tui.selectSession endpoint", () => {
12
+ test("should return 200 when called with valid session", async () => {
13
+ await Instance.provide({
14
+ directory: projectRoot,
15
+ fn: async () => {
16
+ // #given
17
+ const session = await Session.create({})
18
+
19
+ // #when
20
+ const app = Server.App()
21
+ const response = await app.request("/tui/select-session", {
22
+ method: "POST",
23
+ headers: { "Content-Type": "application/json" },
24
+ body: JSON.stringify({ sessionID: session.id }),
25
+ })
26
+
27
+ // #then
28
+ expect(response.status).toBe(200)
29
+ const body = await response.json()
30
+ expect(body).toBe(true)
31
+
32
+ await Session.remove(session.id)
33
+ },
34
+ })
35
+ })
36
+
37
+ test("should return 404 when session does not exist", async () => {
38
+ await Instance.provide({
39
+ directory: projectRoot,
40
+ fn: async () => {
41
+ // #given
42
+ const nonExistentSessionID = "ses_nonexistent123"
43
+
44
+ // #when
45
+ const app = Server.App()
46
+ const response = await app.request("/tui/select-session", {
47
+ method: "POST",
48
+ headers: { "Content-Type": "application/json" },
49
+ body: JSON.stringify({ sessionID: nonExistentSessionID }),
50
+ })
51
+
52
+ // #then
53
+ expect(response.status).toBe(404)
54
+ },
55
+ })
56
+ })
57
+
58
+ test("should return 400 when session ID format is invalid", async () => {
59
+ await Instance.provide({
60
+ directory: projectRoot,
61
+ fn: async () => {
62
+ // #given
63
+ const invalidSessionID = "invalid_session_id"
64
+
65
+ // #when
66
+ const app = Server.App()
67
+ const response = await app.request("/tui/select-session", {
68
+ method: "POST",
69
+ headers: { "Content-Type": "application/json" },
70
+ body: JSON.stringify({ sessionID: invalidSessionID }),
71
+ })
72
+
73
+ // #then
74
+ expect(response.status).toBe(400)
75
+ },
76
+ })
77
+ })
78
+ })