@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,302 @@
1
+ /*
2
+ * API Key 凭据(支持多个模型供应商)。
3
+ *
4
+ * 与 app-setting.json 分开存放:配置文件可能被分享或进版本库,凭据单独放
5
+ * <configDir>/credentials.json,权限 0600。v2 结构按供应商分槽,v1 只有 openai 槽。
6
+ * 读取顺序:显式参数 > 供应商指定的环境变量(内置为 OPENAI_API_KEY)> 本地凭据。
7
+ * 明文只进请求,界面/日志一律用掩码。
8
+ */
9
+
10
+ import { readFileSync } from "node:fs"
11
+ import { join } from "node:path"
12
+
13
+ import { Result } from "../api/result/result.ts"
14
+ import { CONFIG_CODES } from "./codes.ts"
15
+ import { readJsonIfExists, writeJsonAtomic } from "../platform/file.ts"
16
+ import { readEnv } from "../platform/os.ts"
17
+ import { getPaths } from "../platform/path.ts"
18
+
19
+ /** 凭据文件在 config 根目录下的文件名 */
20
+ export const CREDENTIALS_FILE_NAME = "credentials.json"
21
+
22
+ /** 凭据文件结构版本;v2 增加 providers 分槽,v1 只认 openai */
23
+ export const CREDENTIALS_VERSION = 2
24
+
25
+ /** 单个 key 的长度上限,避免把异常输入写进文件 */
26
+ export const MAX_API_KEY_CHARS = 4096
27
+
28
+ /** 内置供应商的 id;它的 key 放在 openai 槽,兼容 v1 与 OPENAI_API_KEY */
29
+ export const BUILTIN_PROVIDER_ID = "openai"
30
+
31
+ /** 凭据文件结构;缺失的槽都视为没有 */
32
+ interface CredentialsFile {
33
+ readonly version: number
34
+ readonly openai?: { readonly apiKey?: string | null } | null
35
+ readonly providers?: Readonly<Record<string, string | null>> | null
36
+ }
37
+
38
+ /** key 的来源:环境变量或本地凭据文件 */
39
+ export type ApiKeySource = "env" | "credentials"
40
+
41
+ export interface ResolvedApiKey {
42
+ readonly apiKey: string
43
+ readonly source: ApiKeySource
44
+ }
45
+
46
+ export interface ApiKeyStatus {
47
+ readonly configured: boolean
48
+ /** 当前生效来源;未配置为 null */
49
+ readonly source: ApiKeySource | null
50
+ /** 掩码后的 key,例如 `sk-…abcd`;未配置为 null */
51
+ readonly masked: string | null
52
+ /** 凭据文件路径,便于界面提示 */
53
+ readonly file: string
54
+ /** 环境变量是否设置(设置时优先于文件) */
55
+ readonly envOverride: boolean
56
+ /** 本地凭据文件里是否有 key(即使被环境变量覆盖也保留,便于界面提供清除) */
57
+ readonly stored: boolean
58
+ }
59
+
60
+ /** 单个供应商的 Key 状态 */
61
+ export interface ProviderKeyStatus extends ApiKeyStatus {
62
+ /** 供应商自己的环境变量名;内置为 OPENAI_API_KEY */
63
+ readonly envVar: string | null
64
+ }
65
+
66
+ /** 供应商凭据来源描述(只用于解析,不含明文) */
67
+ export interface ProviderKeyRef {
68
+ readonly id: string
69
+ readonly apiKeyEnv: string | null
70
+ }
71
+
72
+ /** 默认凭据路径;测试/多环境时可显式传 configDir */
73
+ export function credentialsFile(configDir: string = getPaths().configDir): string {
74
+ return join(configDir, CREDENTIALS_FILE_NAME)
75
+ }
76
+
77
+ /** 列表展示用的掩码;短 key 直接全遮 */
78
+ export function maskApiKey(apiKey: string): string {
79
+ const trimmed = apiKey.trim()
80
+ if (trimmed.length <= 8) {
81
+ return "••••"
82
+ }
83
+ const head = trimmed.slice(0, 3)
84
+ return `${head}…${trimmed.slice(-4)}`
85
+ }
86
+
87
+ /** 校验并规范化用户输入的 key;空白、含控制字符或超长都视为非法 */
88
+ export function normalizeApiKey(raw: unknown): string | null {
89
+ if (typeof raw !== "string") {
90
+ return null
91
+ }
92
+ const trimmed = raw.trim()
93
+ if (trimmed === "" || trimmed.length > MAX_API_KEY_CHARS) {
94
+ return null
95
+ }
96
+ if (/[\s\u0000-\u001f\u007f]/.test(trimmed)) {
97
+ return null
98
+ }
99
+ return trimmed
100
+ }
101
+
102
+ function parseCredentials(value: unknown): CredentialsFile | null {
103
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
104
+ return null
105
+ }
106
+ const record = value as Record<string, unknown>
107
+ const openaiRaw = record["openai"]
108
+ const openai =
109
+ typeof openaiRaw === "object" && openaiRaw !== null
110
+ ? (openaiRaw as Record<string, unknown>)
111
+ : null
112
+ const providersRaw = record["providers"]
113
+ const providers: Record<string, string | null> = {}
114
+ if (typeof providersRaw === "object" && providersRaw !== null) {
115
+ for (const [id, raw] of Object.entries(providersRaw as Record<string, unknown>)) {
116
+ providers[id] = normalizeApiKey(raw)
117
+ }
118
+ }
119
+ return {
120
+ version: typeof record["version"] === "number" ? record["version"] : 1,
121
+ openai: openai === null ? null : { apiKey: normalizeApiKey(openai["apiKey"]) },
122
+ providers,
123
+ }
124
+ }
125
+
126
+ function readFileValue(file: string): CredentialsFile | null {
127
+ let text: string
128
+ try {
129
+ text = readFileSync(file, "utf8")
130
+ } catch {
131
+ return null
132
+ }
133
+ try {
134
+ return parseCredentials(JSON.parse(text))
135
+ } catch {
136
+ return null
137
+ }
138
+ }
139
+
140
+ async function readFileValueAsync(file: string): Promise<CredentialsFile | null> {
141
+ try {
142
+ return parseCredentials(await readJsonIfExists<unknown>(file))
143
+ } catch {
144
+ return null
145
+ }
146
+ }
147
+
148
+ function storedKey(value: CredentialsFile | null, providerId: string): string | null {
149
+ if (value === null) {
150
+ return null
151
+ }
152
+ if (providerId === BUILTIN_PROVIDER_ID) {
153
+ return normalizeApiKey(value.openai?.apiKey)
154
+ }
155
+ return normalizeApiKey(value.providers?.[providerId])
156
+ }
157
+
158
+ function envKey(provider: ProviderKeyRef): { apiKey: string; envVar: string } | null {
159
+ const envVar =
160
+ provider.apiKeyEnv ?? (provider.id === BUILTIN_PROVIDER_ID ? "OPENAI_API_KEY" : null)
161
+ if (envVar === null) {
162
+ return null
163
+ }
164
+ const raw = normalizeApiKey(readEnv(envVar))
165
+ return raw === null ? null : { apiKey: raw, envVar }
166
+ }
167
+
168
+ /** 某个供应商本地保存的 key(同步) */
169
+ export function readProviderApiKeySync(
170
+ providerId: string,
171
+ file: string = credentialsFile(),
172
+ ): string | null {
173
+ return storedKey(readFileValue(file), providerId)
174
+ }
175
+
176
+ /** 某个供应商本地保存的 key(异步) */
177
+ export async function readProviderApiKey(
178
+ providerId: string,
179
+ file: string = credentialsFile(),
180
+ ): Promise<string | null> {
181
+ return storedKey(await readFileValueAsync(file), providerId)
182
+ }
183
+
184
+ /** 默认(内置 openai)供应商本地保存的 key */
185
+ export function readStoredApiKeySync(file: string = credentialsFile()): string | null {
186
+ return readProviderApiKeySync(BUILTIN_PROVIDER_ID, file)
187
+ }
188
+
189
+ export async function readStoredApiKey(file: string = credentialsFile()): Promise<string | null> {
190
+ return await readProviderApiKey(BUILTIN_PROVIDER_ID, file)
191
+ }
192
+
193
+ /** 解析某个供应商的 key:环境变量优先于本地凭据 */
194
+ export function resolveProviderApiKeySync(
195
+ provider: ProviderKeyRef,
196
+ file: string = credentialsFile(),
197
+ ): ResolvedApiKey | null {
198
+ const fromEnv = envKey(provider)
199
+ if (fromEnv !== null) {
200
+ return { apiKey: fromEnv.apiKey, source: "env" }
201
+ }
202
+ const stored = readProviderApiKeySync(provider.id, file)
203
+ return stored === null ? null : { apiKey: stored, source: "credentials" }
204
+ }
205
+
206
+ /** 解析默认供应商的 key:OPENAI_API_KEY 优先于本地凭据 */
207
+ export function resolveApiKeySync(file: string = credentialsFile()): ResolvedApiKey | null {
208
+ return resolveProviderApiKeySync({ id: BUILTIN_PROVIDER_ID, apiKeyEnv: null }, file)
209
+ }
210
+
211
+ /** 默认供应商的状态(CLI 与 API Key 弹窗用) */
212
+ export function apiKeyStatusSync(file: string = credentialsFile()): ApiKeyStatus {
213
+ return providerKeyStatusSync({ id: BUILTIN_PROVIDER_ID, apiKeyEnv: null }, file)
214
+ }
215
+
216
+ /** 指定供应商的 Key 状态(掩码) */
217
+ export function providerKeyStatusSync(
218
+ provider: ProviderKeyRef,
219
+ file: string = credentialsFile(),
220
+ ): ProviderKeyStatus {
221
+ const resolved = resolveProviderApiKeySync(provider, file)
222
+ const envVar =
223
+ provider.apiKeyEnv ?? (provider.id === BUILTIN_PROVIDER_ID ? "OPENAI_API_KEY" : null)
224
+ return {
225
+ configured: resolved !== null,
226
+ source: resolved?.source ?? null,
227
+ masked: resolved === null ? null : maskApiKey(resolved.apiKey),
228
+ file,
229
+ envOverride: envKey(provider) !== null,
230
+ stored: readProviderApiKeySync(provider.id, file) !== null,
231
+ envVar,
232
+ }
233
+ }
234
+
235
+ async function writeCredentials(file: string, value: CredentialsFile): Promise<Result<void>> {
236
+ try {
237
+ await writeJsonAtomic(file, value, { mode: 0o600 })
238
+ } catch {
239
+ return Result.error(CONFIG_CODES.credentialsWriteFailed)
240
+ }
241
+ return Result.success()
242
+ }
243
+
244
+ /** 保存某个供应商的 key;providerId=openai 时写内置槽 */
245
+ export async function saveProviderApiKey(
246
+ providerId: string,
247
+ raw: unknown,
248
+ file: string = credentialsFile(),
249
+ ): Promise<Result<void>> {
250
+ const apiKey = normalizeApiKey(raw)
251
+ if (apiKey === null) {
252
+ return Result.error(CONFIG_CODES.invalidApiKey)
253
+ }
254
+ const current = readFileValue(file)
255
+ if (providerId === BUILTIN_PROVIDER_ID) {
256
+ return await writeCredentials(file, {
257
+ version: CREDENTIALS_VERSION,
258
+ openai: { apiKey },
259
+ providers: current?.providers ?? {},
260
+ })
261
+ }
262
+ return await writeCredentials(file, {
263
+ version: CREDENTIALS_VERSION,
264
+ openai: current?.openai ?? { apiKey: null },
265
+ providers: { ...(current?.providers ?? {}), [providerId]: apiKey },
266
+ })
267
+ }
268
+
269
+ /** 清除某个供应商的 key;内置槽清除后 OPENAI_API_KEY 仍可能生效 */
270
+ export async function clearProviderApiKey(
271
+ providerId: string,
272
+ file: string = credentialsFile(),
273
+ ): Promise<Result<void>> {
274
+ const current = readFileValue(file)
275
+ if (providerId === BUILTIN_PROVIDER_ID) {
276
+ return await writeCredentials(file, {
277
+ version: CREDENTIALS_VERSION,
278
+ openai: { apiKey: null },
279
+ providers: current?.providers ?? {},
280
+ })
281
+ }
282
+ const providers: Record<string, string | null> = { ...(current?.providers ?? {}) }
283
+ delete providers[providerId]
284
+ return await writeCredentials(file, {
285
+ version: CREDENTIALS_VERSION,
286
+ openai: current?.openai ?? { apiKey: null },
287
+ providers,
288
+ })
289
+ }
290
+
291
+ /** 保存默认供应商的 key(兼容旧调用) */
292
+ export async function saveStoredApiKey(
293
+ raw: unknown,
294
+ file: string = credentialsFile(),
295
+ ): Promise<Result<void>> {
296
+ return await saveProviderApiKey(BUILTIN_PROVIDER_ID, raw, file)
297
+ }
298
+
299
+ /** 清除默认供应商的本地 key(兼容旧调用) */
300
+ export async function clearStoredApiKey(file: string = credentialsFile()): Promise<Result<void>> {
301
+ return await clearProviderApiKey(BUILTIN_PROVIDER_ID, file)
302
+ }
@@ -0,0 +1,32 @@
1
+ import { SETTING_VERSION, type AppSetting, type ModelsSetting } from "./types.ts"
2
+
3
+ /** 单供应商时代的默认模型设置;旧配置缺 models 时用它兜底 */
4
+ export const DEFAULT_MODELS: ModelsSetting = Object.freeze({
5
+ providers: Object.freeze([]),
6
+ activeProvider: "openai",
7
+ activeModel: null,
8
+ activeReasoning: "off",
9
+ })
10
+
11
+ /** 缺省配置。缺文件或读取失败时作为回退 */
12
+ export const DEFAULT_SETTINGS: AppSetting = Object.freeze({
13
+ version: SETTING_VERSION,
14
+ logger: Object.freeze({ level: "info" as const }),
15
+ openai: Object.freeze({
16
+ baseUrl: null,
17
+ model: "gpt-4o-mini",
18
+ timeoutMs: 60_000,
19
+ maxRetries: 2,
20
+ }),
21
+ models: DEFAULT_MODELS,
22
+ network: Object.freeze({ proxy: null }),
23
+ sandbox: Object.freeze({
24
+ mode: "strict" as const,
25
+ backend: "auto" as const,
26
+ access: "read-only" as const,
27
+ maxConcurrent: 2,
28
+ defaultTimeoutMs: 60_000,
29
+ defaultMemoryMB: 512,
30
+ outputLimitBytes: 16 * 1024 * 1024,
31
+ }),
32
+ })
@@ -0,0 +1,10 @@
1
+ /*
2
+ * 配置层入口。
3
+ * 校验、默认值与读写;错误以 Result code 返回,不抛异常。
4
+ */
5
+
6
+ export * from "./codes.ts"
7
+ export * from "./defaults.ts"
8
+ export * from "./loader.ts"
9
+ export * from "./types.ts"
10
+ export * from "./validate.ts"
@@ -0,0 +1,80 @@
1
+ /*
2
+ * 配置读写。
3
+ * 默认路径为用户配置目录下的 app-setting.json;缺文件时写入默认值。
4
+ * 失败时 Result 的 code 说明原因,getData() 回退默认配置,供调用方决定是否继续启动。
5
+ */
6
+
7
+ import { join } from "node:path"
8
+
9
+ import { Result } from "../api/result/result.ts"
10
+ import { readTextIfExists, writeJsonAtomic } from "../platform/file.ts"
11
+ import { getPaths } from "../platform/path.ts"
12
+ import { CONFIG_CODES } from "./codes.ts"
13
+ import { DEFAULT_SETTINGS } from "./defaults.ts"
14
+ import type { AppSetting } from "./types.ts"
15
+ import { validateSettings } from "./validate.ts"
16
+
17
+ /** 配置文件在 config 根目录下的文件名 */
18
+ export const SETTING_FILE_NAME = "app-setting.json"
19
+
20
+ /** 默认配置路径 */
21
+ export function settingsFile(): string {
22
+ return join(getPaths().configDir, SETTING_FILE_NAME)
23
+ }
24
+
25
+ /** 读取配置。文件不存在时创建默认配置 */
26
+ export async function loadSettings(file: string = settingsFile()): Promise<Result<AppSetting>> {
27
+ let text: string | null
28
+ try {
29
+ text = await readTextIfExists(file)
30
+ } catch {
31
+ return Result.errorWithData<AppSetting>(DEFAULT_SETTINGS, CONFIG_CODES.readFailed)
32
+ }
33
+
34
+ if (text === null) {
35
+ return await writeDefaults(file)
36
+ }
37
+
38
+ let parsed: unknown
39
+ try {
40
+ parsed = JSON.parse(text)
41
+ } catch {
42
+ // 损坏文件不覆盖,留给调用方决定是否备份
43
+ return Result.errorWithData<AppSetting>(DEFAULT_SETTINGS, CONFIG_CODES.parseFailed)
44
+ }
45
+
46
+ const validated = validateSettings(parsed)
47
+ if (!validated.isSuccess()) {
48
+ return Result.errorWithData<AppSetting>(
49
+ DEFAULT_SETTINGS,
50
+ validated.getCode() ?? CONFIG_CODES.invalid,
51
+ )
52
+ }
53
+ return validated
54
+ }
55
+
56
+ /** 校验后原子写回;字段不合法时不落盘 */
57
+ export async function saveSettings(
58
+ settings: AppSetting,
59
+ file: string = settingsFile(),
60
+ ): Promise<Result<void>> {
61
+ const validated = validateSettings(settings)
62
+ if (!validated.isSuccess()) {
63
+ return Result.error(validated.getCode() ?? CONFIG_CODES.invalid)
64
+ }
65
+ try {
66
+ await writeJsonAtomic(file, validated.getData())
67
+ } catch {
68
+ return Result.error(CONFIG_CODES.writeFailed)
69
+ }
70
+ return Result.success()
71
+ }
72
+
73
+ async function writeDefaults(file: string): Promise<Result<AppSetting>> {
74
+ try {
75
+ await writeJsonAtomic(file, DEFAULT_SETTINGS)
76
+ } catch {
77
+ return Result.errorWithData<AppSetting>(DEFAULT_SETTINGS, CONFIG_CODES.writeFailed)
78
+ }
79
+ return Result.successWithData<AppSetting>(DEFAULT_SETTINGS)
80
+ }
@@ -0,0 +1,133 @@
1
+ /*
2
+ * 模型供应商与模型解析。
3
+ *
4
+ * 内置供应商 id 为 openai,由 app-setting.json 的 openai.* 描述;
5
+ * 自定义供应商来自 models.providers,接口都按 OpenAI 兼容处理(baseUrl + key)。
6
+ */
7
+
8
+ import { BUILTIN_PROVIDER_ID, credentialsFile, resolveProviderApiKeySync } from "./credentials.ts"
9
+ import { DEFAULT_MODELS } from "./defaults.ts"
10
+ import type { AppSetting, ModelProviderSetting, ModelsSetting } from "./types.ts"
11
+
12
+ export { BUILTIN_PROVIDER_ID }
13
+
14
+ /** 解析后的供应商:内置项同样带 builtin 标记与可用的模型列表 */
15
+ export interface ResolvedModelProvider extends ModelProviderSetting {
16
+ readonly builtin: boolean
17
+ }
18
+
19
+ /** 旧配置没有 models 节时用默认值 */
20
+ export function modelsSetting(settings: AppSetting): ModelsSetting {
21
+ return settings.models ?? DEFAULT_MODELS
22
+ }
23
+
24
+ /** 供应商列表:内置 openai 永远排第一,自定义按配置顺序 */
25
+ export function listModelProviders(settings: AppSetting): readonly ResolvedModelProvider[] {
26
+ const builtin: ResolvedModelProvider = {
27
+ id: BUILTIN_PROVIDER_ID,
28
+ name: settings.openai.baseUrl === null ? "OpenAI(默认)" : "默认供应商",
29
+ baseUrl: settings.openai.baseUrl,
30
+ models: [settings.openai.model],
31
+ defaultModel: settings.openai.model,
32
+ apiKeyEnv: "OPENAI_API_KEY",
33
+ builtin: true,
34
+ }
35
+ return [
36
+ builtin,
37
+ ...modelsSetting(settings).providers.map((provider) => ({ ...provider, builtin: false })),
38
+ ]
39
+ }
40
+
41
+ export function findModelProvider(settings: AppSetting, id: string): ResolvedModelProvider | null {
42
+ return listModelProviders(settings).find((provider) => provider.id === id) ?? null
43
+ }
44
+
45
+ /** 当前生效的供应商;配置里的 id 失效时退回内置 openai */
46
+ export function activeModelProvider(settings: AppSetting): ResolvedModelProvider {
47
+ const active = findModelProvider(settings, modelsSetting(settings).activeProvider)
48
+ return active ?? listModelProviders(settings)[0]!
49
+ }
50
+
51
+ /**
52
+ * 某次请求实际使用的模型:
53
+ * 显式覆盖 > 全局 activeModel(仅当前供应商)> 供应商 defaultModel > 模型列表第一个 > 全局 openai.model
54
+ */
55
+ export function effectiveModel(
56
+ settings: AppSetting,
57
+ provider: ResolvedModelProvider,
58
+ override?: string | null,
59
+ ): string {
60
+ const explicit = typeof override === "string" ? override.trim() : ""
61
+ if (explicit !== "") {
62
+ return explicit
63
+ }
64
+ const models = modelsSetting(settings)
65
+ if (provider.id === models.activeProvider && models.activeModel !== null) {
66
+ return models.activeModel
67
+ }
68
+ if (provider.defaultModel !== null && provider.defaultModel !== "") {
69
+ return provider.defaultModel
70
+ }
71
+ if (provider.models.length > 0) {
72
+ return provider.models[0]!
73
+ }
74
+ return settings.openai.model
75
+ }
76
+
77
+ /** 某次请求使用的供应商:请求里带了就用它,否则用全局当前供应商 */
78
+ export function requestProvider(
79
+ settings: AppSetting,
80
+ providerId?: string | null,
81
+ ): ResolvedModelProvider {
82
+ const requested = typeof providerId === "string" ? providerId.trim() : ""
83
+ if (requested !== "") {
84
+ const found = findModelProvider(settings, requested)
85
+ if (found !== null) {
86
+ return found
87
+ }
88
+ }
89
+ return activeModelProvider(settings)
90
+ }
91
+
92
+ /**
93
+ * 某次请求的推理强度:
94
+ * 显式覆盖 > 全局 activeReasoning(仅当前供应商)> off
95
+ */
96
+ export function effectiveReasoning(
97
+ settings: AppSetting,
98
+ provider: ResolvedModelProvider,
99
+ override?: string | null,
100
+ ): string {
101
+ const explicit = typeof override === "string" ? override.trim() : ""
102
+ if (explicit !== "") {
103
+ return explicit
104
+ }
105
+ const models = modelsSetting(settings)
106
+ if (provider.id === models.activeProvider) {
107
+ return models.activeReasoning
108
+ }
109
+ return "off"
110
+ }
111
+
112
+ /** 供应商对应的 OpenAI 设置(baseUrl + 实际模型) */
113
+ export function providerOpenAISettings(
114
+ settings: AppSetting,
115
+ provider: ResolvedModelProvider,
116
+ model?: string | null,
117
+ ): AppSetting["openai"] {
118
+ return {
119
+ ...settings.openai,
120
+ baseUrl: provider.baseUrl,
121
+ model: effectiveModel(settings, provider, model),
122
+ }
123
+ }
124
+
125
+ /** 供应商的 key:环境变量优先,然后本地凭据;没有返回 null */
126
+ export function providerApiKey(provider: ResolvedModelProvider, configDir: string): string | null {
127
+ return (
128
+ resolveProviderApiKeySync(
129
+ { id: provider.id, apiKeyEnv: provider.apiKeyEnv },
130
+ credentialsFile(configDir),
131
+ )?.apiKey ?? null
132
+ )
133
+ }
@@ -0,0 +1,88 @@
1
+ import type { LevelWithSilent } from "pino"
2
+
3
+ /** 配置文件结构版本,字段变更时递增并在 loader 中迁移 */
4
+ export const SETTING_VERSION = 1
5
+
6
+ export interface LoggerSetting {
7
+ readonly level: LevelWithSilent
8
+ }
9
+
10
+ export interface OpenAISetting {
11
+ /** 兼容网关地址;null 表示使用 SDK 默认值或 OPENAI_BASE_URL */
12
+ readonly baseUrl: string | null
13
+ readonly model: string
14
+ readonly timeoutMs: number
15
+ readonly maxRetries: number
16
+ }
17
+
18
+ /** 自定义模型供应商(OpenAI 兼容接口);内置供应商 openai 由 openai.* 字段描述 */
19
+ export interface ModelProviderSetting {
20
+ /** 供应商标识,1-32 位 [a-z0-9-_.];不能叫 openai */
21
+ readonly id: string
22
+ readonly name: string
23
+ /** null 表示使用 SDK 默认地址 */
24
+ readonly baseUrl: string | null
25
+ /** 预置模型列表;可手动维护,也可从供应商接口拉取 */
26
+ readonly models: readonly string[]
27
+ /** 该供应商缺省模型;null 时取列表第一个或全局 openai.model */
28
+ readonly defaultModel: string | null
29
+ /** 可选:用这个环境变量提供该供应商的 API Key(优先级高于本地凭据) */
30
+ readonly apiKeyEnv: string | null
31
+ }
32
+
33
+ /** 推理强度;参考 Harness:off / low / high / max */
34
+ export type ReasoningLevel = "off" | "low" | "high" | "max"
35
+
36
+ export const REASONING_LEVELS: readonly ReasoningLevel[] = ["off", "low", "high", "max"]
37
+
38
+ export interface ModelsSetting {
39
+ /** 自定义供应商;内置 openai 不在列表里 */
40
+ readonly providers: readonly ModelProviderSetting[]
41
+ /** 当前使用的供应商 id;openai 表示内置 */
42
+ readonly activeProvider: string
43
+ /** 当前使用的模型;null 表示用供应商缺省模型 */
44
+ readonly activeModel: string | null
45
+ /** 当前推理强度;off 表示不发推理参数 */
46
+ readonly activeReasoning: ReasoningLevel
47
+ }
48
+
49
+ /** 代理类型,一期只支持 http/https 代理 */
50
+ export type ProxyType = "http"
51
+
52
+ export interface ProxySetting {
53
+ readonly type: ProxyType
54
+ /** 代理地址,认证信息可写在 URL 里 */
55
+ readonly url: string
56
+ /** 不走代理的主机后缀,例如 example.com、.internal */
57
+ readonly noProxy: readonly string[]
58
+ }
59
+
60
+ export interface NetworkSetting {
61
+ /** null 表示直连 */
62
+ readonly proxy: ProxySetting | null
63
+ }
64
+
65
+ export type SandboxMode = "off" | "strict" | "best-effort"
66
+ export type SandboxBackend = "auto" | "bwrap" | "nsjail"
67
+ export type SandboxAccess = "read-only" | "workspace-write" | "danger-full-access"
68
+
69
+ /** OS 级 sandbox 配置 */
70
+ export interface SandboxSetting {
71
+ readonly mode: SandboxMode
72
+ readonly backend: SandboxBackend
73
+ readonly access: SandboxAccess
74
+ readonly maxConcurrent: number
75
+ readonly defaultTimeoutMs: number
76
+ readonly defaultMemoryMB: number
77
+ readonly outputLimitBytes: number
78
+ }
79
+
80
+ export interface AppSetting {
81
+ readonly version: number
82
+ readonly logger: LoggerSetting
83
+ readonly openai: OpenAISetting
84
+ /** 多供应商/模型设置;旧配置没有这一节时按默认值处理 */
85
+ readonly models?: ModelsSetting
86
+ readonly network: NetworkSetting
87
+ readonly sandbox: SandboxSetting
88
+ }