@wardby/cli 0.2.1 → 0.3.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 (407) hide show
  1. package/.env.example +34 -4
  2. package/README.md +41 -4
  3. package/dist/claude-coding-worker/driver.d.ts +6 -1
  4. package/dist/claude-coding-worker/driver.js +27 -1
  5. package/dist/claude-coding-worker/main.js +2 -0
  6. package/dist/claude-coding-worker/tool-socket.d.ts +9 -0
  7. package/dist/claude-coding-worker/tool-socket.js +26 -0
  8. package/dist/cli-help.d.ts +1 -1
  9. package/dist/cli-help.js +13 -4
  10. package/dist/cli.d.ts +1 -1
  11. package/dist/cli.js +219 -29
  12. package/dist/coding/collect-exclude.d.ts +25 -0
  13. package/dist/coding/collect-exclude.js +76 -0
  14. package/dist/coding/profile.d.ts +67 -22
  15. package/dist/coding/profile.js +58 -25
  16. package/dist/coding/protected-path-wording.d.ts +24 -0
  17. package/dist/coding/protected-path-wording.js +55 -0
  18. package/dist/coding/protected-paths.d.ts +31 -0
  19. package/dist/coding/protected-paths.js +48 -0
  20. package/dist/coding/protocol.d.ts +75 -4
  21. package/dist/coding/protocol.js +107 -7
  22. package/dist/coding/registry/adapters.d.ts +2 -0
  23. package/dist/coding/registry/adapters.js +9 -0
  24. package/dist/coding/registry/allowlist.d.ts +9 -0
  25. package/dist/coding/registry/allowlist.js +28 -0
  26. package/dist/coding/registry/json-scan.d.ts +55 -0
  27. package/dist/coding/registry/json-scan.js +191 -0
  28. package/dist/coding/registry/lockfiles.d.ts +6 -0
  29. package/dist/coding/registry/lockfiles.js +89 -0
  30. package/dist/coding/registry/npm-lockfile.d.ts +9 -0
  31. package/dist/coding/registry/npm-lockfile.js +73 -0
  32. package/dist/coding/registry/npm-plan.d.ts +29 -0
  33. package/dist/coding/registry/npm-plan.js +289 -0
  34. package/dist/coding/registry/npm.d.ts +7 -0
  35. package/dist/coding/registry/npm.js +252 -0
  36. package/dist/coding/registry/pypi.d.ts +4 -0
  37. package/dist/coding/registry/pypi.js +210 -0
  38. package/dist/coding/registry/report.d.ts +37 -0
  39. package/dist/coding/registry/report.js +31 -0
  40. package/dist/coding/registry/token.d.ts +4 -0
  41. package/dist/coding/registry/token.js +7 -0
  42. package/dist/coding/registry/types.d.ts +286 -0
  43. package/dist/coding/registry/types.js +19 -0
  44. package/dist/coding/registry/worker-config.d.ts +14 -0
  45. package/dist/coding/registry/worker-config.js +31 -0
  46. package/dist/coding/services/builtins.d.ts +22 -0
  47. package/dist/coding/services/builtins.js +85 -0
  48. package/dist/coding/services/catalog.d.ts +443 -0
  49. package/dist/coding/services/catalog.js +159 -0
  50. package/dist/coding/services/declaration.d.ts +11 -0
  51. package/dist/coding/services/declaration.js +114 -0
  52. package/dist/coding/services/note.d.ts +8 -0
  53. package/dist/coding/services/note.js +15 -0
  54. package/dist/coding/services/resolve.d.ts +25 -0
  55. package/dist/coding/services/resolve.js +50 -0
  56. package/dist/coding/services/wording.d.ts +25 -0
  57. package/dist/coding/services/wording.js +70 -0
  58. package/dist/coding-proxy/main.js +24 -4
  59. package/dist/coding-worker/artifact.d.ts +6 -0
  60. package/dist/coding-worker/debug-trace.d.ts +37 -0
  61. package/dist/coding-worker/debug-trace.js +117 -0
  62. package/dist/coding-worker/driver.d.ts +13 -1
  63. package/dist/coding-worker/driver.js +102 -13
  64. package/dist/coding-worker/errors.js +8 -0
  65. package/dist/coding-worker/main.js +10 -2
  66. package/dist/coding-worker/sdk.d.ts +2 -2
  67. package/dist/coding-worker/sdk.js +7 -2
  68. package/dist/coding-worker/types.d.ts +3 -0
  69. package/dist/config/providers.d.ts +41 -0
  70. package/dist/config/providers.js +66 -0
  71. package/dist/core/budget-groups.d.ts +108 -5
  72. package/dist/core/budget-groups.js +125 -19
  73. package/dist/core/budget-wording.d.ts +22 -0
  74. package/dist/core/budget-wording.js +55 -0
  75. package/dist/core/datastores.js +18 -2
  76. package/dist/core/db.d.ts +5 -1
  77. package/dist/core/db.js +8 -2
  78. package/dist/core/dispatch.d.ts +33 -6
  79. package/dist/core/dispatch.js +260 -43
  80. package/dist/core/engine-native.js +27 -10
  81. package/dist/core/grants.d.ts +86 -0
  82. package/dist/core/grants.js +126 -0
  83. package/dist/core/host-events.d.ts +49 -0
  84. package/dist/core/host-events.js +257 -0
  85. package/dist/core/host-identity-links.d.ts +54 -0
  86. package/dist/core/host-identity-links.js +189 -0
  87. package/dist/core/host-status.d.ts +61 -0
  88. package/dist/core/host-status.js +211 -0
  89. package/dist/core/in-flight-runs.d.ts +8 -0
  90. package/dist/core/in-flight-runs.js +56 -0
  91. package/dist/core/provider-wording.d.ts +12 -0
  92. package/dist/core/provider-wording.js +44 -0
  93. package/dist/core/reconciler.d.ts +38 -2
  94. package/dist/core/reconciler.js +86 -2
  95. package/dist/core/repo-access.d.ts +99 -0
  96. package/dist/core/repo-access.js +136 -0
  97. package/dist/core/review-host-checks.d.ts +11 -0
  98. package/dist/core/review-host-checks.js +41 -0
  99. package/dist/core/review-host-tools.d.ts +47 -0
  100. package/dist/core/review-host-tools.js +347 -0
  101. package/dist/core/run-heartbeat.d.ts +27 -0
  102. package/dist/core/run-heartbeat.js +54 -0
  103. package/dist/core/runner.d.ts +30 -8
  104. package/dist/core/runner.js +237 -40
  105. package/dist/core/secrets.d.ts +11 -2
  106. package/dist/core/secrets.js +25 -6
  107. package/dist/core/subagent-memory-tools.d.ts +1 -1
  108. package/dist/core/subagent-memory-tools.js +16 -3
  109. package/dist/core/tool-admin.d.ts +81 -0
  110. package/dist/core/tool-admin.js +129 -0
  111. package/dist/core/tool-names.d.ts +42 -0
  112. package/dist/core/tool-names.js +64 -0
  113. package/dist/core/untrusted-content.d.ts +32 -0
  114. package/dist/core/untrusted-content.js +72 -0
  115. package/dist/core/webhooks.d.ts +8 -1
  116. package/dist/core/webhooks.js +23 -2
  117. package/dist/generated/prisma/browser.d.ts +100 -0
  118. package/dist/generated/prisma/client.d.ts +100 -0
  119. package/dist/generated/prisma/commonInputTypes.d.ts +30 -0
  120. package/dist/generated/prisma/enums.d.ts +6 -0
  121. package/dist/generated/prisma/enums.js +6 -1
  122. package/dist/generated/prisma/internal/class.d.ts +143 -0
  123. package/dist/generated/prisma/internal/class.js +4 -4
  124. package/dist/generated/prisma/internal/prismaNamespace.d.ts +1746 -577
  125. package/dist/generated/prisma/internal/prismaNamespace.js +179 -6
  126. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +186 -0
  127. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +179 -6
  128. package/dist/generated/prisma/models/Agent.d.ts +294 -1
  129. package/dist/generated/prisma/models/AgentRepository.d.ts +1425 -0
  130. package/dist/generated/prisma/models/AgentRepository.js +1 -0
  131. package/dist/generated/prisma/models/AgentTool.d.ts +95 -1
  132. package/dist/generated/prisma/models/AuthUser.d.ts +56 -1
  133. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +258 -7
  134. package/dist/generated/prisma/models/CodingProxySession.d.ts +123 -2
  135. package/dist/generated/prisma/models/CodingRun.d.ts +1276 -95
  136. package/dist/generated/prisma/models/CodingService.d.ts +1348 -0
  137. package/dist/generated/prisma/models/CodingService.js +1 -0
  138. package/dist/generated/prisma/models/HostEventDelivery.d.ts +946 -0
  139. package/dist/generated/prisma/models/HostEventDelivery.js +1 -0
  140. package/dist/generated/prisma/models/HostIdentity.d.ts +1232 -0
  141. package/dist/generated/prisma/models/HostIdentity.js +1 -0
  142. package/dist/generated/prisma/models/HostIdentityLinkRequest.d.ts +1473 -0
  143. package/dist/generated/prisma/models/HostIdentityLinkRequest.js +1 -0
  144. package/dist/generated/prisma/models/Principal.d.ts +455 -0
  145. package/dist/generated/prisma/models/RegistryAllowance.d.ts +1148 -0
  146. package/dist/generated/prisma/models/RegistryAllowance.js +1 -0
  147. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +1219 -0
  148. package/dist/generated/prisma/models/RegistryApprovedVersion.js +1 -0
  149. package/dist/generated/prisma/models/RegistryFetch.d.ts +1428 -0
  150. package/dist/generated/prisma/models/RegistryFetch.js +1 -0
  151. package/dist/generated/prisma/models/RegistryPlanRefusal.d.ts +1294 -0
  152. package/dist/generated/prisma/models/RegistryPlanRefusal.js +1 -0
  153. package/dist/generated/prisma/models/RegistryVersionFact.d.ts +1085 -0
  154. package/dist/generated/prisma/models/RegistryVersionFact.js +1 -0
  155. package/dist/generated/prisma/models/ResourceGrant.d.ts +1437 -0
  156. package/dist/generated/prisma/models/ResourceGrant.js +1 -0
  157. package/dist/generated/prisma/models/Run.d.ts +389 -1
  158. package/dist/generated/prisma/models/RunHostCheck.d.ts +1239 -0
  159. package/dist/generated/prisma/models/RunHostCheck.js +1 -0
  160. package/dist/generated/prisma/models/RunHostStatus.d.ts +1315 -0
  161. package/dist/generated/prisma/models/RunHostStatus.js +1 -0
  162. package/dist/generated/prisma/models/Tool.d.ts +15 -3
  163. package/dist/generated/prisma/models.d.ts +13 -0
  164. package/dist/help/build.d.ts +1 -0
  165. package/dist/help/build.js +9 -0
  166. package/dist/help/catalog.d.ts +24 -0
  167. package/dist/help/catalog.js +160 -0
  168. package/dist/help/cli.d.ts +2 -0
  169. package/dist/help/cli.js +65 -0
  170. package/dist/help/runtime.d.ts +3 -0
  171. package/dist/help/runtime.js +44 -0
  172. package/dist/help/search.d.ts +9 -0
  173. package/dist/help/search.js +104 -0
  174. package/dist/help-index.json +660 -0
  175. package/dist/import/cli-args.js +3 -2
  176. package/dist/import/create.d.ts +5 -0
  177. package/dist/import/create.js +67 -13
  178. package/dist/import/index.js +19 -9
  179. package/dist/import/neutral-schema.d.ts +11 -11
  180. package/dist/mcp/auth/access.d.ts +70 -0
  181. package/dist/mcp/auth/access.js +58 -0
  182. package/dist/mcp/auth/grants-cli.d.ts +149 -0
  183. package/dist/mcp/auth/grants-cli.js +518 -0
  184. package/dist/mcp/auth/host-account-cli.d.ts +2 -0
  185. package/dist/mcp/auth/host-account-cli.js +47 -0
  186. package/dist/mcp/auth/ownership.d.ts +26 -52
  187. package/dist/mcp/auth/ownership.js +19 -14
  188. package/dist/mcp/auth/repo-authorization.d.ts +22 -0
  189. package/dist/mcp/auth/repo-authorization.js +51 -0
  190. package/dist/mcp/auth/resource-server.d.ts +31 -2
  191. package/dist/mcp/auth/resource-server.js +84 -3
  192. package/dist/mcp/auth/self-hosted/browser.js +2 -2
  193. package/dist/mcp/auth/self-hosted/cli.js +47 -13
  194. package/dist/mcp/auth/self-hosted/credentials.d.ts +20 -2
  195. package/dist/mcp/auth/self-hosted/credentials.js +62 -4
  196. package/dist/mcp/auth/self-hosted/session.d.ts +2 -1
  197. package/dist/mcp/context.d.ts +27 -1
  198. package/dist/mcp/errors.d.ts +25 -6
  199. package/dist/mcp/errors.js +98 -0
  200. package/dist/mcp/host-events/github-ingress.d.ts +36 -0
  201. package/dist/mcp/host-events/github-ingress.js +92 -0
  202. package/dist/mcp/host-events/github-user-callback.d.ts +18 -0
  203. package/dist/mcp/host-events/github-user-callback.js +50 -0
  204. package/dist/mcp/index.d.ts +8 -1
  205. package/dist/mcp/index.js +106 -16
  206. package/dist/mcp/server.js +27 -9
  207. package/dist/mcp/tools/agents.js +446 -48
  208. package/dist/mcp/tools/budget-groups.js +3 -3
  209. package/dist/mcp/tools/datastore.js +22 -15
  210. package/dist/mcp/tools/grants.d.ts +2 -0
  211. package/dist/mcp/tools/grants.js +239 -0
  212. package/dist/mcp/tools/help.d.ts +5 -0
  213. package/dist/mcp/tools/help.js +67 -0
  214. package/dist/mcp/tools/host-accounts.d.ts +2 -0
  215. package/dist/mcp/tools/host-accounts.js +114 -0
  216. package/dist/mcp/tools/memory.d.ts +7 -1
  217. package/dist/mcp/tools/memory.js +5 -5
  218. package/dist/mcp/tools/repositories.d.ts +2 -0
  219. package/dist/mcp/tools/repositories.js +181 -0
  220. package/dist/mcp/tools/runs.d.ts +6 -0
  221. package/dist/mcp/tools/runs.js +60 -6
  222. package/dist/mcp/tools/scheduling.js +3 -6
  223. package/dist/mcp/tools/secrets.js +18 -6
  224. package/dist/mcp/tools/services.d.ts +2 -0
  225. package/dist/mcp/tools/services.js +222 -0
  226. package/dist/mcp/tools/subagents.js +52 -16
  227. package/dist/mcp/tools/tools.d.ts +41 -0
  228. package/dist/mcp/tools/tools.js +201 -40
  229. package/dist/mcp/tools/trigger.js +36 -6
  230. package/dist/mcp/tools/webhooks.js +15 -4
  231. package/dist/mcp/transport/streamable-http.d.ts +10 -0
  232. package/dist/mcp/transport/streamable-http.js +32 -2
  233. package/dist/providers/auth/delegating.d.ts +19 -0
  234. package/dist/providers/auth/delegating.js +71 -0
  235. package/dist/providers/auth/index.d.ts +2 -0
  236. package/dist/providers/auth/index.js +11 -0
  237. package/dist/providers/auth/self-hosted.d.ts +2 -1
  238. package/dist/providers/auth/self-hosted.js +16 -4
  239. package/dist/providers/auth/types.d.ts +6 -0
  240. package/dist/providers/coding-proxy/memory-ledger.d.ts +3 -0
  241. package/dist/providers/coding-proxy/memory-ledger.js +21 -2
  242. package/dist/providers/coding-proxy/metering.d.ts +4 -0
  243. package/dist/providers/coding-proxy/metering.js +28 -2
  244. package/dist/providers/coding-proxy/prisma-ledger.d.ts +17 -0
  245. package/dist/providers/coding-proxy/prisma-ledger.js +50 -5
  246. package/dist/providers/coding-proxy/proxy.d.ts +13 -0
  247. package/dist/providers/coding-proxy/proxy.js +479 -18
  248. package/dist/providers/coding-proxy/registry/audit.d.ts +131 -0
  249. package/dist/providers/coding-proxy/registry/audit.js +380 -0
  250. package/dist/providers/coding-proxy/registry/bounded-fetch.d.ts +16 -0
  251. package/dist/providers/coding-proxy/registry/bounded-fetch.js +77 -0
  252. package/dist/providers/coding-proxy/registry/plan.d.ts +58 -0
  253. package/dist/providers/coding-proxy/registry/plan.js +304 -0
  254. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +34 -0
  255. package/dist/providers/coding-proxy/registry/prisma-store.js +151 -0
  256. package/dist/providers/coding-proxy/registry/service.d.ts +213 -0
  257. package/dist/providers/coding-proxy/registry/service.js +1137 -0
  258. package/dist/providers/coding-proxy/registry/store.d.ts +127 -0
  259. package/dist/providers/coding-proxy/registry/store.js +70 -0
  260. package/dist/providers/coding-proxy/runtime.d.ts +17 -0
  261. package/dist/providers/coding-proxy/runtime.js +63 -0
  262. package/dist/providers/coding-proxy/secure-fetch.js +0 -1
  263. package/dist/providers/coding-proxy/server.d.ts +11 -0
  264. package/dist/providers/coding-proxy/server.js +163 -0
  265. package/dist/providers/coding-proxy/types.d.ts +15 -0
  266. package/dist/providers/engine/types.d.ts +10 -0
  267. package/dist/providers/executor/build.d.ts +2 -2
  268. package/dist/providers/executor/composition.d.ts +3 -0
  269. package/dist/providers/executor/composition.js +19 -0
  270. package/dist/providers/executor/container.d.ts +105 -3
  271. package/dist/providers/executor/container.js +296 -20
  272. package/dist/providers/executor/dbos.d.ts +2 -3
  273. package/dist/providers/executor/in-process.d.ts +2 -3
  274. package/dist/providers/executor/routing.d.ts +7 -0
  275. package/dist/providers/executor/routing.js +13 -0
  276. package/dist/providers/executor/types.d.ts +22 -0
  277. package/dist/providers/jobs/claude-tool-setup.d.ts +23 -0
  278. package/dist/providers/jobs/claude-tool-setup.js +50 -0
  279. package/dist/providers/jobs/collect-prune.d.ts +7 -0
  280. package/dist/providers/jobs/collect-prune.js +27 -0
  281. package/dist/providers/jobs/docker-isolation.d.ts +48 -3
  282. package/dist/providers/jobs/docker-isolation.js +213 -22
  283. package/dist/providers/jobs/docker-services.d.ts +35 -0
  284. package/dist/providers/jobs/docker-services.js +191 -0
  285. package/dist/providers/jobs/docker.d.ts +49 -2
  286. package/dist/providers/jobs/docker.js +279 -32
  287. package/dist/providers/jobs/fake-kubernetes-api.d.ts +1 -0
  288. package/dist/providers/jobs/fake-kubernetes-api.js +12 -3
  289. package/dist/providers/jobs/kubernetes-isolation.d.ts +17 -2
  290. package/dist/providers/jobs/kubernetes-isolation.js +238 -57
  291. package/dist/providers/jobs/kubernetes-platform.d.ts +10 -4
  292. package/dist/providers/jobs/kubernetes-platform.js +11 -5
  293. package/dist/providers/jobs/kubernetes-preflight.js +3 -0
  294. package/dist/providers/jobs/kubernetes.d.ts +21 -2
  295. package/dist/providers/jobs/kubernetes.js +112 -21
  296. package/dist/providers/jobs/types.d.ts +18 -0
  297. package/dist/providers/llm/anthropic.js +6 -2
  298. package/dist/providers/llm/bedrock.js +2 -1
  299. package/dist/providers/llm/claude-messages.d.ts +5 -1
  300. package/dist/providers/llm/claude-messages.js +1 -0
  301. package/dist/providers/llm/claude-provider.d.ts +3 -1
  302. package/dist/providers/llm/claude-provider.js +5 -1
  303. package/dist/providers/llm/index.d.ts +1 -1
  304. package/dist/providers/llm/index.js +1 -1
  305. package/dist/providers/llm/pricing-anthropic.d.ts +10 -0
  306. package/dist/providers/llm/pricing-anthropic.js +32 -14
  307. package/dist/providers/llm/pricing-bedrock-claude.d.ts +8 -0
  308. package/dist/providers/llm/pricing-bedrock-claude.js +9 -0
  309. package/dist/providers/llm/routing.d.ts +10 -1
  310. package/dist/providers/llm/routing.js +18 -0
  311. package/dist/providers/llm/types.d.ts +12 -0
  312. package/dist/providers/llm/types.js +8 -1
  313. package/dist/providers/review-host/diff-lines.d.ts +16 -0
  314. package/dist/providers/review-host/diff-lines.js +59 -0
  315. package/dist/providers/review-host/github-events.d.ts +6 -0
  316. package/dist/providers/review-host/github-events.js +180 -0
  317. package/dist/providers/review-host/github-user-auth.d.ts +38 -0
  318. package/dist/providers/review-host/github-user-auth.js +128 -0
  319. package/dist/providers/review-host/github.d.ts +57 -0
  320. package/dist/providers/review-host/github.js +567 -0
  321. package/dist/providers/review-host/index.d.ts +12 -0
  322. package/dist/providers/review-host/index.js +30 -0
  323. package/dist/providers/review-host/review-format.d.ts +19 -0
  324. package/dist/providers/review-host/review-format.js +59 -0
  325. package/dist/providers/review-host/types.d.ts +284 -0
  326. package/dist/providers/review-host/types.js +24 -0
  327. package/dist/providers/vcs/git.d.ts +16 -6
  328. package/dist/providers/vcs/git.js +77 -13
  329. package/dist/providers/vcs/github.d.ts +74 -3
  330. package/dist/providers/vcs/github.js +195 -15
  331. package/dist/providers/vcs/types.d.ts +42 -4
  332. package/dist/quickstart/index.js +13 -2
  333. package/dist/sandbox/fetch-policy.d.ts +20 -2
  334. package/dist/sandbox/fetch-policy.js +64 -3
  335. package/dist/sandbox/host-functions.d.ts +9 -1
  336. package/dist/sandbox/host-functions.js +12 -5
  337. package/dist/serve.js +1 -1
  338. package/dist/wardby-bin.js +6 -0
  339. package/docs/README.md +30 -0
  340. package/docs/architecture-runtime.md +90 -0
  341. package/docs/assets/brand/wardby-icon-512.png +0 -0
  342. package/docs/assets/brand/wardby-icon.svg +16 -0
  343. package/docs/assets/brand/wardby-mascot-profile-512.png +0 -0
  344. package/docs/assets/brand/wardby-mascot.png +0 -0
  345. package/docs/assets/brand/wardby-mascot.svg +5 -0
  346. package/docs/assets/wardby-workflow.svg +106 -0
  347. package/docs/code-review-agents.md +481 -0
  348. package/docs/coding-agent-setup.md +172 -0
  349. package/docs/coding-packages.md +455 -0
  350. package/docs/coding-services.md +300 -0
  351. package/docs/coding-worker-byo-images.md +98 -0
  352. package/docs/coding-worker-isolation.md +1061 -0
  353. package/docs/getting-started-gke.md +615 -0
  354. package/docs/getting-started-identity-provider.md +308 -0
  355. package/docs/getting-started.md +133 -0
  356. package/docs/observability.md +53 -0
  357. package/docs/release-verification.md +66 -0
  358. package/docs/security-deployment.md +657 -0
  359. package/help/code-review-agents.md +31 -0
  360. package/help/coding-packages.md +31 -0
  361. package/help/coding-services.md +71 -0
  362. package/help/creating-agents.md +68 -0
  363. package/help/deploy-gke.md +39 -0
  364. package/help/deployment-targets.md +39 -0
  365. package/help/errors/budget-group-exhausted.md +25 -0
  366. package/help/errors/docker-isolation-unsupported.md +26 -0
  367. package/help/errors/protected-path.md +45 -0
  368. package/help/errors/repo-access.md +27 -0
  369. package/help/errors/service-declaration-invalid.md +27 -0
  370. package/help/errors/service-declaration-unavailable.md +25 -0
  371. package/help/errors/service-launcher-unsupported.md +30 -0
  372. package/help/errors/service-not-allowed.md +27 -0
  373. package/help/errors/service-unknown.md +23 -0
  374. package/help/errors/service-unready.md +49 -0
  375. package/help/getting-started.md +31 -0
  376. package/help/github.md +30 -0
  377. package/help/identity-and-access.md +39 -0
  378. package/help/mcp.md +30 -0
  379. package/help/native-capabilities.md +30 -0
  380. package/help/observability.md +41 -0
  381. package/help/operating-agents.md +30 -0
  382. package/help/security.md +27 -0
  383. package/help/troubleshooting/budgets.md +26 -0
  384. package/help/troubleshooting/coding-workers.md +47 -0
  385. package/help/troubleshooting/repository-access.md +27 -0
  386. package/package.json +12 -3
  387. package/prisma/migrations/20260925010000_coding_collect_exclude/migration.sql +8 -0
  388. package/prisma/migrations/20260925015000_allowed_egress_default/migration.sql +8 -0
  389. package/prisma/migrations/20260925020000_coding_package_registry/migration.sql +55 -0
  390. package/prisma/migrations/20260925030000_tool_name_per_owner/migration.sql +11 -0
  391. package/prisma/migrations/20260926010000_run_trigger_host_event/migration.sql +7 -0
  392. package/prisma/migrations/20260926020000_code_review_hosts/migration.sql +53 -0
  393. package/prisma/migrations/20260926030000_auth_user_roles/migration.sql +9 -0
  394. package/prisma/migrations/20260926040000_agent_effort/migration.sql +6 -0
  395. package/prisma/migrations/20260926050000_registry_lockfile_plan/migration.sql +32 -0
  396. package/prisma/migrations/20260926050000_repo_access_authorization/migration.sql +82 -0
  397. package/prisma/migrations/20260926060000_registry_plan_refusal/migration.sql +19 -0
  398. package/prisma/migrations/20260926100000_registry_plan_refusal_published_at/migration.sql +5 -0
  399. package/prisma/migrations/20260926190000_run_host_status/migration.sql +18 -0
  400. package/prisma/migrations/20260926210000_run_host_status_at_dispatch/migration.sql +5 -0
  401. package/prisma/migrations/20260927010000_resource_grants/migration.sql +72 -0
  402. package/prisma/migrations/20260927020000_proxy_session_budget_exhausted/migration.sql +3 -0
  403. package/prisma/migrations/20260927030000_coding_debug_trace/migration.sql +4 -0
  404. package/prisma/migrations/20260927040000_proxy_session_upstream_failure/migration.sql +3 -0
  405. package/prisma/migrations/20260927050000_coding_run_services/migration.sql +74 -0
  406. package/prisma/migrations/20260928000000_coding_run_tool_image/migration.sql +5 -0
  407. package/prisma/schema.prisma +407 -21
@@ -1,4 +1,6 @@
1
+ import { loadCodingConcurrencyConfig } from "../config/providers.js";
1
2
  import { logger } from "./logger.js";
3
+ import { HEARTBEAT_TIMEOUT_MS, RECONCILE_INTERVAL_MS } from "./timing.js";
2
4
  const budgetGroupLog = logger.child({ module: "budget-groups" });
3
5
  /**
4
6
  * Calendar-aligned UTC period start. "week" is the ISO week: Monday 00:00
@@ -20,6 +22,44 @@ export function periodStart(period, now) {
20
22
  function toNullableNumber(value) {
21
23
  return value === null || value === undefined ? null : Number(value);
22
24
  }
25
+ const IN_FLIGHT = new Set(["pending", "running"]);
26
+ /**
27
+ * How long a run's last heartbeat keeps its hold alive: the reconciler's
28
+ * heartbeat timeout plus one reconcile interval, so a managed run is reaped
29
+ * (or re-claimed, which refreshes heartbeatAt) before its hold lapses.
30
+ * Managed native runs beat every HEARTBEAT_INTERVAL_MS (InProcessExecutor,
31
+ * DbosExecutor), as do `wardby run` and native sub-agent children
32
+ * (withRunHeartbeat); a coding run beats while its job is polled.
33
+ */
34
+ export const HOLD_HEARTBEAT_TTL_MS = HEARTBEAT_TIMEOUT_MS + RECONCILE_INTERVAL_MS;
35
+ /** Slack past a coding run's queue + run timeout before its hold lapses (matches the sub-agent wait grace). */
36
+ export const CODING_HOLD_GRACE_SEC = 60;
37
+ /** Smallest amount worth holding or reserving: CodingRun.budgetReservedUsd has 6 decimal places. */
38
+ export const MIN_RESERVATION_USD = 0.000001;
39
+ /**
40
+ * Whether an in-flight row still holds budget. A run holds while its last
41
+ * sign of life (heartbeatAt, or startedAt before its first beat) is within
42
+ * HOLD_HEARTBEAT_TTL_MS. A coding run also holds, beat or not, until its
43
+ * queue timeout + run timeout + grace have passed since dispatch: a queued
44
+ * coding run does not beat, and nothing can legitimately spend past that.
45
+ */
46
+ export function isHoldLive(run, now, codingQueueTimeoutSec) {
47
+ if (!IN_FLIGHT.has(run.status))
48
+ return false;
49
+ const lastSign = (run.heartbeatAt ?? run.startedAt).getTime();
50
+ if (now.getTime() - lastSign <= HOLD_HEARTBEAT_TTL_MS)
51
+ return true;
52
+ if (run.codingRun) {
53
+ const deadlineMs = run.startedAt.getTime() + (codingQueueTimeoutSec + run.codingRun.timeoutSec + CODING_HOLD_GRACE_SEC) * 1000;
54
+ return now.getTime() <= deadlineMs;
55
+ }
56
+ return false;
57
+ }
58
+ function isOrderedBefore(run, other) {
59
+ const a = run.startedAt.getTime();
60
+ const b = other.startedAt.getTime();
61
+ return a < b || (a === b && run.id < other.id);
62
+ }
23
63
  /**
24
64
  * Live per-period spend for whichever of a group's daily/weekly/monthly
25
65
  * caps are actually set -- unset periods are omitted from the result, not
@@ -27,7 +67,7 @@ function toNullableNumber(value) {
27
67
  * (month contains week contains day), bucketed in JS, rather than a
28
68
  * separate DB round trip per period.
29
69
  */
30
- export async function computeGroupSpend(db, group, memberAgentIds, now = new Date()) {
70
+ export async function computeGroupSpend(db, group, members, now = new Date(), options = {}) {
31
71
  const caps = [
32
72
  { period: "day", capUsd: toNullableNumber(group.dailyBudgetUsd) },
33
73
  { period: "week", capUsd: toNullableNumber(group.weeklyBudgetUsd) },
@@ -42,28 +82,56 @@ export async function computeGroupSpend(db, group, memberAgentIds, now = new Dat
42
82
  // query itself as a cheap no-op; an empty `agentId: { in: [] }` would
43
83
  // match nothing anyway.
44
84
  const widestStart = periodStart("month", now);
45
- const runs = memberAgentIds.length === 0
85
+ const memberBudgets = new Map(members.map((m) => [m.id, Number(m.budgetUsd)]));
86
+ const excluded = new Set(options.excludeReservationRunIds ?? []);
87
+ const queueTimeoutSec = options.codingQueueTimeoutSec ?? loadCodingConcurrencyConfig().queueTimeoutSec;
88
+ const runs = members.length === 0
46
89
  ? []
47
90
  : await db.run.findMany({
48
- where: { agentId: { in: memberAgentIds }, startedAt: { gte: widestStart } },
49
- select: { costUsd: true, startedAt: true },
91
+ where: { agentId: { in: [...memberBudgets.keys()] }, startedAt: { gte: widestStart } },
92
+ select: {
93
+ id: true,
94
+ agentId: true,
95
+ status: true,
96
+ costUsd: true,
97
+ startedAt: true,
98
+ heartbeatAt: true,
99
+ codingRun: { select: { budgetReservedUsd: true, timeoutSec: true } },
100
+ },
50
101
  });
102
+ const accounted = runs.map((r) => {
103
+ const costUsd = Number(r.costUsd);
104
+ let reservedUsd = 0;
105
+ const holds = !excluded.has(r.id) &&
106
+ (options.holdsBefore === undefined || isOrderedBefore(r, options.holdsBefore)) &&
107
+ isHoldLive(r, now, queueTimeoutSec);
108
+ if (holds) {
109
+ // A coding run holds exactly what dispatch reserved. A native run (or
110
+ // a coding run whose CodingRun row is missing) holds its agent's
111
+ // per-run budget: never less than what it can actually spend.
112
+ const reservation = r.codingRun != null ? Number(r.codingRun.budgetReservedUsd) : (memberBudgets.get(r.agentId) ?? 0);
113
+ reservedUsd = Math.max(0, reservation - costUsd);
114
+ }
115
+ return { startedAt: r.startedAt, costUsd, reservedUsd };
116
+ });
51
117
  return configured.map(({ period, capUsd }) => {
52
118
  const start = periodStart(period, now);
53
- const spentUsd = runs.filter((r) => r.startedAt >= start).reduce((sum, r) => sum + Number(r.costUsd), 0);
54
- return { period, capUsd, spentUsd, remainingUsd: Math.max(0, capUsd - spentUsd) };
119
+ const inPeriod = accounted.filter((r) => r.startedAt >= start);
120
+ const spentUsd = inPeriod.reduce((sum, r) => sum + r.costUsd, 0);
121
+ const reservedUsd = inPeriod.reduce((sum, r) => sum + r.reservedUsd, 0);
122
+ return { period, capUsd, spentUsd, reservedUsd, remainingUsd: Math.max(0, capUsd - spentUsd - reservedUsd) };
55
123
  });
56
124
  }
57
125
  /** Walks parentRunId upward from `runId` to the tree's root (parentRunId null). */
58
126
  async function findRootRun(db, runId) {
59
127
  let current = await db.run.findUniqueOrThrow({
60
128
  where: { id: runId },
61
- select: { id: true, agentId: true, parentRunId: true },
129
+ select: { id: true, agentId: true, parentRunId: true, startedAt: true },
62
130
  });
63
131
  while (current.parentRunId) {
64
132
  current = await db.run.findUniqueOrThrow({
65
133
  where: { id: current.parentRunId },
66
- select: { id: true, agentId: true, parentRunId: true },
134
+ select: { id: true, agentId: true, parentRunId: true, startedAt: true },
67
135
  });
68
136
  }
69
137
  return current;
@@ -88,9 +156,17 @@ async function collectTreeRunIds(db, rootRunId) {
88
156
  * spent so far. The root's ceiling is recomputed fresh here, not pinned
89
157
  * from whatever it was when the root run started — consistent with
90
158
  * BudgetGroup periods already always being live-recomputed rather than
91
- * snapshotted.
159
+ * snapshotted. That group check sees the group as the root did when it
160
+ * loaded: the tree's own holds are left out (the tree spends inside the
161
+ * root's hold, so counting it again would leave the tree nothing), and so
162
+ * are holds of runs that started after the root (they already counted the
163
+ * root's hold).
92
164
  */
93
165
  export async function computeRunTreeSpend(db, parentRunId, now = new Date()) {
166
+ const { rootRunId, capUsd, spentUsd, remainingUsd } = await runTreeSpend(db, parentRunId, now);
167
+ return { rootRunId, capUsd, spentUsd, remainingUsd };
168
+ }
169
+ async function runTreeSpend(db, parentRunId, now) {
94
170
  const root = await findRootRun(db, parentRunId);
95
171
  const treeRunIds = await collectTreeRunIds(db, root.id);
96
172
  const rows = await db.run.findMany({ where: { id: { in: treeRunIds } }, select: { costUsd: true } });
@@ -99,11 +175,23 @@ export async function computeRunTreeSpend(db, parentRunId, now = new Date()) {
99
175
  where: { id: root.agentId },
100
176
  select: { id: true, budgetGroupId: true, budgetUsd: true },
101
177
  });
178
+ const rootOrder = { id: root.id, startedAt: root.startedAt };
102
179
  // Root has no parentRunId of its own, so this terminates in one level —
103
180
  // no unbounded recursion regardless of how deep `parentRunId` itself was.
104
- const rootCeiling = await effectiveBudgetForRun(db, rootAgent, now);
181
+ const rootCeiling = await groupCappedBudget(db, rootAgent, now, {
182
+ excludeReservationRunIds: treeRunIds,
183
+ holdsBefore: rootOrder,
184
+ });
105
185
  const capUsd = rootCeiling.effectiveBudgetUsd;
106
- return { rootRunId: root.id, capUsd, spentUsd, remainingUsd: Math.max(0, capUsd - spentUsd) };
186
+ return {
187
+ rootRunId: root.id,
188
+ capUsd,
189
+ spentUsd,
190
+ remainingUsd: Math.max(0, capUsd - spentUsd),
191
+ treeRunIds,
192
+ root: rootOrder,
193
+ rootBudgetGroupId: rootAgent.budgetGroupId,
194
+ };
107
195
  }
108
196
  /**
109
197
  * The per-run budget ceiling to actually use for `agent`: its own
@@ -116,17 +204,35 @@ export async function computeRunTreeSpend(db, parentRunId, now = new Date()) {
116
204
  * with no caps configured is returned unchanged. Also logs a warning
117
205
  * (never blocks, never throws) once a period's spend crosses the group's
118
206
  * own warnThresholdRatio.
207
+ *
208
+ * A sub-agent in the root's own budget group spends inside the root's hold,
209
+ * so its group check is the root's: the tree's holds and the holds of runs
210
+ * after the root are left out. A sub-agent in any other group is an
211
+ * ordinary member of that group and counts every earlier live hold there,
212
+ * the tree's included.
119
213
  */
120
- export async function effectiveBudgetForRun(db, agent, now = new Date(), parentRunId) {
214
+ export async function effectiveBudgetForRun(db, agent, now = new Date(), parentRunId, options = {}) {
215
+ const self = options.self;
216
+ const ownSpend = { excludeReservationRunIds: self ? [self.id] : [], holdsBefore: self };
217
+ if (!parentRunId)
218
+ return groupCappedBudget(db, agent, now, ownSpend);
219
+ const tree = await runTreeSpend(db, parentRunId, now);
220
+ const sharesRootGroup = agent.budgetGroupId !== null && agent.budgetGroupId === tree.rootBudgetGroupId;
221
+ const spend = sharesRootGroup
222
+ ? { excludeReservationRunIds: [...tree.treeRunIds, ...(self ? [self.id] : [])], holdsBefore: tree.root }
223
+ : ownSpend;
224
+ return groupCappedBudget(db, agent, now, spend, { value: tree.remainingUsd, reason: "run-tree" });
225
+ }
226
+ async function groupCappedBudget(db, agent, now, spendOptions, extra) {
121
227
  const ownBudgetUsd = Number(agent.budgetUsd);
122
228
  const candidates = [];
123
229
  if (agent.budgetGroupId) {
124
230
  const group = await db.budgetGroup.findUnique({
125
231
  where: { id: agent.budgetGroupId },
126
- include: { agents: { select: { id: true } } },
232
+ include: { agents: { select: { id: true, budgetUsd: true } } },
127
233
  });
128
234
  if (group) {
129
- const spend = await computeGroupSpend(db, group, group.agents.map((a) => a.id), now);
235
+ const spend = await computeGroupSpend(db, group, group.agents, now, spendOptions);
130
236
  const warnThresholdRatio = Number(group.warnThresholdRatio);
131
237
  for (const s of spend) {
132
238
  candidates.push({ value: s.remainingUsd, reason: s.period });
@@ -137,13 +243,13 @@ export async function effectiveBudgetForRun(db, agent, now = new Date(), parentR
137
243
  }
138
244
  }
139
245
  }
140
- if (parentRunId) {
141
- const tree = await computeRunTreeSpend(db, parentRunId, now);
142
- candidates.push({ value: tree.remainingUsd, reason: "run-tree" });
143
- }
246
+ if (extra)
247
+ candidates.push(extra);
144
248
  if (candidates.length === 0)
145
249
  return { effectiveBudgetUsd: ownBudgetUsd, constrainedBy: [] };
146
250
  const constrainedBy = candidates.filter((c) => c.value < ownBudgetUsd).map((c) => c.reason);
147
251
  const effectiveBudgetUsd = Math.min(ownBudgetUsd, ...candidates.map((c) => c.value));
148
- return { effectiveBudgetUsd, constrainedBy };
252
+ // Less than the smallest reservable amount is nothing left.
253
+ const exhausted = candidates.find((c) => c.value < MIN_RESERVATION_USD);
254
+ return { effectiveBudgetUsd, constrainedBy, ...(exhausted ? { exhaustedBy: exhausted.reason } : {}) };
149
255
  }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The one sentence a host (a PR comment, a check summary) is told when a run
3
+ * ran out of budget, or could not start for lack of it. Public repositories
4
+ * read these, so it names amounts and the budget group only: never error
5
+ * text, token counts, or ids.
6
+ */
7
+ import type { PrismaClient } from "#prisma";
8
+ export interface BudgetFacts {
9
+ /** The run's own budget (a coding run's reservation); falls back to the agent's. */
10
+ runBudgetUsd?: number | null;
11
+ agentBudgetUsd: number;
12
+ budgetGroupName?: string | null;
13
+ /** The run was refused before it started. */
14
+ refused?: boolean;
15
+ }
16
+ export declare function budgetSentence(facts: BudgetFacts): string;
17
+ /**
18
+ * The sentence for a finished run, read from the database: a coding run's
19
+ * reserved budget, otherwise the agent's. Falls back to a sentence without
20
+ * amounts when they cannot be read. Never throws.
21
+ */
22
+ export declare function loadBudgetSentence(db: Pick<PrismaClient, "run">, runId: string, status: string): Promise<string>;
@@ -0,0 +1,55 @@
1
+ const MAX_GROUP_NAME_CHARS = 64;
2
+ const usd = (amount) => `$${amount.toFixed(2)}`;
3
+ /** A group name is operator-chosen text; keep it to one short, quote-free line. */
4
+ function groupName(name) {
5
+ const cleaned = (name ?? "").replace(/["`]/g, "").replace(/\s+/g, " ").trim().slice(0, MAX_GROUP_NAME_CHARS);
6
+ return cleaned || null;
7
+ }
8
+ export function budgetSentence(facts) {
9
+ const group = groupName(facts.budgetGroupName);
10
+ if (facts.refused) {
11
+ const within = `this run could not start within its ${usd(facts.runBudgetUsd ?? facts.agentBudgetUsd)} budget`;
12
+ return group
13
+ ? `Out of budget: ${within} or what the "${group}" budget group had left of its limit.`
14
+ : `Out of budget: ${within}.`;
15
+ }
16
+ const runBudget = facts.runBudgetUsd ?? facts.agentBudgetUsd;
17
+ const used = `Out of budget: this run's ${usd(runBudget)} budget was used up`;
18
+ // A run reserved less than the agent's own budget: its group had only that much left.
19
+ if (group && runBudget < facts.agentBudgetUsd) {
20
+ return `${used} (the "${group}" budget group had only that much left of its limit).`;
21
+ }
22
+ return `${used}.`;
23
+ }
24
+ /**
25
+ * The sentence for a finished run, read from the database: a coding run's
26
+ * reserved budget, otherwise the agent's. Falls back to a sentence without
27
+ * amounts when they cannot be read. Never throws.
28
+ */
29
+ export async function loadBudgetSentence(db, runId, status) {
30
+ const refused = status === "refused";
31
+ try {
32
+ const row = await db.run.findUnique({
33
+ where: { id: runId },
34
+ select: {
35
+ agent: { select: { budgetUsd: true, budgetGroup: { select: { name: true } } } },
36
+ codingRun: { select: { budgetReservedUsd: true } },
37
+ },
38
+ });
39
+ const agentBudgetUsd = Number(row?.agent?.budgetUsd);
40
+ if (!row?.agent || !Number.isFinite(agentBudgetUsd))
41
+ throw new Error("budget_facts_unavailable");
42
+ const reserved = row.codingRun ? Number(row.codingRun.budgetReservedUsd) : NaN;
43
+ return budgetSentence({
44
+ runBudgetUsd: Number.isFinite(reserved) ? reserved : null,
45
+ agentBudgetUsd,
46
+ budgetGroupName: row.agent.budgetGroup?.name ?? null,
47
+ refused,
48
+ });
49
+ }
50
+ catch {
51
+ return refused
52
+ ? "Out of budget: this run could not start within its budget."
53
+ : "Out of budget: this run's budget was used up.";
54
+ }
55
+ }
@@ -25,9 +25,25 @@ export async function attachDatastore(agentId, datastoreId, db, boundName) {
25
25
  export async function detachDatastore(agentId, boundName, db) {
26
26
  await db.agentDatastore.deleteMany({ where: { agentId, boundName } });
27
27
  }
28
+ /**
29
+ * Owner rule (resource-sharing grants spec §3.4.1): a binding resolves only
30
+ * while the datastore's owner is the agent's CURRENT owner, both non-null.
31
+ * A cross-owner binding (written before that rule, or left behind by
32
+ * make_owner) and every binding on an owner-less agent resolve like an
33
+ * unattached boundName, so one owner's store never reaches another owner's
34
+ * agent (A2/S2-2, R2-1).
35
+ */
28
36
  async function resolveDatastoreId(agentId, boundName, db) {
29
- const attachment = await db.agentDatastore.findFirst({ where: { agentId, boundName } });
30
- return attachment?.datastoreId;
37
+ const attachment = await db.agentDatastore.findFirst({
38
+ where: { agentId, boundName },
39
+ include: { datastore: { select: { ownerId: true } }, agent: { select: { ownerId: true } } },
40
+ });
41
+ if (!attachment)
42
+ return undefined;
43
+ const owner = attachment.agent.ownerId;
44
+ if (owner === null || attachment.datastore.ownerId !== owner)
45
+ return undefined;
46
+ return attachment.datastoreId;
31
47
  }
32
48
  /**
33
49
  * Resolves `boundName` to the Datastore attached to this agent under that
package/dist/core/db.d.ts CHANGED
@@ -32,5 +32,9 @@ export declare function poolSettings(connectionString: string): PoolSettings;
32
32
  * The one way wardby builds a Prisma client. `url` defaults to DATABASE_URL
33
33
  * as read at call time.
34
34
  */
35
- export declare function createPrismaClient(url?: string | undefined): PrismaClient;
35
+ /** `poolMax` overrides the pool size for a caller that sizes its own pools
36
+ * (the coding proxy keeps its ledger and its package registry apart). */
37
+ export declare function createPrismaClient(url?: string | undefined, options?: {
38
+ poolMax?: number;
39
+ }): PrismaClient;
36
40
  export declare const prisma: PrismaClient;
package/dist/core/db.js CHANGED
@@ -60,9 +60,15 @@ class MissingUrlAdapter extends PrismaPg {
60
60
  * The one way wardby builds a Prisma client. `url` defaults to DATABASE_URL
61
61
  * as read at call time.
62
62
  */
63
- export function createPrismaClient(url = process.env.DATABASE_URL) {
63
+ /** `poolMax` overrides the pool size for a caller that sizes its own pools
64
+ * (the coding proxy keeps its ledger and its package registry apart). */
65
+ export function createPrismaClient(url = process.env.DATABASE_URL, options = {}) {
64
66
  const adapter = url
65
- ? new PrismaPg({ connectionString: url, ...poolSettings(url) })
67
+ ? new PrismaPg({
68
+ connectionString: url,
69
+ ...poolSettings(url),
70
+ ...(options.poolMax !== undefined ? { max: options.poolMax } : {}),
71
+ })
66
72
  : new MissingUrlAdapter({ connectionString: "" });
67
73
  return new PrismaClient({ adapter });
68
74
  }
@@ -1,7 +1,8 @@
1
1
  import type { Prisma, PrismaClient, Run, RunTrigger, Task } from "#prisma";
2
2
  import type { Executor } from "../providers/executor/types.js";
3
- export type DispatchDb = Pick<PrismaClient, "agent" | "run" | "codingRun" | "task" | "webhook" | "$transaction" | "$queryRaw">;
4
- type DispatchTx = Pick<Prisma.TransactionClient, "agent" | "run" | "codingRun" | "task" | "webhook" | "$queryRaw">;
3
+ import { type BudgetConstraint } from "./budget-groups.js";
4
+ export type DispatchDb = Pick<PrismaClient, "agent" | "run" | "runHostCheck" | "codingRun" | "task" | "webhook" | "budgetGroup" | "$transaction" | "$queryRaw">;
5
+ export type DispatchTx = Pick<Prisma.TransactionClient, "agent" | "run" | "runHostCheck" | "runHostStatus" | "codingRun" | "codingService" | "task" | "webhook" | "budgetGroup" | "resourceGrant" | "$queryRaw" | "$executeRawUnsafe">;
5
6
  type DispatchAgent = Prisma.AgentGetPayload<{
6
7
  include: {
7
8
  codingProfile: true;
@@ -32,6 +33,19 @@ export interface DispatchRunOptions {
32
33
  ttlMs: number;
33
34
  };
34
35
  beforePersist?: (tx: DispatchTx, agent: DispatchAgent) => Promise<boolean>;
36
+ /**
37
+ * Runs inside the persist transaction right after the run row is created,
38
+ * before the executor is started — for rows that must exist before the run
39
+ * can observe them (e.g. RunHostCheck, see core/host-events.ts).
40
+ */
41
+ afterPersist?: (tx: DispatchTx, run: Run) => Promise<void>;
42
+ /**
43
+ * Who the run is visible to besides the agent owner (Run.triggeredById,
44
+ * resource-sharing grants spec §3.5): the trigger_agent caller, a
45
+ * webhook's creator, a sub-agent's parent triggerer. Omit/null for
46
+ * scheduled and host-event runs, which only the owner sees.
47
+ */
48
+ triggeredById?: string | null;
35
49
  /** Sub-agent dispatch (see AgentSubAgent): links this run into a run tree. */
36
50
  parentRunId?: string;
37
51
  grantedParentMemoryKeys?: string[];
@@ -42,10 +56,10 @@ export interface DispatchRunOptions {
42
56
  */
43
57
  taskOverride?: string;
44
58
  /**
45
- * Overrides `agent.budgetUsd` for this run's coding budget reservation —
46
- * used by sub-agent dispatch to apply the run-tree's tightened effective
47
- * budget (see src/core/budget-groups.ts) instead of the agent's raw
48
- * per-run ceiling, the same composability already applied to native runs.
59
+ * Replaces `agent.budgetUsd` as the requested ceiling for this run's coding
60
+ * budget reservation. The reservation is still tightened by the agent's
61
+ * budget group and, with `parentRunId`, the run tree (see
62
+ * src/core/budget-groups.ts), computed inside the persist transaction.
49
63
  * Ignored for native agents, which compute their own effective budget
50
64
  * inside executeRun's load step.
51
65
  */
@@ -87,6 +101,19 @@ export declare function isSerializationConflict(err: unknown): boolean;
87
101
  * than overwrite whatever landed in between.
88
102
  */
89
103
  export declare function markRunFailedFromExecutorError(db: Pick<DispatchDb, "run">, runId: string, err: unknown): Promise<void>;
104
+ /**
105
+ * The `Run.error` of a coding run refused at dispatch because a budget
106
+ * constraint has nothing left: `budget_group_exhausted:<period>` or
107
+ * `run_tree_exhausted`, then a sentence for people.
108
+ */
109
+ export declare function budgetExhaustedError(constraint: BudgetConstraint): string;
110
+ /**
111
+ * Attempts for the persist transaction, and the jittered backoff between
112
+ * them, for serialization failures and deadlocks.
113
+ *
114
+ * @internal Exported only for the real-PostgreSQL tests.
115
+ */
116
+ export declare const PERSIST_ATTEMPTS = 8;
90
117
  /**
91
118
  * Persists every detached run input in one transaction, then invokes the
92
119
  * executor only after commit. A null result means the caller's transactional