@nylorun/runtime 0.26.0-beta → 0.28.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 (379) hide show
  1. package/CHANGELOG.md +171 -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.d.ts +4 -3
  12. package/dist/api/a2a/card.js +4 -4
  13. package/dist/api/a2a/endpoint.js +3 -4
  14. package/dist/api/a2a/protocol.js +4 -0
  15. package/dist/api/a2a/routes.d.ts +2 -6
  16. package/dist/api/a2a/routes.js +30 -25
  17. package/dist/api/ag-ui/endpoint.js +2 -3
  18. package/dist/api/ag-ui/routes.js +8 -11
  19. package/dist/api/components.d.ts +6789 -3405
  20. package/dist/api/components.js +43 -30
  21. package/dist/api/gate/keys.js +7 -4
  22. package/dist/api/gate/routes.d.ts +6 -2
  23. package/dist/api/gate/routes.js +15 -11
  24. package/dist/api/http/app.js +9 -4
  25. package/dist/api/http/body.d.ts +17 -3
  26. package/dist/api/http/body.js +35 -7
  27. package/dist/api/http/respond.js +6 -2
  28. package/dist/api/http/routes/access.js +5 -4
  29. package/dist/api/http/routes/agent-manifests.d.ts +10 -0
  30. package/dist/api/http/routes/agent-manifests.js +135 -0
  31. package/dist/api/http/routes/agents.d.ts +11 -0
  32. package/dist/api/http/routes/agents.js +418 -0
  33. package/dist/api/http/routes/artifacts.js +21 -9
  34. package/dist/api/http/routes/coverage.d.ts +4 -4
  35. package/dist/api/http/routes/coverage.js +13 -7
  36. package/dist/api/http/routes/files.d.ts +2 -1
  37. package/dist/api/http/routes/files.js +31 -5
  38. package/dist/api/http/routes/mcp.js +3 -3
  39. package/dist/api/http/routes/me.d.ts +1 -1
  40. package/dist/api/http/routes/me.js +1 -2
  41. package/dist/api/http/routes/memories.d.ts +9 -0
  42. package/dist/api/http/routes/memories.js +152 -0
  43. package/dist/api/http/routes/reads.d.ts +10 -111
  44. package/dist/api/http/routes/reads.js +51 -29
  45. package/dist/api/http/routes/sessions.js +26 -54
  46. package/dist/api/http/routes/tenant.d.ts +2 -2
  47. package/dist/api/http/routes/tenant.js +77 -24
  48. package/dist/api/http/routes/triggers.d.ts +10 -0
  49. package/dist/api/http/routes/triggers.js +180 -0
  50. package/dist/api/inbound-files.d.ts +3 -9
  51. package/dist/api/inbound-files.js +18 -24
  52. package/dist/api/openapi.js +73 -47
  53. package/dist/artifacts/disk.d.ts +10 -14
  54. package/dist/artifacts/disk.js +99 -95
  55. package/dist/artifacts/files.d.ts +13 -4
  56. package/dist/artifacts/files.js +27 -9
  57. package/dist/artifacts/folder-upload.d.ts +75 -0
  58. package/dist/artifacts/folder-upload.js +263 -0
  59. package/dist/artifacts/folders.d.ts +14 -8
  60. package/dist/artifacts/folders.js +19 -11
  61. package/dist/artifacts/links.js +7 -6
  62. package/dist/artifacts/parts.d.ts +9 -14
  63. package/dist/artifacts/parts.js +11 -9
  64. package/dist/artifacts/pipe.d.ts +15 -0
  65. package/dist/artifacts/pipe.js +71 -0
  66. package/dist/artifacts/quota.d.ts +36 -0
  67. package/dist/artifacts/quota.js +44 -0
  68. package/dist/artifacts/service.d.ts +25 -1
  69. package/dist/artifacts/service.js +72 -27
  70. package/dist/blob/fs.js +2 -1
  71. package/dist/blob/s3.d.ts +6 -2
  72. package/dist/blob/s3.js +9 -7
  73. package/dist/blob/types.d.ts +1 -1
  74. package/dist/blob/types.js +1 -1
  75. package/dist/core/flow-host.d.ts +0 -1
  76. package/dist/core/limits.d.ts +11 -35
  77. package/dist/core/limits.js +5 -73
  78. package/dist/core/sandbox-routes.js +0 -1
  79. package/dist/core/turn-manifest.d.ts +1 -2
  80. package/dist/core/turn-manifest.js +4 -28
  81. package/dist/execution/memory.d.ts +8 -5
  82. package/dist/execution/memory.js +8 -6
  83. package/dist/execution/types.d.ts +1 -6
  84. package/dist/execution/types.js +0 -5
  85. package/dist/gates/contract.d.ts +3 -2
  86. package/dist/gates/contract.js +1 -1
  87. package/dist/gates/egress-credentials.js +5 -4
  88. package/dist/gates/egress.d.ts +13 -13
  89. package/dist/gates/egress.js +19 -21
  90. package/dist/gates/fixture-model.js +13 -2
  91. package/dist/gates/handler.d.ts +1 -3
  92. package/dist/gates/handler.js +4 -3
  93. package/dist/gates/http-client.d.ts +4 -3
  94. package/dist/gates/http-client.js +5 -7
  95. package/dist/gates/http-tool.d.ts +24 -4
  96. package/dist/gates/http-tool.js +41 -13
  97. package/dist/gates/in-process.d.ts +2 -1
  98. package/dist/gates/in-process.js +17 -9
  99. package/dist/gates/inflight.d.ts +2 -2
  100. package/dist/gates/inflight.js +3 -2
  101. package/dist/gates/journal.js +5 -7
  102. package/dist/gates/mcp-handler.d.ts +4 -3
  103. package/dist/gates/mcp-handler.js +15 -5
  104. package/dist/gates/meter.js +6 -5
  105. package/dist/gates/model-gate.d.ts +11 -2
  106. package/dist/gates/policy.d.ts +34 -6
  107. package/dist/gates/policy.js +66 -18
  108. package/dist/gates/provider-gate.d.ts +22 -0
  109. package/dist/gates/provider-gate.js +30 -0
  110. package/dist/gates/tool-calls.d.ts +1 -3
  111. package/dist/gates/tool-calls.js +2 -3
  112. package/dist/gates/tool-client.d.ts +1 -1
  113. package/dist/gates/tool-client.js +5 -6
  114. package/dist/gates/tool-contract.d.ts +8 -5
  115. package/dist/gates/tool-contract.js +1 -1
  116. package/dist/gates/tool-gate.d.ts +18 -7
  117. package/dist/gates/tool-gate.js +49 -7
  118. package/dist/harness/calls.d.ts +27 -25
  119. package/dist/harness/calls.js +40 -46
  120. package/dist/harness/executors.d.ts +10 -3
  121. package/dist/harness/executors.js +53 -23
  122. package/dist/harness/main.js +2 -2
  123. package/dist/harness/pod.d.ts +2 -2
  124. package/dist/harness/pod.js +7 -6
  125. package/dist/harness/run-tokens.d.ts +4 -1
  126. package/dist/harness/run-tokens.js +6 -2
  127. package/dist/harness/service.d.ts +17 -14
  128. package/dist/harness/service.js +21 -35
  129. package/dist/harness/setup.d.ts +0 -2
  130. package/dist/harness/setup.js +21 -15
  131. package/dist/harness/ws-client.d.ts +2 -2
  132. package/dist/harness/ws-client.js +7 -5
  133. package/dist/harness/ws-port.d.ts +3 -4
  134. package/dist/harness/ws-port.js +3 -4
  135. package/dist/harness-api/artifacts.d.ts +20 -0
  136. package/dist/harness-api/artifacts.js +478 -0
  137. package/dist/harness-api/in-process.d.ts +2 -2
  138. package/dist/harness-api/in-process.js +18 -16
  139. package/dist/harness-api/record.d.ts +10 -9
  140. package/dist/harness-api/record.js +113 -157
  141. package/dist/harness-api/renew.d.ts +1 -1
  142. package/dist/harness-api/renew.js +2 -2
  143. package/dist/harness-api/server.d.ts +1 -16
  144. package/dist/harness-api/server.js +86 -73
  145. package/dist/harness-api/start.d.ts +27 -5
  146. package/dist/harness-api/start.js +102 -19
  147. package/dist/harness-api/tool-journal.d.ts +15 -10
  148. package/dist/harness-api/tool-journal.js +26 -24
  149. package/dist/harness-api/workspace.d.ts +0 -4
  150. package/dist/harness-api/workspace.js +4 -47
  151. package/dist/harness-api/ws-server.js +10 -10
  152. package/dist/host/create-host.js +2 -3
  153. package/dist/host/execution.js +2 -3
  154. package/dist/host/gates.d.ts +2 -9
  155. package/dist/host/gates.js +15 -12
  156. package/dist/host/http.d.ts +2 -4
  157. package/dist/host/http.js +5 -29
  158. package/dist/host/main.js +10 -3
  159. package/dist/host/operate.js +12 -3
  160. package/dist/host/stack-config.d.ts +11 -0
  161. package/dist/host/stack-config.js +21 -1
  162. package/dist/index.d.ts +0 -1
  163. package/dist/index.js +0 -1
  164. package/dist/infra/index.js +2 -1
  165. package/dist/infra/readiness.d.ts +0 -2
  166. package/dist/infra/readiness.js +4 -3
  167. package/dist/keys/client.d.ts +1 -0
  168. package/dist/keys/client.js +2 -3
  169. package/dist/keys/contract.d.ts +0 -2
  170. package/dist/keys/contract.js +0 -2
  171. package/dist/keys/egress-ca.d.ts +0 -2
  172. package/dist/keys/egress-ca.js +2 -3
  173. package/dist/keys/keys.d.ts +15 -4
  174. package/dist/keys/keys.js +22 -1
  175. package/dist/keys/webhooks.d.ts +25 -0
  176. package/dist/keys/webhooks.js +62 -0
  177. package/dist/keys/x509.d.ts +8 -4
  178. package/dist/keys/x509.js +14 -5
  179. package/dist/management-openapi.json +3043 -1954
  180. package/dist/mcp/connect.d.ts +35 -26
  181. package/dist/mcp/connect.js +112 -141
  182. package/dist/mcp/pool.d.ts +27 -22
  183. package/dist/mcp/pool.js +34 -48
  184. package/dist/mcp/preview.d.ts +12 -5
  185. package/dist/mcp/preview.js +43 -26
  186. package/dist/mcp/snapshot.d.ts +35 -86
  187. package/dist/mcp/snapshot.js +93 -135
  188. package/dist/memory/service.d.ts +97 -0
  189. package/dist/memory/service.js +335 -0
  190. package/dist/memory/tool.d.ts +36 -0
  191. package/dist/memory/tool.js +84 -0
  192. package/dist/model/auth-store.js +5 -3
  193. package/dist/model/capabilities.d.ts +1 -1
  194. package/dist/model/catalog.d.ts +9 -36
  195. package/dist/model/catalog.js +6 -33
  196. package/dist/model/descriptor.d.ts +51 -0
  197. package/dist/model/descriptor.js +83 -0
  198. package/dist/model/models.d.ts +0 -3
  199. package/dist/model/models.js +3 -5
  200. package/dist/model/native-blocks.js +1 -1
  201. package/dist/model/pi-model.d.ts +16 -5
  202. package/dist/model/pi-model.js +86 -105
  203. package/dist/openapi.json +13653 -9986
  204. package/dist/reads/cursor.js +3 -1
  205. package/dist/reads/types.d.ts +3 -3
  206. package/dist/record/agent.d.ts +27 -0
  207. package/dist/record/agent.js +46 -0
  208. package/dist/record/append.d.ts +34 -2
  209. package/dist/record/append.js +50 -1
  210. package/dist/record/index.d.ts +2 -2
  211. package/dist/record/index.js +2 -2
  212. package/dist/redact.d.ts +1 -1
  213. package/dist/redact.js +3 -2
  214. package/dist/sandbox/egress-token.d.ts +3 -3
  215. package/dist/sandbox/egress-token.js +3 -3
  216. package/dist/sandbox/join.js +8 -7
  217. package/dist/sandbox/manager.d.ts +41 -41
  218. package/dist/sandbox/manager.js +112 -44
  219. package/dist/sandbox/placement.d.ts +2 -2
  220. package/dist/sandbox/placement.js +7 -10
  221. package/dist/sandbox/pods/client.d.ts +1 -10
  222. package/dist/sandbox/pods/client.js +8 -4
  223. package/dist/sandbox/pods/lifecycle.d.ts +25 -17
  224. package/dist/sandbox/pods/lifecycle.js +51 -29
  225. package/dist/sandbox/pods/network-gate.d.ts +4 -5
  226. package/dist/sandbox/pods/network-gate.js +7 -7
  227. package/dist/sandbox/pods/reconcile.js +14 -3
  228. package/dist/sandbox/pods/spec.js +8 -5
  229. package/dist/sandbox/policy.d.ts +7 -1
  230. package/dist/sandbox/policy.js +10 -3
  231. package/dist/sandbox/resolve.d.ts +11 -6
  232. package/dist/sandbox/resolve.js +19 -9
  233. package/dist/sandbox/setup.d.ts +6 -2
  234. package/dist/sandbox/setup.js +47 -14
  235. package/dist/sandbox/share.d.ts +5 -14
  236. package/dist/sandbox/share.js +5 -34
  237. package/dist/sandbox/skills.d.ts +7 -13
  238. package/dist/sandbox/skills.js +16 -31
  239. package/dist/sandbox/tenant-config.d.ts +2 -2
  240. package/dist/sandbox/tenant-config.js +4 -3
  241. package/dist/sandbox/tools.d.ts +7 -1
  242. package/dist/sandbox/tools.js +26 -26
  243. package/dist/sandbox/types.d.ts +10 -3
  244. package/dist/sandbox/types.js +9 -0
  245. package/dist/store/postgres/connect.d.ts +6 -5
  246. package/dist/store/postgres/connect.js +14 -11
  247. package/dist/store/postgres/control.js +13 -13
  248. package/dist/store/postgres/drizzle/0028_artifact_write_keys.sql +2 -0
  249. package/dist/store/postgres/drizzle/0029_protocol_15.sql +11 -0
  250. package/dist/store/postgres/drizzle/0030_protocol_15_runtime_block.sql +11 -0
  251. package/dist/store/postgres/drizzle/0031_protocol_15_mcp_snapshot.sql +8 -0
  252. package/dist/store/postgres/drizzle/0032_agents.sql +54 -0
  253. package/dist/store/postgres/drizzle/0033_agent_versions.sql +7 -0
  254. package/dist/store/postgres/drizzle/0034_protocol_17_session_queue.sql +13 -0
  255. package/dist/store/postgres/drizzle/0035_t4_triggers.sql +41 -0
  256. package/dist/store/postgres/drizzle/0036_t5_memories.sql +30 -0
  257. package/dist/store/postgres/drizzle/meta/_journal.json +63 -0
  258. package/dist/store/postgres/reads.js +17 -82
  259. package/dist/store/postgres/record-writer.d.ts +4 -4
  260. package/dist/store/postgres/record-writer.js +9 -9
  261. package/dist/store/postgres/schema.d.ts +1382 -151
  262. package/dist/store/postgres/schema.js +191 -37
  263. package/dist/store/postgres/store.js +384 -105
  264. package/dist/store/postgres/tenant.js +1 -2
  265. package/dist/store/types.d.ts +172 -57
  266. package/dist/store/types.js +0 -1
  267. package/dist/streams/relay/core.d.ts +3 -3
  268. package/dist/streams/relay/core.js +9 -10
  269. package/dist/tenant/advance.js +41 -39
  270. package/dist/tenant/agent-manifests.d.ts +72 -0
  271. package/dist/tenant/agent-manifests.js +359 -0
  272. package/dist/tenant/agent-versions.d.ts +126 -0
  273. package/dist/tenant/agent-versions.js +389 -0
  274. package/dist/tenant/agents.d.ts +230 -0
  275. package/dist/tenant/{environments.js → agents.js} +493 -328
  276. package/dist/tenant/auth.d.ts +1 -1
  277. package/dist/tenant/auth.js +3 -3
  278. package/dist/tenant/commands.d.ts +63 -2
  279. package/dist/tenant/commands.js +240 -90
  280. package/dist/tenant/context.d.ts +57 -33
  281. package/dist/tenant/context.js +6 -2
  282. package/dist/tenant/definition-files.d.ts +25 -4
  283. package/dist/tenant/definition-files.js +85 -47
  284. package/dist/tenant/effects.js +15 -51
  285. package/dist/tenant/ephemeral.js +2 -1
  286. package/dist/tenant/history.d.ts +1 -1
  287. package/dist/tenant/history.js +1 -1
  288. package/dist/tenant/host-token.d.ts +3 -3
  289. package/dist/tenant/host-token.js +11 -10
  290. package/dist/tenant/http.d.ts +5 -8
  291. package/dist/tenant/http.js +9 -0
  292. package/dist/tenant/identity-file.d.ts +29 -6
  293. package/dist/tenant/identity-file.js +45 -15
  294. package/dist/tenant/issuers.d.ts +5 -5
  295. package/dist/tenant/issuers.js +34 -26
  296. package/dist/tenant/jwt.d.ts +8 -2
  297. package/dist/tenant/jwt.js +10 -2
  298. package/dist/tenant/limits.d.ts +87 -0
  299. package/dist/tenant/limits.js +172 -0
  300. package/dist/tenant/memories.d.ts +38 -0
  301. package/dist/tenant/memories.js +119 -0
  302. package/dist/tenant/module.d.ts +4 -1
  303. package/dist/tenant/module.js +9 -8
  304. package/dist/tenant/outbound.d.ts +11 -14
  305. package/dist/tenant/outbound.js +10 -15
  306. package/dist/tenant/reset.js +2 -2
  307. package/dist/tenant/run-grants.d.ts +6 -0
  308. package/dist/tenant/run-grants.js +7 -2
  309. package/dist/tenant/run-token.d.ts +0 -4
  310. package/dist/tenant/run-token.js +6 -11
  311. package/dist/tenant/runtime-limits.d.ts +24 -0
  312. package/dist/tenant/runtime-limits.js +27 -0
  313. package/dist/tenant/runtime.d.ts +1 -1
  314. package/dist/tenant/runtime.js +38 -43
  315. package/dist/tenant/session-streams.js +7 -6
  316. package/dist/tenant/session.d.ts +1 -1
  317. package/dist/tenant/session.js +1 -1
  318. package/dist/tenant/sessions.d.ts +28 -45
  319. package/dist/tenant/sessions.js +89 -209
  320. package/dist/tenant/signing-keys.d.ts +1 -1
  321. package/dist/tenant/signing-keys.js +5 -6
  322. package/dist/tenant/status.js +10 -10
  323. package/dist/tenant/streams.js +18 -20
  324. package/dist/tenant/sweep.d.ts +1 -21
  325. package/dist/tenant/sweep.js +51 -51
  326. package/dist/tenant/transcript.d.ts +70 -23
  327. package/dist/tenant/transcript.js +28 -22
  328. package/dist/tenant/triggers.d.ts +143 -0
  329. package/dist/tenant/triggers.js +715 -0
  330. package/dist/tenant/turn-timing.d.ts +11 -1
  331. package/dist/tenant/turn-timing.js +3 -1
  332. package/dist/tenant/types.d.ts +9 -14
  333. package/dist/tenant/worker.d.ts +4 -10
  334. package/dist/tenant/worker.js +10 -14
  335. package/dist/traces/ids.js +5 -1
  336. package/dist/traces/map.d.ts +10 -7
  337. package/dist/traces/map.js +16 -12
  338. package/dist/traces/otlp.d.ts +3 -3
  339. package/dist/traces/otlp.js +5 -3
  340. package/dist/traces/projector.d.ts +9 -4
  341. package/dist/traces/projector.js +13 -7
  342. package/dist/traces/read.js +6 -1
  343. package/dist/tuning.d.ts +390 -0
  344. package/dist/tuning.js +677 -0
  345. package/dist/vault/headers.js +4 -2
  346. package/dist/vault/service.d.ts +13 -8
  347. package/dist/vault/service.js +61 -17
  348. package/dist/version.d.ts +1 -1
  349. package/dist/version.js +1 -1
  350. package/package.json +13 -12
  351. package/dist/api/http/routes/environment-manifests.d.ts +0 -9
  352. package/dist/api/http/routes/environment-manifests.js +0 -118
  353. package/dist/api/http/routes/environments.d.ts +0 -11
  354. package/dist/api/http/routes/environments.js +0 -332
  355. package/dist/artifacts/export.d.ts +0 -8
  356. package/dist/artifacts/export.js +0 -204
  357. package/dist/artifacts/media-types.d.ts +0 -30
  358. package/dist/artifacts/media-types.js +0 -137
  359. package/dist/artifacts/workspace.d.ts +0 -60
  360. package/dist/artifacts/workspace.js +0 -45
  361. package/dist/media.d.ts +0 -10
  362. package/dist/media.js +0 -58
  363. package/dist/record/environment.d.ts +0 -25
  364. package/dist/record/environment.js +0 -44
  365. package/dist/sandbox/runtime-tools.d.ts +0 -9
  366. package/dist/sandbox/runtime-tools.js +0 -16
  367. package/dist/sandbox/session-sandbox.d.ts +0 -16
  368. package/dist/sandbox/session-sandbox.js +0 -77
  369. package/dist/tenant/artifact-tool.d.ts +0 -13
  370. package/dist/tenant/artifact-tool.js +0 -243
  371. package/dist/tenant/environment-manifests.d.ts +0 -57
  372. package/dist/tenant/environment-manifests.js +0 -200
  373. package/dist/tenant/environments.d.ts +0 -174
  374. package/dist/tenant/skill-tool.d.ts +0 -20
  375. package/dist/tenant/skill-tool.js +0 -67
  376. package/dist/tenant/tool-results.d.ts +0 -57
  377. package/dist/tenant/tool-results.js +0 -298
  378. package/dist/tenant/tool-search.d.ts +0 -39
  379. package/dist/tenant/tool-search.js +0 -103
@@ -19,8 +19,6 @@ import type { IssuerScope, SubjectScope, TenantEnvelope } from "@nylorun/core/co
19
19
  import type { DurableCheckpoint, FlowCheckpoint } from "@nylorun/harness/run";
20
20
  import type { AgentManifest, JsonValue, SandboxManifest } from "@nylorun/core/define";
21
21
  import type { OutboxRequest, SessionStore, Tx } from "../store/types.js";
22
- import type { FlowLimits } from "../core/limits.js";
23
- import type { ModelProvider } from "../core/provider.js";
24
22
  import type { ModelGate } from "../gates/model-gate.js";
25
23
  import type { ToolGate } from "../gates/tool-gate.js";
26
24
  import type { Keys } from "../keys/keys.js";
@@ -37,25 +35,33 @@ import type { StuckInvocation, Wake } from "../execution/types.js";
37
35
  import type { WorkState } from "./scheduler.js";
38
36
  import type { SigningKeys } from "./signing-keys.js";
39
37
  import type { BlobStore } from "../blob/index.js";
40
- import type { WorkspaceReader } from "../artifacts/workspace.js";
41
38
  import type { RunGrants } from "./run-grants.js";
42
39
  import type { TraceOptions } from "../traces/options.js";
43
40
  import type { TraceContext } from "../traces/ids.js";
44
41
  export interface Session {
45
42
  id: string;
43
+ /** The Agent the session runs on (protocol 16; a definition id before). */
46
44
  agentId: string;
47
45
  ownerUserId: string;
48
- /** Session pin — the manifest the session was created with. */
46
+ /**
47
+ * Session pin: the loop manifest the session runs, its Agent's manifest version's harness
48
+ * section as the harness runs it (`loopManifestOf`), or a flow's leaf agent.
49
+ */
49
50
  manifest: any;
50
51
  manifestHash: string;
51
52
  /**
52
- * The hash of the definition the session was opened from; `manifestHash` differs when the
53
- * Runtime pinned its `runtime` block on it (R2b C11). Absent on older sessions.
53
+ * The agent manifest version the session runs (protocol 16): its Agent's when it opened, and
54
+ * again at a turn's first segment when its Agent's version changed since (T3, `repinTurn`).
55
+ * Absent on a session opened before protocol 16.
54
56
  */
55
- definitionHash?: string;
57
+ definition?: {
58
+ name: string;
59
+ version: number;
60
+ };
61
+ /** The pinned version's `harness.loop`: passed to the harness, never read by the Runtime. */
62
+ loop?: Record<string, unknown>;
56
63
  /** Validated turn-manifest variants, keyed by hash (loops.md §4.2). */
57
64
  variants?: Record<string, AgentManifest>;
58
- implementationVersion: string;
59
65
  info?: any;
60
66
  status: string;
61
67
  activeTurnId: string | null;
@@ -86,26 +92,35 @@ export interface Session {
86
92
  * and the context core hands on (to the harness, tools and sandbox commands) is in it.
87
93
  */
88
94
  turnTrace?: TraceContext;
95
+ /**
96
+ * What started the active turn when not a client (track T4): the trigger's run, or the session's
97
+ * own booked wake. A memory version written in the turn names its run (track T5).
98
+ */
99
+ turnCause?: {
100
+ kind: "trigger" | "self";
101
+ triggerId: string;
102
+ runId: string;
103
+ };
89
104
  creation: unknown;
90
105
  mcpSnapshot?: McpSnapshot;
91
106
  mcpDiagnostics?: readonly McpDiagnostic[];
92
107
  /**
93
- * The Environment the session names (`environment`, protocol 11): its sandbox is the
94
- * session's (the Environment's id keys the workspace) and its vault holds the session's
108
+ * The Agent's environment the session runs on: since protocol 16 always its Agent's id. Its
109
+ * sandbox is the session's (the id keys the workspace) and its vault holds the session's
95
110
  * credentials. It outlives the session.
96
111
  */
97
112
  environmentId?: string;
98
- /** The Environment's recipe version when the session opened (shown, never enforced). */
113
+ /** The Agent's recipe version when the session last pinned (shown, never enforced). */
99
114
  environmentVersion?: number;
100
115
  /**
101
- * The harness that runs the session's turns (R4.1), pinned when it opened: its Environment's
102
- * harness, else `nylorun`. Absent on a session opened before R4: ours (`harnessOf`).
116
+ * The harness that runs the session's turns (R4.1), pinned when it opened: its manifest's
117
+ * `harness.id`, else `nylorun`. Absent on a session opened before R4: ours (`harnessOf`).
103
118
  */
104
119
  harness?: string;
105
120
  /**
106
121
  * A flow agent's linked session: the session whose turn opened the flow tree. Its sessions
107
122
  * share the tree's Environment, and their turns nest in the root's, so they do not hold the
108
- * Environment against each other (`checkEnvironmentTurn`).
123
+ * Environment against each other (`checkAgentTurn`).
109
124
  */
110
125
  flowRootId?: string;
111
126
  /**
@@ -115,8 +130,10 @@ export interface Session {
115
130
  sandbox?: SandboxManifest;
116
131
  /**
117
132
  * Why the session takes no new turn: `protocol_11` for a session opened before protocol 11
118
- * (migration 0020), `protocol_13` for one opened before protocol 13 (migration 0024). Its
119
- * history stays readable.
133
+ * (migration 0020), `protocol_13` for one opened before protocol 13 (migration 0024),
134
+ * `protocol_15` for an agent session that pinned a `runtime` block before protocol 15
135
+ * (migrations 0029, 0030), `protocol_16` for one opened from a definition before protocol 16
136
+ * (migration 0032). Its history stays readable.
120
137
  */
121
138
  closedReason?: string;
122
139
  /**
@@ -140,7 +157,7 @@ export type AuthScope = {
140
157
  }
141
158
  /**
142
159
  * A trusted issuer's token (Host feature `trusted-issuers`, F9-D12): one subject, with the
143
- * issuer's scopes, agents and Environment grants, until `expiresAt` (ms). Only its expiry ends it.
160
+ * issuer's scopes and Agent grants, until `expiresAt` (ms). Only its expiry ends it.
144
161
  */
145
162
  | {
146
163
  kind: "token";
@@ -149,9 +166,8 @@ export type AuthScope = {
149
166
  subject: string;
150
167
  /** The issuer's scopes the token holds, which may add `studio`. */
151
168
  scopes: ReadonlySet<IssuerScope>;
152
- agents: ReadonlySet<string> | "*";
153
- /** The Environments it reaches: exact ids or `p/*` prefixes. Absent or empty reaches none. */
154
- environments?: readonly string[];
169
+ /** The Agents it reaches: `*`, else exact ids or `p/*` prefixes; empty reaches none. */
170
+ agents: readonly string[] | "*";
155
171
  expiresAt: number;
156
172
  /** The token's `jti`, or a hash of it. */
157
173
  tokenId: string;
@@ -185,11 +201,15 @@ export interface TenantContext {
185
201
  * else the harness that serves workspaces (`harness-api/workspace.ts`).
186
202
  */
187
203
  readonly sandbox: WorkspacePort;
188
- readonly flowLimits: FlowLimits;
189
- readonly modelProvider: ModelProvider;
190
- /** True when the model comes from the Tenant vault selection, served by `modelGate`. */
191
- readonly useVaultModel: boolean;
192
- /** Serves vault-backed model calls (blueprint §15): in this process, or the gates service. */
204
+ /**
205
+ * True when the Runtime's model is not the vault's (scripted, the fixture model, an embedder's
206
+ * provider): `modelGate` serves it, and no vault model need be configured.
207
+ */
208
+ readonly scriptedModel: boolean;
209
+ /**
210
+ * Serves every model call (blueprint §15, protocol 15): the vault's model in this process or
211
+ * the gates service, or a scripted model (`providerModelGate`).
212
+ */
193
213
  readonly modelGate: ModelGate;
194
214
  /**
195
215
  * Serves remote MCP servers and HTTP tools (blueprint §12, F4.1): in this process, or the
@@ -208,11 +228,6 @@ export interface TenantContext {
208
228
  * they mean, and a blob counts once a committed row names its key.
209
229
  */
210
230
  readonly blobs: BlobStore;
211
- /**
212
- * How core reads a session's sandbox workspace at turn end, to export its outputs (F8.2): over
213
- * this process's `sandbox` today; over the Harness API's `workspace.read` from F6.2.
214
- */
215
- readonly workspaces: WorkspaceReader;
216
231
  /**
217
232
  * How the trace route (R7.5) makes spans: the resource and the content the installation exports
218
233
  * (R7.2). Absent: `service.name` `nylorun`, no content.
@@ -267,7 +282,7 @@ export interface TenantContext {
267
282
  abortLocal(sessionId: string, turnId?: string): void;
268
283
  /**
269
284
  * Sandbox pods (F7.2): the sandboxes service and the Runtime image pods copy the engine from.
270
- * Absent without a cluster (`nylorun local sandbox enable`): kind `pod` is `environment_unavailable`.
285
+ * Absent without a cluster (`nylorun local sandbox enable`): kind `pod` is `agent_unavailable`.
271
286
  */
272
287
  readonly pods?: TenantPods;
273
288
  /**
@@ -277,6 +292,12 @@ export interface TenantContext {
277
292
  * sent); `true` without sandbox pods, where there is nothing to send.
278
293
  */
279
294
  sandboxSignal(sandboxId: string, signal: SandboxSignal): Promise<boolean>;
295
+ /**
296
+ * Seam: arm a durable timer (`DurableExecution.timer`; track T4's triggers), outside any tx. The
297
+ * latest time for a key wins. `false` while the Tenant is closing (not armed): what it was for
298
+ * is in Postgres, and the sweep arms it again.
299
+ */
300
+ timer(key: string, at: Date): Promise<boolean>;
280
301
  /** This Tenant's execution invocations that need an operator, for Tenant status. */
281
302
  readonly stuckInvocations?: () => Promise<StuckInvocation[]>;
282
303
  /** Callbacks the Tenant sweep runs after its own steps (`sweep.ts`). */
@@ -286,12 +307,15 @@ export interface TenantContext {
286
307
  }
287
308
  /**
288
309
  * What a request acting for a person may reach: that person's sessions, and, for a token
289
- * caller, only sessions of the agents its issuer allows. Undefined means the whole Tenant.
310
+ * caller, only sessions on the Agents its grants reach (ids and `p/*` prefixes). Undefined means
311
+ * the whole Tenant.
290
312
  */
291
313
  export interface SessionAccess {
292
314
  readonly owner: string;
293
- readonly agents?: ReadonlySet<string>;
315
+ readonly agents?: readonly string[];
294
316
  }
317
+ /** Whether `access` reaches sessions on Agent `agentId`. */
318
+ export declare function reachesAgent(access: SessionAccess | undefined, agentId: string): boolean;
295
319
  /** The session, or a 404. Reads without locking. */
296
320
  export declare function sessionOf(t: Tx, id: string, access?: SessionAccess): Promise<Session>;
297
321
  /** Locks the session for the rest of the transaction and returns it, or a 404. */
@@ -1,5 +1,9 @@
1
- import { DEFAULT_HARNESS } from "@nylorun/core/contracts";
1
+ import { DEFAULT_HARNESS, agentGranted } from "@nylorun/core/contracts";
2
2
  import { fail } from "./http.js";
3
+ /** Whether `access` reaches sessions on Agent `agentId`. */
4
+ export function reachesAgent(access, agentId) {
5
+ return access?.agents === undefined || agentGranted(access.agents, agentId);
6
+ }
3
7
  /**
4
8
  * `access`, when set, limits the request to the owner's sessions of the allowed agents:
5
9
  * anything else is the same 404 as a missing session, so a subject cannot learn which session
@@ -9,7 +13,7 @@ function owned(session, access) {
9
13
  if (!session ||
10
14
  (access !== undefined &&
11
15
  (session.ownerUserId !== access.owner ||
12
- (access.agents !== undefined && !access.agents.has(session.agentId)))))
16
+ !reachesAgent(access, session.agentId))))
13
17
  return fail(404, "Session not found");
14
18
  return session;
15
19
  }
@@ -1,5 +1,5 @@
1
1
  import { type DefinitionFileView } from "@nylorun/core/contracts";
2
- import type { BlobStore } from "../blob/index.js";
2
+ import { type BlobStore } from "../blob/index.js";
3
3
  import type { Tx } from "../store/types.js";
4
4
  import type { TenantContext } from "./context.js";
5
5
  /** Where a definition file's bytes are in the Object store. */
@@ -8,7 +8,10 @@ export declare function definitionFileKey(sha256: string): string;
8
8
  export declare function hasDefinitionFile(ctx: TenantContext, file: string): Promise<boolean>;
9
9
  /**
10
10
  * Stores the bytes of definition file `file`: `201` when they are new, `200` when the Tenant
11
- * holds them already (the body is not read). Bytes that do not hash to `file` are a `400`.
11
+ * holds them already (the body is not read). Bytes that do not hash to `file` are a `400`; more
12
+ * than the Tenant's skill limit (`skills.config`) a `413`. The body streams to a staging key and is copied to
13
+ * the file's key only once its hash is checked, so no file is held in memory and bytes of
14
+ * another hash never replace a file at its key.
12
15
  */
13
16
  export declare function putDefinitionFile(ctx: TenantContext, file: string, request: {
14
17
  body: ReadableStream<Uint8Array> | null;
@@ -18,7 +21,25 @@ export declare function putDefinitionFile(ctx: TenantContext, file: string, requ
18
21
  status: 200 | 201;
19
22
  view: DefinitionFileView;
20
23
  }>;
21
- /** The definition files `document` names that the Tenant does not hold, in order. */
22
- export declare function missingDefinitionFiles(t: Tx, document: unknown): Promise<string[]>;
24
+ /**
25
+ * Why `document` cannot be stored for the files it names: the files the Tenant does not hold
26
+ * (`missing`), else each skill whose files hold more than `limitBytes` together (`oversized`).
27
+ * A file a skill names at two paths counts twice: a sandbox holds both.
28
+ */
29
+ export declare function definitionFileIssues(t: Tx, document: unknown, limitBytes: number): Promise<{
30
+ missing: string[];
31
+ oversized: {
32
+ name: string;
33
+ bytes: number;
34
+ }[];
35
+ }>;
36
+ /** A definition file's bytes as a stream, or undefined when the Object store does not have them. */
37
+ export declare function openDefinitionFile(blobs: BlobStore, sha256: string, options?: {
38
+ range?: {
39
+ start: number;
40
+ end?: number;
41
+ };
42
+ signal?: AbortSignal;
43
+ }): Promise<ReadableStream<Uint8Array> | undefined>;
23
44
  /** A definition file's bytes, or undefined when the Object store does not have them. */
24
45
  export declare function readDefinitionFile(blobs: BlobStore, sha256: string, signal?: AbortSignal): Promise<Uint8Array | undefined>;
@@ -3,15 +3,22 @@
3
3
  * today a skill's folder (`SkillManifest.files`). A client uploads each one once
4
4
  * (`PUT /v1/files/sha256:<hex>`); its bytes go to the Object store at
5
5
  * `definitions/sha256/<hex>`, and a `definition_files` row says the Tenant holds it. A
6
- * definition naming a file the Tenant does not hold is refused (`definition_files_missing`).
7
- * The Runtime reads them to serve the skill tools and to give a sandbox the skills' files.
6
+ * definition naming a file the Tenant does not hold is refused (`definition_files_missing`), and
7
+ * one whose skill's files hold more than the Tenant's skill limit together (`limit_exceeded`,
8
+ * `skills.config`, default 2 GiB). One file may be as large as a whole skill.
9
+ * The Runtime serves them to a run's harness (`definition.file`: our engine's skill tools read
10
+ * them) and gives a sandbox the skills' files.
8
11
  *
9
12
  * Files are never deleted here: `definition_file_uses` records which definition version names
10
13
  * which file, for a later sweep.
11
14
  */
12
- import { createHash } from "node:crypto";
13
- import { DEFINITION_FILE_MAX_BYTES, definitionFilesOf, isDefinitionFileHash, } from "@nylorun/core/contracts";
15
+ import { randomUUID } from "node:crypto";
16
+ import { definitionFilesOf, isDefinitionFileHash, skillsOf, } from "@nylorun/core/contracts";
17
+ import { BlobTooLargeError } from "../blob/index.js";
14
18
  import { fail } from "./http.js";
19
+ import { readSkillLimits } from "./limits.js";
20
+ /** Where an upload's bytes wait while their hash is checked; never read as a definition file. */
21
+ const STAGING_PREFIX = "definitions/uploads/";
15
22
  /** Where a definition file's bytes are in the Object store. */
16
23
  export function definitionFileKey(sha256) {
17
24
  return `definitions/sha256/${sha256.slice("sha256:".length)}`;
@@ -26,73 +33,104 @@ export async function hasDefinitionFile(ctx, file) {
26
33
  const sha256 = checkHash(file);
27
34
  return (await ctx.store.tx((t) => t.definitionFile(sha256))) !== undefined;
28
35
  }
29
- /** The body, at most `DEFINITION_FILE_MAX_BYTES`; past it, `413 limit_exceeded`. */
30
- async function readBody(body, declared) {
31
- const tooLarge = () => fail(413, `A definition file may hold at most ${DEFINITION_FILE_MAX_BYTES} bytes`, {
36
+ function tooLarge(limitBytes) {
37
+ return fail(413, `A definition file may hold at most ${limitBytes} bytes, the Tenant's limit for a whole skill`, {
32
38
  code: "limit_exceeded",
33
- details: { limitBytes: DEFINITION_FILE_MAX_BYTES },
39
+ details: { limitBytes },
34
40
  });
35
- if (declared !== undefined && declared > DEFINITION_FILE_MAX_BYTES) {
36
- await body?.cancel().catch(() => undefined);
37
- tooLarge();
38
- }
39
- if (body === null)
40
- return new Uint8Array();
41
- const chunks = [];
42
- let size = 0;
43
- const reader = body.getReader();
44
- for (;;) {
45
- const { done, value } = await reader.read();
46
- if (done)
47
- break;
48
- size += value.byteLength;
49
- if (size > DEFINITION_FILE_MAX_BYTES) {
50
- await reader.cancel().catch(() => undefined);
51
- tooLarge();
52
- }
53
- chunks.push(value);
54
- }
55
- return Buffer.concat(chunks);
56
41
  }
57
42
  /**
58
43
  * Stores the bytes of definition file `file`: `201` when they are new, `200` when the Tenant
59
- * holds them already (the body is not read). Bytes that do not hash to `file` are a `400`.
44
+ * holds them already (the body is not read). Bytes that do not hash to `file` are a `400`; more
45
+ * than the Tenant's skill limit (`skills.config`) a `413`. The body streams to a staging key and is copied to
46
+ * the file's key only once its hash is checked, so no file is held in memory and bytes of
47
+ * another hash never replace a file at its key.
60
48
  */
61
49
  export async function putDefinitionFile(ctx, file, request, signal) {
62
50
  const sha256 = checkHash(file);
63
- const held = await ctx.store.tx((t) => t.definitionFile(sha256));
51
+ const { held, maxBytes } = await ctx.store.tx(async (t) => ({
52
+ held: await t.definitionFile(sha256),
53
+ maxBytes: (await readSkillLimits(t)).totalBytes,
54
+ }));
64
55
  if (held) {
65
56
  await request.body?.cancel().catch(() => undefined);
66
57
  return { status: 200, view: { sha256, size: held.size } };
67
58
  }
68
- const bytes = await readBody(request.body, request.declaredBytes);
69
- const actual = `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
70
- if (actual !== sha256)
71
- fail(400, `The body's SHA-256 is ${actual}, not ${sha256}: upload a file at its own hash`, {
72
- code: "invalid_request",
73
- details: { expected: sha256, actual },
74
- });
75
- // The key is the content's hash: a concurrent upload of the same file writes the same bytes.
76
- await ctx.blobs.put(definitionFileKey(sha256), bytes, {
59
+ if (request.declaredBytes !== undefined && request.declaredBytes > maxBytes) {
60
+ await request.body?.cancel().catch(() => undefined);
61
+ tooLarge(maxBytes);
62
+ }
63
+ const options = {
77
64
  ...(request.contentType === undefined ? {} : { contentType: request.contentType }),
78
65
  ...(signal ? { signal } : {}),
79
- });
66
+ };
67
+ const staging = `${STAGING_PREFIX}${randomUUID()}`;
68
+ let size;
69
+ try {
70
+ let staged;
71
+ try {
72
+ staged = await ctx.blobs.put(staging, request.body ?? new Uint8Array(), {
73
+ ...options,
74
+ maxBytes,
75
+ });
76
+ }
77
+ catch (error) {
78
+ if (error instanceof BlobTooLargeError)
79
+ tooLarge(maxBytes);
80
+ throw error;
81
+ }
82
+ const actual = `sha256:${staged.sha256}`;
83
+ if (actual !== sha256)
84
+ fail(400, `The body's SHA-256 is ${actual}, not ${sha256}: upload a file at its own hash`, {
85
+ code: "invalid_request",
86
+ details: { expected: sha256, actual },
87
+ });
88
+ const got = await ctx.blobs.get(staging, signal ? { signal } : {});
89
+ if (!got)
90
+ throw new Error(`The Object store lost the upload of ${sha256} at ${staging}`);
91
+ // The key is the content's hash: a concurrent upload of the same file writes the same bytes.
92
+ await ctx.blobs.put(definitionFileKey(sha256), got.body, options);
93
+ size = staged.size;
94
+ }
95
+ finally {
96
+ await ctx.blobs.delete(staging).catch(() => undefined);
97
+ }
80
98
  const inserted = await ctx.store.tx((t) => t.insertDefinitionFile({
81
99
  sha256,
82
100
  kind: "skill",
83
- size: bytes.byteLength,
101
+ size,
84
102
  contentType: request.contentType ?? null,
85
103
  createdAt: new Date().toISOString(),
86
104
  }));
87
- return { status: inserted ? 201 : 200, view: { sha256, size: bytes.byteLength } };
105
+ return { status: inserted ? 201 : 200, view: { sha256, size } };
88
106
  }
89
- /** The definition files `document` names that the Tenant does not hold, in order. */
90
- export async function missingDefinitionFiles(t, document) {
107
+ /**
108
+ * Why `document` cannot be stored for the files it names: the files the Tenant does not hold
109
+ * (`missing`), else each skill whose files hold more than `limitBytes` together (`oversized`).
110
+ * A file a skill names at two paths counts twice: a sandbox holds both.
111
+ */
112
+ export async function definitionFileIssues(t, document, limitBytes) {
91
113
  const named = [...definitionFilesOf(document)].sort();
92
114
  if (named.length === 0)
93
- return [];
115
+ return { missing: [], oversized: [] };
94
116
  const held = await t.heldDefinitionFiles(named);
95
- return named.filter((sha256) => !held.has(sha256));
117
+ const missing = named.filter((sha256) => !held.has(sha256));
118
+ if (missing.length > 0)
119
+ return { missing, oversized: [] };
120
+ const oversized = [];
121
+ for (const skill of skillsOf(document)) {
122
+ let bytes = 0;
123
+ for (const hash of Object.values(skill.files ?? {}))
124
+ if (typeof hash === "string")
125
+ bytes += held.get(hash) ?? 0;
126
+ if (bytes > limitBytes)
127
+ oversized.push({ name: String(skill.name), bytes });
128
+ }
129
+ return { missing, oversized };
130
+ }
131
+ /** A definition file's bytes as a stream, or undefined when the Object store does not have them. */
132
+ export async function openDefinitionFile(blobs, sha256, options = {}) {
133
+ return (await blobs.get(definitionFileKey(sha256), options))?.body;
96
134
  }
97
135
  /** A definition file's bytes, or undefined when the Object store does not have them. */
98
136
  export async function readDefinitionFile(blobs, sha256, signal) {
@@ -1,11 +1,10 @@
1
1
  import { embeddedAgent, flowDelegateManifest, hashManifest, } from "@nylorun/core/define";
2
2
  import { countActiveFlowWork, deriveAgentEffectSessionId, isFlowToolEffect, isWorkflowManifest, linkedMessageInput, linkedMessageKey, linkedTurnEnd, settleAgentEffect, } from "../core/flow-host.js";
3
3
  import { mayDispatchMore } from "../core/limits.js";
4
+ import { readRuntimeLimits } from "./runtime-limits.js";
4
5
  import { sessionCredentials } from "../vault/sources.js";
5
6
  import { isRemoteMcpCall } from "../harness/calls.js";
6
7
  import { isHttpToolCall } from "../gates/http-tool.js";
7
- import { sandboxSpecOf } from "../sandbox/share.js";
8
- import { withRuntimeTools, withSandbox } from "../sandbox/session-sandbox.js";
9
8
  import { loadSession, ownedSession, sessionOf, } from "./context.js";
10
9
  import { fail } from "./http.js";
11
10
  import { turnManifestOf } from "./session.js";
@@ -41,7 +40,7 @@ export function recoversToolCalls(ctx) {
41
40
  }
42
41
  /** True when `request` calls a tool of a declared MCP server (every one is remote) or an HTTP tool. */
43
42
  export function isGateToolEffect(s, request) {
44
- return (isRemoteMcpCall({ rootManifest: s.manifest, mcpSnapshot: s.mcpSnapshot }, request) ||
43
+ return (isRemoteMcpCall({ rootManifest: s.manifest }, request) ||
45
44
  isHttpToolCall(s.manifest, request));
46
45
  }
47
46
  /**
@@ -50,7 +49,7 @@ export function isGateToolEffect(s, request) {
50
49
  * the running call or gets its outcome, instead of becoming `uncertain`.
51
50
  */
52
51
  export function recoversModelCalls(ctx) {
53
- return ctx.useVaultModel && ctx.modelGate.recovers === true;
52
+ return ctx.modelGate.recovers === true;
54
53
  }
55
54
  /** Journal and dispatch a new flow effect (agent or tool node). */
56
55
  export async function resolveNewFlowEffect(ctx, request, signal, lease) {
@@ -87,7 +86,7 @@ export async function resolveNewFlowEffect(ctx, request, signal, lease) {
87
86
  const active = await countActiveFlowWork(t, request.sessionId, request.turnId);
88
87
  // When the run journaled the effect (R7.1); a queued effect keeps it once dispatched.
89
88
  const startedAt = existing?.startedAt ?? new Date().toISOString();
90
- if (!mayDispatchMore(active, ctx.flowLimits)) {
89
+ if (!mayDispatchMore(active, await readRuntimeLimits(t))) {
91
90
  if (!existing || existing.status !== "queued")
92
91
  await t.put("effects", request.effectId, {
93
92
  request,
@@ -162,25 +161,22 @@ export async function resolveNewFlowEffect(ctx, request, signal, lease) {
162
161
  if (exists)
163
162
  return;
164
163
  const definition = leafDefinition(workflow, body, request);
165
- // The tree's Environment reaches every agent in it: its sandbox, with its tools, and its vault.
166
- const inherited = inheritedSandbox(workflow, definition);
167
- // Without one, the agent still gets its runtime block: read_artifact (R2b C11) and its skill tools.
168
- const pinned = inherited?.manifest ? inherited : runtimeTools(definition.manifest);
164
+ // The flow's Agent (Q6) reaches every agent in the tree: its sandbox and its vault. Each leaf
165
+ // session runs on it, with the flow's manifest version, and its leaf agent's loop manifest.
166
+ const sandbox = workflow.sandbox;
169
167
  const created = {
170
168
  id: agentSessionId,
171
- agentId: body.agentId,
169
+ agentId: workflow.agentId,
172
170
  ownerUserId: workflow.ownerUserId,
173
- manifest: pinned?.manifest ?? definition.manifest,
174
- manifestHash: pinned?.manifestHash ?? definition.manifestHash,
175
- definitionHash: definition.manifestHash,
176
- implementationVersion: definition.implementationVersion,
171
+ manifest: definition.manifest,
172
+ manifestHash: definition.manifestHash,
173
+ ...(workflow.definition === undefined ? {} : { definition: workflow.definition }),
177
174
  status: "idle",
178
175
  activeTurnId: null,
179
176
  creation: {
180
177
  requestId: `flow-put-${request.effectId}`,
181
- agentId: body.agentId,
178
+ agent: workflow.agentId,
182
179
  ownerUserId: workflow.ownerUserId,
183
- ...(workflow.environmentId === undefined ? {} : { environment: workflow.environmentId }),
184
180
  },
185
181
  flowRootId: workflow.flowRootId ?? workflow.id,
186
182
  ...(workflow.environmentId === undefined
@@ -191,7 +187,7 @@ export async function resolveNewFlowEffect(ctx, request, signal, lease) {
191
187
  ? {}
192
188
  : { environmentVersion: workflow.environmentVersion }),
193
189
  }),
194
- ...(inherited ? { sandbox: inherited.spec } : {}),
190
+ ...(sandbox === undefined ? {} : { sandbox }),
195
191
  };
196
192
  await t.put("sessions", agentSessionId, created);
197
193
  });
@@ -247,30 +243,6 @@ export async function resolveNewFlowEffect(ctx, request, signal, lease) {
247
243
  return { status: "pending" };
248
244
  });
249
245
  }
250
- /**
251
- * The sandbox a linked session inherits from its tree's owner when that sandbox was chosen at
252
- * open (pinned on the owner). A definition that declares its own sandbox keeps it, as before.
253
- */
254
- function inheritedSandbox(owner, definition) {
255
- const spec = owner?.sandbox;
256
- if (!spec || sandboxSpecOf(definition.manifest))
257
- return undefined;
258
- if (isWorkflowManifest(definition.manifest))
259
- return { spec };
260
- const sandboxed = withSandbox(definition.manifest, spec);
261
- if (!sandboxed.ok)
262
- throw new Error(sandboxed.message);
263
- return { spec, manifest: sandboxed.manifest, manifestHash: sandboxed.manifestHash };
264
- }
265
- /** A linked agent session's `runtime` block without a sandbox (R2b C11); undefined for a workflow. */
266
- function runtimeTools(manifest) {
267
- if (isWorkflowManifest(manifest))
268
- return undefined;
269
- const pinned = withRuntimeTools(manifest);
270
- if (!pinned.ok)
271
- throw new Error(pinned.message);
272
- return { manifest: pinned.manifest, manifestHash: pinned.manifestHash };
273
- }
274
246
  /**
275
247
  * The credential of an MCP server or HTTP tool request made on behalf of a session: from its
276
248
  * Environment's vault (`vault/sources.ts`).
@@ -289,11 +261,7 @@ function leafDefinition(workflow, body, request) {
289
261
  const flow = flowDelegateManifest(turnManifestOf(workflow), body.agentId);
290
262
  if (!flow)
291
263
  return fail(404, `Agent '${body.agentId}' is not a flow agent used as a tool`);
292
- return {
293
- manifest: flow,
294
- manifestHash: hashManifest(flow),
295
- implementationVersion: workflow.implementationVersion,
296
- };
264
+ return { manifest: flow, manifestHash: hashManifest(flow) };
297
265
  }
298
266
  const leaf = isWorkflowManifest(workflow.manifest)
299
267
  ? embeddedAgent(workflow.manifest, body.flow ?? [], body.agentId)
@@ -301,9 +269,5 @@ function leafDefinition(workflow, body, request) {
301
269
  if (!leaf || isWorkflowManifest(leaf))
302
270
  return fail(404, `Agent '${body.agentId}' is not embedded in workflow '${workflow.manifest.id}'`);
303
271
  const manifest = leaf;
304
- return {
305
- manifest,
306
- manifestHash: hashManifest(manifest),
307
- implementationVersion: workflow.implementationVersion,
308
- };
272
+ return { manifest, manifestHash: hashManifest(manifest) };
309
273
  }
@@ -25,6 +25,7 @@ import { hostPaths, tenantPaths } from "./paths.js";
25
25
  import { hostPrincipals } from "./principals.js";
26
26
  import { openTenantRuntime } from "./runtime.js";
27
27
  import { createTrustedIssuers } from "./issuers.js";
28
+ import { hostTuning } from "../tuning.js";
28
29
  const nodeRequire = createRequire(import.meta.url);
29
30
  function coreVersion() {
30
31
  try {
@@ -127,7 +128,7 @@ export async function startEphemeralRuntime(options) {
127
128
  await host?.close();
128
129
  await module.close();
129
130
  await streams.close();
130
- await ownPool?.end({ timeout: 5 });
131
+ await ownPool?.end({ timeout: hostTuning().postgres.closeTimeoutSeconds });
131
132
  if (!options.retainRoot)
132
133
  rmSync(hostRoot, { recursive: true, force: true });
133
134
  };
@@ -16,7 +16,7 @@
16
16
  * transcript on the row too and checks the fold against it at every segment start.
17
17
  */
18
18
  import type { LiveEvent } from "@nylorun/core/contracts";
19
- export { CHUNK_BYTES, TranscriptFoldError, applyUpdate, applyUpdates, transcriptOf, transcriptUpdates, withTranscript, type TranscriptUpdate, } from "@nylorun/core/harness-api";
19
+ export { TranscriptFoldError, applyUpdate, applyUpdates, transcriptOf, transcriptUpdates, withTranscript, type TranscriptUpdate, } from "@nylorun/core/harness-api";
20
20
  /** Where a session's fold starts. */
21
21
  export interface SessionHistory {
22
22
  /** The fold reads the record from this seq: a snapshot at or before the turn's start. */
@@ -1,5 +1,5 @@
1
1
  import { applyUpdate, transcriptOf } from "@nylorun/core/harness-api";
2
- export { CHUNK_BYTES, TranscriptFoldError, applyUpdate, applyUpdates, transcriptOf, transcriptUpdates, withTranscript, } from "@nylorun/core/harness-api";
2
+ export { TranscriptFoldError, applyUpdate, applyUpdates, transcriptOf, transcriptUpdates, withTranscript, } from "@nylorun/core/harness-api";
3
3
  let shadow = false;
4
4
  /** Shadow mode: keep the transcript on the session row and check the fold against it. */
5
5
  export function transcriptShadow() {
@@ -5,8 +5,8 @@ export declare const HOST_TOKEN_TYP = "nylorun-host+jwt";
5
5
  export declare const HOST_TOKEN_AUD = "nylorun-harness-api";
6
6
  export declare const EGRESS_TOKEN_TYP = "nylorun-egress+jwt";
7
7
  export declare const EGRESS_TOKEN_AUD = "nylorun-egress";
8
- /** How long a host or egress token lives. The engine renews them before. */
9
- export declare const HOST_TOKEN_TTL_SECONDS: number;
8
+ /** How long a host or egress token lives (`keys.hostTokenTtlSeconds`). The engine renews them before. */
9
+ export declare const hostTokenTtlSeconds: () => number;
10
10
  /** What a verified host or egress token says. */
11
11
  export interface HostClaims {
12
12
  readonly tenantId: string;
@@ -37,7 +37,7 @@ export interface EgressTokenRequest {
37
37
  /** The host epoch the join set. */
38
38
  readonly epoch: number;
39
39
  readonly podUid: string;
40
- /** Seconds. Default and maximum `HOST_TOKEN_TTL_SECONDS`. */
40
+ /** Seconds. Default and maximum `keys.hostTokenTtlSeconds`. */
41
41
  readonly ttl?: number;
42
42
  }
43
43
  /**