@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
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import { z } from "zod";
3
3
  import { decodeCursor } from "../record/index.js";
4
4
  import { fail } from "../tenant/http.js";
5
+ import { maxHeaderSize } from "node:http";
5
6
  const schema = z
6
7
  .object({
7
8
  version: z.literal(1),
@@ -23,7 +24,8 @@ export function readCursor(tenant, route, filters) {
23
24
  decode(value) {
24
25
  if (value === undefined)
25
26
  return undefined;
26
- if (value.length > 4096 || !/^[A-Za-z0-9_-]+$/.test(value))
27
+ // A cursor comes back in a URL, which Node refuses past `http.maxHeaderSize` anyway.
28
+ if (value.length > maxHeaderSize || !/^[A-Za-z0-9_-]+$/.test(value))
27
29
  return fail(400, "Invalid cursor", { code: "cursor_invalid" });
28
30
  let parsed;
29
31
  try {
@@ -1,4 +1,4 @@
1
- import type { ArtifactKind, ArtifactPage, ModelCallExportPage, ModelCallsPage, EnvironmentPage, ToolCallsPage, SessionManifestView, SessionPage, SessionListItem, SessionUsageTotals, LiveEvent } from "@nylorun/core/contracts";
1
+ import type { ArtifactKind, ArtifactPage, ModelCallExportPage, ModelCallsPage, ToolCallsPage, SessionManifestView, SessionPage, SessionListItem, SessionUsageTotals, LiveEvent } from "@nylorun/core/contracts";
2
2
  export type ReadAccess = {
3
3
  owner?: string;
4
4
  agents?: readonly string[];
@@ -6,7 +6,8 @@ export type ReadAccess = {
6
6
  export type SessionFilters = {
7
7
  agentId?: string;
8
8
  status?: SessionListItem["status"];
9
- environmentId?: string;
9
+ /** Sessions that pinned a version of this agent manifest. */
10
+ manifest?: string;
10
11
  ownerUserId?: string;
11
12
  };
12
13
  export type PageOptions = {
@@ -33,6 +34,5 @@ export interface ReadStore {
33
34
  * for a turn the session never had.
34
35
  */
35
36
  turnEvents(id: string, turnId: string, access: ReadAccess): Promise<LiveEvent[]>;
36
- environments(labels: Record<string, string>, page: PageOptions, access: ReadAccess, grants?: readonly string[]): Promise<EnvironmentPage>;
37
37
  close(): Promise<void>;
38
38
  }
@@ -0,0 +1,27 @@
1
+ import { type AgentEvent, type AgentEventPayload, type AgentEventType } from "@nylorun/core/contracts";
2
+ /** The Agent stream's two statements, in the caller's transaction. */
3
+ export interface AgentRecordWriter {
4
+ /** The seq the Agent's next event takes: one past its last, or 0. */
5
+ nextSeq(agentId: string): Promise<number>;
6
+ insert(row: {
7
+ agentId: string;
8
+ seq: number;
9
+ type: string;
10
+ body: AgentEvent;
11
+ }): Promise<void>;
12
+ }
13
+ export interface AgentAppendInput<T extends AgentEventType> {
14
+ tenantId: string;
15
+ agentId: string;
16
+ time: Date;
17
+ type: T;
18
+ payload: AgentEventPayload<T>;
19
+ /** The Tenant's Runtime limit `recordEntryBytes`, as for a session's events. */
20
+ maxEntryBytes: number;
21
+ }
22
+ /** Builds the event and checks it against the Agent event catalog. */
23
+ export declare function buildAgentEvent<T extends AgentEventType>(input: AgentAppendInput<T> & {
24
+ seq: number;
25
+ }): AgentEvent;
26
+ /** Appends one event to the Agent's stream through `writer`. */
27
+ export declare function appendAgentEvent<T extends AgentEventType>(writer: AgentRecordWriter, input: AgentAppendInput<T>): Promise<AgentEvent>;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * An Agent's lifecycle stream (blueprint D39, F7.1; an Environment's before protocol 16):
3
+ * `agent.created`, `agent.attached`, `agent.detached` and `agent.deleted` (and the rest of
4
+ * `AGENT_EVENT_TYPES`, egress-gate's `agent.egress` for every connection among them, D67), on
5
+ * the `nylorun.agent-event/1` envelope, numbered from 0 per Agent id in
6
+ * `nylorun_streams.agent_events`. The record module is its only writer, as for session events;
7
+ * the store runs the two statements through `AgentRecordWriter` in the caller's transaction, under
8
+ * the Agent row's lock (or, for an Agent being created, its new row).
9
+ *
10
+ * The stream lives in the record only: it is not published to the stream relay, so no S2 stream
11
+ * follows it yet. Clients read it with `GET /v1/agents/{id}/events`.
12
+ */
13
+ import { randomUUID } from "node:crypto";
14
+ import { z } from "zod";
15
+ import { AGENT_EVENT_PAYLOADS, AGENT_EVENT_SCHEMA, AgentEventSchema, } from "@nylorun/core/contracts";
16
+ import { InvalidEventError } from "./envelope.js";
17
+ import { checkEntry } from "./append.js";
18
+ /** Builds the event and checks it against the Agent event catalog. */
19
+ export function buildAgentEvent(input) {
20
+ const payload = AGENT_EVENT_PAYLOADS[input.type];
21
+ const checkedPayload = payload.safeParse(input.payload);
22
+ if (!checkedPayload.success)
23
+ throw new InvalidEventError(input.type, z.prettifyError(checkedPayload.error));
24
+ const event = JSON.parse(JSON.stringify({
25
+ schema: AGENT_EVENT_SCHEMA,
26
+ eventId: randomUUID(),
27
+ tenantId: input.tenantId,
28
+ agentId: input.agentId,
29
+ seq: input.seq,
30
+ time: input.time.toISOString(),
31
+ type: input.type,
32
+ payload: input.payload,
33
+ }));
34
+ const checked = AgentEventSchema.safeParse(event);
35
+ if (!checked.success)
36
+ throw new InvalidEventError(input.type, z.prettifyError(checked.error));
37
+ return event;
38
+ }
39
+ /** Appends one event to the Agent's stream through `writer`. */
40
+ export async function appendAgentEvent(writer, input) {
41
+ checkEntry(`The ${input.type} event's payload`, input.payload, input.maxEntryBytes);
42
+ const seq = await writer.nextSeq(input.agentId);
43
+ const event = buildAgentEvent({ ...input, seq });
44
+ await writer.insert({ agentId: input.agentId, seq, type: input.type, body: event });
45
+ return event;
46
+ }
@@ -9,8 +9,37 @@
9
9
  * The two statements run through `RecordWriter`, which the store implements on its
10
10
  * transaction (`store/postgres/record-writer.ts`): the database driver stays behind
11
11
  * `store/postgres/` (session-store.md §3), and this module decides what is written.
12
+ *
13
+ * Every entry is held to the Tenant's Runtime limit `recordEntryBytes`, which the caller reads
14
+ * and passes: an event whose payload is larger is refused (`RecordEntryTooLargeError`) before
15
+ * anything is written, whoever wrote it, so no record reaches S2 past its 1 MiB.
16
+ */
17
+ import { type EventPayload, type EventType, type EventWriter, type LiveEvent, type SessionEventOf } from "@nylorun/core/contracts";
18
+ /**
19
+ * An entry larger than the Tenant's `recordEntryBytes`: `limit_exceeded`, `413` to an API client
20
+ * and the Harness API error code to a harness.
12
21
  */
13
- import type { EventPayload, EventType, EventWriter, LiveEvent, SessionEventOf } from "@nylorun/core/contracts";
22
+ export declare class RecordEntryTooLargeError extends Error {
23
+ readonly bytes: number;
24
+ readonly maxBytes: number;
25
+ readonly code: "limit_exceeded";
26
+ readonly status = 413;
27
+ readonly rejection: {
28
+ readonly code: "limit_exceeded";
29
+ readonly details: {
30
+ readonly limit: "recordEntryBytes";
31
+ readonly bytes: number;
32
+ readonly maxBytes: number;
33
+ };
34
+ };
35
+ constructor(
36
+ /** What was refused, as the message names it: "The message.user event's payload". */
37
+ what: string, bytes: number, maxBytes: number);
38
+ }
39
+ /** The JSON size of an entry, in bytes: what the record holds of it. */
40
+ export declare function entryBytes(value: unknown): number;
41
+ /** Throws `RecordEntryTooLargeError` when `entry` is larger than `maxBytes`; `what` names it. */
42
+ export declare function checkEntry(what: string, entry: unknown, maxBytes: number): void;
14
43
  /** The record's two statements, in the caller's transaction. */
15
44
  export interface RecordWriter {
16
45
  /**
@@ -42,10 +71,13 @@ export interface AppendInput<T extends EventType> {
42
71
  payload: EventPayload<T>;
43
72
  /** Who wrote it (R4.9). */
44
73
  writer?: EventWriter;
74
+ /** The Tenant's Runtime limit `recordEntryBytes`: the most bytes the payload may hold, as JSON. */
75
+ maxEntryBytes: number;
45
76
  }
46
77
  /**
47
78
  * Appends one event through `writer`. An event the catalog does not describe throws
48
- * `InvalidEventError` before its row is written; the caller's transaction then rolls back.
79
+ * `InvalidEventError`, and one past `maxEntryBytes` `RecordEntryTooLargeError`, before its row is
80
+ * written; the caller's transaction then rolls back.
49
81
  */
50
82
  export declare function appendEvent<T extends EventType>(writer: RecordWriter, input: AppendInput<T>): Promise<{
51
83
  event: SessionEventOf<T>;
@@ -1,9 +1,58 @@
1
+ /**
2
+ * The only write path into the record (Durable Streams §6, blueprint D27): the session's log
3
+ * head allocates the next sequence, the event is built on the envelope and checked against the
4
+ * catalog, and its row is written, both in the caller's transaction. The database holds one
5
+ * Tenant, so rows are keyed by session alone; the Tenant id is the caller's and goes into the
6
+ * envelope only. The caller holds the session row lock, which orders the session's appends,
7
+ * and passes the epoch it read under that lock.
8
+ *
9
+ * The two statements run through `RecordWriter`, which the store implements on its
10
+ * transaction (`store/postgres/record-writer.ts`): the database driver stays behind
11
+ * `store/postgres/` (session-store.md §3), and this module decides what is written.
12
+ *
13
+ * Every entry is held to the Tenant's Runtime limit `recordEntryBytes`, which the caller reads
14
+ * and passes: an event whose payload is larger is refused (`RecordEntryTooLargeError`) before
15
+ * anything is written, whoever wrote it, so no record reaches S2 past its 1 MiB.
16
+ */
17
+ import { limitExceededMessage, } from "@nylorun/core/contracts";
1
18
  import { buildEvent } from "./envelope.js";
19
+ /**
20
+ * An entry larger than the Tenant's `recordEntryBytes`: `limit_exceeded`, `413` to an API client
21
+ * and the Harness API error code to a harness.
22
+ */
23
+ export class RecordEntryTooLargeError extends Error {
24
+ bytes;
25
+ maxBytes;
26
+ code = "limit_exceeded";
27
+ status = 413;
28
+ rejection;
29
+ constructor(
30
+ /** What was refused, as the message names it: "The message.user event's payload". */
31
+ what, bytes, maxBytes) {
32
+ super(limitExceededMessage(what, bytes, "recordEntryBytes", maxBytes));
33
+ this.bytes = bytes;
34
+ this.maxBytes = maxBytes;
35
+ this.name = "RecordEntryTooLargeError";
36
+ this.rejection = { code: "limit_exceeded", details: { limit: "recordEntryBytes", bytes, maxBytes } };
37
+ }
38
+ }
39
+ /** The JSON size of an entry, in bytes: what the record holds of it. */
40
+ export function entryBytes(value) {
41
+ return Buffer.byteLength(JSON.stringify(value) ?? "null");
42
+ }
43
+ /** Throws `RecordEntryTooLargeError` when `entry` is larger than `maxBytes`; `what` names it. */
44
+ export function checkEntry(what, entry, maxBytes) {
45
+ const bytes = entryBytes(entry);
46
+ if (bytes > maxBytes)
47
+ throw new RecordEntryTooLargeError(what, bytes, maxBytes);
48
+ }
2
49
  /**
3
50
  * Appends one event through `writer`. An event the catalog does not describe throws
4
- * `InvalidEventError` before its row is written; the caller's transaction then rolls back.
51
+ * `InvalidEventError`, and one past `maxEntryBytes` `RecordEntryTooLargeError`, before its row is
52
+ * written; the caller's transaction then rolls back.
5
53
  */
6
54
  export async function appendEvent(writer, input) {
55
+ checkEntry(`The ${input.type} event's payload`, input.payload, input.maxEntryBytes);
7
56
  const { seq, generation } = await writer.advance(input.sessionId);
8
57
  const event = buildEvent({
9
58
  tenantId: input.tenantId,
@@ -8,5 +8,5 @@
8
8
  */
9
9
  export { buildEvent, InvalidEventError, type EventInput } from "./envelope.js";
10
10
  export { decodeCursor, encodeCursor } from "./cursor.js";
11
- export { appendEvent, type AppendInput, type RecordWriter } from "./append.js";
12
- export { appendEnvironmentEvent, buildEnvironmentEvent, type EnvironmentAppendInput, type EnvironmentRecordWriter, } from "./environment.js";
11
+ export { RecordEntryTooLargeError, appendEvent, checkEntry, entryBytes, type AppendInput, type RecordWriter, } from "./append.js";
12
+ export { appendAgentEvent, buildAgentEvent, type AgentAppendInput, type AgentRecordWriter, } from "./agent.js";
@@ -8,5 +8,5 @@
8
8
  */
9
9
  export { buildEvent, InvalidEventError } from "./envelope.js";
10
10
  export { decodeCursor, encodeCursor } from "./cursor.js";
11
- export { appendEvent } from "./append.js";
12
- export { appendEnvironmentEvent, buildEnvironmentEvent, } from "./environment.js";
11
+ export { RecordEntryTooLargeError, appendEvent, checkEntry, entryBytes, } from "./append.js";
12
+ export { appendAgentEvent, buildAgentEvent, } from "./agent.js";
package/dist/redact.d.ts CHANGED
@@ -8,7 +8,7 @@ export interface ScrubOptions {
8
8
  readonly counted?: (replacements: number) => void;
9
9
  }
10
10
  /**
11
- * `value` with each of `secrets` (those of at least 8 characters) replaced by `[redacted]`. By
11
+ * `value` with each of `secrets` (those of at least `harness.scrubMinChars`, 8 by default) replaced by `[redacted]`. By
12
12
  * default also any value under a key such as `token` or `secret`, and inline image data.
13
13
  */
14
14
  export declare function scrub(value: unknown, secrets: readonly string[], options?: ScrubOptions): unknown;
package/dist/redact.js CHANGED
@@ -1,10 +1,11 @@
1
+ import { hostTuning } from "./tuning.js";
1
2
  /**
2
- * `value` with each of `secrets` (those of at least 8 characters) replaced by `[redacted]`. By
3
+ * `value` with each of `secrets` (those of at least `harness.scrubMinChars`, 8 by default) replaced by `[redacted]`. By
3
4
  * default also any value under a key such as `token` or `secret`, and inline image data.
4
5
  */
5
6
  export function scrub(value, secrets, options = {}) {
6
7
  // The longest first, so a header value goes whole before the token inside it.
7
- const sorted = secrets.filter((secret) => secret.length >= 8).sort((a, b) => b.length - a.length);
8
+ const sorted = secrets.filter((secret) => secret.length >= hostTuning().harness.scrubMinChars).sort((a, b) => b.length - a.length);
8
9
  let replaced = 0;
9
10
  const walk = (item) => {
10
11
  if (typeof item === "string") {
@@ -14,10 +14,10 @@
14
14
  * check (`EgressSandboxes.live`).
15
15
  */
16
16
  import type { SessionStore } from "../store/types.js";
17
- import { EGRESS_TOKEN_AUD, EGRESS_TOKEN_TYP, mintEgressToken, type EgressTokenRequest, type HostClaims, type HostTokenKeyCache, type HostTokenVerdict } from "../tenant/host-token.js";
17
+ import { EGRESS_TOKEN_AUD, EGRESS_TOKEN_TYP, hostTokenTtlSeconds, mintEgressToken, type EgressTokenRequest, type HostClaims, type HostTokenKeyCache, type HostTokenVerdict } from "../tenant/host-token.js";
18
18
  export { EGRESS_TOKEN_AUD, EGRESS_TOKEN_TYP, mintEgressToken, type EgressTokenRequest };
19
- /** The longest lifetime an egress token has: a host token's. */
20
- export declare const EGRESS_TOKEN_MAX_TTL_SECONDS: number;
19
+ /** The longest lifetime an egress token has: a host token's (`keys.hostTokenTtlSeconds`). */
20
+ export declare const egressTokenMaxTtlSeconds: typeof hostTokenTtlSeconds;
21
21
  export type EgressClaims = HostClaims;
22
22
  export type EgressTokenVerdict = HostTokenVerdict;
23
23
  /** Public keys imported by key id; the key row is still read on every verification. */
@@ -1,7 +1,7 @@
1
- import { EGRESS_TOKEN_AUD, EGRESS_TOKEN_TYP, HOST_TOKEN_TTL_SECONDS, mintEgressToken, verifyHostToken, } from "../tenant/host-token.js";
1
+ import { EGRESS_TOKEN_AUD, EGRESS_TOKEN_TYP, hostTokenTtlSeconds, mintEgressToken, verifyHostToken, } from "../tenant/host-token.js";
2
2
  export { EGRESS_TOKEN_AUD, EGRESS_TOKEN_TYP, mintEgressToken };
3
- /** The longest lifetime an egress token has: a host token's. */
4
- export const EGRESS_TOKEN_MAX_TTL_SECONDS = HOST_TOKEN_TTL_SECONDS;
3
+ /** The longest lifetime an egress token has: a host token's (`keys.hostTokenTtlSeconds`). */
4
+ export const egressTokenMaxTtlSeconds = hostTokenTtlSeconds;
5
5
  /** Verifies an egress token of Tenant `tenantId`; refusal reasons are `egress_token_*`. */
6
6
  export function verifyEgressToken(store, tenantId, raw, cache = new Map()) {
7
7
  return verifyHostToken(store, tenantId, raw, "egress", cache);
@@ -32,10 +32,11 @@
32
32
  * which check failed.
33
33
  */
34
34
  import { createHash, timingSafeEqual } from "node:crypto";
35
- import { isEnvironmentId } from "@nylorun/core/contracts";
35
+ import { isAgentId } from "@nylorun/core/contracts";
36
36
  import { recoverLostVolume, runPendingSeed } from "../artifacts/disk.js";
37
37
  import { recordSetup, setupFile, setupPlanOf, setupState, } from "./setup.js";
38
38
  import { mintHostTokens, staleHost, verifyHostToken, } from "../tenant/host-token.js";
39
+ import { JOIN_TOKEN_MAX, POD_UID_PATTERN } from "@nylorun/core/harness-api";
39
40
  /** A refused join, renewal or host connection. */
40
41
  export class HostAuthError extends Error {
41
42
  status;
@@ -49,7 +50,7 @@ export class HostAuthError extends Error {
49
50
  this.reason = reason;
50
51
  }
51
52
  }
52
- const POD_UID = /^[A-Za-z0-9-]{1,64}$/;
53
+ const POD_UID = POD_UID_PATTERN;
53
54
  const REFUSED = "The join was refused";
54
55
  export function sha256Hex(value) {
55
56
  return createHash("sha256").update(value).digest("hex");
@@ -86,12 +87,12 @@ export function hostAuthority(ctx) {
86
87
  return {
87
88
  async join(request) {
88
89
  const { sandboxId, podUid, joinToken, volumeId } = request;
89
- if (!isEnvironmentId(sandboxId) ||
90
+ if (!isAgentId(sandboxId) ||
90
91
  typeof podUid !== "string" ||
91
92
  !POD_UID.test(podUid) ||
92
93
  typeof joinToken !== "string" ||
93
94
  joinToken.length === 0 ||
94
- joinToken.length > 512 ||
95
+ joinToken.length > JOIN_TOKEN_MAX ||
95
96
  (volumeId !== undefined && (typeof volumeId !== "string" || !POD_UID.test(volumeId))))
96
97
  throw new HostAuthError(400, "A join is { sandboxId, podUid, joinToken }");
97
98
  const pods = ctx.pods;
@@ -135,7 +136,7 @@ export function hostAuthority(ctx) {
135
136
  // A new, empty volume under the same Sandbox: the sandbox's files are gone.
136
137
  const reason = "The sandbox's volume was replaced: its files are gone";
137
138
  await t.updateEnvironmentPod(sandboxId, { observed: "lost", reason, hostEpoch: epoch }, now);
138
- await t.environmentEvent(sandboxId, "environment.lost", { reason });
139
+ await t.agentEvent(sandboxId, "agent.lost", { reason });
139
140
  // Its Sandbox is deleted; only a reset brings the sandbox back.
140
141
  await t.signal({ type: "host.revoked", sandboxId, epoch });
141
142
  await t.signalSandbox(sandboxId, { kind: "reconcile" });
@@ -149,9 +150,9 @@ export function hostAuthority(ctx) {
149
150
  }, now);
150
151
  if (pod.podUid !== podUid) {
151
152
  if (pod.podUid !== undefined)
152
- await t.environmentEvent(sandboxId, "environment.relaunched", { hostEpoch: epoch });
153
+ await t.agentEvent(sandboxId, "agent.relaunched", { hostEpoch: epoch });
153
154
  else
154
- await t.environmentEvent(sandboxId, "environment.running", { hostEpoch: epoch });
155
+ await t.agentEvent(sandboxId, "agent.running", { hostEpoch: epoch });
155
156
  }
156
157
  // The previous host's connection (an older epoch) serves nothing more, on any process.
157
158
  await t.signal({ type: "host.revoked", sandboxId, epoch });
@@ -1,38 +1,17 @@
1
- /**
2
- * Sandbox Manager: owns sandbox lifecycle for the Runtime. One workspace per sandbox resource
3
- * (`sandbox: { id }`, keyed by the sandbox id), or per owning session for a sandbox chosen
4
- * inline or by the Tenant default (keyed by the session id); created on the first sandbox tool
5
- * call, stopped after its idle timeout, reattached on the next call. Each session's calls on a
6
- * workspace run in the order it sends them, and different sessions' calls run at the same time
7
- * (D66): the sessions of one Environment run their turns at once. Opening, stopping and removing
8
- * a workspace run alone: a stop or removal waits for the calls running, and calls that come after
9
- * it wait for it.
10
- *
11
- * The manager keeps no timers and reaches no store: it keeps its compute records through a
12
- * `SandboxRecords` port (the Tenant's `sandboxes` table in core's process, a file in a harness's)
13
- * and writes its events through `emit`. Its owner drives it: `stopIdle` stops sandboxes idle
14
- * past their timeout and marks records of compute this process no longer holds as stopped
15
- * (after a restart); `reconcile` removes workspaces whose owner is gone. `sweep` does both, the
16
- * reconcile once per process, as the Tenant sweep does in core's process.
17
- *
18
- * A session's skills (track R2 M4) are mounted on its workspace, read-only, one folder per
19
- * version (`/skills/<name>@<hash>/`, D66), before the first call that needs them (`skills.ts`);
20
- * their bytes come through the `definitionFile` port.
21
- */
22
1
  import type { EventPayload } from "@nylorun/core/contracts";
23
- import { type AgentManifest, type SandboxManifest, type SandboxToolName } from "@nylorun/core/define";
2
+ import { type SandboxManifest, type SandboxToolName } from "@nylorun/core/define";
24
3
  import { type SandboxRecord, type SandboxRecords } from "./records.js";
25
4
  import { type SandboxSelection, type SandboxSelectionReport } from "./select.js";
5
+ import { type FolderFiles } from "./skills.js";
6
+ import { type SandboxToolLimits } from "@nylorun/harness";
26
7
  import { type DiskAnswer, type DiskOp } from "./disk-fs.js";
27
8
  import { type SandboxToolOutcome } from "./tools.js";
28
- import { type SandboxBackend, type SandboxListing } from "./types.js";
29
- export { sandboxToolSpec } from "./runtime-tools.js";
9
+ import { type SandboxBackend, type SandboxFileBytes, type SandboxListing } from "./types.js";
30
10
  export type { SandboxRecord, SandboxRecords, SandboxState } from "./records.js";
31
11
  export interface SandboxSessionRef {
32
12
  /** The session whose log records the workspace's events: the owning session. */
33
13
  readonly id: string;
34
14
  readonly activeTurnId: string | null;
35
- readonly manifest?: AgentManifest;
36
15
  /**
37
16
  * The sandbox resource the owning session is attached to. Its workspace is keyed by this id,
38
17
  * so every session attached to it shares the files; absent, the workspace is the session's.
@@ -76,12 +55,6 @@ export interface SandboxManagerOptions {
76
55
  readonly preference: string | undefined;
77
56
  /** Delete sandboxes on close (the Runtime's store does not outlive the process). */
78
57
  readonly ephemeral: boolean;
79
- /**
80
- * A definition file's bytes by `sha256:<hex>`, for the skills a session's workspace mounts:
81
- * the Tenant's Object store in core's process, core's answer in a harness (for the run that
82
- * made the call, `session.claim`). Without it no skills are mounted.
83
- */
84
- readonly definitionFile?: (sha256: string, session: SandboxSessionRef) => Promise<Uint8Array>;
85
58
  /** Writes a session event (in core, in its own transaction; in a harness, as a claim). */
86
59
  readonly emit: <T extends SandboxEventType>(sessionId: string, turnId: string | null, type: T, payload: EventPayload<T>, meta: SandboxEventMeta) => void | Promise<void>;
87
60
  }
@@ -119,7 +92,11 @@ export declare class SandboxManager {
119
92
  report(): Promise<SandboxSelectionReport & {
120
93
  readonly defaultImage: string;
121
94
  }>;
122
- run(session: SandboxSessionRef, sandbox: SandboxManifest | undefined, toolName: SandboxToolName, input: unknown, signal: AbortSignal): Promise<SandboxToolOutcome>;
95
+ /**
96
+ * Runs sandbox operation `toolName` in the session's sandbox, held to `limits`: the harness's
97
+ * sandbox tool limits (`DEFAULT_SANDBOX_TOOL_LIMITS` when it names none).
98
+ */
99
+ run(session: SandboxSessionRef, sandbox: SandboxManifest | undefined, toolName: SandboxToolName, input: unknown, signal: AbortSignal, limits?: SandboxToolLimits): Promise<SandboxToolOutcome>;
123
100
  /**
124
101
  * Runs `call` in session `sessionId`'s queue on `live`: after its earlier calls, and after any
125
102
  * stop or removal pending, beside other sessions' calls (D66).
@@ -130,8 +107,8 @@ export declare class SandboxManager {
130
107
  /** The workspace's handle, opened once for the calls that need it at the same time. */
131
108
  private handleOf;
132
109
  /**
133
- * The bytes of one file in the session's sandbox, for `save_artifact` (F8.1), in the same queue
134
- * as its tool calls: `missing` when there is no such file, a failed outcome when the sandbox
110
+ * The bytes of one file in the session's sandbox, for our engine's `save_artifact` and its
111
+ * outputs folder (`files.read`), in the same queue as its tool calls: `missing` when there is no such file, a failed outcome when the sandbox
135
112
  * cannot open or the file is larger than `maxBytes`. Relative paths resolve in the workspace.
136
113
  */
137
114
  readBytes(session: SandboxSessionRef, sandbox: SandboxManifest | undefined, path: string, maxBytes: number, signal: AbortSignal): Promise<{
@@ -145,8 +122,20 @@ export declare class SandboxManager {
145
122
  kind: "failed";
146
123
  }>>;
147
124
  /**
148
- * The files under directory `dir` of the session's sandbox, for the turn-end export (F8.2), in
149
- * the same queue as its tool calls. `missing` when the sandbox was never created (nothing is
125
+ * Writes `body` to one file of the session's sandbox, as it comes, for our engine's
126
+ * `read_artifact` with `path` (protocol 15), in the same queue as its tool calls: its folders
127
+ * are made first, and a file there is replaced. Relative paths resolve in the workspace.
128
+ */
129
+ writeBytes(session: SandboxSessionRef, sandbox: SandboxManifest | undefined, path: string, body: SandboxFileBytes, signal: AbortSignal): Promise<{
130
+ kind: "written";
131
+ path: string;
132
+ size: number;
133
+ } | Extract<SandboxToolOutcome, {
134
+ kind: "failed";
135
+ }>>;
136
+ /**
137
+ * The files under directory `dir` of the session's sandbox, for our engine's outputs folder
138
+ * (`files.list`, protocol 15), in the same queue as its tool calls. `missing` when the sandbox was never created (nothing is
150
139
  * started to look) or `dir` is not a directory. Relative paths resolve in the workspace.
151
140
  */
152
141
  listFiles(session: SandboxSessionRef, sandbox: SandboxManifest | undefined, dir: string, maxEntries: number, signal: AbortSignal): Promise<{
@@ -171,14 +160,25 @@ export declare class SandboxManager {
171
160
  /** The session's live sandbox entry and spec, or why it cannot run here. */
172
161
  private prepare;
173
162
  private execute;
163
+ /**
164
+ * The workspace's handle, opened when there is none. A start that fails is recorded as stopped
165
+ * and answered as a failed outcome: nothing ran yet, so it is definite, not uncertain.
166
+ */
167
+ private started;
174
168
  private executeOpen;
175
169
  /**
176
- * Mounts the skill folders the session needs that the workspace does not hold (D66): on a
177
- * handle just opened all of them, later only versions another session has not mounted. Calls
178
- * that need one folder at once share its mount. A failed outcome when one cannot be mounted;
179
- * the folder is not marked mounted then, so the next call tries again.
170
+ * Writes `files` (path in `folder` to `sha256:<hex>`) to `folder` of the session's sandbox,
171
+ * read-only, each one's bytes from `read`, in the session's queue (protocol 15: the harness
172
+ * decides which folders, and when). A folder the open handle already holds is `present` without
173
+ * an exec; calls that need one folder at once share its mount. A failed outcome when the sandbox
174
+ * cannot start or the folder cannot be written; it is not marked mounted then, so the next call
175
+ * tries again. A reopened handle holds none.
180
176
  */
181
- private mountSkills;
177
+ mountFolder(session: SandboxSessionRef, sandbox: SandboxManifest | undefined, folder: string, files: FolderFiles, read: (sha256: string) => SandboxFileBytes | Promise<SandboxFileBytes>, signal: AbortSignal): Promise<{
178
+ kind: "mounted" | "present";
179
+ } | Extract<SandboxToolOutcome, {
180
+ kind: "failed";
181
+ }>>;
182
182
  private open;
183
183
  private stop;
184
184
  private record;