@nylorun/runtime 0.26.0-beta → 0.27.0-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/README.md +18 -14
  3. package/dist/adapters/execution/restate.d.ts +15 -18
  4. package/dist/adapters/execution/restate.js +31 -27
  5. package/dist/adapters/replication/pgoutput.d.ts +1 -1
  6. package/dist/adapters/replication/pgoutput.js +3 -2
  7. package/dist/adapters/sandbox/local.js +8 -5
  8. package/dist/adapters/sandbox/virtual.js +2 -2
  9. package/dist/adapters/streams/s2.d.ts +1 -1
  10. package/dist/adapters/streams/s2.js +18 -14
  11. package/dist/api/a2a/card.js +1 -1
  12. package/dist/api/a2a/endpoint.js +3 -4
  13. package/dist/api/a2a/protocol.js +4 -0
  14. package/dist/api/a2a/routes.d.ts +2 -6
  15. package/dist/api/a2a/routes.js +12 -18
  16. package/dist/api/ag-ui/endpoint.js +2 -3
  17. package/dist/api/ag-ui/routes.js +4 -4
  18. package/dist/api/components.d.ts +326 -45
  19. package/dist/api/components.js +5 -1
  20. package/dist/api/gate/keys.js +7 -4
  21. package/dist/api/gate/routes.d.ts +6 -2
  22. package/dist/api/gate/routes.js +15 -11
  23. package/dist/api/http/body.d.ts +15 -3
  24. package/dist/api/http/body.js +15 -7
  25. package/dist/api/http/respond.js +6 -2
  26. package/dist/api/http/routes/access.js +5 -4
  27. package/dist/api/http/routes/artifacts.js +19 -7
  28. package/dist/api/http/routes/coverage.js +1 -1
  29. package/dist/api/http/routes/environment-manifests.js +1 -1
  30. package/dist/api/http/routes/environments.js +6 -6
  31. package/dist/api/http/routes/files.d.ts +2 -1
  32. package/dist/api/http/routes/files.js +31 -5
  33. package/dist/api/http/routes/mcp.js +1 -1
  34. package/dist/api/http/routes/reads.d.ts +35 -0
  35. package/dist/api/http/routes/reads.js +50 -22
  36. package/dist/api/http/routes/sessions.js +11 -10
  37. package/dist/api/http/routes/tenant.d.ts +2 -2
  38. package/dist/api/http/routes/tenant.js +69 -16
  39. package/dist/api/inbound-files.d.ts +3 -9
  40. package/dist/api/inbound-files.js +18 -24
  41. package/dist/api/openapi.js +6 -2
  42. package/dist/artifacts/disk.d.ts +0 -4
  43. package/dist/artifacts/disk.js +77 -73
  44. package/dist/artifacts/files.d.ts +13 -4
  45. package/dist/artifacts/files.js +27 -9
  46. package/dist/artifacts/folder-upload.d.ts +75 -0
  47. package/dist/artifacts/folder-upload.js +263 -0
  48. package/dist/artifacts/folders.d.ts +14 -8
  49. package/dist/artifacts/folders.js +19 -11
  50. package/dist/artifacts/links.js +7 -6
  51. package/dist/artifacts/parts.d.ts +9 -14
  52. package/dist/artifacts/parts.js +11 -9
  53. package/dist/artifacts/pipe.d.ts +15 -0
  54. package/dist/artifacts/pipe.js +71 -0
  55. package/dist/artifacts/quota.d.ts +36 -0
  56. package/dist/artifacts/quota.js +44 -0
  57. package/dist/artifacts/service.d.ts +25 -1
  58. package/dist/artifacts/service.js +70 -25
  59. package/dist/blob/fs.js +2 -1
  60. package/dist/blob/s3.d.ts +6 -2
  61. package/dist/blob/s3.js +9 -7
  62. package/dist/blob/types.d.ts +1 -1
  63. package/dist/blob/types.js +1 -1
  64. package/dist/core/limits.d.ts +11 -35
  65. package/dist/core/limits.js +5 -73
  66. package/dist/core/sandbox-routes.js +0 -1
  67. package/dist/core/turn-manifest.d.ts +1 -2
  68. package/dist/core/turn-manifest.js +4 -28
  69. package/dist/execution/memory.d.ts +8 -5
  70. package/dist/execution/memory.js +8 -6
  71. package/dist/execution/types.d.ts +1 -6
  72. package/dist/execution/types.js +0 -5
  73. package/dist/gates/contract.d.ts +3 -2
  74. package/dist/gates/contract.js +1 -1
  75. package/dist/gates/egress-credentials.js +4 -3
  76. package/dist/gates/egress.d.ts +9 -9
  77. package/dist/gates/egress.js +14 -16
  78. package/dist/gates/fixture-model.js +13 -2
  79. package/dist/gates/handler.d.ts +1 -3
  80. package/dist/gates/handler.js +4 -3
  81. package/dist/gates/http-client.d.ts +4 -3
  82. package/dist/gates/http-client.js +5 -7
  83. package/dist/gates/http-tool.d.ts +24 -4
  84. package/dist/gates/http-tool.js +40 -12
  85. package/dist/gates/in-process.d.ts +2 -1
  86. package/dist/gates/in-process.js +17 -9
  87. package/dist/gates/inflight.d.ts +2 -2
  88. package/dist/gates/inflight.js +3 -2
  89. package/dist/gates/journal.js +5 -7
  90. package/dist/gates/mcp-handler.d.ts +4 -3
  91. package/dist/gates/mcp-handler.js +15 -5
  92. package/dist/gates/model-gate.d.ts +11 -2
  93. package/dist/gates/policy.d.ts +28 -5
  94. package/dist/gates/policy.js +60 -17
  95. package/dist/gates/provider-gate.d.ts +22 -0
  96. package/dist/gates/provider-gate.js +30 -0
  97. package/dist/gates/tool-calls.d.ts +1 -3
  98. package/dist/gates/tool-calls.js +2 -3
  99. package/dist/gates/tool-client.d.ts +1 -1
  100. package/dist/gates/tool-client.js +5 -6
  101. package/dist/gates/tool-contract.d.ts +8 -5
  102. package/dist/gates/tool-contract.js +1 -1
  103. package/dist/gates/tool-gate.d.ts +18 -7
  104. package/dist/gates/tool-gate.js +49 -7
  105. package/dist/harness/calls.d.ts +27 -25
  106. package/dist/harness/calls.js +40 -46
  107. package/dist/harness/executors.d.ts +10 -3
  108. package/dist/harness/executors.js +53 -23
  109. package/dist/harness/main.js +2 -2
  110. package/dist/harness/pod.d.ts +0 -2
  111. package/dist/harness/pod.js +7 -6
  112. package/dist/harness/run-tokens.d.ts +4 -1
  113. package/dist/harness/run-tokens.js +6 -2
  114. package/dist/harness/service.d.ts +17 -14
  115. package/dist/harness/service.js +21 -35
  116. package/dist/harness/setup.d.ts +0 -2
  117. package/dist/harness/setup.js +4 -9
  118. package/dist/harness/ws-client.d.ts +2 -2
  119. package/dist/harness/ws-client.js +7 -5
  120. package/dist/harness/ws-port.d.ts +3 -4
  121. package/dist/harness/ws-port.js +3 -4
  122. package/dist/harness-api/artifacts.d.ts +20 -0
  123. package/dist/harness-api/artifacts.js +478 -0
  124. package/dist/harness-api/in-process.d.ts +2 -2
  125. package/dist/harness-api/in-process.js +18 -16
  126. package/dist/harness-api/record.d.ts +10 -9
  127. package/dist/harness-api/record.js +102 -157
  128. package/dist/harness-api/renew.d.ts +1 -1
  129. package/dist/harness-api/renew.js +2 -2
  130. package/dist/harness-api/server.d.ts +1 -16
  131. package/dist/harness-api/server.js +82 -73
  132. package/dist/harness-api/start.d.ts +20 -2
  133. package/dist/harness-api/start.js +57 -18
  134. package/dist/harness-api/tool-journal.d.ts +15 -10
  135. package/dist/harness-api/tool-journal.js +26 -24
  136. package/dist/harness-api/workspace.d.ts +0 -4
  137. package/dist/harness-api/workspace.js +2 -45
  138. package/dist/harness-api/ws-server.js +10 -10
  139. package/dist/host/create-host.js +2 -3
  140. package/dist/host/execution.js +2 -3
  141. package/dist/host/gates.d.ts +2 -9
  142. package/dist/host/gates.js +15 -12
  143. package/dist/host/http.d.ts +0 -2
  144. package/dist/host/http.js +0 -27
  145. package/dist/host/main.js +10 -3
  146. package/dist/host/operate.js +12 -3
  147. package/dist/host/stack-config.d.ts +11 -0
  148. package/dist/host/stack-config.js +21 -1
  149. package/dist/index.d.ts +0 -1
  150. package/dist/index.js +0 -1
  151. package/dist/infra/index.js +2 -1
  152. package/dist/infra/readiness.d.ts +0 -2
  153. package/dist/infra/readiness.js +4 -3
  154. package/dist/keys/client.d.ts +1 -0
  155. package/dist/keys/client.js +2 -3
  156. package/dist/keys/contract.d.ts +0 -2
  157. package/dist/keys/contract.js +0 -2
  158. package/dist/keys/egress-ca.d.ts +0 -2
  159. package/dist/keys/egress-ca.js +2 -3
  160. package/dist/keys/keys.js +6 -1
  161. package/dist/keys/x509.d.ts +8 -4
  162. package/dist/keys/x509.js +14 -5
  163. package/dist/management-openapi.json +1961 -994
  164. package/dist/mcp/connect.d.ts +35 -26
  165. package/dist/mcp/connect.js +112 -141
  166. package/dist/mcp/pool.d.ts +27 -22
  167. package/dist/mcp/pool.js +34 -48
  168. package/dist/mcp/preview.d.ts +12 -5
  169. package/dist/mcp/preview.js +36 -19
  170. package/dist/mcp/snapshot.d.ts +35 -86
  171. package/dist/mcp/snapshot.js +93 -135
  172. package/dist/model/auth-store.js +5 -3
  173. package/dist/model/capabilities.d.ts +1 -1
  174. package/dist/model/catalog.d.ts +9 -36
  175. package/dist/model/catalog.js +6 -33
  176. package/dist/model/descriptor.d.ts +51 -0
  177. package/dist/model/descriptor.js +83 -0
  178. package/dist/model/models.d.ts +0 -3
  179. package/dist/model/models.js +3 -5
  180. package/dist/model/native-blocks.js +1 -1
  181. package/dist/model/pi-model.d.ts +16 -5
  182. package/dist/model/pi-model.js +86 -105
  183. package/dist/openapi.json +838 -1218
  184. package/dist/reads/cursor.js +3 -1
  185. package/dist/record/append.d.ts +34 -2
  186. package/dist/record/append.js +50 -1
  187. package/dist/record/environment.d.ts +2 -0
  188. package/dist/record/environment.js +2 -0
  189. package/dist/record/index.d.ts +1 -1
  190. package/dist/record/index.js +1 -1
  191. package/dist/redact.d.ts +1 -1
  192. package/dist/redact.js +3 -2
  193. package/dist/sandbox/egress-token.d.ts +3 -3
  194. package/dist/sandbox/egress-token.js +3 -3
  195. package/dist/sandbox/join.js +3 -2
  196. package/dist/sandbox/manager.d.ts +41 -41
  197. package/dist/sandbox/manager.js +112 -44
  198. package/dist/sandbox/placement.d.ts +1 -1
  199. package/dist/sandbox/placement.js +5 -8
  200. package/dist/sandbox/pods/client.d.ts +1 -10
  201. package/dist/sandbox/pods/client.js +8 -4
  202. package/dist/sandbox/pods/lifecycle.d.ts +19 -11
  203. package/dist/sandbox/pods/lifecycle.js +45 -23
  204. package/dist/sandbox/pods/network-gate.d.ts +4 -5
  205. package/dist/sandbox/pods/network-gate.js +7 -7
  206. package/dist/sandbox/pods/reconcile.js +4 -1
  207. package/dist/sandbox/pods/spec.js +8 -5
  208. package/dist/sandbox/policy.d.ts +7 -1
  209. package/dist/sandbox/policy.js +10 -3
  210. package/dist/sandbox/resolve.d.ts +8 -3
  211. package/dist/sandbox/resolve.js +12 -2
  212. package/dist/sandbox/setup.d.ts +3 -1
  213. package/dist/sandbox/setup.js +34 -11
  214. package/dist/sandbox/share.d.ts +5 -14
  215. package/dist/sandbox/share.js +5 -34
  216. package/dist/sandbox/skills.d.ts +7 -13
  217. package/dist/sandbox/skills.js +16 -31
  218. package/dist/sandbox/tenant-config.d.ts +2 -2
  219. package/dist/sandbox/tenant-config.js +4 -3
  220. package/dist/sandbox/tools.d.ts +7 -1
  221. package/dist/sandbox/tools.js +26 -26
  222. package/dist/sandbox/types.d.ts +10 -3
  223. package/dist/sandbox/types.js +9 -0
  224. package/dist/store/postgres/connect.d.ts +6 -5
  225. package/dist/store/postgres/connect.js +14 -11
  226. package/dist/store/postgres/control.js +13 -13
  227. package/dist/store/postgres/drizzle/0028_artifact_write_keys.sql +2 -0
  228. package/dist/store/postgres/drizzle/0029_protocol_15.sql +11 -0
  229. package/dist/store/postgres/drizzle/0030_protocol_15_runtime_block.sql +11 -0
  230. package/dist/store/postgres/drizzle/0031_protocol_15_mcp_snapshot.sql +8 -0
  231. package/dist/store/postgres/drizzle/meta/_journal.json +28 -0
  232. package/dist/store/postgres/reads.js +10 -2
  233. package/dist/store/postgres/schema.d.ts +19 -0
  234. package/dist/store/postgres/schema.js +7 -0
  235. package/dist/store/postgres/store.js +55 -26
  236. package/dist/store/types.d.ts +17 -7
  237. package/dist/streams/relay/core.d.ts +3 -3
  238. package/dist/streams/relay/core.js +9 -10
  239. package/dist/tenant/advance.js +21 -31
  240. package/dist/tenant/commands.js +9 -16
  241. package/dist/tenant/context.d.ts +14 -17
  242. package/dist/tenant/definition-files.d.ts +25 -4
  243. package/dist/tenant/definition-files.js +85 -47
  244. package/dist/tenant/effects.js +9 -36
  245. package/dist/tenant/environment-manifests.js +9 -1
  246. package/dist/tenant/environments.d.ts +0 -2
  247. package/dist/tenant/environments.js +49 -28
  248. package/dist/tenant/ephemeral.js +2 -1
  249. package/dist/tenant/history.d.ts +1 -1
  250. package/dist/tenant/history.js +1 -1
  251. package/dist/tenant/host-token.d.ts +3 -3
  252. package/dist/tenant/host-token.js +11 -10
  253. package/dist/tenant/http.d.ts +5 -8
  254. package/dist/tenant/http.js +9 -0
  255. package/dist/tenant/identity-file.d.ts +23 -0
  256. package/dist/tenant/identity-file.js +34 -6
  257. package/dist/tenant/issuers.d.ts +5 -5
  258. package/dist/tenant/issuers.js +31 -23
  259. package/dist/tenant/jwt.d.ts +8 -2
  260. package/dist/tenant/jwt.js +10 -2
  261. package/dist/tenant/limits.d.ts +90 -0
  262. package/dist/tenant/limits.js +175 -0
  263. package/dist/tenant/module.d.ts +4 -1
  264. package/dist/tenant/module.js +9 -8
  265. package/dist/tenant/outbound.d.ts +11 -14
  266. package/dist/tenant/outbound.js +10 -15
  267. package/dist/tenant/run-grants.js +3 -2
  268. package/dist/tenant/run-token.d.ts +0 -4
  269. package/dist/tenant/run-token.js +6 -11
  270. package/dist/tenant/runtime-limits.d.ts +24 -0
  271. package/dist/tenant/runtime-limits.js +27 -0
  272. package/dist/tenant/runtime.js +30 -43
  273. package/dist/tenant/session-streams.js +7 -6
  274. package/dist/tenant/session.d.ts +1 -1
  275. package/dist/tenant/session.js +1 -1
  276. package/dist/tenant/sessions.js +32 -29
  277. package/dist/tenant/signing-keys.d.ts +1 -1
  278. package/dist/tenant/signing-keys.js +5 -6
  279. package/dist/tenant/status.js +4 -3
  280. package/dist/tenant/streams.js +18 -20
  281. package/dist/tenant/sweep.d.ts +1 -21
  282. package/dist/tenant/sweep.js +39 -48
  283. package/dist/tenant/transcript.d.ts +70 -23
  284. package/dist/tenant/transcript.js +28 -22
  285. package/dist/tenant/types.d.ts +9 -14
  286. package/dist/tenant/worker.d.ts +2 -10
  287. package/dist/tenant/worker.js +5 -14
  288. package/dist/traces/ids.js +5 -1
  289. package/dist/traces/map.d.ts +9 -6
  290. package/dist/traces/map.js +9 -11
  291. package/dist/traces/otlp.d.ts +3 -3
  292. package/dist/traces/otlp.js +5 -3
  293. package/dist/traces/projector.d.ts +9 -4
  294. package/dist/traces/projector.js +13 -7
  295. package/dist/traces/read.js +6 -1
  296. package/dist/tuning.d.ts +383 -0
  297. package/dist/tuning.js +658 -0
  298. package/dist/vault/headers.js +4 -2
  299. package/dist/version.d.ts +1 -1
  300. package/dist/version.js +1 -1
  301. package/package.json +3 -3
  302. package/dist/artifacts/export.d.ts +0 -8
  303. package/dist/artifacts/export.js +0 -204
  304. package/dist/artifacts/media-types.d.ts +0 -30
  305. package/dist/artifacts/media-types.js +0 -137
  306. package/dist/artifacts/workspace.d.ts +0 -60
  307. package/dist/artifacts/workspace.js +0 -45
  308. package/dist/media.d.ts +0 -10
  309. package/dist/media.js +0 -58
  310. package/dist/sandbox/runtime-tools.d.ts +0 -9
  311. package/dist/sandbox/runtime-tools.js +0 -16
  312. package/dist/sandbox/session-sandbox.d.ts +0 -16
  313. package/dist/sandbox/session-sandbox.js +0 -77
  314. package/dist/tenant/artifact-tool.d.ts +0 -13
  315. package/dist/tenant/artifact-tool.js +0 -243
  316. package/dist/tenant/skill-tool.d.ts +0 -20
  317. package/dist/tenant/skill-tool.js +0 -67
  318. package/dist/tenant/tool-results.d.ts +0 -57
  319. package/dist/tenant/tool-results.js +0 -298
  320. package/dist/tenant/tool-search.d.ts +0 -39
  321. package/dist/tenant/tool-search.js +0 -103
@@ -1,10 +1,7 @@
1
1
  import { openError, TenantOpenError } from "./cause.js";
2
2
  import { TimeoutError, withTimeout } from "./pool.js";
3
+ import { hostTuning } from "../tuning.js";
3
4
  import { TenantUnavailableError, } from "./types.js";
4
- const OPEN_TIMEOUT_MS = 30_000;
5
- /** Retries of an open that failed outside the Tenant: from 1 s, doubling, at most 30 s apart. */
6
- const RETRY_FIRST_MS = 1_000;
7
- const RETRY_MAX_MS = 30_000;
8
5
  /**
9
6
  * Deep Tenant module (§8): the Host's one Tenant over an injected opener (tenancy.md §5).
10
7
  *
@@ -15,11 +12,15 @@ const RETRY_MAX_MS = 30_000;
15
12
  * with backoff, and by the next request, which gets 503 meanwhile.
16
13
  */
17
14
  export function createTenantModule(options) {
18
- const { logger, openTimeoutMs = OPEN_TIMEOUT_MS } = options;
15
+ const tuning = hostTuning().tenant;
16
+ const { logger, openTimeoutMs = tuning.openTimeoutMs } = options;
17
+ // Retries of an open that failed outside the Tenant: from `openRetry.minMs`, doubling, at most
18
+ // `openRetry.maxMs` apart.
19
+ const { minMs: firstRetryMs, maxMs: maxRetryMs } = tuning.openRetry;
19
20
  let state = { kind: "idle" };
20
21
  let opening;
21
22
  let retry;
22
- let nextDelayMs = RETRY_FIRST_MS;
23
+ let nextDelayMs = firstRetryMs;
23
24
  const current = () => state;
24
25
  async function openOnce() {
25
26
  let handle;
@@ -64,7 +65,7 @@ export function createTenantModule(options) {
64
65
  return;
65
66
  }
66
67
  state = { kind: "open", handle };
67
- nextDelayMs = RETRY_FIRST_MS;
68
+ nextDelayMs = firstRetryMs;
68
69
  logger.info("tenant opened", { tenantId: handle.envelope.id });
69
70
  try {
70
71
  await options.onOpen?.(handle);
@@ -92,7 +93,7 @@ export function createTenantModule(options) {
92
93
  if (retry)
93
94
  return;
94
95
  const delayMs = nextDelayMs;
95
- nextDelayMs = Math.min(delayMs * 2, RETRY_MAX_MS);
96
+ nextDelayMs = Math.min(delayMs * 2, maxRetryMs);
96
97
  retry = setTimeout(() => {
97
98
  retry = undefined;
98
99
  void load();
@@ -30,8 +30,6 @@ export type OutboundResult = {
30
30
  code: string;
31
31
  message: string;
32
32
  };
33
- /** The largest answer read from an endpoint. */
34
- export declare const MAX_RESPONSE_BYTES: number;
35
33
  /** True when `address` is private, loopback, link-local or unspecified (IPv4-mapped included). */
36
34
  export declare function isPrivateAddress(address: string): boolean;
37
35
  /** Why the Host refuses `url`, or `undefined` when it may be called. */
@@ -44,7 +42,8 @@ export declare function refusal(url: URL, policy: OutboundPolicy): string | unde
44
42
  export declare function send(target: string, body: string | undefined, headers: Record<string, string>, options: {
45
43
  policy: OutboundPolicy;
46
44
  signal: AbortSignal;
47
- maxResponseBytes?: number;
45
+ /** The largest answer read: the Tenant's Runtime limit `toolAnswerBytes` for an HTTP tool. */
46
+ maxResponseBytes: number;
48
47
  method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
49
48
  }): Promise<OutboundResult>;
50
49
  /**
@@ -71,23 +70,21 @@ export declare class OutboundFailed extends Error {
71
70
  */
72
71
  sent?: boolean);
73
72
  }
74
- /** The largest answer `guardedFetch` reads. */
75
- export declare const MAX_FETCH_RESPONSE_BYTES: number;
76
- /** How long a `guardedFetch` request may take without a signal of its own. */
77
- export declare const FETCH_TIMEOUT_MS = 30000;
78
73
  /**
79
74
  * A `fetch` under the Host's address policy (F9 C2): the literal-IP and DNS checks of `post`
80
75
  * on the address actually connected to, `localhost` rewritten for the local stack, no
81
- * redirects (`redirect: "error"`; a 3xx answer rejects), a bounded answer and a 30 s timeout
82
- * unless the caller passes a signal. A refused URL or address rejects with `OutboundRefused`,
83
- * any other failure with `OutboundFailed`.
76
+ * redirects (`redirect: "error"`; a 3xx answer rejects), an answer of at most `maxResponseBytes`
77
+ * and a `timeoutMs` timeout unless the caller passes a signal, both the caller's (a Tenant's
78
+ * Runtime limits). A refused URL or address rejects with `OutboundRefused`, any other failure
79
+ * with `OutboundFailed`.
84
80
  *
85
81
  * `stream`: the Response resolves once the headers arrive and its body streams, unbounded and
86
82
  * with no timeout but the caller's signal: remote MCP servers, whose answers and event streams
87
83
  * stay open (`mcp/connect.ts`).
88
84
  */
89
- export declare function guardedFetch(policy: OutboundPolicy, options?: {
90
- maxResponseBytes?: number;
91
- timeoutMs?: number;
92
- stream?: boolean;
85
+ export declare function guardedFetch(policy: OutboundPolicy, options: {
86
+ maxResponseBytes: number;
87
+ timeoutMs: number;
88
+ } | {
89
+ stream: true;
93
90
  }): typeof fetch;
@@ -13,8 +13,6 @@ import { request as httpRequest } from "node:http";
13
13
  import { request as httpsRequest } from "node:https";
14
14
  import { BlockList, isIP } from "node:net";
15
15
  import { Readable } from "node:stream";
16
- /** The largest answer read from an endpoint. */
17
- export const MAX_RESPONSE_BYTES = 8 * 1024 * 1024;
18
16
  const PRIVATE = new BlockList();
19
17
  for (const [network, prefix] of [
20
18
  ["0.0.0.0", 8],
@@ -82,7 +80,7 @@ function guardedLookup(policy) {
82
80
  */
83
81
  export async function send(target, body, headers, options) {
84
82
  const { policy, signal } = options;
85
- const limit = options.maxResponseBytes ?? MAX_RESPONSE_BYTES;
83
+ const limit = options.maxResponseBytes;
86
84
  const url = new URL(target);
87
85
  const refused = refusal(url, policy);
88
86
  if (refused)
@@ -168,25 +166,22 @@ export class OutboundFailed extends Error {
168
166
  this.name = "OutboundFailed";
169
167
  }
170
168
  }
171
- /** The largest answer `guardedFetch` reads. */
172
- export const MAX_FETCH_RESPONSE_BYTES = 1024 * 1024;
173
- /** How long a `guardedFetch` request may take without a signal of its own. */
174
- export const FETCH_TIMEOUT_MS = 30_000;
175
169
  /**
176
170
  * A `fetch` under the Host's address policy (F9 C2): the literal-IP and DNS checks of `post`
177
171
  * on the address actually connected to, `localhost` rewritten for the local stack, no
178
- * redirects (`redirect: "error"`; a 3xx answer rejects), a bounded answer and a 30 s timeout
179
- * unless the caller passes a signal. A refused URL or address rejects with `OutboundRefused`,
180
- * any other failure with `OutboundFailed`.
172
+ * redirects (`redirect: "error"`; a 3xx answer rejects), an answer of at most `maxResponseBytes`
173
+ * and a `timeoutMs` timeout unless the caller passes a signal, both the caller's (a Tenant's
174
+ * Runtime limits). A refused URL or address rejects with `OutboundRefused`, any other failure
175
+ * with `OutboundFailed`.
181
176
  *
182
177
  * `stream`: the Response resolves once the headers arrive and its body streams, unbounded and
183
178
  * with no timeout but the caller's signal: remote MCP servers, whose answers and event streams
184
179
  * stay open (`mcp/connect.ts`).
185
180
  */
186
- export function guardedFetch(policy, options = {}) {
187
- const limit = options.maxResponseBytes ?? MAX_FETCH_RESPONSE_BYTES;
188
- const timeoutMs = options.timeoutMs ?? FETCH_TIMEOUT_MS;
189
- const stream = options.stream === true;
181
+ export function guardedFetch(policy, options) {
182
+ const stream = "stream" in options;
183
+ const limit = "stream" in options ? Infinity : options.maxResponseBytes;
184
+ const timeoutMs = "stream" in options ? undefined : options.timeoutMs;
190
185
  const lookup = guardedLookup(policy);
191
186
  const guarded = async (input, init = {}) => {
192
187
  const request = input instanceof Request ? input : undefined;
@@ -217,7 +212,7 @@ export function guardedFetch(policy, options = {}) {
217
212
  }
218
213
  const originalHost = url.host;
219
214
  dockerHost(url, policy);
220
- const signal = init.signal ?? request?.signal ?? (stream ? undefined : AbortSignal.timeout(timeoutMs));
215
+ const signal = init.signal ?? request?.signal ?? (timeoutMs === undefined ? undefined : AbortSignal.timeout(timeoutMs));
221
216
  const outgoing = { host: originalHost };
222
217
  for (const [name, value] of headers)
223
218
  outgoing[name] = value;
@@ -1,4 +1,5 @@
1
- import { mintRunToken, RUN_TOKEN_RENEW_SECONDS } from "./run-token.js";
1
+ import { mintRunToken } from "./run-token.js";
2
+ import { hostTuning } from "../tuning.js";
2
3
  export function createRunGrants() {
3
4
  const grants = new Map();
4
5
  return {
@@ -50,7 +51,7 @@ export async function renewRunGrant(ctx, lease, run, active = () => true) {
50
51
  const held = ctx.runGrants.get(lease.sessionId);
51
52
  if (held && held.claims.epoch !== lease.epoch)
52
53
  return;
53
- if (held && held.claims.expiresAt - Date.now() > RUN_TOKEN_RENEW_SECONDS * 1000)
54
+ if (held && held.claims.expiresAt - Date.now() > hostTuning().keys.runTokenRenewSeconds * 1000)
54
55
  return;
55
56
  const grant = await mintRunToken(ctx, lease, held ? { agentId: held.claims.agentId, activeTurnId: held.claims.turnId } : run);
56
57
  if (active())
@@ -4,10 +4,6 @@ import type { SessionStore } from "../store/types.js";
4
4
  import type { Lease } from "./context.js";
5
5
  export declare const RUN_TOKEN_TYP = "nylorun-run+jwt";
6
6
  export declare const RUN_TOKEN_AUD = "nylorun-gates";
7
- /** How long a run token lives. */
8
- export declare const RUN_TOKEN_TTL_SECONDS: number;
9
- /** The lease heartbeat re-mints a token with less than this left. */
10
- export declare const RUN_TOKEN_RENEW_SECONDS: number;
11
7
  /** What a verified run token says: one lease of one session's turn. */
12
8
  export interface RunClaims {
13
9
  readonly tenantId: string;
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Signed by the keys service with the Tenant's current signing key, like capability links,
8
8
  * and told apart from them by `typ` and `aud`. Internal: not in `openapi.json`. A token lives
9
- * `RUN_TOKEN_TTL_SECONDS`, no longer than `TOKEN_TTL_MAX_SECONDS`, so a key rotation never
9
+ * `keys.runTokenTtlSeconds` (Host tuning), no longer than `keys.tokenTtlMaxSeconds`, so a key rotation never
10
10
  * revokes a live one (`signing-keys.ts`).
11
11
  *
12
12
  * ```text
@@ -18,15 +18,10 @@
18
18
  import { randomUUID } from "node:crypto";
19
19
  import { errors, importJWK, jwtVerify } from "jose";
20
20
  import { tenantTokenIssuer } from "@nylorun/core/contracts";
21
- import { CLOCK_TOLERANCE_SECONDS, tokenKeyId } from "./jwt.js";
21
+ import { clockToleranceSeconds, tokenKeyId } from "./jwt.js";
22
+ import { hostTuning } from "../tuning.js";
22
23
  export const RUN_TOKEN_TYP = "nylorun-run+jwt";
23
24
  export const RUN_TOKEN_AUD = "nylorun-gates";
24
- /** How long a run token lives. */
25
- export const RUN_TOKEN_TTL_SECONDS = 15 * 60;
26
- /** The lease heartbeat re-mints a token with less than this left. */
27
- export const RUN_TOKEN_RENEW_SECONDS = 5 * 60;
28
- /** Allowed spread between `iat` and `exp` beyond the lifetime. */
29
- const LIFETIME_SLACK_SECONDS = 60;
30
25
  /**
31
26
  * Mints the run token of `lease` over `session`'s active turn. Throws when the session has
32
27
  * no active turn: there is no run to name.
@@ -37,7 +32,7 @@ export async function mintRunToken(signer, lease, session) {
37
32
  throw new Error(`Session ${lease.sessionId} has no active turn to mint a run token for`);
38
33
  const tenantId = signer.config.tenantId;
39
34
  const iat = Math.floor(Date.now() / 1000);
40
- const exp = iat + RUN_TOKEN_TTL_SECONDS;
35
+ const exp = iat + hostTuning().keys.runTokenTtlSeconds;
41
36
  // Signed by the keys service (F4.2): this process never holds the private key.
42
37
  const { token } = await signer.keys.sign({
43
38
  typ: RUN_TOKEN_TYP,
@@ -92,7 +87,7 @@ export async function verifyRunToken(store, tenantId, raw, cache = new Map()) {
92
87
  issuer: tenantTokenIssuer(tenantId),
93
88
  audience: RUN_TOKEN_AUD,
94
89
  typ: RUN_TOKEN_TYP,
95
- clockTolerance: CLOCK_TOLERANCE_SECONDS,
90
+ clockTolerance: clockToleranceSeconds(),
96
91
  requiredClaims: ["sub", "iat", "exp", "jti"],
97
92
  });
98
93
  payload = verified.payload;
@@ -112,7 +107,7 @@ export async function verifyRunToken(store, tenantId, raw, cache = new Map()) {
112
107
  typeof epc !== "number" ||
113
108
  !Number.isSafeInteger(epc) ||
114
109
  epc < 1 ||
115
- exp - iat > RUN_TOKEN_TTL_SECONDS + LIFETIME_SLACK_SECONDS)
110
+ exp - iat > hostTuning().keys.runTokenTtlSeconds + hostTuning().keys.tokenLifetimeSlackSeconds)
116
111
  return refused("claims");
117
112
  return {
118
113
  ok: true,
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The Tenant's Runtime limits (harness boundary S0), stored as Tenant setting `limits.config`
3
+ * (`GET`/`PUT /v1/tenant/limits`): what one record entry, model call, model file, tool answer,
4
+ * custom harness state and Harness API chunk may hold. Unset limits take their defaults
5
+ * (`RUNTIME_LIMIT_DEFAULTS`); none may pass its ceiling (`runtimeLimitIssues`), which the route
6
+ * checks before it writes.
7
+ *
8
+ * Read from Postgres where a limit is checked, never kept: the Record seam, the store's event
9
+ * write, the gates and the segment's `turn.start` each read it in their own transaction.
10
+ */
11
+ import { type RuntimeLimits, type TenantLimitsConfig } from "@nylorun/core/contracts";
12
+ export declare const LIMITS_CONFIG_SETTING = "limits.config";
13
+ interface SettingsReader {
14
+ getSetting(key: string): Promise<string | undefined>;
15
+ }
16
+ interface SettingsWriter extends SettingsReader {
17
+ putSetting(key: string, value: string): Promise<void>;
18
+ }
19
+ /** The Tenant's stored limits; a stored value that does not parse counts as none set. */
20
+ export declare function readLimitsConfig(t: SettingsReader): Promise<TenantLimitsConfig>;
21
+ /** The Runtime limits in force: the Tenant's, with the default for each it leaves out. */
22
+ export declare function readRuntimeLimits(t: SettingsReader): Promise<RuntimeLimits>;
23
+ export declare function writeLimitsConfig(t: SettingsWriter, config: TenantLimitsConfig): Promise<void>;
24
+ export {};
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The Tenant's Runtime limits (harness boundary S0), stored as Tenant setting `limits.config`
3
+ * (`GET`/`PUT /v1/tenant/limits`): what one record entry, model call, model file, tool answer,
4
+ * custom harness state and Harness API chunk may hold. Unset limits take their defaults
5
+ * (`RUNTIME_LIMIT_DEFAULTS`); none may pass its ceiling (`runtimeLimitIssues`), which the route
6
+ * checks before it writes.
7
+ *
8
+ * Read from Postgres where a limit is checked, never kept: the Record seam, the store's event
9
+ * write, the gates and the segment's `turn.start` each read it in their own transaction.
10
+ */
11
+ import { TenantLimitsConfigSchema, runtimeLimitsOf, } from "@nylorun/core/contracts";
12
+ export const LIMITS_CONFIG_SETTING = "limits.config";
13
+ /** The Tenant's stored limits; a stored value that does not parse counts as none set. */
14
+ export async function readLimitsConfig(t) {
15
+ const raw = await t.getSetting(LIMITS_CONFIG_SETTING);
16
+ if (raw === undefined)
17
+ return {};
18
+ const parsed = TenantLimitsConfigSchema.safeParse(JSON.parse(raw));
19
+ return parsed.success ? parsed.data : {};
20
+ }
21
+ /** The Runtime limits in force: the Tenant's, with the default for each it leaves out. */
22
+ export async function readRuntimeLimits(t) {
23
+ return runtimeLimitsOf((await readLimitsConfig(t)).limits);
24
+ }
25
+ export async function writeLimitsConfig(t, config) {
26
+ await t.putSetting(LIMITS_CONFIG_SETTING, JSON.stringify(TenantLimitsConfigSchema.parse(config)));
27
+ }
@@ -1,9 +1,9 @@
1
1
  import { mkdirSync } from "node:fs";
2
- import { resolveFlowLimits } from "../core/limits.js";
3
2
  import { scriptedModel, toolFixtureModel, } from "../core/provider.js";
4
3
  import { tenantModelGate } from "../gates/in-process.js";
5
4
  import { createKekFile, readVaultKek } from "../vault/kek.js";
6
5
  import { SigningKeys } from "./signing-keys.js";
6
+ import { readRuntimeLimits } from "./runtime-limits.js";
7
7
  import { VaultService } from "../vault/service.js";
8
8
  import { McpPool } from "../mcp/pool.js";
9
9
  import { SandboxManager } from "../sandbox/manager.js";
@@ -20,7 +20,8 @@ import { advance } from "./advance.js";
20
20
  import { sweep } from "./sweep.js";
21
21
  import { TenantWorkers, WORKER_ID, } from "./worker.js";
22
22
  import { authorize } from "./effects.js";
23
- import { inProcessToolGate } from "../gates/tool-gate.js";
23
+ import { inProcessToolGate, openMcpThrough } from "../gates/tool-gate.js";
24
+ import { providerModelGate } from "../gates/provider-gate.js";
24
25
  import { inProcessKeys } from "../keys/keys.js";
25
26
  import { tenantApi } from "../api/http/app.js";
26
27
  import { createFsBlobStore } from "../blob/index.js";
@@ -31,24 +32,16 @@ import { localWorkspace, remoteWorkspace, withPodWorkspaces, } from "../harness-
31
32
  import { hostAuthority } from "../sandbox/join.js";
32
33
  import { harnessOfToken } from "./harness-tokens.js";
33
34
  import { reconcileSandbox } from "../sandbox/pods/reconcile.js";
34
- import { sandboxWorkspaceReader } from "../artifacts/workspace.js";
35
- import { readDefinitionFile } from "./definition-files.js";
36
- /** Default ownership lease of an advance; the heartbeat renews it every third. */
37
- const DEFAULT_OWNER_LEASE_MS = 30_000;
35
+ import { hostTuning } from "../tuning.js";
38
36
  function validateConfig(config) {
39
37
  for (const key of ["leaseMs", "ownerLeaseMs", "sweepIntervalMs"]) {
40
38
  const value = config[key];
41
39
  if (value !== undefined && (!Number.isFinite(value) || value <= 0))
42
40
  throw new Error(`${key} must be finite and positive`);
43
41
  }
44
- const flowLimits = resolveFlowLimits({
45
- flow: config.flow,
46
- env: config.flowEnv,
47
- });
48
42
  if ((config.model.kind === "fixture" || config.model.kind === "scripted") &&
49
43
  config.mode === "shared")
50
44
  throw new Error("fixture/scripted models require ephemeral or test mode");
51
- return flowLimits;
52
45
  }
53
46
  export class TenantRuntime {
54
47
  ctx;
@@ -81,7 +74,7 @@ export class TenantRuntime {
81
74
  }
82
75
  static async open(config, hooks) {
83
76
  const envelope = hooks.envelope;
84
- const flowLimits = validateConfig(config);
77
+ validateConfig(config);
85
78
  const paths = config.paths;
86
79
  mkdirSync(paths.root, { recursive: true });
87
80
  mkdirSync(paths.home, { recursive: true });
@@ -128,6 +121,7 @@ export class TenantRuntime {
128
121
  inProcessToolGate(config.delivery ?? {}, {
129
122
  session: (sessionId) => opened.tx((t) => t.get("sessions", sessionId)),
130
123
  authorize: (sessionId, request) => authorize(ctx, sessionId, request),
124
+ limits: () => opened.tx((t) => readRuntimeLimits(t)),
131
125
  logger: config.logger,
132
126
  });
133
127
  const signingKeys = new SigningKeys({ tenantId: config.tenantId, kek: ensureKek });
@@ -144,13 +138,9 @@ export class TenantRuntime {
144
138
  const preference = seededBackend ?? config.sandbox.backend;
145
139
  // With a harness in this process, the Tenant's MCP pool and SandboxManager are its
146
140
  // executors; otherwise the harness holds both (F6.2).
147
- const mcp = inProcess
148
- ? new McpPool({
149
- authorize: (sessionId, request) => authorize(ctx, sessionId, request),
150
- policy: config.delivery ?? {},
151
- ...(toolGate.openMcp ? { openRemote: (server) => toolGate.openMcp(server) } : {}),
152
- })
153
- : undefined;
141
+ // The pool opens every server through the Tool Gate: core never authorizes an MCP
142
+ // connection outside a gate (protocol 15).
143
+ const mcp = inProcess ? new McpPool({ openRemote: openMcpThrough(toolGate) }) : undefined;
154
144
  const ephemeral = config.mode === "ephemeral";
155
145
  const manager = inProcess
156
146
  ? new SandboxManager({
@@ -160,12 +150,6 @@ export class TenantRuntime {
160
150
  defaultSandboxBackends({ root: paths.sandboxes }),
161
151
  preference,
162
152
  ephemeral,
163
- definitionFile: async (sha256) => {
164
- const bytes = await readDefinitionFile(blobs, sha256);
165
- if (!bytes)
166
- throw new Error(`The Object store has no bytes for ${sha256}`);
167
- return bytes;
168
- },
169
153
  emit: async (sessionId, turnId, type, payload) => {
170
154
  if (ctx.closed)
171
155
  return;
@@ -201,9 +185,13 @@ export class TenantRuntime {
201
185
  isPod: async (sandboxId) => (await opened.tx((t) => t.environment(sandboxId)))?.kind === "pod",
202
186
  })
203
187
  : workspaces;
204
- const useVaultModel = config.model.kind === "vault";
188
+ // A model that is not the vault's (scripted, the fixture, an embedder's provider) is
189
+ // served by a gate over it, metered like any (protocol 15): no harness calls a provider.
190
+ const scripted = config.model.kind !== "vault";
205
191
  let modelProvider;
206
- if (hooks.modelProvider)
192
+ if (!scripted)
193
+ modelProvider = undefined;
194
+ else if (hooks.modelProvider)
207
195
  modelProvider = hooks.modelProvider;
208
196
  else if (config.model.kind === "scripted")
209
197
  modelProvider = scriptedModel(config.model.output);
@@ -214,21 +202,23 @@ export class TenantRuntime {
214
202
  const blobs = hooks.blobs ?? createFsBlobStore({ root: paths.blobs });
215
203
  // With the gates service the loop never reads a model credential: only a Runtime
216
204
  // without one (embedding, the ephemeral Runtime, tests) reads it here.
217
- const modelGate = hooks.modelGate ??
218
- tenantModelGate({
219
- store: opened,
220
- kek: ensureKek,
221
- root: paths.home,
222
- logger: config.logger,
223
- blobs,
224
- ...(config.modelCall ? { settings: config.modelCall } : {}),
225
- });
205
+ const modelGate = modelProvider
206
+ ? providerModelGate(modelProvider, { store: opened, logger: config.logger })
207
+ : (hooks.modelGate ??
208
+ tenantModelGate({
209
+ store: opened,
210
+ kek: ensureKek,
211
+ root: paths.home,
212
+ logger: config.logger,
213
+ blobs,
214
+ }));
226
215
  const sessionStreams = createSessionStreams();
227
216
  const workers = hooks.execution?.workers ?? new TenantWorkers();
228
217
  const local = hooks.execution
229
218
  ? undefined
230
219
  : new MemoryExecution({
231
- sweepIntervalMs: config.sweepIntervalMs ?? Math.min(config.leaseMs ?? 30_000, 5000),
220
+ sweepIntervalMs: config.sweepIntervalMs ??
221
+ Math.min(config.leaseMs ?? Infinity, hostTuning().sweep.intervalMs),
232
222
  // Close's `detach` step waits no longer for running work than for its advances.
233
223
  stopGraceMs: workers.graceMs,
234
224
  onError: (error) => config.logger.error("tenant execution failed", {
@@ -245,9 +235,7 @@ export class TenantRuntime {
245
235
  vault,
246
236
  ...(mcp ? { mcp } : {}),
247
237
  sandbox,
248
- flowLimits,
249
- modelProvider,
250
- useVaultModel,
238
+ scriptedModel: scripted,
251
239
  modelGate,
252
240
  toolGate,
253
241
  get harness() {
@@ -260,11 +248,10 @@ export class TenantRuntime {
260
248
  signingKeys,
261
249
  keys,
262
250
  blobs,
263
- workspaces: sandboxWorkspaceReader(sandbox),
264
251
  ...(hooks.traces ? { traces: hooks.traces } : {}),
265
252
  ...(hooks.runGrants ? { runGrants: hooks.runGrants } : {}),
266
253
  workerId: hooks.workerId ?? WORKER_ID,
267
- ownerLeaseMs: config.ownerLeaseMs ?? DEFAULT_OWNER_LEASE_MS,
254
+ ownerLeaseMs: config.ownerLeaseMs ?? hostTuning().tenant.ownerLeaseMs,
268
255
  wake: async (sessionId, wake) => {
269
256
  if (ctx.closing || ctx.closed)
270
257
  return false;
@@ -372,7 +359,7 @@ export class TenantRuntime {
372
359
  harness: harnessStatusOf(this.ctx),
373
360
  };
374
361
  }
375
- drain(activeWork, timeoutMs = 30_000) {
362
+ drain(activeWork, timeoutMs = hostTuning().tenant.drainTimeoutMs) {
376
363
  return drain(this.ctx, activeWork, timeoutMs);
377
364
  }
378
365
  /**
@@ -21,6 +21,7 @@
21
21
  import { historyCursor, historyResume } from "../reads/cursor.js";
22
22
  import { decodeCursor, encodeCursor } from "../record/index.js";
23
23
  import { sleep } from "../retry.js";
24
+ import { hostTuning } from "../tuning.js";
24
25
  import { basinOf } from "../streams/basin.js";
25
26
  import { sessionStream, } from "../streams/types.js";
26
27
  import { fail } from "./http.js";
@@ -33,8 +34,6 @@ export function streamHolderOf(scope) {
33
34
  export function createSessionStreams() {
34
35
  return { wiring: undefined, generation: 0, sessions: new Map() };
35
36
  }
36
- const RETRY_MIN_MS = 100;
37
- const RETRY_MAX_MS = 2000;
38
37
  function frame(event) {
39
38
  return `id: ${event.cursor}\nevent: ${event.type}\ndata: ${JSON.stringify(event)}\n\n`;
40
39
  }
@@ -66,7 +65,7 @@ export function openSse(request, response, onClose) {
66
65
  "x-accel-buffering": "no",
67
66
  });
68
67
  response.flushHeaders();
69
- const timer = setInterval(() => send(response, ": keepalive\n\n"), 15000);
68
+ const timer = setInterval(() => send(response, ": keepalive\n\n"), hostTuning().api.eventStreamKeepaliveMs);
70
69
  timer.unref();
71
70
  request.on("close", () => {
72
71
  clearInterval(timer);
@@ -313,7 +312,9 @@ function runFeed(ctx, feed) {
313
312
  const read = feed.read;
314
313
  const signal = read.signal;
315
314
  void (async () => {
316
- let delay = RETRY_MIN_MS;
315
+ // A failed read is retried after `streams.retry` (Host tuning), doubling.
316
+ const { minMs: retryMinMs, maxMs: retryMaxMs } = hostTuning().streams.retry;
317
+ let delay = retryMinMs;
317
318
  while (!signal.aborted) {
318
319
  const streams = ctx.sessionStreams.wiring?.streams;
319
320
  if (!streams)
@@ -326,7 +327,7 @@ function runFeed(ctx, feed) {
326
327
  if (record.seq < feed.next)
327
328
  continue;
328
329
  feed.next = record.seq + 1;
329
- delay = RETRY_MIN_MS;
330
+ delay = retryMinMs;
330
331
  for (const observer of feed.observers)
331
332
  deliver(observer, record);
332
333
  }
@@ -345,7 +346,7 @@ function runFeed(ctx, feed) {
345
346
  if (!(await stillCurrent(ctx, feed)))
346
347
  break;
347
348
  await sleep(delay, signal);
348
- delay = Math.min(delay * 2, RETRY_MAX_MS);
349
+ delay = Math.min(delay * 2, retryMaxMs);
349
350
  }
350
351
  if (signal.aborted || feed.read !== read)
351
352
  return;
@@ -9,7 +9,7 @@
9
9
  import type { AgentManifest } from "@nylorun/core/define";
10
10
  import type { TurnManifestStore } from "../core/turn-manifest.js";
11
11
  import type { Session } from "./context.js";
12
- export { manifestFor, sessionToolsOf } from "../mcp/snapshot.js";
12
+ export { manifestFor } from "../mcp/snapshot.js";
13
13
  /** Turn-manifest store backed by the session's `variants` map (no schema change). */
14
14
  export declare function variantStore(session: Session): TurnManifestStore;
15
15
  /** Manifest this turn's checkpoint is pinned to (session pin or a stored variant). */
@@ -1,4 +1,4 @@
1
- export { manifestFor, sessionToolsOf } from "../mcp/snapshot.js";
1
+ export { manifestFor } from "../mcp/snapshot.js";
2
2
  /** Turn-manifest store backed by the session's `variants` map (no schema change). */
3
3
  export function variantStore(session) {
4
4
  return {