@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,468 @@
1
+ /*
2
+ * 会话存储。
3
+ * 路径:<dataDir>/sessions/<cwd桶>/<sessionId>/
4
+ * session.json 元信息
5
+ * .lock 写入锁
6
+ * turns/NNNN.jsonl.zstd 每轮一个 zstd 段
7
+ * last.json 存在 cwd 桶目录下,记录该 cwd 的最近会话。
8
+ */
9
+
10
+ import { createHash } from "node:crypto"
11
+ import { realpathSync } from "node:fs"
12
+ import { readdir, writeFile } from "node:fs/promises"
13
+ import { basename, join, resolve } from "node:path"
14
+
15
+ import {
16
+ ensureDir,
17
+ readBytesIfExists,
18
+ readJsonIfExists,
19
+ removePath,
20
+ statIfExists,
21
+ writeBytesAtomic,
22
+ writeJsonAtomic,
23
+ } from "../platform/file.ts"
24
+ import { getPaths } from "../platform/path.ts"
25
+ import { decodeEvents, encodeEvents } from "./compress.ts"
26
+ import { groupTurns } from "./replay.ts"
27
+ import type { SessionEvent, SessionHeader, SessionMeta, SessionTurn } from "./types.ts"
28
+
29
+ const SESSION_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/
30
+ const SEGMENT = /^(\d+)\.jsonl\.zstd$/
31
+ const LOCK_STALE_MS = 10 * 60 * 1000
32
+ const APP_NAME = "wellspring"
33
+ const APP_VERSION = "1.0.0"
34
+
35
+ export class SessionNotFoundError extends Error {
36
+ constructor(id: string) {
37
+ super(`会话不存在:${id}`)
38
+ this.name = "SessionNotFoundError"
39
+ }
40
+ }
41
+
42
+ export class SessionAmbiguousError extends Error {
43
+ constructor(id: string) {
44
+ super(`会话 id 在多个 cwd 桶中重复:${id}`)
45
+ this.name = "SessionAmbiguousError"
46
+ }
47
+ }
48
+
49
+ export class SessionLockedError extends Error {
50
+ constructor(id: string) {
51
+ super(`会话正在被其他进程写入:${id}`)
52
+ this.name = "SessionLockedError"
53
+ }
54
+ }
55
+
56
+ export interface SessionData {
57
+ readonly meta: SessionMeta
58
+ readonly header: SessionHeader
59
+ readonly dir: string
60
+ events: SessionEvent[]
61
+ turns: SessionTurn[]
62
+ }
63
+
64
+ export interface SessionSummary {
65
+ readonly id: string
66
+ readonly cwd: string
67
+ readonly dir: string
68
+ readonly turns: number
69
+ readonly updatedAt: number
70
+ readonly last: boolean
71
+ }
72
+
73
+ export interface CreateSessionOptions {
74
+ readonly cwd: string
75
+ readonly workspace?: string
76
+ readonly model: string
77
+ readonly id?: string
78
+ readonly type?: string
79
+ readonly metadata?: Record<string, unknown>
80
+ }
81
+
82
+ export interface ListSessionsOptions {
83
+ readonly cwd: string
84
+ readonly all?: boolean
85
+ readonly limit?: number
86
+ }
87
+
88
+ export function isValidSessionId(id: string): boolean {
89
+ return SESSION_ID.test(id)
90
+ }
91
+
92
+ export function newSessionId(date = new Date()): string {
93
+ const pad = (value: number): string => String(value).padStart(2, "0")
94
+ const stamp =
95
+ `${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}` +
96
+ `-${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`
97
+ const suffix = Math.floor(Math.random() * 0xffff)
98
+ .toString(16)
99
+ .padStart(4, "0")
100
+ return `${stamp}-${suffix}`
101
+ }
102
+
103
+ function slugOf(name: string): string {
104
+ const cleaned = name
105
+ .replace(/[^A-Za-z0-9._-]/g, "-")
106
+ .replace(/-+/g, "-")
107
+ .replace(/^[-.]+|[-.]+$/g, "")
108
+ return (cleaned === "" ? "root" : cleaned).slice(0, 32)
109
+ }
110
+
111
+ /** cwd → 桶目录名:<slug>-<sha256 前 8 位> */
112
+ export function sessionBucket(cwd: string): string {
113
+ let canonical = cwd
114
+ try {
115
+ canonical = realpathSync(cwd)
116
+ } catch {
117
+ canonical = resolve(cwd)
118
+ }
119
+ const hash = createHash("sha256").update(canonical).digest("hex").slice(0, 8)
120
+ return `${slugOf(basename(canonical))}-${hash}`
121
+ }
122
+
123
+ function isPidAlive(pid: number): boolean {
124
+ try {
125
+ process.kill(pid, 0)
126
+ return true
127
+ } catch (error) {
128
+ return (error as NodeJS.ErrnoException).code === "EPERM"
129
+ }
130
+ }
131
+
132
+ export class SessionStore {
133
+ readonly root: string
134
+
135
+ constructor(root = join(getPaths().dataDir, "sessions")) {
136
+ this.root = root
137
+ }
138
+
139
+ bucketDir(cwd: string): string {
140
+ return join(this.root, sessionBucket(cwd))
141
+ }
142
+
143
+ async lastId(cwd: string): Promise<string | null> {
144
+ const last = await readJsonIfExists<{ id?: unknown }>(
145
+ join(this.bucketDir(cwd), "last.json"),
146
+ )
147
+ return typeof last?.id === "string" ? last.id : null
148
+ }
149
+
150
+ async create(options: CreateSessionOptions): Promise<SessionData> {
151
+ const id = options.id ?? newSessionId()
152
+ if (!isValidSessionId(id)) {
153
+ throw new Error(`会话 id 不合法:${id}`)
154
+ }
155
+ const dir = join(this.bucketDir(options.cwd), id)
156
+ const existing = await this.open(id, options.cwd).catch(() => null)
157
+ if (existing !== null) {
158
+ return existing
159
+ }
160
+
161
+ const workspace = resolve(options.workspace ?? options.cwd)
162
+ const type = options.type ?? "session"
163
+ const metadata = options.metadata ?? {}
164
+ const meta: SessionMeta = {
165
+ type,
166
+ version: 1,
167
+ id,
168
+ createdAt: Date.now(),
169
+ cwd: options.cwd,
170
+ workspace,
171
+ metadata,
172
+ app: APP_NAME,
173
+ appVersion: APP_VERSION,
174
+ model: options.model,
175
+ }
176
+ const header: SessionHeader = { type, metadata, workspace }
177
+ await ensureDir(join(dir, "turns"))
178
+ await writeBytesAtomic(
179
+ join(dir, "turns", "0000.jsonl.zstd"),
180
+ encodeEvents([
181
+ {
182
+ type: "session/header",
183
+ seq: 0,
184
+ time: meta.createdAt,
185
+ data: { ...header },
186
+ },
187
+ ]),
188
+ )
189
+ await writeJsonAtomic(join(dir, "session.json"), meta)
190
+ await this.#writeLast(options.cwd, id)
191
+ return { meta, header, dir, events: [], turns: [] }
192
+ }
193
+
194
+ /** 打开当前 cwd 桶优先,其次其他桶;不存在抛 SessionNotFoundError */
195
+ async open(id: string, cwd?: string): Promise<SessionData> {
196
+ const dir = await this.#findDir(id, cwd)
197
+ const stored = await readJsonIfExists<SessionMeta>(join(dir, "session.json"))
198
+ if (stored === null || typeof stored.type !== "string" || stored.version !== 1) {
199
+ throw new Error(`会话元信息损坏:${id}`)
200
+ }
201
+ const header = (await this.#readHeader(dir)) ?? {
202
+ type: stored.type,
203
+ metadata: stored.metadata ?? {},
204
+ workspace: stored.workspace ?? stored.cwd,
205
+ }
206
+ const meta: SessionMeta = {
207
+ ...stored,
208
+ type: header.type,
209
+ metadata: header.metadata,
210
+ workspace:
211
+ header.workspace === "" ? (stored.workspace ?? stored.cwd) : header.workspace,
212
+ }
213
+ const events = await this.#readEvents(dir)
214
+ return { meta, header, dir, events, turns: groupTurns(events) }
215
+ }
216
+
217
+ /** 取最近一次会话;没有则创建 */
218
+ async openLastOrCreate(cwd: string, model: string): Promise<SessionData> {
219
+ const last = await this.lastId(cwd)
220
+ if (last !== null) {
221
+ try {
222
+ return await this.open(last, cwd)
223
+ } catch {
224
+ return await this.create({ cwd, model })
225
+ }
226
+ }
227
+ return await this.create({ cwd, model })
228
+ }
229
+
230
+ async appendTurn(session: SessionData, events: readonly SessionEvent[]): Promise<number> {
231
+ if (events.length === 0) {
232
+ return session.turns.length
233
+ }
234
+ const release = await this.#acquireLock(session.dir, session.meta.id)
235
+ try {
236
+ const turnsDir = join(session.dir, "turns")
237
+ await ensureDir(turnsDir)
238
+ const names = await readdir(turnsDir)
239
+ let max = 0
240
+ for (const name of names) {
241
+ const match = SEGMENT.exec(name)
242
+ if (match !== null) {
243
+ const index = Number(match[1])
244
+ if (index > max) {
245
+ max = index
246
+ }
247
+ }
248
+ }
249
+ const next = max + 1
250
+ const file = join(turnsDir, `${String(next).padStart(4, "0")}.jsonl.zstd`)
251
+ await writeBytesAtomic(file, encodeEvents(events))
252
+ await this.#writeLast(session.meta.cwd, session.meta.id)
253
+ session.events = [...session.events, ...events]
254
+ session.turns = groupTurns(session.events)
255
+ return next
256
+ } finally {
257
+ await release()
258
+ }
259
+ }
260
+
261
+ async list(options: ListSessionsOptions): Promise<SessionSummary[]> {
262
+ const buckets =
263
+ options.all === true ? await this.#bucketDirs() : [this.bucketDir(options.cwd)]
264
+ const summaries: SessionSummary[] = []
265
+
266
+ for (const bucket of buckets) {
267
+ const last = await readJsonIfExists<{ id?: unknown }>(join(bucket, "last.json"))
268
+ const lastId = typeof last?.id === "string" ? last.id : null
269
+ let names: string[]
270
+ try {
271
+ names = await readdir(bucket)
272
+ } catch {
273
+ continue
274
+ }
275
+ for (const name of names) {
276
+ if (!isValidSessionId(name)) {
277
+ continue
278
+ }
279
+ const dir = join(bucket, name)
280
+ const meta = await readJsonIfExists<SessionMeta>(join(dir, "session.json"))
281
+ if (meta === null) {
282
+ continue
283
+ }
284
+ const segments = await this.#turnFiles(dir)
285
+ const lastFile =
286
+ segments.length === 0
287
+ ? null
288
+ : await statIfExists(
289
+ join(dir, "turns", segments[segments.length - 1] ?? ""),
290
+ )
291
+ summaries.push({
292
+ id: meta.id,
293
+ cwd: meta.cwd,
294
+ dir,
295
+ turns: segments.length,
296
+ updatedAt: lastFile?.mtimeMs ?? meta.createdAt,
297
+ last: lastId === meta.id,
298
+ })
299
+ }
300
+ }
301
+
302
+ summaries.sort((left, right) => right.updatedAt - left.updatedAt)
303
+ return options.limit === undefined ? summaries : summaries.slice(0, options.limit)
304
+ }
305
+
306
+ async remove(id: string): Promise<void> {
307
+ const dir = await this.#findDir(id)
308
+ const meta = await readJsonIfExists<SessionMeta>(join(dir, "session.json"))
309
+ await removePath(dir)
310
+ if (meta !== null) {
311
+ const last = await this.lastId(meta.cwd)
312
+ if (last === id) {
313
+ await removePath(join(this.bucketDir(meta.cwd), "last.json"))
314
+ }
315
+ }
316
+ }
317
+
318
+ async removeAll(cwd: string): Promise<number> {
319
+ const bucket = this.bucketDir(cwd)
320
+ let names: string[]
321
+ try {
322
+ names = await readdir(bucket)
323
+ } catch {
324
+ return 0
325
+ }
326
+ let removed = 0
327
+ for (const name of names) {
328
+ if (!isValidSessionId(name)) {
329
+ continue
330
+ }
331
+ await removePath(join(bucket, name))
332
+ removed += 1
333
+ }
334
+ await removePath(join(bucket, "last.json"))
335
+ return removed
336
+ }
337
+
338
+ async #findDir(id: string, cwd?: string): Promise<string> {
339
+ if (!isValidSessionId(id)) {
340
+ throw new Error(`会话 id 不合法:${id}`)
341
+ }
342
+ const candidates: string[] = []
343
+ if (cwd !== undefined) {
344
+ candidates.push(this.bucketDir(cwd))
345
+ }
346
+ for (const bucket of await this.#bucketDirs()) {
347
+ if (!candidates.includes(bucket)) {
348
+ candidates.push(bucket)
349
+ }
350
+ }
351
+
352
+ const matches: string[] = []
353
+ for (const bucket of candidates) {
354
+ const dir = join(bucket, id)
355
+ if ((await statIfExists(dir)) !== null) {
356
+ matches.push(dir)
357
+ }
358
+ }
359
+ if (matches.length === 0) {
360
+ throw new SessionNotFoundError(id)
361
+ }
362
+ if (matches.length > 1) {
363
+ throw new SessionAmbiguousError(id)
364
+ }
365
+ return matches[0]!
366
+ }
367
+
368
+ async #bucketDirs(): Promise<string[]> {
369
+ let names: string[]
370
+ try {
371
+ names = await readdir(this.root, { withFileTypes: true }).then((entries) =>
372
+ entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name),
373
+ )
374
+ } catch {
375
+ return []
376
+ }
377
+ return names.sort().map((name) => join(this.root, name))
378
+ }
379
+
380
+ async #turnFiles(dir: string): Promise<string[]> {
381
+ try {
382
+ const names = await readdir(join(dir, "turns"))
383
+ return names
384
+ .filter((name) => SEGMENT.test(name) && name !== "0000.jsonl.zstd")
385
+ .sort(
386
+ (left, right) =>
387
+ Number(SEGMENT.exec(left)?.[1]) - Number(SEGMENT.exec(right)?.[1]),
388
+ )
389
+ } catch {
390
+ return []
391
+ }
392
+ }
393
+
394
+ async #readHeader(dir: string): Promise<SessionHeader | null> {
395
+ const data = await readBytesIfExists(join(dir, "turns", "0000.jsonl.zstd"))
396
+ if (data === null) {
397
+ return null
398
+ }
399
+ const event = decodeEvents(data).find((item) => item.type === "session/header")
400
+ if (event === undefined) {
401
+ return null
402
+ }
403
+ const type = event.data["type"]
404
+ const metadata = event.data["metadata"]
405
+ const workspace = event.data["workspace"]
406
+ return {
407
+ type: typeof type === "string" ? type : "session",
408
+ metadata:
409
+ typeof metadata === "object" && metadata !== null && !Array.isArray(metadata)
410
+ ? (metadata as Record<string, unknown>)
411
+ : {},
412
+ workspace: typeof workspace === "string" ? workspace : "",
413
+ }
414
+ }
415
+
416
+ async #readEvents(dir: string): Promise<SessionEvent[]> {
417
+ const files = await this.#turnFiles(dir)
418
+ const events: SessionEvent[] = []
419
+ for (const name of files) {
420
+ const data = await readBytesIfExists(join(dir, "turns", name))
421
+ if (data === null) {
422
+ continue
423
+ }
424
+ events.push(...decodeEvents(data))
425
+ }
426
+ return events
427
+ }
428
+
429
+ async #writeLast(cwd: string, id: string): Promise<void> {
430
+ await writeJsonAtomic(join(this.bucketDir(cwd), "last.json"), {
431
+ id,
432
+ updatedAt: Date.now(),
433
+ })
434
+ }
435
+
436
+ async #acquireLock(dir: string, id: string): Promise<() => Promise<void>> {
437
+ const lock = join(dir, ".lock")
438
+ for (let attempt = 0; attempt < 3; attempt += 1) {
439
+ try {
440
+ await writeFile(
441
+ lock,
442
+ JSON.stringify({ pid: process.pid, acquiredAt: Date.now() }),
443
+ { flag: "wx", mode: 0o600 },
444
+ )
445
+ return async () => {
446
+ await removePath(lock)
447
+ }
448
+ } catch (error) {
449
+ if ((error as NodeJS.ErrnoException).code !== "EEXIST") {
450
+ throw error
451
+ }
452
+ const info = await statIfExists(lock)
453
+ if (info === null) {
454
+ continue
455
+ }
456
+ const content = await readJsonIfExists<{ pid?: unknown }>(lock)
457
+ const pid = typeof content?.pid === "number" ? content.pid : null
458
+ const stale =
459
+ Date.now() - info.mtimeMs > LOCK_STALE_MS || pid === null || !isPidAlive(pid)
460
+ if (!stale) {
461
+ throw new SessionLockedError(id)
462
+ }
463
+ await removePath(lock)
464
+ }
465
+ }
466
+ throw new SessionLockedError(id)
467
+ }
468
+ }
@@ -0,0 +1,61 @@
1
+ /** 会话模型:参考 DeepSeekHarness session.v4,按轮分段的 JSONL 事件流 */
2
+
3
+ export type SessionMode = "chat" | "run"
4
+
5
+ export interface SessionHeader {
6
+ readonly type: string
7
+ readonly metadata: Record<string, unknown>
8
+ readonly workspace: string
9
+ }
10
+
11
+ export interface SessionMeta {
12
+ readonly type: string
13
+ readonly version: 1
14
+ readonly id: string
15
+ readonly createdAt: number
16
+ readonly cwd: string
17
+ readonly workspace: string
18
+ readonly metadata: Record<string, unknown>
19
+ readonly app: string
20
+ readonly appVersion: string
21
+ readonly model: string
22
+ readonly title?: string
23
+ }
24
+
25
+ export type ContentPart =
26
+ | { readonly type: "text"; readonly text: string }
27
+ | { readonly type: "reasoning"; readonly text: string }
28
+ | {
29
+ readonly type: "tool-call"
30
+ readonly id: string
31
+ readonly name: string
32
+ readonly arguments: string
33
+ }
34
+
35
+ export interface SessionMessageRecord {
36
+ readonly role: "user" | "assistant" | "system" | "tool"
37
+ readonly content: readonly ContentPart[]
38
+ readonly source?: Record<string, unknown>
39
+ readonly id?: string
40
+ readonly toolCallId?: string
41
+ }
42
+
43
+ /** 规范化后的流式片段 */
44
+ export interface StreamChunkRecord {
45
+ readonly type: "chunk"
46
+ readonly time: number
47
+ readonly chunk: Record<string, unknown>
48
+ }
49
+
50
+ export interface SessionEvent {
51
+ readonly type: string
52
+ readonly seq: number
53
+ readonly time: number
54
+ readonly data: Record<string, unknown>
55
+ }
56
+
57
+ export interface SessionTurn {
58
+ readonly turn: number
59
+ readonly mode: SessionMode | null
60
+ readonly events: SessionEvent[]
61
+ }
@@ -0,0 +1,21 @@
1
+ // 工作区:会话与 Agent 工具的文件边界
2
+
3
+ import { basename, resolve } from "node:path"
4
+
5
+ export class Workspace {
6
+ readonly root: string
7
+ readonly name: string
8
+
9
+ constructor(root: string) {
10
+ this.root = resolve(root)
11
+ this.name = basename(this.root)
12
+ }
13
+
14
+ static open(path = process.cwd()): Workspace {
15
+ return new Workspace(path)
16
+ }
17
+
18
+ equals(other: Workspace): boolean {
19
+ return this.root === other.root
20
+ }
21
+ }