@wardby/cli 0.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 (412) hide show
  1. package/.env.example +131 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +2 -0
  4. package/README.md +282 -0
  5. package/bin/wardby.js +3 -0
  6. package/deploy/local/docker-compose.yml +19 -0
  7. package/dist/claude-coding-worker/driver.d.ts +70 -0
  8. package/dist/claude-coding-worker/driver.js +128 -0
  9. package/dist/claude-coding-worker/main.d.ts +2 -0
  10. package/dist/claude-coding-worker/main.js +41 -0
  11. package/dist/claude-coding-worker/sdk.d.ts +4 -0
  12. package/dist/claude-coding-worker/sdk.js +43 -0
  13. package/dist/claude-coding-worker/tool-relay.d.ts +1 -0
  14. package/dist/claude-coding-worker/tool-relay.js +9 -0
  15. package/dist/cli-help.d.ts +1 -0
  16. package/dist/cli-help.js +20 -0
  17. package/dist/cli.d.ts +18 -0
  18. package/dist/cli.js +629 -0
  19. package/dist/coding/observability.d.ts +59 -0
  20. package/dist/coding/observability.js +77 -0
  21. package/dist/coding/profile.d.ts +88 -0
  22. package/dist/coding/profile.js +137 -0
  23. package/dist/coding/protocol.d.ts +345 -0
  24. package/dist/coding/protocol.js +445 -0
  25. package/dist/coding/provider.d.ts +4 -0
  26. package/dist/coding/provider.js +18 -0
  27. package/dist/coding-proxy/main.d.ts +1 -0
  28. package/dist/coding-proxy/main.js +51 -0
  29. package/dist/coding-worker/artifact.d.ts +16 -0
  30. package/dist/coding-worker/artifact.js +37 -0
  31. package/dist/coding-worker/driver.d.ts +46 -0
  32. package/dist/coding-worker/driver.js +158 -0
  33. package/dist/coding-worker/errors.d.ts +1 -0
  34. package/dist/coding-worker/errors.js +23 -0
  35. package/dist/coding-worker/isolation-probe.d.ts +1 -0
  36. package/dist/coding-worker/isolation-probe.js +146 -0
  37. package/dist/coding-worker/keeper.d.ts +4 -0
  38. package/dist/coding-worker/keeper.js +29 -0
  39. package/dist/coding-worker/main.d.ts +2 -0
  40. package/dist/coding-worker/main.js +43 -0
  41. package/dist/coding-worker/sdk.d.ts +26 -0
  42. package/dist/coding-worker/sdk.js +28 -0
  43. package/dist/coding-worker/types.d.ts +64 -0
  44. package/dist/coding-worker/types.js +1 -0
  45. package/dist/config/providers.d.ts +158 -0
  46. package/dist/config/providers.js +162 -0
  47. package/dist/core/budget-groups.d.ts +72 -0
  48. package/dist/core/budget-groups.js +149 -0
  49. package/dist/core/budget.d.ts +63 -0
  50. package/dist/core/budget.js +69 -0
  51. package/dist/core/coding-queue.d.ts +32 -0
  52. package/dist/core/coding-queue.js +54 -0
  53. package/dist/core/cron.d.ts +31 -0
  54. package/dist/core/cron.js +43 -0
  55. package/dist/core/datastores.d.ts +41 -0
  56. package/dist/core/datastores.js +105 -0
  57. package/dist/core/db.d.ts +2 -0
  58. package/dist/core/db.js +2 -0
  59. package/dist/core/dispatch.d.ts +81 -0
  60. package/dist/core/dispatch.js +184 -0
  61. package/dist/core/engine-native.d.ts +29 -0
  62. package/dist/core/engine-native.js +259 -0
  63. package/dist/core/http-runtime.d.ts +7 -0
  64. package/dist/core/http-runtime.js +101 -0
  65. package/dist/core/lease.d.ts +13 -0
  66. package/dist/core/lease.js +22 -0
  67. package/dist/core/logger.d.ts +13 -0
  68. package/dist/core/logger.js +45 -0
  69. package/dist/core/memory-tools.d.ts +11 -0
  70. package/dist/core/memory-tools.js +122 -0
  71. package/dist/core/reconciler.d.ts +45 -0
  72. package/dist/core/reconciler.js +152 -0
  73. package/dist/core/runner.d.ts +87 -0
  74. package/dist/core/runner.js +529 -0
  75. package/dist/core/scheduler.d.ts +47 -0
  76. package/dist/core/scheduler.js +121 -0
  77. package/dist/core/secrets.d.ts +46 -0
  78. package/dist/core/secrets.js +100 -0
  79. package/dist/core/subagent-memory-tools.d.ts +18 -0
  80. package/dist/core/subagent-memory-tools.js +121 -0
  81. package/dist/core/timing.d.ts +7 -0
  82. package/dist/core/timing.js +7 -0
  83. package/dist/core/webhooks.d.ts +23 -0
  84. package/dist/core/webhooks.js +113 -0
  85. package/dist/env.d.ts +11 -0
  86. package/dist/env.js +13 -0
  87. package/dist/import/budgets.d.ts +16 -0
  88. package/dist/import/budgets.js +21 -0
  89. package/dist/import/bundle.d.ts +16 -0
  90. package/dist/import/bundle.js +61 -0
  91. package/dist/import/cli-args.d.ts +2 -0
  92. package/dist/import/cli-args.js +44 -0
  93. package/dist/import/create.d.ts +34 -0
  94. package/dist/import/create.js +363 -0
  95. package/dist/import/index.d.ts +25 -0
  96. package/dist/import/index.js +130 -0
  97. package/dist/import/model-gate.d.ts +1 -0
  98. package/dist/import/model-gate.js +3 -0
  99. package/dist/import/neutral-schema.d.ts +369 -0
  100. package/dist/import/neutral-schema.js +109 -0
  101. package/dist/import/preflight.d.ts +41 -0
  102. package/dist/import/preflight.js +71 -0
  103. package/dist/import/report.d.ts +5 -0
  104. package/dist/import/report.js +98 -0
  105. package/dist/import/tool-scan.d.ts +8 -0
  106. package/dist/import/tool-scan.js +20 -0
  107. package/dist/mcp/auth/ownership.d.ts +113 -0
  108. package/dist/mcp/auth/ownership.js +87 -0
  109. package/dist/mcp/auth/principal.d.ts +9 -0
  110. package/dist/mcp/auth/principal.js +9 -0
  111. package/dist/mcp/auth/resource-server.d.ts +47 -0
  112. package/dist/mcp/auth/resource-server.js +82 -0
  113. package/dist/mcp/auth/self-hosted/browser.d.ts +3 -0
  114. package/dist/mcp/auth/self-hosted/browser.js +273 -0
  115. package/dist/mcp/auth/self-hosted/cli.d.ts +2 -0
  116. package/dist/mcp/auth/self-hosted/cli.js +39 -0
  117. package/dist/mcp/auth/self-hosted/credentials.d.ts +58 -0
  118. package/dist/mcp/auth/self-hosted/credentials.js +106 -0
  119. package/dist/mcp/auth/self-hosted/rate-limit.d.ts +13 -0
  120. package/dist/mcp/auth/self-hosted/rate-limit.js +20 -0
  121. package/dist/mcp/auth/self-hosted/session.d.ts +36 -0
  122. package/dist/mcp/auth/self-hosted/session.js +110 -0
  123. package/dist/mcp/capabilities.d.ts +11 -0
  124. package/dist/mcp/capabilities.js +10 -0
  125. package/dist/mcp/context.d.ts +46 -0
  126. package/dist/mcp/context.js +1 -0
  127. package/dist/mcp/errors.d.ts +13 -0
  128. package/dist/mcp/errors.js +22 -0
  129. package/dist/mcp/index.d.ts +32 -0
  130. package/dist/mcp/index.js +187 -0
  131. package/dist/mcp/jsonrpc.d.ts +8 -0
  132. package/dist/mcp/jsonrpc.js +1 -0
  133. package/dist/mcp/server.d.ts +107 -0
  134. package/dist/mcp/server.js +203 -0
  135. package/dist/mcp/tasks/manager.d.ts +63 -0
  136. package/dist/mcp/tasks/manager.js +103 -0
  137. package/dist/mcp/tools/agents.d.ts +2 -0
  138. package/dist/mcp/tools/agents.js +375 -0
  139. package/dist/mcp/tools/budget-groups.d.ts +2 -0
  140. package/dist/mcp/tools/budget-groups.js +136 -0
  141. package/dist/mcp/tools/datastore.d.ts +2 -0
  142. package/dist/mcp/tools/datastore.js +217 -0
  143. package/dist/mcp/tools/memory.d.ts +3 -0
  144. package/dist/mcp/tools/memory.js +60 -0
  145. package/dist/mcp/tools/models.d.ts +8 -0
  146. package/dist/mcp/tools/models.js +15 -0
  147. package/dist/mcp/tools/runs.d.ts +2 -0
  148. package/dist/mcp/tools/runs.js +61 -0
  149. package/dist/mcp/tools/scheduling.d.ts +2 -0
  150. package/dist/mcp/tools/scheduling.js +48 -0
  151. package/dist/mcp/tools/secret-elicitation-form.d.ts +22 -0
  152. package/dist/mcp/tools/secret-elicitation-form.js +93 -0
  153. package/dist/mcp/tools/secret-elicitation-server.d.ts +5 -0
  154. package/dist/mcp/tools/secret-elicitation-server.js +57 -0
  155. package/dist/mcp/tools/secret-elicitation.d.ts +38 -0
  156. package/dist/mcp/tools/secret-elicitation.js +52 -0
  157. package/dist/mcp/tools/secrets.d.ts +13 -0
  158. package/dist/mcp/tools/secrets.js +124 -0
  159. package/dist/mcp/tools/subagents.d.ts +2 -0
  160. package/dist/mcp/tools/subagents.js +133 -0
  161. package/dist/mcp/tools/text-result.d.ts +6 -0
  162. package/dist/mcp/tools/text-result.js +3 -0
  163. package/dist/mcp/tools/tools.d.ts +2 -0
  164. package/dist/mcp/tools/tools.js +211 -0
  165. package/dist/mcp/tools/trigger.d.ts +2 -0
  166. package/dist/mcp/tools/trigger.js +120 -0
  167. package/dist/mcp/tools/webhooks.d.ts +2 -0
  168. package/dist/mcp/tools/webhooks.js +34 -0
  169. package/dist/mcp/transport/http-limits.d.ts +17 -0
  170. package/dist/mcp/transport/http-limits.js +92 -0
  171. package/dist/mcp/transport/stdio.d.ts +23 -0
  172. package/dist/mcp/transport/stdio.js +6 -0
  173. package/dist/mcp/transport/streamable-http.d.ts +34 -0
  174. package/dist/mcp/transport/streamable-http.js +158 -0
  175. package/dist/mcp/unattended-schedules.d.ts +15 -0
  176. package/dist/mcp/unattended-schedules.js +21 -0
  177. package/dist/mcp/webhooks/ingress.d.ts +17 -0
  178. package/dist/mcp/webhooks/ingress.js +33 -0
  179. package/dist/observability/config.d.ts +6 -0
  180. package/dist/observability/config.js +20 -0
  181. package/dist/observability/metrics-server.d.ts +11 -0
  182. package/dist/observability/metrics-server.js +47 -0
  183. package/dist/observability/metrics.d.ts +36 -0
  184. package/dist/observability/metrics.js +158 -0
  185. package/dist/providers/auth/authorization-server.d.ts +41 -0
  186. package/dist/providers/auth/authorization-server.js +1 -0
  187. package/dist/providers/auth/delegating.d.ts +44 -0
  188. package/dist/providers/auth/delegating.js +105 -0
  189. package/dist/providers/auth/index.d.ts +11 -0
  190. package/dist/providers/auth/index.js +20 -0
  191. package/dist/providers/auth/release-gate.d.ts +1 -0
  192. package/dist/providers/auth/release-gate.js +4 -0
  193. package/dist/providers/auth/self-hosted.d.ts +78 -0
  194. package/dist/providers/auth/self-hosted.js +377 -0
  195. package/dist/providers/auth/subject.d.ts +1 -0
  196. package/dist/providers/auth/subject.js +6 -0
  197. package/dist/providers/auth/types.d.ts +63 -0
  198. package/dist/providers/auth/types.js +22 -0
  199. package/dist/providers/coding-proxy/deny-port.d.ts +5 -0
  200. package/dist/providers/coding-proxy/deny-port.js +45 -0
  201. package/dist/providers/coding-proxy/environment-credentials.d.ts +7 -0
  202. package/dist/providers/coding-proxy/environment-credentials.js +16 -0
  203. package/dist/providers/coding-proxy/index.d.ts +7 -0
  204. package/dist/providers/coding-proxy/index.js +7 -0
  205. package/dist/providers/coding-proxy/memory-ledger.d.ts +17 -0
  206. package/dist/providers/coding-proxy/memory-ledger.js +103 -0
  207. package/dist/providers/coding-proxy/metering.d.ts +20 -0
  208. package/dist/providers/coding-proxy/metering.js +161 -0
  209. package/dist/providers/coding-proxy/prisma-ledger.d.ts +15 -0
  210. package/dist/providers/coding-proxy/prisma-ledger.js +213 -0
  211. package/dist/providers/coding-proxy/proxy.d.ts +75 -0
  212. package/dist/providers/coding-proxy/proxy.js +721 -0
  213. package/dist/providers/coding-proxy/runtime.d.ts +18 -0
  214. package/dist/providers/coding-proxy/runtime.js +39 -0
  215. package/dist/providers/coding-proxy/secure-fetch.d.ts +9 -0
  216. package/dist/providers/coding-proxy/secure-fetch.js +72 -0
  217. package/dist/providers/coding-proxy/server.d.ts +17 -0
  218. package/dist/providers/coding-proxy/server.js +139 -0
  219. package/dist/providers/coding-proxy/types.d.ts +99 -0
  220. package/dist/providers/coding-proxy/types.js +1 -0
  221. package/dist/providers/datastore/index.d.ts +2 -0
  222. package/dist/providers/datastore/index.js +2 -0
  223. package/dist/providers/datastore/postgres.d.ts +20 -0
  224. package/dist/providers/datastore/postgres.js +130 -0
  225. package/dist/providers/datastore/scoped.d.ts +10 -0
  226. package/dist/providers/datastore/scoped.js +46 -0
  227. package/dist/providers/datastore/types.d.ts +31 -0
  228. package/dist/providers/datastore/types.js +7 -0
  229. package/dist/providers/email/types.d.ts +46 -0
  230. package/dist/providers/email/types.js +8 -0
  231. package/dist/providers/engine/index.d.ts +1 -0
  232. package/dist/providers/engine/index.js +1 -0
  233. package/dist/providers/engine/types.d.ts +67 -0
  234. package/dist/providers/engine/types.js +16 -0
  235. package/dist/providers/executor/build.d.ts +6 -0
  236. package/dist/providers/executor/build.js +15 -0
  237. package/dist/providers/executor/composition.d.ts +14 -0
  238. package/dist/providers/executor/composition.js +123 -0
  239. package/dist/providers/executor/container.d.ts +184 -0
  240. package/dist/providers/executor/container.js +936 -0
  241. package/dist/providers/executor/dbos-status.d.ts +50 -0
  242. package/dist/providers/executor/dbos-status.js +64 -0
  243. package/dist/providers/executor/dbos.d.ts +53 -0
  244. package/dist/providers/executor/dbos.js +269 -0
  245. package/dist/providers/executor/in-process.d.ts +18 -0
  246. package/dist/providers/executor/in-process.js +38 -0
  247. package/dist/providers/executor/index.d.ts +8 -0
  248. package/dist/providers/executor/index.js +8 -0
  249. package/dist/providers/executor/routing.d.ts +48 -0
  250. package/dist/providers/executor/routing.js +70 -0
  251. package/dist/providers/executor/types.d.ts +55 -0
  252. package/dist/providers/executor/types.js +1 -0
  253. package/dist/providers/index.d.ts +43 -0
  254. package/dist/providers/index.js +18 -0
  255. package/dist/providers/jobs/docker-isolation.d.ts +166 -0
  256. package/dist/providers/jobs/docker-isolation.js +724 -0
  257. package/dist/providers/jobs/docker.d.ts +127 -0
  258. package/dist/providers/jobs/docker.js +1027 -0
  259. package/dist/providers/jobs/fake-kubernetes-api.d.ts +98 -0
  260. package/dist/providers/jobs/fake-kubernetes-api.js +142 -0
  261. package/dist/providers/jobs/fake.d.ts +23 -0
  262. package/dist/providers/jobs/fake.js +132 -0
  263. package/dist/providers/jobs/kubernetes-api.d.ts +60 -0
  264. package/dist/providers/jobs/kubernetes-api.js +20 -0
  265. package/dist/providers/jobs/kubernetes-client.d.ts +36 -0
  266. package/dist/providers/jobs/kubernetes-client.js +171 -0
  267. package/dist/providers/jobs/kubernetes-dry-run-fixture.d.ts +49 -0
  268. package/dist/providers/jobs/kubernetes-dry-run-fixture.js +141 -0
  269. package/dist/providers/jobs/kubernetes-isolation.d.ts +147 -0
  270. package/dist/providers/jobs/kubernetes-isolation.js +607 -0
  271. package/dist/providers/jobs/kubernetes-platform.d.ts +177 -0
  272. package/dist/providers/jobs/kubernetes-platform.js +280 -0
  273. package/dist/providers/jobs/kubernetes-preflight.d.ts +59 -0
  274. package/dist/providers/jobs/kubernetes-preflight.js +339 -0
  275. package/dist/providers/jobs/kubernetes-witness.d.ts +10 -0
  276. package/dist/providers/jobs/kubernetes-witness.js +193 -0
  277. package/dist/providers/jobs/kubernetes.d.ts +127 -0
  278. package/dist/providers/jobs/kubernetes.js +874 -0
  279. package/dist/providers/jobs/safe-extract.d.ts +9 -0
  280. package/dist/providers/jobs/safe-extract.js +325 -0
  281. package/dist/providers/jobs/types.d.ts +78 -0
  282. package/dist/providers/jobs/types.js +6 -0
  283. package/dist/providers/jobs/workspace-swap.d.ts +2 -0
  284. package/dist/providers/jobs/workspace-swap.js +47 -0
  285. package/dist/providers/llm/anthropic.d.ts +13 -0
  286. package/dist/providers/llm/anthropic.js +21 -0
  287. package/dist/providers/llm/bedrock.d.ts +19 -0
  288. package/dist/providers/llm/bedrock.js +33 -0
  289. package/dist/providers/llm/claude-messages.d.ts +106 -0
  290. package/dist/providers/llm/claude-messages.js +157 -0
  291. package/dist/providers/llm/claude-provider.d.ts +40 -0
  292. package/dist/providers/llm/claude-provider.js +31 -0
  293. package/dist/providers/llm/index.d.ts +10 -0
  294. package/dist/providers/llm/index.js +10 -0
  295. package/dist/providers/llm/openai.d.ts +23 -0
  296. package/dist/providers/llm/openai.js +156 -0
  297. package/dist/providers/llm/pricing-anthropic.d.ts +4 -0
  298. package/dist/providers/llm/pricing-anthropic.js +30 -0
  299. package/dist/providers/llm/pricing-bedrock-claude.d.ts +12 -0
  300. package/dist/providers/llm/pricing-bedrock-claude.js +37 -0
  301. package/dist/providers/llm/pricing-core.d.ts +26 -0
  302. package/dist/providers/llm/pricing-core.js +17 -0
  303. package/dist/providers/llm/pricing.d.ts +30 -0
  304. package/dist/providers/llm/pricing.js +74 -0
  305. package/dist/providers/llm/registration.d.ts +8 -0
  306. package/dist/providers/llm/registration.js +39 -0
  307. package/dist/providers/llm/routing.d.ts +25 -0
  308. package/dist/providers/llm/routing.js +32 -0
  309. package/dist/providers/llm/types.d.ts +85 -0
  310. package/dist/providers/llm/types.js +12 -0
  311. package/dist/providers/memory/index.d.ts +2 -0
  312. package/dist/providers/memory/index.js +2 -0
  313. package/dist/providers/memory/postgres.d.ts +20 -0
  314. package/dist/providers/memory/postgres.js +72 -0
  315. package/dist/providers/memory/types.d.ts +32 -0
  316. package/dist/providers/memory/types.js +17 -0
  317. package/dist/providers/secrets/app-key.d.ts +8 -0
  318. package/dist/providers/secrets/app-key.js +50 -0
  319. package/dist/providers/secrets/index.d.ts +10 -0
  320. package/dist/providers/secrets/index.js +13 -0
  321. package/dist/providers/secrets/transfer-envelope.d.ts +12 -0
  322. package/dist/providers/secrets/transfer-envelope.js +35 -0
  323. package/dist/providers/secrets/types.d.ts +18 -0
  324. package/dist/providers/secrets/types.js +12 -0
  325. package/dist/providers/storage/types.d.ts +18 -0
  326. package/dist/providers/storage/types.js +7 -0
  327. package/dist/providers/vcs/git.d.ts +105 -0
  328. package/dist/providers/vcs/git.js +710 -0
  329. package/dist/providers/vcs/github.d.ts +105 -0
  330. package/dist/providers/vcs/github.js +394 -0
  331. package/dist/providers/vcs/index.d.ts +6 -0
  332. package/dist/providers/vcs/index.js +26 -0
  333. package/dist/providers/vcs/types.d.ts +118 -0
  334. package/dist/providers/vcs/types.js +1 -0
  335. package/dist/sandbox/bounded-json.d.ts +2 -0
  336. package/dist/sandbox/bounded-json.js +36 -0
  337. package/dist/sandbox/bridge.d.ts +15 -0
  338. package/dist/sandbox/bridge.js +78 -0
  339. package/dist/sandbox/eval-core.d.ts +37 -0
  340. package/dist/sandbox/eval-core.js +159 -0
  341. package/dist/sandbox/fetch-policy.d.ts +24 -0
  342. package/dist/sandbox/fetch-policy.js +96 -0
  343. package/dist/sandbox/generated/zod-to-json-schema.bundle.js +5 -0
  344. package/dist/sandbox/generated/zod.bundle.js +1 -0
  345. package/dist/sandbox/host-functions.d.ts +29 -0
  346. package/dist/sandbox/host-functions.js +168 -0
  347. package/dist/sandbox/limits.d.ts +39 -0
  348. package/dist/sandbox/limits.js +39 -0
  349. package/dist/sandbox/parser-worker/__fixtures__/crash.d.ts +1 -0
  350. package/dist/sandbox/parser-worker/__fixtures__/crash.js +6 -0
  351. package/dist/sandbox/parser-worker/__fixtures__/echo.d.ts +1 -0
  352. package/dist/sandbox/parser-worker/__fixtures__/echo.js +5 -0
  353. package/dist/sandbox/parser-worker/__fixtures__/reject.d.ts +1 -0
  354. package/dist/sandbox/parser-worker/__fixtures__/reject.js +5 -0
  355. package/dist/sandbox/parser-worker/__fixtures__/spin-forever.d.ts +1 -0
  356. package/dist/sandbox/parser-worker/__fixtures__/spin-forever.js +11 -0
  357. package/dist/sandbox/parser-worker/pool.d.ts +13 -0
  358. package/dist/sandbox/parser-worker/pool.js +111 -0
  359. package/dist/sandbox/parser-worker/worker.d.ts +14 -0
  360. package/dist/sandbox/parser-worker/worker.js +63 -0
  361. package/dist/sandbox/pii-redaction.d.ts +1 -0
  362. package/dist/sandbox/pii-redaction.js +29 -0
  363. package/dist/sandbox/prelude.d.ts +26 -0
  364. package/dist/sandbox/prelude.js +408 -0
  365. package/dist/sandbox/quickjs-module.d.ts +13 -0
  366. package/dist/sandbox/quickjs-module.js +19 -0
  367. package/dist/sandbox/run-in-sandbox.d.ts +34 -0
  368. package/dist/sandbox/run-in-sandbox.js +53 -0
  369. package/dist/sandbox/safe-fetch.d.ts +26 -0
  370. package/dist/sandbox/safe-fetch.js +140 -0
  371. package/dist/sandbox/tool-capabilities.d.ts +66 -0
  372. package/dist/sandbox/tool-capabilities.js +103 -0
  373. package/dist/sandbox/zod-params.d.ts +22 -0
  374. package/dist/sandbox/zod-params.js +60 -0
  375. package/dist/serve.d.ts +14 -0
  376. package/dist/serve.js +54 -0
  377. package/dist/wardby-bin.d.ts +2 -0
  378. package/dist/wardby-bin.js +20 -0
  379. package/package.json +123 -0
  380. package/prisma/migrations/20260905000000_init/migration.sql +34 -0
  381. package/prisma/migrations/20260905010000_scheduler_durability/migration.sql +31 -0
  382. package/prisma/migrations/20260905020000_tools_multiturn/migration.sql +47 -0
  383. package/prisma/migrations/20260905030000_cache_tool_json_schema/migration.sql +13 -0
  384. package/prisma/migrations/20260906000000_mcp_phase4/migration.sql +115 -0
  385. package/prisma/migrations/20260906010000_run_final_text/migration.sql +7 -0
  386. package/prisma/migrations/20260906020000_run_turns/migration.sql +6 -0
  387. package/prisma/migrations/20260906030000_task_principal_id/migration.sql +5 -0
  388. package/prisma/migrations/20260906040000_secure_self_hosted_oauth/migration.sql +67 -0
  389. package/prisma/migrations/20260906050000_phase5_coding_agents/migration.sql +52 -0
  390. package/prisma/migrations/20260906060000_tool_capability_scoping/migration.sql +22 -0
  391. package/prisma/migrations/20260906070000_datastore_pii_flag/migration.sql +6 -0
  392. package/prisma/migrations/20260906080000_secret_elicitation_outcomes/migration.sql +13 -0
  393. package/prisma/migrations/20260907010000_coding_proxy_ledger/migration.sql +57 -0
  394. package/prisma/migrations/20260907020000_budget_groups/migration.sql +24 -0
  395. package/prisma/migrations/20260907030000_coding_webhook_task_override/migration.sql +4 -0
  396. package/prisma/migrations/20260908010000_run_execution_backend/migration.sql +2 -0
  397. package/prisma/migrations/20260908020000_coding_run_audit_metadata/migration.sql +7 -0
  398. package/prisma/migrations/20260910010000_agent_secret_bound_name/migration.sql +16 -0
  399. package/prisma/migrations/20260911010000_coding_worker_toolchains/migration.sql +5 -0
  400. package/prisma/migrations/20260912010000_coding_provider_contract/migration.sql +24 -0
  401. package/prisma/migrations/20260912020000_coding_proxy_protocol/migration.sql +10 -0
  402. package/prisma/migrations/20260912030000_agent_memory/migration.sql +18 -0
  403. package/prisma/migrations/20260912040000_named_shared_datastores/migration.sql +68 -0
  404. package/prisma/migrations/20260913000000_run_trigger_webhook/migration.sql +2 -0
  405. package/prisma/migrations/20260913010000_agent_sub_agent/migration.sql +32 -0
  406. package/prisma/migrations/20260913020000_run_task_override/migration.sql +5 -0
  407. package/prisma/migrations/20260913030000_coding_run_root/migration.sql +11 -0
  408. package/prisma/migrations/20260922010000_coding_run_queued_at/migration.sql +8 -0
  409. package/prisma/migrations/20260922020000_coding_workspace_disk/migration.sql +8 -0
  410. package/prisma/migrations/migration_lock.toml +3 -0
  411. package/prisma/schema.prisma +723 -0
  412. package/scripts/git-askpass.sh +11 -0
@@ -0,0 +1,61 @@
1
+ import { readFileSync, statSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { z } from "zod";
4
+ import { ManifestSchema, NeutralAgentSchema, NeutralToolSchema, NeutralAgentToolSchema, NeutralSecretSchema, NeutralAgentSecretSchema, NeutralSingleDatastoreSchema, NeutralSharedDatastoreSchema, NeutralWebhookSchema, NeutralBudgetSchema, } from "./neutral-schema.js";
5
+ export class BundleError extends Error {
6
+ }
7
+ function readArray(dir, rel, schema) {
8
+ const p = join(dir, rel);
9
+ if (!existsSync(p))
10
+ return [];
11
+ let raw;
12
+ try {
13
+ raw = JSON.parse(readFileSync(p, "utf8"));
14
+ }
15
+ catch (e) {
16
+ throw new BundleError(`${rel}: invalid JSON (${e.message})`);
17
+ }
18
+ const parsed = z.array(schema).safeParse(raw);
19
+ if (!parsed.success)
20
+ throw new BundleError(`${rel}: ${parsed.error.issues[0]?.message ?? "schema mismatch"}`);
21
+ return parsed.data;
22
+ }
23
+ export function openBundle(dir) {
24
+ let st;
25
+ try {
26
+ st = statSync(dir);
27
+ }
28
+ catch {
29
+ throw new BundleError(`no such bundle directory: ${dir}`);
30
+ }
31
+ if (!st.isDirectory())
32
+ throw new BundleError(`bundle path is not a directory (extract the .zip first): ${dir}`);
33
+ const manifestPath = join(dir, "manifest.json");
34
+ if (!existsSync(manifestPath))
35
+ throw new BundleError("manifest.json not found in bundle");
36
+ let raw;
37
+ try {
38
+ raw = JSON.parse(readFileSync(manifestPath, "utf8"));
39
+ }
40
+ catch (e) {
41
+ throw new BundleError(`manifest.json: invalid JSON (${e.message})`);
42
+ }
43
+ const parsed = ManifestSchema.safeParse(raw);
44
+ if (!parsed.success)
45
+ throw new BundleError(`manifest.json: ${parsed.error.issues[0]?.message ?? "invalid"}`);
46
+ const manifest = parsed.data;
47
+ if (manifest.bundleVersion !== 1)
48
+ throw new BundleError(`unsupported bundleVersion ${manifest.bundleVersion}`);
49
+ return {
50
+ manifest,
51
+ readAgents: () => readArray(dir, "config/agents.json", NeutralAgentSchema),
52
+ readTools: () => readArray(dir, "config/tools.json", NeutralToolSchema),
53
+ readAgentTools: () => readArray(dir, "config/agent-tools.json", NeutralAgentToolSchema),
54
+ readSecrets: () => readArray(dir, "config/secrets.json", NeutralSecretSchema),
55
+ readAgentSecrets: () => readArray(dir, "config/agent-secrets.json", NeutralAgentSecretSchema),
56
+ readSingleDatastores: () => readArray(dir, "config/datastores-single.json", NeutralSingleDatastoreSchema),
57
+ readSharedDatastores: () => readArray(dir, "config/datastores-shared.json", NeutralSharedDatastoreSchema),
58
+ readWebhooks: () => readArray(dir, "config/webhooks.json", NeutralWebhookSchema),
59
+ readBudgets: () => readArray(dir, "capabilities/budgets.json", NeutralBudgetSchema),
60
+ };
61
+ }
@@ -0,0 +1,2 @@
1
+ import type { ImportOptions } from "./index.js";
2
+ export declare function parseImportArgs(args: string[]): Omit<ImportOptions, "db" | "env">;
@@ -0,0 +1,44 @@
1
+ import { parseArgs } from "node:util";
2
+ const VALID_CONFLICT_POLICIES = ["fail", "skip", "rename"];
3
+ export function parseImportArgs(args) {
4
+ const { values, positionals } = parseArgs({
5
+ args,
6
+ allowPositionals: true,
7
+ options: {
8
+ owner: { type: "string" },
9
+ public: { type: "boolean" },
10
+ "include-secrets": { type: "boolean" },
11
+ "transfer-key": { type: "string" },
12
+ "default-budget": { type: "string" },
13
+ "dry-run": { type: "boolean" },
14
+ prefix: { type: "string" },
15
+ "on-conflict": { type: "string" },
16
+ "allow-open-fetch": { type: "boolean" },
17
+ },
18
+ });
19
+ // Require one positional: the bundle directory
20
+ if (positionals.length === 0) {
21
+ throw new Error("Missing bundle directory positional argument");
22
+ }
23
+ const dir = positionals[0];
24
+ // Parse owner/public
25
+ const isPublic = values.public ?? false;
26
+ const owner = isPublic ? null : (values.owner ?? null);
27
+ // Validate on-conflict
28
+ const onConflict = (values["on-conflict"] ?? "fail");
29
+ if (!VALID_CONFLICT_POLICIES.includes(onConflict)) {
30
+ throw new Error(`Invalid --on-conflict value "${onConflict}". Must be one of: ${VALID_CONFLICT_POLICIES.join(", ")}`);
31
+ }
32
+ return {
33
+ dir,
34
+ owner,
35
+ isPublic,
36
+ includeSecrets: values["include-secrets"] ?? false,
37
+ transferKeyPath: values["transfer-key"],
38
+ defaultBudget: values["default-budget"],
39
+ dryRun: values["dry-run"] ?? false,
40
+ prefix: values.prefix ?? "imported-",
41
+ onConflict,
42
+ allowOpenFetch: values["allow-open-fetch"] ?? false,
43
+ };
44
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Ordered idempotent create step — writes Tier-1 entities (tools, agents,
3
+ * attachments, secrets, datastores, webhooks, budget groups) to the database
4
+ * from a validated bundle + reconciliation.
5
+ */
6
+ import type { PrismaClient } from "@prisma/client";
7
+ import type { KeyObject } from "node:crypto";
8
+ import type { Bundle } from "./bundle.js";
9
+ import type { Reconciliation } from "./preflight.js";
10
+ import type { SecretCipher } from "../providers/secrets/types.js";
11
+ export interface CreateOptions {
12
+ db: PrismaClient;
13
+ cipher: SecretCipher;
14
+ ownerId: string | null;
15
+ defaultBudget: string;
16
+ secretMode: "references" | "envelope";
17
+ transferPrivateKey?: KeyObject;
18
+ allowOpenFetch: boolean;
19
+ }
20
+ export interface ImportResult {
21
+ agentsCreated: number;
22
+ toolsCreated: number;
23
+ secretsCreated: number;
24
+ datastoreEntries: number;
25
+ datastoresSharedCreated: number;
26
+ budgetGroupsCreated: number;
27
+ webhookSecrets: {
28
+ agentName: string;
29
+ secret: string;
30
+ }[];
31
+ pendingSecretReentry: string[];
32
+ warnings: string[];
33
+ }
34
+ export declare function createFromBundle(bundle: Bundle, recon: Reconciliation, opts: CreateOptions): Promise<ImportResult>;
@@ -0,0 +1,363 @@
1
+ /**
2
+ * Ordered idempotent create step — writes Tier-1 entities (tools, agents,
3
+ * attachments, secrets, datastores, webhooks, budget groups) to the database
4
+ * from a validated bundle + reconciliation.
5
+ */
6
+ import { Prisma } from "@prisma/client";
7
+ import { createSecret, attachSecret } from "../core/secrets.js";
8
+ import { createDatastore, attachDatastore } from "../core/datastores.js";
9
+ import { createWebhook } from "../core/webhooks.js";
10
+ import { deriveJsonSchema } from "../sandbox/zod-params.js";
11
+ import { ToolCapabilitiesPatchSchema, FETCH_WILDCARD } from "../sandbox/tool-capabilities.js";
12
+ import { PostgresDatastore } from "../providers/datastore/postgres.js";
13
+ import { decryptTransferEnvelope } from "../providers/secrets/transfer-envelope.js";
14
+ import { mapBudget } from "./budgets.js";
15
+ export async function createFromBundle(bundle, recon, opts) {
16
+ const { db, cipher, ownerId, secretMode, transferPrivateKey, allowOpenFetch } = opts;
17
+ const warnings = [];
18
+ const webhookSecrets = [];
19
+ const pendingSecretReentry = [];
20
+ const hasOwner = ownerId !== null;
21
+ // Helper: apply nameRemap
22
+ const eff = (name) => recon.nameRemap.get(name) ?? name;
23
+ // Helper: check if agent/tool was skipped/rejected
24
+ const agentSkipped = (name) => recon.agents.find((a) => a.name === name)?.skipped;
25
+ const agentDisabled = (name) => recon.agents.find((a) => a.name === name)?.disabled ?? false;
26
+ const toolRejected = (name) => recon.tools.find((t) => t.name === name)?.rejected;
27
+ const toolSkipped = (name) => recon.tools.find((t) => t.name === name)?.skipped;
28
+ // Track created entities
29
+ let toolsCreated = 0;
30
+ let agentsCreated = 0;
31
+ let secretsCreated = 0;
32
+ let datastoreEntries = 0;
33
+ let datastoresSharedCreated = 0;
34
+ let budgetGroupsCreated = 0;
35
+ // Step 1: Tools
36
+ const toolIdMap = new Map();
37
+ for (const t of bundle.readTools()) {
38
+ if (toolRejected(t.name) || toolSkipped(t.name))
39
+ continue;
40
+ const schema = await deriveJsonSchema(t.paramsZod);
41
+ if (!schema.ok) {
42
+ warnings.push(`tool ${t.name}: failed to derive JSON schema, skipping`);
43
+ continue;
44
+ }
45
+ const tool = await db.tool.upsert({
46
+ where: { name: eff(t.name) },
47
+ create: {
48
+ name: eff(t.name),
49
+ description: t.description,
50
+ paramsZod: t.paramsZod,
51
+ code: t.code,
52
+ jsonSchema: schema.value,
53
+ ownerId,
54
+ },
55
+ update: {},
56
+ });
57
+ toolIdMap.set(t.name, tool.id);
58
+ toolsCreated++;
59
+ }
60
+ // Step 2: Agents
61
+ const agentIdMap = new Map();
62
+ for (const a of bundle.readAgents()) {
63
+ if (agentSkipped(a.name))
64
+ continue;
65
+ const scheduleEnabled = agentDisabled(a.name) ? false : a.scheduleEnabled;
66
+ const agent = await db.agent.upsert({
67
+ where: { name: eff(a.name) },
68
+ create: {
69
+ name: eff(a.name),
70
+ model: a.model,
71
+ systemPrompt: a.systemPrompt,
72
+ budgetUsd: opts.defaultBudget,
73
+ schedule: a.schedule || null,
74
+ timezone: a.timezone,
75
+ maxTurns: a.maxTurns,
76
+ scheduleEnabled,
77
+ ownerId,
78
+ },
79
+ update: {},
80
+ });
81
+ agentIdMap.set(a.name, agent.id);
82
+ agentsCreated++;
83
+ }
84
+ // Step 3: Attach tools
85
+ for (const at of bundle.readAgentTools()) {
86
+ const agentId = agentIdMap.get(at.agentName);
87
+ const toolId = toolIdMap.get(at.toolName);
88
+ if (!agentId || !toolId) {
89
+ const missing = !agentId ? `agent ${at.agentName}` : `tool ${at.toolName}`;
90
+ warnings.push(`agent-tool ${at.agentName}/${at.toolName}: skipped — ${missing} was not imported`);
91
+ continue;
92
+ }
93
+ // Validate capabilities (drop "*" unless allowOpenFetch)
94
+ let allowedHosts = at.allowedHosts;
95
+ if (!allowOpenFetch) {
96
+ allowedHosts = allowedHosts.filter((h) => h !== FETCH_WILDCARD);
97
+ }
98
+ const capsPatch = ToolCapabilitiesPatchSchema.safeParse({
99
+ allowedSecrets: at.allowedSecrets,
100
+ allowedDatastorePrefixes: at.allowedDatastorePrefixes,
101
+ allowedHosts,
102
+ allowedSharedDatastorePrefixes: at.allowedSharedDatastorePrefixes,
103
+ });
104
+ if (!capsPatch.success) {
105
+ warnings.push(`agent-tool ${at.agentName}/${at.toolName}: invalid capabilities, skipping attachment`);
106
+ continue;
107
+ }
108
+ const caps = capsPatch.data;
109
+ await db.agentTool.upsert({
110
+ where: { agentId_toolId: { agentId, toolId } },
111
+ create: {
112
+ agentId,
113
+ toolId,
114
+ allowedSecrets: caps.allowedSecrets ?? [],
115
+ allowedDatastorePrefixes: caps.allowedDatastorePrefixes ?? [],
116
+ allowedHosts: caps.allowedHosts ?? [],
117
+ allowedSharedDatastorePrefixes: caps.allowedSharedDatastorePrefixes ?? {},
118
+ },
119
+ update: {
120
+ allowedSecrets: caps.allowedSecrets ?? [],
121
+ allowedDatastorePrefixes: caps.allowedDatastorePrefixes ?? [],
122
+ allowedHosts: caps.allowedHosts ?? [],
123
+ allowedSharedDatastorePrefixes: caps.allowedSharedDatastorePrefixes ?? {},
124
+ },
125
+ });
126
+ }
127
+ // Step 4: Secrets — one row per base secret, under its canonical name.
128
+ if (secretMode === "envelope") {
129
+ if (!hasOwner) {
130
+ for (const s of bundle.readSecrets()) {
131
+ warnings.push(`secret ${s.name}: skipped — secrets require an owner (public import)`);
132
+ }
133
+ }
134
+ else if (!transferPrivateKey) {
135
+ warnings.push("envelope mode requires transferPrivateKey, skipping secrets");
136
+ }
137
+ else {
138
+ const owner = ownerId; // hasOwner guarantees non-null
139
+ for (const s of bundle.readSecrets()) {
140
+ if (!s.ciphertext) {
141
+ warnings.push(`secret ${s.name}: no ciphertext in envelope mode, skipping`);
142
+ continue;
143
+ }
144
+ let plaintext;
145
+ try {
146
+ // AAD is ALWAYS the base secret name (s.name), never an alias.
147
+ plaintext = decryptTransferEnvelope(s.ciphertext, s.name, transferPrivateKey);
148
+ }
149
+ catch (err) {
150
+ warnings.push(`secret ${s.name}: failed to decrypt (${err instanceof Error ? err.message : String(err)})`);
151
+ continue;
152
+ }
153
+ try {
154
+ await createSecret(s.name, plaintext, owner, cipher, db);
155
+ secretsCreated++; // one per distinct base secret (fixes F1 over-count)
156
+ }
157
+ catch (err) {
158
+ warnings.push(`secret ${s.name}: failed to create (${err instanceof Error ? err.message : String(err)})`);
159
+ }
160
+ }
161
+ }
162
+ }
163
+ else {
164
+ for (const s of bundle.readSecrets()) {
165
+ pendingSecretReentry.push(s.name);
166
+ }
167
+ }
168
+ // Step 5: Attach secrets (envelope mode only)
169
+ if (secretMode === "envelope" && hasOwner) {
170
+ const owner = ownerId;
171
+ for (const as of bundle.readAgentSecrets()) {
172
+ const agentId = agentIdMap.get(as.agentName);
173
+ if (!agentId)
174
+ continue;
175
+ const boundName = as.alias ?? as.secretName;
176
+ try {
177
+ await attachSecret(agentId, as.secretName, owner, db, boundName);
178
+ }
179
+ catch (err) {
180
+ if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === "P2002") {
181
+ // Either an idempotent re-run, or two secrets bound to the same
182
+ // point-of-use name for one agent (a bundle inconsistency). Surface it.
183
+ warnings.push(`agent-secret ${as.agentName}: "${boundName}" already bound — skipped (re-run or duplicate binding)`);
184
+ continue;
185
+ }
186
+ warnings.push(`agent-secret ${as.agentName}/${as.secretName}: failed to attach (${err instanceof Error ? err.message : String(err)})`);
187
+ }
188
+ }
189
+ }
190
+ // Step 6: Per-agent datastore seed
191
+ const ds = new PostgresDatastore(db, cipher);
192
+ for (const d of bundle.readSingleDatastores()) {
193
+ const agentId = agentIdMap.get(d.agentName);
194
+ if (!agentId)
195
+ continue;
196
+ for (const entry of d.entries) {
197
+ try {
198
+ await ds.set(agentId, entry.key, entry.value, { pii: entry.pii });
199
+ datastoreEntries++;
200
+ }
201
+ catch (err) {
202
+ warnings.push(`datastore ${d.agentName}/${entry.key}: failed to set (${err instanceof Error ? err.message : String(err)})`);
203
+ }
204
+ }
205
+ }
206
+ // Step 6.5: Shared datastores — require an owner, same rule as
207
+ // secrets/webhooks/budgets: skip with a warning in public-import mode.
208
+ if (!hasOwner) {
209
+ for (const sd of bundle.readSharedDatastores()) {
210
+ warnings.push(`shared-datastore ${sd.name}: skipped — shared datastores require an owner (public import)`);
211
+ }
212
+ }
213
+ else {
214
+ const owner = ownerId; // hasOwner guarantees non-null
215
+ for (const sd of bundle.readSharedDatastores()) {
216
+ let created;
217
+ try {
218
+ created = await createDatastore(sd.name, owner, db);
219
+ }
220
+ catch (err) {
221
+ if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === "P2002") {
222
+ // Two shared-datastore definitions in this bundle collide on
223
+ // (ownerId, name) — createDatastore isn't idempotent (Task 3).
224
+ // Surface it and move on rather than aborting the whole import.
225
+ warnings.push(`shared-datastore ${sd.name}: a datastore with this name already exists for this owner — skipped`);
226
+ continue;
227
+ }
228
+ warnings.push(`shared-datastore ${sd.name}: failed to create (${err instanceof Error ? err.message : String(err)})`);
229
+ continue;
230
+ }
231
+ datastoresSharedCreated++;
232
+ for (const entry of sd.entries) {
233
+ try {
234
+ await db.datastoreEntry.create({
235
+ data: { datastoreId: created.id, key: entry.key, value: entry.value, pii: false },
236
+ });
237
+ }
238
+ catch (err) {
239
+ warnings.push(`shared-datastore ${sd.name}/${entry.key}: failed to seed (${err instanceof Error ? err.message : String(err)})`);
240
+ }
241
+ }
242
+ for (const agentName of sd.attachedAgentNames) {
243
+ const agentId = agentIdMap.get(agentName);
244
+ if (!agentId)
245
+ continue;
246
+ try {
247
+ await attachDatastore(agentId, created.id, db, sd.name);
248
+ }
249
+ catch (err) {
250
+ if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === "P2002") {
251
+ warnings.push(`shared-datastore ${sd.name}: agent ${agentName} already binds "${sd.name}" — skipped`);
252
+ continue;
253
+ }
254
+ warnings.push(`shared-datastore ${sd.name}/${agentName}: failed to attach (${err instanceof Error ? err.message : String(err)})`);
255
+ }
256
+ }
257
+ }
258
+ }
259
+ // Step 7: Webhooks
260
+ if (!hasOwner) {
261
+ // Webhooks require an owner - skip in public import mode
262
+ for (const w of bundle.readWebhooks()) {
263
+ warnings.push(`webhook for agent ${w.agentName}: skipped — webhooks require an owner (public import)`);
264
+ }
265
+ }
266
+ else {
267
+ const owner = ownerId; // TypeScript narrowing: hasOwner guarantees non-null
268
+ for (const w of bundle.readWebhooks()) {
269
+ const agentId = agentIdMap.get(w.agentName);
270
+ if (!agentId)
271
+ continue;
272
+ try {
273
+ // Check if webhook already exists (idempotency)
274
+ const existing = await db.webhook.findFirst({ where: { agentId } });
275
+ if (existing)
276
+ continue;
277
+ const { id, secret } = await createWebhook(agentId, owner, db);
278
+ webhookSecrets.push({ agentName: w.agentName, secret });
279
+ if (!w.enabled) {
280
+ await db.webhook.update({
281
+ where: { id },
282
+ data: { status: "disabled" },
283
+ });
284
+ }
285
+ }
286
+ catch (err) {
287
+ warnings.push(`webhook ${w.agentName}: failed to create (${err instanceof Error ? err.message : String(err)})`);
288
+ }
289
+ }
290
+ }
291
+ // Step 8: Budget groups
292
+ if (!hasOwner) {
293
+ // Budget groups require an owner - skip in public import mode
294
+ for (const b of bundle.readBudgets()) {
295
+ const mapped = mapBudget(b);
296
+ if (mapped.ok) {
297
+ warnings.push(`budget group ${mapped.group.name}: skipped — budget groups require an owner (public import)`);
298
+ }
299
+ }
300
+ }
301
+ else {
302
+ const owner = ownerId; // TypeScript narrowing: hasOwner guarantees non-null
303
+ const budgetGroupMap = new Map(); // budget name -> groupId
304
+ const agentBudgetAssignments = new Map(); // agent name -> first budget that claimed it
305
+ for (const b of bundle.readBudgets()) {
306
+ const mapped = mapBudget(b);
307
+ if (!mapped.ok)
308
+ continue;
309
+ const { group, agentNames } = mapped;
310
+ try {
311
+ const bg = await db.budgetGroup.upsert({
312
+ where: { ownerId_name: { ownerId: owner, name: group.name } },
313
+ create: {
314
+ name: group.name,
315
+ ownerId: owner,
316
+ dailyBudgetUsd: group.dailyBudgetUsd,
317
+ weeklyBudgetUsd: group.weeklyBudgetUsd,
318
+ monthlyBudgetUsd: group.monthlyBudgetUsd,
319
+ warnThresholdRatio: group.warnThresholdRatio,
320
+ },
321
+ update: {},
322
+ });
323
+ budgetGroupMap.set(group.name, bg.id);
324
+ budgetGroupsCreated++;
325
+ // Attach agents (first budget wins)
326
+ for (const agentName of agentNames) {
327
+ const agentId = agentIdMap.get(agentName);
328
+ if (!agentId)
329
+ continue;
330
+ const existingBudget = agentBudgetAssignments.get(agentName);
331
+ if (existingBudget) {
332
+ warnings.push(`agent ${agentName}: already in budget group "${existingBudget}", ignoring "${group.name}"`);
333
+ continue;
334
+ }
335
+ try {
336
+ await db.agent.update({
337
+ where: { id: agentId },
338
+ data: { budgetGroupId: bg.id },
339
+ });
340
+ agentBudgetAssignments.set(agentName, group.name);
341
+ }
342
+ catch (err) {
343
+ warnings.push(`agent ${agentName}: failed to attach to budget group "${group.name}" (${err instanceof Error ? err.message : String(err)})`);
344
+ }
345
+ }
346
+ }
347
+ catch (err) {
348
+ warnings.push(`budget group ${group.name}: failed to create (${err instanceof Error ? err.message : String(err)})`);
349
+ }
350
+ }
351
+ }
352
+ return {
353
+ agentsCreated,
354
+ toolsCreated,
355
+ secretsCreated,
356
+ datastoreEntries,
357
+ datastoresSharedCreated,
358
+ budgetGroupsCreated,
359
+ webhookSecrets,
360
+ pendingSecretReentry,
361
+ warnings,
362
+ };
363
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Top-level orchestrator: opens a bundle, runs preflight reconciliation,
3
+ * renders the report, and (unless dry-run or fatal collision) creates entities.
4
+ */
5
+ import type { PrismaClient } from "@prisma/client";
6
+ import type { ConflictPolicy } from "./preflight.js";
7
+ import { type ImportResult } from "./create.js";
8
+ export interface ImportOptions {
9
+ dir: string;
10
+ owner: string | null;
11
+ isPublic: boolean;
12
+ includeSecrets: boolean;
13
+ transferKeyPath?: string;
14
+ defaultBudget?: string;
15
+ dryRun: boolean;
16
+ prefix: string;
17
+ onConflict: ConflictPolicy;
18
+ allowOpenFetch: boolean;
19
+ db: PrismaClient;
20
+ env?: NodeJS.ProcessEnv;
21
+ }
22
+ export declare function runImport(opts: ImportOptions): Promise<{
23
+ report: string;
24
+ result?: ImportResult;
25
+ }>;
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Top-level orchestrator: opens a bundle, runs preflight reconciliation,
3
+ * renders the report, and (unless dry-run or fatal collision) creates entities.
4
+ */
5
+ import { openBundle } from "./bundle.js";
6
+ import { preflight } from "./preflight.js";
7
+ import { renderReconciliation } from "./report.js";
8
+ import { createFromBundle } from "./create.js";
9
+ import { supportedGlobalsFromPrelude } from "./tool-scan.js";
10
+ import { SANDBOX_PRELUDE } from "../sandbox/prelude.js";
11
+ import { resolveLlmRegistrations } from "../providers/llm/registration.js";
12
+ import { RoutingLlmProvider } from "../providers/llm/routing.js";
13
+ import { loadProviderConfig } from "../config/providers.js";
14
+ import { buildSecretCipher } from "../providers/secrets/index.js";
15
+ import { resolvePrincipal } from "../mcp/auth/principal.js";
16
+ import { loadTransferPrivateKey, transferKeyIdOf } from "../providers/secrets/transfer-envelope.js";
17
+ import { readFileSync } from "node:fs";
18
+ export async function runImport(opts) {
19
+ const env = opts.env ?? process.env;
20
+ // Guard: owner XOR public
21
+ if (opts.owner === null && !opts.isPublic) {
22
+ throw new Error("Must specify either --owner or --public (not neither)");
23
+ }
24
+ if (opts.owner !== null && opts.isPublic) {
25
+ throw new Error("Cannot specify both --owner and --public");
26
+ }
27
+ // Open bundle
28
+ const bundle = openBundle(opts.dir);
29
+ // Determine effective secret mode: envelope only if bundle is envelope AND --include-secrets
30
+ const effectiveSecretMode = bundle.manifest.secretMode === "envelope" && opts.includeSecrets ? "envelope" : "references";
31
+ // Build routableModels from LLM registrations
32
+ const reg = resolveLlmRegistrations(env);
33
+ const routableModels = reg.kind === "registrations" ? new Set(new RoutingLlmProvider(reg.registrations).listModels()) : new Set();
34
+ // Get supportedGlobals from prelude
35
+ const supportedGlobals = supportedGlobalsFromPrelude(SANDBOX_PRELUDE);
36
+ // Load existing names from db
37
+ const existingAgents = await opts.db.agent.findMany({ select: { name: true } });
38
+ const existingAgentNames = new Set(existingAgents.map((a) => a.name));
39
+ const existingTools = await opts.db.tool.findMany({ select: { name: true } });
40
+ const existingToolNames = new Set(existingTools.map((t) => t.name));
41
+ // For owner-scoped entities (secrets, budgets), load only if we have an owner
42
+ const ownerId = opts.owner !== null && !opts.isPublic ? (await resolvePrincipal(opts.owner, opts.db)).id : null;
43
+ // Tier-1 capabilities: "budgets" and "shared-datastores" are implemented
44
+ const capabilitiesSupported = new Set(["budgets", "shared-datastores"]);
45
+ // Run preflight reconciliation
46
+ const recon = preflight({
47
+ bundle,
48
+ routableModels,
49
+ supportedGlobals,
50
+ existingAgentNames,
51
+ existingToolNames,
52
+ capabilitiesSupported,
53
+ onConflict: opts.onConflict,
54
+ prefix: opts.prefix,
55
+ allowOpenFetch: opts.allowOpenFetch,
56
+ });
57
+ // Render initial report
58
+ let report = renderReconciliation(recon, {
59
+ secretMode: bundle.manifest.secretMode,
60
+ dryRun: opts.dryRun,
61
+ });
62
+ // Early return if dry-run or fatal collision
63
+ if (recon.hasFatalCollision && !opts.dryRun) {
64
+ report +=
65
+ "\n\n*** Import aborted: a name collision was found under --on-conflict fail. No changes were written. ***";
66
+ return { report };
67
+ }
68
+ if (opts.dryRun || recon.hasFatalCollision) {
69
+ return { report };
70
+ }
71
+ // Load and verify transfer key (only when actually importing secrets from envelope)
72
+ let transferPrivateKey = undefined;
73
+ if (effectiveSecretMode === "envelope") {
74
+ if (!opts.transferKeyPath) {
75
+ throw new Error("Importing secrets from an envelope bundle requires --transfer-key");
76
+ }
77
+ const keyPem = readFileSync(opts.transferKeyPath, "utf8");
78
+ transferPrivateKey = loadTransferPrivateKey(keyPem);
79
+ const keyId = transferKeyIdOf(transferPrivateKey);
80
+ if (keyId !== bundle.manifest.transferKeyId) {
81
+ throw new Error(`Transfer key ID mismatch: key has ${keyId}, bundle manifest declares ${bundle.manifest.transferKeyId}`);
82
+ }
83
+ }
84
+ // Build secret cipher
85
+ const providerConfig = loadProviderConfig(env);
86
+ const cipher = buildSecretCipher(providerConfig, env);
87
+ // Run create
88
+ const result = await createFromBundle(bundle, recon, {
89
+ db: opts.db,
90
+ cipher,
91
+ ownerId,
92
+ defaultBudget: opts.defaultBudget ?? "10.00",
93
+ secretMode: effectiveSecretMode,
94
+ transferPrivateKey,
95
+ allowOpenFetch: opts.allowOpenFetch,
96
+ });
97
+ // Append final report sections
98
+ const finalLines = [];
99
+ finalLines.push("");
100
+ finalLines.push("--- Import Complete ---");
101
+ finalLines.push(`Agents created: ${result.agentsCreated}`);
102
+ finalLines.push(`Tools created: ${result.toolsCreated}`);
103
+ finalLines.push(`Secrets created: ${result.secretsCreated}`);
104
+ finalLines.push(`Datastore entries: ${result.datastoreEntries}`);
105
+ finalLines.push(`Shared datastores created: ${result.datastoresSharedCreated}`);
106
+ finalLines.push(`Budget groups created: ${result.budgetGroupsCreated}`);
107
+ if (result.webhookSecrets.length > 0) {
108
+ finalLines.push("");
109
+ finalLines.push("Webhook secrets (save these now, they won't be shown again):");
110
+ for (const ws of result.webhookSecrets) {
111
+ finalLines.push(` ${ws.agentName}: ${ws.secret}`);
112
+ }
113
+ }
114
+ if (result.pendingSecretReentry.length > 0) {
115
+ finalLines.push("");
116
+ finalLines.push("Pending secret re-entry (references mode):");
117
+ for (const name of result.pendingSecretReentry) {
118
+ finalLines.push(` - ${name}`);
119
+ }
120
+ }
121
+ if (result.warnings.length > 0) {
122
+ finalLines.push("");
123
+ finalLines.push("Warnings:");
124
+ for (const w of result.warnings) {
125
+ finalLines.push(` - ${w}`);
126
+ }
127
+ }
128
+ report += "\n" + finalLines.join("\n");
129
+ return { report, result };
130
+ }
@@ -0,0 +1 @@
1
+ export declare function classifyModel(model: string, routableModels: ReadonlySet<string>): "routable" | "unroutable";
@@ -0,0 +1,3 @@
1
+ export function classifyModel(model, routableModels) {
2
+ return routableModels.has(model) ? "routable" : "unroutable";
3
+ }