@wardby/cli 0.7.0 → 0.9.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 (367) hide show
  1. package/.env.example +5 -5
  2. package/README.md +6 -1
  3. package/deploy/local/docker-compose.quickstart-coding.yml +11 -0
  4. package/dist/claude-coding-worker/driver.d.ts +12 -0
  5. package/dist/claude-coding-worker/driver.js +29 -7
  6. package/dist/claude-coding-worker/main.js +5 -1
  7. package/dist/claude-coding-worker/sdk.js +17 -1
  8. package/dist/claude-plugin/command.d.ts +64 -0
  9. package/dist/claude-plugin/command.js +379 -0
  10. package/dist/cli-help.d.ts +1 -1
  11. package/dist/cli-help.js +2 -1
  12. package/dist/cli.js +71 -3
  13. package/dist/coding/code-host.d.ts +16 -0
  14. package/dist/coding/code-host.js +60 -0
  15. package/dist/coding/mcp-token.d.ts +12 -0
  16. package/dist/coding/mcp-token.js +26 -0
  17. package/dist/coding/protocol.js +2 -0
  18. package/dist/coding/redact.js +6 -1
  19. package/dist/coding/transcript/recorder.d.ts +5 -4
  20. package/dist/coding/transcript/recorder.js +3 -9
  21. package/dist/coding-worker/debug-trace.d.ts +3 -1
  22. package/dist/coding-worker/debug-trace.js +4 -2
  23. package/dist/coding-worker/driver.js +8 -1
  24. package/dist/coding-worker/main.js +5 -1
  25. package/dist/coding-worker/mcp-config.d.ts +27 -0
  26. package/dist/coding-worker/mcp-config.js +32 -0
  27. package/dist/coding-worker/sdk.d.ts +36 -0
  28. package/dist/coding-worker/sdk.js +28 -1
  29. package/dist/coding-worker/types.d.ts +4 -0
  30. package/dist/config/mcp-call-limit.d.ts +8 -0
  31. package/dist/config/mcp-call-limit.js +18 -0
  32. package/dist/config/mcp-servers.d.ts +8 -0
  33. package/dist/config/mcp-servers.js +12 -0
  34. package/dist/config/test-simulators.d.ts +10 -0
  35. package/dist/config/test-simulators.js +28 -0
  36. package/dist/config/tool-timeout.d.ts +1 -0
  37. package/dist/config/tool-timeout.js +18 -0
  38. package/dist/core/coding-mcp.d.ts +36 -0
  39. package/dist/core/coding-mcp.js +253 -0
  40. package/dist/core/coding-repository.d.ts +46 -0
  41. package/dist/core/coding-repository.js +92 -0
  42. package/dist/core/delegation-slots.d.ts +27 -0
  43. package/dist/core/delegation-slots.js +44 -0
  44. package/dist/core/dispatch.d.ts +6 -2
  45. package/dist/core/dispatch.js +39 -11
  46. package/dist/core/engine-native.d.ts +2 -0
  47. package/dist/core/engine-native.js +13 -0
  48. package/dist/core/error-code.js +2 -0
  49. package/dist/core/grants.d.ts +28 -3
  50. package/dist/core/grants.js +46 -4
  51. package/dist/core/host-events.js +7 -3
  52. package/dist/core/host-status.js +2 -2
  53. package/dist/core/issue-status.js +4 -3
  54. package/dist/core/listen-address.d.ts +10 -0
  55. package/dist/core/listen-address.js +14 -0
  56. package/dist/core/mark-ready.d.ts +1 -1
  57. package/dist/core/mark-ready.js +1 -1
  58. package/dist/core/mcp-client/client.d.ts +47 -0
  59. package/dist/core/mcp-client/client.js +141 -0
  60. package/dist/core/mcp-client/jsonrpc.d.ts +15 -0
  61. package/dist/core/mcp-client/jsonrpc.js +54 -0
  62. package/dist/core/mcp-client/results.d.ts +13 -0
  63. package/dist/core/mcp-client/results.js +42 -0
  64. package/dist/core/mcp-servers.d.ts +90 -0
  65. package/dist/core/mcp-servers.js +230 -0
  66. package/dist/core/mcp-tools.d.ts +108 -0
  67. package/dist/core/mcp-tools.js +287 -0
  68. package/dist/core/merge-order-check.js +38 -19
  69. package/dist/core/notification-dispatcher.js +2 -1
  70. package/dist/core/power-idle.d.ts +8 -2
  71. package/dist/core/power-idle.js +17 -3
  72. package/dist/core/power.d.ts +5 -0
  73. package/dist/core/power.js +5 -0
  74. package/dist/core/related-pull-requests.js +26 -10
  75. package/dist/core/retention-days.d.ts +5 -0
  76. package/dist/core/retention-days.js +14 -0
  77. package/dist/core/review-fix.js +2 -2
  78. package/dist/core/review-host-tools.js +3 -1
  79. package/dist/core/run-steps/config.d.ts +25 -0
  80. package/dist/core/run-steps/config.js +40 -0
  81. package/dist/core/run-steps/control-chars.d.ts +16 -0
  82. package/dist/core/run-steps/control-chars.js +26 -0
  83. package/dist/core/run-steps/detail.d.ts +32 -0
  84. package/dist/core/run-steps/detail.js +240 -0
  85. package/dist/core/run-steps/extract.d.ts +52 -0
  86. package/dist/core/run-steps/extract.js +467 -0
  87. package/dist/core/run-steps/ingress.d.ts +51 -0
  88. package/dist/core/run-steps/ingress.js +160 -0
  89. package/dist/core/run-steps/last-step.d.ts +15 -0
  90. package/dist/core/run-steps/last-step.js +35 -0
  91. package/dist/core/run-steps/native.d.ts +48 -0
  92. package/dist/core/run-steps/native.js +164 -0
  93. package/dist/core/run-steps/seen.d.ts +16 -0
  94. package/dist/core/run-steps/seen.js +35 -0
  95. package/dist/core/run-steps/summarize.d.ts +57 -0
  96. package/dist/core/run-steps/summarize.js +304 -0
  97. package/dist/core/run-steps/sweep.d.ts +21 -0
  98. package/dist/core/run-steps/sweep.js +41 -0
  99. package/dist/core/run-steps/types.d.ts +89 -0
  100. package/dist/core/run-steps/types.js +39 -0
  101. package/dist/core/run-steps/wire.d.ts +35 -0
  102. package/dist/core/run-steps/wire.js +47 -0
  103. package/dist/core/run-steps/writer.d.ts +49 -0
  104. package/dist/core/run-steps/writer.js +279 -0
  105. package/dist/core/runner.d.ts +70 -16
  106. package/dist/core/runner.js +296 -74
  107. package/dist/core/secret-broker-config.d.ts +2 -0
  108. package/dist/core/secret-broker-config.js +1 -1
  109. package/dist/core/secret-guard.d.ts +5 -2
  110. package/dist/core/secret-guard.js +22 -7
  111. package/dist/core/secrets.d.ts +11 -1
  112. package/dist/core/secrets.js +27 -1
  113. package/dist/core/serializable-retry.d.ts +18 -0
  114. package/dist/core/serializable-retry.js +43 -0
  115. package/dist/core/tool-admin.d.ts +5 -1
  116. package/dist/core/tool-admin.js +7 -2
  117. package/dist/core/tool-names.d.ts +13 -0
  118. package/dist/core/tool-names.js +20 -0
  119. package/dist/core/webhooks.d.ts +4 -0
  120. package/dist/core/webhooks.js +68 -49
  121. package/dist/core/workflow-run-events.js +2 -1
  122. package/dist/generated/prisma/browser.d.ts +39 -0
  123. package/dist/generated/prisma/client.d.ts +39 -0
  124. package/dist/generated/prisma/commonInputTypes.d.ts +80 -50
  125. package/dist/generated/prisma/enums.d.ts +6 -0
  126. package/dist/generated/prisma/enums.js +5 -0
  127. package/dist/generated/prisma/internal/class.d.ts +77 -0
  128. package/dist/generated/prisma/internal/class.js +4 -4
  129. package/dist/generated/prisma/internal/prismaNamespace.d.ts +632 -1
  130. package/dist/generated/prisma/internal/prismaNamespace.js +94 -3
  131. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +98 -0
  132. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +94 -3
  133. package/dist/generated/prisma/models/Agent.d.ts +372 -1
  134. package/dist/generated/prisma/models/AgentMcpServer.d.ts +1412 -0
  135. package/dist/generated/prisma/models/AgentMcpServer.js +1 -0
  136. package/dist/generated/prisma/models/AgentRepository.d.ts +40 -1
  137. package/dist/generated/prisma/models/AuthUser.d.ts +1 -1
  138. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +0 -7
  139. package/dist/generated/prisma/models/CodingProxySession.d.ts +159 -2
  140. package/dist/generated/prisma/models/CodingRun.d.ts +76 -1
  141. package/dist/generated/prisma/models/HostProvider.d.ts +2176 -0
  142. package/dist/generated/prisma/models/HostProvider.js +1 -0
  143. package/dist/generated/prisma/models/HostProviderCredential.d.ts +1285 -0
  144. package/dist/generated/prisma/models/HostProviderCredential.js +1 -0
  145. package/dist/generated/prisma/models/HostProviderOperation.d.ts +1470 -0
  146. package/dist/generated/prisma/models/HostProviderOperation.js +1 -0
  147. package/dist/generated/prisma/models/HostProviderTrustedAccount.d.ts +1145 -0
  148. package/dist/generated/prisma/models/HostProviderTrustedAccount.js +1 -0
  149. package/dist/generated/prisma/models/McpServer.d.ts +1500 -0
  150. package/dist/generated/prisma/models/McpServer.js +1 -0
  151. package/dist/generated/prisma/models/NativeGatewayCall.d.ts +39 -1
  152. package/dist/generated/prisma/models/Principal.d.ts +167 -0
  153. package/dist/generated/prisma/models/ResourceGrant.d.ts +1 -1
  154. package/dist/generated/prisma/models/Run.d.ts +503 -1
  155. package/dist/generated/prisma/models/RunStep.d.ts +1453 -0
  156. package/dist/generated/prisma/models/RunStep.js +1 -0
  157. package/dist/generated/prisma/models/Secret.d.ts +387 -0
  158. package/dist/generated/prisma/models/Tool.d.ts +223 -1
  159. package/dist/generated/prisma/models.d.ts +7 -0
  160. package/dist/help/search.js +12 -3
  161. package/dist/help-index.json +812 -52
  162. package/dist/import/create.js +16 -1
  163. package/dist/import/neutral-schema.d.ts +1 -0
  164. package/dist/import/neutral-schema.js +2 -0
  165. package/dist/mcp/auth/access.d.ts +1 -0
  166. package/dist/mcp/auth/grants-cli.d.ts +6 -4
  167. package/dist/mcp/auth/grants-cli.js +42 -3
  168. package/dist/mcp/auth/resource-server.d.ts +3 -1
  169. package/dist/mcp/auth/resource-server.js +17 -2
  170. package/dist/mcp/context.d.ts +6 -0
  171. package/dist/mcp/index.js +21 -0
  172. package/dist/mcp/tools/agents.js +135 -20
  173. package/dist/mcp/tools/grants.js +66 -28
  174. package/dist/mcp/tools/host-providers.d.ts +2 -0
  175. package/dist/mcp/tools/host-providers.js +215 -0
  176. package/dist/mcp/tools/mcp-servers.d.ts +26 -0
  177. package/dist/mcp/tools/mcp-servers.js +481 -0
  178. package/dist/mcp/tools/power.js +2 -2
  179. package/dist/mcp/tools/repositories.js +50 -10
  180. package/dist/mcp/tools/run-access.d.ts +7 -0
  181. package/dist/mcp/tools/run-access.js +14 -0
  182. package/dist/mcp/tools/run-steps.d.ts +16 -0
  183. package/dist/mcp/tools/run-steps.js +85 -0
  184. package/dist/mcp/tools/runs.js +186 -18
  185. package/dist/mcp/tools/secret-elicitation.d.ts +2 -0
  186. package/dist/mcp/tools/secret-elicitation.js +25 -2
  187. package/dist/mcp/tools/secrets.js +38 -4
  188. package/dist/mcp/tools/tools.d.ts +6 -4
  189. package/dist/mcp/tools/tools.js +40 -8
  190. package/dist/mcp/tools/trigger.js +28 -6
  191. package/dist/mcp/transport/http-limits.d.ts +2 -0
  192. package/dist/mcp/transport/http-limits.js +6 -2
  193. package/dist/mcp/webhooks/ingress.js +10 -0
  194. package/dist/native-worker/gateway-server.d.ts +18 -1
  195. package/dist/native-worker/gateway-server.js +38 -9
  196. package/dist/native-worker/gateway.d.ts +5 -0
  197. package/dist/native-worker/gateway.js +13 -1
  198. package/dist/native-worker/http-server.d.ts +6 -4
  199. package/dist/native-worker/http-server.js +53 -8
  200. package/dist/native-worker/ledger.d.ts +6 -2
  201. package/dist/native-worker/ledger.js +5 -4
  202. package/dist/native-worker/protocol.d.ts +1 -0
  203. package/dist/native-worker/protocol.js +4 -1
  204. package/dist/providers/coding-proxy/capability-hash.d.ts +2 -0
  205. package/dist/providers/coding-proxy/capability-hash.js +5 -0
  206. package/dist/providers/coding-proxy/mcp-route.d.ts +34 -0
  207. package/dist/providers/coding-proxy/mcp-route.js +166 -0
  208. package/dist/providers/coding-proxy/memory-ledger.d.ts +2 -0
  209. package/dist/providers/coding-proxy/memory-ledger.js +16 -0
  210. package/dist/providers/coding-proxy/prisma-ledger.d.ts +1 -0
  211. package/dist/providers/coding-proxy/prisma-ledger.js +36 -2
  212. package/dist/providers/coding-proxy/proxy.d.ts +33 -1
  213. package/dist/providers/coding-proxy/proxy.js +266 -75
  214. package/dist/providers/coding-proxy/run-step-forwarder.d.ts +42 -0
  215. package/dist/providers/coding-proxy/run-step-forwarder.js +206 -0
  216. package/dist/providers/coding-proxy/runtime.d.ts +13 -0
  217. package/dist/providers/coding-proxy/runtime.js +87 -4
  218. package/dist/providers/coding-proxy/server.d.ts +3 -0
  219. package/dist/providers/coding-proxy/server.js +10 -0
  220. package/dist/providers/coding-proxy/types.d.ts +18 -0
  221. package/dist/providers/engine/types.d.ts +26 -0
  222. package/dist/providers/executor/composition.js +5 -0
  223. package/dist/providers/executor/container.d.ts +47 -1
  224. package/dist/providers/executor/container.js +84 -8
  225. package/dist/providers/host-tools/invoke.d.ts +37 -0
  226. package/dist/providers/host-tools/invoke.js +117 -0
  227. package/dist/providers/host-tools/operations.d.ts +65 -0
  228. package/dist/providers/host-tools/operations.js +149 -0
  229. package/dist/providers/host-tools/registry.d.ts +79 -0
  230. package/dist/providers/host-tools/registry.js +362 -0
  231. package/dist/providers/host-tools/request-guard.d.ts +17 -0
  232. package/dist/providers/host-tools/request-guard.js +99 -0
  233. package/dist/providers/host-tools/self-test.d.ts +64 -0
  234. package/dist/providers/host-tools/self-test.js +142 -0
  235. package/dist/providers/jobs/docker-isolation.d.ts +2 -2
  236. package/dist/providers/jobs/docker-isolation.js +30 -8
  237. package/dist/providers/jobs/docker.d.ts +8 -0
  238. package/dist/providers/jobs/docker.js +33 -9
  239. package/dist/providers/jobs/kubernetes-isolation.d.ts +3 -1
  240. package/dist/providers/jobs/kubernetes-isolation.js +15 -2
  241. package/dist/providers/jobs/kubernetes.d.ts +13 -0
  242. package/dist/providers/jobs/kubernetes.js +28 -5
  243. package/dist/providers/jobs/types.d.ts +6 -0
  244. package/dist/providers/review-host/types.d.ts +6 -4
  245. package/dist/providers/review-host/types.js +1 -1
  246. package/dist/providers/vcs/git.d.ts +6 -2
  247. package/dist/providers/vcs/git.js +15 -4
  248. package/dist/providers/vcs/github.d.ts +2 -71
  249. package/dist/providers/vcs/github.js +8 -11
  250. package/dist/providers/vcs/index.d.ts +1 -1
  251. package/dist/providers/vcs/index.js +1 -1
  252. package/dist/providers/vcs/remote.d.ts +4 -0
  253. package/dist/providers/vcs/remote.js +7 -1
  254. package/dist/providers/vcs/routing.d.ts +12 -6
  255. package/dist/providers/vcs/routing.js +21 -6
  256. package/dist/providers/vcs/types.d.ts +71 -3
  257. package/dist/quickstart/index.d.ts +5 -0
  258. package/dist/quickstart/index.js +21 -0
  259. package/dist/quickstart-images.json +1 -1
  260. package/dist/sandbox/eval-core.d.ts +12 -2
  261. package/dist/sandbox/eval-core.js +20 -4
  262. package/dist/sandbox/host-functions.d.ts +4 -0
  263. package/dist/sandbox/host-functions.js +7 -2
  264. package/dist/sandbox/limits.d.ts +4 -1
  265. package/dist/sandbox/limits.js +4 -1
  266. package/dist/sandbox/run-in-sandbox.d.ts +6 -0
  267. package/dist/sandbox/run-in-sandbox.js +14 -2
  268. package/dist/sandbox/safe-fetch.d.ts +2 -0
  269. package/dist/sandbox/safe-fetch.js +1 -1
  270. package/dist/sandbox/secret-broker.d.ts +1 -0
  271. package/dist/sandbox/secret-broker.js +1 -1
  272. package/dist/sandbox/tool-timeout.d.ts +32 -0
  273. package/dist/sandbox/tool-timeout.js +52 -0
  274. package/dist/sandbox/user-tool.d.ts +8 -1
  275. package/dist/sandbox/user-tool.js +9 -3
  276. package/dist/serve.js +26 -18
  277. package/dist/viewer/api-schema.d.ts +66 -0
  278. package/dist/viewer/api-schema.js +31 -0
  279. package/dist/viewer/graph.js +2 -1
  280. package/dist/viewer/openapi.js +2 -1
  281. package/dist/viewer/run-detail.d.ts +2 -0
  282. package/dist/viewer/run-detail.js +26 -1
  283. package/dist/wardby-bin.js +5 -0
  284. package/docs/README.md +11 -1
  285. package/docs/agent-recipes.md +37 -4
  286. package/docs/architecture-runtime.md +1 -1
  287. package/docs/claude-code-plugin.md +208 -0
  288. package/docs/code-review-agents.md +6 -0
  289. package/docs/coding-agent-setup.md +94 -1
  290. package/docs/coding-worker-byo-images.md +4 -2
  291. package/docs/coding-worker-isolation.md +94 -7
  292. package/docs/debugging-agent-runs.md +354 -0
  293. package/docs/getting-started-gke.md +33 -11
  294. package/docs/getting-started-identity-provider.md +43 -37
  295. package/docs/getting-started.md +8 -0
  296. package/docs/host-providers.md +294 -0
  297. package/docs/mcp-servers.md +263 -0
  298. package/docs/native-sandbox.md +31 -9
  299. package/docs/security-deployment.md +161 -31
  300. package/docs/tool-secrets.md +3 -0
  301. package/docs/viewer-api.md +27 -12
  302. package/docs/viewer-api.openapi.yml +78 -2
  303. package/help/admin-viewer.md +5 -0
  304. package/help/agent-recipes.md +33 -2
  305. package/help/brokered-secrets.md +3 -0
  306. package/help/build-claude-code-image.md +1 -1
  307. package/help/claude-code-run-pane.md +63 -0
  308. package/help/deploy-gke.md +5 -0
  309. package/help/errors/coding-mcp-gateway-unavailable.md +46 -0
  310. package/help/errors/coding-mcp-pins-unavailable.md +35 -0
  311. package/help/errors/database-auth-invalid.md +1 -1
  312. package/help/errors/host-provider-error.md +40 -0
  313. package/help/errors/host-tool-failed.md +36 -0
  314. package/help/errors/mcp-call-limit.md +22 -0
  315. package/help/errors/mcp-call-timeout.md +22 -0
  316. package/help/errors/mcp-server-auth-failed.md +22 -0
  317. package/help/errors/mcp-server-credentials-unavailable.md +45 -0
  318. package/help/errors/mcp-server-error.md +28 -0
  319. package/help/errors/mcp-server-unreachable.md +22 -0
  320. package/help/errors/mcp-servers-off.md +21 -0
  321. package/help/errors/mcp-tool-not-allowed.md +26 -0
  322. package/help/errors/mcp-tool-removed.md +22 -0
  323. package/help/errors/mcp-unavailable.md +25 -0
  324. package/help/errors/native-sandbox-capacity.md +1 -1
  325. package/help/errors/native-sandbox-deadline-exceeded.md +1 -1
  326. package/help/errors/native-sandbox-docker-failed.md +1 -1
  327. package/help/errors/native-sandbox-gateway-error.md +1 -1
  328. package/help/errors/native-sandbox-gateway-unavailable.md +1 -1
  329. package/help/errors/native-sandbox-image-not-pinned.md +1 -1
  330. package/help/errors/native-sandbox-isolation-mismatch.md +1 -1
  331. package/help/errors/native-sandbox-network-unenforced.md +1 -1
  332. package/help/errors/native-sandbox-requires-catalog.md +1 -1
  333. package/help/errors/native-sandbox-unavailable.md +1 -1
  334. package/help/errors/native-sandbox-warm-delivery-failed.md +1 -1
  335. package/help/errors/native-sandbox-worker-exited.md +1 -1
  336. package/help/errors/native-sandbox-worker-lost.md +1 -1
  337. package/help/errors/native-sandbox-worker-unready.md +1 -1
  338. package/help/errors/repository-not-listed.md +36 -0
  339. package/help/errors/repository-required.md +36 -0
  340. package/help/errors/tool-timeout.md +38 -0
  341. package/help/host-providers.md +40 -0
  342. package/help/identity-and-access.md +4 -1
  343. package/help/low-power-mode.md +19 -8
  344. package/help/mcp-servers.md +73 -0
  345. package/help/mcp.md +9 -2
  346. package/help/native-capabilities.md +27 -1
  347. package/help/native-sandbox.md +1 -1
  348. package/help/operating-agents.md +16 -0
  349. package/help/related-pull-requests.md +7 -3
  350. package/help/repo-instructions-and-skills.md +3 -1
  351. package/help/resume-runs-locally.md +7 -0
  352. package/help/run-steps.md +140 -0
  353. package/help/stop-run.md +1 -1
  354. package/help/troubleshooting/coding-workers.md +9 -1
  355. package/help/troubleshooting/debugging-agent-runs.md +29 -0
  356. package/package.json +2 -1
  357. package/prisma/migrations/20261102000000_host_providers/migration.sql +56 -0
  358. package/prisma/migrations/20261104000000_coding_agent_repository_list/migration.sql +5 -0
  359. package/prisma/migrations/20261106000000_tool_timeout/migration.sql +4 -0
  360. package/prisma/migrations/20261107000000_mcp_servers/migration.sql +33 -0
  361. package/prisma/migrations/20261108000000_coding_mcp/migration.sql +5 -0
  362. package/prisma/migrations/20261109000000_task_run_index/migration.sql +3 -0
  363. package/prisma/migrations/20261110000000_run_steps/migration.sql +26 -0
  364. package/prisma/migrations/20261111000000_run_steps_viewer_notify/migration.sql +59 -0
  365. package/prisma/migrations/20261112000000_run_steps_detail/migration.sql +9 -0
  366. package/prisma/schema.prisma +211 -14
  367. package/scripts/git-askpass.sh +1 -1
@@ -3,6 +3,8 @@
3
3
  * attachments, secrets, datastores, webhooks, budget groups) to the database
4
4
  * from a validated bundle + reconciliation.
5
5
  */
6
+ import { toolTimeoutProblem } from "../sandbox/tool-timeout.js";
7
+ import { loadToolMaxTimeoutMs } from "../config/tool-timeout.js";
6
8
  import { Prisma } from "#prisma";
7
9
  import { scheduleStartFields } from "../core/schedule-start.js";
8
10
  import { createSecret, attachSecret } from "../core/secrets.js";
@@ -12,7 +14,7 @@ import { SecretCheckUnavailableError, SecretInValueError, createDbSecretWriteGua
12
14
  import { createWebhook } from "../core/webhooks.js";
13
15
  import { deriveJsonSchema } from "../sandbox/zod-params.js";
14
16
  import { toolSubject, zod3ToolWarnings } from "../core/zod3-window.js";
15
- import { findSameNamedAttachedTool, reservedToolNameReason } from "../core/tool-names.js";
17
+ import { findSameNamedAttachedTool, findSameNamedMcpTool, reservedToolNameReason } from "../core/tool-names.js";
16
18
  import { ToolCapabilitiesPatchSchema, FETCH_WILDCARD } from "../sandbox/tool-capabilities.js";
17
19
  import { PostgresDatastore } from "../providers/datastore/postgres.js";
18
20
  import { decryptTransferEnvelope } from "../providers/secrets/transfer-envelope.js";
@@ -70,6 +72,13 @@ export async function createFromBundle(bundle, recon, opts) {
70
72
  warnings.push(`tool ${t.name}: failed to derive JSON schema, skipping`);
71
73
  continue;
72
74
  }
75
+ const timeoutProblem = t.timeoutMs === undefined || t.timeoutMs === null
76
+ ? undefined
77
+ : toolTimeoutProblem(t.timeoutMs, loadToolMaxTimeoutMs());
78
+ if (timeoutProblem) {
79
+ warnings.push(`tool ${t.name}: ${timeoutProblem} Skipping`);
80
+ continue;
81
+ }
73
82
  // Names are unique per owner: reuse the target owner's own same-named
74
83
  // tool (what upsert-by-name used to do), never another owner's. A
75
84
  // compound unique with a nullable column can't key an upsert, hence
@@ -83,6 +92,7 @@ export async function createFromBundle(bundle, recon, opts) {
83
92
  code: t.code,
84
93
  jsonSchema: schema.value,
85
94
  ownerId,
95
+ ...(t.timeoutMs !== undefined && t.timeoutMs !== null ? { timeoutMs: t.timeoutMs } : {}),
86
96
  },
87
97
  }));
88
98
  toolIdMap.set(t.name, tool.id);
@@ -180,6 +190,11 @@ export async function createFromBundle(bundle, recon, opts) {
180
190
  warnings.push(`agent-tool ${at.agentName}/${at.toolName}: skipped — the agent already has a different tool with the same name (${clash.id})`);
181
191
  continue;
182
192
  }
193
+ const mcpClash = await findSameNamedMcpTool(db, agentId, eff(at.toolName));
194
+ if (mcpClash) {
195
+ warnings.push(`agent-tool ${at.agentName}/${at.toolName}: skipped — the agent already has a tool with this name from MCP server "${mcpClash.serverName}"`);
196
+ continue;
197
+ }
183
198
  const caps = capsPatch.data;
184
199
  // The importing operator is trusted with the database, so on an agent
185
200
  // this import owns it grants the bundle's capabilities in the owner's
@@ -68,6 +68,7 @@ export declare const NeutralToolSchema: z.ZodObject<{
68
68
  jsonSchema: z.ZodDefault<z.ZodNullable<z.ZodUnknown>>;
69
69
  code: z.ZodString;
70
70
  secretSchema: z.ZodDefault<z.ZodString>;
71
+ timeoutMs: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
71
72
  }, z.core.$strip>;
72
73
  export type NeutralTool = z.infer<typeof NeutralToolSchema>;
73
74
  export declare const NeutralAgentToolSchema: z.ZodObject<{
@@ -53,6 +53,8 @@ export const NeutralToolSchema = z.object({
53
53
  jsonSchema: z.unknown().nullable().default(null), // ignored; we re-derive (ruling 2)
54
54
  code: z.string(),
55
55
  secretSchema: z.string().default(""),
56
+ /** The tool's own time limit (ms); absent or null keeps the default. Checked against WARDBY_TOOL_MAX_TIMEOUT_MS on import. */
57
+ timeoutMs: z.number().int().nullable().optional(),
56
58
  });
57
59
  export const NeutralAgentToolSchema = z.object({
58
60
  agentName: z.string(),
@@ -60,6 +60,7 @@ export declare function requireAgentAccess(ctx: McpRequestContext, id: string, r
60
60
  budgetGroupId: string | null;
61
61
  memoryEnabled: boolean;
62
62
  effort: string | null;
63
+ runSteps: import("#prisma").RunStepsLevel | null;
63
64
  };
64
65
  access: AgentAccess;
65
66
  }>;
@@ -77,16 +77,18 @@ export interface MigrationReport {
77
77
  }
78
78
  export declare function migrationReport(db: ReportDb): Promise<MigrationReport>;
79
79
  export declare function formatMigrationReport(report: MigrationReport): string;
80
+ /** A binding that belongs to its resource's owner; for an MCP server, boundName is the server name. */
81
+ export type BindingKind = "secret" | "datastore" | "mcp_server";
80
82
  export interface AdoptedAgent {
81
83
  agentId: string;
82
84
  name: string;
83
85
  bindingsRemoved: {
84
- kind: "secret" | "datastore";
86
+ kind: BindingKind;
85
87
  boundName: string;
86
88
  resourceId: string;
87
89
  }[];
88
90
  bindingsKept: {
89
- kind: "secret" | "datastore";
91
+ kind: BindingKind;
90
92
  boundName: string;
91
93
  }[];
92
94
  capabilitiesStamped: string[];
@@ -126,7 +128,7 @@ export declare function formatAdoptResult(result: AdoptResult): string;
126
128
  export interface PruneResult {
127
129
  dryRun: boolean;
128
130
  removed: {
129
- kind: "secret" | "datastore";
131
+ kind: BindingKind;
130
132
  agentId: string;
131
133
  agentName: string;
132
134
  boundName: string;
@@ -134,7 +136,7 @@ export interface PruneResult {
134
136
  resourceOwnerId: string | null;
135
137
  }[];
136
138
  }
137
- /** Deletes cross-owner secret/datastore bindings on owned agents, in one transaction. */
139
+ /** Deletes cross-owner secret/datastore/MCP server bindings on owned agents, in one transaction. */
138
140
  export declare function pruneBindings(db: PrismaClient, opts: {
139
141
  dryRun: boolean;
140
142
  }): Promise<PruneResult>;
@@ -14,13 +14,13 @@
14
14
  * owner's own bindings, deleting the rest, and stamping the new owner's
15
15
  * consent on attachments of its own tools. Other attachments stay inert
16
16
  * and are printed with the attach_tool call that re-grants them.
17
- * - prune-bindings deletes the secret/datastore bindings on owned agents
17
+ * - prune-bindings deletes the secret/datastore/MCP server bindings on owned agents
18
18
  * whose resource another principal owns (inert at run time since the
19
19
  * grants release) and prints each one: the "removed and listed" record.
20
20
  */
21
21
  import { parseArgs } from "node:util";
22
22
  import { Prisma } from "#prisma";
23
- import { canDelegate } from "../../core/grants.js";
23
+ import { canDelegate, filterUnusableMcpServers } from "../../core/grants.js";
24
24
  import { resolvePrincipal } from "./principal.js";
25
25
  const USAGE = "Use grants migration-report [--json] | grants adopt-public --owner <subject> [--dry-run] [--keep-everyone-execute] | grants prune-bindings [--dry-run].";
26
26
  /** The attach_tool call (MCP) that re-grants an attachment's capabilities, for its owner to review and run. */
@@ -276,8 +276,14 @@ export async function adoptPublic(db, opts) {
276
276
  include: { datastore: { select: { ownerId: true } } },
277
277
  orderBy: { boundName: "asc" },
278
278
  });
279
+ const mcpServers = await tx.agentMcpServer.findMany({
280
+ where: { agentId: id },
281
+ include: { server: { select: { id: true, name: true, ownerId: true } } },
282
+ orderBy: { serverId: "asc" },
283
+ });
279
284
  const foreignSecrets = secrets.filter((b) => b.secret.ownerId !== owner.id);
280
285
  const foreignDatastores = datastores.filter((b) => b.datastore.ownerId !== owner.id);
286
+ const foreignMcpServers = await filterUnusableMcpServers(tx, () => owner.id, mcpServers);
281
287
  for (const b of foreignSecrets) {
282
288
  await tx.agentSecret.delete({ where: { agentId_secretId: { agentId: id, secretId: b.secretId } } });
283
289
  }
@@ -286,6 +292,9 @@ export async function adoptPublic(db, opts) {
286
292
  where: { agentId_datastoreId: { agentId: id, datastoreId: b.datastoreId } },
287
293
  });
288
294
  }
295
+ for (const b of foreignMcpServers) {
296
+ await tx.agentMcpServer.delete({ where: { agentId_serverId: { agentId: id, serverId: b.serverId } } });
297
+ }
289
298
  // Only the tool's owner could attach its private tool to a public
290
299
  // agent or change that attachment's capabilities, so those carry
291
300
  // the new owner's consent. Everything else stays inert.
@@ -350,6 +359,11 @@ export async function adoptPublic(db, opts) {
350
359
  boundName: b.boundName,
351
360
  resourceId: b.datastoreId,
352
361
  })),
362
+ ...foreignMcpServers.map((b) => ({
363
+ kind: "mcp_server",
364
+ boundName: b.server.name,
365
+ resourceId: b.serverId,
366
+ })),
353
367
  ],
354
368
  bindingsKept: [
355
369
  ...secrets
@@ -358,6 +372,9 @@ export async function adoptPublic(db, opts) {
358
372
  ...datastores
359
373
  .filter((b) => b.datastore.ownerId === owner.id)
360
374
  .map((b) => ({ kind: "datastore", boundName: b.boundName })),
375
+ ...mcpServers
376
+ .filter((b) => !foreignMcpServers.includes(b))
377
+ .map((b) => ({ kind: "mcp_server", boundName: b.server.name })),
361
378
  ],
362
379
  capabilitiesStamped: own.map((at) => at.tool.name),
363
380
  foreignTools: attachments
@@ -411,7 +428,7 @@ export function formatAdoptResult(result) {
411
428
  }
412
429
  return lines.join("\n");
413
430
  }
414
- /** Deletes cross-owner secret/datastore bindings on owned agents, in one transaction. */
431
+ /** Deletes cross-owner secret/datastore/MCP server bindings on owned agents, in one transaction. */
415
432
  export async function pruneBindings(db, opts) {
416
433
  return db.$transaction(async (tx) => {
417
434
  const secrets = await tx.agentSecret.findMany({
@@ -424,8 +441,17 @@ export async function pruneBindings(db, opts) {
424
441
  include: { agent: { select: { name: true, ownerId: true } }, datastore: { select: { ownerId: true } } },
425
442
  orderBy: [{ agentId: "asc" }, { boundName: "asc" }],
426
443
  });
444
+ const mcpServers = await tx.agentMcpServer.findMany({
445
+ where: { agent: { ownerId: { not: null } } },
446
+ include: {
447
+ agent: { select: { name: true, ownerId: true } },
448
+ server: { select: { id: true, name: true, ownerId: true } },
449
+ },
450
+ orderBy: [{ agentId: "asc" }, { serverId: "asc" }],
451
+ });
427
452
  const foreignSecrets = secrets.filter((b) => b.secret.ownerId !== b.agent.ownerId);
428
453
  const foreignDatastores = datastores.filter((b) => b.datastore.ownerId !== b.agent.ownerId);
454
+ const foreignMcpServers = await filterUnusableMcpServers(tx, (b) => b.agent.ownerId, mcpServers);
429
455
  if (!opts.dryRun) {
430
456
  for (const b of foreignSecrets) {
431
457
  await tx.agentSecret.delete({ where: { agentId_secretId: { agentId: b.agentId, secretId: b.secretId } } });
@@ -435,6 +461,11 @@ export async function pruneBindings(db, opts) {
435
461
  where: { agentId_datastoreId: { agentId: b.agentId, datastoreId: b.datastoreId } },
436
462
  });
437
463
  }
464
+ for (const b of foreignMcpServers) {
465
+ await tx.agentMcpServer.delete({
466
+ where: { agentId_serverId: { agentId: b.agentId, serverId: b.serverId } },
467
+ });
468
+ }
438
469
  }
439
470
  return {
440
471
  dryRun: opts.dryRun,
@@ -455,6 +486,14 @@ export async function pruneBindings(db, opts) {
455
486
  resourceId: b.datastoreId,
456
487
  resourceOwnerId: b.datastore.ownerId,
457
488
  })),
489
+ ...foreignMcpServers.map((b) => ({
490
+ kind: "mcp_server",
491
+ agentId: b.agentId,
492
+ agentName: b.agent.name,
493
+ boundName: b.server.name,
494
+ resourceId: b.serverId,
495
+ resourceOwnerId: b.server.ownerId,
496
+ })),
458
497
  ],
459
498
  };
460
499
  }, { isolationLevel: Prisma.TransactionIsolationLevel.Serializable });
@@ -19,7 +19,9 @@ export declare const SCOPES_SUPPORTED: string[];
19
19
  * runs next to every coding run that names an entry; admin:view reads every
20
20
  * owner's runs (the admin viewer API); models:admin changes the model catalog,
21
21
  * which prices every principal's runs; power:manage scales the shared coding
22
- * proxy and native gateway to zero (power_sleep) and reads their state.
22
+ * proxy and native gateway to zero (power_sleep) and reads their state;
23
+ * hosts:admin registers host providers, whose approved tools run in the push
24
+ * and pull request flow.
23
25
  * A token scope only DELEGATES — it never authorizes on its own:
24
26
  * requireScope/requireAnyScope honour one only when one of the caller's
25
27
  * roles (McpRequestContext.roles, resolved live per request) grants it.
@@ -30,6 +30,9 @@ export const SCOPES_SUPPORTED = [
30
30
  // Scale the coding proxy and native gateway to zero now (power_sleep) and
31
31
  // read their state (power_status); low-power mode only (docs/getting-started-gke.md).
32
32
  "power:manage",
33
+ // Register host providers and approve their tools (docs/host-providers.md).
34
+ // Bound tools decide who has permission and who wrote a comment.
35
+ "hosts:admin",
33
36
  ];
34
37
  /**
35
38
  * Scopes whose operations reach beyond the caller's own (or public)
@@ -40,7 +43,9 @@ export const SCOPES_SUPPORTED = [
40
43
  * runs next to every coding run that names an entry; admin:view reads every
41
44
  * owner's runs (the admin viewer API); models:admin changes the model catalog,
42
45
  * which prices every principal's runs; power:manage scales the shared coding
43
- * proxy and native gateway to zero (power_sleep) and reads their state.
46
+ * proxy and native gateway to zero (power_sleep) and reads their state;
47
+ * hosts:admin registers host providers, whose approved tools run in the push
48
+ * and pull request flow.
44
49
  * A token scope only DELEGATES — it never authorizes on its own:
45
50
  * requireScope/requireAnyScope honour one only when one of the caller's
46
51
  * roles (McpRequestContext.roles, resolved live per request) grants it.
@@ -52,16 +57,26 @@ export const PRIVILEGED_SCOPES = [
52
57
  "admin:view",
53
58
  "models:admin",
54
59
  "power:manage",
60
+ "hosts:admin",
55
61
  ];
56
62
  /**
57
63
  * The built-in roles and the permissions (privileged scope names) each
58
64
  * grants. No roles = member: every non-privileged scope, nothing privileged.
59
65
  */
60
66
  export const ROLE_PERMISSIONS = {
61
- admin: ["agents:admin", "packages:approve", "services:manage", "admin:view", "models:admin", "power:manage"],
67
+ admin: [
68
+ "agents:admin",
69
+ "packages:approve",
70
+ "services:manage",
71
+ "admin:view",
72
+ "models:admin",
73
+ "power:manage",
74
+ "hosts:admin",
75
+ ],
62
76
  "package-approver": ["packages:approve"],
63
77
  "service-manager": ["services:manage"],
64
78
  "model-manager": ["models:admin"],
79
+ "host-manager": ["hosts:admin"],
65
80
  };
66
81
  export const ROLE_NAMES = Object.keys(ROLE_PERMISSIONS);
67
82
  export function isRoleName(name) {
@@ -11,10 +11,12 @@ import type { Principal, PrismaClient } from "#prisma";
11
11
  import type { RequestStateAccessor } from "@modelcontextprotocol/server";
12
12
  import type { ProviderRegistry } from "../providers/index.js";
13
13
  import type { RepoAccessGate } from "../core/repo-access.js";
14
+ import type { RunStepSink } from "../core/run-steps/types.js";
14
15
  import type { IssueTrackerRegistry } from "../providers/issue-tracker/types.js";
15
16
  import type { HostUserAuthorizerRegistry, ReviewHostRegistry } from "../providers/review-host/types.js";
16
17
  import type { Power } from "../core/power.js";
17
18
  import type { ChatProviderRegistry } from "../providers/chat/types.js";
19
+ import type { safeFetch } from "../sandbox/safe-fetch.js";
18
20
  export type McpProviders = Pick<ProviderRegistry, "llm" | "engine" | "datastore" | "secrets" | "executor" | "memory"> & {
19
21
  reviewHosts?: ReviewHostRegistry;
20
22
  /** Issue trackers (Jira); empty or absent = no issue-tracker integration. */
@@ -31,6 +33,10 @@ export type McpProviders = Pick<ProviderRegistry, "llm" | "engine" | "datastore"
31
33
  repoAccess?: RepoAccessGate;
32
34
  /** Low-power mode (scale idle proxy/gateway to zero); absent = DISABLED_POWER. */
33
35
  power?: Power;
36
+ /** Overrides the outbound call to remote MCP servers (register/update/refresh_mcp_server) — tests only. */
37
+ sandboxFetch?: typeof safeFetch;
38
+ /** Records runs' steps; also what the run-steps listener writes through. */
39
+ runSteps?: RunStepSink;
34
40
  };
35
41
  export interface McpRequestContext {
36
42
  principal: Principal;
package/dist/mcp/index.js CHANGED
@@ -13,6 +13,9 @@
13
13
  * missing `AUTH_JWKS_URI`/`AUTH_SIGNING_KEY` a deployment running stdio-only
14
14
  * never needed to set.
15
15
  */
16
+ import { loadToolMaxTimeoutMs } from "../config/tool-timeout.js";
17
+ import { loadMcpServersMode } from "../config/mcp-servers.js";
18
+ import { loadMcpMaxCallsPerRun } from "../config/mcp-call-limit.js";
16
19
  import { startupTestSimulators } from "../config/test-simulators.js";
17
20
  import { loadProviderConfig, loadMcpConfig, loadShutdownDrainSeconds, loadAuthConfig, loadGitHubEventConfig, loadJiraConfig, loadGitHubVcsConfig, loadBlobStoreConfig, } from "../config/providers.js";
18
21
  import { prisma } from "../core/db.js";
@@ -62,6 +65,8 @@ import { registerCostReportTools } from "./tools/cost-report.js";
62
65
  import { registerDatastoreTools } from "./tools/datastore.js";
63
66
  import { registerSubAgentTools } from "./tools/subagents.js";
64
67
  import { registerGrantTools } from "./tools/grants.js";
68
+ import { registerHostProviderTools } from "./tools/host-providers.js";
69
+ import { registerMcpServerTools } from "./tools/mcp-servers.js";
65
70
  import { registerRepositoryTools } from "./tools/repositories.js";
66
71
  import { registerIssueProjectTools } from "./tools/issue-projects.js";
67
72
  import { registerNotificationChannelTools } from "./tools/notification-channels.js";
@@ -72,6 +77,9 @@ import { registerSecretsTools } from "./tools/secrets.js";
72
77
  import { registerWebhookTools } from "./tools/webhooks.js";
73
78
  import { STDIO_SECRET_PATH, secretFormRoute } from "./tools/secret-elicitation-server.js";
74
79
  import { createStdioLinkHost } from "./transport/stdio-link-host.js";
80
+ import { loadRunStepRetentionDays, loadRunStepsLevel } from "../core/run-steps/config.js";
81
+ import { buildRunStepWriter } from "../core/run-steps/writer.js";
82
+ import { registerRunStepsTool } from "./tools/run-steps.js";
75
83
  import { registerRunTranscriptTool } from "./tools/run-transcript.js";
76
84
  import { handleRunTranscriptDownload, RUN_TRANSCRIPT_DOWNLOAD_PATH } from "./tools/run-transcript-download.js";
77
85
  import { createBlobStore } from "../providers/storage/index.js";
@@ -134,12 +142,15 @@ export function registerAllTools(mcp, opts) {
134
142
  blobStoreConfigured: runTranscriptUrl !== undefined && opts.blobStoreConfigured === true,
135
143
  audience: opts.runTranscriptAudience ?? "http",
136
144
  });
145
+ registerRunStepsTool(mcp, { level: loadRunStepsLevel(), retentionDays: loadRunStepRetentionDays() });
137
146
  registerStopRunTool(mcp);
138
147
  registerCostReportTools(mcp);
139
148
  registerDatastoreTools(mcp);
140
149
  registerSubAgentTools(mcp);
141
150
  registerGrantTools(mcp);
142
151
  registerRepositoryTools(mcp);
152
+ registerHostProviderTools(mcp);
153
+ registerMcpServerTools(mcp);
143
154
  registerIssueProjectTools(mcp);
144
155
  registerNotificationChannelTools(mcp);
145
156
  registerHostAccountTools(mcp);
@@ -164,6 +175,8 @@ export function buildMcpProviders() {
164
175
  const secretGuard = createDbSecretWriteGuard(prisma, secrets);
165
176
  const datastore = guardDatastore(new PostgresDatastore(prisma, secrets), secretGuard);
166
177
  const memory = guardAgentMemory(new PostgresAgentMemory(prisma), secretGuard);
178
+ // The one run-steps writer of this process (WARDBY_RUN_STEPS, RUN_STEP_RETENTION_DAYS; invalid stops start-up).
179
+ const runSteps = buildRunStepWriter(prisma, secrets);
167
180
  const reviewHosts = buildReviewHosts(process.env, prisma);
168
181
  const issueTrackers = buildIssueTrackers();
169
182
  const hostUserAuthorizers = buildHostUserAuthorizers();
@@ -192,7 +205,12 @@ export function buildMcpProviders() {
192
205
  reviewHosts,
193
206
  issueTrackers,
194
207
  repoAccess,
208
+ runSteps,
195
209
  };
210
+ // Read again at each tool call; checked here so a bad value stops start-up, not every run.
211
+ loadToolMaxTimeoutMs();
212
+ loadMcpServersMode();
213
+ loadMcpMaxCallsPerRun();
196
214
  const nativeExecutor = buildExecutor(providerConfig, nativeProviders, prisma);
197
215
  // One Power for the process, shared by both executors (wake) and the scheduler leader (sleep).
198
216
  const power = buildPower({ env: process.env, db: prisma });
@@ -221,6 +239,7 @@ export function buildMcpProviders() {
221
239
  repoAccess,
222
240
  chat,
223
241
  power,
242
+ runSteps,
224
243
  },
225
244
  };
226
245
  }
@@ -312,6 +331,7 @@ export async function startMcp(options = {}) {
312
331
  close: async () => {
313
332
  await closeQuietly(stdio.close(), "stdio transport close");
314
333
  await closeQuietly(providers.executor.close?.(), "executor close");
334
+ await providers.runSteps?.flush?.();
315
335
  modelCatalog.close();
316
336
  },
317
337
  };
@@ -449,6 +469,7 @@ export async function startMcp(options = {}) {
449
469
  // closes under them; a run abandoned here is lost, never resumed.
450
470
  await waitForInFlightRuns(drainSeconds * 1000);
451
471
  await closeQuietly(providers.executor.close?.(), "executor close");
472
+ await providers.runSteps?.flush?.();
452
473
  modelCatalog.close();
453
474
  },
454
475
  };