@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
@@ -1,4 +1,5 @@
1
- import { piModel } from "../model/pi-model.js";
1
+ import { modelCallSettingsOf, piModel } from "../model/pi-model.js";
2
+ import { readRuntimeLimits } from "../tenant/runtime-limits.js";
2
3
  import { HostModelVault } from "../vault/host-model.js";
3
4
  import { createMeter } from "./meter.js";
4
5
  import { artifactFiles } from "../artifacts/files.js";
@@ -19,18 +20,25 @@ export function callFiles(store, blobs) {
19
20
  */
20
21
  export function tenantModelGate(options) {
21
22
  const vault = new HostModelVault({ store: options.store, kek: options.kek });
22
- const gate = inProcessModelGate({
23
- root: options.root,
24
- readHostModel: () => vault.readHostModel(),
25
- writeHostCredential: (credential) => vault.updateHostCredential(credential),
26
- ...(options.settings ? { settings: options.settings } : {}),
27
- ...(options.blobs ? { files: callFiles(options.store, options.blobs) } : {}),
28
- });
29
23
  const meter = createMeter({ logger: options.logger });
30
24
  return {
31
- call: (request, signal) => meter.call(options.store, request, () => serve(options.store, gate, request, signal)),
25
+ call: (request, signal) => meter.call(options.store, request, async () => {
26
+ // The Tenant's Runtime limits `model*`, read for this call.
27
+ const gate = inProcessModelGate({
28
+ root: options.root,
29
+ readHostModel: () => vault.readHostModel(),
30
+ writeHostCredential: (credential) => vault.updateHostCredential(credential),
31
+ settings: await modelCallSettings(options.store),
32
+ ...(options.blobs ? { files: callFiles(options.store, options.blobs) } : {}),
33
+ });
34
+ return serve(options.store, gate, request, signal);
35
+ }),
32
36
  };
33
37
  }
38
+ /** The Tenant's model call settings: its Runtime limits `model*`, read now. */
39
+ export async function modelCallSettings(store) {
40
+ return modelCallSettingsOf(await store.tx((t) => readRuntimeLimits(t)));
41
+ }
34
42
  /**
35
43
  * Serves one call: from the fixture model while the Tenant's `model.fixture` setting is on (R4.3),
36
44
  * else from `gate`. Read per call, so a seed applies to the next call.
@@ -49,9 +49,9 @@ export interface InflightCalls<T = ModelGateOutcome> {
49
49
  readonly size: number;
50
50
  }
51
51
  export interface InflightCallsOptions {
52
- /** How long a settled outcome is kept. Default 30 minutes. */
52
+ /** How long a settled outcome is kept. Default `gates.inflightTtlMs` (Host tuning, 30 min). */
53
53
  readonly ttlMs?: number;
54
- /** Most entries; the oldest settled ones go first. Default 10,000. */
54
+ /** Most entries; the oldest settled ones go first. Default `gates.inflightMax` (10,000). */
55
55
  readonly max?: number;
56
56
  readonly now?: () => number;
57
57
  }
@@ -1,3 +1,4 @@
1
+ import { hostTuning } from "../tuning.js";
1
2
  /** A re-send whose request differs from the call already running under its key. */
2
3
  export class InflightConflict extends Error {
3
4
  name = "InflightConflict";
@@ -7,8 +8,8 @@ export class InflightStale extends Error {
7
8
  name = "InflightStale";
8
9
  }
9
10
  export function createInflightCalls(options = {}) {
10
- const ttlMs = options.ttlMs ?? 30 * 60_000;
11
- const max = options.max ?? 10_000;
11
+ const ttlMs = options.ttlMs ?? hostTuning().gates.inflightTtlMs;
12
+ const max = options.max ?? hostTuning().gates.inflightMax;
12
13
  const now = options.now ?? Date.now;
13
14
  const entries = new Map();
14
15
  /** Drops expired outcomes, then the oldest settled ones while over `max`. */
@@ -1,4 +1,3 @@
1
- import { mcpToolOf } from "../mcp/snapshot.js";
2
1
  import { canonical } from "../store/canonical.js";
3
2
  import { httpToolRefOf } from "./http-tool.js";
4
3
  export function journalCheck(vaults) {
@@ -25,12 +24,11 @@ export function journalCheck(vaults) {
25
24
  return `Effect '${key}' was journaled with other input`;
26
25
  return held(row);
27
26
  }
28
- const session = await t.get("sessions", request.sessionId);
29
- const tool = mcpToolOf(session?.mcpSnapshot, request);
30
- if (!tool ||
31
- tool.serverName !== call.server.serverName ||
32
- (tool.agentId ?? null) !== (call.server.agentId ?? null) ||
33
- tool.serverToolName !== call.name)
27
+ const target = request.target;
28
+ if (target?.kind !== "mcp" ||
29
+ target.server !== call.server.serverName ||
30
+ target.tool !== call.name ||
31
+ (request.agent?.id ?? null) !== (call.server.agentId ?? null))
34
32
  return `Effect '${key}' calls another tool`;
35
33
  if (canonical(argumentsOf(request.input)) !== canonical(call.arguments))
36
34
  return `Effect '${key}' was journaled with other input`;
@@ -4,12 +4,13 @@ import type { OutboundPolicy } from "../tenant/outbound.js";
4
4
  import type { Logger } from "../tenant/types.js";
5
5
  import type { McpAnswer } from "./tool-contract.js";
6
6
  import { type TenantVaults } from "./tenant-vaults.js";
7
- /** A connection unused this long is closed; the next request opens it again. */
8
- export declare const GATE_MCP_IDLE_MS: number;
9
7
  export interface McpHandlerOptions {
10
8
  readonly vaults: TenantVaults;
11
9
  readonly logger: Logger;
12
- /** Default `GATE_MCP_IDLE_MS`. */
10
+ /**
11
+ * A connection unused this long is closed; the next request opens it again. Default
12
+ * `gates.mcpIdleMs` (Host tuning, 15 min).
13
+ */
13
14
  readonly idleMs?: number;
14
15
  readonly now?: () => number;
15
16
  /** Tests replace how a server is opened. */
@@ -1,14 +1,14 @@
1
1
  import { McpCallFailed, McpConnectionStale, openMcpServer, unreachable, } from "../mcp/connect.js";
2
2
  import { findServer } from "../mcp/pool.js";
3
+ import { readRuntimeLimits } from "../tenant/runtime-limits.js";
3
4
  import { GateRefusal } from "./tenant-vaults.js";
4
- /** A connection unused this long is closed; the next request opens it again. */
5
- export const GATE_MCP_IDLE_MS = 15 * 60_000;
5
+ import { hostTuning } from "../tuning.js";
6
6
  /** The server is not one the session may reach through the gate. */
7
7
  class NotDeclared extends Error {
8
8
  }
9
9
  export function createMcpHandler(options) {
10
10
  const { vaults, logger } = options;
11
- const idleMs = options.idleMs ?? GATE_MCP_IDLE_MS;
11
+ const idleMs = options.idleMs ?? hostTuning().gates.mcpIdleMs;
12
12
  const now = options.now ?? Date.now;
13
13
  const open = options.open ?? openMcpServer;
14
14
  const live = new Map();
@@ -42,6 +42,7 @@ export function createMcpHandler(options) {
42
42
  ...(server.agentId === undefined ? {} : { agentId: server.agentId }),
43
43
  }),
44
44
  policy: options.delivery ?? {},
45
+ errorExcerptChars: (await vault.store.tx((t) => readRuntimeLimits(t))).errorExcerptChars,
45
46
  });
46
47
  const entry = { connection, lastUsedAt: now(), active: 0 };
47
48
  live.set(key, entry);
@@ -80,7 +81,11 @@ export function createMcpHandler(options) {
80
81
  // the session is not the server's failure, and stays as it was.
81
82
  if (!call || error instanceof GateRefusal || error instanceof NotDeclared)
82
83
  throw error;
83
- throw unreachable(server.serverName, error);
84
+ const limits = await vaults
85
+ .open(tenantId)
86
+ .then((vault) => vault.store.tx((t) => readRuntimeLimits(t)))
87
+ .catch(() => undefined);
88
+ throw unreachable(server.serverName, error, limits?.errorExcerptChars);
84
89
  }
85
90
  }
86
91
  async function use(tenantId, server, run, call = false) {
@@ -112,10 +117,15 @@ export function createMcpHandler(options) {
112
117
  * the call sent once more (R2b C7).
113
118
  */
114
119
  async function callOnce(tenantId, request, signal) {
120
+ // The Tenant's Runtime limits, read for this call: the largest answer the gate keeps, and how
121
+ // much of a failed one its error quotes.
122
+ const { toolAnswerBytes, errorExcerptChars } = await (await vaults.open(tenantId)).store.tx((t) => readRuntimeLimits(t));
115
123
  for (let attempt = 0;; attempt += 1) {
116
124
  try {
117
125
  return await use(tenantId, request.server, (entry) => entry.connection.client.callTool({ name: request.name, arguments: request.arguments }, {
118
126
  signal,
127
+ maxResultBytes: toolAnswerBytes,
128
+ errorExcerptChars,
119
129
  ...(request.key === undefined ? {} : { key: request.key }),
120
130
  ...(request.traceparent === undefined ? {} : { traceparent: request.traceparent }),
121
131
  }), true);
@@ -188,7 +198,7 @@ function errorOf(error) {
188
198
  ...(error.code === "credential_rejected" ? { code: 401 } : {}),
189
199
  failure: error.failure,
190
200
  };
191
- const message = error instanceof Error ? error.message.slice(0, 2000) : String(error);
201
+ const message = error instanceof Error ? error.message.slice(0, hostTuning().gates.errorMessageChars) : String(error);
192
202
  const code = error && typeof error === "object" && "code" in error && typeof error.code === "number"
193
203
  ? error.code
194
204
  : undefined;
@@ -37,7 +37,7 @@ export function createMeter(options) {
37
37
  session: request.sessionId,
38
38
  effect: request.effectId,
39
39
  scope: budget.scope,
40
- ...(budget.scope === "agent" ? { agent: budget.scopeId } : {}),
40
+ ...(budget.scope === "manifest" ? { manifest: budget.scopeId } : {}),
41
41
  });
42
42
  return { keys, refusal: failure("budget_exhausted", reached, false) };
43
43
  }
@@ -124,7 +124,8 @@ export function usageRow(request, outcome, at, timing) {
124
124
  : null,
125
125
  sessionId: request.sessionId,
126
126
  turnId: request.turnId,
127
- agentId: request.agentId,
127
+ // The calling agent's loop manifest id: a manifest version's name (protocol 16).
128
+ manifestName: request.agentId,
128
129
  provider: producer.provider ?? null,
129
130
  model: producer.model ?? outcome.evidence?.resolvedModel ?? request.call.model?.id ?? null,
130
131
  inputTokens,
@@ -148,8 +149,8 @@ function scopeOf(budget, request, at) {
148
149
  const since = budget.period ? { since: periodStart(budget.period, at) } : {};
149
150
  if (budget.scope === "turn")
150
151
  return { scope: "turn", id: request.turnId };
151
- if (budget.scope === "agent")
152
- return budget.scopeId === request.agentId ? { scope: "agent", id: request.agentId, ...since } : undefined;
152
+ if (budget.scope === "manifest")
153
+ return budget.scopeId === request.agentId ? { scope: "manifest", id: request.agentId, ...since } : undefined;
153
154
  return { scope: "tenant", ...since };
154
155
  }
155
156
  /**
@@ -160,7 +161,7 @@ export function capReached(budget, spent, inflight) {
160
161
  const projected = (total) => total + (spent.calls > 0 ? (inflight * total) / spent.calls : 0);
161
162
  const name = budget.scope === "turn"
162
163
  ? "The turn's cap"
163
- : `${budget.scope === "agent" ? `Agent ${budget.scopeId}'s` : "The Tenant's"} ${budget.period === "day" ? "daily" : "monthly"} cap`;
164
+ : `${budget.scope === "manifest" ? `Agent manifest ${budget.scopeId}'s` : "The Tenant's"} ${budget.period === "day" ? "daily" : "monthly"} cap`;
164
165
  const raise = "raise it with PUT /v1/tenant/budgets";
165
166
  if (budget.limitTokens !== null && projected(spent.tokens) >= budget.limitTokens)
166
167
  return `${name} of ${budget.limitTokens} tokens is reached (${spent.tokens} used); ${raise}`;
@@ -4,11 +4,13 @@
4
4
  * call needs that the loop must not hold: the provider credential, pi-ai, its retries and
5
5
  * idle watchdog, failure classification and scrubbing.
6
6
  *
7
- * Two implementations: `inProcessModelGate` (embedding, the ephemeral Runtime, tests) and the
7
+ * Three implementations: `inProcessModelGate` (embedding, the ephemeral Runtime, tests), the
8
8
  * HTTP client of the gates service (the `gateway` container), which keeps the credential out
9
- * of the loop process. Both return what `piModel` returns, so the effect journal is the same
9
+ * of the loop process, and `providerModelGate`, which serves a Runtime's scripted model (tests,
10
+ * `model: {kind: "scripted"}`) the same way, metered. Both return what `piModel` returns, so the effect journal is the same
10
11
  * either way.
11
12
  */
13
+ import type { AgentRef } from "@nylorun/core/define";
12
14
  import type { RuntimeModelAdapter, RuntimeModelCall } from "../contracts.js";
13
15
  export type { ModelCallSettings } from "../model/pi-model.js";
14
16
  /**
@@ -25,6 +27,13 @@ export interface ModelGateRequest {
25
27
  /** The effect's journal id; sent as `Idempotency-Key` (acted on from P1.2). */
26
28
  readonly effectId: string;
27
29
  readonly invocationId: string;
30
+ /**
31
+ * The agent used as a tool the call is for; absent for the session's root agent. In process
32
+ * only: a scripted provider reads it (`providerModelGate`).
33
+ */
34
+ readonly agent?: AgentRef;
35
+ /** A call that summarizes history for a compaction (protocol 15); in process only, like `agent`. */
36
+ readonly purpose?: "summary";
28
37
  readonly call: RuntimeModelCall;
29
38
  }
30
39
  /** A model candidate or a failure outcome: exactly what `piModel` returns. */
@@ -10,11 +10,17 @@
10
10
  * (`deny`, then `ask`, then `allow`), and a call no rule matches runs. A session pinned to a
11
11
  * manifest saved before R5 step 2 keeps its `approval: "always"` as an ask: no session loses
12
12
  * the approval it was opened with. A policy that cannot be read refuses every call.
13
+ *
14
+ * A rule's `tool` matches the tool's identity (protocol 15): an MCP tool's own name on its
15
+ * server (`server` names the server), an HTTP tool's declared name, a flow stage's key. The name
16
+ * a harness gave the model never matches. A stored rule whose `tool` has `__` in it (an MCP tool
17
+ * named by its old model-facing `server__tool` name) makes the policy unreadable, so every call
18
+ * is refused until the policy names it by `server` and `tool`: a rule never silently stops
19
+ * matching.
13
20
  */
14
21
  import { type ToolPolicy, type ToolRule } from "@nylorun/core/contracts";
15
22
  import type { AgentManifest } from "@nylorun/core/define";
16
23
  import type { HostEffect } from "@nylorun/harness/run";
17
- import { type McpSnapshot } from "../mcp/snapshot.js";
18
24
  import type { Tx } from "../store/types.js";
19
25
  import type { Session } from "../tenant/context.js";
20
26
  /** The `tenant_settings` key the policy is kept under. */
@@ -22,13 +28,18 @@ export declare const TOOL_POLICY_SETTING = "tool-policy";
22
28
  /** A call as the policy reads it. */
23
29
  export interface PolicyCall {
24
30
  readonly kind: "mcp" | "http";
25
- /** The name the model calls the tool by; a flow stage's key. */
31
+ /**
32
+ * The tool's identity: an MCP tool's own name on its server, an HTTP tool's declared name, a
33
+ * flow stage's key.
34
+ */
26
35
  readonly tool: string;
27
36
  /** The MCP server's name. */
28
37
  readonly server?: string;
29
- /** The agent that calls it. */
38
+ /** The agent that calls it: its manifest's id (an agent manifest's name), never an Agent's id. */
30
39
  readonly agent: string;
31
40
  readonly input: unknown;
41
+ /** The name the model called it by, for display only: no rule matches it. */
42
+ readonly name?: string;
32
43
  }
33
44
  export type PolicyDecision = {
34
45
  readonly effect: "allow";
@@ -36,14 +47,31 @@ export type PolicyDecision = {
36
47
  readonly effect: "ask" | "deny";
37
48
  readonly reason: string;
38
49
  };
39
- /** The Tenant's policy; an empty one when none was set. Throws when it cannot be read. */
50
+ /** A stored policy this Runtime cannot apply: every call is refused, with `message` as why. */
51
+ export declare class ToolPolicyUnreadable extends Error {
52
+ constructor(message: string);
53
+ }
54
+ /**
55
+ * The Tenant's policy; an empty one when none was set. Throws when it cannot be read, a
56
+ * `ToolPolicyUnreadable` saying which rule when one names an MCP tool by a model-facing name.
57
+ */
40
58
  export declare function readToolPolicy(t: Pick<Tx, "getSetting">): Promise<ToolPolicy>;
41
59
  /**
42
60
  * The decision for `request`, a session's MCP or HTTP tool call: the Tenant's rules and the
43
61
  * pinned manifest's `approval`. A policy that cannot be read refuses the call.
44
62
  */
45
63
  export declare function toolCallDecision(t: Pick<Tx, "getSetting">, s: Session, request: HostEffect, kind: "mcp" | "http"): Promise<PolicyDecision>;
64
+ /**
65
+ * `request` as the policy reads it: by its target's identity (protocol 15), and by the agent that
66
+ * calls it: an agent used as a tool by its id, the session's root agent by its loop manifest's id
67
+ * (protocol 16: the agent manifest's name). Never the session's Agent id (`s.agentId`), which
68
+ * protocol 16 made the Agent the session runs on (`users/ada/desk` for the manifest `desk`).
69
+ */
70
+ export declare function policyCallOf(s: Pick<Session, "manifest">, request: HostEffect, kind: "mcp" | "http"): PolicyCall;
46
71
  /** Decides `call` by `rules`; `pinnedAsk` adds the ask of a manifest saved before R5 step 2. */
47
72
  export declare function decide(rules: readonly ToolRule[], call: PolicyCall, pinnedAsk?: boolean): PolicyDecision;
48
- /** The pinned `approval: "always"` of the call's tool, in a manifest saved before R5 step 2. */
49
- export declare function pinnedApproval(manifest: AgentManifest, snapshot: McpSnapshot | undefined, request: HostEffect): boolean;
73
+ /**
74
+ * The pinned `approval: "always"` of the call's tool, in a manifest saved before R5 step 2: an
75
+ * MCP tool's settings by its own name, an HTTP tool's declaration by its declared name.
76
+ */
77
+ export declare function pinnedApproval(manifest: AgentManifest, request: HostEffect): boolean;
@@ -10,21 +10,44 @@
10
10
  * (`deny`, then `ask`, then `allow`), and a call no rule matches runs. A session pinned to a
11
11
  * manifest saved before R5 step 2 keeps its `approval: "always"` as an ask: no session loses
12
12
  * the approval it was opened with. A policy that cannot be read refuses every call.
13
+ *
14
+ * A rule's `tool` matches the tool's identity (protocol 15): an MCP tool's own name on its
15
+ * server (`server` names the server), an HTTP tool's declared name, a flow stage's key. The name
16
+ * a harness gave the model never matches. A stored rule whose `tool` has `__` in it (an MCP tool
17
+ * named by its old model-facing `server__tool` name) makes the policy unreadable, so every call
18
+ * is refused until the policy names it by `server` and `tool`: a rule never silently stops
19
+ * matching.
13
20
  */
14
21
  import { ToolPolicySchema } from "@nylorun/core/contracts";
15
- import { mcpToolOf, mcpToolSettingsIn } from "../mcp/snapshot.js";
22
+ import { mcpToolSettingsIn } from "../mcp/snapshot.js";
16
23
  import { canonical } from "../store/canonical.js";
17
24
  import { turnManifestOf } from "../tenant/session.js";
18
25
  import { declaredHttpTool } from "./http-tool.js";
19
26
  /** The `tenant_settings` key the policy is kept under. */
20
27
  export const TOOL_POLICY_SETTING = "tool-policy";
21
28
  const STRICTNESS = { allow: 0, ask: 1, deny: 2 };
22
- /** The Tenant's policy; an empty one when none was set. Throws when it cannot be read. */
29
+ /** A stored policy this Runtime cannot apply: every call is refused, with `message` as why. */
30
+ export class ToolPolicyUnreadable extends Error {
31
+ constructor(message) {
32
+ super(message);
33
+ this.name = "ToolPolicyUnreadable";
34
+ }
35
+ }
36
+ /**
37
+ * The Tenant's policy; an empty one when none was set. Throws when it cannot be read, a
38
+ * `ToolPolicyUnreadable` saying which rule when one names an MCP tool by a model-facing name.
39
+ */
23
40
  export async function readToolPolicy(t) {
24
41
  const raw = await t.getSetting(TOOL_POLICY_SETTING);
25
42
  if (raw === undefined)
26
43
  return { rules: [], updatedAt: null };
27
- return ToolPolicySchema.parse(JSON.parse(raw));
44
+ const parsed = ToolPolicySchema.safeParse(JSON.parse(raw));
45
+ if (parsed.success)
46
+ return parsed.data;
47
+ const issue = parsed.error.issues[0];
48
+ throw new ToolPolicyUnreadable(issue?.path.at(-1) === "tool"
49
+ ? `Rule ${Number(issue.path[1]) + 1} of the Tenant's tool policy names a tool by a model-facing name: ${issue.message}. Set the policy again (PUT /v1/tenant/tool-policy)`
50
+ : `The Tenant's tool policy could not be read: ${issue?.message ?? "malformed"}`);
28
51
  }
29
52
  /**
30
53
  * The decision for `request`, a session's MCP or HTTP tool call: the Tenant's rules and the
@@ -35,22 +58,42 @@ export async function toolCallDecision(t, s, request, kind) {
35
58
  try {
36
59
  rules = (await readToolPolicy(t)).rules;
37
60
  }
38
- catch {
39
- return { effect: "deny", reason: "The Tenant's tool policy could not be read, so no tool call runs" };
61
+ catch (error) {
62
+ return {
63
+ effect: "deny",
64
+ reason: error instanceof ToolPolicyUnreadable
65
+ ? `${error.message}, so no tool call runs`
66
+ : "The Tenant's tool policy could not be read, so no tool call runs",
67
+ };
40
68
  }
41
- const mcp = mcpToolOf(s.mcpSnapshot, request);
42
- return decide(rules, {
69
+ return decide(rules, policyCallOf(s, request, kind), pinnedApproval(turnManifestOf(s), request));
70
+ }
71
+ /**
72
+ * `request` as the policy reads it: by its target's identity (protocol 15), and by the agent that
73
+ * calls it: an agent used as a tool by its id, the session's root agent by its loop manifest's id
74
+ * (protocol 16: the agent manifest's name). Never the session's Agent id (`s.agentId`), which
75
+ * protocol 16 made the Agent the session runs on (`users/ada/desk` for the manifest `desk`).
76
+ */
77
+ export function policyCallOf(s, request, kind) {
78
+ const target = request.target;
79
+ return {
43
80
  kind,
44
- tool: request.toolName ?? request.key ?? request.effectId,
45
- ...(mcp ? { server: mcp.serverName } : {}),
46
- agent: request.agent?.id ?? s.agentId,
81
+ tool: target?.kind === "mcp" || target?.kind === "http"
82
+ ? target.tool
83
+ : (request.key ?? request.effectId),
84
+ ...(target?.kind === "mcp" ? { server: target.server } : {}),
85
+ agent: request.agent?.id ?? s.manifest.id,
47
86
  input: request.input,
48
- }, pinnedApproval(turnManifestOf(s), s.mcpSnapshot, request));
87
+ ...(request.toolName === undefined ? {} : { name: request.toolName }),
88
+ };
49
89
  }
50
90
  /** Decides `call` by `rules`; `pinnedAsk` adds the ask of a manifest saved before R5 step 2. */
51
91
  export function decide(rules, call, pinnedAsk = false) {
52
92
  let strictest = pinnedAsk
53
- ? { effect: "ask", reason: `The agent's manifest asks for approval of '${call.tool}'` }
93
+ ? {
94
+ effect: "ask",
95
+ reason: `The agent's manifest asks for approval of '${call.server === undefined ? call.tool : `${call.server} / ${call.tool}`}'`,
96
+ }
54
97
  : undefined;
55
98
  for (const rule of rules) {
56
99
  if (!matches(rule, call))
@@ -63,12 +106,17 @@ export function decide(rules, call, pinnedAsk = false) {
63
106
  return { effect: "allow" };
64
107
  return { effect: strictest.effect, reason: strictest.reason };
65
108
  }
66
- /** The pinned `approval: "always"` of the call's tool, in a manifest saved before R5 step 2. */
67
- export function pinnedApproval(manifest, snapshot, request) {
68
- const mcp = mcpToolOf(snapshot, request);
69
- if (mcp)
70
- return mcpToolSettingsIn(manifest, mcp).approval === "always";
71
- return declaredHttpTool(manifest, request.agent?.id, request.toolName)?.approval === "always";
109
+ /**
110
+ * The pinned `approval: "always"` of the call's tool, in a manifest saved before R5 step 2: an
111
+ * MCP tool's settings by its own name, an HTTP tool's declaration by its declared name.
112
+ */
113
+ export function pinnedApproval(manifest, request) {
114
+ const target = request.target;
115
+ if (target?.kind === "mcp")
116
+ return mcpToolSettingsIn(manifest, request.agent?.id, target.server, target.tool).approval === "always";
117
+ if (target?.kind === "http")
118
+ return declaredHttpTool(manifest, request.agent?.id, target.tool)?.approval === "always";
119
+ return false;
72
120
  }
73
121
  function matches(rule, call) {
74
122
  if (rule.kind !== undefined && rule.kind !== call.kind)
@@ -0,0 +1,22 @@
1
+ /**
2
+ * A Model Gate over a `ModelProvider` (protocol 15): how a Runtime whose model is scripted (tests,
3
+ * `model: {kind: "scripted"}` or `"fixture"`, an embedder's provider) serves its harness's model
4
+ * calls. The harness calls the gate as it calls any (`invokeModel`), in process or not: no harness
5
+ * calls a provider directly.
6
+ *
7
+ * The provider gets the call as an effect (`HostEffect`), rebuilt from the request: the ids, the
8
+ * agent used as a tool, the call's purpose, and the call as its `input`. With a store, each call
9
+ * is metered in the usage ledger like the Tenant's own gate's, and the Tenant's fixture model
10
+ * setting is answered first (R4.3). It dies with its process: it never `recovers`.
11
+ */
12
+ import type { HostEffect } from "@nylorun/harness/run";
13
+ import type { ModelProvider } from "../core/provider.js";
14
+ import type { SessionStore } from "../store/types.js";
15
+ import type { Logger } from "../tenant/types.js";
16
+ import type { ModelGate, ModelGateRequest } from "./model-gate.js";
17
+ /** The effect a provider sees for `request`. */
18
+ export declare function providerEffect(request: ModelGateRequest): HostEffect;
19
+ export declare function providerModelGate(provider: ModelProvider, options?: {
20
+ readonly store?: SessionStore;
21
+ readonly logger?: Logger;
22
+ }): ModelGate;
@@ -0,0 +1,30 @@
1
+ import { serve } from "./in-process.js";
2
+ import { createMeter } from "./meter.js";
3
+ /** The effect a provider sees for `request`. */
4
+ export function providerEffect(request) {
5
+ return {
6
+ effectId: request.effectId,
7
+ sessionId: request.sessionId,
8
+ turnId: request.turnId,
9
+ agentId: request.agentId,
10
+ // The gate is told no definition hash; a provider routes by the call, never by the hash.
11
+ manifestHash: "",
12
+ kind: "model",
13
+ ...(request.agent === undefined ? {} : { agent: request.agent }),
14
+ ...(request.purpose === undefined ? {} : { purpose: request.purpose }),
15
+ input: request.call,
16
+ context: { invocationId: request.invocationId },
17
+ };
18
+ }
19
+ export function providerModelGate(provider, options = {}) {
20
+ const direct = {
21
+ call: async (request, signal) => (await provider(providerEffect(request), signal)),
22
+ };
23
+ const { store, logger } = options;
24
+ if (!store || !logger)
25
+ return direct;
26
+ const meter = createMeter({ logger });
27
+ return {
28
+ call: (request, signal) => meter.call(store, request, () => serve(store, direct, request, signal)),
29
+ };
30
+ }
@@ -21,8 +21,6 @@ import type { Logger } from "../tenant/types.js";
21
21
  import { type InflightCallsOptions, type InflightOwner } from "./inflight.js";
22
22
  import type { TenantVaults } from "./tenant-vaults.js";
23
23
  import type { McpAnswer } from "./tool-contract.js";
24
- /** How long a settled crossing is kept. */
25
- export declare const TOOL_CROSSING_TTL_MS: number;
26
24
  /** A tool call's answer: an MCP `CallToolResult`, or an HTTP tool's outcome. */
27
25
  export type ToolCallAnswer = McpAnswer<Record<string, unknown>>;
28
26
  export interface ToolCalls {
@@ -40,7 +38,7 @@ export interface ToolCalls {
40
38
  cancel(key: string, sessionId?: string): boolean;
41
39
  /** Aborts every running call (gateway shutdown). */
42
40
  close(): void;
43
- /** Deletes crossings settled more than `TOOL_CROSSING_TTL_MS` ago. */
41
+ /** Deletes crossings settled more than `gates.toolCrossingTtlMs` (Host tuning, 24 h) ago. */
44
42
  prune(): Promise<void>;
45
43
  }
46
44
  export interface ToolCallsOptions {
@@ -1,6 +1,5 @@
1
1
  import { createInflightCalls, InflightConflict, } from "./inflight.js";
2
- /** How long a settled crossing is kept. */
3
- export const TOOL_CROSSING_TTL_MS = 24 * 60 * 60_000;
2
+ import { hostTuning } from "../tuning.js";
4
3
  const CANCELLED = {
5
4
  ok: false,
6
5
  error: { message: "The call was cancelled while it ran; it may have reached its server" },
@@ -71,7 +70,7 @@ export function createToolCalls(options) {
71
70
  async prune() {
72
71
  try {
73
72
  const vault = await vaults.open(undefined);
74
- const before = new Date(now() - TOOL_CROSSING_TTL_MS).toISOString();
73
+ const before = new Date(now() - hostTuning().gates.toolCrossingTtlMs).toISOString();
75
74
  await vault.store.tx((t) => t.pruneToolCrossings(before));
76
75
  }
77
76
  catch {
@@ -21,7 +21,7 @@ export interface HttpToolGateOptions {
21
21
  readonly runTokens?: RunTokens;
22
22
  /** Sent as `Nylorun-Tenant`; the gate checks it against its database's Tenant. */
23
23
  readonly tenantId?: string;
24
- /** How long an MCP request may stay silent. Default `GATE_CLIENT_TIMEOUT_MS`. */
24
+ /** How long an MCP request may stay silent. Default `gates.clientTimeoutMs` (Host tuning). */
25
25
  readonly timeoutMs?: number;
26
26
  }
27
27
  export declare function httpToolGate(options: HttpToolGateOptions): ToolGate;
@@ -26,7 +26,7 @@ import { request as httpRequest } from "node:http";
26
26
  import { request as httpsRequest } from "node:https";
27
27
  import { McpCallFailed, } from "../mcp/connect.js";
28
28
  import { TENANT_HEADER } from "./contract.js";
29
- import { GATE_CLIENT_TIMEOUT_MS } from "./http-client.js";
29
+ import { hostTuning } from "../tuning.js";
30
30
  import { HTTP_CALLS_PATH, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, TOOL_CALLS_PATH, } from "./tool-contract.js";
31
31
  /**
32
32
  * A keyed call whose answer the hop lost (R5.3): the gate never got it, the connection broke,
@@ -36,11 +36,9 @@ import { HTTP_CALLS_PATH, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, TOOL_
36
36
  export class GateCallLost extends Error {
37
37
  name = "GateCallLost";
38
38
  }
39
- /** How long a close or a cancel may take; neither changes an outcome. */
40
- const SHORT_TIMEOUT_MS = 2_000;
41
39
  export function httpToolGate(options) {
42
40
  const where = new URL(options.url).origin;
43
- const timeoutMs = options.timeoutMs ?? GATE_CLIENT_TIMEOUT_MS;
41
+ const timeoutMs = options.timeoutMs ?? hostTuning().gates.clientTimeoutMs;
44
42
  function exchange(path, body, request) {
45
43
  const url = new URL(path, options.url);
46
44
  const send = url.protocol === "https:" ? httpsRequest : httpRequest;
@@ -88,7 +86,7 @@ export function httpToolGate(options) {
88
86
  responded = true;
89
87
  readBody(response).then((text) => settle({ kind: "answer", status: response.statusCode ?? 0, text }), (error) => failed(error));
90
88
  });
91
- outgoing.on("socket", (socket) => socket.setKeepAlive(true, 30_000));
89
+ outgoing.on("socket", (socket) => socket.setKeepAlive(true, hostTuning().gates.keepAliveMs));
92
90
  outgoing.on("finish", () => {
93
91
  sent = true;
94
92
  });
@@ -147,7 +145,8 @@ export function httpToolGate(options) {
147
145
  }
148
146
  async function fireAndForget(path, scope) {
149
147
  await exchange(path, scope.body, {
150
- timeoutMs: SHORT_TIMEOUT_MS,
148
+ // A close or a cancel is short (`gates.shortTimeoutMs`); neither changes an outcome.
149
+ timeoutMs: hostTuning().gates.shortTimeoutMs,
151
150
  ...(scope.bearer ? { bearer: scope.bearer } : {}),
152
151
  });
153
152
  }
@@ -23,14 +23,17 @@
23
23
  * - `POST /nylorun/v1/mcp/close` `{server}`: closes the server's connection; `204`.
24
24
  * Each answers `200 {ok: true, result}` or `200 {ok: false, error}`: an MCP failure is an
25
25
  * answer, not a gate error. A tool call's failure is coded (`error.failure`, R2b C7), and neither
26
- * a result nor a failure carries a credential value the gate sent (C8). An answer past 8 MiB is
27
- * `mcp.too-large` (C11), as an HTTP tool's is `http.too-large`; core shapes what fits into a
28
- * result the model can take (`tenant/tool-results.ts`). A keyed call whose earlier attempt was
26
+ * a result nor a failure carries a credential value the gate sent (C8). An answer past the
27
+ * Tenant's Runtime limit `toolAnswerBytes` (default 8 MiB), which also caps the bodies the gate
28
+ * reads, is `mcp.too-large` (C11), as an HTTP tool's is `http.too-large`; the harness shapes
29
+ * what fits into a result the model can take (`shapeToolOutcome`, protocol 15). The tool-calls
30
+ * body names the tool by its identity: the server (`{agentId?, serverName}`) and the server's
31
+ * own name for the tool (`name`). A keyed call whose earlier attempt was
29
32
  * lost with the gateway runs again under the same key (R5.3); one another gateway process holds
30
33
  * answers `{ok: false, error: {uncertain: true}}`, and the caller sends it again.
31
34
  *
32
35
  * HTTP tools (R2 M3). `POST /nylorun/v1/http-calls` `{tool, effectId, turnId, input}`: one call
33
- * of an HTTP tool. The loop names the tool (`{sessionId?, agentId?, toolName}`), or a
36
+ * of an HTTP tool. The loop names the tool (`{sessionId?, agentId?, toolName}`, its declared name), or a
34
37
  * flow's HTTP stage or HTTP verifier by its stage key (`{sessionId?, stage}`); the gate finds its
35
38
  * URL, method and credential in the session's pinned manifest
36
39
  * (`gates/http-tool.ts`). A run token's turn is the call's; `turnId` counts only under core's
@@ -39,7 +42,7 @@
39
42
  * model sees), or `{ok: false, error: {uncertain: true}}` for a call another gateway process holds.
40
43
  */
41
44
  import type { McpCallFailure } from "../mcp/connect.js";
42
- export { HTTP_CALLS_PATH, HttpCallBodySchema, MAX_TOOL_BODY_BYTES, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, McpListBodySchema, McpServerBodySchema, McpServerRefSchema, TOOL_CALLS_PATH, ToolCallBodySchema, type HttpCallBody, type ToolCallBody, } from "@nylorun/core/harness-api";
45
+ export { HTTP_CALLS_PATH, HttpCallBodySchema, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, McpListBodySchema, McpServerBodySchema, McpServerRefSchema, TOOL_CALLS_PATH, ToolCallBodySchema, type HttpCallBody, type ToolCallBody, } from "@nylorun/core/harness-api";
43
46
  /** Why an MCP request failed, as the loop's diagnostics read it (`mcp/connect.ts`). */
44
47
  export interface McpGateError {
45
48
  readonly message: string;
@@ -1 +1 @@
1
- export { HTTP_CALLS_PATH, HttpCallBodySchema, MAX_TOOL_BODY_BYTES, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, McpListBodySchema, McpServerBodySchema, McpServerRefSchema, TOOL_CALLS_PATH, ToolCallBodySchema, } from "@nylorun/core/harness-api";
1
+ export { HTTP_CALLS_PATH, HttpCallBodySchema, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, McpListBodySchema, McpServerBodySchema, McpServerRefSchema, TOOL_CALLS_PATH, ToolCallBodySchema, } from "@nylorun/core/harness-api";