c0de-agent 0.0.0 → 1.1.0

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 (336) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +101 -0
  3. package/dist/cli/commands/acp.d.ts +19 -0
  4. package/dist/cli/commands/acp.js +50 -0
  5. package/dist/cli/commands/chat.d.ts +13 -0
  6. package/dist/cli/commands/chat.js +26 -0
  7. package/dist/cli/commands/config.d.ts +17 -0
  8. package/dist/cli/commands/config.js +77 -0
  9. package/dist/cli/commands/init.d.ts +9 -0
  10. package/dist/cli/commands/init.js +14 -0
  11. package/dist/cli/commands/plugin.d.ts +11 -0
  12. package/dist/cli/commands/plugin.js +31 -0
  13. package/dist/cli/commands/serve.d.ts +18 -0
  14. package/dist/cli/commands/serve.js +35 -0
  15. package/dist/cli/commands/update.d.ts +24 -0
  16. package/dist/cli/commands/update.js +40 -0
  17. package/dist/cli/deps.d.ts +30 -0
  18. package/dist/cli/deps.js +70 -0
  19. package/dist/cli/index.d.ts +8 -0
  20. package/dist/cli/index.js +155 -0
  21. package/dist/cli/modes/acp.d.ts +18 -0
  22. package/dist/cli/modes/acp.js +57 -0
  23. package/dist/cli/modes/print.d.ts +16 -0
  24. package/dist/cli/modes/print.js +30 -0
  25. package/dist/cli/parser.d.ts +19 -0
  26. package/dist/cli/parser.js +28 -0
  27. package/dist/cli/utils/output.d.ts +11 -0
  28. package/dist/cli/utils/output.js +23 -0
  29. package/dist/cli/utils/prompt.d.ts +12 -0
  30. package/dist/cli/utils/prompt.js +18 -0
  31. package/dist/core/agent.d.ts +12 -0
  32. package/dist/core/agent.js +100 -0
  33. package/dist/core/agents/builtin.d.ts +6 -0
  34. package/dist/core/agents/builtin.js +76 -0
  35. package/dist/core/agents/discovery.d.ts +6 -0
  36. package/dist/core/agents/discovery.js +96 -0
  37. package/dist/core/agents/index.d.ts +6 -0
  38. package/dist/core/agents/index.js +4 -0
  39. package/dist/core/agents/parallel.d.ts +13 -0
  40. package/dist/core/agents/parallel.js +37 -0
  41. package/dist/core/agents/registry.d.ts +4 -0
  42. package/dist/core/agents/registry.js +23 -0
  43. package/dist/core/agents/types.d.ts +37 -0
  44. package/dist/core/agents/types.js +1 -0
  45. package/dist/core/compact.d.ts +11 -0
  46. package/dist/core/compact.js +31 -0
  47. package/dist/core/config.d.ts +7 -0
  48. package/dist/core/config.js +85 -0
  49. package/dist/core/context.d.ts +23 -0
  50. package/dist/core/context.js +93 -0
  51. package/dist/core/index.d.ts +13 -0
  52. package/dist/core/index.js +11 -0
  53. package/dist/core/loop.d.ts +35 -0
  54. package/dist/core/loop.js +915 -0
  55. package/dist/core/metrics.d.ts +27 -0
  56. package/dist/core/metrics.js +94 -0
  57. package/dist/core/prompt-registry.d.ts +21 -0
  58. package/dist/core/prompt-registry.js +200 -0
  59. package/dist/core/prompt.d.ts +11 -0
  60. package/dist/core/prompt.js +13 -0
  61. package/dist/core/secret.d.ts +12 -0
  62. package/dist/core/secret.js +51 -0
  63. package/dist/core/slash.d.ts +15 -0
  64. package/dist/core/slash.js +113 -0
  65. package/dist/core/steering.d.ts +8 -0
  66. package/dist/core/steering.js +15 -0
  67. package/dist/core/title.d.ts +42 -0
  68. package/dist/core/title.js +116 -0
  69. package/dist/core/tool-exec.d.ts +20 -0
  70. package/dist/core/tool-exec.js +64 -0
  71. package/dist/core/types.d.ts +97 -0
  72. package/dist/core/types.js +1 -0
  73. package/dist/core/worktree.d.ts +24 -0
  74. package/dist/core/worktree.js +70 -0
  75. package/dist/dap/index.d.ts +6 -0
  76. package/dist/dap/index.js +4 -0
  77. package/dist/dap/protocol.d.ts +40 -0
  78. package/dist/dap/protocol.js +132 -0
  79. package/dist/dap/session.d.ts +23 -0
  80. package/dist/dap/session.js +130 -0
  81. package/dist/dap/transport.d.ts +8 -0
  82. package/dist/dap/transport.js +30 -0
  83. package/dist/dap/types.d.ts +50 -0
  84. package/dist/dap/types.js +2 -0
  85. package/dist/db/client.d.ts +22 -0
  86. package/dist/db/client.js +39 -0
  87. package/dist/db/index.d.ts +6 -0
  88. package/dist/db/index.js +4 -0
  89. package/dist/db/migrate.d.ts +9 -0
  90. package/dist/db/migrate.js +15 -0
  91. package/dist/db/schema.d.ts +965 -0
  92. package/dist/db/schema.js +112 -0
  93. package/dist/db/types.d.ts +11 -0
  94. package/dist/db/types.js +1 -0
  95. package/dist/llm/index.d.ts +13 -0
  96. package/dist/llm/index.js +8 -0
  97. package/dist/llm/protocols/openai-compat.d.ts +139 -0
  98. package/dist/llm/protocols/openai-compat.js +214 -0
  99. package/dist/llm/protocols/utils/index.d.ts +2 -0
  100. package/dist/llm/protocols/utils/index.js +2 -0
  101. package/dist/llm/protocols/utils/lifecycle.d.ts +23 -0
  102. package/dist/llm/protocols/utils/lifecycle.js +46 -0
  103. package/dist/llm/protocols/utils/tool-stream.d.ts +46 -0
  104. package/dist/llm/protocols/utils/tool-stream.js +94 -0
  105. package/dist/llm/provider-error.d.ts +5 -0
  106. package/dist/llm/provider-error.js +33 -0
  107. package/dist/llm/provider.d.ts +32 -0
  108. package/dist/llm/provider.js +195 -0
  109. package/dist/llm/registry.d.ts +44 -0
  110. package/dist/llm/registry.js +107 -0
  111. package/dist/llm/retry.d.ts +37 -0
  112. package/dist/llm/retry.js +82 -0
  113. package/dist/llm/routing.d.ts +36 -0
  114. package/dist/llm/routing.js +53 -0
  115. package/dist/llm/schema/errors.d.ts +88 -0
  116. package/dist/llm/schema/errors.js +33 -0
  117. package/dist/llm/schema/events.d.ts +135 -0
  118. package/dist/llm/schema/events.js +35 -0
  119. package/dist/llm/schema/ids.d.ts +22 -0
  120. package/dist/llm/schema/ids.js +3 -0
  121. package/dist/llm/schema/index.d.ts +5 -0
  122. package/dist/llm/schema/index.js +5 -0
  123. package/dist/llm/schema/messages.d.ts +97 -0
  124. package/dist/llm/schema/messages.js +18 -0
  125. package/dist/llm/schema/options.d.ts +54 -0
  126. package/dist/llm/schema/options.js +54 -0
  127. package/dist/llm/token.d.ts +2 -0
  128. package/dist/llm/token.js +13 -0
  129. package/dist/llm/transport.d.ts +31 -0
  130. package/dist/llm/transport.js +165 -0
  131. package/dist/mcp/index.d.ts +1 -0
  132. package/dist/mcp/index.js +3 -0
  133. package/dist/plugins/builtin.d.ts +6 -0
  134. package/dist/plugins/builtin.js +54 -0
  135. package/dist/plugins/hooks.d.ts +3 -0
  136. package/dist/plugins/hooks.js +79 -0
  137. package/dist/plugins/index.d.ts +9 -0
  138. package/dist/plugins/index.js +8 -0
  139. package/dist/plugins/init.d.ts +23 -0
  140. package/dist/plugins/init.js +30 -0
  141. package/dist/plugins/lifecycle.d.ts +6 -0
  142. package/dist/plugins/lifecycle.js +74 -0
  143. package/dist/plugins/loader.d.ts +16 -0
  144. package/dist/plugins/loader.js +69 -0
  145. package/dist/plugins/logger.d.ts +4 -0
  146. package/dist/plugins/logger.js +31 -0
  147. package/dist/plugins/registry.d.ts +7 -0
  148. package/dist/plugins/registry.js +24 -0
  149. package/dist/plugins/types.d.ts +113 -0
  150. package/dist/plugins/types.js +1 -0
  151. package/dist/project/detect.d.ts +4 -0
  152. package/dist/project/detect.js +131 -0
  153. package/dist/project/index.d.ts +4 -0
  154. package/dist/project/index.js +2 -0
  155. package/dist/project/project.d.ts +23 -0
  156. package/dist/project/project.js +87 -0
  157. package/dist/project/resolve.d.ts +8 -0
  158. package/dist/project/resolve.js +81 -0
  159. package/dist/server/agent-manager.d.ts +34 -0
  160. package/dist/server/agent-manager.js +62 -0
  161. package/dist/server/app.d.ts +5 -0
  162. package/dist/server/app.js +78 -0
  163. package/dist/server/context.d.ts +20 -0
  164. package/dist/server/context.js +49 -0
  165. package/dist/server/dev.d.ts +14 -0
  166. package/dist/server/dev.js +148 -0
  167. package/dist/server/index.d.ts +11 -0
  168. package/dist/server/index.js +7 -0
  169. package/dist/server/middleware/auth.d.ts +15 -0
  170. package/dist/server/middleware/auth.js +29 -0
  171. package/dist/server/middleware/cors.d.ts +16 -0
  172. package/dist/server/middleware/cors.js +44 -0
  173. package/dist/server/middleware/error.d.ts +15 -0
  174. package/dist/server/middleware/error.js +11 -0
  175. package/dist/server/permission/interactive.d.ts +24 -0
  176. package/dist/server/permission/interactive.js +56 -0
  177. package/dist/server/permission/store.d.ts +32 -0
  178. package/dist/server/permission/store.js +56 -0
  179. package/dist/server/routes/agent.d.ts +4 -0
  180. package/dist/server/routes/agent.js +19 -0
  181. package/dist/server/routes/catalog.d.ts +42 -0
  182. package/dist/server/routes/catalog.js +194 -0
  183. package/dist/server/routes/chat.d.ts +8 -0
  184. package/dist/server/routes/chat.js +318 -0
  185. package/dist/server/routes/commands.d.ts +5 -0
  186. package/dist/server/routes/commands.js +17 -0
  187. package/dist/server/routes/config.d.ts +4 -0
  188. package/dist/server/routes/config.js +27 -0
  189. package/dist/server/routes/files.d.ts +4 -0
  190. package/dist/server/routes/files.js +183 -0
  191. package/dist/server/routes/filesystem.d.ts +29 -0
  192. package/dist/server/routes/filesystem.js +108 -0
  193. package/dist/server/routes/health.d.ts +3 -0
  194. package/dist/server/routes/health.js +13 -0
  195. package/dist/server/routes/permissions.d.ts +5 -0
  196. package/dist/server/routes/permissions.js +23 -0
  197. package/dist/server/routes/project.d.ts +4 -0
  198. package/dist/server/routes/project.js +51 -0
  199. package/dist/server/routes/provider.d.ts +16 -0
  200. package/dist/server/routes/provider.js +66 -0
  201. package/dist/server/routes/session.d.ts +4 -0
  202. package/dist/server/routes/session.js +204 -0
  203. package/dist/server/routes/terminal.d.ts +5 -0
  204. package/dist/server/routes/terminal.js +66 -0
  205. package/dist/server/routes/tool.d.ts +4 -0
  206. package/dist/server/routes/tool.js +28 -0
  207. package/dist/server/routes/update.d.ts +14 -0
  208. package/dist/server/routes/update.js +49 -0
  209. package/dist/server/server.d.ts +56 -0
  210. package/dist/server/server.js +269 -0
  211. package/dist/server/terminal/pty-manager.d.ts +53 -0
  212. package/dist/server/terminal/pty-manager.js +160 -0
  213. package/dist/server/types.d.ts +76 -0
  214. package/dist/server/types.js +2 -0
  215. package/dist/server/util/safe-path.d.ts +7 -0
  216. package/dist/server/util/safe-path.js +7 -0
  217. package/dist/session/archive.d.ts +15 -0
  218. package/dist/session/archive.js +129 -0
  219. package/dist/session/branch.d.ts +9 -0
  220. package/dist/session/branch.js +63 -0
  221. package/dist/session/compaction.d.ts +33 -0
  222. package/dist/session/compaction.js +261 -0
  223. package/dist/session/context.d.ts +16 -0
  224. package/dist/session/context.js +173 -0
  225. package/dist/session/index.d.ts +10 -0
  226. package/dist/session/index.js +10 -0
  227. package/dist/session/message.d.ts +22 -0
  228. package/dist/session/message.js +145 -0
  229. package/dist/session/session.d.ts +37 -0
  230. package/dist/session/session.js +144 -0
  231. package/dist/session/shake.d.ts +66 -0
  232. package/dist/session/shake.js +304 -0
  233. package/dist/session/snapshot.d.ts +11 -0
  234. package/dist/session/snapshot.js +60 -0
  235. package/dist/session/squash.d.ts +9 -0
  236. package/dist/session/squash.js +88 -0
  237. package/dist/session/token.d.ts +10 -0
  238. package/dist/session/token.js +33 -0
  239. package/dist/session/types.d.ts +122 -0
  240. package/dist/session/types.js +1 -0
  241. package/dist/shared/index.d.ts +2 -0
  242. package/dist/shared/index.js +1 -0
  243. package/dist/shared/types/agent.d.ts +229 -0
  244. package/dist/shared/types/agent.js +1 -0
  245. package/dist/shared/types/base.d.ts +32 -0
  246. package/dist/shared/types/base.js +1 -0
  247. package/dist/shared/types/config.d.ts +114 -0
  248. package/dist/shared/types/config.js +1 -0
  249. package/dist/shared/types/index.d.ts +6 -0
  250. package/dist/shared/types/index.js +1 -0
  251. package/dist/shared/types/llm.d.ts +123 -0
  252. package/dist/shared/types/llm.js +1 -0
  253. package/dist/shared/types/message.d.ts +71 -0
  254. package/dist/shared/types/message.js +1 -0
  255. package/dist/shared/types/tool.d.ts +137 -0
  256. package/dist/shared/types/tool.js +1 -0
  257. package/dist/shared/utils/path.d.ts +15 -0
  258. package/dist/shared/utils/path.js +23 -0
  259. package/dist/shared/utils.d.ts +5 -0
  260. package/dist/shared/utils.js +10 -0
  261. package/dist/tools/builtin/bash.d.ts +12 -0
  262. package/dist/tools/builtin/bash.js +121 -0
  263. package/dist/tools/builtin/dap.d.ts +23 -0
  264. package/dist/tools/builtin/dap.js +231 -0
  265. package/dist/tools/builtin/edit.d.ts +12 -0
  266. package/dist/tools/builtin/edit.js +151 -0
  267. package/dist/tools/builtin/glob.d.ts +11 -0
  268. package/dist/tools/builtin/glob.js +120 -0
  269. package/dist/tools/builtin/grep.d.ts +6 -0
  270. package/dist/tools/builtin/grep.js +141 -0
  271. package/dist/tools/builtin/read.d.ts +6 -0
  272. package/dist/tools/builtin/read.js +73 -0
  273. package/dist/tools/builtin/resolvers.d.ts +12 -0
  274. package/dist/tools/builtin/resolvers.js +79 -0
  275. package/dist/tools/builtin/task.d.ts +9 -0
  276. package/dist/tools/builtin/task.js +100 -0
  277. package/dist/tools/builtin/write.d.ts +6 -0
  278. package/dist/tools/builtin/write.js +36 -0
  279. package/dist/tools/builtin/yield.d.ts +9 -0
  280. package/dist/tools/builtin/yield.js +40 -0
  281. package/dist/tools/executor.d.ts +9 -0
  282. package/dist/tools/executor.js +54 -0
  283. package/dist/tools/hashline/index.d.ts +2 -0
  284. package/dist/tools/hashline/index.js +3 -0
  285. package/dist/tools/hashline/patch.d.ts +48 -0
  286. package/dist/tools/hashline/patch.js +201 -0
  287. package/dist/tools/index.d.ts +30 -0
  288. package/dist/tools/index.js +55 -0
  289. package/dist/tools/permission.d.ts +13 -0
  290. package/dist/tools/permission.js +39 -0
  291. package/dist/tools/registry.d.ts +15 -0
  292. package/dist/tools/registry.js +54 -0
  293. package/dist/tools/resolver.d.ts +15 -0
  294. package/dist/tools/resolver.js +47 -0
  295. package/dist/tools/truncate.d.ts +8 -0
  296. package/dist/tools/truncate.js +50 -0
  297. package/dist/tools/types.d.ts +101 -0
  298. package/dist/tools/types.js +1 -0
  299. package/dist/tools/validate.d.ts +8 -0
  300. package/dist/tools/validate.js +130 -0
  301. package/dist/tools/websearch/fetch.d.ts +11 -0
  302. package/dist/tools/websearch/fetch.js +21 -0
  303. package/dist/tools/websearch/index.d.ts +19 -0
  304. package/dist/tools/websearch/index.js +78 -0
  305. package/dist/tools/websearch/providers/brave.d.ts +5 -0
  306. package/dist/tools/websearch/providers/brave.js +53 -0
  307. package/dist/tools/websearch/providers/duckduckgo.d.ts +3 -0
  308. package/dist/tools/websearch/providers/duckduckgo.js +75 -0
  309. package/dist/tools/websearch/providers/tavily.d.ts +11 -0
  310. package/dist/tools/websearch/providers/tavily.js +89 -0
  311. package/dist/tools/websearch/types.d.ts +51 -0
  312. package/dist/tools/websearch/types.js +18 -0
  313. package/dist/tools/websearch/websearch.d.ts +10 -0
  314. package/dist/tools/websearch/websearch.js +48 -0
  315. package/dist/update/index.d.ts +10 -0
  316. package/dist/update/index.js +6 -0
  317. package/dist/update/ipc.d.ts +15 -0
  318. package/dist/update/ipc.js +41 -0
  319. package/dist/update/scheduler.d.ts +34 -0
  320. package/dist/update/scheduler.js +57 -0
  321. package/dist/update/snapshot.d.ts +39 -0
  322. package/dist/update/snapshot.js +99 -0
  323. package/dist/update/updater.d.ts +48 -0
  324. package/dist/update/updater.js +83 -0
  325. package/dist/update/version.d.ts +18 -0
  326. package/dist/update/version.js +49 -0
  327. package/drizzle/0000_magical_nightshade.sql +55 -0
  328. package/drizzle/0001_chemical_doctor_faustus.sql +13 -0
  329. package/drizzle/0002_amusing_micromacro.sql +12 -0
  330. package/drizzle/0003_regular_purifiers.sql +2 -0
  331. package/drizzle/meta/0000_snapshot.json +448 -0
  332. package/drizzle/meta/0001_snapshot.json +539 -0
  333. package/drizzle/meta/0002_snapshot.json +633 -0
  334. package/drizzle/meta/0003_snapshot.json +645 -0
  335. package/drizzle/meta/_journal.json +34 -0
  336. package/package.json +108 -8
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 wmzy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # c0de-agent
2
+
3
+ 开源 AI 编码助手,采用 Browser-Server 架构(Hono + SSE 后端 / React 前端 / PGLite 本地数据库 / CLI)。
4
+
5
+ ## 特性
6
+
7
+ - **Browser-Server 架构**:Hono 后端通过 SSE 推送 LLM 流式响应;React 前端单页应用。
8
+ - **本地优先**:会话与索引存储在 PGLite(浏览器/进程内 PostgreSQL),数据随用随取。
9
+ - **多项目**:工作区隔离的多项目管理,每个项目独立会话历史与配置。
10
+ - **工具系统**:内置文件读写、bash、grep、glob、编辑等工具,可按需启用/禁用。
11
+ - **权限模式**:`default` / `yolo` 等授权模式,控制工具执行前是否需用户确认。
12
+ - **会话可恢复**:会话快照序列化/反序列化,支持进程重启后无缝恢复。
13
+ - **无感知热更新**:后台定期检查新版本,序列化当前会话 → npm 自更新 → 端口 handoff 接管,用户无感升级。
14
+ - **Web 搜索**:内置 websearch 工具,支持多搜索引擎。
15
+ - **斜杠命令**:`/compact`、`/model`、`/clear` 等可配置的斜杠命令。
16
+ - **主题与多语言**:亮/暗主题,简体中文 / English。
17
+
18
+ ## 安装
19
+
20
+ ```bash
21
+ # 全局安装(推荐)
22
+ npm install -g c0de-agent
23
+
24
+ # 或用 pnpm / yarn
25
+ pnpm add -g c0de-agent
26
+ ```
27
+
28
+ 要求 Node.js >= 22.0.0。
29
+
30
+ ## 使用
31
+
32
+ ```bash
33
+ # 在项目目录启动
34
+ c0de serve
35
+
36
+ # 指定端口并自动打开浏览器
37
+ c0de serve --port 3000 --open
38
+
39
+ # 从快照恢复会话
40
+ c0de serve --restore snapshot.json
41
+
42
+ # 打印模式(单次问答,不启动服务)
43
+ c0de chat "解释这段代码"
44
+
45
+ # 更新检查
46
+ c0de update --check
47
+ ```
48
+
49
+ 启动后访问 `http://localhost:3000`。
50
+
51
+ ## 开发
52
+
53
+ ```bash
54
+ # 安装依赖
55
+ pnpm install
56
+
57
+ # 启动开发服务器(前端热更新)
58
+ pnpm dev
59
+
60
+ # 类型检查
61
+ pnpm typecheck # 后端
62
+ pnpm typecheck:web # 前端
63
+
64
+ # 测试
65
+ pnpm test
66
+
67
+ # 构建
68
+ pnpm build # 编译 CLI/后端到 dist/
69
+ pnpm build:web # 构建前端到 dist-web/
70
+
71
+ # 代码检查与格式化
72
+ pnpm lint
73
+ pnpm format
74
+ ```
75
+
76
+ ## 架构
77
+
78
+ ```
79
+ src/
80
+ ├── cli/ # CLI 入口与命令(serve / chat / update)
81
+ ├── core/ # 配置、agent 注册、权限、工具注册
82
+ ├── llm/ # LLM provider 抽象与调用
83
+ ├── server/ # Hono HTTP 服务、SSE 流、路由、handoff
84
+ ├── session/ # 会话上下文与消息转换
85
+ ├── shared/ # 前后端共享类型
86
+ ├── tools/ # 内置工具实现
87
+ ├── update/ # 版本检查、热更新调度器、会话快照
88
+ └── web/ # React 前端(组件、视图、服务、hooks)
89
+ ```
90
+
91
+ ## 发布
92
+
93
+ 采用 [semantic-release](https://github.com/semantic-release/semantic-release) 自动化发布,基于 conventional commits(`feat:`、`fix:`、`refactor:` 等)自动计算版本号、生成 changelog 并发布到 npm。
94
+
95
+ - `main` 分支推送触发 `.github/workflows/release.yml`
96
+ - 通过 GitHub Actions OIDC trusted publishing 发布(无需 NPM_TOKEN)
97
+ - 发布产物带 npm provenance(可验证来源)
98
+
99
+ ## License
100
+
101
+ [MIT](./LICENSE)
@@ -0,0 +1,19 @@
1
+ import type { LoopDeps } from '../../core/loop.js';
2
+ import type { Config } from '../../shared/types/config.js';
3
+ import type { ACPHandler } from '../modes/acp.js';
4
+ type AcpHandlersOptions = {
5
+ onEvent: (method: string, params: Record<string, unknown>) => void;
6
+ };
7
+ /** 构造 ACP method → handler 映射。chat 复用 Print 模式。 */
8
+ declare function createAcpHandlers(config: Config, deps: LoopDeps, opts: AcpHandlersOptions): Record<string, ACPHandler>;
9
+ /** 写一行 ACP event 到给定 writer(命令层用于接 stdout)。 */
10
+ declare function writeAcpEvent(writer: (line: string) => void, method: string, params: Record<string, unknown>): void;
11
+ type AcpCommandContext = {
12
+ config: Config;
13
+ deps: LoopDeps;
14
+ stdin?: NodeJS.ReadableStream;
15
+ stdout?: NodeJS.WritableStream;
16
+ };
17
+ declare function runAcpCommand(ctx: AcpCommandContext): Promise<void>;
18
+ export type { AcpCommandContext, AcpHandlersOptions };
19
+ export { createAcpHandlers, runAcpCommand, writeAcpEvent };
@@ -0,0 +1,50 @@
1
+ import readline from 'node:readline/promises';
2
+ import { createSession, listSessions } from '../../session/session.js';
3
+ import { formatACPEvent, runAcpLoop } from '../modes/acp.js';
4
+ import { runPrintMode } from '../modes/print.js';
5
+ /** 构造 ACP method → handler 映射。chat 复用 Print 模式。 */
6
+ function createAcpHandlers(config, deps, opts) {
7
+ return {
8
+ 'session/create': async (params) => {
9
+ const title = params.title ?? 'acp-session';
10
+ const session = await createSession(deps.db, title);
11
+ return { sessionId: session.id };
12
+ },
13
+ 'session/list': async () => {
14
+ const sessions = await listSessions(deps.db);
15
+ return { sessions };
16
+ },
17
+ chat: async (params) => {
18
+ const message = params.message;
19
+ if (!message)
20
+ throw new Error('chat: message is required');
21
+ const text = await runPrintMode(config, message, deps, {
22
+ onEvent: (e) => opts.onEvent('event', e),
23
+ });
24
+ return { text };
25
+ },
26
+ abort: async () => ({ ok: true }),
27
+ 'tool/confirm': async () => ({ ok: true }),
28
+ };
29
+ }
30
+ /** 写一行 ACP event 到给定 writer(命令层用于接 stdout)。 */
31
+ function writeAcpEvent(writer, method, params) {
32
+ writer(formatACPEvent(method, params));
33
+ }
34
+ async function runAcpCommand(ctx) {
35
+ const out = ctx.stdout ?? process.stdout;
36
+ const rl = readline.createInterface({ input: ctx.stdin ?? process.stdin });
37
+ async function* reader() {
38
+ for await (const line of rl)
39
+ yield line;
40
+ }
41
+ const handlers = createAcpHandlers(ctx.config, ctx.deps, {
42
+ onEvent: (_method, params) => out.write(`${formatACPEvent('event', params)}\n`),
43
+ });
44
+ await runAcpLoop({
45
+ reader: reader(),
46
+ writer: (line) => out.write(`${line}\n`),
47
+ handlers,
48
+ });
49
+ }
50
+ export { createAcpHandlers, runAcpCommand, writeAcpEvent };
@@ -0,0 +1,13 @@
1
+ import type { LoopDeps } from '../../core/loop.js';
2
+ import type { Config } from '../../shared/types/config.js';
3
+ import type { CommandArgs } from '../parser.js';
4
+ type ChatCommandContext = {
5
+ args: CommandArgs;
6
+ config: Config;
7
+ deps: LoopDeps;
8
+ stdout?: (s: string) => void;
9
+ stderr?: (s: string) => void;
10
+ };
11
+ declare function runChatCommand(ctx: ChatCommandContext): Promise<void>;
12
+ export type { ChatCommandContext };
13
+ export { runChatCommand };
@@ -0,0 +1,26 @@
1
+ import { runPrintMode } from '../modes/print.js';
2
+ async function runChatCommand(ctx) {
3
+ const message = ctx.args.positionals.join(' ').trim();
4
+ if (!message)
5
+ throw new Error('chat: a message is required (c0de chat "your question")');
6
+ const out = ctx.stdout ?? process.stdout.write.bind(process.stdout);
7
+ const err = ctx.stderr ?? process.stderr.write.bind(process.stderr);
8
+ const format = ctx.args.options.format ?? 'text';
9
+ const model = ctx.args.options.model;
10
+ const text = await runPrintMode(ctx.config, message, ctx.deps, {
11
+ ...(model ? { model } : {}),
12
+ onEvent: (e) => {
13
+ if (e._tag === 'tool_call_start')
14
+ err(`[tool] ${e.tool}\n`);
15
+ else if (e._tag === 'thinking')
16
+ err(`[thinking] ${e.text}\n`);
17
+ },
18
+ });
19
+ if (format === 'json') {
20
+ out(`${JSON.stringify({ text })}\n`);
21
+ }
22
+ else {
23
+ out(`${text}\n`);
24
+ }
25
+ }
26
+ export { runChatCommand };
@@ -0,0 +1,17 @@
1
+ import type { CommandArgs } from '../parser.js';
2
+ type ConfigCommandContext = {
3
+ args: CommandArgs;
4
+ cwd: string;
5
+ write?: (s: string) => void;
6
+ };
7
+ /** 按 a.b.c 点路径从对象取值;找不到抛错。 */
8
+ declare function getByPath(obj: unknown, path: string): unknown;
9
+ /** 按 a.b.c 点路径写值(创建中间对象)。 */
10
+ declare function setByPath(obj: Record<string, unknown>, path: string, value: unknown): void;
11
+ /** 把字符串解析为合适的标量类型。 */
12
+ declare function coerce(value: string): unknown;
13
+ /** 构造 a.b.c → { a: { b: { c: value } } } 的 patch 对象。 */
14
+ declare function setPathPatch(path: string, value: unknown): Record<string, unknown>;
15
+ declare function runConfigCommand(ctx: ConfigCommandContext): Promise<void>;
16
+ export type { ConfigCommandContext };
17
+ export { coerce, getByPath, runConfigCommand, setByPath, setPathPatch };
@@ -0,0 +1,77 @@
1
+ import { loadConfig, mergeConfig, saveConfig } from '../../core/config.js';
2
+ /** 按 a.b.c 点路径从对象取值;找不到抛错。 */
3
+ function getByPath(obj, path) {
4
+ const parts = path.split('.');
5
+ let cur = obj;
6
+ for (const p of parts) {
7
+ if (cur === null || typeof cur !== 'object')
8
+ throw new Error(`config: key "${path}" not found`);
9
+ cur = cur[p];
10
+ if (cur === undefined)
11
+ throw new Error(`config: key "${path}" not found`);
12
+ }
13
+ return cur;
14
+ }
15
+ /** 按 a.b.c 点路径写值(创建中间对象)。 */
16
+ function setByPath(obj, path, value) {
17
+ const parts = path.split('.');
18
+ let cur = obj;
19
+ for (let i = 0; i < parts.length - 1; i++) {
20
+ const k = parts[i];
21
+ const next = cur[k];
22
+ cur[k] = (next !== null && typeof next === 'object' ? next : {});
23
+ cur = cur[k];
24
+ }
25
+ cur[parts[parts.length - 1]] = value;
26
+ }
27
+ /** 把字符串解析为合适的标量类型。 */
28
+ function coerce(value) {
29
+ if (value === 'true')
30
+ return true;
31
+ if (value === 'false')
32
+ return false;
33
+ if (/^-?\d+(\.\d+)?$/.test(value))
34
+ return Number(value);
35
+ try {
36
+ return JSON.parse(value);
37
+ }
38
+ catch {
39
+ return value;
40
+ }
41
+ }
42
+ /** 构造 a.b.c → { a: { b: { c: value } } } 的 patch 对象。 */
43
+ function setPathPatch(path, value) {
44
+ const root = {};
45
+ setByPath(root, path, value);
46
+ return root;
47
+ }
48
+ async function runConfigCommand(ctx) {
49
+ const write = ctx.write ?? process.stdout.write.bind(process.stdout);
50
+ const sub = ctx.args.positionals[0];
51
+ const config = await loadConfig(ctx.cwd);
52
+ if (sub === 'get') {
53
+ const key = ctx.args.positionals[1];
54
+ if (!key) {
55
+ write(`${JSON.stringify(config, null, 2)}\n`);
56
+ return;
57
+ }
58
+ const val = getByPath(config, key);
59
+ write(`${typeof val === 'object' ? JSON.stringify(val) : String(val)}\n`);
60
+ return;
61
+ }
62
+ if (sub === 'set') {
63
+ const key = ctx.args.positionals[1];
64
+ const rawValue = ctx.args.positionals[2];
65
+ if (!key)
66
+ throw new Error('config set: a key is required');
67
+ if (rawValue === undefined)
68
+ throw new Error('config set: a value is required');
69
+ const scope = ctx.args.options.global ? 'global' : 'project';
70
+ const merged = mergeConfig(config, setPathPatch(key, coerce(rawValue)));
71
+ await saveConfig(merged, scope, ctx.cwd);
72
+ write(`Set ${key} (scope: ${scope})\n`);
73
+ return;
74
+ }
75
+ throw new Error(`config: unknown subcommand "${sub ?? ''}" (expected get|set)`);
76
+ }
77
+ export { coerce, getByPath, runConfigCommand, setByPath, setPathPatch };
@@ -0,0 +1,9 @@
1
+ import type { CommandArgs } from '../parser.js';
2
+ type InitCommandContext = {
3
+ args: CommandArgs;
4
+ cwd: string;
5
+ log?: (s: string) => void;
6
+ };
7
+ declare function runInitCommand(ctx: InitCommandContext): Promise<void>;
8
+ export type { InitCommandContext };
9
+ export { runInitCommand };
@@ -0,0 +1,14 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { DEFAULT_CONFIG, saveConfig } from '../../core/config.js';
4
+ async function runInitCommand(ctx) {
5
+ const log = ctx.log ?? process.stdout.write.bind(process.stdout);
6
+ const force = ctx.args.options.force ?? false;
7
+ const path = join(ctx.cwd, '.c0de', 'config.json');
8
+ if (existsSync(path) && !force) {
9
+ throw new Error(`init: config already exists at ${path} (use --force to overwrite)`);
10
+ }
11
+ await saveConfig(DEFAULT_CONFIG, 'project', ctx.cwd);
12
+ log(`Created ${path}\n`);
13
+ }
14
+ export { runInitCommand };
@@ -0,0 +1,11 @@
1
+ import type { Plugin } from '../../plugins/types.js';
2
+ import type { CommandArgs } from '../parser.js';
3
+ type PluginCommandContext = {
4
+ args: CommandArgs;
5
+ cwd: string;
6
+ discover?: (cwd: string) => Promise<Plugin[]>;
7
+ write?: (s: string) => void;
8
+ };
9
+ declare function runPluginCommand(ctx: PluginCommandContext): Promise<void>;
10
+ export type { PluginCommandContext };
11
+ export { runPluginCommand };
@@ -0,0 +1,31 @@
1
+ import { loadConfig, saveConfig } from '../../core/config.js';
2
+ async function runPluginCommand(ctx) {
3
+ const write = ctx.write ?? process.stdout.write.bind(process.stdout);
4
+ const discover = ctx.discover ?? (async () => []);
5
+ const sub = ctx.args.positionals[0];
6
+ if (sub === 'list') {
7
+ const plugins = await discover(ctx.cwd);
8
+ if (plugins.length === 0) {
9
+ write('No plugins found.\n');
10
+ return;
11
+ }
12
+ for (const p of plugins) {
13
+ write(`- ${p.name}${p.version ? `@${p.version}` : ''}\n`);
14
+ }
15
+ return;
16
+ }
17
+ if (sub === 'install') {
18
+ const name = ctx.args.positionals[1];
19
+ if (!name)
20
+ throw new Error('plugin install: a plugin name is required');
21
+ const config = await loadConfig(ctx.cwd);
22
+ const enabled = config.plugins.enabled;
23
+ if (!enabled.includes(name))
24
+ enabled.push(name);
25
+ await saveConfig(config, 'project', ctx.cwd);
26
+ write(`Enabled plugin "${name}".\n`);
27
+ return;
28
+ }
29
+ throw new Error(`plugin: unknown subcommand "${sub ?? ''}" (expected list|install)`);
30
+ }
31
+ export { runPluginCommand };
@@ -0,0 +1,18 @@
1
+ import type { StartServerOptions } from '../../server/index.js';
2
+ import type { CommandArgs } from '../parser.js';
3
+ type RunningHandle = {
4
+ port: number;
5
+ close(): Promise<void>;
6
+ };
7
+ type ServeCommandContext = {
8
+ args: CommandArgs;
9
+ cwd: string;
10
+ serverStarter?: (opts: StartServerOptions) => Promise<RunningHandle>;
11
+ banner?: (s: string) => void;
12
+ opener?: (url: string) => void | Promise<void>;
13
+ /** false = 测试时不挂起进程(不 await 永久 promise)。 */
14
+ hold?: boolean;
15
+ };
16
+ declare function runServeCommand(ctx: ServeCommandContext): Promise<void>;
17
+ export type { RunningHandle, ServeCommandContext };
18
+ export { runServeCommand };
@@ -0,0 +1,35 @@
1
+ import { startServer } from '../../server/index.js';
2
+ import { openBrowser, printStartupBanner } from '../utils/output.js';
3
+ async function runServeCommand(ctx) {
4
+ const port = ctx.args.options.port ?? 3000;
5
+ const shouldOpen = ctx.args.options.open ?? true;
6
+ const starter = ctx.serverStarter ?? startServer;
7
+ const restore = ctx.args.options.restore;
8
+ const handoffPort = ctx.args.options['handoff-port'];
9
+ const handle = await starter({
10
+ port,
11
+ cwd: ctx.cwd,
12
+ ...(restore ? { restoreFrom: restore } : {}),
13
+ ...(handoffPort ? { handoffPort } : {}),
14
+ });
15
+ const url = `http://localhost:${handle.port}`;
16
+ (ctx.banner ?? printStartupBanner)(url);
17
+ if (shouldOpen) {
18
+ const opener = ctx.opener ?? ((u) => openBrowser(u));
19
+ await opener(url);
20
+ }
21
+ // 生产:阻塞直到进程被杀;测试:立即返回。
22
+ if (ctx.hold === false) {
23
+ await handle.close();
24
+ return;
25
+ }
26
+ await new Promise((resolve) => {
27
+ const shutdown = () => {
28
+ // await close 确保 PGLite WASM 正常关闭刷写 WAL,否则下次启动 dataDir 损坏 abort。
29
+ void handle.close().then(resolve);
30
+ };
31
+ process.on('SIGINT', shutdown);
32
+ process.on('SIGTERM', shutdown);
33
+ });
34
+ }
35
+ export { runServeCommand };
@@ -0,0 +1,24 @@
1
+ import type { DB } from '../../db/client.js';
2
+ import { checkForUpdate, type HotUpdateOptions } from '../../update/index.js';
3
+ import type { CommandArgs } from '../parser.js';
4
+ type UpdateCommandContext = {
5
+ args: CommandArgs;
6
+ cwd: string;
7
+ /** 可选 DB:提供则把当前会话状态序列化进快照(迁移活跃会话)。 */
8
+ db?: DB;
9
+ config?: unknown;
10
+ /** 测试注入版本检查(默认走真实 npm registry)。 */
11
+ checkFn?: typeof checkForUpdate;
12
+ /** 透传给 performHotUpdate(测试注入 install/spawn mock)。 */
13
+ updateOpts?: HotUpdateOptions;
14
+ out?: (s: string) => void;
15
+ };
16
+ /**
17
+ * `c0de update`:检查 npm registry 新版本。
18
+ * - 默认:check-only,报告有无更新。
19
+ * - `--apply`:执行热更新(序列化快照 → npm install -g → 接力新实例)。
20
+ * 活跃会话迁移需要注入 db(server 内触发时提供;独立 CLI 无活跃会话)。
21
+ */
22
+ declare function runUpdateCommand(ctx: UpdateCommandContext): Promise<void>;
23
+ export type { UpdateCommandContext };
24
+ export { runUpdateCommand };
@@ -0,0 +1,40 @@
1
+ import { checkForUpdate, performHotUpdate, serializeSessions, } from '../../update/index.js';
2
+ /**
3
+ * `c0de update`:检查 npm registry 新版本。
4
+ * - 默认:check-only,报告有无更新。
5
+ * - `--apply`:执行热更新(序列化快照 → npm install -g → 接力新实例)。
6
+ * 活跃会话迁移需要注入 db(server 内触发时提供;独立 CLI 无活跃会话)。
7
+ */
8
+ async function runUpdateCommand(ctx) {
9
+ const out = ctx.out ?? ((s) => process.stdout.write(`${s}\n`));
10
+ const check = ctx.checkFn ?? checkForUpdate;
11
+ const result = await check();
12
+ out(`当前版本 ${result.currentVersion},最新版本 ${result.latestVersion}`);
13
+ if (!result.hasUpdate) {
14
+ out('已是最新版本');
15
+ return;
16
+ }
17
+ const apply = ctx.args.options.apply ?? false;
18
+ if (!apply) {
19
+ out(`发现新版本 ${result.latestVersion}。加 --apply 执行热更新。`);
20
+ return;
21
+ }
22
+ out(`发现新版本 ${result.latestVersion},开始热更新…`);
23
+ const snapshot = ctx.db
24
+ ? await serializeSessions(ctx.db, ctx.config)
25
+ : {
26
+ version: result.currentVersion,
27
+ sessions: [],
28
+ entries: [],
29
+ config: ctx.config ?? null,
30
+ timestamp: Date.now(),
31
+ };
32
+ const r = await performHotUpdate(snapshot, ctx.updateOpts);
33
+ if (r._tag === 'success') {
34
+ out(`热更新完成,快照写入 ${r.snapshotPath}。新实例将接管。`);
35
+ }
36
+ else {
37
+ out(`热更新失败(${r._tag}):${'error' in r ? r.error : ''}`);
38
+ }
39
+ }
40
+ export { runUpdateCommand };
@@ -0,0 +1,30 @@
1
+ import type { LoopDeps } from '../core/loop.js';
2
+ import type { DB } from '../db/client.js';
3
+ import type { Registry } from '../llm/registry.js';
4
+ import type { Config } from '../shared/types/config.js';
5
+ import type { PermissionChecker } from '../tools/types.js';
6
+ /** 权限策略:
7
+ * - 'full-auto':所有工具无条件放行(print/acp 等非交互模式)。
8
+ * - 'safe'(默认):只读工具放行,写/执行工具需确认(chat 等 agent 自主执行场景)。 */
9
+ type PermissionStrategy = 'full-auto' | 'safe';
10
+ /** 真正非交互模式(print/acp):所有工具无条件放行(命令由用户显式触发)。 */
11
+ declare const fullyAutoApproveChecker: PermissionChecker;
12
+ /** 安全策略:只读工具(permission: 'auto',如 read/grep/glob/websearch)自动放行;
13
+ * 写/执行工具(permission: 'ask',如 bash/write/edit)返回 ask 需确认;
14
+ * permission: 'deny' 拒绝。复用 tools 层 autoAllowChecker(按工具自身声明的权限分级)。 */
15
+ declare const readOnlySafeChecker: PermissionChecker;
16
+ /** 把 config.providers 注册到新建的 LLM registry。 */
17
+ declare function buildLLMRegistry(config: Config): Registry;
18
+ type BuildDepsOptions = {
19
+ db: DB;
20
+ cwd: string;
21
+ /** 权限策略:'full-auto' 全部放行;'safe' 只读放行、写操作 ask。不传时按
22
+ * config.permission.defaultMode 决定('auto'→full-auto,'default'→safe)。 */
23
+ permissionStrategy?: PermissionStrategy;
24
+ /** 测试注入 mock chatStream。 */
25
+ chatStream?: LoopDeps['chatStream'];
26
+ };
27
+ /** 组装完整 LoopDeps(默认 safe 放行 + 默认工具注册表)。 */
28
+ declare function buildAgentDeps(config: Config, opts: BuildDepsOptions): Promise<LoopDeps>;
29
+ export type { BuildDepsOptions, PermissionStrategy };
30
+ export { buildAgentDeps, buildLLMRegistry, fullyAutoApproveChecker, readOnlySafeChecker };
@@ -0,0 +1,70 @@
1
+ import { decryptSecret } from '../core/secret.js';
2
+ import { createRegistry, registerProvider } from '../llm/index.js';
3
+ import { initPlugins } from '../plugins/index.js';
4
+ import { createDefaultRegistry, createDefaultURLRegistry } from '../tools/index.js';
5
+ import { autoAllowChecker } from '../tools/permission.js';
6
+ /** 真正非交互模式(print/acp):所有工具无条件放行(命令由用户显式触发)。 */
7
+ const fullyAutoApproveChecker = {
8
+ check: async (_tool, _input, _ctx) => {
9
+ return { _tag: 'allow' };
10
+ },
11
+ confirm: (_toolCallId, _approved) => { },
12
+ };
13
+ /** 安全策略:只读工具(permission: 'auto',如 read/grep/glob/websearch)自动放行;
14
+ * 写/执行工具(permission: 'ask',如 bash/write/edit)返回 ask 需确认;
15
+ * permission: 'deny' 拒绝。复用 tools 层 autoAllowChecker(按工具自身声明的权限分级)。 */
16
+ const readOnlySafeChecker = autoAllowChecker;
17
+ /** 把 config.providers 注册到新建的 LLM registry。 */
18
+ function buildLLMRegistry(config) {
19
+ const registry = createRegistry();
20
+ for (const p of config.providers) {
21
+ registerProviderFromConfig(registry, p);
22
+ }
23
+ return registry;
24
+ }
25
+ function registerProviderFromConfig(registry, p) {
26
+ // 兼容 config.json 中以 _tag 标识 provider 的格式(name 缺失时回退到 _tag)
27
+ const name = p.name || p._tag;
28
+ if (!name || !p.baseURL)
29
+ return;
30
+ // baseURL 已含 /v1 时用 /chat/completions,避免 /v1/v1 双重前缀
31
+ const path = p.baseURL.replace(/\/+$/, '').endsWith('/v1') ? '/chat/completions' : undefined;
32
+ registerProvider(registry, {
33
+ name,
34
+ baseURL: p.baseURL,
35
+ apiKey: p.apiKey ? decryptSecret(p.apiKey) : p.apiKey,
36
+ ...(path ? { path } : {}),
37
+ });
38
+ }
39
+ /** 解析权限 checker:显式策略优先,否则回退到 config.permission.defaultMode。 */
40
+ function resolvePermissionChecker(config, strategy) {
41
+ if (strategy === 'full-auto')
42
+ return fullyAutoApproveChecker;
43
+ if (strategy === 'safe')
44
+ return readOnlySafeChecker;
45
+ return config.permission.defaultMode === 'auto' ? fullyAutoApproveChecker : readOnlySafeChecker;
46
+ }
47
+ /** 组装完整 LoopDeps(默认 safe 放行 + 默认工具注册表)。 */
48
+ async function buildAgentDeps(config, opts) {
49
+ const llmRegistry = buildLLMRegistry(config);
50
+ const toolRegistry = createDefaultRegistry(config);
51
+ const { hookRunner } = await initPlugins({
52
+ cwd: opts.cwd,
53
+ config,
54
+ toolRegistry,
55
+ llmRegistry,
56
+ });
57
+ const deps = {
58
+ db: opts.db,
59
+ llmRegistry,
60
+ toolRegistry,
61
+ urlRegistry: createDefaultURLRegistry(),
62
+ hookRunner,
63
+ permission: resolvePermissionChecker(config, opts.permissionStrategy),
64
+ config,
65
+ cwd: opts.cwd,
66
+ ...(opts.chatStream ? { chatStream: opts.chatStream } : {}),
67
+ };
68
+ return deps;
69
+ }
70
+ export { buildAgentDeps, buildLLMRegistry, fullyAutoApproveChecker, readOnlySafeChecker };
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import type { CommandSpec } from './parser.js';
3
+ declare const COMMANDS: CommandSpec[];
4
+ type DispatchOverrides = {
5
+ runServe?: () => Promise<void>;
6
+ };
7
+ declare function dispatch(argv: string[], overrides?: DispatchOverrides): Promise<void>;
8
+ export { COMMANDS, dispatch };