@nylorun/runtime 0.12.0-beta → 0.14.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 +361 -0
- package/README.md +69 -15
- package/dist/adapters/execution/restate.d.ts +7 -2
- package/dist/adapters/execution/restate.js +38 -8
- package/dist/adapters/replication/pgoutput.d.ts +16 -0
- package/dist/adapters/replication/pgoutput.js +169 -0
- package/dist/adapters/streams/s2.js +37 -20
- package/dist/admin-openapi.json +1071 -0
- package/dist/api/a2a/card.d.ts +15 -0
- package/dist/api/a2a/card.js +24 -0
- package/dist/api/a2a/endpoint.d.ts +8 -0
- package/dist/api/a2a/endpoint.js +81 -0
- package/dist/api/a2a/protocol.d.ts +144 -0
- package/dist/api/a2a/protocol.js +188 -0
- package/dist/api/a2a/routes.d.ts +19 -0
- package/dist/api/a2a/routes.js +289 -0
- package/dist/api/a2a/tasks.d.ts +50 -0
- package/dist/api/a2a/tasks.js +186 -0
- package/dist/api/ag-ui/endpoint.d.ts +8 -0
- package/dist/api/ag-ui/endpoint.js +126 -0
- package/dist/api/ag-ui/history.d.ts +7 -0
- package/dist/api/ag-ui/history.js +60 -0
- package/dist/api/ag-ui/routes.d.ts +32 -0
- package/dist/api/ag-ui/routes.js +305 -0
- package/dist/api/ag-ui/session-id.d.ts +1 -0
- package/dist/api/ag-ui/session-id.js +12 -0
- package/dist/api/ag-ui/sse.d.ts +9 -0
- package/dist/api/ag-ui/sse.js +7 -0
- package/dist/api/ag-ui/translate.d.ts +38 -0
- package/dist/api/ag-ui/translate.js +222 -0
- package/dist/api/components.d.ts +7825 -0
- package/dist/api/components.js +83 -0
- package/dist/api/http/app.d.ts +18 -0
- package/dist/api/http/app.js +58 -0
- package/dist/api/http/body.d.ts +4 -0
- package/dist/api/http/body.js +37 -0
- package/dist/api/http/define.d.ts +39 -0
- package/dist/api/http/define.js +130 -0
- package/dist/api/http/respond.d.ts +9 -0
- package/dist/api/http/respond.js +44 -0
- package/dist/api/http/routes/access.d.ts +24 -0
- package/dist/api/http/routes/access.js +259 -0
- package/dist/api/http/routes/actions.d.ts +8 -0
- package/dist/api/http/routes/actions.js +76 -0
- package/dist/api/http/routes/endpoints.d.ts +7 -0
- package/dist/api/http/routes/endpoints.js +100 -0
- package/dist/api/http/routes/sessions.d.ts +3 -0
- package/dist/api/http/routes/sessions.js +205 -0
- package/dist/api/http/routes/tenant.d.ts +10 -0
- package/dist/api/http/routes/tenant.js +172 -0
- package/dist/api/http/routes/vaults.d.ts +8 -0
- package/dist/api/http/routes/vaults.js +167 -0
- package/dist/api/openapi.d.ts +19 -0
- package/dist/api/openapi.js +138 -0
- package/dist/api/route.d.ts +12 -0
- package/dist/api/route.js +4 -0
- package/dist/core/bearer.d.ts +8 -0
- package/dist/core/bearer.js +11 -0
- package/dist/core/flow-host.d.ts +7 -15
- package/dist/core/flow-host.js +19 -41
- package/dist/core/sandbox-routes.d.ts +12 -7
- package/dist/core/sandbox-routes.js +24 -25
- package/dist/execution/memory.d.ts +8 -5
- package/dist/execution/memory.js +33 -13
- package/dist/execution/types.d.ts +38 -6
- package/dist/execution/types.js +12 -3
- package/dist/host/admin-api.d.ts +22 -0
- package/dist/host/admin-api.js +178 -0
- package/dist/host/app.d.ts +34 -0
- package/dist/host/app.js +185 -0
- package/dist/host/config-for.d.ts +2 -0
- package/dist/host/config-for.js +1 -0
- package/dist/host/config.d.ts +11 -0
- package/dist/host/cors.d.ts +27 -0
- package/dist/host/cors.js +64 -0
- package/dist/host/create-host.d.ts +31 -3
- package/dist/host/create-host.js +168 -327
- package/dist/host/http.d.ts +14 -3
- package/dist/host/http.js +64 -23
- package/dist/host/main.js +55 -4
- package/dist/host/stack-config.d.ts +20 -0
- package/dist/host/stack-config.js +55 -0
- package/dist/mcp/pool.d.ts +19 -1
- package/dist/mcp/pool.js +60 -10
- package/dist/model/catalog.d.ts +2 -10
- package/dist/model/classify.d.ts +13 -0
- package/dist/model/classify.js +61 -0
- package/dist/model/models.d.ts +10 -1
- package/dist/model/models.js +14 -6
- package/dist/model/pi-model.d.ts +17 -2
- package/dist/model/pi-model.js +366 -222
- package/dist/openapi.json +25696 -0
- package/dist/sandbox/manager.d.ts +13 -1
- package/dist/sandbox/manager.js +8 -11
- package/dist/sandbox/resolve.d.ts +33 -0
- package/dist/sandbox/resolve.js +81 -0
- package/dist/sandbox/session-sandbox.d.ts +11 -0
- package/dist/sandbox/session-sandbox.js +51 -0
- package/dist/sandbox/share.d.ts +14 -2
- package/dist/sandbox/share.js +33 -3
- package/dist/sandbox/tenant-config.d.ts +37 -0
- package/dist/sandbox/tenant-config.js +51 -0
- package/dist/sandbox/tools.d.ts +7 -9
- package/dist/sandbox/tools.js +11 -3
- package/dist/sandbox/types.d.ts +8 -2
- package/dist/store/event.d.ts +19 -0
- package/dist/store/event.js +49 -0
- package/dist/store/memory.d.ts +20 -8
- package/dist/store/memory.js +265 -100
- package/dist/store/postgres/connect.d.ts +13 -0
- package/dist/store/postgres/connect.js +5 -0
- package/dist/store/postgres/migrations/003_subject_tokens.d.ts +8 -0
- package/dist/store/postgres/migrations/003_subject_tokens.js +42 -0
- package/dist/store/postgres/migrations/004_publishable_keys.d.ts +6 -0
- package/dist/store/postgres/migrations/004_publishable_keys.js +18 -0
- package/dist/store/postgres/migrations/005_action_endpoints.d.ts +6 -0
- package/dist/store/postgres/migrations/005_action_endpoints.js +32 -0
- package/dist/store/postgres/migrations/006_drop_executors.d.ts +11 -0
- package/dist/store/postgres/migrations/006_drop_executors.js +32 -0
- package/dist/store/postgres/migrations/007_event_time.d.ts +7 -0
- package/dist/store/postgres/migrations/007_event_time.js +14 -0
- package/dist/store/postgres/migrations/008_durable_streams.d.ts +13 -0
- package/dist/store/postgres/migrations/008_durable_streams.js +35 -0
- package/dist/store/postgres/migrations/index.d.ts +5 -1
- package/dist/store/postgres/migrations/index.js +22 -2
- package/dist/store/postgres/migrations/shared/index.d.ts +31 -0
- package/dist/store/postgres/migrations/shared/index.js +92 -0
- package/dist/store/postgres/record.d.ts +11 -0
- package/dist/store/postgres/record.js +64 -0
- package/dist/store/postgres/store.js +337 -95
- package/dist/store/postgres/tenants.js +14 -0
- package/dist/store/types.d.ts +176 -81
- package/dist/streams/basin.d.ts +18 -1
- package/dist/streams/basin.js +34 -2
- package/dist/streams/control.d.ts +18 -0
- package/dist/streams/control.js +29 -0
- package/dist/streams/memory.d.ts +3 -1
- package/dist/streams/memory.js +14 -8
- package/dist/streams/relay/core.d.ts +35 -0
- package/dist/streams/relay/core.js +366 -0
- package/dist/streams/relay/memory.d.ts +69 -0
- package/dist/streams/relay/memory.js +176 -0
- package/dist/streams/relay/types.d.ts +77 -0
- package/dist/streams/relay/types.js +7 -0
- package/dist/streams/types.d.ts +66 -36
- package/dist/streams/types.js +18 -53
- package/dist/tenant/access-policy.d.ts +30 -0
- package/dist/tenant/access-policy.js +52 -0
- package/dist/tenant/actions.d.ts +10 -149
- package/dist/tenant/actions.js +5 -167
- package/dist/tenant/advance.js +32 -0
- package/dist/tenant/auth.d.ts +19 -17
- package/dist/tenant/auth.js +90 -93
- package/dist/tenant/browser.d.ts +15 -0
- package/dist/tenant/browser.js +39 -0
- package/dist/tenant/commands.d.ts +18 -2
- package/dist/tenant/commands.js +121 -129
- package/dist/tenant/context.d.ts +75 -18
- package/dist/tenant/context.js +14 -10
- package/dist/tenant/delivery-token.d.ts +41 -0
- package/dist/tenant/delivery-token.js +105 -0
- package/dist/tenant/delivery.d.ts +62 -0
- package/dist/tenant/delivery.js +476 -0
- package/dist/tenant/effects.d.ts +5 -0
- package/dist/tenant/effects.js +138 -48
- package/dist/tenant/endpoints.d.ts +67 -0
- package/dist/tenant/endpoints.js +90 -0
- package/dist/tenant/ephemeral.d.ts +6 -0
- package/dist/tenant/ephemeral.js +60 -36
- package/dist/tenant/http.d.ts +8 -9
- package/dist/tenant/http.js +13 -27
- package/dist/tenant/jwt.d.ts +16 -0
- package/dist/tenant/jwt.js +50 -0
- package/dist/tenant/module.d.ts +3 -0
- package/dist/tenant/module.js +6 -12
- package/dist/tenant/outbound.d.ts +44 -0
- package/dist/tenant/outbound.js +127 -0
- package/dist/tenant/pool.d.ts +0 -2
- package/dist/tenant/pool.js +0 -18
- package/dist/tenant/reset.d.ts +0 -4
- package/dist/tenant/reset.js +0 -5
- package/dist/tenant/runtime.d.ts +10 -20
- package/dist/tenant/runtime.js +59 -42
- package/dist/tenant/scheduler.d.ts +7 -2
- package/dist/tenant/scheduler.js +7 -3
- package/dist/tenant/session-streams.d.ts +125 -0
- package/dist/tenant/session-streams.js +399 -0
- package/dist/tenant/sessions.d.ts +28 -4
- package/dist/tenant/sessions.js +118 -24
- package/dist/tenant/signing-keys.d.ts +55 -0
- package/dist/tenant/signing-keys.js +172 -0
- package/dist/tenant/slim.d.ts +8 -0
- package/dist/tenant/slim.js +21 -0
- package/dist/tenant/status.d.ts +0 -3
- package/dist/tenant/status.js +19 -12
- package/dist/tenant/streams.d.ts +60 -67
- package/dist/tenant/streams.js +140 -208
- package/dist/tenant/subject-limits.d.ts +16 -0
- package/dist/tenant/subject-limits.js +45 -0
- package/dist/tenant/sweep.d.ts +1 -10
- package/dist/tenant/sweep.js +29 -69
- package/dist/tenant/tokens.d.ts +14 -0
- package/dist/tenant/tokens.js +178 -0
- package/dist/tenant/transcript.d.ts +48 -5
- package/dist/tenant/transcript.js +58 -1
- package/dist/tenant/types.d.ts +29 -7
- package/dist/tenant/worker.d.ts +3 -1
- package/dist/tenant/worker.js +9 -3
- package/dist/vault/service.d.ts +18 -2
- package/dist/vault/service.js +57 -13
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +20 -8
- package/dist/core/executors.d.ts +0 -44
- package/dist/core/executors.js +0 -95
- package/dist/streams/relay.d.ts +0 -37
- package/dist/streams/relay.js +0 -254
- package/dist/tenant/live.d.ts +0 -92
- package/dist/tenant/live.js +0 -290
- package/dist/tenant/routes-tenant.d.ts +0 -12
- package/dist/tenant/routes-tenant.js +0 -137
- package/dist/tenant/routes.d.ts +0 -9
- package/dist/tenant/routes.js +0 -151
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,366 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.14.0-beta
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 9546ac7: **Postgres is the record of every session event; S2 delivers it.** Durable Streams v1.
|
|
8
|
+
|
|
9
|
+
- **The record.** Each event is written to `nylorun_streams.session_events` in the transaction that causes it, with the session's log head. The per-Tenant outbox, its relay, its drain in the Tenant sweep and `StreamGapError` are gone: losing S2's data, the relay or its replication slot now costs delay, never events.
|
|
10
|
+
- **The stream relay.** With S2, every `api` or `all` Runtime process runs the relay; its Postgres replication slot (`nylorun_stream_relay`) lets exactly one be active. It appends with `matchSeq`, acknowledges the slot only after S2 has the events, refills gaps from the record, and reconciles the record with S2 after a new or lost slot. Without S2 (a local development Host), each Tenant relays its own commits.
|
|
11
|
+
- **Postgres needs logical replication.** The Runtime refuses to start an `api` or `all` process with S2 unless `wal_level = logical` and its role may replicate; the error names the setting. The local stack is configured for it. See `DEPLOYMENT.md`.
|
|
12
|
+
- **No incarnations.** A session's stream is `sessions/<id>`. A sessions reset moves the Tenant to a new **basin generation**: the old basin gets a `sessions.reset` signal, every process moves its readers, and the old basin is deleted after a grace period. Tenant deletion deletes every generation's basin and the Tenant's record rows.
|
|
13
|
+
- **Status.** Tenant status `streams` reports `generation` and the Tenant's `relay` instead of the outbox; the Host aggregate reports the process's `relay` (with its slot lag in bytes) instead of `outboxDepth` and `relayLagMs`.
|
|
14
|
+
- **Session history does not survive the upgrade.** Installs are in beta, so Tenant schema migration 8 is a fresh start for session data: a Tenant with sessions loses them, with their commands, checkpoints, effects, Actions and links, as a sessions reset does, and moves to basin generation 1; its settings, agents, Action endpoints, keys, policy and vaults stay. Clients holding cursors start again.
|
|
15
|
+
|
|
16
|
+
- 9546ac7: **Protocol 4: every session event is typed, on the `nylorun.event/2` envelope.**
|
|
17
|
+
|
|
18
|
+
- **The catalog.** `EVENT_CATALOG` in `@nylorun/core/contracts` lists every event type the Runtime writes, with its payload schema, its schema version and its source. `SessionEventSchema` is their union, discriminated on `type`; `parseSessionEvent` types a known event and returns an unknown one as the bare envelope.
|
|
19
|
+
- **The envelope.** Events carry `schema`, `seq`, `epoch`, `runId`, `incarnation`, `schemaVersion`, `source`, `evidence`, `visibility`, `retention` and an optional `trace`. `createdAt` is renamed `time`. The envelope is no longer strict, so later fields never break a client.
|
|
20
|
+
- **Validated writes.** `Tx.event` is typed by the catalog, and both Session Stores check each event against it before it commits (`InvalidEventError`). Workflow `action.pending` payloads may carry `path` and `key`.
|
|
21
|
+
- **OpenAPI.** Each event type is a component (`MessageAssistantEvent`, …), `SessionEvent` is their union, and the session SSE and history responses refer to them.
|
|
22
|
+
- **Clients.** `@nylorun/agents` reads events with `parseSessionEvent`, so a newer Runtime's event types reach your code instead of failing the stream. Studio reads `time`.
|
|
23
|
+
|
|
24
|
+
See `MIGRATION.md`.
|
|
25
|
+
|
|
26
|
+
### Minor Changes
|
|
27
|
+
|
|
28
|
+
- c7614a4: **A2A: serve agents to other agents (v1, gateway mode).** The Runtime answers [A2A](https://a2a-protocol.org) 1.0 over JSON-RPC for the Tenant's agents (optional Host feature `a2a-endpoint`), and the app server publishes them with `createA2aHandler`.
|
|
29
|
+
|
|
30
|
+
- **Runtime.** `POST /v1/a2a/agents/:agent` acts for a subject with `sessions:own`. It serves `SendMessage` (blocking up to 5 minutes, or `returnImmediately`), `GetTask` and `CancelTask`. A context is one session per subject, agent and `contextId`, and a task is one turn. A question pauses the task as `TASK_STATE_INPUT_REQUIRED` until the caller replies on the same task. The `messageId` is the idempotency key. `ListTasks`, streaming, push notifications and the extended card answer with their A2A errors, and approvals cannot be answered over A2A yet. `GET /v1/a2a/agents/:agent/card` returns the card built from the manifest, without interfaces. `observeSession` lets in-process readers join a session's shared event feed.
|
|
31
|
+
- **Agents SDK.** `@nylorun/agents/a2a`: `createA2aHandler({ agents, subject, publicUrl, card })` forwards each partner's JSON-RPC request to the Runtime as that partner's subject, and serves the Agent Card with its own URL, provider and security schemes. It loads no A2A package. `Transport.forward` returns the Runtime's raw response.
|
|
32
|
+
|
|
33
|
+
- 77807ad: **Action endpoints: background outcomes.** An endpoint can answer a delivery with `202`, keep it alive, use the session's sandbox, and post the outcome later, all with the delivery token.
|
|
34
|
+
|
|
35
|
+
- **`POST /v1/actions/:id/heartbeat` with a delivery token** extends the delivery by a lease (`leaseMs`) and returns a fresh token (`{ token, deadlineAt }`). It answers `409` once the delivery was cancelled, lost or sent again, which tells the endpoint to stop. Executors keep their claim heartbeat on the same route.
|
|
36
|
+
- **`POST /v1/actions/:id/result` (new, delivery token only)** records the outcome. The same result again returns the first receipt; a different one is `409`.
|
|
37
|
+
- **`POST /v1/actions/:id/sandbox/:tool` with a delivery token** runs the session's sandbox tools for that Action while it is being delivered. The body is the tool's input, with no claim fields.
|
|
38
|
+
- **Deadline.** A `202` delivery that stops heartbeating is lost at its deadline: a tool becomes `uncertain`; a hook, `fn` or `verify` is delivered again.
|
|
39
|
+
- The heartbeat and sandbox routes are no longer marked deprecated in the OpenAPI document. Their executor use is.
|
|
40
|
+
|
|
41
|
+
- 679c488: **Action endpoints: the Runtime delivers Actions (Host feature `action-endpoints`).** For an agent with a registered endpoint, each tool call, hook and workflow `fn`, `verify` or tool node is POSTed to the endpoint and the answer settles it. Agents without one keep their executors.
|
|
42
|
+
|
|
43
|
+
- **The request.** `{ type: "action", action, sandbox }`, with a delivery token in `Nylorun-Signature` (for this Tenant, URL, Action, generation and body) and the Action id as `Idempotency-Key`. Deliveries of one Action never overlap, and at most `maxConcurrent` are in flight per endpoint.
|
|
44
|
+
- **The answer.**
|
|
45
|
+
- `200` with `Nylorun-Outcome: 1` is the outcome. A plain `200` is a tool's output, or what an `fn` or `verify` returned; the tool's output schema still applies.
|
|
46
|
+
- `202` means the result comes later.
|
|
47
|
+
- `429` and `503` (honouring `Retry-After`), a version mismatch (`409`) and anything that never reached the endpoint are retried, backing off from 250 ms to 30 s. The failure is reported as `action.delivery_failed` at most every 10 s.
|
|
48
|
+
- Any other `4xx`, or a `3xx` (redirects are not followed), fails the Action with `endpoint.rejected`.
|
|
49
|
+
- No answer after sending (timeout, reset, `5xx`) loses it: a tool becomes `uncertain`; a hook, `fn` or `verify` is delivered again. A delivery whose deadline passes (a Worker died) is lost the same way, by the Tenant sweep.
|
|
50
|
+
- **Cancel.** A cancelled turn aborts the request at once. The code may have run, so the Action becomes `uncertain`, as a claimed one does.
|
|
51
|
+
- **Events and health.** `action.delivered` and `action.delivery_failed` are new events. Endpoint health records successes and failures.
|
|
52
|
+
- **Ping.** `POST /v1/endpoints/:agentId/ping` sends a signed ping and records what the endpoint serves. It answers `502` when the endpoint doesn't answer.
|
|
53
|
+
- **Host settings.**
|
|
54
|
+
- `NYLORUN_ENDPOINT_LOOPBACK=docker-host`: in the local stack, `localhost` means the Docker host.
|
|
55
|
+
- `NYLORUN_ENDPOINT_PRIVATE` (`allow`/`refuse`): checked on the address actually connected to.
|
|
56
|
+
- `NYLORUN_ENDPOINT_HTTP` (`allow`/`refuse`).
|
|
57
|
+
- **Executors unchanged.** Executor results and deliveries record outcomes through one function, so the two paths behave the same.
|
|
58
|
+
|
|
59
|
+
- 706b3f0: **Action endpoints: delivery tokens (groundwork; no route accepts them yet).** The Runtime can sign a token for one delivery of one Action, and recognises it when it comes back as a bearer.
|
|
60
|
+
|
|
61
|
+
- **The token.** An ES256 JWT signed with the Tenant's current signing key. Its `typ` is `nylorun-delivery+jwt`, `iss` is the Tenant, `aud` is the endpoint URL, `sub` is the Action id (or `ping`), and `agt`, `gen` and `bdy` carry the agent, generation and body hash. It lives at most 900 s.
|
|
62
|
+
- **As a bearer.**
|
|
63
|
+
- A delivery token reaches only the routes that list it, and none does yet (every other route answers `403`).
|
|
64
|
+
- It is refused from browsers (`origin_rejected`) and cannot act for a subject.
|
|
65
|
+
- An expired token or a revoked key is `401 token_expired`; anything else, a ping token included, is the opaque `404`.
|
|
66
|
+
- **Key rotation.** It now waits for the longest token either kind may have signed, so a delivery token is never revoked while it is live, even under a short subject-token policy.
|
|
67
|
+
- Subject tokens share their header checks with delivery tokens (`tenant/jwt.ts`), with no change in behaviour.
|
|
68
|
+
|
|
69
|
+
- ab1eab7: **The Tenant's public keys are public.** `GET /v1/access/jwks` answers with `Nylorun-Tenant` alone, with no credential, so an Action endpoint can verify delivery tokens (and anyone can verify subject tokens) without holding a key.
|
|
70
|
+
|
|
71
|
+
- A credential that is sent is still checked: a wrong one is still the opaque `404`. A browser still needs a publishable key.
|
|
72
|
+
- Routes declare this with `anonymous: true`, which only the JWKS route uses. In the OpenAPI document it appears as an empty security requirement (`{}`).
|
|
73
|
+
|
|
74
|
+
- c85cd9e: **Action endpoints: register them (nothing is delivered yet).** An application registers, for each agent, the URL that will run its Actions. The Runtime stores the registration and its health; deliveries follow in a later release.
|
|
75
|
+
|
|
76
|
+
- **Routes (application key only).**
|
|
77
|
+
- `PUT /v1/endpoints` registers or updates up to 64 endpoints: `agentId`, `url` (http or https, no credentials or fragment), `implementationVersion`, optional `manifestHash`, `timeoutMs` (default 60 000, at most 840 000) and `maxConcurrent` (default 16).
|
|
78
|
+
- `GET /v1/endpoints` lists them with their health: last delivery, last success, last error, consecutive failures, and what the last ping reported.
|
|
79
|
+
- `DELETE /v1/endpoints/:agentId` removes one.
|
|
80
|
+
- Subjects, subject tokens and executors are refused.
|
|
81
|
+
- **One path per agent.** Registering an endpoint removes the agent's executor and ends its streams. `PUT /v1/executors` for an agent with an endpoint is `409`, naming the endpoint to remove first.
|
|
82
|
+
- **Health.** Registering the same URL again keeps an endpoint's health; a new URL starts with none.
|
|
83
|
+
- **Store.** Postgres migration 5 adds the `endpoints` table and a `deadline_at` column on Actions.
|
|
84
|
+
- **Core.** Adds `DeleteEndpointResponseSchema`. The endpoint response schemas are strict.
|
|
85
|
+
|
|
86
|
+
- 4282d5f: **Breaking: executors are removed; protocol 3.** The Runtime delivers every Action (tool, hook, `fn`, `verify`) to the Action endpoint an agent registers. It no longer offers Actions for executors to claim. See `MIGRATION.md`, "Action endpoints replace executors".
|
|
87
|
+
|
|
88
|
+
- **Core.** `PROTOCOL_VERSION` is 3 and a Host serves only protocol 3. `action-endpoints` is a protocol feature instead of an optional Host feature. Removed:
|
|
89
|
+
|
|
90
|
+
- the executor, claim and Action-list schemas;
|
|
91
|
+
- `action_result` from `SessionCommandSchema`;
|
|
92
|
+
- the `claimed` Action status, `claimId` and `leaseExpiresAt`.
|
|
93
|
+
|
|
94
|
+
New: `ActionResultReceiptSchema`, the receipt of `POST /v1/actions/:id/result`, which is `AcceptedResponse` without `requestId`.
|
|
95
|
+
|
|
96
|
+
- **Runtime.** Removed:
|
|
97
|
+
|
|
98
|
+
- `PUT`/`GET /v1/executors`, `DELETE /v1/executors/:agentId`, `GET /v1/executors/connect`;
|
|
99
|
+
- `GET /v1/actions`, `POST /v1/actions/:id/claim`, and the executor form of `POST /v1/actions/:id/heartbeat`;
|
|
100
|
+
- the `tenant/work` stream;
|
|
101
|
+
- claim expiry;
|
|
102
|
+
- executor credentials.
|
|
103
|
+
|
|
104
|
+
`POST /v1/actions/:id/sandbox/:tool` takes the delivery token only. Tenant summaries report `inFlightDeliveries` instead of `connectedExecutors`. Tenant status lists each agent's endpoint and has an `endpoints` check instead of `executors`.
|
|
105
|
+
|
|
106
|
+
Postgres migration 6 drops the `executors` table. Actions an executor had claimed are handled like lost deliveries: a tool becomes `uncertain`, and a hook, `fn` or `verify` is delivered again.
|
|
107
|
+
|
|
108
|
+
- **Agents.** Removed: `connectAgents`, the `@nylorun/agents/executor` subpath, derived executor keys and `NYLORUN_EXECUTOR_KEY`. Serve agents with `createActionHandler` and call `register({ url })`.
|
|
109
|
+
- **CLI.** Executor keys are gone from Project credentials. `nylo tenant endpoints` shows each endpoint and its health.
|
|
110
|
+
|
|
111
|
+
- 50d0fb5: **AG-UI in the Runtime.** The Runtime serves AG-UI itself at `/v1/ag-ui/agents/:agent` (optional Host feature `ag-ui-endpoint`), and pages reach it directly with a subject token. `@nylorun/agents` no longer contains or depends on any AG-UI package.
|
|
112
|
+
|
|
113
|
+
- **Runtime.** `POST /v1/ag-ui/agents/:agent` runs (a `RunAgentInput` in, server-sent AG-UI events out); `GET …/threads/:thread/messages`, `GET …/threads/:thread/events` (reattach) and `POST …/threads/:thread/cancel`. For a person named by a subject token (limited to the role's agents) or by subject headers; an application key alone is `400`. A thread's session (`sessionIdFor`, unchanged, so existing threads keep their sessions) is created on its first run with `forwardedProps.nylorun.session` (`vaultIds`, `credentialSelections`, and `info` from app servers only) and never changed afterwards. Limits and a busy session are streamed as `RUN_ERROR`. A stream opened with a token ends at the token's expiry or revocation with `CUSTOM nylorun.stream_closed`. The translation moves here from `@nylorun/agents`, and `@ag-ui/core` becomes a Runtime dependency.
|
|
114
|
+
- **Agents SDK.** `createAgUiHandler` keeps its options and routes and forwards each request to the Runtime acting for the signed-in person; it now needs a Runtime with `ag-ui-endpoint` (`502 runtime_feature_missing` otherwise). `session()` options apply when a thread's session is created; whatever the browser sends in `forwardedProps.nylorun` is replaced. `@ag-ui/core` is no longer a dependency. `@nylorun/agents/browser` adds `agUi(agentId)`, a `{ url, fetch }` for `HttpAgent` that adds the key and a current token and reattaches a run the Runtime ended at token expiry, so the agent sees one run, and `agUiHistory()`. The transport gains `forward()`, which returns the Runtime's response as it is.
|
|
115
|
+
|
|
116
|
+
- 50d0fb5: **Browser access: web pages and apps call the Runtime with a publishable key.** A page ships a publishable key and gets subject tokens from its app server; the Runtime answers it directly, with CORS (optional Host feature `browser-access`).
|
|
117
|
+
|
|
118
|
+
- **Publishable keys.** `nr_pub_<tenantId>_…`, sent in `Nylorun-Key`, name the Tenant and one app, with an origin allowlist (exact origins, or `http://localhost:*` and `http://127.0.0.1:*` for development; none for native apps). `GET`/`POST /v1/access/publishable-keys`, `PUT`/`DELETE …/:id`. A key alone grants the policy's `anon` role, at most the public agent list, and reaches no session or vault. Postgres migration 4.
|
|
119
|
+
- **Host.** With browser access on, requests with an `Origin` reach Tenant routes; `/health`, `/ready` and admin routes still refuse them. Preflights for browser routes (agents, sessions, vaults, AG-UI, JWKS) are answered from the route alone and grant no credentials; the actual request must carry a publishable key whose allowlist names the origin, and only then do responses (JSON, errors, `401`, `429`, event streams) carry CORS headers. A disallowed origin or unknown key gets the opaque `404`. Tenant and executor keys sent with an `Origin` are refused before they are looked up. `Nylorun-Tenant` may be left out when `Nylorun-Key` names the Tenant; both must agree when both are sent. Browser access is on in the stack (`NYLORUN_BROWSER_ACCESS=off` turns it off) and off for a Host started from `host.json` unless `browserAccess` is true.
|
|
120
|
+
- **JWKS.** `GET /v1/access/jwks` is readable by any caller that reaches the Tenant.
|
|
121
|
+
- **Agents SDK.** `@nylorun/agents/browser`: `createBrowserClient({ url, publishableKey, token })` keeps subject tokens in memory, refreshes them a minute before expiry or after `401 token_expired`, one fetch at a time, and creates sessions and vaults owned by the token's subject; it loads no Node module. `createTokenEndpoint()` is the app server's token route. `client.access.publishableKeys` manages keys. The transport accepts a `token` source and a `publishableKey`, and event streams the Runtime ends at token expiry reconnect at once. The Tenant API client classes move to a module with no Node imports; `@nylorun/agents` and `/client` export the same names.
|
|
122
|
+
- **CLI.** `nylo access keys list|create|set-origins|revoke`.
|
|
123
|
+
|
|
124
|
+
- c121144: **Definitions no longer declare a sandbox.** `.sandbox()` on ReAct and flow agents, and the `sandbox`, `SandboxError`, `SandboxOptions` and `SandboxCapability` exports, are removed. Open the session with one instead, `createSession({ sandbox: { … } })`, or set the Tenant's default; see `MIGRATION.md`.
|
|
125
|
+
|
|
126
|
+
- **Build and registration.** A capability that still carries `sandbox` fails the build (`sandbox.in-definition`), and `PUT /v1/agents/:id` refuses such a definition with a `400` that names it. Definitions stored before this release keep their sandbox.
|
|
127
|
+
- **Trees.** `sandbox.mismatch` and `workflow.sandbox-mismatch` are gone, with the workflow manifest's derived `sandbox`: a tree shares the sandbox its session was opened with.
|
|
128
|
+
- **Executors.** The action claim reports whether the session has a sandbox (`ActionClaim.sandbox`), and `ctx.sandbox` follows it.
|
|
129
|
+
|
|
130
|
+
- 28c6115: **Every Tenant route is a Hono route, and paths are strict.** The Tenant API's hand-written router is gone. Each route is declared once with who may call it (credentials, subject scopes, browser access), in `api/http/routes/`, `api/ag-ui/` and `api/a2a/`. That one declaration now decides what the router's own tables (`routeAccess`, `isBrowserRoute`) decided: a subject's scopes and which browser preflights are allowed. Routes answer as before.
|
|
131
|
+
|
|
132
|
+
A path or method that no route serves is now authenticated like any other request (an unknown credential is still the opaque `404`) and then answered `404 request_rejected` "Route not found". Before, the router matched loosely, and some of these requests reached a route or got another answer:
|
|
133
|
+
|
|
134
|
+
- **Extra path segments:** `POST /v1/sessions/:id/commands/…`, `GET /v1/sessions/:id/items/…` and `/events/…`, `GET /v1/executors/connect/…` and `POST /v1/actions/:id/claim/…` (and `/heartbeat/…`) no longer reach those routes.
|
|
135
|
+
- **`GET /v1/actions/:id`** is `404`, not `400 Invalid JSON`.
|
|
136
|
+
- **A trailing slash or an empty segment** (`/v1/sessions/`, `/v1//sessions`, `/v1/agents/`) is `404`. Before, it was served as the route without it.
|
|
137
|
+
- **An unknown path under a known resource:**
|
|
138
|
+
- An unknown sub-route of a session is `404 Route not found`, even when the session is missing (before: "Session not found").
|
|
139
|
+
- A subject calling an unknown path under `/v1/executors`, `/v1/actions`, `/v1/tokens` or `/v1/access` gets `404` (before: `403 scope_required`).
|
|
140
|
+
- An executor calling any path or method no route serves gets `404` (before: `403 Application credential required`).
|
|
141
|
+
- **`HEAD`** is `404` for every caller.
|
|
142
|
+
- **Browser preflights** for paths no route serves (for example `/v1/sessions/:id/unknown`, `/v1/ag-ui/anything`), or for a method a route lacks, are refused (`403`) instead of allowed.
|
|
143
|
+
|
|
144
|
+
**`TenantHandle.handle` is removed**; the Host reaches a Tenant with `TenantHandle.fetch(request, { incoming, outgoing })`.
|
|
145
|
+
|
|
146
|
+
- 101bb6f: **The Runtime serves HTTP through Hono.** The Host's request pipeline (Origin, Content-Type, `/health`, `/ready`, the Admin API and Tenant resolution) is now a Hono app served by `@hono/node-server`. It answers byte for byte as before. `hono`, `@hono/zod-openapi` and `zod` are now dependencies. Routes move to Hono group by group in later releases.
|
|
147
|
+
|
|
148
|
+
- **`TenantHandle.fetch(request, { incoming, outgoing })`** is how the Host reaches an open Tenant. `TenantHandle.handle(request, response, url)` is deprecated and optional, and will be removed once every Tenant route is on Hono. Code that implements `TenantHandle` must add `fetch`.
|
|
149
|
+
- **The process's globals are left alone.** An app that embeds the Runtime (`startEphemeralRuntime`) keeps its own `Request` and `Response`. The Runtime also answers correctly in a process where `@hono/node-server`'s `serve()` has already replaced them.
|
|
150
|
+
- **A request target that is not a path** (such as `OPTIONS *`) is `400 invalid_request` "Invalid request target".
|
|
151
|
+
|
|
152
|
+
- 6ab4c59: **Long sessions on any model: compaction.** A session whose history outgrows the model's context window keeps going, on a 16k local model as on a 1M hosted one.
|
|
153
|
+
|
|
154
|
+
- **Compaction.**
|
|
155
|
+
- **When.** Before each model call the engine estimates the prompt: the last reported usage, plus about four characters per token for what came after. If the estimate would not leave room for the reply, the engine first compacts: it asks the model to summarize the older history, then keeps about the newest 20,000 tokens (at most 30% of the window) verbatim.
|
|
156
|
+
- **What it keeps.** The cut never separates a tool call from its result. The current turn's request is always kept. A later compaction merges with the earlier summary.
|
|
157
|
+
- **Overflow.** If a provider still reports a context overflow, the engine compacts once and asks again.
|
|
158
|
+
- **Storage.** The summary is a `compaction` transcript entry that replaces the older entries in the session state; the event log keeps the full history. The summary call is a journaled model effect, so replays are deterministic.
|
|
159
|
+
- **New event.** `context.compacted` (`trigger`, `tokensBefore`, `tokensAfter`).
|
|
160
|
+
- **Custom endpoints.**
|
|
161
|
+
- **Settings.** Model Settings take `settings: { contextWindow, maxTokens, reasoning, compat }` for a custom OpenAI-compatible provider (vLLM, SGLang, llama.cpp, Ollama, LM Studio). `compat` is passed to pi-ai: `thinkingFormat`, `thinkingTokenBudgetField`, `chatTemplateKwargs` and the rest.
|
|
162
|
+
- **Defaults.** Without settings, a custom endpoint is assumed to have a 32k window and an 8k output limit. They used to be 128k and 16k.
|
|
163
|
+
- **Where to set them.** `nylo configure` asks for the window and output limit. Studio's Model Settings shows all four fields.
|
|
164
|
+
- **Storage.**
|
|
165
|
+
- Model effects no longer journal the model request next to the call, so each call's prompt is stored once.
|
|
166
|
+
- When a turn ends, its model effects are slimmed to their identity and status; the transcript holds the answers.
|
|
167
|
+
- Session storage now grows with the window, not with the square of the session's length.
|
|
168
|
+
- **Core.**
|
|
169
|
+
- `TranscriptEntry` adds `compaction` (`TranscriptCompactionEntry`).
|
|
170
|
+
- `ModelAdapterContext.compaction` marks a summary call.
|
|
171
|
+
- `CustomModelSettings` / `CustomModelSettingsSchema` describe the custom endpoint settings.
|
|
172
|
+
|
|
173
|
+
- 6ab4c59: **Model calls don't strand sessions.** A model provider failure is now a known outcome, not a lost call. The Runtime retries what can be retried, and otherwise fails the turn with `model.<code>`, so the session accepts the next message instead of sitting `uncertain` until it is cancelled.
|
|
174
|
+
|
|
175
|
+
- **Runtime.**
|
|
176
|
+
|
|
177
|
+
- **Upgrade.** The model adapter moves to pi-ai 0.99.1 and always streams.
|
|
178
|
+
- **Per-call settings.**
|
|
179
|
+
- Every call carries the session id, so OpenAI and other providers reuse the prompt cache and route to the same backend.
|
|
180
|
+
- Provider auth no longer reads the process environment.
|
|
181
|
+
- Rate limits, overloads, timeouts and transient errors are retried: 3 attempts with backoff, honouring `Retry-After`.
|
|
182
|
+
- A stream that produces nothing for 300 s is aborted and retried. `TenantConfig.modelCall` sets attempts, backoff, the idle timeout and the request timeout.
|
|
183
|
+
- **Failures.** Anything else fails the turn with one of these codes:
|
|
184
|
+
|
|
185
|
+
- `model.context_overflow`, `model.rate_limited`, `model.overloaded`, `model.timeout`, `model.transient`
|
|
186
|
+
- `model.content_policy`, `model.auth` (whose message says where to fix the credential)
|
|
187
|
+
- `model.invalid_request`, `model.invalid_output`
|
|
188
|
+
|
|
189
|
+
Only a call whose outcome was lost, such as a Worker dying mid-call, is still `uncertain`.
|
|
190
|
+
|
|
191
|
+
- **Structured output.** A structured final answer is repaired (control characters, a Markdown code fence) before it is parsed.
|
|
192
|
+
- **Model history.** Replayed history keeps the model that produced each message, so a model switch no longer sends one model's signatures or tool-call ids to another. Reasoning from OpenAI-compatible servers (`reasoning_content`, `reasoning`) is sent back only within the turn that produced it.
|
|
193
|
+
|
|
194
|
+
- **Events.**
|
|
195
|
+
- `message.assistant` adds `model` (`provider`, `model`), `finishReason` and `usage`.
|
|
196
|
+
- A new `model.failed` transcript event (`code`, `message`, `retryable`) is written instead of `message.assistant` when a call fails.
|
|
197
|
+
- **Core and harness.**
|
|
198
|
+
- New types and helpers: `ModelFailureOutcome`, `ModelFailureCode`, `MODEL_FAILURE_CODES`, `isModelFailureOutcome`, `ModelProducer`.
|
|
199
|
+
- `PromptItem` assistant messages may carry `producer`.
|
|
200
|
+
- `ModelUsage` adds `cacheWriteTokens`.
|
|
201
|
+
- A model adapter may return a failure outcome.
|
|
202
|
+
- The durable engine version is `hosted-3`: a turn that is running when the Runtime is upgraded fails once with `execution.incompatible`, and the next message works.
|
|
203
|
+
- **CLI.**
|
|
204
|
+
- `nylo configure` passes a stable installation id to OAuth logins that need one (OpenAI "Sign in with ChatGPT"), stored as `cli-installation-id` in the Host root.
|
|
205
|
+
- A custom OpenAI-compatible provider now prompts for its API key instead of failing.
|
|
206
|
+
|
|
207
|
+
- 10c3bb9: **OpenAPI 3.2 documents for the Runtime's APIs.** Both documents are generated from the routes as declared for serving, so they can't drift from what the Runtime answers. Load either into any OpenAPI 3.2 tool, for example Scalar, to render API docs.
|
|
208
|
+
|
|
209
|
+
- **Tenant API:** `@nylorun/runtime/openapi.json`, also served at `GET /openapi.json`. The document route needs no key and refuses a browser `Origin`, as `/health` does.
|
|
210
|
+
- **Admin API:** `@nylorun/runtime/admin-openapi.json`, also served at `GET /v1/admin/openapi.json` with the admin key, on the operator listener when there is one.
|
|
211
|
+
- **Who may call each operation:** its `security` (application key, subject token, publishable key, executor key, admin key), plus `x-nylorun-credentials`, `x-nylorun-scopes` and `x-nylorun-browser`.
|
|
212
|
+
- **Event streams** are documented as `text/event-stream` with an `itemSchema`.
|
|
213
|
+
- **Deprecation:** the executor routes are marked deprecated.
|
|
214
|
+
- **Drift check:** committed snapshots in `runtime/openapi/` make every API change a reviewable diff, and `check-package` fails when the routes and the snapshots disagree.
|
|
215
|
+
|
|
216
|
+
- 50d0fb5: **The Admin API on its own listener.** A Runtime can serve the Admin API on an operator listener, so the port that faces browsers and reverse proxies serves the Tenant API alone. The stack does this by default.
|
|
217
|
+
|
|
218
|
+
- **Runtime.** With an operator listener (`adminPort` in `host.json`, or `NYLORUN_ADMIN_LISTEN_PORT`, `NYLORUN_ADMIN_LISTEN_HOST` and `NYLORUN_ADMIN_ALLOWED_HOSTS` in a container), the public listener answers `/v1/admin/**` with the opaque `404` and the operator listener serves the Admin API, Host shutdown and the Tenant API, never to browsers. Each checks `Host` against its own port. `/ready` needs both listening; a taken port on either exits with code 98. Without one, a single listener serves everything as before.
|
|
219
|
+
- **Stack.** `nylorun start` publishes the operator port on loopback (`NYLORUN_ADMIN_PORT`, default 8788), writes it to `host.json` as `adminPort`, and points Studio at `runtime:4001`. `nylorun status` prints it.
|
|
220
|
+
- **Admin client.** Reads `adminPort` from `host.json` and sends Admin API requests there (`admin.adminUrl`); `admin.url` stays the Tenant API URL. A `host.json` without `adminPort` keeps working.
|
|
221
|
+
|
|
222
|
+
- c121144: **Choose a session's sandbox when you open it.** `createSession({ sandbox })` (`PutSessionRequest.sandbox`) now takes `false`, `{ session }` to share, or an inline sandbox: `image`, `network.allow` and `resources`. Omit it for the Tenant's default. The agent definition needs no `.sandbox()`: the Runtime resolves the request against the Tenant's limits, pins it on the session and adds the six sandbox tools to that session only (capability `nylorun.sandbox`). The registered definition is unchanged.
|
|
223
|
+
|
|
224
|
+
- **Tenant configuration.** `GET /v1/tenant/sandbox` adds `config`; `PUT /v1/tenant/sandbox` sets `default` (`none`, `virtual` or an inline sandbox) and `limits` (`network` ceiling, `resources` maximum, `defaultResources`, `idle`). Unset, a Tenant's default is `none` and its ceiling is the package registries and code hosts of today's `dev` preset. `SeedTenantConfigRequest.sandbox.config` seeds it.
|
|
225
|
+
- **Checks at open.** A request outside the limits is a `400` that lists every problem. An inline sandbox from a caller acting for a subject is a `403`; such callers get the Tenant default or `false`. An `image` is refused: the virtual sandbox has no images. The sandbox is fixed for the session's life: a different one on a later `PUT` is a `409`.
|
|
226
|
+
- **Trees inherit.** The agent sessions of a flow agent, the agents a session uses as tools, and sessions attached with `{ session }` use the sandbox the session was opened with, and get its tools.
|
|
227
|
+
- **Compatible.** An agent that declares `.sandbox()` keeps working as before; opening its session with a `sandbox` value is a `400` that says to remove `.sandbox()` from the agent.
|
|
228
|
+
|
|
229
|
+
- 6ab4c59: **Long turns roll over.** A turn no longer fails when it runs past the 50-minute advance deadline.
|
|
230
|
+
|
|
231
|
+
- **How it works.** At a step boundary with no open work, a long turn ends its segment and continues in the next one: same turn, a new checkpoint, woken at once. By default this happens after 50 steps or 20 minutes in a segment; `TenantConfig.rollover` changes both.
|
|
232
|
+
- **What clients see.** A rolled-over turn emits no `turn.*` event, and clients still see one turn.
|
|
233
|
+
- **Storage.** Each finished segment's model effects are slimmed.
|
|
234
|
+
- **Harness.** `runDurable` takes `yieldAfter: { steps, ms }` and can return `yielded`, and `RunResult` adds `yielded`. The durable host writes the next checkpoint at `segment + 1` with `{ kind: "continue" }`. Agents used as tools never roll over.
|
|
235
|
+
|
|
236
|
+
- 9546ac7: **The stream relay, ready to wire in.** The Runtime gains the relay that will feed S2 from a Postgres record of session events over logical replication (Durable Streams v1); nothing uses it yet.
|
|
237
|
+
|
|
238
|
+
- **Relay core** (`streams/relay/`): per-session pumps appending with `matchSeq`, acknowledgements only after S2 has the rows, refills from the record on a gap, reconciliation after a new or lost slot, and rows of an old basin generation dropped.
|
|
239
|
+
- **Change source** (`adapters/replication/pgoutput.ts`): a persistent `pgoutput` slot, one active process per slot, always resumed from the confirmed position; a pending reconciliation is kept in `nylorun_streams.relay_slots` so a crash cannot skip it.
|
|
240
|
+
- **Shared schema** (`nylorun_streams`): `session_events`, `session_log_heads`, `relay_slots` and the `nylorun_stream_relay` publication, migrated by the Host.
|
|
241
|
+
- **Basin generations**: `basinOf(tenantId, generation)` names a Tenant's later basins (`<basin>-<g base36>`).
|
|
242
|
+
- **Local stack**: Postgres runs with `wal_level=logical` and `max_slot_wal_keep_size=4GB`. `nylorun start` recreates the Postgres container once; its data volume is kept. `DEPLOYMENT.md` lists the settings for a Postgres you run yourself.
|
|
243
|
+
|
|
244
|
+
- 50d0fb5: **Subject tokens: a person's own credential for the Runtime.** An app server mints a short-lived token for one signed-in person, and their app calls the Runtime directly (optional Host feature `subject-tokens`). Requests with application keys and subject headers are unchanged.
|
|
245
|
+
|
|
246
|
+
- **Runtime.** `POST /v1/tokens` (application key only) mints an ES256 JWT for a subject and a role, valid 60–900 seconds. The Tenant API accepts it as a bearer and resolves its scopes and agents from the role on every request. Forged, foreign or malformed tokens get the opaque `404`; an expired token, a revoked subject, a revoked key or a removed role gets `401 token_expired` with `WWW-Authenticate`. Tokens carry only `agents:read`, `sessions:own` and `vaults:own`; they may not set session `info`, send `message.manifest` or store OAuth refresh credentials, and `GET /v1/agents` shows them `{ agentId, name, description }` of their role's agents only.
|
|
247
|
+
- **Access policy.** `GET`/`PUT /v1/access/policy`: roles with token scopes, an agent allowlist and limits (`turnsPerHour`, `concurrentTurns`, answered with `429 limit_exceeded` and `Retry-After`). Without roles nothing is minted.
|
|
248
|
+
- **Signing keys.** Per Tenant, the private key sealed with the vault KEK: `GET /v1/access/signing-keys`, `POST …/rotate` (refused while the previous key may still verify live tokens; `force` for incidents), `POST …/:kid/revoke`, `GET /v1/access/jwks`. A Tenant with signing keys and no KEK is quarantined `kek-missing`.
|
|
249
|
+
- **Revocation.** `POST /v1/access/revocations` ends a subject's tokens; their open event streams end with `event: nylorun.closed` on every process. A stream opened with a token also ends when the token expires.
|
|
250
|
+
- Postgres migration 3 adds `signing_keys`, `subject_epochs`, `subject_usage` and an index on the session owner and status. New error codes `token_expired` and `limit_exceeded`.
|
|
251
|
+
- **Agents SDK.** `client.tokens.create()`, `client.access.getPolicy()`/`putPolicy()`/`revokeSubject()`/`jwks()` and `client.access.signingKeys.list()`/`rotate()`/`revoke()`, each checking the Host feature first.
|
|
252
|
+
- **CLI.** `nylo access policy get|set|init`, `nylo access signing-keys list|rotate|revoke`, `nylo access revoke <subject>` and `nylo access token` for trying the API.
|
|
253
|
+
|
|
254
|
+
### Patch Changes
|
|
255
|
+
|
|
256
|
+
- f82752e: **Action endpoints: Durable Session Execution can run deliveries (groundwork, unused yet).** The Worker endpoint registers a fourth Restate virtual object, `NylorunAction` (key `<tenantId>:<actionId>`), whose `deliver` handler runs one Action's delivery at a time and re-sends itself after a delay when the delivery asks to be retried. The in-process execution does the same. Nothing schedules deliveries yet. Operators will see the new service in Restate, and its paused invocations appear in the Tenant status with the others.
|
|
257
|
+
- 4135d23: **The Admin API is declared as Hono routes.** Each `/v1/admin/**` route is declared once, for serving and for the Runtime's OpenAPI document (`host/admin-api.ts`). Answers are unchanged, apart from strict paths:
|
|
258
|
+
|
|
259
|
+
- A trailing slash (`/v1/admin/tenants/`) or an empty segment (`/v1//admin/tenants`) no longer reaches a route. With the admin key it is `404 not_found` "Route not found"; before, it was served as the route without the slash.
|
|
260
|
+
|
|
261
|
+
- 3da8769: **HTTP fixes ahead of the move to Hono.**
|
|
262
|
+
|
|
263
|
+
- **Shutdown no longer waits for open streams.** Stopping the Runtime used to wait for every session-event, executor and AG-UI stream client to disconnect. It now ends open streams (clients see the stream end and reconnect), lets other requests in progress finish, and closes any connection still open after 10 seconds (`host_shutdown_forced` in the log).
|
|
264
|
+
- **Sandbox tool calls stop when their caller leaves.** `POST /v1/sessions/:id/sandbox/:tool` and `POST /v1/actions/:id/sandbox/:tool` now see the client disconnect. Before, the abort signal never fired once the request body had been read.
|
|
265
|
+
- **Multibyte request bodies.** A UTF-8 character whose bytes arrive in different chunks is no longer corrupted.
|
|
266
|
+
- **Malformed paths.** A path with invalid percent-encoding (such as `%E0%A4%A`) is `400 request_rejected` "Malformed path", not `500`.
|
|
267
|
+
- **Failures after a response started.** When a Tenant fails after starting its response, the Host ends that response instead of trying to send a second one.
|
|
268
|
+
- **Listener errors** after the Runtime starts listening are logged (`listener_error`) instead of being dropped.
|
|
269
|
+
|
|
270
|
+
- 2ab8ed1: **Schemas for every Runtime answer.** `@nylorun/core/contracts` now has a Zod schema for each successful response of the Tenant and Admin APIs that lacked one, so clients can validate what they receive and the Runtime's OpenAPI document can be generated from them.
|
|
271
|
+
|
|
272
|
+
- **Agents:** `ListAgentsResponseSchema` (`AgentDefinitionViewSchema`), `ListPublicAgentsResponseSchema` (`PublicAgentSchema`) and `PutAgentResponseSchema`.
|
|
273
|
+
- **Sessions:** `ListSessionsResponseSchema` (`SessionSummarySchema`, `SESSION_STATUSES`) and `SessionViewSchema`.
|
|
274
|
+
- **Executors and actions:** `ListActionsResponseSchema`, `ActionHeartbeatResponseSchema`, `DeleteExecutorResponseSchema` and `SandboxToolOutcomeSchema`.
|
|
275
|
+
- **Tenant settings:** `ResetTenantResponseSchema`, `HostModelCatalogSchema`, `ListProvidersResponseSchema` (`HostModelProviderInfoSchema`), and `TenantSandboxViewSchema` with `EffectiveSandboxConfigSchema` (the configuration with defaults applied, sizes in MiB).
|
|
276
|
+
- **Vaults:** `VaultInfoSchema`, `CredentialInfoSchema`, `ListVaultsResponseSchema`, `ListCredentialsResponseSchema` and `DeletedResponseSchema`. `VaultInfo`, `CredentialInfo` and `HostModelProviderInfo` are now inferred from their schemas; their fields are no longer `readonly`.
|
|
277
|
+
- **Access:** `AccessPolicyResponseSchema` and `ListPublishableKeysResponseSchema`.
|
|
278
|
+
- **Admin:** `AdminTenantListSchema` and `HostShutdownResponseSchema`.
|
|
279
|
+
- **Streams:** `StreamClosedFrameSchema` (the `nylorun.closed` frame) and `AgUiRunErrorCodeSchema` (codes of an AG-UI `RUN_ERROR`, which add `session_busy` and `runtime_error`).
|
|
280
|
+
|
|
281
|
+
`ERROR_CODES` gains `request_rejected`, `invalid_request`, `subject_required` and `internal_error`, codes the Runtime already sends. `RejectedResponseSchema` now accepts every rejection the Runtime makes. An exhaustive `switch` over `ErrorCode` needs the new cases.
|
|
282
|
+
|
|
283
|
+
- f296363: **Runtime lifecycle fixes.**
|
|
284
|
+
|
|
285
|
+
- **Stream relay.** Stopping the relay while its change source was still preparing the replication slot no longer hangs shutdown with the slot held.
|
|
286
|
+
- **MCP connections.** A connection a session has not used for 15 minutes is closed by the Tenant sweep, and the next call opens it again, as after a restart. Before, every stdio MCP server a session started kept running until the Tenant closed. Concurrent calls to a server that is not connected now share one connection instead of each opening one and leaking all but the last.
|
|
287
|
+
- **Tenant close.** Every close step runs even when an earlier one fails, so a failing MCP or sandbox close no longer leaves the stream readers, the relay and the store open. The first error is still rethrown, and each failed step is logged as `tenant close step failed`.
|
|
288
|
+
|
|
289
|
+
- bb999c0: **Runtime robustness fixes.**
|
|
290
|
+
|
|
291
|
+
- **Stream relay.** After a fresh replication slot, the relay marks the record reconciled only once every re-sent row is in S2. Before, it did so once the rows were queued, so losing the connection or the process before they reached S2 left those sessions' streams missing events until their next write.
|
|
292
|
+
- **Vault OAuth refresh.** Concurrent uses of an expired grant in one process share one refresh, instead of each spending the refresh token. A refresh that loses a race with another process uses the token that process stored instead of failing with `refresh_failed`. A token endpoint that takes more than 30 s fails the refresh (`VaultServiceOptions.refreshTimeoutMs`).
|
|
293
|
+
- **Postgres.** Connections of the Host's pool have `statement_timeout` and `idle_in_transaction_session_timeout` of 60 s, so a hung statement or abandoned transaction no longer holds a shared connection and its locks forever (`PostgresClientOptions.statementTimeoutMs` and `idleInTransactionTimeoutMs`; 0 turns either off). Schema migrations and Tenant deletion run without the statement timeout.
|
|
294
|
+
- **Ephemeral runtime.** `startEphemeralRuntime` closes what it opened, and removes its Host root unless retained, when it fails to start.
|
|
295
|
+
|
|
296
|
+
- 9546ac7: **A session's first events reach readers at once.** Tenant basins now create a stream on read, so a client that opens SSE before a session's first event follows the stream live instead of polling for it with a backoff of up to 2 s. Existing basins are updated when their Tenant opens.
|
|
297
|
+
- 9546ac7: **Durable Streams failure suite and latency gate.** New integration tests run the stream relay on Postgres logical replication and s2-lite through a relay crash mid-stream, a 10 s S2 outage, a slot invalidated by `max_slot_wal_keep_size`, and a takeover by another process, checking that every S2 stream equals the record. An opt-in benchmark (`NYLORUN_BENCH=1`) holds commit to S2 under 200 ms at p99 with 50 sessions.
|
|
298
|
+
- 9546ac7: **`LiveHub` is now `SessionStreams`.** Internal rename, no behaviour change: a process's readers of Durable Streams are `ctx.sessionStreams` (`tenant/session-streams.ts`), with one `SessionStream` per observed session.
|
|
299
|
+
- 4b64d57: **The A2A endpoint on Hono.** `POST /v1/a2a/agents/:agent` (A2A JSON-RPC, for a subject) and `GET /v1/a2a/agents/:agent/card` are declared as Hono routes (`api/a2a/endpoint.ts`). The Runtime's OpenAPI document describes the JSON-RPC envelope and links the A2A specification. Answers are unchanged: the legacy dispatcher and the routes share one implementation.
|
|
300
|
+
- 7add998: **Access routes on Hono.** `POST /v1/tokens`, the access policy, signing keys, publishable keys, subject revocations and the public keys (`GET /v1/access/jwks`, open to any caller that reached the Tenant) are declared as Hono routes (`api/http/routes/access.ts`), with who may call each for the Runtime's OpenAPI document. Answers are unchanged.
|
|
301
|
+
- f4ca1c8: **The AG-UI endpoint on Hono.** Its four routes (run, thread messages, reattach, cancel under `/v1/ag-ui/agents/:agent`) are declared as Hono routes (`api/ag-ui/endpoint.ts`), documented with AG-UI's own schemas (`RunAgentInput`, the event union, `Message`). Answers and streams are unchanged: the legacy dispatcher and the routes share one implementation.
|
|
302
|
+
- 18468d9: **Tenant routes start moving to Hono.** The executor and Action routes and session commands (`/v1/executors/connect`, `/v1/actions/**`, `/v1/executors`, `/v1/executors/:agentId` and `POST /v1/sessions/:id/commands`) are declared as Hono routes (`api/http/routes/executors.ts`). Each says who may call it: its credentials, subject scopes and browser access. The Runtime's OpenAPI document shows this, and the executor routes are marked deprecated there, since Action endpoints replace them. Answers are unchanged. A path the new routes don't match exactly still goes to the router they replace, so its answer is unchanged too.
|
|
303
|
+
|
|
304
|
+
**Core:** the recursive contract schemas (JSON values, workflow nodes and manifests, and an agent used as a tool) carry a Zod `id`, so documents generated from them refer back to the named schema instead of recursing. Parsing is unchanged.
|
|
305
|
+
|
|
306
|
+
- 43fcbee: **Agent and session routes on Hono.** `GET /v1/agents`, `PUT /v1/agents/:id`, `GET /v1/sessions`, `PUT` and `GET /v1/sessions/:id`, `GET /v1/sessions/:id/items`, the session event stream (`GET /v1/sessions/:id/events`) and `POST /v1/sessions/:id/sandbox/:tool` are declared as Hono routes (`api/http/routes/sessions.ts`), with who may call each for the Runtime's OpenAPI document. Answers are unchanged.
|
|
307
|
+
- 469b052: **Tenant settings and vault routes on Hono.** `/v1/tenant/**` (status, reset, config seed, models, providers, model and model selection, sandbox configuration) and `/v1/vaults/**` (vaults and credentials) are declared as Hono routes (`api/http/routes/tenant.ts`, `api/http/routes/vaults.ts`), with who may call each for the Runtime's OpenAPI document. Answers are unchanged: an executor calling them is still refused and recorded, and a subject's vault is still checked as theirs before anything else.
|
|
308
|
+
- Pin core to the tested release.
|
|
309
|
+
- Pin harness to the tested release.
|
|
310
|
+
- Updated dependencies [c7614a4]
|
|
311
|
+
- Updated dependencies [679c488]
|
|
312
|
+
- Updated dependencies [c85cd9e]
|
|
313
|
+
- Updated dependencies [4282d5f]
|
|
314
|
+
- Updated dependencies [82d95ef]
|
|
315
|
+
- Updated dependencies [f48f12f]
|
|
316
|
+
- Updated dependencies [50d0fb5]
|
|
317
|
+
- Updated dependencies [50d0fb5]
|
|
318
|
+
- Updated dependencies [c121144]
|
|
319
|
+
- Updated dependencies [6ab4c59]
|
|
320
|
+
- Updated dependencies [6ab4c59]
|
|
321
|
+
- Updated dependencies [2ab8ed1]
|
|
322
|
+
- Updated dependencies [c121144]
|
|
323
|
+
- Updated dependencies [6ab4c59]
|
|
324
|
+
- Updated dependencies [9546ac7]
|
|
325
|
+
- Updated dependencies [9546ac7]
|
|
326
|
+
- Updated dependencies [9d52189]
|
|
327
|
+
- Updated dependencies [50d0fb5]
|
|
328
|
+
- Updated dependencies [18468d9]
|
|
329
|
+
- Updated dependencies
|
|
330
|
+
- @nylorun/core@0.9.0-beta
|
|
331
|
+
- @nylorun/harness@0.21.0-beta
|
|
332
|
+
|
|
333
|
+
## 0.13.0-beta
|
|
334
|
+
|
|
335
|
+
### Minor Changes
|
|
336
|
+
|
|
337
|
+
- 5278b4e: **Flow agents on workflow manifest v2.** A flow agent compiles to `workflowSchemaVersion: 2` and runs on the new `flow-2` engine; v1 workflows (`Chain`, `Switch`, `Parallel`, `Map`, `Loop`) keep running on `flow-1`, so in-flight runs finish as they began.
|
|
338
|
+
|
|
339
|
+
- **Manifest (core).** Any node may carry `id` and `input`; there are no slots. `chain` and `parallel` are bare collections, a Map is `{ map: { each } }` over its input, and a Loop has `max?` and `decide?`. The header adds `name`, `description`, `metadata`, `inputSchema` and `outputSchema`, and `agents` embeds every agent the flow runs, so one manifest hash covers the whole flow. `Agent.from(json, { nodes, agents })` rebuilds a flow agent. Path and key helpers (`leafPath`, `stageKey`, `forEachFlowNode`, `embeddedAgent`, …) are exported from `@nylorun/core/define`.
|
|
340
|
+
- **Paths (harness).** Linked agent sessions are named by the agent: its id, `[i]` per Map item, and a nested flow agent's id in front. Control stages add nothing, so wrapping a step in a Loop keeps its session. Functions are bound under stage keys (`route:on`, `@1.default.1:input`) and all receive `{ input, results, flowInput }`; `flowInput` works inside nested `flow()`. A Loop without `decide` retries with the verifier's feedback up to `max` and then fails with `loop.exhausted`. Nested flow agents run inline.
|
|
341
|
+
- **Runtime.** Leaves of a v2 workflow resolve from its embedded `agents` (with the workflow's plugin roots, keyed `<agent>/<capability>`) instead of the registry. `loop.iteration` is emitted only for a Loop's own agent turns.
|
|
342
|
+
- **Agents SDK.** `saveAgent(flowAgent)` PUTs one document; application mode registers the flow's executor with its manifest hash. An executor leaves `fn`, `verify` and tool actions of a v2 flow unclaimed when they belong to another manifest hash, because stage keys can shift between deploys; it reports each skipped action once through `onError`.
|
|
343
|
+
- **Studio.** Draws v2 manifests: agents and tools at their session paths, control stages at their stage keys, nested flow agents inline, and lights a Map's agent from its item sessions.
|
|
344
|
+
- Build diagnostics: `flow.duplicate-leaf`, `flow.duplicate-id`, `flow.agent-conflict`, `flow.v1-workflow`, `loop.invalid-verify`, `workflow.flow-agent-child`. Also fixes v1 flows passing an agent step's output to the next step still wrapped in the runtime's turn marker.
|
|
345
|
+
|
|
346
|
+
- 426fd27: **Flow agents as subagents.** `.subagents(flowAgent)` lets a ReAct agent delegate to a flow agent. The flow's workflow manifest v2 is inlined in the delegating tool (`ToolManifest.agent` may be a workflow manifest), so it is saved with the parent and served by the parent's executor, plugin roots included (`<flow>/<agent>/<capability>`).
|
|
347
|
+
|
|
348
|
+
- **Engine (harness).** A call to a flow subagent is one durable `agent` effect (`role: "delegate"`) between the delegation's start and settle points; the flow's output is the tool result, and a failed flow is a failed tool result. Local `run()` refuses flow subagents, which need the Runtime.
|
|
349
|
+
- **Runtime.** The effect starts a linked flow session from the parent's pinned manifest, fresh per call, and settles when the flow's turn ends. Cancelling any session now cascades to the linked sessions it started, not only a workflow's.
|
|
350
|
+
- **Core.** `delegation.flow-unsupported` now only reports a workflow built with `Chain`, `Switch`, `Parallel`, `Map` or `Loop`. New helpers: `flowDelegatesOf`, `flowDelegateManifest`, `isFlowDelegate`; `delegatesOf` lists only the ReAct agents run in-process.
|
|
351
|
+
|
|
352
|
+
### Patch Changes
|
|
353
|
+
|
|
354
|
+
- Pin core to the tested release.
|
|
355
|
+
- Pin harness to the tested release.
|
|
356
|
+
- Updated dependencies [e537a82]
|
|
357
|
+
- Updated dependencies [5278b4e]
|
|
358
|
+
- Updated dependencies [426fd27]
|
|
359
|
+
- Updated dependencies [8cda500]
|
|
360
|
+
- Updated dependencies
|
|
361
|
+
- @nylorun/core@0.8.0-beta
|
|
362
|
+
- @nylorun/harness@0.20.0-beta
|
|
363
|
+
|
|
3
364
|
## 0.12.0-beta
|
|
4
365
|
|
|
5
366
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -37,7 +37,17 @@ sets: `NYLORUN_DATABASE_URL` (required), `NYLORUN_RESTATE_INGRESS_URL`,
|
|
|
37
37
|
`NYLORUN_RESTATE_ADMIN_URL`, `NYLORUN_WORKER_URL` and
|
|
38
38
|
`NYLORUN_RESTATE_IDENTITY_KEY` (Restate), `NYLORUN_S2_ENDPOINT` and
|
|
39
39
|
`NYLORUN_S2_TOKEN`, and in container mode `NYLORUN_LISTEN_HOST`,
|
|
40
|
-
`NYLORUN_LISTEN_PORT`, `NYLORUN_ALLOWED_HOSTS` and `NYLORUN_PUBLIC_URL
|
|
40
|
+
`NYLORUN_LISTEN_PORT`, `NYLORUN_ALLOWED_HOSTS` and `NYLORUN_PUBLIC_URL`, plus
|
|
41
|
+
`NYLORUN_BROWSER_ACCESS` (`on` or `off`) and the operator listener
|
|
42
|
+
(`NYLORUN_ADMIN_LISTEN_PORT`, `NYLORUN_ADMIN_LISTEN_HOST`,
|
|
43
|
+
`NYLORUN_ADMIN_ALLOWED_HOSTS`).
|
|
44
|
+
|
|
45
|
+
With an operator listener (the stack's default: container port 4001), the Host
|
|
46
|
+
serves two ports. The public one serves the Tenant API, to browsers too when
|
|
47
|
+
browser access is on, and answers admin routes with the opaque `404`. The
|
|
48
|
+
operator one serves the Admin API, Host shutdown and the Tenant API, never to
|
|
49
|
+
browsers; keep it on loopback or a private network and never proxy it. Outside
|
|
50
|
+
a container, `adminPort` in `host.json` does the same on loopback.
|
|
41
51
|
|
|
42
52
|
The Host root is `NYLORUN_HOME` or `~/.nylorun` (bind-mounted at `/nylorun` in
|
|
43
53
|
the stack). What stays on the Host is under `tenants/<tenantId>/`.
|
|
@@ -46,7 +56,7 @@ the stack). What stays on the Host is under `tenants/<tenantId>/`.
|
|
|
46
56
|
|
|
47
57
|
```text
|
|
48
58
|
<host root>/
|
|
49
|
-
host.json # format 1: hostId, host, port, runtimeVersion, …
|
|
59
|
+
host.json # format 1: hostId, host, port, adminPort?, runtimeVersion, …
|
|
50
60
|
host-credentials.json # adminKey (0600)
|
|
51
61
|
stack/ # compose.yaml, .env (0600), Restate identity key
|
|
52
62
|
tenants/<tenantId>/ # vault-kek, plugin-data, logs, home, tmp, sandboxes
|
|
@@ -59,16 +69,58 @@ the stack). What stays on the Host is under `tenants/<tenantId>/`.
|
|
|
59
69
|
| --- | --- | --- |
|
|
60
70
|
| `GET /health` | none | `service: "nylorun-runtime"`, `hostId`, protocol `{min,max,features}`, pid |
|
|
61
71
|
| `GET /ready` | none | Listener up, Tenants discovered, and Postgres, Restate and S2 answer (`checks`) |
|
|
62
|
-
| `GET /
|
|
72
|
+
| `GET /openapi.json` | none | The Tenant API's OpenAPI 3.2 document (below); refuses an `Origin` |
|
|
73
|
+
| `GET /v1/admin/status` | admin key | `AdminStatusSchema`; alias `GET /v1/admin/host`. On the operator listener when there is one |
|
|
63
74
|
| `/v1/admin/tenants*` | admin key | Create / list / get / delete Tenants |
|
|
64
75
|
| `POST /v1/admin/host/shutdown` | admin key | Host-private; not in `@nylorun/admin` |
|
|
65
|
-
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
`415 unsupported_media_type`.
|
|
76
|
+
| `GET /v1/admin/openapi.json` | admin key | The Admin API's OpenAPI 3.2 document |
|
|
77
|
+
| `/v1/*` Tenant routes | application key, subject token or delivery token | Require `Nylorun-Tenant` (or `Nylorun-Key`) + `Nylorun-Protocol` |
|
|
78
|
+
|
|
79
|
+
Every route checks `Host` first (`421 host_rejected`) and rejects non-JSON bodies
|
|
80
|
+
with `415 unsupported_media_type`. An `Origin` is `403 origin_rejected` on
|
|
81
|
+
`/health`, `/ready`, admin routes, and everywhere when browser access is off.
|
|
82
|
+
With browser access on (feature `browser-access`: the stack's default, or
|
|
83
|
+
`browserAccess` in `host.json`), the Host answers preflights for browser routes
|
|
84
|
+
from the route alone, and the Tenant admits an `Origin` only with a publishable
|
|
85
|
+
key (`Nylorun-Key`) that lists it, adding CORS headers only then; Tenant keys
|
|
86
|
+
and delivery tokens are refused from browsers before they are looked up. A
|
|
87
|
+
publishable key also names the Tenant, so `Nylorun-Tenant` may be left out. Missing or unsupported protocol → `426` before
|
|
70
88
|
authentication. Unknown, quarantined or rejected Tenant credentials → opaque
|
|
71
|
-
`404` with identical body.
|
|
89
|
+
`404` with identical body. A path or method no route serves is `404 Route not found`
|
|
90
|
+
once the caller is known.
|
|
91
|
+
|
|
92
|
+
## API reference (OpenAPI)
|
|
93
|
+
|
|
94
|
+
The Runtime describes its APIs as OpenAPI 3.2 documents, generated from the routes it serves,
|
|
95
|
+
so they cannot drift from its answers:
|
|
96
|
+
|
|
97
|
+
| Document | In the package | Served | On each release |
|
|
98
|
+
| --- | --- | --- | --- |
|
|
99
|
+
| Tenant API | `@nylorun/runtime/openapi.json` | `GET /openapi.json` | `openapi.json` |
|
|
100
|
+
| Admin API | `@nylorun/runtime/admin-openapi.json` | `GET /v1/admin/openapi.json` (admin key) | `admin-openapi.json` |
|
|
101
|
+
|
|
102
|
+
The release assets are on the `@nylorun/runtime@<version>` GitHub Release. Point any OpenAPI 3.2
|
|
103
|
+
tool at one of them; for [Scalar](https://scalar.com), the package file of a version works as is:
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
https://cdn.jsdelivr.net/npm/@nylorun/runtime@<version>/dist/openapi.json
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Each operation's `security` says which credentials it takes (application key, subject token,
|
|
110
|
+
publishable key, delivery token, admin key), and its `x-nylorun-credentials`,
|
|
111
|
+
`x-nylorun-scopes` (the subject scopes that reach it) and `x-nylorun-browser` fields say who
|
|
112
|
+
may call it. Event streams are `text/event-stream` with an `itemSchema`. `runtime/openapi/` holds the committed snapshots: a change to a route changes
|
|
113
|
+
them (`node scripts/build-openapi.mjs --write`), and `check-package` fails until they are
|
|
114
|
+
updated.
|
|
115
|
+
|
|
116
|
+
## HTTP layer
|
|
117
|
+
|
|
118
|
+
Routes are Hono routes (`@hono/zod-openapi`), each declared once with who may call it
|
|
119
|
+
(`api/http/define.ts`): that declaration serves the route, checks subject scopes, answers
|
|
120
|
+
browser preflights and makes the OpenAPI document. `host/` holds the listeners, the `Host`
|
|
121
|
+
check (in Node, before Hono) and the Host pipeline (`host/app.ts`); `api/` the Tenant and
|
|
122
|
+
Admin routes (`api/http/routes/`, `api/ag-ui/`, `api/a2a/`, `host/admin-api.ts`). Only `host/`
|
|
123
|
+
and `api/` import Hono.
|
|
72
124
|
|
|
73
125
|
## Embedding and tests
|
|
74
126
|
|
|
@@ -79,8 +131,10 @@ its Tenants live in memory and are gone after `close()`. The smoke checks'
|
|
|
79
131
|
temporary Tenants (`scripts/lib/temporary-tenant.mjs`) do not use it; they are
|
|
80
132
|
created on the Docker stack.
|
|
81
133
|
|
|
82
|
-
Register
|
|
83
|
-
(
|
|
134
|
+
Register Action endpoints with `PUT /v1/endpoints` using the application principal
|
|
135
|
+
(`createActionHandler(...).register({ url })` in `@nylorun/agents` does this). The
|
|
136
|
+
Runtime delivers each Action there with an `http` or `https` POST, so the URL must be
|
|
137
|
+
reachable from the Runtime. Model gateway
|
|
84
138
|
and sandbox backend are Tenant configuration (vault / seed), not Host process
|
|
85
139
|
env.
|
|
86
140
|
|
|
@@ -88,9 +142,9 @@ env.
|
|
|
88
142
|
|
|
89
143
|
The session-first `/v1` API is specified in
|
|
90
144
|
[HOST_CONTRACT.md](../harness/HOST_CONTRACT.md). Application tokens authorize
|
|
91
|
-
definition/session APIs
|
|
92
|
-
|
|
93
|
-
|
|
145
|
+
definition/session APIs. The Runtime delivers Actions to Action endpoints, and a
|
|
146
|
+
delivery token authorizes only its own Action's heartbeat, result and sandbox calls.
|
|
147
|
+
Session observers cannot submit action results.
|
|
94
148
|
|
|
95
149
|
Postgres transactions persist session checkpoints, command receipts, individual
|
|
96
150
|
effects/actions, waits and the event outbox — **per Tenant schema**; history is
|
|
@@ -116,7 +170,7 @@ project's Tenant and writes its Project link; the project's `npm run dev` runs
|
|
|
116
170
|
| `corrupt` / `migration-failed` / `envelope-invalid` / `open-failed` / `open-timeout` | Follow the `nylo tenant status` repair string |
|
|
117
171
|
| `schema-too-new` | Run a Runtime at least as new as the one that migrated the schema |
|
|
118
172
|
| `426 protocol_unsupported` | Upgrade clients or Host to a compatible set |
|
|
119
|
-
| `421 host_rejected` / `403 origin_rejected` |
|
|
173
|
+
| `421 host_rejected` / `403 origin_rejected` | In a container, list the `Host` in `NYLORUN_ALLOWED_HOSTS`. From a browser, use a subject token and a publishable key that lists the page's origin, never a Tenant key |
|
|
120
174
|
| `503` for a Tenant | Postgres or Restate is unreachable; `GET /ready` names which |
|
|
121
175
|
| Port in use | Change `NYLORUN_PORT` in `<Host root>/stack/.env` and run `nylorun up` |
|
|
122
176
|
| Logs | `nylorun logs runtime` |
|
|
@@ -90,8 +90,10 @@ export declare class RestateExecution implements DurableExecution {
|
|
|
90
90
|
session: string;
|
|
91
91
|
tenant: string;
|
|
92
92
|
timer: string;
|
|
93
|
+
action: string;
|
|
93
94
|
};
|
|
94
95
|
wake(tenantId: string, sessionId: string, wake: Wake): Promise<void>;
|
|
96
|
+
deliver(tenantId: string, actionId: string): Promise<void>;
|
|
95
97
|
timer(tenantId: string, key: string, at: Date): Promise<void>;
|
|
96
98
|
armSweep(tenantId: string): Promise<void>;
|
|
97
99
|
disarmSweep(tenantId: string): Promise<void>;
|
|
@@ -106,8 +108,11 @@ export declare class RestateExecution implements DurableExecution {
|
|
|
106
108
|
start(handlers: WorkerHandlers): Promise<void>;
|
|
107
109
|
stop(): Promise<void>;
|
|
108
110
|
private definitions;
|
|
109
|
-
/**
|
|
110
|
-
|
|
111
|
+
/**
|
|
112
|
+
* Runs a Worker handler with a signal aborted by `stop` or by the end of the Restate
|
|
113
|
+
* attempt (`advance` and `deliver`).
|
|
114
|
+
*/
|
|
115
|
+
private runAborted;
|
|
111
116
|
/** Runs a Worker handler so that `stop` waits for it. Refuses once stopping; Restate retries. */
|
|
112
117
|
private runTracked;
|
|
113
118
|
private staleSweepMs;
|