@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
@@ -115,11 +115,15 @@ export declare class PrismaGatewayLedger {
115
115
  setDelegation(sessionId: string, callId: string, state: {
116
116
  status: "pending" | "waiting_budget";
117
117
  childAgentId: string;
118
+ childRepository?: string;
118
119
  childRunId?: string;
119
120
  }): Promise<void>;
120
121
  delegation(sessionId: string, callId: string): Promise<DelegationState | null>;
121
- /** The sub-agents other delegations of this run are waiting for budget to start. */
122
- waitingChildAgentIds(sessionId: string, exceptCallId: string): Promise<string[]>;
122
+ /** The sub-agents (and repositories, null = the child's default) other delegations of this run wait on budget to start. */
123
+ waitingDelegations(sessionId: string, exceptCallId: string): Promise<{
124
+ childAgentId: string;
125
+ childRepository: string | null;
126
+ }[]>;
123
127
  /** Delegations of this session whose child run is started and not yet reported. */
124
128
  openDelegationChildren(sessionId: string): Promise<string[]>;
125
129
  }
@@ -202,6 +202,7 @@ export class PrismaGatewayLedger {
202
202
  data: {
203
203
  status: state.status,
204
204
  childAgentId: state.childAgentId,
205
+ ...(state.childRepository ? { childRepository: state.childRepository } : {}),
205
206
  ...(state.childRunId ? { childRunId: state.childRunId } : {}),
206
207
  },
207
208
  });
@@ -213,13 +214,13 @@ export class PrismaGatewayLedger {
213
214
  const status = row.status === "waiting_budget" ? "waiting_budget" : row.status === "completed" ? "completed" : "pending";
214
215
  return { status, childRunId: row.childRunId, childAgentId: row.childAgentId, createdAt: row.createdAt };
215
216
  }
216
- /** The sub-agents other delegations of this run are waiting for budget to start. */
217
- async waitingChildAgentIds(sessionId, exceptCallId) {
217
+ /** The sub-agents (and repositories, null = the child's default) other delegations of this run wait on budget to start. */
218
+ async waitingDelegations(sessionId, exceptCallId) {
218
219
  const rows = await this.db.nativeGatewayCall.findMany({
219
220
  where: { sessionId, status: "waiting_budget", callId: { not: exceptCallId }, childAgentId: { not: null } },
220
- select: { childAgentId: true },
221
+ select: { childAgentId: true, childRepository: true },
221
222
  });
222
- return rows.map((row) => row.childAgentId);
223
+ return rows.map((row) => ({ childAgentId: row.childAgentId, childRepository: row.childRepository }));
223
224
  }
224
225
  /** Delegations of this session whose child run is started and not yet reported. */
225
226
  async openDelegationChildren(sessionId) {
@@ -145,6 +145,7 @@ export declare const WorkerInputSchema: z.ZodObject<{
145
145
  userTools: z.ZodRecord<z.ZodString, z.ZodObject<{
146
146
  code: z.ZodString;
147
147
  paramsZod: z.ZodString;
148
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
148
149
  }, z.core.$strict>>;
149
150
  runsConcurrently: z.ZodArray<z.ZodString>;
150
151
  pricing: z.ZodObject<{
@@ -125,7 +125,10 @@ const LoadedToolSchema = z
125
125
  .object({ name: z.string(), description: z.string(), jsonSchema: z.record(z.string(), z.unknown()) })
126
126
  .strict();
127
127
  /** A user tool as the worker runs it: code and schema only. Capabilities stay on the gateway. */
128
- const WorkerUserToolSchema = z.object({ code: z.string(), paramsZod: z.string() }).strict();
128
+ /** `timeoutMs`: the tool's time limit for this run, already capped by the server; absent = the default. */
129
+ const WorkerUserToolSchema = z
130
+ .object({ code: z.string(), paramsZod: z.string(), timeoutMs: z.number().int().positive().optional() })
131
+ .strict();
129
132
  const PricingSchema = z
130
133
  .object({
131
134
  provider: z.string(),
@@ -0,0 +1,2 @@
1
+ /** SHA-256 (base64url) of a run credential: the proxy stores only this, never the value. */
2
+ export declare function capabilityHash(capability: string): string;
@@ -0,0 +1,5 @@
1
+ import { createHash } from "node:crypto";
2
+ /** SHA-256 (base64url) of a run credential: the proxy stores only this, never the value. */
3
+ export function capabilityHash(capability) {
4
+ return createHash("sha256").update(capability).digest("base64url");
5
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The coding proxy's /mcp route (remote MCP servers, phase 2): the worker's MCP server URL. It
3
+ * checks the run's MCP token (`rmt_…`, WARDBY_MCP_TOKEN in the worker) against the proxy session,
4
+ * then forwards the JSON-RPC body unchanged, with the same Authorization, to the native gateway's
5
+ * /coding-mcp route (WARDBY_MCP_GATEWAY_URL), which checks the token again and runs the call. The
6
+ * proxy never sees an MCP server URL or secret; the gateway redacts results before they get here.
7
+ *
8
+ * Secrets: the token is only hashed and forwarded, never logged or echoed. The route's log line
9
+ * carries the session id, a sanitized JSON-RPC method, the status and a fixed reason code only:
10
+ * never the body, the token or an error's text. Every body this route writes is fixed text or the
11
+ * gateway's answer, unchanged.
12
+ */
13
+ import type { IncomingMessage, ServerResponse } from "node:http";
14
+ import type { ProxyLedger } from "./types.js";
15
+ export declare const MCP_ROUTE_PATH = "/mcp";
16
+ /** The longest a forwarded call may take, when the session's deadline is later. */
17
+ export declare const MCP_FORWARD_MAX_MS: number;
18
+ export declare const MCP_UNAVAILABLE_MESSAGE = "MCP tools aren't available on this server.";
19
+ /**
20
+ * A JSON-RPC method as the log may carry it: its first 64 characters when they are letters, `/`
21
+ * and `_` only, else "other". Anything that starts like an MCP token is "other" too.
22
+ */
23
+ export declare function mcpLogMethod(value: unknown): string;
24
+ export interface McpRouteOptions {
25
+ ledger: Pick<ProxyLedger, "findSessionByMcpTokenHash">;
26
+ /** The native gateway's base URL; without one, /mcp answers 503 mcp_unavailable. */
27
+ gatewayUrl: string | undefined;
28
+ fetchImpl?: typeof fetch;
29
+ now?: () => Date;
30
+ log?: {
31
+ info(fields: Record<string, unknown>, message: string): void;
32
+ };
33
+ }
34
+ export declare function createMcpRoute(options: McpRouteOptions): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
@@ -0,0 +1,166 @@
1
+ import { isMcpToken, mcpTokenHash, MCP_TOKEN_REQUIRED_MESSAGE } from "../../coding/mcp-token.js";
2
+ import { logger } from "../../core/logger.js";
3
+ import { HTTP_LIMITS, HttpBoundaryError, readBodyBytes } from "../../mcp/transport/http-limits.js";
4
+ export const MCP_ROUTE_PATH = "/mcp";
5
+ /** The gateway's route this one forwards to. */
6
+ const GATEWAY_PATH = "/coding-mcp";
7
+ /** The longest a forwarded call may take, when the session's deadline is later. */
8
+ export const MCP_FORWARD_MAX_MS = 5 * 60_000;
9
+ /** The largest gateway answer relayed (a tool result is text the model reads; same as a model request). */
10
+ const MAX_GATEWAY_RESPONSE_BYTES = 8 * 1024 * 1024;
11
+ export const MCP_UNAVAILABLE_MESSAGE = "MCP tools aren't available on this server.";
12
+ const MCP_UNREACHABLE_MESSAGE = "MCP tools can't be reached right now.";
13
+ const LOG_METHOD = /^[A-Za-z/_]+$/;
14
+ /**
15
+ * A JSON-RPC method as the log may carry it: its first 64 characters when they are letters, `/`
16
+ * and `_` only, else "other". Anything that starts like an MCP token is "other" too.
17
+ */
18
+ export function mcpLogMethod(value) {
19
+ if (typeof value !== "string")
20
+ return "other";
21
+ const method = value.slice(0, 64);
22
+ return LOG_METHOD.test(method) && !method.includes("rmt_") ? method : "other";
23
+ }
24
+ function methodOf(body) {
25
+ try {
26
+ const message = JSON.parse(body.toString("utf8"));
27
+ return mcpLogMethod(message?.method);
28
+ }
29
+ catch {
30
+ return "other";
31
+ }
32
+ }
33
+ class GatewayError extends Error {
34
+ reason;
35
+ constructor(reason) {
36
+ super(reason);
37
+ this.reason = reason;
38
+ }
39
+ }
40
+ const JSON_HEADERS = { "content-type": "application/json", "cache-control": "no-store" };
41
+ const rpcError = (code, message) => JSON.stringify({ jsonrpc: "2.0", id: null, error: { code, message } });
42
+ async function readGatewayBody(response) {
43
+ const chunks = [];
44
+ let size = 0;
45
+ if (!response.body)
46
+ return Buffer.alloc(0);
47
+ for await (const chunk of response.body) {
48
+ size += chunk.byteLength;
49
+ if (size > MAX_GATEWAY_RESPONSE_BYTES) {
50
+ void response.body.cancel().catch(() => undefined);
51
+ throw new GatewayError("gateway_response_too_large");
52
+ }
53
+ chunks.push(Buffer.from(chunk));
54
+ }
55
+ return Buffer.concat(chunks, size);
56
+ }
57
+ export function createMcpRoute(options) {
58
+ const fetchImpl = options.fetchImpl ?? fetch;
59
+ const now = options.now ?? (() => new Date());
60
+ const log = options.log ?? logger.child({ module: "coding-proxy" });
61
+ const gatewayUrl = options.gatewayUrl?.replace(/\/+$/, "");
62
+ return async (req, res) => {
63
+ const startedAt = performance.now();
64
+ const seen = {};
65
+ /** Refused before the body was read: close the connection rather than read what is still coming. */
66
+ const closeIfBodyUnread = () => {
67
+ if (!req.complete && !res.headersSent)
68
+ res.setHeader("connection", "close");
69
+ };
70
+ const send = (status, body, headers = JSON_HEADERS) => {
71
+ res.writeHead(status, headers).end(body);
72
+ };
73
+ try {
74
+ if (req.method !== "POST") {
75
+ closeIfBodyUnread();
76
+ res.setHeader("allow", "POST");
77
+ if (req.method === "HEAD")
78
+ res.writeHead(405, JSON_HEADERS).end();
79
+ else
80
+ send(405, rpcError(-32600, "Use POST."));
81
+ return;
82
+ }
83
+ if (!gatewayUrl) {
84
+ closeIfBodyUnread();
85
+ send(503, JSON.stringify({ error: "mcp_unavailable", message: MCP_UNAVAILABLE_MESSAGE }));
86
+ return;
87
+ }
88
+ const token = /^Bearer (\S+)$/.exec(req.headers.authorization ?? "")?.[1];
89
+ const session = isMcpToken(token)
90
+ ? await options.ledger.findSessionByMcpTokenHash(mcpTokenHash(token))
91
+ : undefined;
92
+ const at = now().getTime();
93
+ if (!session || session.status !== "active" || at >= session.deadlineAt.getTime()) {
94
+ // No WWW-Authenticate: a client must not start OAuth discovery against this route.
95
+ closeIfBodyUnread();
96
+ send(401, rpcError(-32001, MCP_TOKEN_REQUIRED_MESSAGE));
97
+ return;
98
+ }
99
+ seen.sessionId = session.id;
100
+ if (req.headers["content-type"]?.split(";", 1)[0].trim().toLowerCase() !== "application/json") {
101
+ closeIfBodyUnread();
102
+ send(415, rpcError(-32600, "Send one JSON-RPC message as application/json."));
103
+ return;
104
+ }
105
+ let body;
106
+ try {
107
+ body = await readBodyBytes(req, HTTP_LIMITS.json, AbortSignal.timeout(HTTP_LIMITS.requestMs));
108
+ }
109
+ catch (error) {
110
+ closeIfBodyUnread();
111
+ send(error instanceof HttpBoundaryError ? error.status : 400, rpcError(-32600, "The request body could not be read."));
112
+ return;
113
+ }
114
+ seen.method = methodOf(body);
115
+ // The call may take as long as it needs, up to the run's deadline or MCP_FORWARD_MAX_MS. The
116
+ // server's requestTimeout covers receiving the request only, which is over by now.
117
+ const controller = new AbortController();
118
+ const timer = setTimeout(() => controller.abort(new GatewayError("gateway_timeout")), Math.min(MCP_FORWARD_MAX_MS, session.deadlineAt.getTime() - at));
119
+ const clientGone = () => {
120
+ if (!res.writableFinished)
121
+ controller.abort(new GatewayError("client_disconnected"));
122
+ };
123
+ res.once("close", clientGone);
124
+ try {
125
+ const upstream = await fetchImpl(`${gatewayUrl}${GATEWAY_PATH}`, {
126
+ method: "POST",
127
+ headers: { authorization: req.headers.authorization, "content-type": "application/json" },
128
+ body: new Uint8Array(body),
129
+ redirect: "error",
130
+ signal: controller.signal,
131
+ });
132
+ const answer = await readGatewayBody(upstream);
133
+ send(upstream.status, answer, {
134
+ "content-type": upstream.headers.get("content-type") ?? "application/json",
135
+ "cache-control": "no-store",
136
+ });
137
+ }
138
+ catch (error) {
139
+ const reason = controller.signal.reason instanceof GatewayError ? controller.signal.reason.reason : undefined;
140
+ throw error instanceof GatewayError ? error : new GatewayError(reason ?? "gateway_unreachable");
141
+ }
142
+ finally {
143
+ clearTimeout(timer);
144
+ res.off("close", clientGone);
145
+ }
146
+ }
147
+ catch (error) {
148
+ // Nothing of the error's text leaves or is logged: only a fixed reason code.
149
+ seen.reason = error instanceof GatewayError ? error.reason : "gateway_unreachable";
150
+ if (!res.headersSent)
151
+ send(502, JSON.stringify({ error: "mcp_unavailable", message: MCP_UNREACHABLE_MESSAGE }));
152
+ else
153
+ res.destroy();
154
+ }
155
+ finally {
156
+ log.info({
157
+ event: "mcp.request",
158
+ ...(seen.sessionId ? { sessionId: seen.sessionId } : {}),
159
+ ...(seen.method ? { method: seen.method } : {}),
160
+ status: res.statusCode,
161
+ ...(seen.reason ? { reason: seen.reason } : {}),
162
+ durationMs: Math.round(performance.now() - startedAt),
163
+ }, "coding proxy mcp request");
164
+ }
165
+ };
166
+ }
@@ -4,6 +4,7 @@ export declare class MemoryProxyLedger implements ProxyLedger {
4
4
  private readonly options;
5
5
  private readonly sessions;
6
6
  private readonly sessionByCapability;
7
+ private readonly sessionByMcpToken;
7
8
  private readonly requests;
8
9
  private readonly requestBySessionKey;
9
10
  private readonly startedAt;
@@ -11,6 +12,7 @@ export declare class MemoryProxyLedger implements ProxyLedger {
11
12
  now?: () => Date;
12
13
  });
13
14
  createSession(input: CreateProxySessionInput): Promise<void>;
15
+ findSessionByMcpTokenHash(mcpTokenHash: string): Promise<ProxySession | undefined>;
14
16
  findSessionByCapabilityHash(capabilityHash: string): Promise<ProxySession | null>;
15
17
  reserve(input: ReserveProxyRequestInput): Promise<ReserveProxyRequestResult>;
16
18
  complete(requestId: string, usage: ProxyUsage, actualCostUsd: number, upstreamStatus: number): Promise<ProxyRequest>;
@@ -10,6 +10,7 @@ function cloneSession(session) {
10
10
  terms: session.terms
11
11
  ? { version: session.terms.version, entry: { ...session.terms.entry, efforts: [...session.terms.entry.efforts] } }
12
12
  : null,
13
+ mcpTools: session.mcpTools ? structuredClone(session.mcpTools) : null,
13
14
  };
14
15
  }
15
16
  function cloneRequest(request) {
@@ -24,6 +25,7 @@ export class MemoryProxyLedger {
24
25
  options;
25
26
  sessions = new Map();
26
27
  sessionByCapability = new Map();
28
+ sessionByMcpToken = new Map();
27
29
  requests = new Map();
28
30
  requestBySessionKey = new Map();
29
31
  startedAt = new Map();
@@ -36,14 +38,28 @@ export class MemoryProxyLedger {
36
38
  }
37
39
  if (this.sessionByCapability.has(input.capabilityHash))
38
40
  throw new Error("proxy_capability_collision");
41
+ if (input.mcpTokenHash !== undefined && this.sessionByMcpToken.has(input.mcpTokenHash)) {
42
+ throw new Error("proxy_mcp_token_collision");
43
+ }
39
44
  const session = {
40
45
  ...input,
41
46
  allowedModels: [...input.allowedModels],
42
47
  status: "active",
43
48
  terms: input.terms ? normalizeProxyModelTerms(input.terms) : null,
49
+ mcpTools: input.mcpTools ? structuredClone(input.mcpTools) : null,
50
+ mcpTokenHash: input.mcpTokenHash ?? null,
51
+ mcpCallCount: 0,
52
+ runStepsLevel: input.runStepsLevel ?? null,
44
53
  };
45
54
  this.sessions.set(session.id, session);
46
55
  this.sessionByCapability.set(session.capabilityHash, session.id);
56
+ if (session.mcpTokenHash !== null)
57
+ this.sessionByMcpToken.set(session.mcpTokenHash, session.id);
58
+ }
59
+ async findSessionByMcpTokenHash(mcpTokenHash) {
60
+ const id = this.sessionByMcpToken.get(mcpTokenHash);
61
+ const session = id ? this.sessions.get(id) : undefined;
62
+ return session ? cloneSession(session) : undefined;
47
63
  }
48
64
  async findSessionByCapabilityHash(capabilityHash) {
49
65
  const id = this.sessionByCapability.get(capabilityHash);
@@ -20,6 +20,7 @@ export declare class PrismaProxyLedger implements ProxyLedger {
20
20
  private transaction;
21
21
  createSession(input: CreateProxySessionInput): Promise<void>;
22
22
  findSessionByCapabilityHash(capabilityHash: string): Promise<ProxySession | null>;
23
+ findSessionByMcpTokenHash(mcpTokenHash: string): Promise<ProxySession | undefined>;
23
24
  reserve(input: ReserveProxyRequestInput): Promise<ReserveProxyRequestResult>;
24
25
  complete(requestId: string, usage: ProxyUsage, actualCostUsd: number, upstreamStatus: number): Promise<ProxyRequest>;
25
26
  /**
@@ -1,3 +1,4 @@
1
+ import { RUN_STEPS_LEVELS } from "../../core/run-steps/config.js";
1
2
  import { logger } from "../../core/logger.js";
2
3
  import { normalizeProxyModelTerms } from "./types.js";
3
4
  const log = logger.child({ module: "coding-proxy-ledger" });
@@ -14,6 +15,9 @@ export const LEDGER_TRANSACTION_MAX_WAIT_MS = 5_000;
14
15
  * the model request. The row lock it holds is per session, so a longer
15
16
  * window only delays that run's own next request. */
16
17
  export const LEDGER_TRANSACTION_TIMEOUT_MS = 20_000;
18
+ function isRunStepsLevel(value) {
19
+ return typeof value === "string" && RUN_STEPS_LEVELS.includes(value);
20
+ }
17
21
  function sessionFromRow(row) {
18
22
  if (!Array.isArray(row.allowedModels) || !row.allowedModels.every((model) => typeof model === "string")) {
19
23
  throw new Error("invalid_proxy_session_models");
@@ -35,8 +39,27 @@ function sessionFromRow(row) {
35
39
  budgetExhaustedAt: row.budgetExhaustedAt ?? null,
36
40
  upstreamFailure: row.upstreamFailure ?? null,
37
41
  terms: sessionTerms(row),
42
+ mcpTools: sessionMcpTools(row),
43
+ mcpTokenHash: row.mcpTokenHash ?? null,
44
+ mcpCallCount: Number(row.mcpCallCount ?? 0),
45
+ runStepsLevel: isRunStepsLevel(row.runStepsLevel) ? row.runStepsLevel : null,
38
46
  };
39
47
  }
48
+ /** The session's pinned MCP tools; null when it has none. Anything but a list of pins refuses the session. */
49
+ function sessionMcpTools(row) {
50
+ const stored = row.mcpTools ?? null;
51
+ if (stored === null)
52
+ return null;
53
+ if (!Array.isArray(stored) ||
54
+ !stored.every((pin) => typeof pin === "object" &&
55
+ pin !== null &&
56
+ typeof pin.exposedName === "string" &&
57
+ typeof pin.toolName === "string" &&
58
+ typeof pin.serverId === "string")) {
59
+ throw new Error("invalid_proxy_session_mcp_tools");
60
+ }
61
+ return stored;
62
+ }
40
63
  /**
41
64
  * The session's stored model terms. Null only when both columns are null (a session from before
42
65
  * the catalog, which prices from the shipped fallback); terms that are partly present or cannot be
@@ -109,22 +132,33 @@ export class PrismaProxyLedger {
109
132
  await this.db.$executeRaw `
110
133
  INSERT INTO "CodingProxySession"
111
134
  ("id", "runId", "capabilityHash", "credentialRef", "protocol", "allowedModels", "deadlineAt",
112
- "budgetUsd", "status", "registryTokenHash", "pricingVersion", "catalogEntry", "createdAt", "updatedAt")
135
+ "budgetUsd", "status", "registryTokenHash", "pricingVersion", "catalogEntry", "mcpTools", "mcpTokenHash", "runStepsLevel",
136
+ "createdAt", "updatedAt")
113
137
  VALUES
114
138
  (${input.id}, ${input.runId}, ${input.capabilityHash}, ${input.credentialRef}, ${input.protocol}, ${models}::jsonb,
115
139
  ${input.deadlineAt}, ${input.budgetUsd}, 'active', ${input.registryTokenHash},
116
140
  ${terms?.version ?? null}, ${terms ? JSON.stringify(terms.entry) : null}::jsonb,
141
+ ${input.mcpTools ? JSON.stringify(input.mcpTools) : null}::jsonb, ${input.mcpTokenHash ?? null},
142
+ ${input.runStepsLevel ?? null}::"RunStepsLevel",
117
143
  CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
118
144
  `;
119
145
  }
120
146
  async findSessionByCapabilityHash(capabilityHash) {
121
147
  const rows = await this.db.$queryRaw `
122
148
  SELECT "id", "runId", "capabilityHash", "credentialRef", "protocol", "allowedModels", "deadlineAt", "budgetUsd", "status", "registryTokenHash",
123
- "budgetExhaustedAt", "upstreamFailure", "pricingVersion", "catalogEntry"
149
+ "budgetExhaustedAt", "upstreamFailure", "pricingVersion", "catalogEntry", "mcpTools", "mcpTokenHash", "mcpCallCount", "runStepsLevel"
124
150
  FROM "CodingProxySession" WHERE "capabilityHash" = ${capabilityHash}
125
151
  `;
126
152
  return rows[0] ? sessionFromRow(rows[0]) : null;
127
153
  }
154
+ async findSessionByMcpTokenHash(mcpTokenHash) {
155
+ const rows = await this.db.$queryRaw `
156
+ SELECT "id", "runId", "capabilityHash", "credentialRef", "protocol", "allowedModels", "deadlineAt", "budgetUsd", "status", "registryTokenHash",
157
+ "budgetExhaustedAt", "upstreamFailure", "pricingVersion", "catalogEntry", "mcpTools", "mcpTokenHash", "mcpCallCount", "runStepsLevel"
158
+ FROM "CodingProxySession" WHERE "mcpTokenHash" = ${mcpTokenHash}
159
+ `;
160
+ return rows[0] ? sessionFromRow(rows[0]) : undefined;
161
+ }
128
162
  async reserve(input) {
129
163
  return this.transaction(async (tx) => {
130
164
  const sessions = await tx.$queryRaw `
@@ -1,4 +1,9 @@
1
1
  import type { ModelPricing } from "../llm/pricing-core.js";
2
+ import { capabilityHash } from "./capability-hash.js";
3
+ import type { McpToolPin } from "../../core/mcp-tools.js";
4
+ import { type StepCaptureOptions, type StreamStepExtractor } from "../../core/run-steps/extract.js";
5
+ import { type RunStepsLevel } from "../../core/run-steps/config.js";
6
+ import type { RunStepSubmitter } from "../../core/run-steps/types.js";
2
7
  import type { CredentialResolver, ProxyAuditSink, ProxyLedger, ProxyModelTerms, ProxyProtocol, ProxyRefusalRecord } from "./types.js";
3
8
  export declare const PROXY_MAX_BODY_BYTES: number;
4
9
  export declare const PROXY_MAX_OUTPUT_TOKENS = 1000000;
@@ -43,6 +48,12 @@ export interface CreateCodingProxySession {
43
48
  budgetUsd: number;
44
49
  /** The run's catalog entry recorded at dispatch; the session then prices and shapes requests from it. */
45
50
  terms?: ProxyModelTerms;
51
+ /** The run's pinned MCP tools (no URLs or secrets); only with mcpTokenHash, and only when there is one. */
52
+ mcpTools?: McpToolPin[];
53
+ /** SHA-256 (base64url) of the run's MCP token; the control plane mints and delivers the token itself. */
54
+ mcpTokenHash?: string;
55
+ /** The run's level (Run.runStepsLevel), fixed at dispatch; absent counts as summary. */
56
+ runStepsLevel?: RunStepsLevel;
46
57
  }
47
58
  export interface CreatedCodingProxySession {
48
59
  id: string;
@@ -69,8 +80,21 @@ export interface CodingProxyOptions {
69
80
  * dependency cache's seal, ModelRequestSeal). Awaited; a failure is ignored, never the request's.
70
81
  */
71
82
  onModelRequest?: (runId: string) => Promise<void>;
83
+ /**
84
+ * Where coding runs' steps go (RunStepForwarder, to the control plane's run-steps listener);
85
+ * absent, no step is extracted. Steps are read from frames after they are relayed and handed over
86
+ * unmasked (the control plane redacts them by exact value before writing). Extraction never fails,
87
+ * delays or alters a relay, and nothing of it is logged or written to the proxy's database.
88
+ * Tool-result output (its end) is sent only for a session at detail under a detail ceiling; at off
89
+ * nothing is read.
90
+ */
91
+ steps?: RunStepSubmitter;
92
+ /** The proxy's own WARDBY_RUN_STEPS: a session captures detail only when this is detail too. Default summary. */
93
+ runStepsCeiling?: RunStepsLevel;
94
+ /** Tests only: replaces the stream step extractor. */
95
+ createStepExtractor?: (protocol: ProxyProtocol, options?: StepCaptureOptions) => StreamStepExtractor;
72
96
  }
73
- export declare function capabilityHash(capability: string): string;
97
+ export { capabilityHash };
74
98
  export declare class CodingProxy {
75
99
  private readonly ledger;
76
100
  private readonly credentials;
@@ -82,6 +106,11 @@ export declare class CodingProxy {
82
106
  private readonly priceVersion;
83
107
  private readonly activeRequests;
84
108
  private readonly onModelRequest?;
109
+ private readonly steps?;
110
+ private readonly createStepExtractor?;
111
+ private readonly runStepsCeiling;
112
+ /** Results already handed over, per session: each request resends the history. */
113
+ private readonly seenResults;
85
114
  constructor(options: CodingProxyOptions);
86
115
  createSession(input: CreateCodingProxySession): Promise<CreatedCodingProxySession>;
87
116
  cancelSession(sessionId: string): Promise<void>;
@@ -100,6 +129,9 @@ export declare class CodingProxy {
100
129
  private complete;
101
130
  private forwardJson;
102
131
  private forwardStream;
132
+ /** Queues a step batch for the control plane. Best effort: any failure drops the steps, never the request. */
133
+ private submitSteps;
134
+ private newStepExtractor;
103
135
  /** Best effort: the executor reads it to name the failure; it must never break the relay. */
104
136
  private recordUpstreamFailure;
105
137
  private markUncertain;