@nylorun/runtime 0.25.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 (326) hide show
  1. package/CHANGELOG.md +169 -0
  2. package/README.md +26 -16
  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/app.d.ts +2 -2
  24. package/dist/api/http/app.js +2 -2
  25. package/dist/api/http/body.d.ts +15 -3
  26. package/dist/api/http/body.js +15 -7
  27. package/dist/api/http/define.d.ts +1 -1
  28. package/dist/api/http/respond.js +7 -3
  29. package/dist/api/http/routes/access.js +5 -4
  30. package/dist/api/http/routes/artifacts.js +19 -7
  31. package/dist/api/http/routes/coverage.js +1 -1
  32. package/dist/api/http/routes/environment-manifests.js +1 -1
  33. package/dist/api/http/routes/environments.js +6 -6
  34. package/dist/api/http/routes/files.d.ts +2 -1
  35. package/dist/api/http/routes/files.js +31 -5
  36. package/dist/api/http/routes/mcp.js +1 -1
  37. package/dist/api/http/routes/reads.d.ts +35 -0
  38. package/dist/api/http/routes/reads.js +50 -22
  39. package/dist/api/http/routes/sessions.js +12 -11
  40. package/dist/api/http/routes/tenant.d.ts +2 -2
  41. package/dist/api/http/routes/tenant.js +69 -16
  42. package/dist/api/inbound-files.d.ts +3 -9
  43. package/dist/api/inbound-files.js +18 -24
  44. package/dist/api/openapi.js +6 -2
  45. package/dist/artifacts/disk.d.ts +0 -4
  46. package/dist/artifacts/disk.js +77 -73
  47. package/dist/artifacts/files.d.ts +13 -4
  48. package/dist/artifacts/files.js +27 -9
  49. package/dist/artifacts/folder-upload.d.ts +75 -0
  50. package/dist/artifacts/folder-upload.js +263 -0
  51. package/dist/artifacts/folders.d.ts +14 -8
  52. package/dist/artifacts/folders.js +19 -11
  53. package/dist/artifacts/links.js +7 -6
  54. package/dist/artifacts/parts.d.ts +9 -14
  55. package/dist/artifacts/parts.js +11 -9
  56. package/dist/artifacts/pipe.d.ts +15 -0
  57. package/dist/artifacts/pipe.js +71 -0
  58. package/dist/artifacts/quota.d.ts +36 -0
  59. package/dist/artifacts/quota.js +44 -0
  60. package/dist/artifacts/service.d.ts +25 -1
  61. package/dist/artifacts/service.js +70 -25
  62. package/dist/blob/fs.js +2 -1
  63. package/dist/blob/s3.d.ts +6 -2
  64. package/dist/blob/s3.js +9 -7
  65. package/dist/blob/types.d.ts +1 -1
  66. package/dist/blob/types.js +1 -1
  67. package/dist/core/limits.d.ts +11 -35
  68. package/dist/core/limits.js +5 -73
  69. package/dist/core/sandbox-routes.js +0 -1
  70. package/dist/core/turn-manifest.d.ts +1 -2
  71. package/dist/core/turn-manifest.js +4 -28
  72. package/dist/execution/memory.d.ts +8 -5
  73. package/dist/execution/memory.js +8 -6
  74. package/dist/execution/types.d.ts +1 -6
  75. package/dist/execution/types.js +0 -5
  76. package/dist/gates/contract.d.ts +3 -2
  77. package/dist/gates/contract.js +1 -1
  78. package/dist/gates/egress-credentials.js +4 -3
  79. package/dist/gates/egress.d.ts +9 -9
  80. package/dist/gates/egress.js +19 -19
  81. package/dist/gates/fixture-model.js +13 -2
  82. package/dist/gates/handler.d.ts +1 -3
  83. package/dist/gates/handler.js +4 -3
  84. package/dist/gates/http-client.d.ts +4 -3
  85. package/dist/gates/http-client.js +5 -7
  86. package/dist/gates/http-tool.d.ts +24 -4
  87. package/dist/gates/http-tool.js +53 -17
  88. package/dist/gates/in-process.d.ts +2 -1
  89. package/dist/gates/in-process.js +17 -9
  90. package/dist/gates/inflight.d.ts +2 -2
  91. package/dist/gates/inflight.js +3 -2
  92. package/dist/gates/journal.js +5 -7
  93. package/dist/gates/mcp-handler.d.ts +4 -3
  94. package/dist/gates/mcp-handler.js +15 -5
  95. package/dist/gates/model-gate.d.ts +11 -2
  96. package/dist/gates/policy.d.ts +28 -5
  97. package/dist/gates/policy.js +60 -17
  98. package/dist/gates/provider-gate.d.ts +22 -0
  99. package/dist/gates/provider-gate.js +30 -0
  100. package/dist/gates/tool-calls.d.ts +1 -3
  101. package/dist/gates/tool-calls.js +2 -3
  102. package/dist/gates/tool-client.d.ts +1 -1
  103. package/dist/gates/tool-client.js +5 -6
  104. package/dist/gates/tool-contract.d.ts +8 -5
  105. package/dist/gates/tool-contract.js +1 -1
  106. package/dist/gates/tool-gate.d.ts +18 -7
  107. package/dist/gates/tool-gate.js +49 -7
  108. package/dist/harness/calls.d.ts +27 -25
  109. package/dist/harness/calls.js +40 -46
  110. package/dist/harness/executors.d.ts +10 -3
  111. package/dist/harness/executors.js +53 -23
  112. package/dist/harness/main.js +2 -2
  113. package/dist/harness/pod.d.ts +0 -2
  114. package/dist/harness/pod.js +7 -6
  115. package/dist/harness/run-tokens.d.ts +4 -1
  116. package/dist/harness/run-tokens.js +6 -2
  117. package/dist/harness/service.d.ts +17 -14
  118. package/dist/harness/service.js +21 -35
  119. package/dist/harness/setup.d.ts +0 -2
  120. package/dist/harness/setup.js +4 -9
  121. package/dist/harness/ws-client.d.ts +2 -2
  122. package/dist/harness/ws-client.js +7 -5
  123. package/dist/harness/ws-port.d.ts +3 -4
  124. package/dist/harness/ws-port.js +3 -4
  125. package/dist/harness-api/artifacts.d.ts +20 -0
  126. package/dist/harness-api/artifacts.js +478 -0
  127. package/dist/harness-api/in-process.d.ts +2 -2
  128. package/dist/harness-api/in-process.js +18 -16
  129. package/dist/harness-api/record.d.ts +10 -9
  130. package/dist/harness-api/record.js +102 -157
  131. package/dist/harness-api/renew.d.ts +1 -1
  132. package/dist/harness-api/renew.js +2 -2
  133. package/dist/harness-api/server.d.ts +1 -16
  134. package/dist/harness-api/server.js +82 -73
  135. package/dist/harness-api/start.d.ts +20 -2
  136. package/dist/harness-api/start.js +57 -18
  137. package/dist/harness-api/tool-journal.d.ts +15 -10
  138. package/dist/harness-api/tool-journal.js +26 -24
  139. package/dist/harness-api/workspace.d.ts +0 -4
  140. package/dist/harness-api/workspace.js +2 -45
  141. package/dist/harness-api/ws-server.js +10 -10
  142. package/dist/host/create-host.js +2 -3
  143. package/dist/host/execution.js +2 -3
  144. package/dist/host/gates.d.ts +2 -9
  145. package/dist/host/gates.js +15 -12
  146. package/dist/host/http.d.ts +0 -2
  147. package/dist/host/http.js +0 -27
  148. package/dist/host/main.js +10 -3
  149. package/dist/host/operate.js +12 -3
  150. package/dist/host/stack-config.d.ts +11 -0
  151. package/dist/host/stack-config.js +21 -1
  152. package/dist/index.d.ts +0 -1
  153. package/dist/index.js +0 -1
  154. package/dist/infra/index.js +2 -1
  155. package/dist/infra/readiness.d.ts +0 -2
  156. package/dist/infra/readiness.js +4 -3
  157. package/dist/keys/client.d.ts +1 -0
  158. package/dist/keys/client.js +2 -3
  159. package/dist/keys/contract.d.ts +1 -3
  160. package/dist/keys/contract.js +1 -3
  161. package/dist/keys/egress-ca.d.ts +0 -2
  162. package/dist/keys/egress-ca.js +2 -3
  163. package/dist/keys/keys.js +6 -1
  164. package/dist/keys/x509.d.ts +8 -4
  165. package/dist/keys/x509.js +14 -5
  166. package/dist/management-openapi.json +1961 -994
  167. package/dist/mcp/connect.d.ts +35 -26
  168. package/dist/mcp/connect.js +112 -141
  169. package/dist/mcp/pool.d.ts +27 -22
  170. package/dist/mcp/pool.js +34 -48
  171. package/dist/mcp/preview.d.ts +13 -6
  172. package/dist/mcp/preview.js +37 -20
  173. package/dist/mcp/snapshot.d.ts +35 -86
  174. package/dist/mcp/snapshot.js +93 -135
  175. package/dist/model/auth-store.js +5 -3
  176. package/dist/model/capabilities.d.ts +1 -1
  177. package/dist/model/catalog.d.ts +9 -36
  178. package/dist/model/catalog.js +6 -33
  179. package/dist/model/descriptor.d.ts +51 -0
  180. package/dist/model/descriptor.js +83 -0
  181. package/dist/model/models.d.ts +0 -3
  182. package/dist/model/models.js +3 -5
  183. package/dist/model/native-blocks.js +1 -1
  184. package/dist/model/pi-model.d.ts +16 -5
  185. package/dist/model/pi-model.js +86 -105
  186. package/dist/openapi.json +866 -1218
  187. package/dist/reads/cursor.js +3 -1
  188. package/dist/record/append.d.ts +34 -2
  189. package/dist/record/append.js +50 -1
  190. package/dist/record/environment.d.ts +2 -0
  191. package/dist/record/environment.js +2 -0
  192. package/dist/record/index.d.ts +1 -1
  193. package/dist/record/index.js +1 -1
  194. package/dist/redact.d.ts +1 -1
  195. package/dist/redact.js +3 -2
  196. package/dist/sandbox/egress-token.d.ts +3 -3
  197. package/dist/sandbox/egress-token.js +3 -3
  198. package/dist/sandbox/join.js +3 -2
  199. package/dist/sandbox/manager.d.ts +41 -41
  200. package/dist/sandbox/manager.js +112 -44
  201. package/dist/sandbox/placement.d.ts +1 -1
  202. package/dist/sandbox/placement.js +5 -8
  203. package/dist/sandbox/pods/client.d.ts +1 -10
  204. package/dist/sandbox/pods/client.js +8 -4
  205. package/dist/sandbox/pods/lifecycle.d.ts +19 -11
  206. package/dist/sandbox/pods/lifecycle.js +45 -23
  207. package/dist/sandbox/pods/network-gate.d.ts +4 -5
  208. package/dist/sandbox/pods/network-gate.js +7 -7
  209. package/dist/sandbox/pods/reconcile.js +4 -1
  210. package/dist/sandbox/pods/spec.js +8 -5
  211. package/dist/sandbox/policy.d.ts +7 -1
  212. package/dist/sandbox/policy.js +10 -3
  213. package/dist/sandbox/resolve.d.ts +8 -3
  214. package/dist/sandbox/resolve.js +12 -2
  215. package/dist/sandbox/setup.d.ts +3 -1
  216. package/dist/sandbox/setup.js +34 -11
  217. package/dist/sandbox/share.d.ts +5 -14
  218. package/dist/sandbox/share.js +5 -34
  219. package/dist/sandbox/skills.d.ts +7 -13
  220. package/dist/sandbox/skills.js +16 -31
  221. package/dist/sandbox/tenant-config.d.ts +2 -2
  222. package/dist/sandbox/tenant-config.js +4 -3
  223. package/dist/sandbox/tools.d.ts +7 -1
  224. package/dist/sandbox/tools.js +26 -26
  225. package/dist/sandbox/types.d.ts +10 -3
  226. package/dist/sandbox/types.js +9 -0
  227. package/dist/store/postgres/connect.d.ts +6 -5
  228. package/dist/store/postgres/connect.js +14 -11
  229. package/dist/store/postgres/control.js +13 -13
  230. package/dist/store/postgres/drizzle/0028_artifact_write_keys.sql +2 -0
  231. package/dist/store/postgres/drizzle/0029_protocol_15.sql +11 -0
  232. package/dist/store/postgres/drizzle/0030_protocol_15_runtime_block.sql +11 -0
  233. package/dist/store/postgres/drizzle/0031_protocol_15_mcp_snapshot.sql +8 -0
  234. package/dist/store/postgres/drizzle/meta/_journal.json +28 -0
  235. package/dist/store/postgres/migrate.js +1 -1
  236. package/dist/store/postgres/reads.js +10 -2
  237. package/dist/store/postgres/schema.d.ts +19 -0
  238. package/dist/store/postgres/schema.js +7 -0
  239. package/dist/store/postgres/store.js +55 -26
  240. package/dist/store/types.d.ts +17 -7
  241. package/dist/streams/relay/core.d.ts +3 -3
  242. package/dist/streams/relay/core.js +9 -10
  243. package/dist/tenant/advance.js +21 -31
  244. package/dist/tenant/commands.js +9 -16
  245. package/dist/tenant/context.d.ts +14 -17
  246. package/dist/tenant/definition-files.d.ts +25 -4
  247. package/dist/tenant/definition-files.js +85 -47
  248. package/dist/tenant/effects.js +9 -36
  249. package/dist/tenant/environment-manifests.js +9 -1
  250. package/dist/tenant/environments.d.ts +0 -2
  251. package/dist/tenant/environments.js +54 -30
  252. package/dist/tenant/ephemeral.d.ts +1 -1
  253. package/dist/tenant/ephemeral.js +2 -1
  254. package/dist/tenant/history.d.ts +1 -1
  255. package/dist/tenant/history.js +1 -1
  256. package/dist/tenant/host-token.d.ts +3 -3
  257. package/dist/tenant/host-token.js +12 -11
  258. package/dist/tenant/http.d.ts +5 -8
  259. package/dist/tenant/http.js +9 -0
  260. package/dist/tenant/identity-file.d.ts +24 -1
  261. package/dist/tenant/identity-file.js +35 -7
  262. package/dist/tenant/issuers.d.ts +5 -5
  263. package/dist/tenant/issuers.js +31 -23
  264. package/dist/tenant/jwt.d.ts +8 -2
  265. package/dist/tenant/jwt.js +10 -2
  266. package/dist/tenant/limits.d.ts +90 -0
  267. package/dist/tenant/limits.js +175 -0
  268. package/dist/tenant/module.d.ts +4 -1
  269. package/dist/tenant/module.js +9 -8
  270. package/dist/tenant/outbound.d.ts +17 -19
  271. package/dist/tenant/outbound.js +18 -21
  272. package/dist/tenant/run-grants.js +3 -2
  273. package/dist/tenant/run-token.d.ts +0 -4
  274. package/dist/tenant/run-token.js +6 -11
  275. package/dist/tenant/runtime-limits.d.ts +24 -0
  276. package/dist/tenant/runtime-limits.js +27 -0
  277. package/dist/tenant/runtime.js +30 -43
  278. package/dist/tenant/session-streams.js +7 -6
  279. package/dist/tenant/session.d.ts +1 -1
  280. package/dist/tenant/session.js +1 -1
  281. package/dist/tenant/sessions.js +32 -29
  282. package/dist/tenant/signing-keys.d.ts +1 -1
  283. package/dist/tenant/signing-keys.js +5 -6
  284. package/dist/tenant/status.js +4 -3
  285. package/dist/tenant/streams.js +18 -20
  286. package/dist/tenant/sweep.d.ts +1 -21
  287. package/dist/tenant/sweep.js +39 -48
  288. package/dist/tenant/transcript.d.ts +70 -23
  289. package/dist/tenant/transcript.js +28 -22
  290. package/dist/tenant/types.d.ts +11 -16
  291. package/dist/tenant/worker.d.ts +2 -10
  292. package/dist/tenant/worker.js +5 -14
  293. package/dist/traces/ids.js +5 -1
  294. package/dist/traces/map.d.ts +9 -6
  295. package/dist/traces/map.js +9 -11
  296. package/dist/traces/otlp.d.ts +3 -3
  297. package/dist/traces/otlp.js +5 -3
  298. package/dist/traces/projector.d.ts +9 -4
  299. package/dist/traces/projector.js +13 -7
  300. package/dist/traces/read.js +6 -1
  301. package/dist/tuning.d.ts +383 -0
  302. package/dist/tuning.js +658 -0
  303. package/dist/vault/headers.js +4 -2
  304. package/dist/version.d.ts +1 -1
  305. package/dist/version.js +1 -1
  306. package/package.json +3 -3
  307. package/dist/artifacts/export.d.ts +0 -8
  308. package/dist/artifacts/export.js +0 -204
  309. package/dist/artifacts/media-types.d.ts +0 -30
  310. package/dist/artifacts/media-types.js +0 -137
  311. package/dist/artifacts/workspace.d.ts +0 -60
  312. package/dist/artifacts/workspace.js +0 -45
  313. package/dist/media.d.ts +0 -10
  314. package/dist/media.js +0 -58
  315. package/dist/sandbox/runtime-tools.d.ts +0 -9
  316. package/dist/sandbox/runtime-tools.js +0 -16
  317. package/dist/sandbox/session-sandbox.d.ts +0 -16
  318. package/dist/sandbox/session-sandbox.js +0 -77
  319. package/dist/tenant/artifact-tool.d.ts +0 -13
  320. package/dist/tenant/artifact-tool.js +0 -243
  321. package/dist/tenant/skill-tool.d.ts +0 -20
  322. package/dist/tenant/skill-tool.js +0 -67
  323. package/dist/tenant/tool-results.d.ts +0 -57
  324. package/dist/tenant/tool-results.js +0 -298
  325. package/dist/tenant/tool-search.d.ts +0 -39
  326. package/dist/tenant/tool-search.js +0 -103
@@ -1,20 +1,19 @@
1
- import { createHash } from "node:crypto";
2
- import { delegatesOf, pluginOf, deferredToolsInstructions, deferredToolsTools, delegateManifest, mcpToolSettings, } from "@nylorun/core/define";
1
+ import { delegatesOf, pluginOf, delegateManifest, mcpToolSettings, } from "@nylorun/core/define";
2
+ import { findServer } from "./pool.js";
3
3
  /**
4
- * The `mcp.discovered` payload: each server's outcome, with the tools it added to the snapshot,
5
- * and the Agent Plugin that brought the server (from `manifest`, the session's pinned one).
4
+ * The `mcp.discovered` payload: each server's outcome, with the tools it added to the snapshot
5
+ * that its settings in `manifest` (the session's pinned one) leave enabled, and the Agent Plugin
6
+ * that brought the server.
6
7
  */
7
8
  export function mcpDiscovered(snapshot, diagnostics, manifest) {
8
9
  const agents = new Map(manifest === undefined
9
10
  ? []
10
11
  : [[undefined, manifest], ...delegatesOf(manifest).map(({ manifest: child }) => [child.id, child])]);
11
- const key = (item) => JSON.stringify([item.agentId ?? null, item.serverName]);
12
+ const key = (agentId, serverName) => JSON.stringify([agentId ?? null, serverName]);
12
13
  const tools = new Map();
13
- const deferred = new Map();
14
- for (const tool of snapshot.mcpTools) {
15
- tools.set(key(tool), (tools.get(key(tool)) ?? 0) + 1);
16
- if (tool.deferred)
17
- deferred.set(key(tool), (deferred.get(key(tool)) ?? 0) + 1);
14
+ for (const server of snapshot.servers) {
15
+ const enabled = server.tools.filter((tool) => manifest === undefined || isEnabledIn(manifest, server.agentId, server.name, tool.name));
16
+ tools.set(key(server.agentId, server.name), enabled.length);
18
17
  }
19
18
  return {
20
19
  servers: diagnostics.map((item) => ({
@@ -23,149 +22,108 @@ export function mcpDiscovered(snapshot, diagnostics, manifest) {
23
22
  ...withPlugin(pluginOf(agents.get(item.agentId), { server: item.serverName })),
24
23
  outcome: item.outcome,
25
24
  message: item.message,
26
- tools: tools.get(key(item)) ?? 0,
27
- ...(deferred.has(key(item)) ? { deferred: deferred.get(key(item)) } : {}),
25
+ tools: tools.get(key(item.agentId, item.serverName)) ?? 0,
28
26
  ...(item.disabled ? { disabled: item.disabled } : {}),
29
27
  ...(item.unknownTools?.length ? { unknownTools: [...item.unknownTools] } : {}),
30
28
  ...(item.credentialIds === undefined ? {} : { credentialIds: [...item.credentialIds] }),
31
- ...(item.renamed?.length ? { renamed: item.renamed.map((tool) => ({ ...tool })) } : {}),
32
29
  })),
33
30
  };
34
31
  }
35
32
  function withPlugin(plugin) {
36
33
  return plugin === undefined ? {} : { plugin };
37
34
  }
38
- /** The longest tool name every model provider accepts (R2b C6, Q14). */
39
- export const MODEL_TOOL_NAME_MAX = 64;
40
- /**
41
- * The name the model knows an MCP tool by (R2b C6, Q13): `server__tool`, with each character
42
- * outside `[A-Za-z0-9_-]` replaced by `_`, since MCP allows `.` and 128 characters and OpenAI,
43
- * Bedrock and Gemini on Vertex do not. A name over 64 characters, or one that collides
44
- * (`suffixed`), keeps 55 and adds `_` and 8 hex characters of the SHA-256 of the raw
45
- * `server/tool`.
46
- */
47
- export function normalizeToolName(serverName, serverToolName, options = {}) {
48
- const name = `${serverName}__${serverToolName}`.replace(/[^A-Za-z0-9_-]/gu, "_");
49
- if (name.length <= MODEL_TOOL_NAME_MAX && !options.suffixed)
50
- return name;
51
- const hash = createHash("sha256")
52
- .update(`${serverName}/${serverToolName}`)
53
- .digest("hex")
54
- .slice(0, 8);
55
- return `${name.slice(0, MODEL_TOOL_NAME_MAX - 9)}_${hash}`;
56
- }
57
- /** The names of the agent's tools: its own and those the Runtime pinned. */
58
- export function declaredToolNames(manifest) {
59
- return new Set([...(manifest.tools ?? []), ...(manifest.runtime?.tools ?? [])].map((tool) => tool.name));
60
- }
61
- /** The declaration of the server a tool of the snapshot comes from, in `manifest`. */
62
- function serverOf(manifest, tool) {
63
- const agent = tool.agentId === undefined ? manifest : delegateManifest(manifest, tool.agentId);
64
- return agent?.mcpServers?.[tool.serverName];
35
+ /** The tool `tool` of server `server` of agent `agentId` (the root when absent), as discovered. */
36
+ export function mcpToolIn(snapshot, agentId, server, tool) {
37
+ return snapshot?.servers
38
+ .find((item) => item.agentId === agentId && item.name === server)
39
+ ?.tools.find((item) => item.name === tool);
65
40
  }
66
41
  /** The tool's settings in `manifest` (R2b C9); the defaults when its server is not there. */
67
- export function mcpToolSettingsIn(manifest, tool) {
68
- const server = serverOf(manifest, tool);
69
- return server ? mcpToolSettings(server, tool.serverToolName) : { enabled: true, approval: "never" };
42
+ export function mcpToolSettingsIn(manifest, agentId, server, tool) {
43
+ const declared = findServer(manifest, agentId, server);
44
+ return declared ? mcpToolSettings(declared.server, tool) : { enabled: true, approval: "never" };
45
+ }
46
+ /** True when the tool's settings in `manifest` leave it enabled (R2b C9). */
47
+ export function isEnabledIn(manifest, agentId, server, tool) {
48
+ return mcpToolSettingsIn(manifest, agentId, server, tool).enabled;
70
49
  }
71
50
  /**
72
- * The tools of a snapshot, as the engine gets them for a turn whose manifest is `manifest` (the
73
- * session's pin, or a turn variant that tightened its MCP servers' tools):
74
- *
75
- * - a tool its settings disable is left out (R2b C9); the Tool Gate holds a call its approval
76
- * or the Tenant's tool policy asks a person about (R5 step 2);
77
- * - a deferred tool (R2b C10) is marked so, out of the model's list, and its agent gets the
78
- * session tools `tool_search`, with the note on the servers it holds deferred tools of, and
79
- * `tool_call`. Their names are reserved: no tool of the agent's own takes them.
80
- *
81
- * Nothing here changes between the steps of a turn, so neither does the model's tool list.
51
+ * The snapshot's facts for a turn whose manifest is `manifest` (the session's pin, or a turn
52
+ * variant that tightened its MCP servers' tools): each tool with whether its settings leave it
53
+ * `enabled` and, when they say, whether to defer it. A server the turn's manifest no longer
54
+ * declares is left out.
82
55
  */
83
- export function sessionToolsOf(snapshot, manifest) {
84
- if (!snapshot?.mcpTools.length)
85
- return undefined;
86
- const inline = [];
87
- const deferred = new Map();
88
- const notes = new Map();
89
- for (const tool of snapshot.mcpTools) {
90
- const settings = mcpToolSettingsIn(manifest, tool);
91
- if (!settings.enabled)
92
- continue;
93
- const defer = tool.deferred === true;
94
- const entry = {
95
- ...(tool.agentId === undefined ? {} : { agentId: tool.agentId }),
96
- name: tool.name,
97
- ...(tool.description === undefined ? {} : { description: tool.description }),
98
- inputSchema: tool.inputSchema,
99
- ...(tool.outputSchema === undefined ? {} : { outputSchema: tool.outputSchema }),
100
- ...(defer ? { deferred: true } : {}),
101
- };
102
- if (!defer) {
103
- inline.push(entry);
104
- continue;
105
- }
106
- deferred.set(tool.agentId, [...(deferred.get(tool.agentId) ?? []), entry]);
107
- const servers = notes.get(tool.agentId) ?? new Map();
108
- servers.set(tool.serverName, (servers.get(tool.serverName) ?? 0) + 1);
109
- notes.set(tool.agentId, servers);
110
- }
111
- const session = [];
112
- for (const [agentId, tools] of deferred) {
113
- const servers = [...notes.get(agentId)].map(([serverName, count]) => {
114
- const instructions = snapshot.servers?.find((item) => item.agentId === agentId && item.serverName === serverName)?.instructions;
115
- return { serverName, tools: count, ...(instructions ? { instructions } : {}) };
116
- });
117
- const [search, call] = deferredToolsTools();
118
- for (const tool of [
119
- { ...search, instructions: [deferredToolsInstructions(servers)] },
120
- call,
121
- ])
122
- session.push({ ...(agentId === undefined ? {} : { agentId }), ...tool });
123
- session.push(...tools);
124
- }
125
- return [...inline, ...session];
56
+ export function mcpFactsOf(snapshot, manifest) {
57
+ return {
58
+ servers: snapshot.servers.flatMap((server) => {
59
+ if (!findServer(manifest, server.agentId, server.name))
60
+ return [];
61
+ return [
62
+ {
63
+ ...(server.agentId === undefined ? {} : { agentId: server.agentId }),
64
+ name: server.name,
65
+ ...(server.instructions === undefined ? {} : { instructions: server.instructions }),
66
+ tools: server.tools.map((tool) => {
67
+ const settings = mcpToolSettingsIn(manifest, server.agentId, server.name, tool.name);
68
+ return {
69
+ ...tool,
70
+ enabled: settings.enabled,
71
+ ...(settings.deferred === undefined ? {} : { deferred: settings.deferred }),
72
+ };
73
+ }),
74
+ },
75
+ ];
76
+ }),
77
+ };
78
+ }
79
+ /** The manifest of the agent an effect belongs to: the root, or an agent it uses as a tool. */
80
+ export function manifestFor(manifest, agent) {
81
+ return agent ? delegateManifest(manifest, agent.id) : manifest;
126
82
  }
127
- /** The share of the model's context window past which an agent's MCP tools are deferred (Q21). */
128
- export const DEFER_CONTEXT_SHARE = 0.1;
129
- /** Characters per token, to estimate what tool definitions take of a context window (Q21). */
130
- export const CHARS_PER_TOKEN = 4;
131
83
  /**
132
- * The snapshot with its deferred tools marked (R2b C10, Q21), decided once for the session when
133
- * core records it. A tool's own setting, then `"*"`'s, then its server's, decides; a tool none
134
- * sets is deferred when the JSON of its agent's MCP tools that would be listed passes a tenth of
135
- * the model's context window (`contextWindow` tokens, at 4 characters a token).
84
+ * `snapshot` within the Tenant's Runtime limit `mcpSnapshotBytes` (its JSON, which every
85
+ * `turn.start.mcp` carries): its servers in order while they fit. A server that does not is left
86
+ * out, so the session never offers its tools, and its diagnostic says so (`failed`, replacing
87
+ * the one it had). Unchanged when the whole snapshot fits.
136
88
  */
137
- export function pinDeferral(snapshot, manifest, contextWindow) {
138
- const limit = contextWindow * CHARS_PER_TOKEN * DEFER_CONTEXT_SHARE;
139
- const listed = new Map();
140
- const set = snapshot.mcpTools.map((tool) => mcpToolSettingsIn(manifest, tool).deferred);
141
- snapshot.mcpTools.forEach((tool, i) => {
142
- if (set[i] === true)
143
- return;
144
- const size = JSON.stringify({ name: tool.name, description: tool.description ?? "", inputSchema: tool.inputSchema }).length;
145
- listed.set(tool.agentId, (listed.get(tool.agentId) ?? 0) + size);
89
+ export function fitSnapshot(snapshot, diagnostics, limitBytes) {
90
+ const bytes = (value) => Buffer.byteLength(JSON.stringify(value));
91
+ if (bytes(snapshot) <= limitBytes)
92
+ return { snapshot, diagnostics: [...diagnostics] };
93
+ const kept = [];
94
+ const dropped = new Map();
95
+ const key = (agentId, serverName) => JSON.stringify([agentId ?? null, serverName]);
96
+ for (const server of snapshot.servers) {
97
+ const next = { ...snapshot, servers: [...kept, server] };
98
+ const size = bytes(next);
99
+ if (size <= limitBytes)
100
+ kept.push(server);
101
+ else
102
+ dropped.set(key(server.agentId, server.name), bytes(server));
103
+ }
104
+ const tooLarge = (agentId, serverName, size) => ({
105
+ ...(agentId === undefined ? {} : { agentId }),
106
+ serverName,
107
+ outcome: "failed",
108
+ message: `The server's tools and instructions take ${size} bytes, past what the session may pin with the rest: the Runtime limit mcpSnapshotBytes (${limitBytes} bytes; PUT /v1/tenant/limits). Its tools are not offered.`,
146
109
  });
147
- const mcpTools = snapshot.mcpTools.map((tool, i) => {
148
- const { deferred: _, ...rest } = tool;
149
- const defer = set[i] ?? (listed.get(tool.agentId) ?? 0) > limit;
150
- return defer ? { ...rest, deferred: true } : rest;
110
+ const out = diagnostics.map((item) => {
111
+ const size = dropped.get(key(item.agentId, item.serverName));
112
+ return size === undefined ? item : tooLarge(item.agentId, item.serverName, size);
151
113
  });
152
- return { ...snapshot, mcpTools };
153
- }
154
- /**
155
- * The snapshot's record of an MCP tool call, or undefined when the call is not an MCP tool. With
156
- * the turn's `manifest`, a tool its settings disable is not one either (R2b C9).
157
- */
158
- export function mcpToolOf(snapshot, request, manifest) {
159
- const tool = snapshot?.mcpTools.find((tool) => tool.agentId === request.agent?.id && tool.name === request.toolName);
160
- if (tool && manifest && !isEnabledIn(manifest, tool))
161
- return undefined;
162
- return tool;
163
- }
164
- /** True when the tool's settings in `manifest` leave it enabled (R2b C9). */
165
- export function isEnabledIn(manifest, tool) {
166
- return mcpToolSettingsIn(manifest, tool).enabled;
114
+ for (const server of snapshot.servers) {
115
+ const size = dropped.get(key(server.agentId, server.name));
116
+ if (size !== undefined && !out.some((item) => key(item.agentId, item.serverName) === key(server.agentId, server.name)))
117
+ out.push(tooLarge(server.agentId, server.name, size));
118
+ }
119
+ return { snapshot: { ...snapshot, servers: kept }, diagnostics: out };
167
120
  }
168
- /** The manifest of the agent an effect belongs to: the root, or an agent it uses as a tool. */
169
- export function manifestFor(manifest, agent) {
170
- return agent ? delegateManifest(manifest, agent.id) : manifest;
121
+ /** True for a snapshot of the shape this Runtime pins (`snapshotSchemaVersion` 2). */
122
+ export function isSnapshot(value) {
123
+ const snapshot = value;
124
+ return (typeof snapshot === "object" &&
125
+ snapshot !== null &&
126
+ snapshot.snapshotSchemaVersion === 2 &&
127
+ typeof snapshot.manifestHash === "string" &&
128
+ Array.isArray(snapshot.servers));
171
129
  }
@@ -1,6 +1,7 @@
1
1
  var _a;
2
2
  import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
3
3
  import { dirname } from "node:path";
4
+ import { hostTuning } from "../tuning.js";
4
5
  export class ProjectCredentialStore {
5
6
  file;
6
7
  legacyFile;
@@ -68,7 +69,8 @@ export class ProjectCredentialStore {
68
69
  async #locked(operation) {
69
70
  await mkdir(dirname(this.file), { recursive: true });
70
71
  const lock = this.file + ".lock";
71
- for (let attempt = 0; attempt < 100; attempt += 1) {
72
+ const { credentialLockPollMs: pollMs, credentialLockAttempts: attempts } = hostTuning().host;
73
+ for (let attempt = 0; attempt < attempts; attempt += 1) {
72
74
  try {
73
75
  await mkdir(lock);
74
76
  break;
@@ -76,9 +78,9 @@ export class ProjectCredentialStore {
76
78
  catch (error) {
77
79
  if (error.code !== "EEXIST")
78
80
  throw error;
79
- await new Promise((resolve) => setTimeout(resolve, 25));
81
+ await new Promise((resolve) => setTimeout(resolve, pollMs));
80
82
  }
81
- if (attempt === 99)
83
+ if (attempt === attempts - 1)
82
84
  throw new Error("Timed out waiting for the credential store.");
83
85
  }
84
86
  try {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * What a model reads (protocol 12): its pi-ai catalog's `input` (text, image) and what the
3
3
  * operator added. One function, `capabilitiesOf`, serves the catalog, the accept check, the Model
4
- * Gate and `read_artifact`.
4
+ * Gate.
5
5
  *
6
6
  * The operator may add only an input our provider path sends natively for the model's API
7
7
  * (`NATIVE_INPUTS`): an image on every API; a PDF on the APIs below; Office documents on the
@@ -1,21 +1,7 @@
1
1
  import type { Api, Model } from "@earendil-works/pi-ai";
2
- import type { HostModelCatalog, HostModelView, ModelInput } from "@nylorun/core/contracts";
3
- import type { SessionStore } from "../store/types.js";
2
+ import type { HostModelCatalog, ModelInput } from "@nylorun/core/contracts";
3
+ import { type ModelBindingView } from "./descriptor.js";
4
4
  export type { HostModelCatalog };
5
- /**
6
- * The context window, in tokens, of the Tenant's model (`GET /v1/tenant/model`'s view): the
7
- * custom endpoint's setting, else the provider catalog's. A model the catalog does not know, or
8
- * none configured, is assumed small (`CUSTOM_CONTEXT_WINDOW`), as for a custom endpoint.
9
- */
10
- export declare function contextWindowOf(view: {
11
- configured: boolean;
12
- provider?: string;
13
- model?: string;
14
- baseUrl?: string;
15
- settings?: {
16
- contextWindow?: number;
17
- };
18
- }): number;
19
5
  /**
20
6
  * Public provider and model names, and what each model reads with the operator's additions
21
7
  * (`added`, by `<provider>/<model>`) and what may be added (protocol 12). No credentials.
@@ -25,25 +11,12 @@ export declare function hostModelCatalog(added?: Readonly<Record<string, readonl
25
11
  export declare function catalogModel(provider: string, model: string): Model<Api> | undefined;
26
12
  /**
27
13
  * What a configured model reads (protocol 12): a custom endpoint's `settings.inputs` (text only
28
- * by default), else its catalog's inputs and the operator's additions (`added`). Undefined for no
29
- * model, or one the catalog does not know.
14
+ * by default), else its catalog's inputs and the operator's additions (`added`), as its
15
+ * descriptor says (`hostModelDescriptor`). Undefined for no model, or one the catalog does not
16
+ * know.
30
17
  */
31
18
  export declare function inputsOfHostModel(view: {
32
- configured: boolean;
33
- provider?: string;
34
- model?: string;
35
- baseUrl?: string;
36
- settings?: {
37
- inputs?: readonly ModelInput[];
38
- };
39
- }, added?: Readonly<Record<string, readonly ModelInput[]>>): ModelInput[] | undefined;
40
- /**
41
- * What the Tenant's model reads now, for the accept check and `read_artifact`: undefined when no
42
- * model is in the vault (a test's fake provider, say), and the check is skipped.
43
- */
44
- export declare function currentModelInputs(ctx: {
45
- readonly store: SessionStore;
46
- readonly vault: {
47
- getHostModel(): Promise<HostModelView>;
48
- };
49
- }): Promise<ModelInput[] | undefined>;
19
+ readonly configured: false;
20
+ } | ({
21
+ readonly configured: true;
22
+ } & ModelBindingView), added?: Readonly<Record<string, readonly ModelInput[]>>): ModelInput[] | undefined;
@@ -1,6 +1,6 @@
1
- import { readAddedInputs } from "../tenant/model-setting.js";
2
1
  import { addableInputs, capabilitiesOf } from "./capabilities.js";
3
- import { CUSTOM_CONTEXT_WINDOW, modelsFor } from "./models.js";
2
+ import { hostModelDescriptor } from "./descriptor.js";
3
+ import { modelsFor } from "./models.js";
4
4
  const emptyStore = {
5
5
  async read() {
6
6
  return undefined;
@@ -13,19 +13,6 @@ const emptyStore = {
13
13
  },
14
14
  async delete() { },
15
15
  };
16
- /**
17
- * The context window, in tokens, of the Tenant's model (`GET /v1/tenant/model`'s view): the
18
- * custom endpoint's setting, else the provider catalog's. A model the catalog does not know, or
19
- * none configured, is assumed small (`CUSTOM_CONTEXT_WINDOW`), as for a custom endpoint.
20
- */
21
- export function contextWindowOf(view) {
22
- if (!view.configured || !view.provider || !view.model)
23
- return CUSTOM_CONTEXT_WINDOW;
24
- if (view.baseUrl)
25
- return view.settings?.contextWindow ?? CUSTOM_CONTEXT_WINDOW;
26
- const models = modelsFor({ provider: "", model: "" }, emptyStore, { environment: false });
27
- return models.getModel(view.provider, view.model)?.contextWindow ?? CUSTOM_CONTEXT_WINDOW;
28
- }
29
16
  /**
30
17
  * Public provider and model names, and what each model reads with the operator's additions
31
18
  * (`added`, by `<provider>/<model>`) and what may be added (protocol 12). No credentials.
@@ -53,26 +40,12 @@ export function catalogModel(provider, model) {
53
40
  }
54
41
  /**
55
42
  * What a configured model reads (protocol 12): a custom endpoint's `settings.inputs` (text only
56
- * by default), else its catalog's inputs and the operator's additions (`added`). Undefined for no
57
- * model, or one the catalog does not know.
43
+ * by default), else its catalog's inputs and the operator's additions (`added`), as its
44
+ * descriptor says (`hostModelDescriptor`). Undefined for no model, or one the catalog does not
45
+ * know.
58
46
  */
59
47
  export function inputsOfHostModel(view, added = {}) {
60
- if (!view.configured || !view.provider || !view.model)
61
- return undefined;
62
- if (view.baseUrl) {
63
- const inputs = view.settings?.inputs ?? [];
64
- return capabilitiesOf({ api: "openai-completions", input: inputs.includes("image") ? ["text", "image"] : ["text"] }, inputs).inputs;
65
- }
66
- const model = catalogModel(view.provider, view.model);
67
- return model && capabilitiesOf(model, added[`${view.provider}/${view.model}`]).inputs;
68
- }
69
- /**
70
- * What the Tenant's model reads now, for the accept check and `read_artifact`: undefined when no
71
- * model is in the vault (a test's fake provider, say), and the check is skipped.
72
- */
73
- export async function currentModelInputs(ctx) {
74
- const view = await ctx.vault.getHostModel();
75
48
  if (!view.configured)
76
49
  return undefined;
77
- return inputsOfHostModel(view, await ctx.store.tx((t) => readAddedInputs(t)));
50
+ return hostModelDescriptor(view, added)?.inputs;
78
51
  }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The model descriptor (protocol 15): the Tenant's model as a harness learns it in
3
+ * `turn.start.model` — its provider and id, what it reads, its context window and output limit.
4
+ * One resolution serves the descriptor, the catalog's inputs and the Model Gate: the binding
5
+ * becomes a pi-ai `Selection` (`selectionOf`), the registry finds the model, and
6
+ * `describeModel` reads it with the operator's additions. So what a harness is told and what the
7
+ * gate takes cannot disagree.
8
+ */
9
+ import type { Api, Model } from "@earendil-works/pi-ai";
10
+ import { type CustomModelSettings, type HostModelView, type ModelInput } from "@nylorun/core/contracts";
11
+ import type { ModelDescriptor } from "@nylorun/core/harness-api";
12
+ import type { SessionStore } from "../store/types.js";
13
+ import { type Selection } from "./models.js";
14
+ /** A configured model: its provider and model, and a custom endpoint's address and settings. */
15
+ export interface ModelBindingView {
16
+ readonly provider: string;
17
+ readonly model: string;
18
+ readonly baseUrl?: string;
19
+ readonly settings?: CustomModelSettings;
20
+ }
21
+ /**
22
+ * The pi-ai selection for `binding`. A call may name another model of the same provider
23
+ * (`requested`, as `<model>` or `<provider>/<model>`); a custom endpoint carries its settings.
24
+ */
25
+ export declare function selectionOf(binding: ModelBindingView, requested?: string): Selection;
26
+ /** The inputs the operator added that apply to `selection`: a custom endpoint's own, or the Tenant's. */
27
+ export declare function addedInputsOf(selection: Selection, binding: Pick<ModelBindingView, "settings">, added: Readonly<Record<string, readonly ModelInput[]>>): readonly ModelInput[] | undefined;
28
+ /** A pi-ai model as a descriptor, with the inputs the operator added (`capabilitiesOf`). */
29
+ export declare function describeModel(found: Model<Api>, added?: readonly ModelInput[]): ModelDescriptor;
30
+ /** The fixture model (`model.fixture`): it reads every input, since it ignores files. */
31
+ export declare const FIXTURE_DESCRIPTOR: ModelDescriptor;
32
+ /**
33
+ * The descriptor of a configured model (`binding`), with the Tenant's added inputs; undefined
34
+ * for a model the catalog does not know. No credential is read.
35
+ */
36
+ export declare function hostModelDescriptor(binding: ModelBindingView, added?: Readonly<Record<string, readonly ModelInput[]>>): ModelDescriptor | undefined;
37
+ /**
38
+ * The model the Tenant's turns use now: the fixture model's descriptor when the Tenant uses it,
39
+ * else its active model's; undefined when none is configured (a test's scripted provider, say).
40
+ */
41
+ export declare function currentModelDescriptor(ctx: {
42
+ readonly store: SessionStore;
43
+ readonly vault: {
44
+ getHostModel(): Promise<HostModelView>;
45
+ };
46
+ }): Promise<ModelDescriptor | undefined>;
47
+ /**
48
+ * The context window, in tokens, of the Tenant's model now; without one, or one the catalog does
49
+ * not know, it is assumed small (`CUSTOM_MODEL_SETTING_DEFAULTS`), as for a custom endpoint.
50
+ */
51
+ export declare function currentContextWindow(ctx: Parameters<typeof currentModelDescriptor>[0]): Promise<number>;
@@ -0,0 +1,83 @@
1
+ import { MODEL_INPUTS, } from "@nylorun/core/contracts";
2
+ import { readAddedInputs, usesFixtureModel } from "../tenant/model-setting.js";
3
+ import { capabilitiesOf } from "./capabilities.js";
4
+ import { CUSTOM_MODEL_SETTING_DEFAULTS } from "@nylorun/core/contracts";
5
+ import { modelsFor } from "./models.js";
6
+ /**
7
+ * The pi-ai selection for `binding`. A call may name another model of the same provider
8
+ * (`requested`, as `<model>` or `<provider>/<model>`); a custom endpoint carries its settings.
9
+ */
10
+ export function selectionOf(binding, requested) {
11
+ return {
12
+ provider: binding.provider,
13
+ model: requested?.startsWith(`${binding.provider}/`)
14
+ ? requested.slice(binding.provider.length + 1)
15
+ : (requested ?? binding.model),
16
+ ...(binding.baseUrl ? { custom: { baseUrl: binding.baseUrl, ...(binding.settings ?? {}) } } : {}),
17
+ };
18
+ }
19
+ /** The inputs the operator added that apply to `selection`: a custom endpoint's own, or the Tenant's. */
20
+ export function addedInputsOf(selection, binding, added) {
21
+ return selection.custom ? binding.settings?.inputs : added[`${selection.provider}/${selection.model}`];
22
+ }
23
+ /** A pi-ai model as a descriptor, with the inputs the operator added (`capabilitiesOf`). */
24
+ export function describeModel(found, added) {
25
+ return {
26
+ provider: found.provider,
27
+ id: found.id,
28
+ inputs: capabilitiesOf(found, added).inputs,
29
+ contextWindow: found.contextWindow,
30
+ maxOutputTokens: found.maxTokens,
31
+ ...(found.reasoning === undefined ? {} : { reasoning: found.reasoning }),
32
+ };
33
+ }
34
+ /** The fixture model (`model.fixture`): it reads every input, since it ignores files. */
35
+ export const FIXTURE_DESCRIPTOR = Object.freeze({
36
+ provider: "fixture",
37
+ id: "fixture",
38
+ inputs: [...MODEL_INPUTS],
39
+ contextWindow: CUSTOM_MODEL_SETTING_DEFAULTS.contextWindow,
40
+ maxOutputTokens: CUSTOM_MODEL_SETTING_DEFAULTS.maxTokens,
41
+ });
42
+ const emptyStore = {
43
+ async read() {
44
+ return undefined;
45
+ },
46
+ async list() {
47
+ return [];
48
+ },
49
+ async modify(_providerId, fn) {
50
+ return fn(undefined);
51
+ },
52
+ async delete() { },
53
+ };
54
+ /**
55
+ * The descriptor of a configured model (`binding`), with the Tenant's added inputs; undefined
56
+ * for a model the catalog does not know. No credential is read.
57
+ */
58
+ export function hostModelDescriptor(binding, added = {}) {
59
+ const selection = selectionOf(binding);
60
+ const found = modelsFor(selection, emptyStore, { environment: false }).getModel(selection.provider, selection.model);
61
+ return found && describeModel(found, addedInputsOf(selection, binding, added));
62
+ }
63
+ /**
64
+ * The model the Tenant's turns use now: the fixture model's descriptor when the Tenant uses it,
65
+ * else its active model's; undefined when none is configured (a test's scripted provider, say).
66
+ */
67
+ export async function currentModelDescriptor(ctx) {
68
+ const { fixture, added } = await ctx.store.tx(async (t) => ({
69
+ fixture: await usesFixtureModel(t),
70
+ added: await readAddedInputs(t),
71
+ }));
72
+ if (fixture)
73
+ return FIXTURE_DESCRIPTOR;
74
+ const view = await ctx.vault.getHostModel();
75
+ return view.configured ? hostModelDescriptor(view, added) : undefined;
76
+ }
77
+ /**
78
+ * The context window, in tokens, of the Tenant's model now; without one, or one the catalog does
79
+ * not know, it is assumed small (`CUSTOM_MODEL_SETTING_DEFAULTS`), as for a custom endpoint.
80
+ */
81
+ export async function currentContextWindow(ctx) {
82
+ return (await currentModelDescriptor(ctx))?.contextWindow ?? CUSTOM_MODEL_SETTING_DEFAULTS.contextWindow;
83
+ }
@@ -13,9 +13,6 @@ export type Selection = Readonly<{
13
13
  compat?: Readonly<Record<string, unknown>>;
14
14
  }>;
15
15
  }>;
16
- /** A custom endpoint whose window is unknown is assumed small: an early compaction beats a failed call. */
17
- export declare const CUSTOM_CONTEXT_WINDOW = 32768;
18
- export declare const CUSTOM_MAX_TOKENS = 8192;
19
16
  /**
20
17
  * Build the pi-ai model registry from explicit credentials only.
21
18
  * Ambient process environment / provider env auth is never consulted (A7, A10).
@@ -1,9 +1,7 @@
1
1
  import { createProvider, } from "@earendil-works/pi-ai";
2
2
  import { stream, streamSimple, } from "@earendil-works/pi-ai/api/openai-completions";
3
3
  import { builtinModels } from "@earendil-works/pi-ai/providers/all";
4
- /** A custom endpoint whose window is unknown is assumed small: an early compaction beats a failed call. */
5
- export const CUSTOM_CONTEXT_WINDOW = 32_768;
6
- export const CUSTOM_MAX_TOKENS = 8_192;
4
+ import { CUSTOM_MODEL_SETTING_DEFAULTS } from "@nylorun/core/contracts";
7
5
  /**
8
6
  * Build the pi-ai model registry from explicit credentials only.
9
7
  * Ambient process environment / provider env auth is never consulted (A7, A10).
@@ -27,8 +25,8 @@ export function modelsFor(selection, credentials, options = {}) {
27
25
  reasoning: selection.custom.reasoning ?? false,
28
26
  input: selection.custom.inputs?.includes("image") ? ["text", "image"] : ["text"],
29
27
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
30
- contextWindow: selection.custom.contextWindow ?? CUSTOM_CONTEXT_WINDOW,
31
- maxTokens: selection.custom.maxTokens ?? CUSTOM_MAX_TOKENS,
28
+ contextWindow: selection.custom.contextWindow ?? CUSTOM_MODEL_SETTING_DEFAULTS.contextWindow,
29
+ maxTokens: selection.custom.maxTokens ?? CUSTOM_MODEL_SETTING_DEFAULTS.maxTokens,
32
30
  ...(selection.custom.compat
33
31
  ? { compat: { ...selection.custom.compat } }
34
32
  : {}),
@@ -13,7 +13,7 @@
13
13
  * sending a marker to the model.
14
14
  */
15
15
  import { randomUUID } from "node:crypto";
16
- import { essence } from "../artifacts/media-types.js";
16
+ import { essence } from "@nylorun/core/contracts";
17
17
  import { NATIVE_INPUTS } from "./capabilities.js";
18
18
  /**
19
19
  * The kinds each pi-ai API has a native block for here: the model inputs an operator may add