@nylorun/runtime 0.26.0-beta → 0.27.0-beta

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 (321) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/README.md +18 -14
  3. package/dist/adapters/execution/restate.d.ts +15 -18
  4. package/dist/adapters/execution/restate.js +31 -27
  5. package/dist/adapters/replication/pgoutput.d.ts +1 -1
  6. package/dist/adapters/replication/pgoutput.js +3 -2
  7. package/dist/adapters/sandbox/local.js +8 -5
  8. package/dist/adapters/sandbox/virtual.js +2 -2
  9. package/dist/adapters/streams/s2.d.ts +1 -1
  10. package/dist/adapters/streams/s2.js +18 -14
  11. package/dist/api/a2a/card.js +1 -1
  12. package/dist/api/a2a/endpoint.js +3 -4
  13. package/dist/api/a2a/protocol.js +4 -0
  14. package/dist/api/a2a/routes.d.ts +2 -6
  15. package/dist/api/a2a/routes.js +12 -18
  16. package/dist/api/ag-ui/endpoint.js +2 -3
  17. package/dist/api/ag-ui/routes.js +4 -4
  18. package/dist/api/components.d.ts +326 -45
  19. package/dist/api/components.js +5 -1
  20. package/dist/api/gate/keys.js +7 -4
  21. package/dist/api/gate/routes.d.ts +6 -2
  22. package/dist/api/gate/routes.js +15 -11
  23. package/dist/api/http/body.d.ts +15 -3
  24. package/dist/api/http/body.js +15 -7
  25. package/dist/api/http/respond.js +6 -2
  26. package/dist/api/http/routes/access.js +5 -4
  27. package/dist/api/http/routes/artifacts.js +19 -7
  28. package/dist/api/http/routes/coverage.js +1 -1
  29. package/dist/api/http/routes/environment-manifests.js +1 -1
  30. package/dist/api/http/routes/environments.js +6 -6
  31. package/dist/api/http/routes/files.d.ts +2 -1
  32. package/dist/api/http/routes/files.js +31 -5
  33. package/dist/api/http/routes/mcp.js +1 -1
  34. package/dist/api/http/routes/reads.d.ts +35 -0
  35. package/dist/api/http/routes/reads.js +50 -22
  36. package/dist/api/http/routes/sessions.js +11 -10
  37. package/dist/api/http/routes/tenant.d.ts +2 -2
  38. package/dist/api/http/routes/tenant.js +69 -16
  39. package/dist/api/inbound-files.d.ts +3 -9
  40. package/dist/api/inbound-files.js +18 -24
  41. package/dist/api/openapi.js +6 -2
  42. package/dist/artifacts/disk.d.ts +0 -4
  43. package/dist/artifacts/disk.js +77 -73
  44. package/dist/artifacts/files.d.ts +13 -4
  45. package/dist/artifacts/files.js +27 -9
  46. package/dist/artifacts/folder-upload.d.ts +75 -0
  47. package/dist/artifacts/folder-upload.js +263 -0
  48. package/dist/artifacts/folders.d.ts +14 -8
  49. package/dist/artifacts/folders.js +19 -11
  50. package/dist/artifacts/links.js +7 -6
  51. package/dist/artifacts/parts.d.ts +9 -14
  52. package/dist/artifacts/parts.js +11 -9
  53. package/dist/artifacts/pipe.d.ts +15 -0
  54. package/dist/artifacts/pipe.js +71 -0
  55. package/dist/artifacts/quota.d.ts +36 -0
  56. package/dist/artifacts/quota.js +44 -0
  57. package/dist/artifacts/service.d.ts +25 -1
  58. package/dist/artifacts/service.js +70 -25
  59. package/dist/blob/fs.js +2 -1
  60. package/dist/blob/s3.d.ts +6 -2
  61. package/dist/blob/s3.js +9 -7
  62. package/dist/blob/types.d.ts +1 -1
  63. package/dist/blob/types.js +1 -1
  64. package/dist/core/limits.d.ts +11 -35
  65. package/dist/core/limits.js +5 -73
  66. package/dist/core/sandbox-routes.js +0 -1
  67. package/dist/core/turn-manifest.d.ts +1 -2
  68. package/dist/core/turn-manifest.js +4 -28
  69. package/dist/execution/memory.d.ts +8 -5
  70. package/dist/execution/memory.js +8 -6
  71. package/dist/execution/types.d.ts +1 -6
  72. package/dist/execution/types.js +0 -5
  73. package/dist/gates/contract.d.ts +3 -2
  74. package/dist/gates/contract.js +1 -1
  75. package/dist/gates/egress-credentials.js +4 -3
  76. package/dist/gates/egress.d.ts +9 -9
  77. package/dist/gates/egress.js +14 -16
  78. package/dist/gates/fixture-model.js +13 -2
  79. package/dist/gates/handler.d.ts +1 -3
  80. package/dist/gates/handler.js +4 -3
  81. package/dist/gates/http-client.d.ts +4 -3
  82. package/dist/gates/http-client.js +5 -7
  83. package/dist/gates/http-tool.d.ts +24 -4
  84. package/dist/gates/http-tool.js +40 -12
  85. package/dist/gates/in-process.d.ts +2 -1
  86. package/dist/gates/in-process.js +17 -9
  87. package/dist/gates/inflight.d.ts +2 -2
  88. package/dist/gates/inflight.js +3 -2
  89. package/dist/gates/journal.js +5 -7
  90. package/dist/gates/mcp-handler.d.ts +4 -3
  91. package/dist/gates/mcp-handler.js +15 -5
  92. package/dist/gates/model-gate.d.ts +11 -2
  93. package/dist/gates/policy.d.ts +28 -5
  94. package/dist/gates/policy.js +60 -17
  95. package/dist/gates/provider-gate.d.ts +22 -0
  96. package/dist/gates/provider-gate.js +30 -0
  97. package/dist/gates/tool-calls.d.ts +1 -3
  98. package/dist/gates/tool-calls.js +2 -3
  99. package/dist/gates/tool-client.d.ts +1 -1
  100. package/dist/gates/tool-client.js +5 -6
  101. package/dist/gates/tool-contract.d.ts +8 -5
  102. package/dist/gates/tool-contract.js +1 -1
  103. package/dist/gates/tool-gate.d.ts +18 -7
  104. package/dist/gates/tool-gate.js +49 -7
  105. package/dist/harness/calls.d.ts +27 -25
  106. package/dist/harness/calls.js +40 -46
  107. package/dist/harness/executors.d.ts +10 -3
  108. package/dist/harness/executors.js +53 -23
  109. package/dist/harness/main.js +2 -2
  110. package/dist/harness/pod.d.ts +0 -2
  111. package/dist/harness/pod.js +7 -6
  112. package/dist/harness/run-tokens.d.ts +4 -1
  113. package/dist/harness/run-tokens.js +6 -2
  114. package/dist/harness/service.d.ts +17 -14
  115. package/dist/harness/service.js +21 -35
  116. package/dist/harness/setup.d.ts +0 -2
  117. package/dist/harness/setup.js +4 -9
  118. package/dist/harness/ws-client.d.ts +2 -2
  119. package/dist/harness/ws-client.js +7 -5
  120. package/dist/harness/ws-port.d.ts +3 -4
  121. package/dist/harness/ws-port.js +3 -4
  122. package/dist/harness-api/artifacts.d.ts +20 -0
  123. package/dist/harness-api/artifacts.js +478 -0
  124. package/dist/harness-api/in-process.d.ts +2 -2
  125. package/dist/harness-api/in-process.js +18 -16
  126. package/dist/harness-api/record.d.ts +10 -9
  127. package/dist/harness-api/record.js +102 -157
  128. package/dist/harness-api/renew.d.ts +1 -1
  129. package/dist/harness-api/renew.js +2 -2
  130. package/dist/harness-api/server.d.ts +1 -16
  131. package/dist/harness-api/server.js +82 -73
  132. package/dist/harness-api/start.d.ts +20 -2
  133. package/dist/harness-api/start.js +57 -18
  134. package/dist/harness-api/tool-journal.d.ts +15 -10
  135. package/dist/harness-api/tool-journal.js +26 -24
  136. package/dist/harness-api/workspace.d.ts +0 -4
  137. package/dist/harness-api/workspace.js +2 -45
  138. package/dist/harness-api/ws-server.js +10 -10
  139. package/dist/host/create-host.js +2 -3
  140. package/dist/host/execution.js +2 -3
  141. package/dist/host/gates.d.ts +2 -9
  142. package/dist/host/gates.js +15 -12
  143. package/dist/host/http.d.ts +0 -2
  144. package/dist/host/http.js +0 -27
  145. package/dist/host/main.js +10 -3
  146. package/dist/host/operate.js +12 -3
  147. package/dist/host/stack-config.d.ts +11 -0
  148. package/dist/host/stack-config.js +21 -1
  149. package/dist/index.d.ts +0 -1
  150. package/dist/index.js +0 -1
  151. package/dist/infra/index.js +2 -1
  152. package/dist/infra/readiness.d.ts +0 -2
  153. package/dist/infra/readiness.js +4 -3
  154. package/dist/keys/client.d.ts +1 -0
  155. package/dist/keys/client.js +2 -3
  156. package/dist/keys/contract.d.ts +0 -2
  157. package/dist/keys/contract.js +0 -2
  158. package/dist/keys/egress-ca.d.ts +0 -2
  159. package/dist/keys/egress-ca.js +2 -3
  160. package/dist/keys/keys.js +6 -1
  161. package/dist/keys/x509.d.ts +8 -4
  162. package/dist/keys/x509.js +14 -5
  163. package/dist/management-openapi.json +1961 -994
  164. package/dist/mcp/connect.d.ts +35 -26
  165. package/dist/mcp/connect.js +112 -141
  166. package/dist/mcp/pool.d.ts +27 -22
  167. package/dist/mcp/pool.js +34 -48
  168. package/dist/mcp/preview.d.ts +12 -5
  169. package/dist/mcp/preview.js +36 -19
  170. package/dist/mcp/snapshot.d.ts +35 -86
  171. package/dist/mcp/snapshot.js +93 -135
  172. package/dist/model/auth-store.js +5 -3
  173. package/dist/model/capabilities.d.ts +1 -1
  174. package/dist/model/catalog.d.ts +9 -36
  175. package/dist/model/catalog.js +6 -33
  176. package/dist/model/descriptor.d.ts +51 -0
  177. package/dist/model/descriptor.js +83 -0
  178. package/dist/model/models.d.ts +0 -3
  179. package/dist/model/models.js +3 -5
  180. package/dist/model/native-blocks.js +1 -1
  181. package/dist/model/pi-model.d.ts +16 -5
  182. package/dist/model/pi-model.js +86 -105
  183. package/dist/openapi.json +838 -1218
  184. package/dist/reads/cursor.js +3 -1
  185. package/dist/record/append.d.ts +34 -2
  186. package/dist/record/append.js +50 -1
  187. package/dist/record/environment.d.ts +2 -0
  188. package/dist/record/environment.js +2 -0
  189. package/dist/record/index.d.ts +1 -1
  190. package/dist/record/index.js +1 -1
  191. package/dist/redact.d.ts +1 -1
  192. package/dist/redact.js +3 -2
  193. package/dist/sandbox/egress-token.d.ts +3 -3
  194. package/dist/sandbox/egress-token.js +3 -3
  195. package/dist/sandbox/join.js +3 -2
  196. package/dist/sandbox/manager.d.ts +41 -41
  197. package/dist/sandbox/manager.js +112 -44
  198. package/dist/sandbox/placement.d.ts +1 -1
  199. package/dist/sandbox/placement.js +5 -8
  200. package/dist/sandbox/pods/client.d.ts +1 -10
  201. package/dist/sandbox/pods/client.js +8 -4
  202. package/dist/sandbox/pods/lifecycle.d.ts +19 -11
  203. package/dist/sandbox/pods/lifecycle.js +45 -23
  204. package/dist/sandbox/pods/network-gate.d.ts +4 -5
  205. package/dist/sandbox/pods/network-gate.js +7 -7
  206. package/dist/sandbox/pods/reconcile.js +4 -1
  207. package/dist/sandbox/pods/spec.js +8 -5
  208. package/dist/sandbox/policy.d.ts +7 -1
  209. package/dist/sandbox/policy.js +10 -3
  210. package/dist/sandbox/resolve.d.ts +8 -3
  211. package/dist/sandbox/resolve.js +12 -2
  212. package/dist/sandbox/setup.d.ts +3 -1
  213. package/dist/sandbox/setup.js +34 -11
  214. package/dist/sandbox/share.d.ts +5 -14
  215. package/dist/sandbox/share.js +5 -34
  216. package/dist/sandbox/skills.d.ts +7 -13
  217. package/dist/sandbox/skills.js +16 -31
  218. package/dist/sandbox/tenant-config.d.ts +2 -2
  219. package/dist/sandbox/tenant-config.js +4 -3
  220. package/dist/sandbox/tools.d.ts +7 -1
  221. package/dist/sandbox/tools.js +26 -26
  222. package/dist/sandbox/types.d.ts +10 -3
  223. package/dist/sandbox/types.js +9 -0
  224. package/dist/store/postgres/connect.d.ts +6 -5
  225. package/dist/store/postgres/connect.js +14 -11
  226. package/dist/store/postgres/control.js +13 -13
  227. package/dist/store/postgres/drizzle/0028_artifact_write_keys.sql +2 -0
  228. package/dist/store/postgres/drizzle/0029_protocol_15.sql +11 -0
  229. package/dist/store/postgres/drizzle/0030_protocol_15_runtime_block.sql +11 -0
  230. package/dist/store/postgres/drizzle/0031_protocol_15_mcp_snapshot.sql +8 -0
  231. package/dist/store/postgres/drizzle/meta/_journal.json +28 -0
  232. package/dist/store/postgres/reads.js +10 -2
  233. package/dist/store/postgres/schema.d.ts +19 -0
  234. package/dist/store/postgres/schema.js +7 -0
  235. package/dist/store/postgres/store.js +55 -26
  236. package/dist/store/types.d.ts +17 -7
  237. package/dist/streams/relay/core.d.ts +3 -3
  238. package/dist/streams/relay/core.js +9 -10
  239. package/dist/tenant/advance.js +21 -31
  240. package/dist/tenant/commands.js +9 -16
  241. package/dist/tenant/context.d.ts +14 -17
  242. package/dist/tenant/definition-files.d.ts +25 -4
  243. package/dist/tenant/definition-files.js +85 -47
  244. package/dist/tenant/effects.js +9 -36
  245. package/dist/tenant/environment-manifests.js +9 -1
  246. package/dist/tenant/environments.d.ts +0 -2
  247. package/dist/tenant/environments.js +49 -28
  248. package/dist/tenant/ephemeral.js +2 -1
  249. package/dist/tenant/history.d.ts +1 -1
  250. package/dist/tenant/history.js +1 -1
  251. package/dist/tenant/host-token.d.ts +3 -3
  252. package/dist/tenant/host-token.js +11 -10
  253. package/dist/tenant/http.d.ts +5 -8
  254. package/dist/tenant/http.js +9 -0
  255. package/dist/tenant/identity-file.d.ts +23 -0
  256. package/dist/tenant/identity-file.js +34 -6
  257. package/dist/tenant/issuers.d.ts +5 -5
  258. package/dist/tenant/issuers.js +31 -23
  259. package/dist/tenant/jwt.d.ts +8 -2
  260. package/dist/tenant/jwt.js +10 -2
  261. package/dist/tenant/limits.d.ts +90 -0
  262. package/dist/tenant/limits.js +175 -0
  263. package/dist/tenant/module.d.ts +4 -1
  264. package/dist/tenant/module.js +9 -8
  265. package/dist/tenant/outbound.d.ts +11 -14
  266. package/dist/tenant/outbound.js +10 -15
  267. package/dist/tenant/run-grants.js +3 -2
  268. package/dist/tenant/run-token.d.ts +0 -4
  269. package/dist/tenant/run-token.js +6 -11
  270. package/dist/tenant/runtime-limits.d.ts +24 -0
  271. package/dist/tenant/runtime-limits.js +27 -0
  272. package/dist/tenant/runtime.js +30 -43
  273. package/dist/tenant/session-streams.js +7 -6
  274. package/dist/tenant/session.d.ts +1 -1
  275. package/dist/tenant/session.js +1 -1
  276. package/dist/tenant/sessions.js +32 -29
  277. package/dist/tenant/signing-keys.d.ts +1 -1
  278. package/dist/tenant/signing-keys.js +5 -6
  279. package/dist/tenant/status.js +4 -3
  280. package/dist/tenant/streams.js +18 -20
  281. package/dist/tenant/sweep.d.ts +1 -21
  282. package/dist/tenant/sweep.js +39 -48
  283. package/dist/tenant/transcript.d.ts +70 -23
  284. package/dist/tenant/transcript.js +28 -22
  285. package/dist/tenant/types.d.ts +9 -14
  286. package/dist/tenant/worker.d.ts +2 -10
  287. package/dist/tenant/worker.js +5 -14
  288. package/dist/traces/ids.js +5 -1
  289. package/dist/traces/map.d.ts +9 -6
  290. package/dist/traces/map.js +9 -11
  291. package/dist/traces/otlp.d.ts +3 -3
  292. package/dist/traces/otlp.js +5 -3
  293. package/dist/traces/projector.d.ts +9 -4
  294. package/dist/traces/projector.js +13 -7
  295. package/dist/traces/read.js +6 -1
  296. package/dist/tuning.d.ts +383 -0
  297. package/dist/tuning.js +658 -0
  298. package/dist/vault/headers.js +4 -2
  299. package/dist/version.d.ts +1 -1
  300. package/dist/version.js +1 -1
  301. package/package.json +3 -3
  302. package/dist/artifacts/export.d.ts +0 -8
  303. package/dist/artifacts/export.js +0 -204
  304. package/dist/artifacts/media-types.d.ts +0 -30
  305. package/dist/artifacts/media-types.js +0 -137
  306. package/dist/artifacts/workspace.d.ts +0 -60
  307. package/dist/artifacts/workspace.js +0 -45
  308. package/dist/media.d.ts +0 -10
  309. package/dist/media.js +0 -58
  310. package/dist/sandbox/runtime-tools.d.ts +0 -9
  311. package/dist/sandbox/runtime-tools.js +0 -16
  312. package/dist/sandbox/session-sandbox.d.ts +0 -16
  313. package/dist/sandbox/session-sandbox.js +0 -77
  314. package/dist/tenant/artifact-tool.d.ts +0 -13
  315. package/dist/tenant/artifact-tool.js +0 -243
  316. package/dist/tenant/skill-tool.d.ts +0 -20
  317. package/dist/tenant/skill-tool.js +0 -67
  318. package/dist/tenant/tool-results.d.ts +0 -57
  319. package/dist/tenant/tool-results.js +0 -298
  320. package/dist/tenant/tool-search.d.ts +0 -39
  321. package/dist/tenant/tool-search.js +0 -103
@@ -5,7 +5,7 @@
5
5
  * global registry.
6
6
  */
7
7
  import { z } from "zod";
8
- import { EnvironmentManifestSchema, EnvironmentSecretSlotsSchema, DeleteEnvironmentManifestResponseSchema, EnvironmentManifestPlanSchema, EnvironmentManifestVersionsSchema, EnvironmentManifestViewSchema, ListEnvironmentManifestsResponseSchema, PutEnvironmentManifestRequestSchema, PutEnvironmentSecretValueRequestSchema, SaveEnvironmentManifestResponseSchema, SessionListItemSchema, ModelCallSchema, SessionPageSchema, SessionManifestViewSchema, HistoryPageSchema, SessionUsageTotalsSchema, ModelCallsPageSchema, ModelCallExportPageSchema, EnvironmentPageSchema, ToolCallSchema, ToolCallsPageSchema, TurnTraceSchema, JwksSchema, SigningKeyListSchema, SigningKeyViewSchema, RotateSigningKeysRequestSchema, RevokeSigningKeyRequestSchema, MeResponseSchema, TenantStatusSchema, ResetTenantRequestSchema, ResetTenantResponseSchema, SeedTenantConfigRequestSchema, SeedTenantConfigResponseSchema, HostModelCatalogSchema, TenantSandboxViewSchema, ModelUsageTotalsSchema, ModelBudgetsSchema, PutModelBudgetsRequestSchema, ToolPolicySchema, PutToolPolicyRequestSchema, PutModelInputsRequestSchema, ModelInputsViewSchema, PutTenantEnvironmentsRequestSchema, ListProvidersResponseSchema, HostModelViewSchema, PutHostModelRequestSchema, SelectHostModelRequestSchema, PutEnvironmentSecretRequestSchema, EnvironmentSecretViewSchema, ListEnvironmentSecretsResponseSchema, McpPreviewRequestSchema, McpPreviewSchema, CredentialCoverageRequestSchema, CredentialCoverageSchema, DeletedResponseSchema, ListAgentsResponseSchema, ListPublicAgentsResponseSchema, ListSessionsResponseSchema, LiveEventSchema, PutAgentRequestSchema, PutAgentResponseSchema, PutSessionRequestSchema, SessionItemsResponseSchema, SessionViewSchema, StreamClosedFrameSchema, AcceptedResponseSchema, SandboxToolOutcomeSchema, PutEnvironmentRequestSchema, EnvironmentViewSchema, EnvironmentSnapshotSchema, RestoreEnvironmentRequestSchema, ForkEnvironmentRequestSchema, EnvironmentForkPlanSchema, ForkEnvironmentResponseSchema, EnvironmentRestoreSchema, EnvironmentVersionsSchema, ListEnvironmentsResponseSchema, DeleteEnvironmentResponseSchema, ListEnvironmentEventsResponseSchema, ArtifactViewSchema, ArtifactListItemSchema, ArtifactPageSchema, ArtifactVersionViewSchema, ListArtifactsResponseSchema, UploadArtifactResponseSchema, DefinitionFileViewSchema, DeleteArtifactResponseSchema, CreateArtifactLinkRequestSchema, ArtifactLinkSchema, PutTenantArtifactsRequestSchema, TenantArtifactsViewSchema, ArtifactTreeSchema, ArtifactDiffSchema, SessionCommandSchema, ListOperatorKeysResponseSchema, PutOperatorKeyResponseSchema, DeleteOperatorKeyResponseSchema, OperatorKeySchema, ProtocolRejectedResponseSchema, RejectedResponseSchema, EVENT_SCHEMAS, EVENT_TYPES, } from "@nylorun/core/contracts";
8
+ import { EnvironmentManifestSchema, EnvironmentSecretSlotsSchema, DeleteEnvironmentManifestResponseSchema, EnvironmentManifestPlanSchema, EnvironmentManifestVersionsSchema, EnvironmentManifestViewSchema, ListEnvironmentManifestsResponseSchema, PutEnvironmentManifestRequestSchema, PutEnvironmentSecretValueRequestSchema, SaveEnvironmentManifestResponseSchema, SessionListItemSchema, ModelCallSchema, SessionPageSchema, SessionManifestViewSchema, HistoryPageSchema, SessionUsageTotalsSchema, ModelCallsPageSchema, ModelCallExportPageSchema, EnvironmentPageSchema, ToolCallSchema, ToolCallsPageSchema, TurnTraceSchema, JwksSchema, SigningKeyListSchema, SigningKeyViewSchema, RotateSigningKeysRequestSchema, RevokeSigningKeyRequestSchema, MeResponseSchema, TenantStatusSchema, ResetTenantRequestSchema, ResetTenantResponseSchema, SeedTenantConfigRequestSchema, SeedTenantConfigResponseSchema, HostModelCatalogSchema, TenantSandboxViewSchema, ModelUsageTotalsSchema, ModelBudgetsSchema, PutModelBudgetsRequestSchema, ToolPolicySchema, PutToolPolicyRequestSchema, PutModelInputsRequestSchema, ModelInputsViewSchema, PutTenantEnvironmentsRequestSchema, ListProvidersResponseSchema, HostModelViewSchema, PutHostModelRequestSchema, SelectHostModelRequestSchema, PutEnvironmentSecretRequestSchema, EnvironmentSecretViewSchema, ListEnvironmentSecretsResponseSchema, McpPreviewRequestSchema, McpPreviewSchema, CredentialCoverageRequestSchema, CredentialCoverageSchema, DeletedResponseSchema, ListAgentsResponseSchema, ListPublicAgentsResponseSchema, ListSessionsResponseSchema, LiveEventSchema, PutAgentRequestSchema, PutAgentResponseSchema, PutSessionRequestSchema, SessionItemsResponseSchema, SessionViewSchema, StreamClosedFrameSchema, AcceptedResponseSchema, SandboxToolOutcomeSchema, PutEnvironmentRequestSchema, EnvironmentViewSchema, EnvironmentSnapshotSchema, RestoreEnvironmentRequestSchema, ForkEnvironmentRequestSchema, EnvironmentForkPlanSchema, ForkEnvironmentResponseSchema, EnvironmentRestoreSchema, EnvironmentVersionsSchema, ListEnvironmentsResponseSchema, DeleteEnvironmentResponseSchema, ListEnvironmentEventsResponseSchema, ArtifactViewSchema, ArtifactListItemSchema, ArtifactPageSchema, ArtifactVersionViewSchema, ListArtifactsResponseSchema, UploadArtifactResponseSchema, DefinitionFileViewSchema, DeleteArtifactResponseSchema, CreateArtifactLinkRequestSchema, ArtifactLinkSchema, PutTenantArtifactsRequestSchema, PutTenantSkillsRequestSchema, PutTenantLimitsRequestSchema, TenantLimitsViewSchema, TenantArtifactsViewSchema, TenantSkillsViewSchema, ArtifactTreeSchema, ArtifactDiffSchema, SessionCommandSchema, ListOperatorKeysResponseSchema, PutOperatorKeyResponseSchema, DeleteOperatorKeyResponseSchema, OperatorKeySchema, ProtocolRejectedResponseSchema, RejectedResponseSchema, EVENT_SCHEMAS, EVENT_TYPES, } from "@nylorun/core/contracts";
9
9
  function named(id, schema) {
10
10
  return schema.meta({ id });
11
11
  }
@@ -50,6 +50,10 @@ export const CreateArtifactLinkRequest = named("CreateArtifactLinkRequest", Crea
50
50
  export const ArtifactLink = named("ArtifactLink", ArtifactLinkSchema);
51
51
  export const PutTenantArtifactsRequest = named("PutTenantArtifactsRequest", PutTenantArtifactsRequestSchema);
52
52
  export const TenantArtifactsView = named("TenantArtifactsView", TenantArtifactsViewSchema);
53
+ export const PutTenantSkillsRequest = named("PutTenantSkillsRequest", PutTenantSkillsRequestSchema);
54
+ export const TenantSkillsView = named("TenantSkillsView", TenantSkillsViewSchema);
55
+ export const PutTenantLimitsRequest = named("PutTenantLimitsRequest", PutTenantLimitsRequestSchema);
56
+ export const TenantLimitsView = named("TenantLimitsView", TenantLimitsViewSchema);
53
57
  export const ArtifactTree = named("ArtifactTree", ArtifactTreeSchema);
54
58
  export const ArtifactDiff = named("ArtifactDiff", ArtifactDiffSchema);
55
59
  export const SessionCommand = named("SessionCommand", SessionCommandSchema);
@@ -1,13 +1,16 @@
1
1
  import { bodyLimit } from "hono/body-limit";
2
2
  import { HttpError } from "../../tenant/http.js";
3
3
  import { VaultError } from "../../vault/error.js";
4
- import { KEYS_PATH, MAX_KEYS_BODY_BYTES } from "../../keys/contract.js";
4
+ import { KEYS_PATH } from "../../keys/contract.js";
5
+ import { hostTuning } from "../../tuning.js";
5
6
  import { KEYS_OPERATIONS } from "../../keys/keys.js";
6
7
  export function mountKeysRoutes(app, options) {
7
- app.post(`${KEYS_PATH}/:operation`, options.authorized, bodyLimit({
8
- maxSize: MAX_KEYS_BODY_BYTES,
8
+ app.post(`${KEYS_PATH}/:operation`, options.authorized,
9
+ // The largest request body: a credential with its secret, or a token's claims (`keys.bodyBytes`).
10
+ (c, next) => bodyLimit({
11
+ maxSize: hostTuning().keys.bodyBytes,
9
12
  onError: (c) => c.json({ error: { code: "invalid_request", message: "The body is too large" } }, 400),
10
- }), async (c) => {
13
+ })(c, next), async (c) => {
11
14
  const operation = c.req.param("operation");
12
15
  if (!KEYS_OPERATIONS.includes(operation))
13
16
  return c.json({ error: { code: "invalid_request", message: `Unknown keys operation ${operation}` } }, 404);
@@ -1,4 +1,5 @@
1
1
  import { Hono } from "hono";
2
+ import type { RuntimeLimits } from "@nylorun/core/contracts";
2
3
  import type { ModelCallHandler } from "../../gates/handler.js";
3
4
  import { type InflightCalls } from "../../gates/inflight.js";
4
5
  import type { McpHandler } from "../../gates/mcp-handler.js";
@@ -25,8 +26,11 @@ export interface GatesAppOptions {
25
26
  readonly inflight: InflightCalls;
26
27
  /** Whether the gate's dependencies answer (Postgres). */
27
28
  readonly ready: () => Promise<boolean>;
28
- /** Largest body read. Default `MAX_MODEL_CALL_BYTES`. */
29
- readonly maxBodyBytes?: number;
29
+ /**
30
+ * The Tenant's Runtime limits, read from its database for each call (`modelCallBytes` bounds a
31
+ * model call's body, `toolAnswerBytes` a tool request's).
32
+ */
33
+ readonly limits: () => Promise<RuntimeLimits>;
30
34
  /** Remote MCP servers (F4.1). Without it the MCP routes answer 404. */
31
35
  readonly mcp?: McpHandler;
32
36
  /** HTTP tool calls (R2 M3). Without it the HTTP calls route answers 404. */
@@ -22,10 +22,10 @@ import { Hono } from "hono";
22
22
  import { bodyLimit } from "hono/body-limit";
23
23
  import { HTTPException } from "hono/http-exception";
24
24
  import { isTenantId } from "@nylorun/core/compatibility";
25
- import { MAX_MODEL_CALL_BYTES, MODEL_CALLS_PATH, ModelCallBodySchema, TENANT_HEADER, } from "../../gates/contract.js";
25
+ import { MODEL_CALLS_PATH, ModelCallBodySchema, TENANT_HEADER, } from "../../gates/contract.js";
26
26
  import { InflightConflict, InflightStale } from "../../gates/inflight.js";
27
27
  import { mountKeysRoutes } from "./keys.js";
28
- import { HTTP_CALLS_PATH, HttpCallBodySchema, MAX_TOOL_BODY_BYTES, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, McpListBodySchema, McpServerBodySchema, TOOL_CALLS_PATH, ToolCallBodySchema, } from "../../gates/tool-contract.js";
28
+ import { HTTP_CALLS_PATH, HttpCallBodySchema, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, McpListBodySchema, McpServerBodySchema, TOOL_CALLS_PATH, ToolCallBodySchema, } from "../../gates/tool-contract.js";
29
29
  import { looksLikeToken } from "../../tenant/jwt.js";
30
30
  import { adminKeyMatches } from "../../host/http.js";
31
31
  import { canonical } from "../../store/canonical.js";
@@ -37,7 +37,6 @@ const gateError = (code, message) => ({
37
37
  });
38
38
  export function createGatesApp(options) {
39
39
  const app = new Hono();
40
- const maxSize = options.maxBodyBytes ?? MAX_MODEL_CALL_BYTES;
41
40
  const logger = options.logger ?? { info() { }, warn() { }, error() { } };
42
41
  // Hono's default, but logged through the logger: never the body, which may hold secrets.
43
42
  app.onError((error, c) => {
@@ -105,10 +104,18 @@ export function createGatesApp(options) {
105
104
  return claims?.tenantId ?? tenantId;
106
105
  };
107
106
  const badTenant = (c) => c.json(invalid(`The ${TENANT_HEADER} header must name a Tenant, the run token's when there is one`), 400);
108
- const toolBodies = bodyLimit({
109
- maxSize: MAX_TOOL_BODY_BYTES,
110
- onError: (c) => c.json(invalid(`A request body may be at most ${MAX_TOOL_BODY_BYTES} bytes`), 400),
111
- });
107
+ /**
108
+ * A body of at most the Tenant's limit `name`, read for this request: a larger one is `400`,
109
+ * naming the limit.
110
+ */
111
+ const limited = (name, what) => async (c, next) => {
112
+ const maxSize = (await options.limits())[name];
113
+ return bodyLimit({
114
+ maxSize,
115
+ onError: (c) => c.json(invalid(`${what} may be at most ${maxSize} bytes (the Runtime limit ${name})`), 400),
116
+ })(c, next);
117
+ };
118
+ const toolBodies = limited("toolAnswerBytes", "A request body");
112
119
  /** The parsed body, or the 400 to answer. */
113
120
  async function read(c, schema) {
114
121
  const tenantId = tenantOf(c);
@@ -322,10 +329,7 @@ export function createGatesApp(options) {
322
329
  return c.json(gateError("gate_forbidden", "The call is another session's"), 403);
323
330
  return c.body(null, 204);
324
331
  });
325
- app.post(MODEL_CALLS_PATH, run({ live: true }), bodyLimit({
326
- maxSize,
327
- onError: (c) => c.json(invalid(`A model call body may be at most ${maxSize} bytes`), 400),
328
- }), async (c) => {
332
+ app.post(MODEL_CALLS_PATH, run({ live: true }), limited("modelCallBytes", "A model call body"), async (c) => {
329
333
  // Optional: the gate serves its database's one Tenant, and refuses a call naming another.
330
334
  const tenantId = tenantOf(c);
331
335
  if (tenantId === false)
@@ -1,4 +1,16 @@
1
+ import type { TenantContext } from "../../tenant/context.js";
2
+ /** What a body is: a JSON request (`requestBodyBytes`), or a message that may carry files inline. */
3
+ export type BodyKind = "json" | "inline";
4
+ /** The most bytes the Tenant's route reads of a body of `kind`. */
5
+ export declare function bodyLimit(tenant: TenantContext, kind?: BodyKind): Promise<number>;
1
6
  /** The body as text; past `maxBytes`, `413 Request too large`. */
2
- export declare function readText(request: Request, maxBytes?: number): Promise<string>;
3
- /** The body as JSON, before any schema. */
4
- export declare function readJson(request: Request, maxBytes?: number): Promise<unknown>;
7
+ export declare function readText(request: Request, maxBytes: number): Promise<string>;
8
+ /** The body of a Tenant route's request as JSON, before any schema. */
9
+ export declare function readJson(c: {
10
+ readonly req: {
11
+ readonly raw: Request;
12
+ };
13
+ readonly env: {
14
+ readonly tenant: TenantContext;
15
+ };
16
+ }, kind?: BodyKind): Promise<unknown>;
@@ -1,12 +1,20 @@
1
1
  /**
2
2
  * Request bodies of Tenant routes, read as the router they replace read them
3
- * (`tenant/http.ts`): at most 1 MiB unless a route allows more (an endpoint that takes files
4
- * inline), UTF-8, and a missing or malformed JSON body is `400 Invalid JSON`.
3
+ * (`tenant/http.ts`): at most the Tenant's Runtime limit `requestBodyBytes`, or for an endpoint
4
+ * that takes files inline `inlineBodyBytes` of its limits (one file at `inlineFileBytes` in
5
+ * base64, and the rest), UTF-8, and a missing or malformed JSON body is `400 Invalid JSON`. The
6
+ * limits are read for each request.
5
7
  */
8
+ import { inlineBodyBytes } from "@nylorun/core/contracts";
6
9
  import { fail } from "../../tenant/http.js";
7
- const MAX_BODY_BYTES = 1024 * 1024;
10
+ import { readRuntimeLimits } from "../../tenant/runtime-limits.js";
11
+ /** The most bytes the Tenant's route reads of a body of `kind`. */
12
+ export async function bodyLimit(tenant, kind = "json") {
13
+ const limits = await tenant.store.tx((t) => readRuntimeLimits(t));
14
+ return kind === "inline" ? inlineBodyBytes(limits) : limits.requestBodyBytes;
15
+ }
8
16
  /** The body as text; past `maxBytes`, `413 Request too large`. */
9
- export async function readText(request, maxBytes = MAX_BODY_BYTES) {
17
+ export async function readText(request, maxBytes) {
10
18
  if (request.body === null)
11
19
  return "";
12
20
  const chunks = [];
@@ -25,9 +33,9 @@ export async function readText(request, maxBytes = MAX_BODY_BYTES) {
25
33
  }
26
34
  return Buffer.concat(chunks).toString("utf8");
27
35
  }
28
- /** The body as JSON, before any schema. */
29
- export async function readJson(request, maxBytes = MAX_BODY_BYTES) {
30
- const text = await readText(request, maxBytes);
36
+ /** The body of a Tenant route's request as JSON, before any schema. */
37
+ export async function readJson(c, kind = "json") {
38
+ const text = await readText(c.req.raw, await bodyLimit(c.env.tenant, kind));
31
39
  try {
32
40
  return JSON.parse(text);
33
41
  }
@@ -4,6 +4,7 @@
4
4
  * (`routes.ts`) both answer through here, so a route answers the same wherever it runs.
5
5
  */
6
6
  import { SandboxRouteError } from "../../core/sandbox-routes.js";
7
+ import { RecordEntryTooLargeError } from "../../record/index.js";
7
8
  import { HttpError, OpaqueAuthError } from "../../tenant/http.js";
8
9
  import { VaultError } from "../../vault/error.js";
9
10
  /** A JSON answer. CORS headers a browser needs are already on the Node response. */
@@ -24,13 +25,16 @@ export function rejectionOf(error) {
24
25
  return { status: error.status, body: error.body, headers: {} };
25
26
  const status = error instanceof HttpError ||
26
27
  error instanceof VaultError ||
27
- error instanceof SandboxRouteError
28
+ error instanceof SandboxRouteError ||
29
+ error instanceof RecordEntryTooLargeError
28
30
  ? error.status
29
31
  : error?.name === "ZodError" ||
30
32
  error?.message === "Invalid cursor"
31
33
  ? 400
32
34
  : 500;
33
- const rejection = error instanceof HttpError || error instanceof VaultError ? error.rejection : {};
35
+ const rejection = error instanceof HttpError || error instanceof VaultError || error instanceof RecordEntryTooLargeError
36
+ ? error.rejection
37
+ : {};
34
38
  return {
35
39
  status,
36
40
  body: {
@@ -1,10 +1,11 @@
1
1
  import { z } from "zod";
2
- import { RevokeSigningKeyRequestSchema, RotateSigningKeysRequestSchema, TOKEN_TTL_MAX_SECONDS, } from "@nylorun/core/contracts";
2
+ import { RevokeSigningKeyRequestSchema, RotateSigningKeysRequestSchema, } from "@nylorun/core/contracts";
3
3
  import { Jwks, RevokeSigningKeyRequest, RotateSigningKeysRequest, SigningKeyList, SigningKeyView, } from "../../components.js";
4
4
  import { publicJwk, signingKeyView } from "../../../tenant/signing-keys.js";
5
5
  import { readJson } from "../body.js";
6
6
  import { tenantRoute } from "../define.js";
7
7
  import { jsonResponse } from "../respond.js";
8
+ import { hostTuning } from "../../../tuning.js";
8
9
  /** The Management API's signing-key routes: a management key. */
9
10
  const MANAGEMENT = { credentials: ["management"], scopes: "never" };
10
11
  const json = (schema, description) => ({
@@ -74,10 +75,10 @@ function signingKeyRoutesAt(api, base, access) {
74
75
  },
75
76
  }, async (c) => {
76
77
  const ctx = c.env.tenant;
77
- const request = RotateSigningKeysRequestSchema.parse(await readJson(c.req.raw));
78
+ const request = RotateSigningKeysRequestSchema.parse(await readJson(c));
78
79
  // The longest any token the Runtime signs lives (capability links, run tokens).
79
80
  const keys = await ctx.keys.rotateSigningKeys({
80
- maxTtlSeconds: TOKEN_TTL_MAX_SECONDS,
81
+ maxTtlSeconds: hostTuning().keys.tokenTtlMaxSeconds,
81
82
  force: request.force === true,
82
83
  });
83
84
  ctx.config.logger.info("signing keys rotated", { force: request.force === true });
@@ -95,7 +96,7 @@ function signingKeyRoutesAt(api, base, access) {
95
96
  },
96
97
  }, async (c) => {
97
98
  const ctx = c.env.tenant;
98
- RevokeSigningKeyRequestSchema.parse(await readJson(c.req.raw));
99
+ RevokeSigningKeyRequestSchema.parse(await readJson(c));
99
100
  const row = await ctx.store.tx((t) => ctx.signingKeys.revoke(t, c.req.param("kid")));
100
101
  ctx.config.logger.info("signing key revoked", { kid: row.id });
101
102
  return jsonResponse(200, signingKeyView(row));
@@ -21,7 +21,7 @@ import { effectiveArtifactLimits, readArtifactsConfig, writeArtifactsConfig, } f
21
21
  import { contentKey, diffManifests, entryAt, readManifest } from "../../../artifacts/folders.js";
22
22
  import { mintArtifactLink, verifyArtifactLink } from "../../../artifacts/links.js";
23
23
  import { zipStream, zipTooLarge } from "../../../artifacts/zip.js";
24
- import { normalizeContentType } from "../../../artifacts/media-types.js";
24
+ import { normalizeContentType } from "@nylorun/core/contracts";
25
25
  import { artifactContent, deleteArtifact, folderContent, getArtifact, listArtifacts, readableArtifact, uploadArtifact, versionOf, } from "../../../artifacts/service.js";
26
26
  import { accessOf } from "../../../tenant/auth.js";
27
27
  import { readAccess, readStoreOf } from "../../../reads/access.js";
@@ -29,7 +29,9 @@ import { fail } from "../../../tenant/http.js";
29
29
  import { readJson } from "../body.js";
30
30
  import { tenantRoute } from "../define.js";
31
31
  import { jsonResponse } from "../respond.js";
32
- import { pageQuery, parseQuery } from "./reads.js";
32
+ import { labelIssues } from "../../../tenant/limits.js";
33
+ import { readRuntimeLimits } from "../../../tenant/runtime-limits.js";
34
+ import { pageQuery, pageSize, parseQuery } from "./reads.js";
33
35
  /** Reading and writing artifacts: whoever may use sessions, a person only in their own. */
34
36
  const OWN = {
35
37
  credentials: ["application", "subject", "token"],
@@ -105,6 +107,15 @@ function labelsOf(values) {
105
107
  fail(400, parsed.error.issues[0]?.message ?? "Invalid labels");
106
108
  return labels;
107
109
  }
110
+ /** `labels` to set on an artifact, within the Tenant's Runtime limits (read for the request). */
111
+ async function settableLabels(ctx, labels) {
112
+ if (labels === undefined)
113
+ return undefined;
114
+ const issues = labelIssues(labels, await ctx.store.tx((t) => readRuntimeLimits(t)), "artifactLabels");
115
+ if (issues.length > 0)
116
+ fail(400, issues.join(" "));
117
+ return labels;
118
+ }
108
119
  function versionNumber(value) {
109
120
  if (value === "latest")
110
121
  return undefined;
@@ -285,7 +296,7 @@ export function artifactRoutes(api) {
285
296
  const request = c.req.raw;
286
297
  const name = c.req.query("name");
287
298
  const sessionId = c.req.query("sessionId");
288
- const labels = labelsOf(c.req.queries("label"));
299
+ const labels = await settableLabels(c.env.tenant, labelsOf(c.req.queries("label")));
289
300
  const contentType = declaredType(request);
290
301
  const uploaded = await uploadArtifact(c.env.tenant, {
291
302
  ...(name === undefined ? {} : { name }),
@@ -337,9 +348,10 @@ export function artifactRoutes(api) {
337
348
  }, async (c) => {
338
349
  const sessionId = c.req.query("sessionId");
339
350
  if (c.req.query("limit") !== undefined) {
340
- const { limit, cursor, kind } = parseQuery(artifactPageQuery, c.req.query());
341
- if (limit === undefined)
351
+ const { limit: asked, cursor, kind } = parseQuery(artifactPageQuery, c.req.query());
352
+ if (asked === undefined)
342
353
  return fail(400, "Pagination requires limit");
354
+ const limit = await pageSize(c.env.tenant, asked);
343
355
  return jsonResponse(200, await readStoreOf(c.env.tenant).artifacts({ sessionId, kind, labels: labelsOf(c.req.queries("label")) ?? {} }, { limit, cursor }, readAccess(c.get("scope"))));
344
356
  }
345
357
  return jsonResponse(200, await listArtifacts(c.env.tenant, sessionId === undefined ? {} : { sessionId }, accessOf(c.get("scope"))));
@@ -457,7 +469,7 @@ export function artifactRoutes(api) {
457
469
  responses: { 200: json(ArtifactLink, "The link") },
458
470
  }, async (c) => {
459
471
  const ctx = c.env.tenant;
460
- const request = CreateArtifactLinkRequestSchema.parse(await readJson(c.req.raw));
472
+ const request = CreateArtifactLinkRequestSchema.parse(await readJson(c));
461
473
  const id = c.req.param("artifactId");
462
474
  const { artifact, version } = await ctx.store.tx(async (t) => {
463
475
  const artifact = await readableArtifact(t, id, accessOf(c.get("scope")));
@@ -528,7 +540,7 @@ export function artifactRoutes(api) {
528
540
  responses: { 200: json(TenantArtifactsView, "The limits now in force") },
529
541
  }, async (c) => {
530
542
  const ctx = c.env.tenant;
531
- const { requestId: _requestId, ...config } = PutTenantArtifactsRequestSchema.parse(await readJson(c.req.raw));
543
+ const { requestId: _requestId, ...config } = PutTenantArtifactsRequestSchema.parse(await readJson(c));
532
544
  await ctx.store.tx((t) => writeArtifactsConfig(t, config));
533
545
  return jsonResponse(200, await artifactsView(ctx));
534
546
  });
@@ -26,7 +26,7 @@ export function coverageRoutes(api) {
26
26
  404: json(Rejected, "No such agent, or no such Environment"),
27
27
  },
28
28
  }, async (c) => {
29
- const request = CredentialCoverageRequestSchema.parse(await readJson(c.req.raw));
29
+ const request = CredentialCoverageRequestSchema.parse(await readJson(c));
30
30
  const tenant = c.env.tenant;
31
31
  const definition = (await tenant.store.tx((t) => t.get("definitions", request.agentId))) ?? fail(404, "Definition not found");
32
32
  return jsonResponse(200, await tenant.vault.coverage(definition.manifest, request));
@@ -70,7 +70,7 @@ export function environmentManifestRoutes(api) {
70
70
  },
71
71
  }, async (c) => {
72
72
  const name = nameOf(c.req.param("name"));
73
- const body = PutEnvironmentManifestRequestSchema.parse(await readJson(c.req.raw));
73
+ const body = PutEnvironmentManifestRequestSchema.parse(await readJson(c));
74
74
  const ifMatch = ifMatchOf(c.req.header("if-match"));
75
75
  const options = ifMatch === undefined ? {} : { ifMatch };
76
76
  return jsonResponse(200, c.req.query("dryRun") === "true"
@@ -88,7 +88,7 @@ export function environmentRoutes(api) {
88
88
  },
89
89
  }, async (c) => {
90
90
  const id = idOf(c.req.param("environmentId"));
91
- const body = PutEnvironmentRequestSchema.parse(await readJson(c.req.raw));
91
+ const body = PutEnvironmentRequestSchema.parse(await readJson(c));
92
92
  return jsonResponse(200, await putEnvironment(c.env.tenant, id, body, c.get("scope")));
93
93
  });
94
94
  tenantRoute(api, READ, {
@@ -105,7 +105,7 @@ export function environmentRoutes(api) {
105
105
  path: "/v1/environments/{environmentId}/events",
106
106
  tags: ["Environments"],
107
107
  summary: "Read an Environment's events",
108
- description: "`environment.created`, `.attached`, `.detached`, `.deleted`, a pod's `.running`, `.suspended`, `.relaunched`, `.lost`, `.reset` and `.failed`, and `environment.egress` for every connection its sandbox opens through egress-gate, naming the turns that were running (D67), in order, numbered from 0, at most 1000 per call.",
108
+ description: "`environment.created`, `.attached`, `.detached`, `.deleted`, a pod's `.running`, `.suspended`, `.relaunched`, `.lost`, `.reset` and `.failed`, and `environment.egress` for every connection its sandbox opens through egress-gate, naming the turns that were running (D67), in order, numbered from 0, at most the Tenant's Runtime limit `environmentEventItems` (default 1000) per call: `from` reads on.",
109
109
  request: {
110
110
  params: environmentId,
111
111
  query: z.object({
@@ -213,7 +213,7 @@ export function environmentRoutes(api) {
213
213
  409: { description: "A turn or another copy holds the disk (`environment_busy`)" },
214
214
  },
215
215
  }, async (c) => {
216
- const body = RestoreEnvironmentRequestSchema.parse(await readJson(c.req.raw));
216
+ const body = RestoreEnvironmentRequestSchema.parse(await readJson(c));
217
217
  return jsonResponse(200, await restoreEnvironment(c.env.tenant, idOf(c.req.param("environmentId")), c.get("scope"), body.version));
218
218
  });
219
219
  tenantRoute(api, WRITE, {
@@ -234,7 +234,7 @@ export function environmentRoutes(api) {
234
234
  409: { description: "The id exists, or a turn or another copy holds the source's disk (`environment_busy`)" },
235
235
  },
236
236
  }, async (c) => {
237
- const body = ForkEnvironmentRequestSchema.parse(await readJson(c.req.raw));
237
+ const body = ForkEnvironmentRequestSchema.parse(await readJson(c));
238
238
  const answer = await forkEnvironment(c.env.tenant, idOf(c.req.param("environmentId")), body, c.get("scope"));
239
239
  return jsonResponse("dryRun" in answer ? 200 : 201, answer);
240
240
  });
@@ -295,7 +295,7 @@ export function environmentRoutes(api) {
295
295
  path: "/v1/environments/{environmentId}/secrets/{name}",
296
296
  tags: ["Environments"],
297
297
  summary: "Write an Environment's secret",
298
- description: "Creates or replaces one credential of the Environment's vault: an `environment_secret` (the variable `name` reads the sentinel `nylorun-managed` in the sandbox, and egress-gate sets the value as a header on requests to `allowedHosts`), an `environment_variable` (a plain variable), or a `bearer` token or `headers` map for the MCP servers and HTTP tools at `url`. The same name and type re-seals the value and binding; another type replaces it. A rotated value is used from the next request. A second credential for a host or a URL is `409 credential_conflict`. When what the Environment runs declares secret slots (protocol 14, D64), send only the value (`{ value }`, or `{ headers }` for a `headers` slot): the type and binding come from the slot, and a name it does not declare is `409 secret_not_in_manifest`.",
298
+ description: "Creates or replaces one credential of the Environment's vault: an `environment_secret` (the variable `name` reads the sentinel `nylorun_managed` in the sandbox, and egress-gate sets the value as a header on requests to `allowedHosts`), an `environment_variable` (a plain variable), or a `bearer` token or `headers` map for the MCP servers and HTTP tools at `url`. The same name and type re-seals the value and binding; another type replaces it. A rotated value is used from the next request. A second credential for a host or a URL is `409 credential_conflict`. When what the Environment runs declares secret slots (protocol 14, D64), send only the value (`{ value }`, or `{ headers }` for a `headers` slot): the type and binding come from the slot, and a name it does not declare is `409 secret_not_in_manifest`.",
299
299
  request: {
300
300
  params: secretPath,
301
301
  body: {
@@ -312,7 +312,7 @@ export function environmentRoutes(api) {
312
312
  const scope = c.get("scope");
313
313
  assertReaches(scope, id);
314
314
  const name = c.req.param("name") ?? "";
315
- const body = await secretRequestFor(c.env.tenant, id, name, await readJson(c.req.raw));
315
+ const body = await secretRequestFor(c.env.tenant, id, name, await readJson(c));
316
316
  return jsonResponse(200, await c.env.tenant.keys.putEnvironmentSecret(id, name, body, actorOf(scope)));
317
317
  });
318
318
  tenantRoute(api, WRITE, {
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Definition files (track R2 M4): `PUT /v1/files/sha256:{hex}` uploads one file a definition
3
3
  * names by its content hash (a skill's), `HEAD` says whether the Tenant holds it. Application
4
- * key only: definitions are the application's, not a person's.
4
+ * key only: definitions are the application's, not a person's. The Tenant's skill limit is
5
+ * `GET`/`PUT /v1/tenant/skills`, a Management API route.
5
6
  */
6
7
  import type { OpenAPIHono } from "@hono/zod-openapi";
7
8
  import type { TenantEnv } from "../app.js";
@@ -1,13 +1,17 @@
1
1
  import { z } from "zod";
2
- import { DEFINITION_FILE_MAX_BYTES } from "@nylorun/core/contracts";
3
- import { DefinitionFileView } from "../../components.js";
4
- import { normalizeContentType } from "../../../artifacts/media-types.js";
2
+ import { PutTenantSkillsRequestSchema } from "@nylorun/core/contracts";
3
+ import { DefinitionFileView, PutTenantSkillsRequest, TenantSkillsView } from "../../components.js";
4
+ import { readJson } from "../body.js";
5
+ import { normalizeContentType } from "@nylorun/core/contracts";
5
6
  import { hasDefinitionFile, putDefinitionFile } from "../../../tenant/definition-files.js";
7
+ import { effectiveSkillLimits, readSkillsConfig, writeSkillsConfig } from "../../../tenant/limits.js";
6
8
  import { fail } from "../../../tenant/http.js";
7
9
  import { tenantRoute } from "../define.js";
8
10
  import { jsonResponse } from "../respond.js";
9
11
  const APPLICATION = { credentials: ["application"], scopes: "never" };
10
12
  const UPLOAD = { ...APPLICATION, bytes: true };
13
+ /** The Tenant's skill limit: a Management API route (`/v1/tenant/skills`). */
14
+ const SETTINGS = { credentials: ["management"], scopes: "never" };
11
15
  const file = z.object({
12
16
  file: z.string().meta({ description: "`sha256:` and the SHA-256 of the file's bytes, 64 lowercase hex digits" }),
13
17
  });
@@ -36,7 +40,7 @@ export function fileRoutes(api) {
36
40
  path: "/v1/files/{file}",
37
41
  tags: ["Definition files"],
38
42
  summary: "Upload a definition file",
39
- description: `Stores the body, at most ${DEFINITION_FILE_MAX_BYTES} bytes, at the SHA-256 the path names; a body with another hash stores nothing (\`400\`). A file the Tenant holds already is kept as it is (\`200\`).`,
43
+ description: "Streams the body, at most the Tenant's skill limit (`/v1/tenant/skills`, default 2 GiB: one file may be as large as a whole skill), to the SHA-256 the path names; a body with another hash stores nothing (`400`). A file the Tenant holds already is kept as it is (`200`).",
40
44
  request: {
41
45
  params: file,
42
46
  body: {
@@ -48,7 +52,7 @@ export function fileRoutes(api) {
48
52
  responses: {
49
53
  200: view("The Tenant held the file already"),
50
54
  201: view("The file, stored"),
51
- 413: { description: `Larger than ${DEFINITION_FILE_MAX_BYTES} bytes (\`limit_exceeded\`)` },
55
+ 413: { description: "Larger than the Tenant's skill limit (`limit_exceeded`)" },
52
56
  },
53
57
  }, async (c) => {
54
58
  const request = c.req.raw;
@@ -74,4 +78,26 @@ export function fileRoutes(api) {
74
78
  return fail(404, "The Runtime does not hold this file");
75
79
  return new Response(null, { status: 200 });
76
80
  });
81
+ tenantRoute(api, SETTINGS, {
82
+ method: "get",
83
+ path: "/v1/tenant/skills",
84
+ tags: ["Tenant"],
85
+ summary: "Get the Tenant's skill limit",
86
+ responses: { 200: { description: "The limit in force", content: { "application/json": { schema: TenantSkillsView } } } },
87
+ }, async (c) => jsonResponse(200, { limits: effectiveSkillLimits(await c.env.tenant.store.tx((t) => readSkillsConfig(t))) }));
88
+ tenantRoute(api, SETTINGS, {
89
+ method: "put",
90
+ path: "/v1/tenant/skills",
91
+ tags: ["Tenant"],
92
+ summary: "Set the Tenant's skill limit",
93
+ description: "The most bytes one skill's files may hold together, for every agent the Tenant stores and every Environment, whose manifest may set a lower one (`limits.skills`). Unset, the limit takes the default (2 GiB). Agents already stored keep their skills; a session opens only while its agent's skills fit.",
94
+ request: {
95
+ body: { required: true, content: { "application/json": { schema: PutTenantSkillsRequest } } },
96
+ },
97
+ responses: { 200: { description: "The limit now in force", content: { "application/json": { schema: TenantSkillsView } } } },
98
+ }, async (c) => {
99
+ const { requestId: _requestId, ...config } = PutTenantSkillsRequestSchema.parse(await readJson(c));
100
+ await c.env.tenant.store.tx((t) => writeSkillsConfig(t, config));
101
+ return jsonResponse(200, { limits: effectiveSkillLimits(config) });
102
+ });
77
103
  }
@@ -26,7 +26,7 @@ export function mcpRoutes(api) {
26
26
  502: json(Rejected, "The server could not be listed (`mcp_preview_failed`): `details.failure` is the code a tool call would have failed with, such as `mcp.unreachable` for an address the Host refuses"),
27
27
  },
28
28
  }, async (c) => {
29
- const request = McpPreviewRequestSchema.parse(await readJson(c.req.raw));
29
+ const request = McpPreviewRequestSchema.parse(await readJson(c));
30
30
  return jsonResponse(200, await c.env.tenant.keys.previewMcp(request));
31
31
  });
32
32
  }
@@ -6,6 +6,15 @@ export declare const pageQuery: z.ZodObject<{
6
6
  limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
7
7
  cursor: z.ZodOptional<z.ZodString>;
8
8
  }, z.core.$strip>;
9
+ /**
10
+ * The size of a page: `asked`, or, when the query names none, `fallback`, each within the Tenant's
11
+ * Runtime limit `name` (read for each request): a page asked larger holds that many, and its
12
+ * cursor reads on.
13
+ */
14
+ export declare function pageSize(ctx: TenantEnv["Bindings"]["tenant"], asked: number | undefined, options?: {
15
+ fallback?: number;
16
+ name?: "pageItems" | "exportPageItems";
17
+ }): Promise<number>;
9
18
  export declare const sessionPageQuery: z.ZodObject<{
10
19
  limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
11
20
  cursor: z.ZodOptional<z.ZodString>;
@@ -72,6 +81,19 @@ export declare function environmentPage(ctx: TenantEnv["Bindings"]["tenant"], sc
72
81
  path: string;
73
82
  files: Record<string, string>;
74
83
  })[] | undefined;
84
+ limits?: {
85
+ artifacts?: {
86
+ fileBytes?: number | undefined;
87
+ totalBytes?: number | undefined;
88
+ } | undefined;
89
+ skills?: {
90
+ totalBytes?: number | undefined;
91
+ } | undefined;
92
+ disk?: {
93
+ versionBytes?: number | undefined;
94
+ versionEntries?: number | undefined;
95
+ } | undefined;
96
+ } | undefined;
75
97
  secrets?: Record<string, {
76
98
  required?: boolean | undefined;
77
99
  description?: string | undefined;
@@ -108,6 +130,19 @@ export declare function environmentPage(ctx: TenantEnv["Bindings"]["tenant"], sc
108
130
  manifestName?: string | undefined;
109
131
  manifestVersion?: number | undefined;
110
132
  manifestHash?: string | undefined;
133
+ limits: {
134
+ artifacts: {
135
+ fileBytes: number;
136
+ totalBytes: number;
137
+ };
138
+ skills: {
139
+ totalBytes: number;
140
+ };
141
+ disk: {
142
+ versionBytes: number;
143
+ versionEntries: number;
144
+ };
145
+ };
111
146
  forkedFrom?: {
112
147
  environment: string;
113
148
  disk: number | null;