@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.
- package/CHANGELOG.md +169 -0
- package/README.md +26 -16
- package/dist/adapters/execution/restate.d.ts +15 -18
- package/dist/adapters/execution/restate.js +31 -27
- package/dist/adapters/replication/pgoutput.d.ts +1 -1
- package/dist/adapters/replication/pgoutput.js +3 -2
- package/dist/adapters/sandbox/local.js +8 -5
- package/dist/adapters/sandbox/virtual.js +2 -2
- package/dist/adapters/streams/s2.d.ts +1 -1
- package/dist/adapters/streams/s2.js +18 -14
- package/dist/api/a2a/card.js +1 -1
- package/dist/api/a2a/endpoint.js +3 -4
- package/dist/api/a2a/protocol.js +4 -0
- package/dist/api/a2a/routes.d.ts +2 -6
- package/dist/api/a2a/routes.js +12 -18
- package/dist/api/ag-ui/endpoint.js +2 -3
- package/dist/api/ag-ui/routes.js +4 -4
- package/dist/api/components.d.ts +326 -45
- package/dist/api/components.js +5 -1
- package/dist/api/gate/keys.js +7 -4
- package/dist/api/gate/routes.d.ts +6 -2
- package/dist/api/gate/routes.js +15 -11
- package/dist/api/http/app.d.ts +2 -2
- package/dist/api/http/app.js +2 -2
- package/dist/api/http/body.d.ts +15 -3
- package/dist/api/http/body.js +15 -7
- package/dist/api/http/define.d.ts +1 -1
- package/dist/api/http/respond.js +7 -3
- package/dist/api/http/routes/access.js +5 -4
- package/dist/api/http/routes/artifacts.js +19 -7
- package/dist/api/http/routes/coverage.js +1 -1
- package/dist/api/http/routes/environment-manifests.js +1 -1
- package/dist/api/http/routes/environments.js +6 -6
- package/dist/api/http/routes/files.d.ts +2 -1
- package/dist/api/http/routes/files.js +31 -5
- package/dist/api/http/routes/mcp.js +1 -1
- package/dist/api/http/routes/reads.d.ts +35 -0
- package/dist/api/http/routes/reads.js +50 -22
- package/dist/api/http/routes/sessions.js +12 -11
- package/dist/api/http/routes/tenant.d.ts +2 -2
- package/dist/api/http/routes/tenant.js +69 -16
- package/dist/api/inbound-files.d.ts +3 -9
- package/dist/api/inbound-files.js +18 -24
- package/dist/api/openapi.js +6 -2
- package/dist/artifacts/disk.d.ts +0 -4
- package/dist/artifacts/disk.js +77 -73
- package/dist/artifacts/files.d.ts +13 -4
- package/dist/artifacts/files.js +27 -9
- package/dist/artifacts/folder-upload.d.ts +75 -0
- package/dist/artifacts/folder-upload.js +263 -0
- package/dist/artifacts/folders.d.ts +14 -8
- package/dist/artifacts/folders.js +19 -11
- package/dist/artifacts/links.js +7 -6
- package/dist/artifacts/parts.d.ts +9 -14
- package/dist/artifacts/parts.js +11 -9
- package/dist/artifacts/pipe.d.ts +15 -0
- package/dist/artifacts/pipe.js +71 -0
- package/dist/artifacts/quota.d.ts +36 -0
- package/dist/artifacts/quota.js +44 -0
- package/dist/artifacts/service.d.ts +25 -1
- package/dist/artifacts/service.js +70 -25
- package/dist/blob/fs.js +2 -1
- package/dist/blob/s3.d.ts +6 -2
- package/dist/blob/s3.js +9 -7
- package/dist/blob/types.d.ts +1 -1
- package/dist/blob/types.js +1 -1
- package/dist/core/limits.d.ts +11 -35
- package/dist/core/limits.js +5 -73
- package/dist/core/sandbox-routes.js +0 -1
- package/dist/core/turn-manifest.d.ts +1 -2
- package/dist/core/turn-manifest.js +4 -28
- package/dist/execution/memory.d.ts +8 -5
- package/dist/execution/memory.js +8 -6
- package/dist/execution/types.d.ts +1 -6
- package/dist/execution/types.js +0 -5
- package/dist/gates/contract.d.ts +3 -2
- package/dist/gates/contract.js +1 -1
- package/dist/gates/egress-credentials.js +4 -3
- package/dist/gates/egress.d.ts +9 -9
- package/dist/gates/egress.js +19 -19
- package/dist/gates/fixture-model.js +13 -2
- package/dist/gates/handler.d.ts +1 -3
- package/dist/gates/handler.js +4 -3
- package/dist/gates/http-client.d.ts +4 -3
- package/dist/gates/http-client.js +5 -7
- package/dist/gates/http-tool.d.ts +24 -4
- package/dist/gates/http-tool.js +53 -17
- package/dist/gates/in-process.d.ts +2 -1
- package/dist/gates/in-process.js +17 -9
- package/dist/gates/inflight.d.ts +2 -2
- package/dist/gates/inflight.js +3 -2
- package/dist/gates/journal.js +5 -7
- package/dist/gates/mcp-handler.d.ts +4 -3
- package/dist/gates/mcp-handler.js +15 -5
- package/dist/gates/model-gate.d.ts +11 -2
- package/dist/gates/policy.d.ts +28 -5
- package/dist/gates/policy.js +60 -17
- package/dist/gates/provider-gate.d.ts +22 -0
- package/dist/gates/provider-gate.js +30 -0
- package/dist/gates/tool-calls.d.ts +1 -3
- package/dist/gates/tool-calls.js +2 -3
- package/dist/gates/tool-client.d.ts +1 -1
- package/dist/gates/tool-client.js +5 -6
- package/dist/gates/tool-contract.d.ts +8 -5
- package/dist/gates/tool-contract.js +1 -1
- package/dist/gates/tool-gate.d.ts +18 -7
- package/dist/gates/tool-gate.js +49 -7
- package/dist/harness/calls.d.ts +27 -25
- package/dist/harness/calls.js +40 -46
- package/dist/harness/executors.d.ts +10 -3
- package/dist/harness/executors.js +53 -23
- package/dist/harness/main.js +2 -2
- package/dist/harness/pod.d.ts +0 -2
- package/dist/harness/pod.js +7 -6
- package/dist/harness/run-tokens.d.ts +4 -1
- package/dist/harness/run-tokens.js +6 -2
- package/dist/harness/service.d.ts +17 -14
- package/dist/harness/service.js +21 -35
- package/dist/harness/setup.d.ts +0 -2
- package/dist/harness/setup.js +4 -9
- package/dist/harness/ws-client.d.ts +2 -2
- package/dist/harness/ws-client.js +7 -5
- package/dist/harness/ws-port.d.ts +3 -4
- package/dist/harness/ws-port.js +3 -4
- package/dist/harness-api/artifacts.d.ts +20 -0
- package/dist/harness-api/artifacts.js +478 -0
- package/dist/harness-api/in-process.d.ts +2 -2
- package/dist/harness-api/in-process.js +18 -16
- package/dist/harness-api/record.d.ts +10 -9
- package/dist/harness-api/record.js +102 -157
- package/dist/harness-api/renew.d.ts +1 -1
- package/dist/harness-api/renew.js +2 -2
- package/dist/harness-api/server.d.ts +1 -16
- package/dist/harness-api/server.js +82 -73
- package/dist/harness-api/start.d.ts +20 -2
- package/dist/harness-api/start.js +57 -18
- package/dist/harness-api/tool-journal.d.ts +15 -10
- package/dist/harness-api/tool-journal.js +26 -24
- package/dist/harness-api/workspace.d.ts +0 -4
- package/dist/harness-api/workspace.js +2 -45
- package/dist/harness-api/ws-server.js +10 -10
- package/dist/host/create-host.js +2 -3
- package/dist/host/execution.js +2 -3
- package/dist/host/gates.d.ts +2 -9
- package/dist/host/gates.js +15 -12
- package/dist/host/http.d.ts +0 -2
- package/dist/host/http.js +0 -27
- package/dist/host/main.js +10 -3
- package/dist/host/operate.js +12 -3
- package/dist/host/stack-config.d.ts +11 -0
- package/dist/host/stack-config.js +21 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/infra/index.js +2 -1
- package/dist/infra/readiness.d.ts +0 -2
- package/dist/infra/readiness.js +4 -3
- package/dist/keys/client.d.ts +1 -0
- package/dist/keys/client.js +2 -3
- package/dist/keys/contract.d.ts +1 -3
- package/dist/keys/contract.js +1 -3
- package/dist/keys/egress-ca.d.ts +0 -2
- package/dist/keys/egress-ca.js +2 -3
- package/dist/keys/keys.js +6 -1
- package/dist/keys/x509.d.ts +8 -4
- package/dist/keys/x509.js +14 -5
- package/dist/management-openapi.json +1961 -994
- package/dist/mcp/connect.d.ts +35 -26
- package/dist/mcp/connect.js +112 -141
- package/dist/mcp/pool.d.ts +27 -22
- package/dist/mcp/pool.js +34 -48
- package/dist/mcp/preview.d.ts +13 -6
- package/dist/mcp/preview.js +37 -20
- package/dist/mcp/snapshot.d.ts +35 -86
- package/dist/mcp/snapshot.js +93 -135
- package/dist/model/auth-store.js +5 -3
- package/dist/model/capabilities.d.ts +1 -1
- package/dist/model/catalog.d.ts +9 -36
- package/dist/model/catalog.js +6 -33
- package/dist/model/descriptor.d.ts +51 -0
- package/dist/model/descriptor.js +83 -0
- package/dist/model/models.d.ts +0 -3
- package/dist/model/models.js +3 -5
- package/dist/model/native-blocks.js +1 -1
- package/dist/model/pi-model.d.ts +16 -5
- package/dist/model/pi-model.js +86 -105
- package/dist/openapi.json +866 -1218
- package/dist/reads/cursor.js +3 -1
- package/dist/record/append.d.ts +34 -2
- package/dist/record/append.js +50 -1
- package/dist/record/environment.d.ts +2 -0
- package/dist/record/environment.js +2 -0
- package/dist/record/index.d.ts +1 -1
- package/dist/record/index.js +1 -1
- package/dist/redact.d.ts +1 -1
- package/dist/redact.js +3 -2
- package/dist/sandbox/egress-token.d.ts +3 -3
- package/dist/sandbox/egress-token.js +3 -3
- package/dist/sandbox/join.js +3 -2
- package/dist/sandbox/manager.d.ts +41 -41
- package/dist/sandbox/manager.js +112 -44
- package/dist/sandbox/placement.d.ts +1 -1
- package/dist/sandbox/placement.js +5 -8
- package/dist/sandbox/pods/client.d.ts +1 -10
- package/dist/sandbox/pods/client.js +8 -4
- package/dist/sandbox/pods/lifecycle.d.ts +19 -11
- package/dist/sandbox/pods/lifecycle.js +45 -23
- package/dist/sandbox/pods/network-gate.d.ts +4 -5
- package/dist/sandbox/pods/network-gate.js +7 -7
- package/dist/sandbox/pods/reconcile.js +4 -1
- package/dist/sandbox/pods/spec.js +8 -5
- package/dist/sandbox/policy.d.ts +7 -1
- package/dist/sandbox/policy.js +10 -3
- package/dist/sandbox/resolve.d.ts +8 -3
- package/dist/sandbox/resolve.js +12 -2
- package/dist/sandbox/setup.d.ts +3 -1
- package/dist/sandbox/setup.js +34 -11
- package/dist/sandbox/share.d.ts +5 -14
- package/dist/sandbox/share.js +5 -34
- package/dist/sandbox/skills.d.ts +7 -13
- package/dist/sandbox/skills.js +16 -31
- package/dist/sandbox/tenant-config.d.ts +2 -2
- package/dist/sandbox/tenant-config.js +4 -3
- package/dist/sandbox/tools.d.ts +7 -1
- package/dist/sandbox/tools.js +26 -26
- package/dist/sandbox/types.d.ts +10 -3
- package/dist/sandbox/types.js +9 -0
- package/dist/store/postgres/connect.d.ts +6 -5
- package/dist/store/postgres/connect.js +14 -11
- package/dist/store/postgres/control.js +13 -13
- package/dist/store/postgres/drizzle/0028_artifact_write_keys.sql +2 -0
- package/dist/store/postgres/drizzle/0029_protocol_15.sql +11 -0
- package/dist/store/postgres/drizzle/0030_protocol_15_runtime_block.sql +11 -0
- package/dist/store/postgres/drizzle/0031_protocol_15_mcp_snapshot.sql +8 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +28 -0
- package/dist/store/postgres/migrate.js +1 -1
- package/dist/store/postgres/reads.js +10 -2
- package/dist/store/postgres/schema.d.ts +19 -0
- package/dist/store/postgres/schema.js +7 -0
- package/dist/store/postgres/store.js +55 -26
- package/dist/store/types.d.ts +17 -7
- package/dist/streams/relay/core.d.ts +3 -3
- package/dist/streams/relay/core.js +9 -10
- package/dist/tenant/advance.js +21 -31
- package/dist/tenant/commands.js +9 -16
- package/dist/tenant/context.d.ts +14 -17
- package/dist/tenant/definition-files.d.ts +25 -4
- package/dist/tenant/definition-files.js +85 -47
- package/dist/tenant/effects.js +9 -36
- package/dist/tenant/environment-manifests.js +9 -1
- package/dist/tenant/environments.d.ts +0 -2
- package/dist/tenant/environments.js +54 -30
- package/dist/tenant/ephemeral.d.ts +1 -1
- package/dist/tenant/ephemeral.js +2 -1
- package/dist/tenant/history.d.ts +1 -1
- package/dist/tenant/history.js +1 -1
- package/dist/tenant/host-token.d.ts +3 -3
- package/dist/tenant/host-token.js +12 -11
- package/dist/tenant/http.d.ts +5 -8
- package/dist/tenant/http.js +9 -0
- package/dist/tenant/identity-file.d.ts +24 -1
- package/dist/tenant/identity-file.js +35 -7
- package/dist/tenant/issuers.d.ts +5 -5
- package/dist/tenant/issuers.js +31 -23
- package/dist/tenant/jwt.d.ts +8 -2
- package/dist/tenant/jwt.js +10 -2
- package/dist/tenant/limits.d.ts +90 -0
- package/dist/tenant/limits.js +175 -0
- package/dist/tenant/module.d.ts +4 -1
- package/dist/tenant/module.js +9 -8
- package/dist/tenant/outbound.d.ts +17 -19
- package/dist/tenant/outbound.js +18 -21
- package/dist/tenant/run-grants.js +3 -2
- package/dist/tenant/run-token.d.ts +0 -4
- package/dist/tenant/run-token.js +6 -11
- package/dist/tenant/runtime-limits.d.ts +24 -0
- package/dist/tenant/runtime-limits.js +27 -0
- package/dist/tenant/runtime.js +30 -43
- package/dist/tenant/session-streams.js +7 -6
- package/dist/tenant/session.d.ts +1 -1
- package/dist/tenant/session.js +1 -1
- package/dist/tenant/sessions.js +32 -29
- package/dist/tenant/signing-keys.d.ts +1 -1
- package/dist/tenant/signing-keys.js +5 -6
- package/dist/tenant/status.js +4 -3
- package/dist/tenant/streams.js +18 -20
- package/dist/tenant/sweep.d.ts +1 -21
- package/dist/tenant/sweep.js +39 -48
- package/dist/tenant/transcript.d.ts +70 -23
- package/dist/tenant/transcript.js +28 -22
- package/dist/tenant/types.d.ts +11 -16
- package/dist/tenant/worker.d.ts +2 -10
- package/dist/tenant/worker.js +5 -14
- package/dist/traces/ids.js +5 -1
- package/dist/traces/map.d.ts +9 -6
- package/dist/traces/map.js +9 -11
- package/dist/traces/otlp.d.ts +3 -3
- package/dist/traces/otlp.js +5 -3
- package/dist/traces/projector.d.ts +9 -4
- package/dist/traces/projector.js +13 -7
- package/dist/traces/read.js +6 -1
- package/dist/tuning.d.ts +383 -0
- package/dist/tuning.js +658 -0
- package/dist/vault/headers.js +4 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/dist/artifacts/export.d.ts +0 -8
- package/dist/artifacts/export.js +0 -204
- package/dist/artifacts/media-types.d.ts +0 -30
- package/dist/artifacts/media-types.js +0 -137
- package/dist/artifacts/workspace.d.ts +0 -60
- package/dist/artifacts/workspace.js +0 -45
- package/dist/media.d.ts +0 -10
- package/dist/media.js +0 -58
- package/dist/sandbox/runtime-tools.d.ts +0 -9
- package/dist/sandbox/runtime-tools.js +0 -16
- package/dist/sandbox/session-sandbox.d.ts +0 -16
- package/dist/sandbox/session-sandbox.js +0 -77
- package/dist/tenant/artifact-tool.d.ts +0 -13
- package/dist/tenant/artifact-tool.js +0 -243
- package/dist/tenant/skill-tool.d.ts +0 -20
- package/dist/tenant/skill-tool.js +0 -67
- package/dist/tenant/tool-results.d.ts +0 -57
- package/dist/tenant/tool-results.js +0 -298
- package/dist/tenant/tool-search.d.ts +0 -39
- package/dist/tenant/tool-search.js +0 -103
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,174 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.27.0-beta
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 0a2fbc5: **Artifacts reach the harness through the Harness API; `read_artifact` and `save_artifact` run in the harness (protocol 15, Harness API 4).** The first step of the harness boundary: model-facing work belongs to the harness, and the Runtime offers primitives and holds limits and access. A fresh start for agent sessions: the Runtime speaks protocol 15 only. See MIGRATION.md.
|
|
8
|
+
|
|
9
|
+
- **The artifact seam.** A harness reads and writes the artifacts of the run it holds: `artifact.read {artifactId, version?, offset?, length?}` answers the version's metadata (`ArtifactMetaSchema`) and its bytes from `offset`, at most `turn.start.limits.chunkBytes`; `artifact.write` (`begin`, `chunk`, `commit`, `abort`) makes a file artifact of the session or a new version of one of its own, streamed with backpressure into the Object store and committed in Postgres within the Tenant's and the Environment's artifact limits. The scope is always the run's session: its own artifacts, and the Tenant-wide ones its messages named; anything else is the new error code `not_found`, alike. A write's `key` makes it idempotent within the session (`artifact_versions.write_key`, migration 0028), and its `effectId` links the artifact to a tool call of the turn, whose call id `artifact.created` carries. An upload the run leaves open commits nothing. Client helpers: `readArtifact`, `openArtifactWrite`, `writeArtifactBytes`, `toBase64` and `fromBase64` in `@nylorun/core/harness-api`.
|
|
10
|
+
- **Our harness runs the artifact tools.** `read_artifact` (every agent) and `save_artifact` (with a sandbox) are our engine's tools, defined in `@nylorun/harness` (`artifactToolsFor`, `runArtifactTool`) and run over the seam and the run's sandbox files (`HarnessExecutors.files`, `SandboxManager.writeBytes`); their calls are kind `harness`. `save_artifact` keys its write by its effect id. `read_artifact` takes `path` with a sandbox, which copies the whole artifact into it, and hands a file of any other type to the model as a file of the result (the Model Gate writes the note for one the model does not read; `artifact.unsupported` is gone). Its page is harness configuration, `createHarness({ artifactPageBytes })` (32 KiB by default), and now always ends on a whole character. `runDurable` takes `engineTools`; `apiHost` takes the engine's configuration.
|
|
11
|
+
- **The Runtime pins no artifact tools.** `runtimeManifestFor` has no `save` or `read`; `RUNTIME_TOOL_NAMES` no longer holds the two names, so an author tool may take one (our harness then refuses the turn). A session without a sandbox or skills pins its definition unchanged. Core no longer runs either tool (`tenant/artifact-tool.ts` is gone). Migration 0029 closes every agent session that pinned them (`closedReason: "protocol_15"`, `409 session_closed`); workflow sessions carry over.
|
|
12
|
+
- **Media types are core's.** `contentTypeFor`, `essence`, `normalizeContentType`, `isText`, `isModelImage`, `modelInputOf`, `inputLabel`, `extensionFor`, `unreadableReason`, `MODEL_IMAGE_TYPES` and `DEFAULT_CONTENT_TYPE` are exported from `@nylorun/core/contracts`, for the Runtime and harnesses alike.
|
|
13
|
+
- `PROTOCOL_VERSION` 15 with required feature `harness-boundary`; `HARNESS_API_VERSION` 4. The SDKs and the CLI send protocol 15.
|
|
14
|
+
|
|
15
|
+
- ebe7348: **The harness decides how files reach the model; the Model Gate only fetches and translates (protocol 15).** The second step of the harness boundary, still protocol 15 and Harness API 4. See MIGRATION.md.
|
|
16
|
+
|
|
17
|
+
- **Any file may be sent.** A message naming a file the model does not read is accepted: `422 attachment_unsupported` and its error code are gone, and AG-UI and A2A accept such files too. Files are still held to the artifact size limits at upload.
|
|
18
|
+
- **`turn.start.model`** is the model descriptor (`ModelDescriptorSchema`): the provider, id, inputs, context window and output limit of the model the turn's calls use, absent for flows and without a model. One resolution (`model/descriptor.ts`) serves it, the catalog's inputs and the gate.
|
|
19
|
+
- **Our engine shows each file.** An image or document the model reads goes as its artifact reference, a text file is read over the artifact seam and inlined as a `<file>` block, and anything else (past `modelFileBytes`, a kind the model does not read) is a note it writes. `fileView`, `representFiles`, `fileBlock`, `fileNote` and `mediaReferenceLine` (moved from `@nylorun/core/define`) are exported from `@nylorun/harness`. A budget from the descriptor bounds the prompt before the first answer, and compaction counts files as the model gets them.
|
|
20
|
+
- **The Model Gate refuses instead of writing notes.** A text file as a media part, or a kind the model or its API does not read, fails the call with the new model failure code `unsupported_input`; a reference it cannot fetch fails `invalid_request`. Nothing is sent, and neither is retried.
|
|
21
|
+
- **Structured answers are the engine's.** `ModelCall.outputSchema` is removed: our engine writes the JSON instruction and parses the answer (fenced, with control characters repaired; `parseJsonWithRepair` ported from pi-ai). `message.assistant` for a structured answer now carries its JSON text.
|
|
22
|
+
- **`read_artifact`** refuses a file the turn's model does not read (`artifact.unsupported`, with the reason).
|
|
23
|
+
- `unreadableReason` is removed; `isOffice` joins the media type helpers in `@nylorun/core/contracts`.
|
|
24
|
+
- Studio's file picker accepts every file, and the refusal chips are gone.
|
|
25
|
+
|
|
26
|
+
- ff6470e: **The harness writes the model's instructions and defines the sandbox and skill tools; no `runtime` block (protocol 15).** The third step of the harness boundary, still protocol 15 and Harness API 4. See MIGRATION.md.
|
|
27
|
+
|
|
28
|
+
- **No `runtime` block.** The Runtime no longer pins model-facing text or tools on a session's manifest: a session pins its definition as registered (`manifestHash` equals `definitionHash`) and keeps its sandbox spec on the session. The manifest schema refuses `runtime` with what replaces it (`REMOVED_MANIFEST_FIELDS`). `runtimeManifestFor`, `runtimeToolOf`, `RuntimeManifest`, `RUNTIME_TOOL_NAMES`, `isRuntimeToolName`, `createSandboxTools`, `SANDBOX_INSTRUCTIONS`, the skill tool names, `isSkillTool`, `SKILLS_USAGE`, `formatSkillCatalog` and `skillOfToolCall` leave `@nylorun/core/define`; `RUNTIME_PART_ID` is `SESSION_PART_ID` (`"session"`), and `agentFrom` takes `sessionInstructions`. `@nylorun/agents` no longer re-exports the skill catalog helpers. Migration 0030 closes the agent sessions that still pinned a `runtime` block (`closedReason: "protocol_15"`).
|
|
29
|
+
- **`turn.start` states facts.** `environment` (`TurnEnvironmentSchema`: `{id, kind, sandbox?: {workspace}}`) and `routing.sandbox.spec` (the pinned spec) join the agent's `skills`.
|
|
30
|
+
- **Our engine words them.** `@nylorun/harness` writes the skill catalog, the sandbox note and the skills' folder note, and defines the six sandbox tools, `load_skill` and `read_skill_resource`, in the order and bytes the `runtime` block had, so the prompt's prefix is unchanged (`engineToolsFor`, `sandboxTools`, `sandboxInstructions`, `skillCatalogText`, `skillFolderNote`, `skillTools`, all exported for a harness of your own). The skill tools run in the harness over `definition.file` (`runSkillTool`), and core no longer runs them (`tenant/skill-tool.ts` is gone). The sandbox tools' limits are harness configuration (`createHarness({ sandboxTools })`, `harnessExecutors({ sandboxTools })`, `DEFAULT_SANDBOX_TOOL_LIMITS`), as is the most a skill read takes into the context (`createHarness({ skillReadBytes })`, 10 MiB by default), held to the run's `limits.recordEntryBytes`.
|
|
31
|
+
- **Effects name their target.** A tool effect carries `target: {kind: "mcp" | "http" | "sandbox" | "harness" | "platform"}` (`EffectTargetSchema`) and may carry `skill`; the record routes by the kind, never by the tool's name, and a call without a target or one the session lacks is `tool.unavailable`. `hello.features.tools` and `NativeToolSchema` are removed, no tool name is reserved, and the record keeps the skill the intent names when the agent has it. A skill tool's `tool.completed` is `kind: "harness"` (it was `platform`).
|
|
32
|
+
- **Studio** drops the manifest panel's Runtime section: it shows the sandbox tools when the session's Environment has a sandbox.
|
|
33
|
+
|
|
34
|
+
- f443475: **The harness builds the MCP tool list and shapes tool results; tools are identified by server and tool (protocol 15).** The fourth step of the harness boundary, still protocol 15 and Harness API 4. See MIGRATION.md.
|
|
35
|
+
|
|
36
|
+
- **Tools have an identity.** An MCP tool call's target is `{kind: "mcp", server, tool}` (the server's own name for the tool) and an HTTP tool call's `{kind: "http", tool}` (its declared name); `platform` is gone. `toolName` is the model's name, for display. The record checks an MCP call against the session's discovery (`tool.unknown`) and the turn's tool settings (`tool.disabled`), and `tool.completed`, tool-call rows (`tool`), approvals (`Approve server / tool?`, `interaction.tool`) and traces (`nylorun.tool.identity`) carry the identity. The Tool Gate matches a call to its journaled target.
|
|
37
|
+
- **Tool policy keys on identity.** A rule's `tool` is the tool's identity, never the model's name. A rule whose `tool` has `__` in it is refused at `PUT /v1/tenant/tool-policy`; a stored one makes the policy unreadable, so every call is denied (and `GET` answers `409`) until the policy names the tool by `server` and `tool`.
|
|
38
|
+
- **`turn.start.mcp` states facts.** The session pins what its servers listed, raw (`McpSnapshot` v2: servers, scrubbed instructions, tools as named); each turn gets `mcp` (`McpFactsSchema`: every tool with `enabled` and the manifest's `deferred` hint) in place of `sessionTools` and `routing.mcpSnapshot`, and `session.mcp` answers `{mcp}`. `mcp.discovered` has no `renamed` or `deferred`. Migration 0031 closes the sessions that pinned the former snapshot (`closedReason: "protocol_15"`).
|
|
39
|
+
- **Our engine names, defers and searches.** `@nylorun/harness` names MCP tools (`mcpToolName`, `mcpToolNames`, within the 64-character provider ceiling), defers them by the manifest's setting or the model's window and pins that layout in its state (`mcpToolSet`, `McpLayout`), and runs `tool_search` (BM25) itself; core's `tool_search`, `deferredToolsTools`, `TOOL_SEARCH_TOOL` and `TOOL_CALL_TOOL` leave `@nylorun/core/define`, and `runDurable` takes `mcp` instead of `sessionTools`.
|
|
40
|
+
- **Our engine shapes tool results.** Core no longer stores large or binary tool results: the record refuses an outcome past `limits.recordEntryBytes` (`limit_exceeded`). Our engine spills them with `artifact.write`, keyed by the call and its bytes (`spillKey`), with a preview, an image as a file for a model that reads images, and one budget per step (`shapeToolOutcome`, `StepBudget`, exported for a harness of your own). The Tool Gate still scrubs credentials and refuses answers past `limits.toolAnswerBytes`.
|
|
41
|
+
- **Harness configuration.** `createHarness({ mcpTools, toolResults })` sets the deferral share, characters per token, fallback window, the note's instruction length, `tool_search`'s limits, the inline cap, preview head and tail, step budget, stub, small size and entry envelope (`DEFAULT_MCP_TOOL_CONFIG`, `DEFAULT_TOOL_RESULT_CONFIG`).
|
|
42
|
+
- **The MCP preview** names tools as Nylorun's engine would (`modelName`, `renamed`) and shows a server's instructions uncut.
|
|
43
|
+
- **Studio** shows an MCP tool as `server / tool` in tool and approval cards, with the model's name, and links the artifacts a tool's result was stored in.
|
|
44
|
+
- **`examples/harness-minimal`** spills a large `bash` output with `artifact.write` and keeps a preview; its README shows how a harness of your own offers MCP tools.
|
|
45
|
+
|
|
46
|
+
- cf425c6: **The harness mounts skills and saves outputs; the in-process harness uses the gates; compaction is a transcript edit (protocol 15).** The fifth step of the harness boundary, still protocol 15 and Harness API 4. See MIGRATION.md.
|
|
47
|
+
|
|
48
|
+
- **Skill folders are our engine's.** Before each sandbox call our engine mounts each skill version of the turn's tree at `/skills/<name>@<hash>/` with `executors.files.mount`, reading the bytes over `definition.file`; the SandboxManager only writes them (`mountFolder`), once per open sandbox (`present` after). `SandboxManager.mountSkills`, its `definitionFile` port and `SandboxSessionRef.manifest` are gone, and the operator sandbox route mounts nothing.
|
|
49
|
+
- **The outputs folder is our engine's (Q5).** At a completed turn's end in a sandbox our engine saves `/workspace/outputs` as the session's `outputs` folder before `turn.completed`, over the new folder mode of `artifact.write` (`kind: "folder"`, `file`, chunks named by hash, `unchanged`, `refused`). Core takes every byte, checks each file's hash before content is stored under it, dedupes, and keeps the content epoch and quotas. Versions say `source: "engine"`; `artifact.export.skipped` and `artifact.export.failed` are harness claims. Core's export (`artifacts/export.ts`, the `WorkspaceReader`, `workspace.read` listing and bytes calls) is removed.
|
|
50
|
+
- **No limit literals.** The new Runtime limit `folderEntries` (10,000; a count, its ceiling from the manifest's one string) replaces `EXPORT_MAX_FILES`, and `createHarness({ outputs: { dir, maxBytes } })` (`/workspace/outputs`, 1 GiB) replaces `EXPORT_MAX_BYTES`. `RUNTIME_LIMIT_CEILINGS` entries are `{value, unit, why}`.
|
|
51
|
+
- **In-process parity.** Every model call goes through the Model Gate: a scripted model is served by `providerModelGate`, metered like any. The MCP pool opens every server through the Tool Gate (`openRemote` is required; the in-process gate's `openMcp` finds the server in the session's pinned manifest and authorizes it with the vault). `ModelRoute` is `{tenantId, modelGate}`; `TenantContext.modelProvider`, `useVaultModel` and `workspaces` are gone.
|
|
52
|
+
- **Compaction is a transcript edit (Q4).** Summary calls say `purpose: "summary"` (no `message.assistant`), and the segment's edit that replaced the history says `kind: "compaction"` with its facts and summary calls (`CompactionFactsSchema`, `transcriptUpdates(..., compaction)`). Core checks the calls and writes one `context.compacted`, which loses `partial`.
|
|
53
|
+
|
|
54
|
+
- dc75e58: **Host timings, retries and engine settings are configuration with defaults (B15).** Still protocol 15 and Harness API 4. See MIGRATION.md and DEPLOYMENT.md ("Host tuning").
|
|
55
|
+
|
|
56
|
+
- **Host tuning.** The Runtime processes' timeouts, retries, poll intervals and internal sizes are one typed schema with a default each (`HostTuningSchema`, `runtime/server/src/tuning.ts`): keys, the Harness API, the API's streams, the Host, the Object store, the Tenant, its sweep, Durable Session Execution, Restate, Postgres, Durable Streams and the relay, the gates, egress-gate, sandbox pods, harnesses and traces. An operator sets any part in `NYLORUN_TUNING` (JSON), parsed with the stack configuration and read once at start; every default is the value before. An unknown key or a value past its ceiling (Node's longest timer, S3's part sizes, S2's batch, the sandboxes service's wait) stops the process naming the key. Core hands a sandbox pod's engine the `harness` and `engine` groups the operator set. `nylorun start` passes `NYLORUN_TUNING` to the runtime, gateway and harness containers.
|
|
57
|
+
- **Our engine's loop is configuration.** `createHarness` takes `compaction` (`CompactionConfig`, `DEFAULT_COMPACTION_CONFIG`: the kept tail, the reply's reserve, the estimate), `partialOutputChars` (a failed agent-as-tool's output its parent sees), `resendDelaysMs` and `leaseRetryMs`; `runDurable` takes `loop` (`LoopConfig`), which an invocation hands its agents used as tools. `EngineToolConfig` is `EngineConfig`. The Runtime's harness host passes the tuning's `engine` group to `createHarness`.
|
|
58
|
+
- **Kept as constants**, each justified where it is defined: Node's longest timer, S3's part sizes and object key, S2's batch, the sandboxes service's longest wait and pod variable, the `environment.egress` event's 16 running turns, W3C's 512-character `tracestate`, and the 24-hour floor of a wake's dedupe key.
|
|
59
|
+
|
|
60
|
+
- 23774c4: **The last hard-coded limits are configuration (harness boundary B15c).** Still protocol 15 and Harness API 4. Every default is the value before. See MIGRATION.md, and DEPLOYMENT.md's Runtime limits and Host tuning.
|
|
61
|
+
|
|
62
|
+
- **21 more Runtime limits** (`GET`/`PUT /v1/tenant/limits`): a message's parts (`messageParts`), page sizes (`pageItems`, `exportPageItems`, `environmentEventItems`; a page asked larger holds that many), labels (`artifactLabels`, `labelKeyChars`, `labelValueChars`), a manifest's setup command, descriptions and secret hosts (`setupCommandChars`, `manifestDescriptionChars`, `secretDescriptionChars`, `secretHosts`), a failed pod's reason (`setupReasonChars`, `setupCommandExcerptChars`), secret values (`secretValueChars`), the tool policy and budgets (`toolRules`, `toolRuleFieldChars`, `toolRuleTextChars`, `modelBudgets`) and flows (`flowConcurrency`, `flowMapItems`, `flowLoopIterations`, replacing the `NYLORUN_FLOW_*` variables no Host read). Request schemas lose these maxima; the Runtime checks the Tenant's.
|
|
63
|
+
- **More Host tuning** (`NYLORUN_TUNING`): token lifetimes and clock tolerance (`keys.*`), the advance deadline and grace (`execution.*`), `nylorun-operate`'s waits, the credential store's lock, sweep arming, Postgres batches and the replication pool, a basin repair's log cadence, egress sockets, the engine poll and sandbox memory floor, MCP listing pages and diagnostics, sandbox helper commands, the scrub threshold, exec event and local stream sizes; and in the engine, `flowValueChars` and `toolResults.minPreviewBytes`.
|
|
64
|
+
- **The CLI's own waits are `NYLORUN_CLI_TUNING`**: `nylorun start`'s waits and polls, the Compose healthchecks and WAL cap, and `nylorun local sandbox`'s waits.
|
|
65
|
+
- **Studio follows the Runtime's limits**: no upload cap of its own, the Tenant's `requestBodyBytes` read for a write it parses past the default (`@nylorun/agents` exports `RUNTIME_LIMIT_DEFAULTS`), no CPU cap in its form.
|
|
66
|
+
- **Kept, each justified where it is defined**: Linux's `MAX_ARG_STRLEN` (a setup command's ceiling) and `PATH_MAX` (a link target), a model-facing tool name's 64 characters, RFC 6838's media type length, Postgres's 65,535 bind parameters, a tmpfs page, and identifier grammars (the protocol's).
|
|
67
|
+
|
|
68
|
+
- b1e815d: **Runtime limits are a Tenant setting, and harnesses get them in `turn.start.limits`.**
|
|
69
|
+
|
|
70
|
+
- What one record entry, model call, model file, tool answer, custom harness state and Harness API chunk may hold is the new Management API setting `GET`/`PUT /v1/tenant/limits` (`{ limits: { recordEntryBytes, modelCallBytes, modelFileBytes, toolAnswerBytes, harnessStateBytes, chunkBytes } }`), also `admin.settings.limits` and `nylorun tenant settings limits [get | put <file|->]`.
|
|
71
|
+
- The defaults are today's sizes (`RUNTIME_LIMIT_DEFAULTS`): 960 KiB, 32 MiB, 8 MiB, 8 MiB, 256 KiB and 16 MiB. A limit left out of a `PUT` takes its default.
|
|
72
|
+
- Each limit has a ceiling a dependency sets (`RUNTIME_LIMIT_CEILINGS`): S2's 1 MiB record less 64 KiB for the event's envelope, the 64 MiB Harness API frame, the longest JavaScript string. A limit above its ceiling is `400`, naming the ceiling.
|
|
73
|
+
- Each is read from the Tenant's database where it is checked; nothing keeps it.
|
|
74
|
+
- **The record holds every write to `recordEntryBytes`.** An event whose payload, or an effect outcome whose value, is larger, whoever wrote it, is refused with `limit_exceeded`: `413` (`details.limit: "recordEntryBytes"`) to an API client, the new Harness API error code `limit_exceeded` to a harness. A harness's claimed event past it is refused rather than dropped. Before, such an event reached a record S2 could not take.
|
|
75
|
+
- **The gates read the setting.** The Model Gate refuses a body past `modelCallBytes` and a file past `modelFileBytes`; the Tool Gate keeps no MCP or HTTP answer past `toolAnswerBytes` (`mcp.too-large`, `http.too-large`) and reads no tool body past it. A custom harness's state past `harnessStateBytes` fails its turn with `limit_exceeded` (it was `invalid`), and a `definition.file` range longer than `chunkBytes` is `limit_exceeded`. Core's step budget for tool results is unchanged (256 KiB), or half `recordEntryBytes` when that is less.
|
|
76
|
+
- **`turn.start` carries `limits`** (`RuntimeLimitsSchema`), the limits in force when the segment started. Harness API 3 and protocol 14 are unchanged, but `TurnStartSchema` is strict: a harness built against an older `@nylorun/core` refuses a `turn.start` with `limits`, so upgrade a custom harness with the Runtime. Our harness asks for skill files `limits.chunkBytes` at a time, and holds MCP answers on its own connections to `limits.toolAnswerBytes`. `createHarness` takes `onStart(grant, start)`.
|
|
77
|
+
- **Removed exports:** `MAX_MODEL_CALL_BYTES`, `MAX_TOOL_BODY_BYTES`, `MAX_HARNESS_STATE_BYTES` and `DEFINITION_FILE_CHUNK_BYTES` from `@nylorun/core`. Added: `RuntimeLimitsSchema`, `RUNTIME_LIMIT_DEFAULTS`, `RUNTIME_LIMIT_CEILINGS`, `runtimeLimitsOf`, `runtimeLimitIssues`, `limitExceededMessage`, `S2_RECORD_MAX_BYTES`, `RECORD_ENVELOPE_RESERVE_BYTES`, `JS_STRING_MAX_LENGTH` and the `TenantLimits*` schemas.
|
|
78
|
+
|
|
79
|
+
- f2e9b0a: **Skill and artifact limits are set per Tenant and per Environment manifest; a skill holds up to 2 GiB by default, with no limit per file or on the number of files.**
|
|
80
|
+
|
|
81
|
+
- The 10 MiB limit per skill file and the 500-file limit are gone. A skill's files may hold up to the Tenant's skill limit together: 2 GiB by default (`SKILL_TOTAL_BYTES_DEFAULT`). A file at two paths counts twice, since a sandbox holds both copies. `SKILL_FILES_MAX` and `DEFINITION_FILE_MAX_BYTES` are no longer exported.
|
|
82
|
+
- The Tenant's skill limit is the new Management API setting `GET`/`PUT /v1/tenant/skills` (`{ limits: { totalBytes } }`), also available as `admin.settings.skills` and `nylorun tenant settings skills [get | put <file|->]`.
|
|
83
|
+
- `PUT /v1/files/sha256:<hex>` takes a file up to that limit.
|
|
84
|
+
- `PUT /v1/agents/{id}` refuses a skill over it, an agent used as a tool included: `413 limit_exceeded`, with `details.skills` listing each skill and its size.
|
|
85
|
+
- An environment manifest, or the inline fields of `PUT /v1/environments/{id}`, may set `limits`: `artifacts.fileBytes`, `artifacts.totalBytes` and `skills.totalBytes`. Like the manifest's other fields, they are fixed for the Environment's life.
|
|
86
|
+
- Each limit must be at most the Tenant's. A higher one is refused with `400` when the Environment is made or the manifest is saved.
|
|
87
|
+
- A limit left out is the Tenant's at the time it is checked. A Tenant that lowers a limit lowers it for every Environment.
|
|
88
|
+
- The Environment view's new `limits` field gives the limits in force.
|
|
89
|
+
- An Environment's artifacts are its sessions' artifacts and its disk versions. Uploads, `save_artifact`, turn-end exports and disk snapshots hold them to the Environment's per-file limit and to its own total, as well as to the Tenant's total. A turn-end export past the Environment's total is skipped with the new reason `environment_total`, and a disk snapshot past it is `413` with `details.limit: "environment_total"`.
|
|
90
|
+
- A session opens on an Environment only when its agent's skills fit the Environment's skill limit; otherwise it is `409 environment_unsuitable`, with `details.skills`.
|
|
91
|
+
- `PUT /v1/files` streams the body to the Object store instead of holding it in memory. Only bytes that match the named hash reach the file's key. Environment files named by hash are held to the same per-file maximum.
|
|
92
|
+
- `@nylorun/agents`: loading a skills folder no longer checks a size, since the limit is the Tenant's; the Runtime refuses an oversized skill. The `skills.file-too-large` and `skills.too-many-files` errors are gone. Files are hashed and read a chunk at a time.
|
|
93
|
+
- Sandboxes get skill files as a stream. A harness fetches them from core 16 MiB at a time: `definition.file` takes optional `offset` and `length` (at most the Runtime limit `chunkBytes`).
|
|
94
|
+
- `load_skill` and `read_skill_resource` read files of up to 10 MiB into the model's context. A larger file fails with `skill.resource_too_large`, and the error names the file's path in the sandbox when there is one.
|
|
95
|
+
|
|
96
|
+
- 6772612: **The remaining request, upload, token and sandbox limits are Tenant settings (harness boundary B15).** Still protocol 15 and Harness API 4. See MIGRATION.md and DEPLOYMENT.md's Runtime limits.
|
|
97
|
+
|
|
98
|
+
- **27 more Runtime limits** in `GET`/`PUT /v1/tenant/limits`, each with today's value as its default and a ceiling from a dependency (a JavaScript string or timer, a request read as one string, a Harness API frame, a JavaScript number): request bodies and inline files (`requestBodyBytes`, `inlineFileBytes`), `a2aWaitMs`, `errorExcerptChars`, `traceContentBytes`, an Environment's labels, setup and input files (`environmentLabels`, `environmentSetupCommands`, `environmentFiles`, `environmentFilesPerEntry`, `environmentSecretSlots`, `setupCommandMs`, `setupOutputChars`), disk versions (`diskVersionEntries`, `diskVersionBytes`, `diskLeaseMs`, `diskPodWaitMs`; an Environment's manifest may lower the first two with `limits.disk`), model calls (`modelRequestMs`, `modelIdleMs`, `modelAttempts`, `modelRetryDelayMs`, `modelProviderRetries`, `modelRetryDelayMaxMs`, read by the gates for each call) and tools (`toolAttempts`, `httpToolTimeoutMs`, `mcpPreviewMs`, `mcpMetadataBytes`, and the new `mcpSnapshotBytes`: what a session pins of its MCP servers' tools and instructions, past which a server is left out with a diagnostic).
|
|
99
|
+
- **Schema maxima are checked against the Tenant's limits**: an Environment's labels, setup commands, input files, files per entry, secret slots and setup timeout, and an HTTP tool's `timeoutMs` (at deploy and at each call). `limits.environments` and `lifecycle.stopGrace` lose their arbitrary caps; an identity file's issuer takes any number of grants and `jwksFetch` settings.
|
|
100
|
+
- **`turn.start.limits` carries only a harness's limits** (`HarnessLimitsSchema`, `harnessLimitsOf`), and a harness drops one it does not know. `transcriptUpdates` takes `recordEntryBytes` and fills each event up to it; `CHUNK_BYTES` is gone.
|
|
101
|
+
- **Constants a dependency or a standard fixes stay, named for it**: a token is read up to Node's `http.maxHeaderSize`; artifact names and folder paths keep `FILE_NAME_MAX` (255) and `FILE_PATH_MAX` (1,024); a skill file's path is what `FILE_PATH_MAX` leaves under its mount folder; `tracestate` keeps W3C's 512.
|
|
102
|
+
- **Removed**: `ENVIRONMENT_LABELS_MAX`, `ENVIRONMENT_SETUP_MAX`, `ENVIRONMENT_SETUP_TIMEOUT_MAX_MS` (now `ENVIRONMENT_SETUP_TIMEOUT_DEFAULT`), `ENVIRONMENT_FILES_MAX`, `ENVIRONMENT_SECRET_SLOTS_MAX`, `TOKEN_ENVIRONMENT_GRANTS_MAX`, `HTTP_TOOL_MAX_TIMEOUT_MS`, `READ_ARTIFACT_MAX_BYTES` and `CHUNK_BYTES` from `@nylorun/core`; the image checks (`decodeImageBase64`, `validateImageBytes`, `IMAGE_MEDIA_TYPES`, `MAX_IMAGE_BYTES`), the Tenant configuration's `modelCall` and `TrustedIssuersOptions`' `refetchMs`/`maxAgeMs` from `@nylorun/runtime`. Studio's Environment form no longer caps setup commands and input files at 16: the Runtime checks the Tenant's limit.
|
|
103
|
+
|
|
104
|
+
### Patch Changes
|
|
105
|
+
|
|
106
|
+
- 8715ad8: The fixture model reads its `fixture:*` script in a turn that carries a file. Our harness ends such a turn with a user message listing the files (`FILES_MESSAGE_HEADER`, now exported by `@nylorun/harness`), and the fixture model read that message instead: it answered "I remember: …" and called no tool. It now skips that message, for the script and for the tool result it answers after.
|
|
107
|
+
- 06940f5: The Model Gate reads only the files a session may read: its own artifacts and the Tenant-wide ones its messages named, as `read_artifact` does. Before, a model call could name any Tenant-wide artifact and the gate sent its bytes to the provider.
|
|
108
|
+
- 0f3836f: A pod Environment pins its image by digest only when the digest is of the repository it asked for. kind names an image it loads onto a node `import-<date>`, and the Runtime pinned `docker.io/library/import-<date>@sha256:…`, which no registry serves: the next pod failed with `ErrImagePull`.
|
|
109
|
+
- b8b5b8c: **The trace projector's status counts the batch it is posting.** `pendingTxs` now includes the transactions of a post in flight, which are not acknowledged until it settles; it said `0` while one was still being retried.
|
|
110
|
+
- 2459430: **An `environment_secret` reads `nylorun_managed` in the sandbox instead of `nylorun-managed`, so CLIs that check a token's format send their requests.**
|
|
111
|
+
|
|
112
|
+
- The Vercel CLI refuses a `VERCEL_TOKEN` with any character outside letters, digits and `_` (`Must not contain: "-"`) and exits before egress-gate can set the header. `ENVIRONMENT_SECRET_SENTINEL` is now `nylorun_managed`.
|
|
113
|
+
- egress-gate never compares the value: it replaces the credential's header whatever the CLI sent, so nothing else changes. A script that checks for the literal `nylorun-managed` should check for `nylorun_managed`.
|
|
114
|
+
|
|
115
|
+
- Pin core to the tested release.
|
|
116
|
+
- Pin harness to the tested release.
|
|
117
|
+
- Updated dependencies [8715ad8]
|
|
118
|
+
- Updated dependencies [0a2fbc5]
|
|
119
|
+
- Updated dependencies [ebe7348]
|
|
120
|
+
- Updated dependencies [ff6470e]
|
|
121
|
+
- Updated dependencies [f443475]
|
|
122
|
+
- Updated dependencies [cf425c6]
|
|
123
|
+
- Updated dependencies [dc75e58]
|
|
124
|
+
- Updated dependencies [23774c4]
|
|
125
|
+
- Updated dependencies [b1e815d]
|
|
126
|
+
- Updated dependencies [2459430]
|
|
127
|
+
- Updated dependencies [f2e9b0a]
|
|
128
|
+
- Updated dependencies [6772612]
|
|
129
|
+
- Updated dependencies
|
|
130
|
+
- @nylorun/core@0.23.0-beta
|
|
131
|
+
- @nylorun/harness@0.28.0-beta
|
|
132
|
+
|
|
133
|
+
## 0.26.0-beta
|
|
134
|
+
|
|
135
|
+
### Minor Changes
|
|
136
|
+
|
|
137
|
+
- a0cf8b2: **HTTP tools take `GET` and `DELETE`, and URL path parameters.**
|
|
138
|
+
|
|
139
|
+
- `method` is `GET`, `POST` (default), `PUT`, `PATCH` or `DELETE`. `POST`, `PUT` and `PATCH` send the input as the JSON body, as before. `GET` and `DELETE` send no body: the input becomes the query string, after any query string written in the URL. An array repeats its name (`tag=a&tag=b`) and a `null` is left out.
|
|
140
|
+
- The URL's path may name input fields as `{field}`, as in `https://api.example.com/orders/{orderId}`. Each value is percent-encoded into the path and is not sent again in the body or query string. A value that is empty, `.` or `..`, or not a string, number or boolean is refused before the call is sent (`tool.invalid-input`).
|
|
141
|
+
- `http()` and the manifest contract check a tool against its input schema. Each `{field}` must be a required scalar property. For `GET` and `DELETE`, a property must not be an object and must not repeat a query parameter the URL already sets.
|
|
142
|
+
- An HTTP verifier still takes only `POST`, `PUT` or `PATCH` and a URL without `{field}` parameters, because it is sent `{ input, output, iteration }` as a body. A credential with `via` cannot serve a tool with `{field}` parameters (`http.credential`).
|
|
143
|
+
- core exports `httpToolRequest`, which maps a call's input to the request, and `httpPathParameters`. The Runtime's outbound `post()` is now `send()`, which can send a request without a body.
|
|
144
|
+
|
|
145
|
+
### Patch Changes
|
|
146
|
+
|
|
147
|
+
- 620072d: **Docs and schemas match what the CLI and the Runtime do.**
|
|
148
|
+
|
|
149
|
+
- `@nylorun/core`: the environment manifest's JSON Schema (`@nylorun/core/schemas/environment-manifest.json`) takes the CLI's `{ path, from }` `files` entry, so an editor no longer flags a manifest that `nylorun environments manifests save` accepts. The Runtime's own schema is unchanged: the CLI turns the folder into `{ path, files }` before saving. `manifest_changed` says to save without `If-Match` (`--if-match`, `ifMatch`); no command takes `--force`.
|
|
150
|
+
- Tool names, skill names and MCP server names are each unique within their kind, as the builder and the Runtime check; a tool, a skill and a server may share a name. The docs said they were unique across kinds.
|
|
151
|
+
- `harness_mismatch` is described as what it is since protocol 14: an Environment's harness is fixed for its life (fork onto a manifest version to run another), and a session's turn is refused when its Environment id was deleted and made again with another harness, or an Environment changed in place before protocol 14 applies that change.
|
|
152
|
+
- `@nylorun/agents`: the README names `nylorun environments list | delete`, not `nylorun local sandbox ls | rm`.
|
|
153
|
+
- MIGRATION.md no longer offers a tool's `approval`, removed in protocol 11, as a replacement for step middleware.
|
|
154
|
+
|
|
155
|
+
- 71edf68: egress-gate's `environment.egress` names the turns its one read saw as the connection opened: the read starts as the name resolves and the tunnel never waits for it, as the docs now say. The egress-gate event test waits for that read before it moves a turn, so it no longer fails on a slow runner.
|
|
156
|
+
- 000ff75: **READMEs and help text match protocol 14.**
|
|
157
|
+
|
|
158
|
+
- `nylorun --help` lists `environments fork`, `manifests` and `delete-version`. The package description no longer offers `nylo` as the Runtime client, and the README says nylorun depends on `@nylorun/agents` too.
|
|
159
|
+
- The READMEs name the current commands: `nylorun tenant keys`, `nylorun tenant mcp inspect`, `nylorun local logs` and `nylorun local reset`. `@nylorun/admin` says it speaks protocol 14.
|
|
160
|
+
- `@nylorun/agents`: a lost MCP or HTTP tool call is sent again with its key, then fails to the model as `tool.interrupted` (it is not left `uncertain`). Every manifest is v7. A2A takes `raw` files. A delegated agent cannot pause.
|
|
161
|
+
- `@nylorun/runtime`: the README describes protocol 14, `PUT /v1/sessions/{id}` says it answers an identical session (vaults are no longer attached), and the database-layout error names `nylorun local reset`.
|
|
162
|
+
- `@nylorun/create-agent`: `nylorun start` writes the project's keys (no key is derived any more).
|
|
163
|
+
|
|
164
|
+
- Pin core to the tested release.
|
|
165
|
+
- Pin harness to the tested release.
|
|
166
|
+
- Updated dependencies [620072d]
|
|
167
|
+
- Updated dependencies [a0cf8b2]
|
|
168
|
+
- Updated dependencies
|
|
169
|
+
- @nylorun/core@0.22.0-beta
|
|
170
|
+
- @nylorun/harness@0.27.1-beta
|
|
171
|
+
|
|
3
172
|
## 0.25.0-beta
|
|
4
173
|
|
|
5
174
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -172,11 +172,20 @@ are refused from browsers before they are looked up. The Runtime sends no CORS h
|
|
|
172
172
|
`OPTIONS` with `204` and `Allow` only: the operator's reverse proxy answers preflights
|
|
173
173
|
([DEPLOYMENT.md](../../guides/DEPLOYMENT.md#calling-the-runtime-from-browsers-and-apps)). Missing or
|
|
174
174
|
unsupported protocol → `426` before authentication, unless the request sends neither
|
|
175
|
-
`Nylorun-Protocol` nor `Authorization` (the Host serves protocol
|
|
175
|
+
`Nylorun-Protocol` nor `Authorization` (the Host serves protocol 15 only; protocol 15 moves
|
|
176
|
+
`read_artifact` and `save_artifact` to our harness, which runs them over the Harness API's
|
|
177
|
+
artifact seam, and closes every agent session that pinned them; protocol 14 adds
|
|
178
|
+
environment manifests (`/v1/environment-manifests/{name}`): an Environment is made from one
|
|
179
|
+
version and never changes what it runs (a new version reaches it through
|
|
180
|
+
`POST /v1/environments/{id}/fork`), a manifest's `secrets` declare slots and an agent's
|
|
181
|
+
`requires` is checked when a session opens; sessions on one Environment run their turns in
|
|
182
|
+
parallel, and egress connections are `environment.egress` events on the Environment's stream,
|
|
183
|
+
in no session log or trace; protocol 13 makes the
|
|
176
184
|
manifest flat, manifest 7: no `capabilities`, tools known by name, the Runtime's own tools in the
|
|
177
185
|
pinned manifest's `runtime` block and no `capabilityId` on events, tool call rows or the Harness
|
|
178
186
|
API, now 3; it closes every session opened before it; protocol 12 adds
|
|
179
|
-
model inputs
|
|
187
|
+
model inputs and `read_artifact` for every agent (its accept check, `422
|
|
188
|
+
attachment_unsupported`, left with protocol 15: the harness decides how the model sees a file),
|
|
180
189
|
and changes nothing a protocol 11 client sends; protocol 11 replaces
|
|
181
190
|
sandbox resources, the Tenant's default sandbox, inline sandboxes and user and installation
|
|
182
191
|
vaults with Environments, each one sandbox and one vault, under `/v1/environments`, and
|
|
@@ -188,9 +197,9 @@ credential_required` or `credential_invalid` with a `WWW-Authenticate: Bearer` c
|
|
|
188
197
|
token without a route's scope gets `error="insufficient_scope"`, and
|
|
189
198
|
`/.well-known/oauth-protected-resource` lists the trusted issuers (RFC 9728); protocol 8 gives keys roles, moves vaults and signing keys under `/v1/tenant` and removes
|
|
190
199
|
the Admin API, and those old paths answer `404` with no alias; protocol 7 removes subject tokens, the access policy, revocations, browser keys and
|
|
191
|
-
derived principals, whose routes answer `404`; protocol 6 adds file and folder artifacts and message `parts`; at each turn's end
|
|
192
|
-
|
|
193
|
-
`outputs` folder, read at `/v1/artifacts/{id}/versions/{n|latest}/tree`, `/files/{path}`,
|
|
200
|
+
derived principals, whose routes answer `404`; protocol 6 adds file and folder artifacts and message `parts`; at each turn's end
|
|
201
|
+
our harness saves `/workspace/outputs` of the session's sandbox as a version of its
|
|
202
|
+
`outputs` folder (over the artifact seam since protocol 15), read at `/v1/artifacts/{id}/versions/{n|latest}/tree`, `/files/{path}`,
|
|
194
203
|
`/diff?from=` and `/zip`). Clients name no Tenant (since protocol 5). A Tenant that
|
|
195
204
|
could not be opened → opaque `404` with identical body. A path or method no route serves is `404 Route not found`
|
|
196
205
|
once the caller is known.
|
|
@@ -268,11 +277,11 @@ stage) is refused. Your services are reached as tools: HTTP tools, POSTed from t
|
|
|
268
277
|
so their URLs must be reachable from it, and remote MCP servers. Each URL gets a
|
|
269
278
|
credential in the vault of the Environment a session names (`PUT
|
|
270
279
|
/v1/environments/{id}/secrets/{name}`), the operator previews an MCP server's tools
|
|
271
|
-
(`nylorun mcp inspect --environment <id>`),
|
|
272
|
-
and the manifest says which tools are enabled
|
|
273
|
-
|
|
274
|
-
person, or are refused, is the Tenant's tool policy
|
|
275
|
-
([DEPLOYMENT.md](../../guides/DEPLOYMENT.md#tool-policy)). Model gateway
|
|
280
|
+
(`nylorun tenant mcp inspect --environment <id>`),
|
|
281
|
+
and the manifest says which tools are enabled, and which to defer (a hint the harness
|
|
282
|
+
follows; [DEPLOYMENT.md](../../guides/DEPLOYMENT.md#mcp-servers-and-http-tools)). Which calls wait for a
|
|
283
|
+
person, or are refused, is the Tenant's tool policy, which names an MCP tool by `server` and
|
|
284
|
+
its own name ([DEPLOYMENT.md](../../guides/DEPLOYMENT.md#tool-policy)). Model gateway
|
|
276
285
|
and sandbox backend are Tenant configuration (the Tenant's own vault, Tenant
|
|
277
286
|
settings and seed), not Host process env.
|
|
278
287
|
|
|
@@ -288,10 +297,11 @@ read from Durable Streams (S2). An advance owns its session through a lease with
|
|
|
288
297
|
an epoch; a Worker that takes over after a crash marks in-flight model effects
|
|
289
298
|
`uncertain`, and sends an interrupted MCP or HTTP tool call again with the same key (R5). Vault ciphertext needs that Tenant's own KEK.
|
|
290
299
|
|
|
291
|
-
A session that names an Environment of kind `virtual` or `pod` gets
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
names
|
|
300
|
+
A session that names an Environment of kind `virtual` or `pod` gets a sandbox, its spec pinned
|
|
301
|
+
on the session: our harness offers the sandbox tools and `save_artifact` and writes their notes
|
|
302
|
+
(protocol 15), and runs the calls in it. The agent declares nothing, and no tool name is
|
|
303
|
+
reserved: each call names what runs it. The Tenant owns each Environment; backend names are
|
|
304
|
+
prefixed `nylorun-<tenant-id>-`.
|
|
295
305
|
|
|
296
306
|
## Local Project workflow
|
|
297
307
|
|
|
@@ -311,11 +321,11 @@ the Project link (outside a project it runs the Tenant `default`); the project's
|
|
|
311
321
|
| `database-layout-old` | The database holds `tenant_<id>` schemas of an older Runtime, or the `schema_version` tables of a pre-release one: point the Runtime at a new database (locally, a new Tenant: `nylorun start --tenant <new name>`); the old one is left as it is |
|
|
312
322
|
| `426 protocol_unsupported` | Upgrade clients or Host to a compatible set |
|
|
313
323
|
| `421 host_rejected` / `403 origin_rejected` | In a container, list the `Host` in `NYLORUN_ALLOWED_HOSTS`. From a browser, send a trusted issuer's token, never a key |
|
|
314
|
-
|
|
|
324
|
+
| A turn fails `model.unsupported_input` | A custom harness sent the Model Gate a part the model cannot take (a text file as media, or a kind the model does not read): it should decide by `turn.start.model`. With our harness, the model was switched mid-turn: send the message again |
|
|
315
325
|
| `403 key_role_mismatch` | The key belongs to the other API: use a management key on `/v1/tenant/*` (`@nylorun/admin`) and an application key everywhere else (`@nylorun/agents`) |
|
|
316
326
|
| `503` for a Tenant | Postgres or Restate is unreachable; `GET /ready` names which |
|
|
317
327
|
| Port in use | Change `NYLORUN_PORT` in `~/.nylorun/tenants/<name>/docker/.env` and run `nylorun start` |
|
|
318
|
-
| Logs | `nylorun logs runtime` |
|
|
328
|
+
| Logs | `nylorun local logs runtime` |
|
|
319
329
|
|
|
320
330
|
Definitions have no `agent.run()`; applications use `@nylorun/agents`.
|
|
321
331
|
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import { type DurableExecution, type SandboxSignal, type StuckInvocation, type Wake, type WorkerHandlers } from "../../execution/types.js";
|
|
2
|
-
/**
|
|
3
|
-
* How long one send through the ingress keeps retrying while the ingress is unreachable,
|
|
4
|
-
* overloaded, or answers 404 because a just-registered service has not reached it yet. The
|
|
5
|
-
* outbox's grace (`OUTBOX_GRACE_MS` in `tenant/sweep.ts`) is longer.
|
|
6
|
-
*/
|
|
7
|
-
export declare const SEND_RETRY_MS = 10000;
|
|
8
2
|
export interface RestateTimeouts {
|
|
9
3
|
/**
|
|
10
4
|
* How long an invocation may run without journal progress before Restate
|
|
11
5
|
* asks it to suspend. An advance makes no journal entries while it runs, so
|
|
12
|
-
* this must exceed the longest segment. Default one hour.
|
|
6
|
+
* this must exceed the longest segment. Default `restate.inactivityMs` (Host tuning, one hour).
|
|
13
7
|
*/
|
|
14
8
|
inactivityMs?: number;
|
|
15
|
-
/** How long after the inactivity timeout Restate aborts the attempt. Default
|
|
9
|
+
/** How long after the inactivity timeout Restate aborts the attempt. Default `restate.abortMs`. */
|
|
16
10
|
abortMs?: number;
|
|
17
11
|
}
|
|
18
12
|
/**
|
|
@@ -21,13 +15,13 @@ export interface RestateTimeouts {
|
|
|
21
15
|
* `listStuckInvocations` until an operator resumes it.
|
|
22
16
|
*/
|
|
23
17
|
export interface RestateRetry {
|
|
24
|
-
/** Default 100. */
|
|
18
|
+
/** Default `restate.handlerRetry.minMs` (Host tuning, 100 ms). */
|
|
25
19
|
initialIntervalMs?: number;
|
|
26
|
-
/** Default
|
|
20
|
+
/** Default `restate.handlerRetry.maxMs` (30 s). */
|
|
27
21
|
maxIntervalMs?: number;
|
|
28
|
-
/** Default 2. */
|
|
22
|
+
/** Default 2: the wait doubles, as every backoff of the Runtime does. */
|
|
29
23
|
exponentiationFactor?: number;
|
|
30
|
-
/** Attempts, including the first, before pausing. Default 70. */
|
|
24
|
+
/** Attempts, including the first, before pausing. Default `restate.handlerAttempts` (70). */
|
|
31
25
|
maxAttempts?: number;
|
|
32
26
|
}
|
|
33
27
|
export interface RestateExecutionOptions {
|
|
@@ -56,11 +50,11 @@ export interface RestateExecutionOptions {
|
|
|
56
50
|
identityKeys?: string[];
|
|
57
51
|
timeouts?: RestateTimeouts;
|
|
58
52
|
retry?: RestateRetry;
|
|
59
|
-
/** Delay between sweep passes of one Tenant. Default
|
|
53
|
+
/** Delay between sweep passes of one Tenant. Default `sweep.intervalMs` (Host tuning, 5 s). */
|
|
60
54
|
sweepIntervalMs?: number;
|
|
61
55
|
/**
|
|
62
|
-
* How long wakes with a `dedupeKey` are remembered. Default
|
|
63
|
-
* 24 hours (§12.3).
|
|
56
|
+
* How long wakes with a `dedupeKey` are remembered. Default `execution.dedupeRetentionMs`;
|
|
57
|
+
* at least 24 hours (§12.3, `DEDUPE_RETENTION_MIN_MS`).
|
|
64
58
|
*/
|
|
65
59
|
dedupeRetentionMs?: number;
|
|
66
60
|
/**
|
|
@@ -70,12 +64,15 @@ export interface RestateExecutionOptions {
|
|
|
70
64
|
* versioned URL without it (`workerDeployment` in `infra/execution.ts`, §14.6).
|
|
71
65
|
*/
|
|
72
66
|
forceRegistration?: boolean;
|
|
73
|
-
/**
|
|
67
|
+
/**
|
|
68
|
+
* How long `start` keeps retrying registration while Restate comes up. Default
|
|
69
|
+
* `restate.registrationDeadlineMs` (Host tuning, 60 s).
|
|
70
|
+
*/
|
|
74
71
|
registrationTimeoutMs?: number;
|
|
75
72
|
/**
|
|
76
73
|
* How long `stop` waits for running handlers after aborting them; the ones still running
|
|
77
74
|
* then are abandoned and their attempts end with the dropped connections, so Restate
|
|
78
|
-
* retries them. Default `
|
|
75
|
+
* retries them. Default `execution.stopGraceMs` (Host tuning, 30 s).
|
|
79
76
|
*/
|
|
80
77
|
stopGraceMs?: number;
|
|
81
78
|
/** Replaces the SDK's console logging. */
|
|
@@ -132,7 +129,7 @@ export declare class RestateExecution implements DurableExecution {
|
|
|
132
129
|
private serviceOptions;
|
|
133
130
|
/**
|
|
134
131
|
* One-way send through the ingress (`@restatedev/restate-sdk-clients`). Every send carries
|
|
135
|
-
* an idempotency key, so the client's retries (`
|
|
132
|
+
* an idempotency key, so the client's retries (`restate.sendRetryMs`), and a send repeated after
|
|
136
133
|
* its answer was lost, start one invocation: the request's own key where it has one (an
|
|
137
134
|
* outbox row's, a timer's time), or one made for this call.
|
|
138
135
|
*/
|
|
@@ -39,14 +39,8 @@ import { createServer } from "node:http2";
|
|
|
39
39
|
import * as restate from "@restatedev/restate-sdk";
|
|
40
40
|
import * as clients from "@restatedev/restate-sdk-clients";
|
|
41
41
|
import { retry } from "../../retry.js";
|
|
42
|
-
import {
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* How long one send through the ingress keeps retrying while the ingress is unreachable,
|
|
46
|
-
* overloaded, or answers 404 because a just-registered service has not reached it yet. The
|
|
47
|
-
* outbox's grace (`OUTBOX_GRACE_MS` in `tenant/sweep.ts`) is longer.
|
|
48
|
-
*/
|
|
49
|
-
export const SEND_RETRY_MS = 10_000;
|
|
42
|
+
import { DEDUPE_RETENTION_MIN_MS, hostTuning } from "../../tuning.js";
|
|
43
|
+
import { WAKE_REASONS, parseSessionKey, sessionKey, settleWithin, } from "../../execution/types.js";
|
|
50
44
|
export function createRestateExecution(options) {
|
|
51
45
|
return new RestateExecution(options);
|
|
52
46
|
}
|
|
@@ -75,20 +69,24 @@ export class RestateExecution {
|
|
|
75
69
|
sandbox: `${prefix}NylorunSandbox`,
|
|
76
70
|
};
|
|
77
71
|
this.ingressUrl = options.ingressUrl.replace(/\/+$/, "");
|
|
72
|
+
const tuning = hostTuning().restate;
|
|
78
73
|
this.ingress = clients.connect({
|
|
79
74
|
url: this.ingressUrl,
|
|
75
|
+
// One send keeps retrying for `restate.sendRetryMs` while the ingress is unreachable,
|
|
76
|
+
// overloaded, or answers 404 because a just-registered service has not reached it yet;
|
|
77
|
+
// the outbox's grace (`sweep.outboxGraceMs`) is longer.
|
|
80
78
|
retry: {
|
|
81
79
|
maxAttempts: false,
|
|
82
|
-
maxDuration:
|
|
83
|
-
initialInterval:
|
|
84
|
-
maxInterval:
|
|
80
|
+
maxDuration: tuning.sendRetryMs,
|
|
81
|
+
initialInterval: tuning.sendBackoff.minMs,
|
|
82
|
+
maxInterval: tuning.sendBackoff.maxMs,
|
|
85
83
|
// A just-registered service can take a moment to reach the ingress.
|
|
86
84
|
shouldRetry: (failure) => clients.defaultShouldRetry(failure) ||
|
|
87
85
|
(failure.kind === "response" && failure.status === 404),
|
|
88
86
|
},
|
|
89
87
|
});
|
|
90
88
|
this.adminUrl = options.adminUrl.replace(/\/+$/, "");
|
|
91
|
-
this.sweepIntervalMs = options.sweepIntervalMs ??
|
|
89
|
+
this.sweepIntervalMs = options.sweepIntervalMs ?? hostTuning().sweep.intervalMs;
|
|
92
90
|
}
|
|
93
91
|
/** Service names this execution registers, for diagnostics and tests. */
|
|
94
92
|
get serviceNames() {
|
|
@@ -179,7 +177,7 @@ export class RestateExecution {
|
|
|
179
177
|
this.stopping = true;
|
|
180
178
|
for (const controller of this.controllers)
|
|
181
179
|
controller.abort(new Error("Worker stopping"));
|
|
182
|
-
const abandoned = await settleWithin(this.inflight, this.options.stopGraceMs ??
|
|
180
|
+
const abandoned = await settleWithin(this.inflight, this.options.stopGraceMs ?? hostTuning().execution.stopGraceMs);
|
|
183
181
|
if (abandoned > 0)
|
|
184
182
|
this.options.logger?.("warn", `Worker stopped with ${abandoned} handler(s) still running; abandoned`);
|
|
185
183
|
this.handlers = undefined;
|
|
@@ -195,7 +193,7 @@ export class RestateExecution {
|
|
|
195
193
|
const timeout = setTimeout(() => {
|
|
196
194
|
for (const session of this.sessions)
|
|
197
195
|
session.destroy();
|
|
198
|
-
},
|
|
196
|
+
}, hostTuning().restate.closeGraceMs);
|
|
199
197
|
await closed;
|
|
200
198
|
clearTimeout(timeout);
|
|
201
199
|
}
|
|
@@ -216,7 +214,7 @@ export class RestateExecution {
|
|
|
216
214
|
},
|
|
217
215
|
options: {
|
|
218
216
|
...serviceOptions,
|
|
219
|
-
idempotencyRetention: Math.max(this.options.dedupeRetentionMs ??
|
|
217
|
+
idempotencyRetention: Math.max(this.options.dedupeRetentionMs ?? hostTuning().execution.dedupeRetentionMs, DEDUPE_RETENTION_MIN_MS),
|
|
220
218
|
},
|
|
221
219
|
});
|
|
222
220
|
const tenant = restate.object({
|
|
@@ -352,26 +350,28 @@ export class RestateExecution {
|
|
|
352
350
|
return run;
|
|
353
351
|
}
|
|
354
352
|
staleSweepMs() {
|
|
355
|
-
|
|
353
|
+
const tuning = hostTuning().restate;
|
|
354
|
+
return Math.max(this.sweepIntervalMs * tuning.staleSweepIntervals, tuning.staleSweepMinMs);
|
|
356
355
|
}
|
|
357
356
|
serviceOptions() {
|
|
358
357
|
const timeouts = this.options.timeouts ?? {};
|
|
359
358
|
const retry = this.options.retry ?? {};
|
|
359
|
+
const tuning = hostTuning().restate;
|
|
360
360
|
return {
|
|
361
|
-
inactivityTimeout: timeouts.inactivityMs ??
|
|
362
|
-
abortTimeout: timeouts.abortMs ??
|
|
361
|
+
inactivityTimeout: timeouts.inactivityMs ?? tuning.inactivityMs,
|
|
362
|
+
abortTimeout: timeouts.abortMs ?? tuning.abortMs,
|
|
363
363
|
retryPolicy: {
|
|
364
|
-
initialInterval: retry.initialIntervalMs ??
|
|
365
|
-
maxInterval: retry.maxIntervalMs ??
|
|
364
|
+
initialInterval: retry.initialIntervalMs ?? tuning.handlerRetry.minMs,
|
|
365
|
+
maxInterval: retry.maxIntervalMs ?? tuning.handlerRetry.maxMs,
|
|
366
366
|
exponentiationFactor: retry.exponentiationFactor ?? 2,
|
|
367
|
-
maxAttempts: retry.maxAttempts ??
|
|
367
|
+
maxAttempts: retry.maxAttempts ?? tuning.handlerAttempts,
|
|
368
368
|
onMaxAttempts: "pause",
|
|
369
369
|
},
|
|
370
370
|
};
|
|
371
371
|
}
|
|
372
372
|
/**
|
|
373
373
|
* One-way send through the ingress (`@restatedev/restate-sdk-clients`). Every send carries
|
|
374
|
-
* an idempotency key, so the client's retries (`
|
|
374
|
+
* an idempotency key, so the client's retries (`restate.sendRetryMs`), and a send repeated after
|
|
375
375
|
* its answer was lost, start one invocation: the request's own key where it has one (an
|
|
376
376
|
* outbox row's, a timer's time), or one made for this call.
|
|
377
377
|
*/
|
|
@@ -382,7 +382,7 @@ export class RestateExecution {
|
|
|
382
382
|
handler,
|
|
383
383
|
key,
|
|
384
384
|
parameter: body,
|
|
385
|
-
opts: clients.SendOpts.from({ idempotencyKey, timeout:
|
|
385
|
+
opts: clients.SendOpts.from({ idempotencyKey, timeout: hostTuning().restate.sendTimeoutMs }),
|
|
386
386
|
});
|
|
387
387
|
}
|
|
388
388
|
catch (error) {
|
|
@@ -402,7 +402,7 @@ export class RestateExecution {
|
|
|
402
402
|
method: "POST",
|
|
403
403
|
headers: { "content-type": "application/json" },
|
|
404
404
|
body: JSON.stringify({ uri, force }),
|
|
405
|
-
signal: AbortSignal.timeout(
|
|
405
|
+
signal: AbortSignal.timeout(hostTuning().restate.registrationRequestTimeoutMs),
|
|
406
406
|
});
|
|
407
407
|
if (response.ok)
|
|
408
408
|
return (await response.json().catch(() => ({})))
|
|
@@ -412,7 +412,10 @@ export class RestateExecution {
|
|
|
412
412
|
// Discovery failures (Restate cannot reach the endpoint yet) come back
|
|
413
413
|
// as 4xx/5xx; keep trying until the deadline.
|
|
414
414
|
throw new Error(message);
|
|
415
|
-
}, {
|
|
415
|
+
}, {
|
|
416
|
+
...hostTuning().restate.registrationBackoff,
|
|
417
|
+
deadlineMs: this.options.registrationTimeoutMs ?? hostTuning().restate.registrationDeadlineMs,
|
|
418
|
+
}).catch((error) => {
|
|
416
419
|
throw new Error(`Restate deployment registration failed: ${error.message}`, {
|
|
417
420
|
cause: error,
|
|
418
421
|
});
|
|
@@ -445,7 +448,8 @@ export async function listStuckInvocations(options) {
|
|
|
445
448
|
const tenant = sqlString(options.tenantId);
|
|
446
449
|
clauses.push(`(target_service_key = ${tenant} OR starts_with(target_service_key, ${sqlString(`${options.tenantId}:`)}))`);
|
|
447
450
|
}
|
|
448
|
-
const
|
|
451
|
+
const { stuckListDefault, stuckListMax } = hostTuning().restate;
|
|
452
|
+
const limit = Math.max(1, Math.min(options.limit ?? stuckListDefault, stuckListMax));
|
|
449
453
|
const rows = await query(options.adminUrl, "SELECT id, status, target_service_name, target_handler_name, target_service_key, " +
|
|
450
454
|
"retry_count, last_failure, modified_at FROM sys_invocation " +
|
|
451
455
|
`WHERE ${clauses.join(" AND ")} ORDER BY modified_at LIMIT ${limit}`);
|
|
@@ -487,7 +491,7 @@ async function query(adminUrl, sql) {
|
|
|
487
491
|
method: "POST",
|
|
488
492
|
headers: { "content-type": "application/json", accept: "application/json" },
|
|
489
493
|
body: JSON.stringify({ query: sql }),
|
|
490
|
-
signal: AbortSignal.timeout(
|
|
494
|
+
signal: AbortSignal.timeout(hostTuning().restate.queryTimeoutMs),
|
|
491
495
|
});
|
|
492
496
|
if (!response.ok)
|
|
493
497
|
throw new Error(`Restate query ${response.status}: ${await response.text().catch(() => "")}`);
|
|
@@ -15,7 +15,7 @@ export interface PgoutputSourceOptions {
|
|
|
15
15
|
schema?: string;
|
|
16
16
|
/** The connections' `application_name`. Default `nylorun-stream-relay`. */
|
|
17
17
|
applicationName?: string;
|
|
18
|
-
/** Wait between attempts to take the slot. Default 5 s. */
|
|
18
|
+
/** Wait between attempts to take the slot. Default `postgres.replicationRetryMs` (Host tuning, 5 s). */
|
|
19
19
|
retryMs?: number;
|
|
20
20
|
log?: (message: string, fields?: Record<string, unknown>) => void;
|
|
21
21
|
}
|
|
@@ -21,18 +21,19 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import pg from "pg";
|
|
23
23
|
import { LogicalReplicationService, PgoutputPlugin } from "pg-logical-replication";
|
|
24
|
+
import { hostTuning } from "../../tuning.js";
|
|
24
25
|
export const DEFAULT_RELAY_SLOT = "nylorun_stream_relay";
|
|
25
26
|
export function createPgoutputSource(options) {
|
|
26
27
|
const slot = options.slot ?? DEFAULT_RELAY_SLOT;
|
|
27
28
|
const publication = options.publication ?? "nylorun_stream_relay";
|
|
28
29
|
const schema = options.schema ?? "nylorun_streams";
|
|
29
|
-
const retryMs = options.retryMs ??
|
|
30
|
+
const retryMs = options.retryMs ?? hostTuning().postgres.replicationRetryMs;
|
|
30
31
|
const applicationName = options.applicationName ?? "nylorun-stream-relay";
|
|
31
32
|
const { tenantId } = options;
|
|
32
33
|
const log = options.log ?? (() => { });
|
|
33
34
|
const pool = new pg.Pool({
|
|
34
35
|
connectionString: options.connectionString,
|
|
35
|
-
max:
|
|
36
|
+
max: hostTuning().postgres.replicationPoolSize,
|
|
36
37
|
application_name: applicationName,
|
|
37
38
|
});
|
|
38
39
|
let service;
|
|
@@ -16,8 +16,7 @@ import { lstat, readdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
|
16
16
|
import { posix } from "node:path";
|
|
17
17
|
import { SANDBOX_WORKSPACE } from "@nylorun/core/define";
|
|
18
18
|
import { SandboxFileTooLargeError } from "../../sandbox/types.js";
|
|
19
|
-
|
|
20
|
-
const STREAM_LIMIT = 4 * 1024 * 1024;
|
|
19
|
+
import { hostTuning } from "../../tuning.js";
|
|
21
20
|
/** This process's environment without the engine's own variables. */
|
|
22
21
|
function baseEnv(env, workspace) {
|
|
23
22
|
const out = {};
|
|
@@ -26,18 +25,22 @@ function baseEnv(env, workspace) {
|
|
|
26
25
|
out[name] = value;
|
|
27
26
|
return { PATH: "/usr/local/bin:/usr/bin:/bin", LANG: "C.UTF-8", TERM: "dumb", ...out, HOME: workspace };
|
|
28
27
|
}
|
|
29
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Collects a stream, keeping at most `harness.commandStreamBytes` (Host tuning) of it, head first;
|
|
30
|
+
* the tools keep less of it (`engine.sandboxTools.outputChars`).
|
|
31
|
+
*/
|
|
30
32
|
function collector() {
|
|
33
|
+
const limit = hostTuning().harness.commandStreamBytes;
|
|
31
34
|
const chunks = [];
|
|
32
35
|
let size = 0;
|
|
33
36
|
let dropped = 0;
|
|
34
37
|
return {
|
|
35
38
|
push(chunk) {
|
|
36
|
-
if (size >=
|
|
39
|
+
if (size >= limit) {
|
|
37
40
|
dropped += chunk.length;
|
|
38
41
|
return;
|
|
39
42
|
}
|
|
40
|
-
const room =
|
|
43
|
+
const room = limit - size;
|
|
41
44
|
const kept = chunk.length > room ? chunk.subarray(0, room) : chunk;
|
|
42
45
|
chunks.push(kept);
|
|
43
46
|
size += kept.length;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { mkdirSync, readdirSync, rmSync } from "node:fs";
|
|
8
8
|
import { join, posix } from "node:path";
|
|
9
9
|
import { SANDBOX_WORKSPACE } from "@nylorun/core/define";
|
|
10
|
-
import { SandboxFileTooLargeError } from "../../sandbox/types.js";
|
|
10
|
+
import { SandboxFileTooLargeError, wholeBytes } from "../../sandbox/types.js";
|
|
11
11
|
const ENV = Object.freeze({
|
|
12
12
|
PATH: "/usr/local/bin:/usr/bin:/bin",
|
|
13
13
|
HOME: SANDBOX_WORKSPACE,
|
|
@@ -143,7 +143,7 @@ export function virtualBackend(options) {
|
|
|
143
143
|
return { entries, truncated: !complete };
|
|
144
144
|
},
|
|
145
145
|
async writeFile(path, content) {
|
|
146
|
-
await (typeof content === "string" ? fs.writeFile(path, content, "utf8") : fs.writeFile(path, content));
|
|
146
|
+
await (typeof content === "string" ? fs.writeFile(path, content, "utf8") : fs.writeFile(path, await wholeBytes(content)));
|
|
147
147
|
},
|
|
148
148
|
async stop() { },
|
|
149
149
|
};
|