@xyit/wellspring 0.0.0-stage → 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 (464) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +853 -2
  3. package/dist/agent/pending-asks.d.ts +20 -0
  4. package/dist/agent/pending-asks.js +70 -0
  5. package/dist/agent/pending-asks.js.map +1 -0
  6. package/dist/agent/task-registry.d.ts +14 -0
  7. package/dist/agent/task-registry.js +80 -0
  8. package/dist/agent/task-registry.js.map +1 -0
  9. package/dist/agent/tool-context.d.ts +30 -0
  10. package/dist/agent/tool-context.js +10 -0
  11. package/dist/agent/tool-context.js.map +1 -0
  12. package/dist/agent/usage.d.ts +40 -0
  13. package/dist/agent/usage.js +122 -0
  14. package/dist/agent/usage.js.map +1 -0
  15. package/dist/api/host/agent.d.ts +165 -0
  16. package/dist/api/host/agent.js +5 -0
  17. package/dist/api/host/agent.js.map +1 -0
  18. package/dist/api/host/events.d.ts +2 -0
  19. package/dist/api/host/events.js +6 -0
  20. package/dist/api/host/events.js.map +1 -0
  21. package/dist/api/host/exec.d.ts +36 -0
  22. package/dist/api/host/exec.js +10 -0
  23. package/dist/api/host/exec.js.map +1 -0
  24. package/dist/api/host/fs.d.ts +24 -0
  25. package/dist/api/host/fs.js +7 -0
  26. package/dist/api/host/fs.js.map +1 -0
  27. package/dist/api/host/hooks.d.ts +210 -0
  28. package/dist/api/host/hooks.js +401 -0
  29. package/dist/api/host/hooks.js.map +1 -0
  30. package/dist/api/host/host.d.ts +36 -0
  31. package/dist/api/host/host.js +53 -0
  32. package/dist/api/host/host.js.map +1 -0
  33. package/dist/api/host/http.d.ts +58 -0
  34. package/dist/api/host/http.js +6 -0
  35. package/dist/api/host/http.js.map +1 -0
  36. package/dist/api/host/index.d.ts +15 -0
  37. package/dist/api/host/index.js +20 -0
  38. package/dist/api/host/index.js.map +1 -0
  39. package/dist/api/host/models.d.ts +65 -0
  40. package/dist/api/host/models.js +8 -0
  41. package/dist/api/host/models.js.map +1 -0
  42. package/dist/api/host/network.d.ts +22 -0
  43. package/dist/api/host/network.js +7 -0
  44. package/dist/api/host/network.js.map +1 -0
  45. package/dist/api/host/plugin.d.ts +138 -0
  46. package/dist/api/host/plugin.js +6 -0
  47. package/dist/api/host/plugin.js.map +1 -0
  48. package/dist/api/host/plugins.d.ts +49 -0
  49. package/dist/api/host/plugins.js +6 -0
  50. package/dist/api/host/plugins.js.map +1 -0
  51. package/dist/api/host/pty.d.ts +55 -0
  52. package/dist/api/host/pty.js +21 -0
  53. package/dist/api/host/pty.js.map +1 -0
  54. package/dist/api/host/session.d.ts +5 -0
  55. package/dist/api/host/session.js +52 -0
  56. package/dist/api/host/session.js.map +1 -0
  57. package/dist/api/host/version.d.ts +2 -0
  58. package/dist/api/host/version.js +3 -0
  59. package/dist/api/host/version.js.map +1 -0
  60. package/dist/api/host/workspace.d.ts +38 -0
  61. package/dist/api/host/workspace.js +9 -0
  62. package/dist/api/host/workspace.js.map +1 -0
  63. package/dist/api/plugin/http-client.d.ts +42 -0
  64. package/dist/api/plugin/http-client.js +364 -0
  65. package/dist/api/plugin/http-client.js.map +1 -0
  66. package/dist/api/plugin/http-protocol.d.ts +152 -0
  67. package/dist/api/plugin/http-protocol.js +49 -0
  68. package/dist/api/plugin/http-protocol.js.map +1 -0
  69. package/dist/api/result/result.d.ts +16 -0
  70. package/dist/api/result/result.js +43 -0
  71. package/dist/api/result/result.js.map +1 -0
  72. package/dist/commands/agent-turn.d.ts +63 -0
  73. package/dist/commands/agent-turn.js +687 -0
  74. package/dist/commands/agent-turn.js.map +1 -0
  75. package/dist/commands/ask-prompt.d.ts +6 -0
  76. package/dist/commands/ask-prompt.js +49 -0
  77. package/dist/commands/ask-prompt.js.map +1 -0
  78. package/dist/commands/config.d.ts +2 -0
  79. package/dist/commands/config.js +283 -0
  80. package/dist/commands/config.js.map +1 -0
  81. package/dist/commands/conversation.d.ts +51 -0
  82. package/dist/commands/conversation.js +630 -0
  83. package/dist/commands/conversation.js.map +1 -0
  84. package/dist/commands/doctor.d.ts +2 -0
  85. package/dist/commands/doctor.js +77 -0
  86. package/dist/commands/doctor.js.map +1 -0
  87. package/dist/commands/exec-approval.d.ts +3 -0
  88. package/dist/commands/exec-approval.js +80 -0
  89. package/dist/commands/exec-approval.js.map +1 -0
  90. package/dist/commands/help.d.ts +2 -0
  91. package/dist/commands/help.js +35 -0
  92. package/dist/commands/help.js.map +1 -0
  93. package/dist/commands/key.d.ts +2 -0
  94. package/dist/commands/key.js +226 -0
  95. package/dist/commands/key.js.map +1 -0
  96. package/dist/commands/plugin.d.ts +2 -0
  97. package/dist/commands/plugin.js +190 -0
  98. package/dist/commands/plugin.js.map +1 -0
  99. package/dist/commands/session.d.ts +2 -0
  100. package/dist/commands/session.js +167 -0
  101. package/dist/commands/session.js.map +1 -0
  102. package/dist/commands/shared.d.ts +35 -0
  103. package/dist/commands/shared.js +66 -0
  104. package/dist/commands/shared.js.map +1 -0
  105. package/dist/commands/start.d.ts +2 -0
  106. package/dist/commands/start.js +75 -0
  107. package/dist/commands/start.js.map +1 -0
  108. package/dist/commands/stop.d.ts +2 -0
  109. package/dist/commands/stop.js +24 -0
  110. package/dist/commands/stop.js.map +1 -0
  111. package/dist/commands/version.d.ts +2 -0
  112. package/dist/commands/version.js +33 -0
  113. package/dist/commands/version.js.map +1 -0
  114. package/dist/config/codes.d.ts +13 -0
  115. package/dist/config/codes.js +15 -0
  116. package/dist/config/codes.js.map +1 -0
  117. package/dist/config/credentials.d.ts +67 -0
  118. package/dist/config/credentials.js +214 -0
  119. package/dist/config/credentials.js.map +1 -0
  120. package/dist/config/defaults.d.ts +5 -0
  121. package/dist/config/defaults.js +31 -0
  122. package/dist/config/defaults.js.map +1 -0
  123. package/dist/config/index.d.ts +5 -0
  124. package/dist/config/index.js +10 -0
  125. package/dist/config/index.js.map +1 -0
  126. package/dist/config/loader.d.ts +10 -0
  127. package/dist/config/loader.js +68 -0
  128. package/dist/config/loader.js.map +1 -0
  129. package/dist/config/providers.d.ts +30 -0
  130. package/dist/config/providers.js +97 -0
  131. package/dist/config/providers.js.map +1 -0
  132. package/dist/config/types.d.ts +75 -0
  133. package/dist/config/types.js +4 -0
  134. package/dist/config/types.js.map +1 -0
  135. package/dist/config/validate.d.ts +4 -0
  136. package/dist/config/validate.js +391 -0
  137. package/dist/config/validate.js.map +1 -0
  138. package/dist/display/markdown.d.ts +7 -0
  139. package/dist/display/markdown.js +116 -0
  140. package/dist/display/markdown.js.map +1 -0
  141. package/dist/display/tool-label.d.ts +6 -0
  142. package/dist/display/tool-label.js +81 -0
  143. package/dist/display/tool-label.js.map +1 -0
  144. package/dist/event/event.d.ts +27 -0
  145. package/dist/event/event.js +152 -0
  146. package/dist/event/event.js.map +1 -0
  147. package/dist/index.d.ts +2 -0
  148. package/dist/index.js +308 -0
  149. package/dist/index.js.map +1 -0
  150. package/dist/input/codes.d.ts +15 -0
  151. package/dist/input/codes.js +20 -0
  152. package/dist/input/codes.js.map +1 -0
  153. package/dist/input/commands.d.ts +10 -0
  154. package/dist/input/commands.js +65 -0
  155. package/dist/input/commands.js.map +1 -0
  156. package/dist/input/help.d.ts +8 -0
  157. package/dist/input/help.js +51 -0
  158. package/dist/input/help.js.map +1 -0
  159. package/dist/input/index.d.ts +6 -0
  160. package/dist/input/index.js +10 -0
  161. package/dist/input/index.js.map +1 -0
  162. package/dist/input/parse-options.d.ts +11 -0
  163. package/dist/input/parse-options.js +51 -0
  164. package/dist/input/parse-options.js.map +1 -0
  165. package/dist/input/parse.d.ts +3 -0
  166. package/dist/input/parse.js +119 -0
  167. package/dist/input/parse.js.map +1 -0
  168. package/dist/input/types.d.ts +17 -0
  169. package/dist/input/types.js +2 -0
  170. package/dist/input/types.js.map +1 -0
  171. package/dist/logger/elog4js.d.ts +65 -0
  172. package/dist/logger/elog4js.js +305 -0
  173. package/dist/logger/elog4js.js.map +1 -0
  174. package/dist/logger/logger.d.ts +37 -0
  175. package/dist/logger/logger.js +196 -0
  176. package/dist/logger/logger.js.map +1 -0
  177. package/dist/network/index.d.ts +2 -0
  178. package/dist/network/index.js +6 -0
  179. package/dist/network/index.js.map +1 -0
  180. package/dist/network/openai.d.ts +117 -0
  181. package/dist/network/openai.js +443 -0
  182. package/dist/network/openai.js.map +1 -0
  183. package/dist/network/proxy.d.ts +9 -0
  184. package/dist/network/proxy.js +72 -0
  185. package/dist/network/proxy.js.map +1 -0
  186. package/dist/network/web.d.ts +34 -0
  187. package/dist/network/web.js +152 -0
  188. package/dist/network/web.js.map +1 -0
  189. package/dist/platform/clipboard.d.ts +15 -0
  190. package/dist/platform/clipboard.js +82 -0
  191. package/dist/platform/clipboard.js.map +1 -0
  192. package/dist/platform/exec.d.ts +28 -0
  193. package/dist/platform/exec.js +95 -0
  194. package/dist/platform/exec.js.map +1 -0
  195. package/dist/platform/file.d.ts +38 -0
  196. package/dist/platform/file.js +197 -0
  197. package/dist/platform/file.js.map +1 -0
  198. package/dist/platform/index.d.ts +7 -0
  199. package/dist/platform/index.js +12 -0
  200. package/dist/platform/index.js.map +1 -0
  201. package/dist/platform/notification.d.ts +14 -0
  202. package/dist/platform/notification.js +82 -0
  203. package/dist/platform/notification.js.map +1 -0
  204. package/dist/platform/open-external.d.ts +10 -0
  205. package/dist/platform/open-external.js +105 -0
  206. package/dist/platform/open-external.js.map +1 -0
  207. package/dist/platform/os.d.ts +20 -0
  208. package/dist/platform/os.js +86 -0
  209. package/dist/platform/os.js.map +1 -0
  210. package/dist/platform/path.d.ts +32 -0
  211. package/dist/platform/path.js +154 -0
  212. package/dist/platform/path.js.map +1 -0
  213. package/dist/plugin/access-guard.d.ts +1 -0
  214. package/dist/plugin/access-guard.js +40 -0
  215. package/dist/plugin/access-guard.js.map +1 -0
  216. package/dist/plugin/agent-service.d.ts +25 -0
  217. package/dist/plugin/agent-service.js +809 -0
  218. package/dist/plugin/agent-service.js.map +1 -0
  219. package/dist/plugin/agent-tools.d.ts +12 -0
  220. package/dist/plugin/agent-tools.js +31 -0
  221. package/dist/plugin/agent-tools.js.map +1 -0
  222. package/dist/plugin/capabilities.d.ts +26 -0
  223. package/dist/plugin/capabilities.js +192 -0
  224. package/dist/plugin/capabilities.js.map +1 -0
  225. package/dist/plugin/console-guard.d.ts +2 -0
  226. package/dist/plugin/console-guard.js +52 -0
  227. package/dist/plugin/console-guard.js.map +1 -0
  228. package/dist/plugin/data-access.d.ts +15 -0
  229. package/dist/plugin/data-access.js +57 -0
  230. package/dist/plugin/data-access.js.map +1 -0
  231. package/dist/plugin/fs.d.ts +3 -0
  232. package/dist/plugin/fs.js +93 -0
  233. package/dist/plugin/fs.js.map +1 -0
  234. package/dist/plugin/host-alias.d.ts +2 -0
  235. package/dist/plugin/host-alias.js +57 -0
  236. package/dist/plugin/host-alias.js.map +1 -0
  237. package/dist/plugin/index.d.ts +7 -0
  238. package/dist/plugin/index.js +11 -0
  239. package/dist/plugin/index.js.map +1 -0
  240. package/dist/plugin/install.d.ts +17 -0
  241. package/dist/plugin/install.js +163 -0
  242. package/dist/plugin/install.js.map +1 -0
  243. package/dist/plugin/loader.d.ts +45 -0
  244. package/dist/plugin/loader.js +739 -0
  245. package/dist/plugin/loader.js.map +1 -0
  246. package/dist/plugin/manage.d.ts +31 -0
  247. package/dist/plugin/manage.js +271 -0
  248. package/dist/plugin/manage.js.map +1 -0
  249. package/dist/plugin/models-service.d.ts +15 -0
  250. package/dist/plugin/models-service.js +317 -0
  251. package/dist/plugin/models-service.js.map +1 -0
  252. package/dist/plugin/network-service.d.ts +10 -0
  253. package/dist/plugin/network-service.js +87 -0
  254. package/dist/plugin/network-service.js.map +1 -0
  255. package/dist/plugin/package-manager.d.ts +46 -0
  256. package/dist/plugin/package-manager.js +148 -0
  257. package/dist/plugin/package-manager.js.map +1 -0
  258. package/dist/plugin/paths.d.ts +6 -0
  259. package/dist/plugin/paths.js +15 -0
  260. package/dist/plugin/paths.js.map +1 -0
  261. package/dist/plugin/registry.d.ts +17 -0
  262. package/dist/plugin/registry.js +82 -0
  263. package/dist/plugin/registry.js.map +1 -0
  264. package/dist/plugin/runtime.d.ts +9 -0
  265. package/dist/plugin/runtime.js +43 -0
  266. package/dist/plugin/runtime.js.map +1 -0
  267. package/dist/plugin/scaffold.d.ts +13 -0
  268. package/dist/plugin/scaffold.js +132 -0
  269. package/dist/plugin/scaffold.js.map +1 -0
  270. package/dist/plugin/state.d.ts +6 -0
  271. package/dist/plugin/state.js +38 -0
  272. package/dist/plugin/state.js.map +1 -0
  273. package/dist/plugin/zip.d.ts +7 -0
  274. package/dist/plugin/zip.js +138 -0
  275. package/dist/plugin/zip.js.map +1 -0
  276. package/dist/sandbox/audit.d.ts +12 -0
  277. package/dist/sandbox/audit.js +20 -0
  278. package/dist/sandbox/audit.js.map +1 -0
  279. package/dist/sandbox/backends/bwrap.d.ts +28 -0
  280. package/dist/sandbox/backends/bwrap.js +197 -0
  281. package/dist/sandbox/backends/bwrap.js.map +1 -0
  282. package/dist/sandbox/backends/direct.d.ts +7 -0
  283. package/dist/sandbox/backends/direct.js +32 -0
  284. package/dist/sandbox/backends/direct.js.map +1 -0
  285. package/dist/sandbox/bridge-state.d.ts +13 -0
  286. package/dist/sandbox/bridge-state.js +12 -0
  287. package/dist/sandbox/bridge-state.js.map +1 -0
  288. package/dist/sandbox/index.d.ts +5 -0
  289. package/dist/sandbox/index.js +6 -0
  290. package/dist/sandbox/index.js.map +1 -0
  291. package/dist/sandbox/manager.d.ts +8 -0
  292. package/dist/sandbox/manager.js +325 -0
  293. package/dist/sandbox/manager.js.map +1 -0
  294. package/dist/sandbox/memory-limit.d.ts +44 -0
  295. package/dist/sandbox/memory-limit.js +193 -0
  296. package/dist/sandbox/memory-limit.js.map +1 -0
  297. package/dist/sandbox/plugin-client.d.ts +80 -0
  298. package/dist/sandbox/plugin-client.js +1601 -0
  299. package/dist/sandbox/plugin-client.js.map +1 -0
  300. package/dist/sandbox/plugin-host.d.ts +1 -0
  301. package/dist/sandbox/plugin-host.js +1001 -0
  302. package/dist/sandbox/plugin-host.js.map +1 -0
  303. package/dist/sandbox/protocol.d.ts +43 -0
  304. package/dist/sandbox/protocol.js +96 -0
  305. package/dist/sandbox/protocol.js.map +1 -0
  306. package/dist/sandbox/rpc-timeouts.d.ts +28 -0
  307. package/dist/sandbox/rpc-timeouts.js +15 -0
  308. package/dist/sandbox/rpc-timeouts.js.map +1 -0
  309. package/dist/sandbox/supervisor.d.ts +31 -0
  310. package/dist/sandbox/supervisor.js +114 -0
  311. package/dist/sandbox/supervisor.js.map +1 -0
  312. package/dist/sandbox/types.d.ts +124 -0
  313. package/dist/sandbox/types.js +17 -0
  314. package/dist/sandbox/types.js.map +1 -0
  315. package/dist/service/control.d.ts +32 -0
  316. package/dist/service/control.js +117 -0
  317. package/dist/service/control.js.map +1 -0
  318. package/dist/session/compress.d.ts +3 -0
  319. package/dist/session/compress.js +42 -0
  320. package/dist/session/compress.js.map +1 -0
  321. package/dist/session/index.d.ts +4 -0
  322. package/dist/session/index.js +8 -0
  323. package/dist/session/index.js.map +1 -0
  324. package/dist/session/registry.d.ts +4 -0
  325. package/dist/session/registry.js +12 -0
  326. package/dist/session/registry.js.map +1 -0
  327. package/dist/session/replay.d.ts +10 -0
  328. package/dist/session/replay.js +109 -0
  329. package/dist/session/replay.js.map +1 -0
  330. package/dist/session/session.d.ts +40 -0
  331. package/dist/session/session.js +108 -0
  332. package/dist/session/session.js.map +1 -0
  333. package/dist/session/store.d.ts +58 -0
  334. package/dist/session/store.js +382 -0
  335. package/dist/session/store.js.map +1 -0
  336. package/dist/session/types.d.ts +56 -0
  337. package/dist/session/types.js +3 -0
  338. package/dist/session/types.js.map +1 -0
  339. package/dist/workspace/index.d.ts +7 -0
  340. package/dist/workspace/index.js +17 -0
  341. package/dist/workspace/index.js.map +1 -0
  342. package/dist/workspace/registry.d.ts +25 -0
  343. package/dist/workspace/registry.js +293 -0
  344. package/dist/workspace/registry.js.map +1 -0
  345. package/package.json +73 -5
  346. package/scripts/build-node-pty.mjs +55 -0
  347. package/scripts/rewrite-dts.mjs +36 -0
  348. package/scripts/run-tests.mjs +41 -0
  349. package/scripts/verify-sandbox.ts +98 -0
  350. package/src/agent/pending-asks.ts +88 -0
  351. package/src/agent/task-registry.ts +108 -0
  352. package/src/agent/tool-context.ts +47 -0
  353. package/src/agent/usage.ts +170 -0
  354. package/src/api/host/agent.ts +162 -0
  355. package/src/api/host/events.ts +7 -0
  356. package/src/api/host/exec.ts +47 -0
  357. package/src/api/host/fs.ts +33 -0
  358. package/src/api/host/hooks.ts +635 -0
  359. package/src/api/host/host.ts +99 -0
  360. package/src/api/host/http.ts +79 -0
  361. package/src/api/host/index.ts +20 -0
  362. package/src/api/host/models.ts +81 -0
  363. package/src/api/host/network.ts +32 -0
  364. package/src/api/host/plugin.ts +158 -0
  365. package/src/api/host/plugins.ts +59 -0
  366. package/src/api/host/pty.ts +73 -0
  367. package/src/api/host/session.ts +61 -0
  368. package/src/api/host/version.ts +2 -0
  369. package/src/api/host/workspace.ts +51 -0
  370. package/src/api/plugin/http-client.ts +492 -0
  371. package/src/api/plugin/http-protocol.ts +231 -0
  372. package/src/api/result/result.ts +52 -0
  373. package/src/commands/agent-turn.ts +817 -0
  374. package/src/commands/ask-prompt.ts +52 -0
  375. package/src/commands/config.ts +306 -0
  376. package/src/commands/conversation.ts +777 -0
  377. package/src/commands/doctor.ts +92 -0
  378. package/src/commands/exec-approval.ts +91 -0
  379. package/src/commands/help.ts +41 -0
  380. package/src/commands/key.ts +281 -0
  381. package/src/commands/plugin.ts +222 -0
  382. package/src/commands/session.ts +179 -0
  383. package/src/commands/shared.ts +103 -0
  384. package/src/commands/start.ts +88 -0
  385. package/src/commands/stop.ts +24 -0
  386. package/src/commands/version.ts +40 -0
  387. package/src/config/codes.ts +17 -0
  388. package/src/config/credentials.ts +302 -0
  389. package/src/config/defaults.ts +32 -0
  390. package/src/config/index.ts +10 -0
  391. package/src/config/loader.ts +80 -0
  392. package/src/config/providers.ts +133 -0
  393. package/src/config/types.ts +88 -0
  394. package/src/config/validate.ts +458 -0
  395. package/src/display/markdown.ts +137 -0
  396. package/src/display/tool-label.ts +87 -0
  397. package/src/event/event.ts +171 -0
  398. package/src/index.ts +344 -0
  399. package/src/input/codes.ts +21 -0
  400. package/src/input/commands.ts +76 -0
  401. package/src/input/help.ts +60 -0
  402. package/src/input/index.ts +10 -0
  403. package/src/input/parse-options.ts +66 -0
  404. package/src/input/parse.ts +138 -0
  405. package/src/input/types.ts +19 -0
  406. package/src/logger/elog4js.ts +366 -0
  407. package/src/logger/logger.ts +251 -0
  408. package/src/network/index.ts +6 -0
  409. package/src/network/openai.ts +571 -0
  410. package/src/network/proxy.ts +80 -0
  411. package/src/network/web.ts +206 -0
  412. package/src/platform/clipboard.ts +107 -0
  413. package/src/platform/exec.ts +128 -0
  414. package/src/platform/file.ts +235 -0
  415. package/src/platform/index.ts +12 -0
  416. package/src/platform/notification.ts +108 -0
  417. package/src/platform/open-external.ts +132 -0
  418. package/src/platform/os.ts +101 -0
  419. package/src/platform/path.ts +214 -0
  420. package/src/plugin/access-guard.ts +46 -0
  421. package/src/plugin/agent-service.ts +969 -0
  422. package/src/plugin/agent-tools.ts +43 -0
  423. package/src/plugin/capabilities.ts +240 -0
  424. package/src/plugin/console-guard.ts +66 -0
  425. package/src/plugin/data-access.ts +70 -0
  426. package/src/plugin/fs.ts +109 -0
  427. package/src/plugin/host-alias.ts +61 -0
  428. package/src/plugin/index.ts +11 -0
  429. package/src/plugin/install.ts +213 -0
  430. package/src/plugin/loader.ts +952 -0
  431. package/src/plugin/manage.ts +338 -0
  432. package/src/plugin/models-service.ts +383 -0
  433. package/src/plugin/network-service.ts +102 -0
  434. package/src/plugin/package-manager.ts +214 -0
  435. package/src/plugin/paths.ts +19 -0
  436. package/src/plugin/registry.ts +103 -0
  437. package/src/plugin/runtime.ts +57 -0
  438. package/src/plugin/scaffold.ts +158 -0
  439. package/src/plugin/state.ts +52 -0
  440. package/src/plugin/zip.ts +156 -0
  441. package/src/sandbox/audit.ts +38 -0
  442. package/src/sandbox/backends/bwrap.ts +251 -0
  443. package/src/sandbox/backends/direct.ts +43 -0
  444. package/src/sandbox/bridge-state.ts +29 -0
  445. package/src/sandbox/index.ts +5 -0
  446. package/src/sandbox/manager.ts +406 -0
  447. package/src/sandbox/memory-limit.ts +245 -0
  448. package/src/sandbox/plugin-client.ts +1881 -0
  449. package/src/sandbox/plugin-host.ts +1282 -0
  450. package/src/sandbox/protocol.ts +142 -0
  451. package/src/sandbox/pty-bridge.py +154 -0
  452. package/src/sandbox/rpc-timeouts.ts +43 -0
  453. package/src/sandbox/supervisor.ts +172 -0
  454. package/src/sandbox/types.ts +149 -0
  455. package/src/service/control.ts +155 -0
  456. package/src/session/compress.ts +47 -0
  457. package/src/session/index.ts +8 -0
  458. package/src/session/registry.ts +17 -0
  459. package/src/session/replay.ts +132 -0
  460. package/src/session/session.ts +134 -0
  461. package/src/session/store.ts +468 -0
  462. package/src/session/types.ts +61 -0
  463. package/src/workspace/index.ts +21 -0
  464. package/src/workspace/registry.ts +356 -0
@@ -0,0 +1,171 @@
1
+ /*
2
+ * EventEntity / EventBus
3
+ *
4
+ * EventEntity 的负载只读,取消状态可变:监听器对事件实例调 cancel 后
5
+ * isCancelled 立即为 true,EventBus 据此终止后续传播
6
+ * 取消不回滚已完成的投递
7
+ */
8
+
9
+ export class EventEntity<T> {
10
+ private readonly data: T
11
+ private cancelled: boolean
12
+ private cancelReason: string
13
+
14
+ private constructor(data: T, cancelled = false, cancelReason = "") {
15
+ this.data = data
16
+ this.cancelled = cancelled
17
+ this.cancelReason = cancelReason
18
+ }
19
+
20
+ public static create<T>(data: T, cancelled = false, cancelReason = ""): EventEntity<T> {
21
+ return new EventEntity(data, cancelled, cancelReason)
22
+ }
23
+
24
+ public cancel(reason = ""): this {
25
+ this.cancelled = true
26
+ this.cancelReason = reason
27
+ return this
28
+ }
29
+
30
+ public getData(): T {
31
+ return this.data
32
+ }
33
+ public isCancelled(): boolean {
34
+ return this.cancelled
35
+ }
36
+ public getCancelReason(): string {
37
+ return this.cancelReason
38
+ }
39
+ }
40
+
41
+ import { getHostBridge } from "../sandbox/bridge-state.ts"
42
+
43
+ export type EventListener<T = unknown> = (event: EventEntity<T>) => void
44
+
45
+ // 存储层擦除负载类型:同一总线容纳各事件名的监听器
46
+ type ListenerRecord = {
47
+ readonly fn: EventListener<any>
48
+ active: boolean
49
+ }
50
+
51
+ export class EventBus {
52
+ private readonly listeners = new Map<string, ListenerRecord[]>()
53
+ private readonly bridgeSubscriptions = new Set<string>()
54
+
55
+ subscribe<T>(eventName: string, listener: EventListener<T>): () => void {
56
+ if (typeof listener !== "function") {
57
+ throw new TypeError(`监听器不是函数:${eventName}`)
58
+ }
59
+ const record: ListenerRecord = { fn: listener, active: true }
60
+ const bridge = getHostBridge()
61
+ if (bridge !== null && !this.bridgeSubscriptions.has(eventName)) {
62
+ this.bridgeSubscriptions.add(eventName)
63
+ void bridge.request("host.event.subscribe", { name: eventName }).catch(() => undefined)
64
+ }
65
+ const handlers = this.listeners.get(eventName)
66
+ if (handlers) {
67
+ handlers.push(record)
68
+ } else {
69
+ this.listeners.set(eventName, [record])
70
+ }
71
+
72
+ return () => this.remove(eventName, record)
73
+ }
74
+
75
+ publish<T>(eventName: string, event: EventEntity<T>): void {
76
+ const bridge = getHostBridge()
77
+ if (bridge !== null) {
78
+ bridge.notify("host.event.publish", { name: eventName, data: event.getData() })
79
+ return
80
+ }
81
+ this.deliverLocal(eventName, event)
82
+ }
83
+
84
+ /** sandbox bridge 收到宿主事件后在本进程投递 */
85
+ receive<T>(eventName: string, data: T): void {
86
+ this.deliverLocal(eventName, EventEntity.create(data))
87
+ }
88
+
89
+ private deliverLocal<T>(eventName: string, event: EventEntity<T>): void {
90
+ const handlers = this.listeners.get(eventName)
91
+ if (!handlers || handlers.length === 0) {
92
+ return
93
+ }
94
+
95
+ let firstError: unknown
96
+ let failed = false
97
+ // 快照后校验存活状态:本轮回调内的退订对后续监听器生效
98
+ for (const record of handlers.slice()) {
99
+ if (!record.active) continue
100
+ if (event.isCancelled()) break
101
+ try {
102
+ record.fn(event)
103
+ } catch (error) {
104
+ // 单监听器异常不中断其余监听器,循环结束后抛出首个异常
105
+ if (!failed) {
106
+ firstError = error
107
+ failed = true
108
+ }
109
+ }
110
+ }
111
+ if (failed) {
112
+ throw firstError
113
+ }
114
+ }
115
+
116
+ once<T>(eventName: string, listener: EventListener<T>): () => void {
117
+ const unsubscribe = this.subscribe<T>(eventName, (event) => {
118
+ // 先退订再回调:回调内重入发布不会二次触发,回调抛错也不残留订阅
119
+ unsubscribe()
120
+ listener(event)
121
+ })
122
+ return unsubscribe
123
+ }
124
+
125
+ clear(eventName: string): void {
126
+ this.unsubscribeBridge(eventName)
127
+ const handlers = this.listeners.get(eventName)
128
+ if (!handlers) return
129
+ for (const record of handlers) {
130
+ record.active = false
131
+ }
132
+ this.listeners.delete(eventName)
133
+ }
134
+
135
+ clearAll(): void {
136
+ for (const eventName of [...this.bridgeSubscriptions]) {
137
+ this.unsubscribeBridge(eventName)
138
+ }
139
+ for (const handlers of this.listeners.values()) {
140
+ for (const record of handlers) {
141
+ record.active = false
142
+ }
143
+ }
144
+ this.listeners.clear()
145
+ }
146
+
147
+ private remove(eventName: string, record: ListenerRecord): void {
148
+ if (!record.active) return
149
+ record.active = false
150
+ const handlers = this.listeners.get(eventName)
151
+ if (!handlers) return
152
+ const index = handlers.indexOf(record)
153
+ if (index !== -1) {
154
+ handlers.splice(index, 1)
155
+ }
156
+ if (handlers.length === 0) {
157
+ this.listeners.delete(eventName)
158
+ this.unsubscribeBridge(eventName)
159
+ }
160
+ }
161
+
162
+ private unsubscribeBridge(eventName: string): void {
163
+ if (!this.bridgeSubscriptions.delete(eventName)) {
164
+ return
165
+ }
166
+ const bridge = getHostBridge()
167
+ bridge?.notify("host.event.unsubscribe", { name: eventName })
168
+ }
169
+ }
170
+
171
+ export const eventBus = new EventBus()
package/src/index.ts ADDED
@@ -0,0 +1,344 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ * Wellspring CLI 入口。
4
+ * 解析全局参数 → 应用目录/日志覆盖 → 加载配置与插件 → 分发命令。
5
+ */
6
+
7
+ import { resolve } from "node:path"
8
+
9
+ import type { HostOutput, PluginCommandContext } from "./api/host/plugin.ts"
10
+ import { configureHost, setHostStatus } from "./api/host/host.ts"
11
+ import { setHookErrorHandler, setHookGuard, withHookOwner } from "./api/host/hooks.ts"
12
+ import { runConfigCommand } from "./commands/config.ts"
13
+ import { runConversationCommand } from "./commands/conversation.ts"
14
+ import { runDoctorCommand } from "./commands/doctor.ts"
15
+ import { runHelpCommand } from "./commands/help.ts"
16
+ import { runKeyCommand } from "./commands/key.ts"
17
+ import { runPluginCommand } from "./commands/plugin.ts"
18
+ import {
19
+ errorMessage,
20
+ exitCodeFor,
21
+ failure,
22
+ type CommandContext,
23
+ type CommandOutcome,
24
+ } from "./commands/shared.ts"
25
+ import { runSessionCommand } from "./commands/session.ts"
26
+ import { runStartCommand } from "./commands/start.ts"
27
+ import { runStopCommand } from "./commands/stop.ts"
28
+ import { runVersionCommand } from "./commands/version.ts"
29
+ import { credentialsFile } from "./config/credentials.ts"
30
+ import {
31
+ activeModelProvider,
32
+ effectiveModel,
33
+ effectiveReasoning,
34
+ providerApiKey,
35
+ providerOpenAISettings,
36
+ } from "./config/providers.ts"
37
+ import { DEFAULT_SETTINGS } from "./config/defaults.ts"
38
+ import { loadSettings, SETTING_FILE_NAME } from "./config/loader.ts"
39
+ import type { AppSetting } from "./config/types.ts"
40
+ import { BUILTIN_NAMES, findBuiltin } from "./input/commands.ts"
41
+ import { parseGlobal } from "./input/parse.ts"
42
+ import type { GlobalOptions } from "./input/types.ts"
43
+ import { getElog, initElog } from "./logger/elog4js.ts"
44
+ import { closeLogger, initLogger } from "./logger/logger.ts"
45
+ import { initOpenAIClient, type OpenAIClient } from "./network/openai.ts"
46
+ import { createProxyFetch } from "./network/proxy.ts"
47
+ import { getPaths } from "./platform/path.ts"
48
+ import { withConsoleGuard } from "./plugin/console-guard.ts"
49
+ import { loadPlugins, type LoadedPlugin } from "./plugin/loader.ts"
50
+ import { createPluginFileApi } from "./plugin/fs.ts"
51
+ import { ensurePluginDataDir, loadPluginConfig } from "./plugin/runtime.ts"
52
+ import { shutdownAllSandboxPlugins } from "./sandbox/plugin-client.ts"
53
+ import { AgentToolRegistry } from "./plugin/agent-tools.ts"
54
+ import { PluginRegistry } from "./plugin/registry.ts"
55
+
56
+ function printParseError(code: string): void {
57
+ const elog = getElog()
58
+ elog.error(errorMessage(code))
59
+ elog.notice("运行 wellspring --help 查看用法")
60
+ process.exitCode = 2
61
+ }
62
+
63
+ function emitOutcome(outcome: CommandOutcome, json: boolean): void {
64
+ const code = outcome.result.getCode()
65
+ if (json) {
66
+ const payload = {
67
+ success: outcome.result.isSuccess(),
68
+ code: outcome.result.isSuccess() ? null : code,
69
+ data: outcome.result.isSuccess() ? outcome.result.getData() : null,
70
+ }
71
+ process.stdout.write(`${JSON.stringify(payload)}\n`)
72
+ } else if (!outcome.result.isSuccess() && code !== null) {
73
+ getElog().error(errorMessage(code))
74
+ }
75
+ process.exitCode = outcome.result.isSuccess() ? 0 : exitCodeFor(code)
76
+ }
77
+
78
+ function stripJsonFlag(argv: readonly string[]): { argv: string[]; json: boolean } {
79
+ const next = [...argv]
80
+ const marker = next.indexOf("--")
81
+ const limit = marker === -1 ? next.length : marker
82
+ for (let index = 0; index < limit; index += 1) {
83
+ if (next[index] === "--json") {
84
+ next.splice(index, 1)
85
+ return { argv: next, json: true }
86
+ }
87
+ }
88
+ return { argv: next, json: false }
89
+ }
90
+
91
+ function createPluginOutput(pluginName: string): HostOutput {
92
+ const elog = getElog()
93
+ return {
94
+ info: (text) => elog.plugin("info", pluginName, text),
95
+ warn: (text) => elog.plugin("warn", pluginName, text),
96
+ error: (text) => elog.plugin("error", pluginName, text),
97
+ print: (text = "") => elog.plugin("info", pluginName, text),
98
+ }
99
+ }
100
+
101
+ async function main(argv: readonly string[]): Promise<void> {
102
+ const parsed = parseGlobal(argv)
103
+ if (!parsed.isSuccess()) {
104
+ printParseError(parsed.getCode() ?? "usage.invalid-value")
105
+ return
106
+ }
107
+ const parsedGlobal = parsed.getData()
108
+ if (parsedGlobal === null) {
109
+ printParseError("usage.invalid-value")
110
+ return
111
+ }
112
+ const { options: globalOptions } = parsedGlobal
113
+ let command = parsedGlobal.command
114
+ let commandArgv = [...parsedGlobal.commandArgv]
115
+
116
+ if (globalOptions.version) {
117
+ command = "version"
118
+ commandArgv = []
119
+ }
120
+
121
+ const builtin = command === null ? undefined : findBuiltin(command)
122
+ const builtinName = builtin?.name ?? null
123
+ let jsonMode = globalOptions.json
124
+ if (builtinName !== null) {
125
+ const stripped = stripJsonFlag(commandArgv)
126
+ commandArgv = stripped.argv
127
+ jsonMode = jsonMode || stripped.json
128
+ }
129
+
130
+ const options: GlobalOptions = { ...globalOptions, json: jsonMode }
131
+
132
+ if (globalOptions.home !== undefined) {
133
+ process.env["WELLSPRING_HOME"] = globalOptions.home
134
+ }
135
+ const paths = getPaths()
136
+ configureHost({ paths })
137
+ setHostStatus("starting")
138
+ const settingsFile = resolve(globalOptions.config ?? `${paths.configDir}/${SETTING_FILE_NAME}`)
139
+
140
+ const loaded = await loadSettings(settingsFile)
141
+ const settings: AppSetting = loaded.getData() ?? DEFAULT_SETTINGS
142
+ const configCode = loaded.isSuccess() ? null : loaded.getCode()
143
+
144
+ initElog({ json: jsonMode })
145
+ const elog = getElog()
146
+
147
+ const logger = await initLogger({
148
+ settings,
149
+ level: globalOptions.logLevel ?? (globalOptions.quiet ? "silent" : undefined),
150
+ json: jsonMode,
151
+ stdout: false,
152
+ })
153
+ if (configCode !== null) {
154
+ logger.warn({ code: configCode }, "配置加载失败,使用默认配置")
155
+ elog.warn(`配置加载失败,使用默认配置:${errorMessage(configCode)}`)
156
+ }
157
+
158
+ setHookGuard(async (owner, task) => {
159
+ await withHookOwner(owner, async () => {
160
+ await withConsoleGuard(owner, logger.child({ plugin: owner }), task)
161
+ })
162
+ })
163
+
164
+ setHookErrorHandler(({ hook, owner, error }) => {
165
+ const message = error instanceof Error ? error.message : String(error)
166
+ logger.warn({ hook, owner, message }, "插件钩子执行失败")
167
+ elog.warn(`插件钩子执行失败:${hook}(${owner ?? "-"}):${message}`)
168
+ })
169
+
170
+ let openai: OpenAIClient | null = null
171
+ let proxyFetch: ReturnType<typeof createProxyFetch>
172
+ try {
173
+ proxyFetch = createProxyFetch(settings.network.proxy)
174
+ } catch (error) {
175
+ const reason = error instanceof Error ? error.message : String(error)
176
+ logger.warn({ reason }, "代理初始化失败")
177
+ elog.warn(`代理初始化失败:${reason}`)
178
+ proxyFetch = undefined
179
+ }
180
+ // 当前供应商/模型:启动时解析一次,CLI 单轮命令直接用
181
+ const provider = activeModelProvider(settings)
182
+ const activeModel = effectiveModel(settings, provider)
183
+ const activeReasoning = effectiveReasoning(settings, provider)
184
+ const providerApiKeyValue = providerApiKey(provider, paths.configDir)
185
+ const openaiResult = initOpenAIClient({
186
+ settings: providerOpenAISettings(settings, provider),
187
+ apiKey: providerApiKeyValue ?? "",
188
+ credentialsFile: credentialsFile(paths.configDir),
189
+ logger: logger.child({ module: "openai" }),
190
+ fetch: proxyFetch,
191
+ })
192
+ if (openaiResult.isSuccess()) {
193
+ openai = openaiResult.getData()
194
+ } else {
195
+ logger.warn({ code: openaiResult.getCode() }, "OpenAI 客户端不可用")
196
+ }
197
+
198
+ const registry = new PluginRegistry()
199
+ const agentTools = new AgentToolRegistry()
200
+ let pluginsCache: readonly LoadedPlugin[] | null = null
201
+ const ensurePlugins = async (): Promise<readonly LoadedPlugin[]> => {
202
+ if (pluginsCache !== null) {
203
+ return pluginsCache
204
+ }
205
+ pluginsCache = await loadPlugins({
206
+ paths,
207
+ config: settings,
208
+ logger,
209
+ registry,
210
+ agentTools,
211
+ sandbox: settings.sandbox,
212
+ })
213
+ setHostStatus("running")
214
+ for (const plugin of pluginsCache) {
215
+ if (plugin.status === "failed") {
216
+ logger.warn({ plugin: plugin.name, error: plugin.error }, "插件加载失败")
217
+ }
218
+ }
219
+ return pluginsCache
220
+ }
221
+
222
+ const commandHelpRequested =
223
+ builtinName !== null && commandArgv.some((token) => token === "--help" || token === "-h")
224
+ const requested = commandHelpRequested ? builtinName : command
225
+ let commandName: string
226
+ if ((globalOptions.help || commandHelpRequested) && requested !== null) {
227
+ commandName = "help"
228
+ commandArgv = [requested]
229
+ } else {
230
+ commandName = requested ?? "help"
231
+ }
232
+
233
+ const ctx: CommandContext = {
234
+ global: options,
235
+ settings,
236
+ settingsFile,
237
+ configCode,
238
+ paths,
239
+ logger,
240
+ elog,
241
+ registry,
242
+ agentTools,
243
+ openai,
244
+ activeProvider: provider.id,
245
+ activeModel,
246
+ activeReasoning,
247
+ loadPlugins: ensurePlugins,
248
+ }
249
+
250
+ try {
251
+ // 钩子与插件命令都可能在任意命令里用到;version / key / plugin 不启动插件
252
+ // plugin 子命令只改文件,插件是否加载由下次运行决定
253
+ if (commandName !== "version" && commandName !== "key" && commandName !== "plugin") {
254
+ await ensurePlugins()
255
+ }
256
+ setHostStatus("running")
257
+
258
+ let outcome: CommandOutcome
259
+ switch (commandName) {
260
+ case "chat":
261
+ outcome = await runConversationCommand(ctx, commandArgv, "chat")
262
+ break
263
+ case "run":
264
+ outcome = await runConversationCommand(ctx, commandArgv, "run")
265
+ break
266
+ case "start":
267
+ outcome = await runStartCommand(ctx)
268
+ break
269
+ case "stop":
270
+ outcome = await runStopCommand(ctx)
271
+ break
272
+ case "session":
273
+ outcome = await runSessionCommand(ctx, commandArgv)
274
+ break
275
+ case "config":
276
+ outcome = await runConfigCommand(ctx, commandArgv)
277
+ break
278
+ case "plugin":
279
+ outcome = await runPluginCommand(ctx, commandArgv)
280
+ break
281
+ case "doctor":
282
+ outcome = await runDoctorCommand(ctx)
283
+ break
284
+ case "key":
285
+ outcome = await runKeyCommand(ctx, commandArgv)
286
+ break
287
+ case "version":
288
+ outcome = await runVersionCommand(ctx)
289
+ break
290
+ case "help":
291
+ outcome = await runHelpCommand(ctx, commandArgv)
292
+ break
293
+ default: {
294
+ const record = registry.resolve(commandName)
295
+ if (record === undefined) {
296
+ outcome = failure(`usage.unknown-command:${commandName}`)
297
+ break
298
+ }
299
+ const pluginLogger = logger.child({ plugin: record.pluginName })
300
+ try {
301
+ const pluginDataDir = await ensurePluginDataDir(record.pluginName, paths)
302
+ const pluginConfig = await loadPluginConfig(record.pluginName, paths)
303
+ const pluginFs = createPluginFileApi(pluginDataDir)
304
+ const workspaceFs = createPluginFileApi(process.cwd())
305
+ const pluginContext: PluginCommandContext = {
306
+ argv: commandArgv,
307
+ env: process.env,
308
+ paths,
309
+ config: settings,
310
+ logger: pluginLogger,
311
+ output: createPluginOutput(record.pluginName),
312
+ pluginDataDir,
313
+ pluginConfig,
314
+ fs: pluginFs,
315
+ workspaceFs,
316
+ cwd: process.cwd(),
317
+ json: jsonMode,
318
+ stdin: process.stdin,
319
+ stdout: process.stdout,
320
+ stderr: process.stderr,
321
+ }
322
+ const code = await withHookOwner(record.pluginName, async () =>
323
+ withConsoleGuard(record.pluginName, pluginLogger, async () =>
324
+ record.command.run(pluginContext),
325
+ ),
326
+ )
327
+ process.exitCode = typeof code === "number" ? code : 0
328
+ return
329
+ } catch (error) {
330
+ const message = error instanceof Error ? error.message : String(error)
331
+ logger.error({ plugin: record.pluginName, message }, "插件命令执行失败")
332
+ outcome = failure(`plugin.command-failed:${message}`)
333
+ }
334
+ }
335
+ }
336
+ emitOutcome(outcome, jsonMode)
337
+ } finally {
338
+ setHostStatus("stopped")
339
+ await shutdownAllSandboxPlugins()
340
+ await closeLogger()
341
+ }
342
+ }
343
+
344
+ await main(process.argv.slice(2))
@@ -0,0 +1,21 @@
1
+ /** 入参错误码,退出码统一为 2 */
2
+ export const USAGE_CODES = {
3
+ unknownCommand: "usage.unknown-command",
4
+ unknownOption: "usage.unknown-option",
5
+ unknownSubcommand: "usage.unknown-subcommand",
6
+ missingValue: "usage.missing-value",
7
+ invalidValue: "usage.invalid-value",
8
+ missingContext: "usage.missing-context",
9
+ invalidSessionId: "usage.invalid-session-id",
10
+ unknownConfigKey: "usage.unknown-config-key",
11
+ conflictingOptions: "usage.conflicting-options",
12
+ missingConfirmation: "usage.missing-confirmation",
13
+ } as const
14
+
15
+ export function usageCode(code: string, detail?: string): string {
16
+ return detail === undefined || detail === "" ? code : `${code}:${detail}`
17
+ }
18
+
19
+ export function isUsageCode(code: string | null): boolean {
20
+ return code !== null && code.startsWith("usage.")
21
+ }
@@ -0,0 +1,76 @@
1
+ /** 内置命令元数据,帮助文本与命令校验共用这一份 */
2
+
3
+ export interface BuiltinCommandSpec {
4
+ readonly name: string
5
+ readonly summary: string
6
+ readonly usage: string
7
+ readonly aliases?: readonly string[]
8
+ }
9
+
10
+ export const BUILTIN_COMMANDS: readonly BuiltinCommandSpec[] = [
11
+ {
12
+ name: "chat",
13
+ summary: "对话模式,单轮对话或进入交互式会话",
14
+ usage: "wellspring chat [--session-id <id>] [--new] [--model <name>] [--reasoning off|low|high|max] [--system <text>] <context...>",
15
+ },
16
+ {
17
+ name: "run",
18
+ summary: "Agent 模式,单轮执行或进入交互式会话",
19
+ usage: "wellspring run [--session-id <id>] [--new] [--agent <name>] [--model <name>] [--reasoning off|low|high|max] [--permission read-only|workspace-write|danger-full-access] [--allow-exec] [--max-steps <n>] <context...>",
20
+ },
21
+ {
22
+ name: "start",
23
+ summary: "以服务进程启动,加载插件并触发 onInit",
24
+ usage: "wellspring start",
25
+ },
26
+ {
27
+ name: "stop",
28
+ summary: "停止正在运行的 Wellspring 服务",
29
+ usage: "wellspring stop",
30
+ },
31
+ {
32
+ name: "session",
33
+ summary: "查看、切换与删除会话",
34
+ usage: "wellspring session <list|show|delete> [args]",
35
+ },
36
+ {
37
+ name: "config",
38
+ summary: "配置路径、查看与读写配置项",
39
+ usage: "wellspring config <path|show|get|set> [args]",
40
+ },
41
+ {
42
+ name: "key",
43
+ summary: "查看、设置、清除与测试 OpenAI API Key",
44
+ usage: "wellspring key <status|set|clear|test|path> [--provider <id>] [args]",
45
+ },
46
+ {
47
+ name: "plugin",
48
+ summary: "插件列表、安装与删除",
49
+ usage: "wellspring plugin <list|new|install|link|enable|disable|remove> [args]",
50
+ },
51
+ {
52
+ name: "doctor",
53
+ summary: "环境与配置诊断",
54
+ usage: "wellspring doctor [--json]",
55
+ },
56
+ {
57
+ name: "version",
58
+ summary: "显示版本与运行环境",
59
+ usage: "wellspring version [--json]",
60
+ aliases: ["-v"],
61
+ },
62
+ {
63
+ name: "help",
64
+ summary: "显示帮助",
65
+ usage: "wellspring help [command]",
66
+ aliases: ["-h"],
67
+ },
68
+ ]
69
+
70
+ export const BUILTIN_NAMES: ReadonlySet<string> = new Set(BUILTIN_COMMANDS.map((spec) => spec.name))
71
+
72
+ export function findBuiltin(name: string): BuiltinCommandSpec | undefined {
73
+ return BUILTIN_COMMANDS.find(
74
+ (spec) => spec.name === name || (spec.aliases ?? []).includes(name),
75
+ )
76
+ }
@@ -0,0 +1,60 @@
1
+ /*
2
+ * 帮助文本生成。内置命令来自命令表,插件命令来自注册表。
3
+ */
4
+
5
+ import { BUILTIN_COMMANDS, findBuiltin } from "./commands.ts"
6
+
7
+ export interface HelpPluginCommand {
8
+ readonly name: string
9
+ readonly summary: string
10
+ readonly usage: string
11
+ readonly plugin: string
12
+ }
13
+
14
+ export function formatGlobalHelp(pluginCommands: readonly HelpPluginCommand[]): string {
15
+ const lines: string[] = []
16
+ lines.push("Wellspring 源泉 —— 聚合式 Agent 平台")
17
+ lines.push("")
18
+ lines.push("用法:wellspring <command> [args] [options]")
19
+ lines.push("")
20
+ lines.push("命令:")
21
+ for (const spec of BUILTIN_COMMANDS) {
22
+ lines.push(` ${spec.name.padEnd(9)} ${spec.summary}`)
23
+ }
24
+ if (pluginCommands.length > 0) {
25
+ lines.push("")
26
+ lines.push("插件命令:")
27
+ for (const command of pluginCommands) {
28
+ lines.push(` ${command.name.padEnd(9)} ${command.summary}(来自 ${command.plugin})`)
29
+ }
30
+ }
31
+ lines.push("")
32
+ lines.push("全局参数:")
33
+ lines.push(" -c, --config <file> 指定配置文件")
34
+ lines.push(" --home <dir> 便携模式根目录")
35
+ lines.push(" -l, --log-level <level> 日志级别")
36
+ lines.push(" --json 机器可读输出")
37
+ lines.push(" -q, --quiet 静默")
38
+ lines.push(" -h, --help 帮助")
39
+ lines.push(" -v, --version 版本")
40
+ lines.push("")
41
+ lines.push('示例:wellspring chat "解释一下 EventBus"')
42
+ lines.push(' wellspring run --session-id 20261021-173000-ab12 "读取 package.json"')
43
+ return lines.join("\n")
44
+ }
45
+
46
+ export function formatCommandHelp(name: string, pluginCommand?: HelpPluginCommand): string | null {
47
+ const spec = findBuiltin(name)
48
+ if (spec !== undefined) {
49
+ return [`用法:${spec.usage}`, "", spec.summary].join("\n")
50
+ }
51
+ if (pluginCommand !== undefined) {
52
+ return [
53
+ `用法:${pluginCommand.usage}`,
54
+ "",
55
+ pluginCommand.summary,
56
+ `来自插件:${pluginCommand.plugin}`,
57
+ ].join("\n")
58
+ }
59
+ return null
60
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * 入参层入口。
3
+ */
4
+
5
+ export * from "./codes.ts"
6
+ export * from "./commands.ts"
7
+ export * from "./help.ts"
8
+ export * from "./parse-options.ts"
9
+ export * from "./parse.ts"
10
+ export * from "./types.ts"