@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
@@ -51,22 +51,23 @@
51
51
  import { AsyncLocalStorage } from "node:async_hooks";
52
52
  import { randomUUID } from "node:crypto";
53
53
  import { and, count, desc, eq, getTableColumns, gte, gt, inArray, isNotNull, isNull, lt, lte, ne, or, sql, } from "drizzle-orm";
54
- import { appendEnvironmentEvent, appendEvent } from "../../record/index.js";
54
+ import { appendAgentEvent, appendEvent } from "../../record/index.js";
55
+ import { readRuntimeLimits } from "../../tenant/runtime-limits.js";
55
56
  import { OwnershipLostError, PrincipalRoleConflict } from "../ownership.js";
56
57
  import { followControlSignals, pruneSignals, writeSignal } from "./control.js";
57
58
  import { database, driverError } from "./db.js";
58
59
  import { expectedSchemaVersion, readSchemaVersion } from "./migrate.js";
60
+ import { hostTuning } from "../../tuning.js";
59
61
  import { createPostgresRecordReader } from "./record.js";
60
- import { postgresEnvironmentRecordWriter, postgresRecordWriter } from "./record-writer.js";
61
- import { artifacts, artifactVersions, artifactContent, definitionFiles, definitionFileUses, commands, definitions, effects, links, modelBudgets, modelUsage, principals, sandboxes, environmentEvents, environments, environmentManifests, sessionEvents, sessionLogHeads, sessions, toJson, toolCrossings, signingKeys, tenant, tenantSettings, vaultAudit, vaultCredentials, vaultIdempotency, vaults, sandboxSignals, wakes, } from "./schema.js";
62
+ import { postgresAgentRecordWriter, postgresRecordWriter } from "./record-writer.js";
63
+ import { artifacts, artifactVersions, artifactContent, definitionFiles, definitionFileUses, commands, effects, links, modelBudgets, modelUsage, principals, sandboxes, agentEvents, agents, agentManifests, sessionEvents, sessionLogHeads, sessions, sessionQueue, agentTriggers, triggerRuns, memories, memoryVersions, toJson, toolCrossings, signingKeys, tenant, tenantSettings, vaultAudit, vaultCredentials, vaultIdempotency, vaults, sandboxSignals, wakes, } from "./schema.js";
62
64
  export function createPostgresSessionStore(options) {
63
65
  return new PostgresSessionStore(options);
64
66
  }
65
67
  const OPEN_SESSION = ["running", "runnable"];
66
- /** Rows per statement when a folder version names many files. */
67
- const CONTENT_BATCH = 1000;
68
+ /** Rows per statement when a folder version or a definition names many files (Host tuning). */
69
+ const contentBatch = () => hostTuning().postgres.contentBatchRows;
68
70
  const DOCUMENTS = {
69
- definitions,
70
71
  sessions: sessions,
71
72
  commands,
72
73
  effects: effects,
@@ -255,10 +256,15 @@ function environmentOf(row) {
255
256
  updatedAt: row.updatedAt,
256
257
  ...(row.diskOp ? { diskOp: row.diskOp } : {}),
257
258
  ...(row.diskSeed ? { diskSeed: row.diskSeed } : {}),
258
- ...(row.manifestName !== null ? { manifestName: row.manifestName } : {}),
259
- ...(row.manifestVersion !== null ? { manifestVersion: row.manifestVersion } : {}),
260
- ...(row.manifestHash !== null ? { manifestHash: row.manifestHash } : {}),
259
+ manifestName: row.manifestName,
260
+ manifestVersion: row.manifestVersion,
261
+ manifestRef: row.manifestRef,
262
+ manifestHash: row.manifestHash,
263
+ desiredState: row.desiredState,
261
264
  ...(row.forkedFrom ? { forkedFrom: row.forkedFrom } : {}),
265
+ ...(row.targetVersion !== null ? { targetVersion: row.targetVersion } : {}),
266
+ ...(row.failedVersion !== null ? { failedVersion: row.failedVersion } : {}),
267
+ ...(row.startCheck ? { startCheck: row.startCheck } : {}),
262
268
  ...(row.k8sName !== null && row.desired !== null && row.observed !== null
263
269
  ? {
264
270
  pod: {
@@ -281,7 +287,7 @@ function environmentOf(row) {
281
287
  : {}),
282
288
  };
283
289
  }
284
- function environmentManifestOf(row) {
290
+ function agentManifestOf(row) {
285
291
  return {
286
292
  name: row.name,
287
293
  version: row.version,
@@ -320,7 +326,7 @@ const SIGNING_KEY_STAMP = {
320
326
  };
321
327
  /** The audit columns a row has (`ord` only orders them). */
322
328
  const { ord: _ord, ...AUDIT } = getTableColumns(vaultAudit);
323
- const SESSION_TABLES = [sessions, commands, effects, links, wakes];
329
+ const SESSION_TABLES = [sessions, commands, effects, links, wakes, sessionQueue];
324
330
  /**
325
331
  * The outbox's tables, by the kind of request each holds. Their delivery columns (`id`,
326
332
  * `created_at`, `attempts`, `retry_at`, `parked_at`) are the same.
@@ -430,6 +436,7 @@ class PostgresTx {
430
436
  type,
431
437
  payload,
432
438
  ...(writer ? { writer } : {}),
439
+ maxEntryBytes: await this.maxEntryBytes(),
433
440
  });
434
441
  this.events.push(event);
435
442
  this.generations.push(generation);
@@ -626,44 +633,40 @@ class PostgresTx {
626
633
  const rows = await this.db.select({ body: table.body }).from(table).orderBy(table.id);
627
634
  return rows.map((row) => row.body);
628
635
  }
629
- async listDefinitions() {
630
- this.check();
631
- return this.bodies(definitions);
632
- }
633
636
  async listSandboxes() {
634
637
  this.check();
635
638
  return this.bodies(sandboxes);
636
639
  }
637
- // --- Environments ----------------------------------------------------------
640
+ // --- Agents ----------------------------------------------------------------
638
641
  async environment(id, options = {}) {
639
642
  this.check();
640
- const query = this.db.select().from(environments).where(eq(environments.id, id));
643
+ const query = this.db.select().from(agents).where(eq(agents.id, id));
641
644
  const [row] = options.lock ? await query.for("update") : await query;
642
645
  return row && environmentOf(row);
643
646
  }
644
647
  async createEnvironment(row, limit) {
645
648
  this.check();
646
649
  // Every create takes this lock, so two never both see room for one more.
647
- await this.db.execute(sql `SELECT pg_advisory_xact_lock(hashtext('nylorun.environments'))`);
650
+ await this.db.execute(sql `SELECT pg_advisory_xact_lock(hashtext('nylorun.agents'))`);
648
651
  const [found] = await this.db
649
- .select({ id: environments.id })
650
- .from(environments)
651
- .where(eq(environments.id, row.id));
652
+ .select({ id: agents.id })
653
+ .from(agents)
654
+ .where(eq(agents.id, row.id));
652
655
  if (found)
653
656
  return "exists";
654
- const [counted] = await this.db.select({ n: count() }).from(environments);
657
+ const [counted] = await this.db.select({ n: count() }).from(agents);
655
658
  if ((counted?.n ?? 0) >= limit)
656
659
  return "limit";
657
- const { pod, ownerUserId, diskOp, diskSeed, manifestName, manifestVersion, manifestHash, forkedFrom, ...environment } = row;
658
- await this.db.insert(environments).values({
660
+ const { pod, ownerUserId, diskOp, diskSeed, forkedFrom, targetVersion, failedVersion, startCheck, ...environment } = row;
661
+ await this.db.insert(agents).values({
659
662
  ...environment,
660
663
  ownerUserId: ownerUserId ?? null,
661
664
  diskOp: diskOp ?? null,
662
665
  diskSeed: diskSeed ?? null,
663
- manifestName: manifestName ?? null,
664
- manifestVersion: manifestVersion ?? null,
665
- manifestHash: manifestHash ?? null,
666
666
  forkedFrom: forkedFrom ?? null,
667
+ targetVersion: targetVersion ?? null,
668
+ failedVersion: failedVersion ?? null,
669
+ startCheck: startCheck ?? null,
667
670
  ...(pod ? podColumns(pod) : {}),
668
671
  });
669
672
  return "created";
@@ -672,88 +675,88 @@ class PostgresTx {
672
675
  this.check();
673
676
  const columns = Object.fromEntries(Object.entries(patch).filter(([, value]) => value !== undefined));
674
677
  await this.db
675
- .update(environments)
678
+ .update(agents)
676
679
  .set({ ...columns, updatedAt })
677
- .where(eq(environments.id, id));
680
+ .where(eq(agents.id, id));
678
681
  }
679
682
  async updateEnvironmentPod(id, patch, updatedAt) {
680
683
  this.check();
681
684
  await this.db
682
- .update(environments)
685
+ .update(agents)
683
686
  .set({ ...podColumns(patch), updatedAt })
684
- .where(eq(environments.id, id));
687
+ .where(eq(agents.id, id));
685
688
  }
686
689
  async deleteEnvironment(id) {
687
690
  this.check();
688
691
  // Its vault and credentials go with it (ON DELETE CASCADE).
689
- await this.db.delete(environments).where(eq(environments.id, id));
692
+ await this.db.delete(agents).where(eq(agents.id, id));
690
693
  }
691
694
  async listEnvironments(filter = {}) {
692
695
  this.check();
693
696
  const labels = filter.labels;
694
697
  const rows = await this.db
695
698
  .select()
696
- .from(environments)
699
+ .from(agents)
697
700
  .where(labels === undefined || Object.keys(labels).length === 0
698
701
  ? undefined
699
- : sql `nylorun.doc(${environments.labels}) @> ${toJson(labels)}::jsonb`)
700
- .orderBy(environments.id);
702
+ : sql `nylorun.doc(${agents.labels}) @> ${toJson(labels)}::jsonb`)
703
+ .orderBy(agents.id);
701
704
  return rows.map(environmentOf);
702
705
  }
703
- // --- Environment manifests (D63) -----------------------------------------------
704
- async lockEnvironmentManifest(name) {
706
+ // --- Agent manifests (protocol 16) ---------------------------------------------
707
+ async lockAgentManifest(name) {
705
708
  this.check();
706
- await this.db.execute(sql `SELECT pg_advisory_xact_lock(hashtext(${`nylorun.environment_manifests:${name}`}))`);
709
+ await this.db.execute(sql `SELECT pg_advisory_xact_lock(hashtext(${`nylorun.agent_manifests:${name}`}))`);
707
710
  }
708
- async environmentManifest(name, version) {
711
+ async agentManifest(name, version) {
709
712
  this.check();
710
713
  const [row] = await this.db
711
714
  .select()
712
- .from(environmentManifests)
715
+ .from(agentManifests)
713
716
  .where(version === undefined
714
- ? eq(environmentManifests.name, name)
715
- : and(eq(environmentManifests.name, name), eq(environmentManifests.version, version)))
716
- .orderBy(desc(environmentManifests.version))
717
+ ? eq(agentManifests.name, name)
718
+ : and(eq(agentManifests.name, name), eq(agentManifests.version, version)))
719
+ .orderBy(desc(agentManifests.version))
717
720
  .limit(1);
718
- return row && environmentManifestOf(row);
721
+ return row && agentManifestOf(row);
719
722
  }
720
- async insertEnvironmentManifest(row) {
723
+ async insertAgentManifest(row) {
721
724
  this.check();
722
- await this.db.insert(environmentManifests).values(row);
725
+ await this.db.insert(agentManifests).values(row);
723
726
  }
724
- async listEnvironmentManifests() {
727
+ async listAgentManifests() {
725
728
  this.check();
726
729
  const rows = await this.db
727
- .selectDistinctOn([environmentManifests.name])
728
- .from(environmentManifests)
729
- .orderBy(environmentManifests.name, desc(environmentManifests.version));
730
- return rows.map(environmentManifestOf);
730
+ .selectDistinctOn([agentManifests.name])
731
+ .from(agentManifests)
732
+ .orderBy(agentManifests.name, desc(agentManifests.version));
733
+ return rows.map(agentManifestOf);
731
734
  }
732
- async environmentManifestVersions(name) {
735
+ async agentManifestVersions(name) {
733
736
  this.check();
734
737
  const rows = await this.db
735
738
  .select()
736
- .from(environmentManifests)
737
- .where(eq(environmentManifests.name, name))
738
- .orderBy(desc(environmentManifests.version));
739
- return rows.map(environmentManifestOf);
739
+ .from(agentManifests)
740
+ .where(eq(agentManifests.name, name))
741
+ .orderBy(desc(agentManifests.version));
742
+ return rows.map(agentManifestOf);
740
743
  }
741
- async deleteEnvironmentManifest(name) {
744
+ async deleteAgentManifest(name) {
742
745
  this.check();
743
746
  const deleted = await this.db
744
- .delete(environmentManifests)
745
- .where(eq(environmentManifests.name, name))
746
- .returning({ version: environmentManifests.version });
747
+ .delete(agentManifests)
748
+ .where(eq(agentManifests.name, name))
749
+ .returning({ version: agentManifests.version });
747
750
  return deleted.length;
748
751
  }
749
- async environmentsOfManifest(name) {
752
+ async agentsOfManifest(name) {
750
753
  this.check();
751
754
  const rows = await this.db
752
- .select({ version: environments.manifestVersion, n: count() })
753
- .from(environments)
754
- .where(eq(environments.manifestName, name))
755
- .groupBy(environments.manifestVersion);
756
- return new Map(rows.filter((row) => row.version !== null).map((row) => [row.version, row.n]));
755
+ .select({ version: agents.manifestVersion, n: count() })
756
+ .from(agents)
757
+ .where(eq(agents.manifestName, name))
758
+ .groupBy(agents.manifestVersion);
759
+ return new Map(rows.map((row) => [row.version, row.n]));
757
760
  }
758
761
  async sessionsOnEnvironment(environmentId) {
759
762
  this.check();
@@ -762,24 +765,30 @@ class PostgresTx {
762
765
  .orderBy(sessions.id);
763
766
  return rows.map((row) => storedSession(row));
764
767
  }
765
- async environmentEvent(environmentId, type, payload) {
768
+ async agentEvent(agentId, type, payload) {
766
769
  this.check();
767
- return appendEnvironmentEvent(postgresEnvironmentRecordWriter(this.db), {
770
+ return appendAgentEvent(postgresAgentRecordWriter(this.db), {
768
771
  tenantId: this.tenantId,
769
- environmentId,
772
+ agentId,
770
773
  time: this.now(),
771
774
  type,
772
775
  payload,
776
+ maxEntryBytes: await this.maxEntryBytes(),
773
777
  });
774
778
  }
775
- async environmentEvents(environmentId, options = {}) {
779
+ /** The Tenant's Runtime limit `recordEntryBytes`, read in this transaction for each write. */
780
+ async maxEntryBytes() {
781
+ return (await readRuntimeLimits(this)).recordEntryBytes;
782
+ }
783
+ async agentEvents(agentId, options = {}) {
776
784
  this.check();
777
- const rows = await this.db
778
- .select({ body: environmentEvents.body })
779
- .from(environmentEvents)
780
- .where(and(eq(environmentEvents.environmentId, environmentId), options.fromSeq === undefined ? undefined : gte(environmentEvents.seq, options.fromSeq), options.types === undefined ? undefined : inArray(environmentEvents.type, [...options.types]), options.since === undefined ? undefined : gte(environmentEvents.committedAt, options.since), options.until === undefined ? undefined : lt(environmentEvents.committedAt, options.until)))
781
- .orderBy(environmentEvents.seq)
782
- .limit(options.limit ?? 1000);
785
+ const query = this.db
786
+ .select({ body: agentEvents.body })
787
+ .from(agentEvents)
788
+ .where(and(eq(agentEvents.agentId, agentId), options.fromSeq === undefined ? undefined : gte(agentEvents.seq, options.fromSeq), options.types === undefined ? undefined : inArray(agentEvents.type, [...options.types]), options.since === undefined ? undefined : gte(agentEvents.committedAt, options.since), options.until === undefined ? undefined : lt(agentEvents.committedAt, options.until)))
789
+ .orderBy(agentEvents.seq)
790
+ .$dynamic();
791
+ const rows = await (options.limit === undefined ? query : query.limit(options.limit));
783
792
  return rows.map((row) => row.body);
784
793
  }
785
794
  async effectBodies(where) {
@@ -827,13 +836,13 @@ class PostgresTx {
827
836
  WHERE ${sessions.status} IN ('running', 'runnable'))::int AS running,
828
837
  (SELECT count(*) FROM ${effects} WHERE ${effects.status} = 'uncertain')::int AS uncertain,
829
838
  (SELECT count(*) FROM ${sandboxes})::int AS sandboxes,
830
- (SELECT count(*) FROM ${definitions})::int AS definitions`);
839
+ (SELECT count(*) FROM ${agentManifests})::int AS manifests`);
831
840
  return {
832
841
  sessions: row.sessions,
833
842
  runningSessions: row.running,
834
843
  uncertainEffects: row.uncertain,
835
844
  sandboxes: row.sandboxes,
836
- definitions: row.definitions,
845
+ agentManifests: row.manifests,
837
846
  };
838
847
  }
839
848
  // --- control bus (D21) ---------------------------------------------------
@@ -1080,7 +1089,7 @@ class PostgresTx {
1080
1089
  costUsd: sql `coalesce(sum(${modelUsage.costUsd}), 0)::double precision`.mapWith(Number),
1081
1090
  })
1082
1091
  .from(modelUsage)
1083
- .where(and(query.scope === "agent" ? eq(modelUsage.agentId, query.id ?? "") : undefined, query.scope === "turn" ? eq(modelUsage.turnId, query.id ?? "") : undefined, query.since !== undefined ? gte(modelUsage.createdAt, query.since) : undefined));
1092
+ .where(and(query.scope === "manifest" ? eq(modelUsage.manifestName, query.id ?? "") : undefined, query.scope === "turn" ? eq(modelUsage.turnId, query.id ?? "") : undefined, query.since !== undefined ? gte(modelUsage.createdAt, query.since) : undefined));
1084
1093
  return row;
1085
1094
  }
1086
1095
  async listModelBudgets() {
@@ -1096,6 +1105,249 @@ class PostgresTx {
1096
1105
  if (rows.length > 0)
1097
1106
  await this.db.insert(modelBudgets).values([...rows]);
1098
1107
  }
1108
+ // --- session queues (protocol 17) -------------------------------------------
1109
+ async enqueueMessage(row) {
1110
+ this.check();
1111
+ const [last] = await this.db
1112
+ .select({ seq: sql `max(${sessionQueue.seq})` })
1113
+ .from(sessionQueue)
1114
+ .where(eq(sessionQueue.sessionId, row.sessionId));
1115
+ const seq = Number(last?.seq ?? 0) + 1;
1116
+ await this.db.insert(sessionQueue).values({ ...row, seq });
1117
+ return seq;
1118
+ }
1119
+ async queuedMessages(sessionId) {
1120
+ this.check();
1121
+ return this.db
1122
+ .select()
1123
+ .from(sessionQueue)
1124
+ .where(eq(sessionQueue.sessionId, sessionId))
1125
+ .orderBy(sessionQueue.seq);
1126
+ }
1127
+ async countQueuedMessages(sessionId) {
1128
+ this.check();
1129
+ const [row] = await this.db
1130
+ .select({ n: count() })
1131
+ .from(sessionQueue)
1132
+ .where(eq(sessionQueue.sessionId, sessionId));
1133
+ return Number(row?.n ?? 0);
1134
+ }
1135
+ async deleteQueuedMessages(ids) {
1136
+ this.check();
1137
+ if (ids.length > 0)
1138
+ await this.db.delete(sessionQueue).where(inArray(sessionQueue.id, [...ids]));
1139
+ }
1140
+ // --- triggers (track T4) ----------------------------------------------------
1141
+ async agentTriggers(agentId) {
1142
+ this.check();
1143
+ return this.db
1144
+ .select()
1145
+ .from(agentTriggers)
1146
+ .where(eq(agentTriggers.agentId, agentId))
1147
+ .orderBy(agentTriggers.triggerId);
1148
+ }
1149
+ async agentTrigger(agentId, triggerId, options = {}) {
1150
+ this.check();
1151
+ const query = this.db
1152
+ .select()
1153
+ .from(agentTriggers)
1154
+ .where(and(eq(agentTriggers.agentId, agentId), eq(agentTriggers.triggerId, triggerId)));
1155
+ const [row] = options.lock ? await query.for("update") : await query;
1156
+ return row;
1157
+ }
1158
+ async putAgentTrigger(row) {
1159
+ this.check();
1160
+ const { agentId: _a, triggerId: _t, createdAt: _c, ...set } = row;
1161
+ await this.db
1162
+ .insert(agentTriggers)
1163
+ .values(row)
1164
+ .onConflictDoUpdate({ target: [agentTriggers.agentId, agentTriggers.triggerId], set });
1165
+ }
1166
+ async deleteAgentTrigger(agentId, triggerId) {
1167
+ this.check();
1168
+ await this.db
1169
+ .delete(agentTriggers)
1170
+ .where(and(eq(agentTriggers.agentId, agentId), eq(agentTriggers.triggerId, triggerId)));
1171
+ }
1172
+ async deleteAgentTriggers(agentId) {
1173
+ this.check();
1174
+ await this.db.delete(agentTriggers).where(eq(agentTriggers.agentId, agentId));
1175
+ await this.db.delete(triggerRuns).where(eq(triggerRuns.agentId, agentId));
1176
+ }
1177
+ async activeTriggers(options) {
1178
+ this.check();
1179
+ const conditions = [eq(agentTriggers.status, "active"), isNotNull(agentTriggers.nextFireAt)];
1180
+ if (options.dueBefore !== undefined)
1181
+ conditions.push(lte(agentTriggers.nextFireAt, options.dueBefore));
1182
+ if (options.changedSince !== undefined)
1183
+ conditions.push(gte(agentTriggers.updatedAt, options.changedSince));
1184
+ if (options.after)
1185
+ conditions.push(or(gt(agentTriggers.agentId, options.after.agentId), and(eq(agentTriggers.agentId, options.after.agentId), gt(agentTriggers.triggerId, options.after.triggerId))));
1186
+ return this.db
1187
+ .select()
1188
+ .from(agentTriggers)
1189
+ .where(and(...conditions))
1190
+ .orderBy(agentTriggers.agentId, agentTriggers.triggerId)
1191
+ .limit(options.limit);
1192
+ }
1193
+ async agentTriggerByEndpoint(endpointId) {
1194
+ this.check();
1195
+ const [row] = await this.db.select().from(agentTriggers).where(eq(agentTriggers.endpointId, endpointId));
1196
+ return row;
1197
+ }
1198
+ async nextWakeAt(agentId) {
1199
+ this.check();
1200
+ const [row] = await this.db
1201
+ .select({ at: sql `min(${agentTriggers.nextFireAt})` })
1202
+ .from(agentTriggers)
1203
+ .where(and(eq(agentTriggers.agentId, agentId), eq(agentTriggers.status, "active")));
1204
+ return row?.at ?? null;
1205
+ }
1206
+ async insertTriggerRun(row) {
1207
+ this.check();
1208
+ const inserted = await this.db
1209
+ .insert(triggerRuns)
1210
+ .values(row)
1211
+ .onConflictDoNothing()
1212
+ .returning({ id: triggerRuns.id });
1213
+ return inserted.length === 1;
1214
+ }
1215
+ async triggerRunByKey(agentId, runKey) {
1216
+ this.check();
1217
+ const [row] = await this.db
1218
+ .select()
1219
+ .from(triggerRuns)
1220
+ .where(and(eq(triggerRuns.agentId, agentId), eq(triggerRuns.runKey, runKey)));
1221
+ return row;
1222
+ }
1223
+ async updateTriggerRun(id, patch) {
1224
+ this.check();
1225
+ await this.db.update(triggerRuns).set(patch).where(eq(triggerRuns.id, id));
1226
+ }
1227
+ async countTriggerRuns(agentId, since, statuses) {
1228
+ this.check();
1229
+ const [row] = await this.db
1230
+ .select({ n: count() })
1231
+ .from(triggerRuns)
1232
+ .where(and(eq(triggerRuns.agentId, agentId), gte(triggerRuns.firedAt, since), inArray(triggerRuns.status, [...statuses])));
1233
+ return Number(row?.n ?? 0);
1234
+ }
1235
+ async listTriggerRuns(agentId, options) {
1236
+ this.check();
1237
+ const conditions = [eq(triggerRuns.agentId, agentId)];
1238
+ if (options.triggerId !== undefined)
1239
+ conditions.push(eq(triggerRuns.triggerId, options.triggerId));
1240
+ if (options.before !== undefined)
1241
+ conditions.push(lt(triggerRuns.id, options.before));
1242
+ return this.db
1243
+ .select()
1244
+ .from(triggerRuns)
1245
+ .where(and(...conditions))
1246
+ .orderBy(desc(triggerRuns.id))
1247
+ .limit(options.limit);
1248
+ }
1249
+ async pruneTriggerRuns(before) {
1250
+ this.check();
1251
+ const deleted = await this.db
1252
+ .delete(triggerRuns)
1253
+ .where(lt(triggerRuns.firedAt, before))
1254
+ .returning({ id: triggerRuns.id });
1255
+ return deleted.length;
1256
+ }
1257
+ // --- memory (track T5) ------------------------------------------------------
1258
+ async memory(agentId, path, options = {}) {
1259
+ this.check();
1260
+ // The path's own lock, held whether or not a row has it, so two writes creating it queue.
1261
+ if (options.lock)
1262
+ await this.db.execute(sql `SELECT pg_advisory_xact_lock(hashtext(${`nylorun.memories:${agentId}:${path}`}))`);
1263
+ const query = this.db
1264
+ .select()
1265
+ .from(memories)
1266
+ .where(and(eq(memories.agentId, agentId), eq(memories.path, path)));
1267
+ const [row] = options.lock ? await query.for("update") : await query;
1268
+ return row;
1269
+ }
1270
+ async memories(agentId, options) {
1271
+ this.check();
1272
+ const conditions = [eq(memories.agentId, agentId)];
1273
+ // `starts_with`, not LIKE: a path may hold `%` or `_`.
1274
+ if (options.folder !== undefined)
1275
+ conditions.push(sql `starts_with(${memories.path}, ${`${options.folder}/`})`);
1276
+ if (options.after !== undefined)
1277
+ conditions.push(gt(memories.path, options.after));
1278
+ const ordered = this.db
1279
+ .select()
1280
+ .from(memories)
1281
+ .where(and(...conditions))
1282
+ .orderBy(memories.path);
1283
+ const limited = options.limit === undefined ? ordered : ordered.limit(options.limit);
1284
+ return options.lock ? limited.for("update") : limited;
1285
+ }
1286
+ async countMemories(agentId) {
1287
+ this.check();
1288
+ const [row] = await this.db.select({ n: count() }).from(memories).where(eq(memories.agentId, agentId));
1289
+ return Number(row?.n ?? 0);
1290
+ }
1291
+ async recentMemories(agentId, limit) {
1292
+ this.check();
1293
+ return this.db
1294
+ .select({ path: memories.path, description: memories.description, bytes: memories.bytes })
1295
+ .from(memories)
1296
+ .where(eq(memories.agentId, agentId))
1297
+ .orderBy(desc(memories.updatedAt), memories.path)
1298
+ .limit(limit);
1299
+ }
1300
+ async putMemory(row) {
1301
+ this.check();
1302
+ const { agentId: _a, path: _p, ...set } = row;
1303
+ await this.db
1304
+ .insert(memories)
1305
+ .values(row)
1306
+ .onConflictDoUpdate({ target: [memories.agentId, memories.path], set });
1307
+ }
1308
+ async deleteMemory(agentId, path) {
1309
+ this.check();
1310
+ await this.db.delete(memories).where(and(eq(memories.agentId, agentId), eq(memories.path, path)));
1311
+ }
1312
+ async insertMemoryVersion(row) {
1313
+ this.check();
1314
+ await this.db.insert(memoryVersions).values(row);
1315
+ }
1316
+ async memoryVersions(agentId, options) {
1317
+ this.check();
1318
+ const conditions = [eq(memoryVersions.agentId, agentId)];
1319
+ if (options.path !== undefined)
1320
+ conditions.push(eq(memoryVersions.path, options.path));
1321
+ if (options.before !== undefined)
1322
+ conditions.push(lt(memoryVersions.id, options.before));
1323
+ return this.db
1324
+ .select()
1325
+ .from(memoryVersions)
1326
+ .where(and(...conditions))
1327
+ .orderBy(desc(memoryVersions.id))
1328
+ .limit(options.limit);
1329
+ }
1330
+ async memoryVersion(agentId, id) {
1331
+ this.check();
1332
+ const [row] = await this.db
1333
+ .select()
1334
+ .from(memoryVersions)
1335
+ .where(and(eq(memoryVersions.agentId, agentId), eq(memoryVersions.id, id)));
1336
+ return row;
1337
+ }
1338
+ async copyMemories(from, to, now) {
1339
+ this.check();
1340
+ const copied = await this.db.execute(sql `
1341
+ INSERT INTO ${memories} (agent_id, path, content, content_sha256, bytes, description, version, updated_at)
1342
+ SELECT ${to}, path, content, content_sha256, bytes, description, 1, ${now}
1343
+ FROM ${memories} WHERE agent_id = ${from}`);
1344
+ return Number(copied.count ?? 0);
1345
+ }
1346
+ async deleteAgentMemories(agentId) {
1347
+ this.check();
1348
+ await this.db.delete(memories).where(eq(memories.agentId, agentId));
1349
+ await this.db.delete(memoryVersions).where(eq(memoryVersions.agentId, agentId));
1350
+ }
1099
1351
  // --- tool crossings --------------------------------------------------------
1100
1352
  async toolCrossing(key) {
1101
1353
  this.check();
@@ -1181,6 +1433,11 @@ class PostgresTx {
1181
1433
  .where(and(eq(artifactVersions.artifactId, artifactId), eq(artifactVersions.version, version)));
1182
1434
  return row;
1183
1435
  }
1436
+ async artifactVersionByWriteKey(writeKey) {
1437
+ this.check();
1438
+ const [row] = await this.db.select().from(artifactVersions).where(eq(artifactVersions.writeKey, writeKey));
1439
+ return row;
1440
+ }
1184
1441
  async artifactVersions(artifactId) {
1185
1442
  this.check();
1186
1443
  return this.db
@@ -1220,21 +1477,32 @@ class PostgresTx {
1220
1477
  this.check();
1221
1478
  await this.db.execute(sql `SELECT pg_advisory_xact_lock(hashtext('nylorun.artifacts'))`);
1222
1479
  }
1223
- async artifactBytes() {
1480
+ /** The artifacts of Environment `environmentId`: its disk versions, and its sessions'. */
1481
+ artifactsOfEnvironment(environmentId) {
1482
+ return or(eq(artifacts.environmentId, environmentId), inArray(artifacts.sessionId, this.db.select({ id: sessions.id }).from(sessions).where(eq(sessions.environmentId, environmentId))));
1483
+ }
1484
+ async artifactBytes(scope) {
1224
1485
  this.check();
1486
+ const within = scope === undefined ? undefined : this.artifactsOfEnvironment(scope.environmentId);
1225
1487
  const [files] = await this.db
1226
1488
  .select({
1227
1489
  bytes: sql `coalesce(sum(${artifactVersions.size}), 0)::bigint`.mapWith(Number),
1228
1490
  })
1229
1491
  .from(artifactVersions)
1230
1492
  .innerJoin(artifacts, eq(artifacts.id, artifactVersions.artifactId))
1231
- .where(eq(artifacts.kind, "file"));
1493
+ .where(within === undefined ? eq(artifacts.kind, "file") : and(eq(artifacts.kind, "file"), within));
1232
1494
  // A folder's files are stored once per distinct hash, however many versions name them.
1233
- const distinct = this.db
1234
- .select({ size: sql `max(${artifactContent.size})`.as("size") })
1235
- .from(artifactContent)
1236
- .groupBy(artifactContent.sha256)
1237
- .as("distinct_content");
1495
+ const distinct = (within === undefined
1496
+ ? this.db
1497
+ .select({ size: sql `max(${artifactContent.size})`.as("size") })
1498
+ .from(artifactContent)
1499
+ .groupBy(artifactContent.sha256)
1500
+ : this.db
1501
+ .select({ size: sql `max(${artifactContent.size})`.as("size") })
1502
+ .from(artifactContent)
1503
+ .innerJoin(artifacts, eq(artifacts.id, artifactContent.artifactId))
1504
+ .where(within)
1505
+ .groupBy(artifactContent.sha256)).as("distinct_content");
1238
1506
  const [content] = await this.db
1239
1507
  .select({ bytes: sql `coalesce(sum(${distinct.size}), 0)::bigint`.mapWith(Number) })
1240
1508
  .from(distinct);
@@ -1242,22 +1510,26 @@ class PostgresTx {
1242
1510
  }
1243
1511
  async insertArtifactContent(artifactId, version, files) {
1244
1512
  this.check();
1245
- for (let at = 0; at < files.length; at += CONTENT_BATCH)
1513
+ for (let at = 0; at < files.length; at += contentBatch())
1246
1514
  await this.db
1247
1515
  .insert(artifactContent)
1248
1516
  .values(files
1249
- .slice(at, at + CONTENT_BATCH)
1517
+ .slice(at, at + contentBatch())
1250
1518
  .map((file) => ({ artifactId, version, sha256: file.sha256, size: file.size })))
1251
1519
  .onConflictDoNothing();
1252
1520
  }
1253
- async referencedArtifactContent(shas) {
1521
+ async referencedArtifactContent(shas, scope) {
1254
1522
  this.check();
1255
1523
  const found = new Set();
1256
- for (let at = 0; at < shas.length; at += CONTENT_BATCH) {
1257
- const rows = await this.db
1258
- .selectDistinct({ sha256: artifactContent.sha256 })
1259
- .from(artifactContent)
1260
- .where(inArray(artifactContent.sha256, shas.slice(at, at + CONTENT_BATCH)));
1524
+ for (let at = 0; at < shas.length; at += contentBatch()) {
1525
+ const batch = inArray(artifactContent.sha256, shas.slice(at, at + contentBatch()));
1526
+ const rows = scope === undefined
1527
+ ? await this.db.selectDistinct({ sha256: artifactContent.sha256 }).from(artifactContent).where(batch)
1528
+ : await this.db
1529
+ .selectDistinct({ sha256: artifactContent.sha256 })
1530
+ .from(artifactContent)
1531
+ .innerJoin(artifacts, eq(artifacts.id, artifactContent.artifactId))
1532
+ .where(and(batch, this.artifactsOfEnvironment(scope.environmentId)));
1261
1533
  for (const row of rows)
1262
1534
  found.add(row.sha256);
1263
1535
  }
@@ -1302,23 +1574,23 @@ class PostgresTx {
1302
1574
  }
1303
1575
  async heldDefinitionFiles(shas) {
1304
1576
  this.check();
1305
- const found = new Set();
1306
- for (let at = 0; at < shas.length; at += CONTENT_BATCH) {
1577
+ const found = new Map();
1578
+ for (let at = 0; at < shas.length; at += contentBatch()) {
1307
1579
  const rows = await this.db
1308
- .select({ sha256: definitionFiles.sha256 })
1580
+ .select({ sha256: definitionFiles.sha256, size: definitionFiles.size })
1309
1581
  .from(definitionFiles)
1310
- .where(inArray(definitionFiles.sha256, shas.slice(at, at + CONTENT_BATCH)));
1582
+ .where(inArray(definitionFiles.sha256, shas.slice(at, at + contentBatch())));
1311
1583
  for (const row of rows)
1312
- found.add(row.sha256);
1584
+ found.set(row.sha256, row.size);
1313
1585
  }
1314
1586
  return found;
1315
1587
  }
1316
1588
  async insertDefinitionFileUses(agentId, manifestHash, shas) {
1317
1589
  this.check();
1318
- for (let at = 0; at < shas.length; at += CONTENT_BATCH)
1590
+ for (let at = 0; at < shas.length; at += contentBatch())
1319
1591
  await this.db
1320
1592
  .insert(definitionFileUses)
1321
- .values(shas.slice(at, at + CONTENT_BATCH).map((sha256) => ({ agentId, manifestHash, sha256 })))
1593
+ .values(shas.slice(at, at + contentBatch()).map((sha256) => ({ agentId, manifestHash, sha256 })))
1322
1594
  .onConflictDoNothing();
1323
1595
  }
1324
1596
  // --- settings ------------------------------------------------------------
@@ -1344,6 +1616,8 @@ class PostgresTx {
1344
1616
  if (scope === "sessions" || scope === "all") {
1345
1617
  for (const table of SESSION_TABLES)
1346
1618
  await db.delete(table);
1619
+ // A session's booked wake (T4) goes with it.
1620
+ await db.delete(agentTriggers).where(eq(agentTriggers.kind, "wake"));
1347
1621
  await db.delete(toolCrossings);
1348
1622
  // A session's artifacts go with it (their versions by cascade).
1349
1623
  await db.delete(artifacts).where(isNotNull(artifacts.sessionId));
@@ -1356,15 +1630,20 @@ class PostgresTx {
1356
1630
  basinGeneration: sql `${tenant.basinGeneration} + 1`,
1357
1631
  });
1358
1632
  }
1359
- if (scope === "environments" || scope === "all") {
1633
+ if (scope === "agents" || scope === "all") {
1360
1634
  await db.delete(sandboxes);
1361
1635
  // Their vaults and credentials go with them (ON DELETE CASCADE).
1362
- await db.delete(environments);
1363
- await db.delete(environmentEvents);
1636
+ await db.delete(agents);
1637
+ await db.delete(agentEvents);
1638
+ await db.delete(agentTriggers);
1639
+ await db.delete(triggerRuns);
1640
+ // Memories belong to the Agents (D72).
1641
+ await db.delete(memories);
1642
+ await db.delete(memoryVersions);
1364
1643
  await db.delete(sandboxSignals);
1365
1644
  }
1366
1645
  if (scope === "all") {
1367
- await db.delete(definitions);
1646
+ await db.delete(agentManifests);
1368
1647
  // The files stay, as their bytes do; only what used them goes.
1369
1648
  await db.delete(definitionFileUses);
1370
1649
  await db.delete(modelUsage);