@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,1001 @@
1
+ /*
2
+ * sandbox 插件进程入口。
3
+ * 由宿主通过 bwrap/direct backend 启动;stdio 上跑 frame 协议,插件代码只通过 bridge 访问宿主。
4
+ */
5
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
6
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
7
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
8
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
9
+ });
10
+ }
11
+ return path;
12
+ };
13
+ import { Readable } from "node:stream";
14
+ import { pathToFileURL } from "node:url";
15
+ import { emitAfterStep, emitAfterTurn, emitAgentAsyncTaskComplete, emitAgentAsk, emitAgentCallTool, emitAgentQueryTask, emitAgentRead, emitAgentRequestPermission, emitAgentRunAsync, emitAgentRunSync, emitAgentSetGoal, emitAgentSetTasks, emitAgentSubmit, emitBeforeStep, emitBeforeTurn, emitInitHooks, emitOnMessage, emitSessionStart, emitShutdownHooks, emitUserAnswer, listHookKinds, withHookOwner, } from "../api/host/hooks.js";
16
+ import { eventBus } from "../event/event.js";
17
+ import { ensureAccessGuard } from "../plugin/access-guard.js";
18
+ import { ensureHostAlias } from "../plugin/host-alias.js";
19
+ import { setHostBridge } from "./bridge-state.js";
20
+ import { FrameDecoder, encodeMessage, nextRequestId, } from "./protocol.js";
21
+ import { RPC_TIMEOUT_MS } from "./rpc-timeouts.js";
22
+ const rawStdoutWrite = process.stdout.write.bind(process.stdout);
23
+ const rawStderrWrite = process.stderr.write.bind(process.stderr);
24
+ function writeFrame(message) {
25
+ rawStdoutWrite(encodeMessage(message));
26
+ }
27
+ const pending = new Map();
28
+ function bridgeRequest(method, params, timeoutMs = RPC_TIMEOUT_MS.default) {
29
+ const id = nextRequestId("child");
30
+ return new Promise((resolveRequest, rejectRequest) => {
31
+ // timeoutMs 为 null 时不挂定时器:长任务 RPC(例如 agent.stream)由运行过程自身结束
32
+ const timer = timeoutMs === null
33
+ ? null
34
+ : setTimeout(() => {
35
+ pending.delete(id);
36
+ rejectRequest(new Error(`host RPC 超时:${method}`));
37
+ }, timeoutMs);
38
+ timer?.unref();
39
+ const clearTimer = () => {
40
+ if (timer !== null) {
41
+ clearTimeout(timer);
42
+ }
43
+ };
44
+ pending.set(id, {
45
+ resolve: (value) => {
46
+ clearTimer();
47
+ resolveRequest(value);
48
+ },
49
+ reject: (error) => {
50
+ clearTimer();
51
+ rejectRequest(error);
52
+ },
53
+ timer,
54
+ });
55
+ writeFrame({
56
+ v: 1,
57
+ type: "request",
58
+ id,
59
+ method,
60
+ params,
61
+ ...(timeoutMs === null ? {} : { timeoutMs }),
62
+ });
63
+ });
64
+ }
65
+ function bridgeNotify(method, params) {
66
+ writeFrame({ v: 1, type: "event", method, params });
67
+ }
68
+ let hostSnapshot = null;
69
+ const bridge = {
70
+ request: bridgeRequest,
71
+ notify: bridgeNotify,
72
+ getHostSnapshot: () => {
73
+ if (hostSnapshot === null) {
74
+ throw new Error("插件未获得 getHost 权限");
75
+ }
76
+ return hostSnapshot;
77
+ },
78
+ shutdown: () => {
79
+ void bridgeRequest("host.shutdown", {}).catch(() => undefined);
80
+ },
81
+ };
82
+ setHostBridge(bridge);
83
+ ensureHostAlias();
84
+ ensureAccessGuard();
85
+ const HOOK_API_NAME = {
86
+ message: "onMessage",
87
+ sessionStart: "onSessionStart",
88
+ beforeTurn: "beforeTurn",
89
+ beforeStep: "beforeStep",
90
+ afterStep: "afterStep",
91
+ afterTurn: "afterTurn",
92
+ agentRunSync: "onAgentRunSync",
93
+ agentRunAsync: "onAgentRunAsync",
94
+ agentAsyncTaskComplete: "onAgentAsyncTaskComplete",
95
+ agentCallTool: "onAgentCallTool",
96
+ agentAsk: "onAgentAsk",
97
+ agentRead: "onAgentRead",
98
+ agentQueryTask: "onAgentQueryTask",
99
+ agentSubmit: "onAgentSubmit",
100
+ agentSetTasks: "onAgentSetTasks",
101
+ agentSetGoal: "onAgentSetGoal",
102
+ agentRequestPermission: "onAgentRequestPermission",
103
+ userAnswer: "onUserAnswer",
104
+ init: "onInit",
105
+ shutdown: "onShutdown",
106
+ };
107
+ let runtime = null;
108
+ const httpHandlers = new Map();
109
+ const agentStreamHandlers = new Map();
110
+ const websocketHandlers = new Map();
111
+ const wsMessages = new Map();
112
+ const wsCloses = new Map();
113
+ function remoteExec() {
114
+ return {
115
+ async run(options) {
116
+ return (await bridgeRequest("host.exec.run", {
117
+ command: options.command,
118
+ cwd: options.cwd,
119
+ env: options.env ?? {},
120
+ timeoutMs: options.timeoutMs,
121
+ }));
122
+ },
123
+ async poll(sessionId) {
124
+ return (await bridgeRequest("host.exec.poll", { sessionId }));
125
+ },
126
+ async stop(sessionId) {
127
+ await bridgeRequest("host.exec.stop", { sessionId });
128
+ },
129
+ };
130
+ }
131
+ function remotePty() {
132
+ return {
133
+ async available() {
134
+ const result = (await bridgeRequest("host.pty.available", {}));
135
+ const backend = result.backend === "node-pty" || result.backend === "python-pty"
136
+ ? result.backend
137
+ : undefined;
138
+ return {
139
+ available: result.available === true,
140
+ backend,
141
+ reason: typeof result.reason === "string" ? result.reason : undefined,
142
+ };
143
+ },
144
+ async spawn(options) {
145
+ return (await bridgeRequest("host.pty.spawn", {
146
+ file: options.file ?? "",
147
+ args: options.args ?? [],
148
+ cwd: options.cwd,
149
+ env: options.env ?? {},
150
+ cols: options.cols,
151
+ rows: options.rows,
152
+ }));
153
+ },
154
+ async poll(sessionId) {
155
+ return (await bridgeRequest("host.pty.poll", { sessionId }));
156
+ },
157
+ async write(sessionId, data) {
158
+ await bridgeRequest("host.pty.write", { sessionId, data });
159
+ },
160
+ async resize(sessionId, cols, rows) {
161
+ await bridgeRequest("host.pty.resize", { sessionId, cols, rows });
162
+ },
163
+ async kill(sessionId) {
164
+ await bridgeRequest("host.pty.kill", { sessionId });
165
+ },
166
+ };
167
+ }
168
+ function remoteAgent() {
169
+ return {
170
+ async chat(input) {
171
+ return await bridgeRequest("host.agent.chat", input, RPC_TIMEOUT_MS.agentChat);
172
+ },
173
+ async stream(input, onEvent) {
174
+ const streamId = nextRequestId("agent-stream");
175
+ agentStreamHandlers.set(streamId, onEvent);
176
+ try {
177
+ // 一轮 Agent 可能跑很久(多步工具调用),不设 RPC 上限
178
+ return await bridgeRequest("host.agent.stream", { streamId, input }, RPC_TIMEOUT_MS.agentStream);
179
+ }
180
+ finally {
181
+ agentStreamHandlers.delete(streamId);
182
+ }
183
+ },
184
+ async validateWorkspace(path) {
185
+ return (await bridgeRequest("host.agent.validateWorkspace", {
186
+ path,
187
+ }));
188
+ },
189
+ async pickDirectory() {
190
+ return (await bridgeRequest("host.agent.pickDirectory", {}));
191
+ },
192
+ async searchWorkspaceFiles(root, query) {
193
+ return (await bridgeRequest("host.agent.searchWorkspaceFiles", {
194
+ root,
195
+ query,
196
+ }));
197
+ },
198
+ async interject(sessionId, message) {
199
+ return (await bridgeRequest("host.agent.interject", {
200
+ sessionId,
201
+ message,
202
+ }));
203
+ },
204
+ async stop(sessionId) {
205
+ return (await bridgeRequest("host.agent.stop", { sessionId }));
206
+ },
207
+ async respondApproval(approvalId, approved) {
208
+ return (await bridgeRequest("host.agent.respondApproval", {
209
+ approvalId,
210
+ approved,
211
+ }));
212
+ },
213
+ async respondAsk(askId, answer) {
214
+ return (await bridgeRequest("host.agent.respondAsk", {
215
+ askId,
216
+ answer,
217
+ }));
218
+ },
219
+ };
220
+ }
221
+ function remoteModels() {
222
+ return {
223
+ async state() {
224
+ return (await bridgeRequest("host.models.state", {}));
225
+ },
226
+ async setActive(providerId, model, reasoning) {
227
+ return (await bridgeRequest("host.models.setActive", {
228
+ providerId,
229
+ model,
230
+ reasoning,
231
+ }));
232
+ },
233
+ async saveProvider(input) {
234
+ return (await bridgeRequest("host.models.saveProvider", input));
235
+ },
236
+ async removeProvider(id) {
237
+ return (await bridgeRequest("host.models.removeProvider", {
238
+ id,
239
+ }));
240
+ },
241
+ async fetchModels(id, apiKey) {
242
+ const payload = { id };
243
+ if (apiKey !== undefined) {
244
+ payload["apiKey"] = apiKey;
245
+ }
246
+ return (await bridgeRequest("host.models.fetchModels", payload, RPC_TIMEOUT_MS.modelsFetch));
247
+ },
248
+ async saveKey(id, apiKey) {
249
+ return (await bridgeRequest("host.models.saveKey", {
250
+ id,
251
+ apiKey,
252
+ }));
253
+ },
254
+ async clearKey(id) {
255
+ return (await bridgeRequest("host.models.clearKey", { id }));
256
+ },
257
+ };
258
+ }
259
+ function remoteNetwork() {
260
+ return {
261
+ async state() {
262
+ return (await bridgeRequest("host.network.state", {}));
263
+ },
264
+ async saveProxy(input) {
265
+ return (await bridgeRequest("host.network.saveProxy", input));
266
+ },
267
+ };
268
+ }
269
+ function remotePlugins() {
270
+ return {
271
+ async list() {
272
+ return (await bridgeRequest("host.plugins.list", {}));
273
+ },
274
+ async install(input) {
275
+ return (await bridgeRequest("host.plugins.install", input, RPC_TIMEOUT_MS.pluginsInstall));
276
+ },
277
+ async remove(id) {
278
+ return (await bridgeRequest("host.plugins.remove", { id }));
279
+ },
280
+ async enable(id) {
281
+ return (await bridgeRequest("host.plugins.enable", { id }));
282
+ },
283
+ async disable(id) {
284
+ return (await bridgeRequest("host.plugins.disable", { id }));
285
+ },
286
+ };
287
+ }
288
+ function remoteWorkspaces() {
289
+ return {
290
+ async list() {
291
+ return (await bridgeRequest("host.workspaces.list", {}));
292
+ },
293
+ async add(input) {
294
+ return (await bridgeRequest("host.workspaces.add", input));
295
+ },
296
+ async remove(id) {
297
+ return (await bridgeRequest("host.workspaces.remove", {
298
+ id,
299
+ }));
300
+ },
301
+ async rename(id, name) {
302
+ return (await bridgeRequest("host.workspaces.rename", {
303
+ id,
304
+ name,
305
+ }));
306
+ },
307
+ async touch(id) {
308
+ return (await bridgeRequest("host.workspaces.touch", {
309
+ id,
310
+ }));
311
+ },
312
+ };
313
+ }
314
+ function remoteHttp() {
315
+ return {
316
+ async createServer(options, handler) {
317
+ const serverId = nextRequestId("http");
318
+ httpHandlers.set(serverId, handler);
319
+ if (typeof options.websocket === "function") {
320
+ websocketHandlers.set(serverId, options.websocket);
321
+ }
322
+ try {
323
+ const ready = (await bridgeRequest("host.http.createServer", {
324
+ serverId,
325
+ host: options.host,
326
+ port: options.port,
327
+ tls: options.tls,
328
+ websocket: typeof options.websocket === "function",
329
+ }));
330
+ return {
331
+ serverId: ready.serverId,
332
+ host: ready.host,
333
+ port: ready.port,
334
+ async close() {
335
+ httpHandlers.delete(serverId);
336
+ await bridgeRequest("host.http.closeServer", { serverId });
337
+ },
338
+ };
339
+ }
340
+ catch (error) {
341
+ httpHandlers.delete(serverId);
342
+ throw error;
343
+ }
344
+ },
345
+ };
346
+ }
347
+ function isObject(value) {
348
+ return typeof value === "object" && value !== null && !Array.isArray(value);
349
+ }
350
+ function validatePlugin(value) {
351
+ if (!isObject(value)) {
352
+ throw new Error("setup() 必须返回 WellspringPlugin 对象");
353
+ }
354
+ const id = value["id"];
355
+ const name = value["name"];
356
+ const version = value["version"];
357
+ const status = value["status"];
358
+ if (typeof id !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(id)) {
359
+ throw new Error(`插件 id 不合法:${String(id)}`);
360
+ }
361
+ if (typeof name !== "string" || name.trim() === "") {
362
+ throw new Error(`插件 name 不合法:${String(name)}`);
363
+ }
364
+ if (typeof version !== "string" || version.trim() === "") {
365
+ throw new Error(`插件 version 不合法:${String(version)}`);
366
+ }
367
+ if (status !== "ok" && status !== "failed") {
368
+ throw new Error(`插件 status 必须是 ok / failed:${String(status)}`);
369
+ }
370
+ return value;
371
+ }
372
+ function createLogger() {
373
+ const make = (bindings = {}) => {
374
+ const log = (level) => (first, second) => {
375
+ const fields = isObject(first) ? first : bindings;
376
+ const message = isObject(first) ? String(second ?? "") : String(first ?? "");
377
+ bridgeNotify("host.log", { level, message, fields });
378
+ };
379
+ const logger = {
380
+ trace: log("trace"),
381
+ debug: log("debug"),
382
+ info: log("info"),
383
+ warn: log("warn"),
384
+ error: log("error"),
385
+ fatal: log("fatal"),
386
+ child: (childBindings) => make({ ...bindings, ...childBindings }),
387
+ };
388
+ return logger;
389
+ };
390
+ return make();
391
+ }
392
+ const logger = createLogger();
393
+ const output = {
394
+ info: (text) => bridgeNotify("host.output", { kind: "info", text }),
395
+ warn: (text) => bridgeNotify("host.output", { kind: "warn", text }),
396
+ error: (text) => bridgeNotify("host.output", { kind: "error", text }),
397
+ print: (text = "") => bridgeNotify("host.output", { kind: "print", text }),
398
+ };
399
+ function createFileApi(scope) {
400
+ const call = (method, params = {}) => bridgeRequest(`host.${scope}.${method}`, params);
401
+ return {
402
+ root: scope,
403
+ async readText(path) {
404
+ const result = (await call("readText", { path }));
405
+ return result.text;
406
+ },
407
+ async readBytes(path) {
408
+ const result = (await call("readBytes", { path }));
409
+ if (result.data === null) {
410
+ return null;
411
+ }
412
+ return new Uint8Array(Buffer.from(result.data, "base64"));
413
+ },
414
+ async readJson(path) {
415
+ const result = (await call("readJson", { path }));
416
+ return result.value;
417
+ },
418
+ async writeText(path, text) {
419
+ await call("writeText", { path, text });
420
+ },
421
+ async writeBytes(path, bytes) {
422
+ await call("writeBytes", {
423
+ path,
424
+ data: Buffer.from(bytes).toString("base64"),
425
+ });
426
+ },
427
+ async writeJson(path, value) {
428
+ await call("writeJson", { path, value });
429
+ },
430
+ async list(path = "") {
431
+ const result = (await call("list", { path }));
432
+ return result.entries;
433
+ },
434
+ async stat(path) {
435
+ const result = (await call("stat", { path }));
436
+ return result.stat;
437
+ },
438
+ async mkdir(path) {
439
+ await call("mkdir", { path });
440
+ },
441
+ async remove(path) {
442
+ await call("remove", { path });
443
+ },
444
+ async exists(path) {
445
+ const result = (await call("exists", { path }));
446
+ return result.exists;
447
+ },
448
+ };
449
+ }
450
+ function patchConsole() {
451
+ const methods = [
452
+ ["log", "info"],
453
+ ["info", "info"],
454
+ ["debug", "debug"],
455
+ ["warn", "warn"],
456
+ ["error", "error"],
457
+ ["trace", "trace"],
458
+ ["dir", "info"],
459
+ ["table", "info"],
460
+ ];
461
+ for (const [method, level] of methods) {
462
+ ;
463
+ console[method] = (...args) => {
464
+ bridgeNotify("host.console", { level, args: args.map((item) => String(item)) });
465
+ };
466
+ }
467
+ console.assert = (condition, ...args) => {
468
+ if (!condition) {
469
+ bridgeNotify("host.console", { level: "error", args: args.map(String) });
470
+ }
471
+ };
472
+ }
473
+ function patchProcessStreams() {
474
+ process.stdout.write = ((chunk) => {
475
+ bridgeNotify("host.log", { level: "info", message: String(chunk), fields: {} });
476
+ return true;
477
+ });
478
+ process.stderr.write = ((chunk) => {
479
+ bridgeNotify("host.log", { level: "error", message: String(chunk), fields: {} });
480
+ return true;
481
+ });
482
+ }
483
+ function remotePluginData(targetId) {
484
+ const call = async (method, args) => await bridgeRequest("host.pluginData", { targetId, method, args });
485
+ return {
486
+ root: "",
487
+ async readText(path) {
488
+ return (await call("readText", [path]));
489
+ },
490
+ async readBytes(path) {
491
+ const value = (await call("readBytes", [path]));
492
+ return value === null ? null : Uint8Array.from(value);
493
+ },
494
+ async readJson(path) {
495
+ return (await call("readJson", [path]));
496
+ },
497
+ async writeText(path, text) {
498
+ await call("writeText", [path, text]);
499
+ },
500
+ async writeBytes(path, bytes) {
501
+ await call("writeBytes", [path, [...bytes]]);
502
+ },
503
+ async writeJson(path, value) {
504
+ await call("writeJson", [path, value]);
505
+ },
506
+ async list(path = "") {
507
+ return (await call("list", [path]));
508
+ },
509
+ async stat(path) {
510
+ return (await call("stat", [path]));
511
+ },
512
+ async mkdir(path) {
513
+ await call("mkdir", [path]);
514
+ },
515
+ async remove(path) {
516
+ await call("remove", [path]);
517
+ },
518
+ async exists(path) {
519
+ return (await call("exists", [path]));
520
+ },
521
+ };
522
+ }
523
+ async function bootstrap(params) {
524
+ const hostData = params.host;
525
+ hostSnapshot =
526
+ hostData === null
527
+ ? null
528
+ : {
529
+ getStatus: () => hostData.status,
530
+ getOS: () => hostData.os,
531
+ getPaths: () => hostData.paths,
532
+ getPlugins: () => hostData.plugins.map((plugin) => ({
533
+ id: plugin.id,
534
+ name: plugin.name,
535
+ version: plugin.version,
536
+ deps: plugin.deps,
537
+ commands: plugin.commands,
538
+ getStatus: () => plugin.status,
539
+ })),
540
+ };
541
+ const pluginId = params.pluginId;
542
+ const commands = [];
543
+ const agentTools = [];
544
+ const api = {
545
+ apiVersion: 1,
546
+ plugin: { id: pluginId, name: params.pluginName, version: params.pluginVersion },
547
+ paths: params.paths,
548
+ config: params.config,
549
+ logger,
550
+ output,
551
+ pluginDataDir: params.pluginDataDir,
552
+ pluginConfig: params.pluginConfig,
553
+ fs: createFileApi("fs"),
554
+ workspaceFs: createFileApi("workspaceFs"),
555
+ registerCommand: (command) => {
556
+ commands.push(command);
557
+ },
558
+ registerAgentTool: (tool) => {
559
+ agentTools.push(tool);
560
+ },
561
+ pluginData: async (targetId) => {
562
+ return remotePluginData(targetId);
563
+ },
564
+ capabilities: {
565
+ async executeCode(input) {
566
+ // 沙箱自己的命令超时最长 600s,RPC 用更长的上限,避免宿主先放弃等待
567
+ return await bridgeRequest("host.capabilities.executeCode", input, RPC_TIMEOUT_MS.sandboxExec);
568
+ },
569
+ async startBackgroundCode(input) {
570
+ return await bridgeRequest("host.capabilities.startBackgroundCode", input);
571
+ },
572
+ async queryTask(taskId) {
573
+ return await bridgeRequest("host.capabilities.queryTask", { taskId });
574
+ },
575
+ async stopTask(taskId, mode) {
576
+ return await bridgeRequest("host.capabilities.stopTask", { taskId, mode });
577
+ },
578
+ async webSearch(query, count) {
579
+ return await bridgeRequest("host.capabilities.webSearch", { query, count });
580
+ },
581
+ async webFetch(url) {
582
+ return await bridgeRequest("host.capabilities.webFetch", { url });
583
+ },
584
+ },
585
+ http: remoteHttp(),
586
+ agent: remoteAgent(),
587
+ models: remoteModels(),
588
+ network: remoteNetwork(),
589
+ plugins: remotePlugins(),
590
+ workspaces: remoteWorkspaces(),
591
+ exec: remoteExec(),
592
+ pty: remotePty(),
593
+ };
594
+ const module = (await withHookOwner(pluginId, async () => {
595
+ return (await import(__rewriteRelativeImportExtension(pathToFileURL(params.pluginEntry).href)));
596
+ }));
597
+ if (typeof module.setup !== "function") {
598
+ throw new Error("入口需要导出 setup() 函数");
599
+ }
600
+ let created = null;
601
+ await withHookOwner(pluginId, async () => {
602
+ created = validatePlugin(await module.setup());
603
+ if (created.status !== "ok") {
604
+ throw new Error(`插件自报状态:${created.status}`);
605
+ }
606
+ commands.push(...(created.commands ?? []));
607
+ agentTools.push(...(created.agentTools ?? []));
608
+ });
609
+ if (created === null) {
610
+ throw new Error("插件未初始化");
611
+ }
612
+ const plugin = created;
613
+ const current = {
614
+ owner: pluginId,
615
+ plugin,
616
+ commands,
617
+ agentTools,
618
+ hooks: listHookKinds(pluginId),
619
+ api,
620
+ initialized: false,
621
+ };
622
+ runtime = current;
623
+ if (params.deferInit !== true) {
624
+ await initializeRuntime(current);
625
+ }
626
+ return readyOf(current);
627
+ }
628
+ async function initializeRuntime(current) {
629
+ if (current.initialized) {
630
+ return;
631
+ }
632
+ await withHookOwner(current.owner, async () => {
633
+ await current.plugin.init?.(current.api);
634
+ });
635
+ for (const tool of current.agentTools) {
636
+ if (typeof tool.name !== "string" || typeof tool.call !== "function") {
637
+ throw new Error("Agent 工具缺少 name / call");
638
+ }
639
+ }
640
+ current.initialized = true;
641
+ current.hooks = listHookKinds(current.owner);
642
+ }
643
+ function readyOf(current) {
644
+ return {
645
+ plugin: {
646
+ id: current.plugin.id,
647
+ name: current.plugin.name,
648
+ version: current.plugin.version,
649
+ status: current.plugin.status,
650
+ deps: [...(current.plugin.deps ?? [])],
651
+ },
652
+ commands: current.commands.map((command) => ({
653
+ name: command.name,
654
+ summary: command.summary,
655
+ usage: command.usage,
656
+ aliases: command.aliases,
657
+ })),
658
+ agentTools: current.agentTools.map((tool) => ({
659
+ name: tool.name,
660
+ introduction: {
661
+ params: { ...tool.introduction.params },
662
+ content: tool.introduction.content,
663
+ },
664
+ })),
665
+ hooks: current.hooks.map((kind) => HOOK_API_NAME[kind]),
666
+ };
667
+ }
668
+ async function dispatchHook(name, payload) {
669
+ switch (name) {
670
+ case "onMessage":
671
+ await emitOnMessage(payload);
672
+ return { prompt: payload["prompt"] ?? [] };
673
+ case "onSessionStart":
674
+ await emitSessionStart(payload);
675
+ return { prompt: payload["prompt"] ?? [] };
676
+ case "beforeTurn":
677
+ await emitBeforeTurn(payload);
678
+ return {};
679
+ case "beforeStep":
680
+ await emitBeforeStep(payload);
681
+ return {};
682
+ case "afterStep":
683
+ await emitAfterStep(payload);
684
+ return {};
685
+ case "afterTurn":
686
+ await emitAfterTurn(payload);
687
+ return {};
688
+ case "onAgentRunSync":
689
+ await emitAgentRunSync(payload);
690
+ return {};
691
+ case "onAgentRunAsync":
692
+ await emitAgentRunAsync(payload);
693
+ return {};
694
+ case "onAgentAsyncTaskComplete":
695
+ await emitAgentAsyncTaskComplete(payload);
696
+ return {};
697
+ case "onAgentCallTool":
698
+ await emitAgentCallTool(payload);
699
+ return {};
700
+ case "onAgentAsk":
701
+ await emitAgentAsk(payload);
702
+ return {};
703
+ case "onAgentRead":
704
+ await emitAgentRead(payload);
705
+ return {};
706
+ case "onAgentQueryTask":
707
+ await emitAgentQueryTask(payload);
708
+ return {};
709
+ case "onAgentSubmit":
710
+ await emitAgentSubmit(payload);
711
+ return {};
712
+ case "onAgentSetTasks":
713
+ await emitAgentSetTasks(payload);
714
+ return {};
715
+ case "onAgentSetGoal":
716
+ await emitAgentSetGoal(payload);
717
+ return {};
718
+ case "onAgentRequestPermission":
719
+ await emitAgentRequestPermission(payload);
720
+ return {};
721
+ case "onUserAnswer":
722
+ await emitUserAnswer(payload);
723
+ return {};
724
+ case "onInit":
725
+ await emitInitHooks();
726
+ return {};
727
+ case "onShutdown":
728
+ await emitShutdownHooks();
729
+ return {};
730
+ default:
731
+ throw new Error(`未知钩子:${name}`);
732
+ }
733
+ }
734
+ async function runCommand(request) {
735
+ if (runtime === null) {
736
+ throw new Error("插件尚未初始化");
737
+ }
738
+ const params = request.params;
739
+ const command = runtime.commands.find((item) => item.name === params.name);
740
+ if (command === undefined) {
741
+ throw new Error(`命令不存在:${params.name}`);
742
+ }
743
+ const context = {
744
+ argv: params.argv,
745
+ env: {},
746
+ paths: runtime.api.paths,
747
+ config: runtime.api.config,
748
+ logger,
749
+ output,
750
+ pluginDataDir: runtime.api.pluginDataDir,
751
+ pluginConfig: runtime.api.pluginConfig,
752
+ fs: runtime.api.fs,
753
+ workspaceFs: runtime.api.workspaceFs,
754
+ cwd: params.cwd,
755
+ json: params.json,
756
+ stdin: Readable.from([params.stdin ?? ""]),
757
+ stdout: process.stdout,
758
+ stderr: process.stderr,
759
+ };
760
+ const code = await withHookOwner(runtime.owner, async () => await command.run(context));
761
+ return { exitCode: typeof code === "number" ? code : 0 };
762
+ }
763
+ async function handleHostRequest(request) {
764
+ try {
765
+ let result;
766
+ if (request.method === "plugin.command") {
767
+ result = await runCommand(request);
768
+ }
769
+ else if (request.method === "plugin.agentTool") {
770
+ if (runtime === null) {
771
+ throw new Error("插件尚未初始化");
772
+ }
773
+ const params = request.params;
774
+ const tool = runtime.agentTools.find((item) => item.name === params.name);
775
+ if (tool === undefined) {
776
+ throw new Error(`Agent 工具不存在:${params.name}`);
777
+ }
778
+ result = await withHookOwner(runtime.owner, async () => (await tool.call(params.args)));
779
+ }
780
+ else if (request.method === "plugin.init") {
781
+ if (runtime === null) {
782
+ throw new Error("插件尚未初始化");
783
+ }
784
+ await initializeRuntime(runtime);
785
+ result = readyOf(runtime);
786
+ }
787
+ else if (request.method === "plugin.websocket.connect") {
788
+ if (runtime === null) {
789
+ throw new Error("插件尚未初始化");
790
+ }
791
+ const params = request.params;
792
+ const handler = websocketHandlers.get(params.serverId);
793
+ if (handler === undefined) {
794
+ throw new Error("WebSocket handler 不存在");
795
+ }
796
+ const connectionId = params.connectionId;
797
+ const socket = {
798
+ connectionId,
799
+ async send(data) {
800
+ await bridgeRequest("host.websocket.send", { connectionId, data });
801
+ },
802
+ async close(code = 1000, reason = "") {
803
+ await bridgeRequest("host.websocket.close", {
804
+ connectionId,
805
+ code,
806
+ reason,
807
+ });
808
+ },
809
+ onMessage(handler) {
810
+ const list = wsMessages.get(connectionId) ?? [];
811
+ list.push(handler);
812
+ wsMessages.set(connectionId, list);
813
+ },
814
+ onClose(handler) {
815
+ const list = wsCloses.get(connectionId) ?? [];
816
+ list.push(handler);
817
+ wsCloses.set(connectionId, list);
818
+ },
819
+ };
820
+ await withHookOwner(runtime.owner, async () => handler(socket, params.request));
821
+ result = {};
822
+ }
823
+ else if (request.method === "plugin.websocket.message") {
824
+ const params = request.params;
825
+ const text = params.binary
826
+ ? Buffer.from(params.data, "base64").toString("utf8")
827
+ : Buffer.from(params.data, "base64").toString("utf8");
828
+ for (const handler of wsMessages.get(params.connectionId) ?? []) {
829
+ handler(text);
830
+ }
831
+ result = {};
832
+ }
833
+ else if (request.method === "plugin.websocket.close") {
834
+ const params = request.params;
835
+ for (const handler of wsCloses.get(params.connectionId) ?? []) {
836
+ handler(params.code, params.reason);
837
+ }
838
+ wsMessages.delete(params.connectionId);
839
+ wsCloses.delete(params.connectionId);
840
+ result = {};
841
+ }
842
+ else if (request.method === "plugin.http") {
843
+ if (runtime === null) {
844
+ throw new Error("插件尚未初始化");
845
+ }
846
+ const params = request.params;
847
+ const handler = httpHandlers.get(params.serverId);
848
+ if (handler === undefined) {
849
+ throw new Error(`HTTP handler 不存在:${params.serverId}`);
850
+ }
851
+ const requestId = params.requestId;
852
+ let flushed = false;
853
+ let ended = false;
854
+ const buffered = [];
855
+ const flush = () => {
856
+ if (flushed) {
857
+ return;
858
+ }
859
+ flushed = true;
860
+ for (const chunk of buffered) {
861
+ bridgeNotify("host.http.stream", { requestId, chunk });
862
+ }
863
+ buffered.length = 0;
864
+ if (ended) {
865
+ bridgeNotify("host.http.stream", { requestId, end: true });
866
+ }
867
+ };
868
+ const stream = {
869
+ write(chunk) {
870
+ if (flushed) {
871
+ bridgeNotify("host.http.stream", { requestId, chunk });
872
+ }
873
+ else {
874
+ buffered.push(chunk);
875
+ }
876
+ },
877
+ end() {
878
+ if (flushed) {
879
+ bridgeNotify("host.http.stream", { requestId, end: true });
880
+ }
881
+ else {
882
+ ended = true;
883
+ }
884
+ },
885
+ };
886
+ const response = (await withHookOwner(runtime.owner, async () => handler(params.request, stream)));
887
+ if (response.stream === true) {
888
+ setImmediate(flush);
889
+ }
890
+ result = response;
891
+ }
892
+ else if (request.method === "plugin.hook") {
893
+ const params = request.params;
894
+ if (runtime === null) {
895
+ throw new Error("插件尚未初始化");
896
+ }
897
+ result = await withHookOwner(runtime.owner, async () => dispatchHook(params.hook, params.payload));
898
+ }
899
+ else if (request.method === "sandbox.ping") {
900
+ result = { time: Date.now() };
901
+ }
902
+ else if (request.method === "sandbox.shutdown") {
903
+ await emitShutdownHooks();
904
+ result = {};
905
+ writeFrame({ v: 1, type: "response", id: request.id, ok: true, result });
906
+ setTimeout(() => process.exit(0), 10);
907
+ return;
908
+ }
909
+ else {
910
+ throw new Error(`未知方法:${request.method}`);
911
+ }
912
+ writeFrame({ v: 1, type: "response", id: request.id, ok: true, result });
913
+ }
914
+ catch (error) {
915
+ writeFrame({
916
+ v: 1,
917
+ type: "response",
918
+ id: request.id,
919
+ ok: false,
920
+ error: {
921
+ code: request.method === "plugin.hook"
922
+ ? "plugin.hook-failed"
923
+ : "plugin.command-failed",
924
+ message: error instanceof Error ? error.message : String(error),
925
+ },
926
+ });
927
+ }
928
+ }
929
+ const configureResolvers = [];
930
+ async function main() {
931
+ const decoder = new FrameDecoder();
932
+ process.stdin.on("data", async (chunk) => {
933
+ for (const message of decoder.push(chunk)) {
934
+ if (message.type === "response") {
935
+ const entry = pending.get(message.id);
936
+ if (entry !== undefined) {
937
+ pending.delete(message.id);
938
+ if (message.ok) {
939
+ entry.resolve(message.result);
940
+ }
941
+ else {
942
+ entry.reject(new Error(message.error?.message ?? "host RPC 失败"));
943
+ }
944
+ }
945
+ continue;
946
+ }
947
+ if (message.type === "event") {
948
+ /*
949
+ * 事件回调出错不能拖垮 stdin 读取
950
+ *
951
+ * 这里在 data 监听里同步执行插件侧回调;一旦抛出就是未捕获异常,
952
+ * 插件可能直接挂掉或丢掉这一帧里剩下的事件——宿主还在跑、界面却再也
953
+ * 收不到任何事件,表现就是「服务端一直有日志、页面卡住不动」。
954
+ */
955
+ try {
956
+ if (message.method === "sandbox.event") {
957
+ const params = message.params;
958
+ eventBus.receive(params.name, params.data);
959
+ }
960
+ else if (message.method === "sandbox.agent.stream") {
961
+ const params = message.params;
962
+ agentStreamHandlers.get(params.streamId)?.(params.event);
963
+ }
964
+ }
965
+ catch (error) {
966
+ process.stderr.write(`事件处理失败(${message.method}):${error instanceof Error ? error.message : String(error)}\n`);
967
+ }
968
+ continue;
969
+ }
970
+ const request = message;
971
+ if (request.method === "sandbox.configure") {
972
+ const params = request.params;
973
+ try {
974
+ patchConsole();
975
+ patchProcessStreams();
976
+ const ready = await bootstrap(params);
977
+ writeFrame({ v: 1, type: "response", id: request.id, ok: true, result: ready });
978
+ }
979
+ catch (error) {
980
+ writeFrame({
981
+ v: 1,
982
+ type: "response",
983
+ id: request.id,
984
+ ok: false,
985
+ error: {
986
+ code: "plugin.init-failed",
987
+ message: error instanceof Error ? error.message : String(error),
988
+ },
989
+ });
990
+ setTimeout(() => process.exit(1), 10);
991
+ }
992
+ continue;
993
+ }
994
+ void handleHostRequest(request);
995
+ }
996
+ });
997
+ process.stdin.resume();
998
+ await new Promise(() => undefined);
999
+ }
1000
+ await main();
1001
+ //# sourceMappingURL=plugin-host.js.map