@nylorun/runtime 0.13.0-beta → 0.15.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 +434 -0
- package/README.md +137 -41
- package/dist/adapters/execution/restate.d.ts +7 -2
- package/dist/adapters/execution/restate.js +40 -10
- package/dist/adapters/replication/pgoutput.d.ts +21 -0
- package/dist/adapters/replication/pgoutput.js +170 -0
- package/dist/adapters/streams/s2.js +37 -20
- package/dist/admin-openapi.json +570 -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 +8065 -0
- package/dist/api/components.js +82 -0
- package/dist/api/gate/keys.d.ts +14 -0
- package/dist/api/gate/keys.js +59 -0
- package/dist/api/gate/routes.d.ts +34 -0
- package/dist/api/gate/routes.js +235 -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 +122 -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 +266 -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 +11 -0
- package/dist/api/http/routes/tenant.js +244 -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 +137 -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 +16 -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/gates/contract.d.ts +51 -0
- package/dist/gates/contract.js +37 -0
- package/dist/gates/handler.d.ts +21 -0
- package/dist/gates/handler.js +55 -0
- package/dist/gates/http-client.d.ts +12 -0
- package/dist/gates/http-client.js +160 -0
- package/dist/gates/in-process.d.ts +32 -0
- package/dist/gates/in-process.js +42 -0
- package/dist/gates/inflight.d.ts +39 -0
- package/dist/gates/inflight.js +70 -0
- package/dist/gates/mcp-handler.d.ts +35 -0
- package/dist/gates/mcp-handler.js +142 -0
- package/dist/gates/meter.d.ts +24 -0
- package/dist/gates/meter.js +165 -0
- package/dist/gates/model-gate.d.ts +45 -0
- package/dist/gates/model-gate.js +1 -0
- package/dist/gates/tenant-vaults.d.ts +64 -0
- package/dist/gates/tenant-vaults.js +94 -0
- package/dist/gates/tool-calls.d.ts +51 -0
- package/dist/gates/tool-calls.js +64 -0
- package/dist/gates/tool-client.d.ts +12 -0
- package/dist/gates/tool-client.js +201 -0
- package/dist/gates/tool-contract.d.ts +116 -0
- package/dist/gates/tool-contract.js +64 -0
- package/dist/gates/tool-gate.d.ts +45 -0
- package/dist/gates/tool-gate.js +10 -0
- package/dist/host/admin-api.d.ts +23 -0
- package/dist/host/admin-api.js +74 -0
- package/dist/host/app.d.ts +34 -0
- package/dist/host/app.js +181 -0
- package/dist/host/config-for.d.ts +3 -1
- package/dist/host/config-for.js +3 -2
- 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 +36 -8
- package/dist/host/create-host.js +161 -330
- package/dist/host/execution.d.ts +20 -18
- package/dist/host/execution.js +2 -2
- package/dist/host/gates.d.ts +58 -0
- package/dist/host/gates.js +127 -0
- package/dist/host/http.d.ts +20 -4
- package/dist/host/http.js +81 -23
- package/dist/host/index.d.ts +1 -1
- package/dist/host/main.js +189 -58
- package/dist/host/stack-config.d.ts +91 -19
- package/dist/host/stack-config.js +246 -17
- package/dist/infra/database.d.ts +2 -2
- package/dist/infra/execution.d.ts +5 -5
- package/dist/infra/execution.js +8 -6
- package/dist/infra/index.d.ts +1 -1
- package/dist/infra/workers.d.ts +17 -17
- package/dist/infra/workers.js +9 -9
- package/dist/keys/client.d.ts +9 -0
- package/dist/keys/client.js +70 -0
- package/dist/keys/contract.d.ts +24 -0
- package/dist/keys/contract.js +12 -0
- package/dist/keys/keys.d.ts +41 -0
- package/dist/keys/keys.js +50 -0
- package/dist/mcp/connect.d.ts +43 -3
- package/dist/mcp/connect.js +12 -5
- package/dist/mcp/pool.d.ts +39 -3
- package/dist/mcp/pool.js +74 -11
- 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 +25889 -0
- package/dist/record/append.d.ts +51 -0
- package/dist/record/append.js +20 -0
- package/dist/record/envelope.d.ts +19 -0
- package/dist/record/envelope.js +49 -0
- package/dist/record/index.d.ts +11 -0
- package/dist/record/index.js +11 -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/postgres/connect.d.ts +25 -9
- package/dist/store/postgres/connect.js +27 -10
- package/dist/store/postgres/db.d.ts +16 -0
- package/dist/store/postgres/db.js +28 -0
- package/dist/store/postgres/drizzle/0000_foundation.sql +22 -0
- package/dist/store/postgres/drizzle/0001_baseline.sql +255 -0
- package/dist/store/postgres/drizzle/0002_stream_relay.sql +4 -0
- package/dist/store/postgres/drizzle/0003_tool_crossings.sql +9 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +34 -0
- package/dist/store/postgres/migrate.d.ts +68 -0
- package/dist/store/postgres/migrate.js +183 -0
- package/dist/store/postgres/record-writer.d.ts +4 -0
- package/dist/store/postgres/record-writer.js +34 -0
- package/dist/store/postgres/record.d.ts +5 -0
- package/dist/store/postgres/record.js +60 -0
- package/dist/store/postgres/schema.d.ts +3096 -0
- package/dist/store/postgres/schema.js +363 -0
- package/dist/store/postgres/store.d.ts +2 -4
- package/dist/store/postgres/store.js +590 -434
- package/dist/store/postgres/tenant.d.ts +56 -0
- package/dist/store/postgres/tenant.js +154 -0
- package/dist/store/types.d.ts +183 -132
- package/dist/store/types.js +0 -1
- 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 +33 -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/types.d.ts +78 -0
- package/dist/streams/relay/types.js +8 -0
- package/dist/streams/types.d.ts +71 -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.d.ts +7 -2
- package/dist/tenant/advance.js +125 -14
- 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/cause.d.ts +25 -0
- package/dist/tenant/cause.js +45 -0
- package/dist/tenant/commands.d.ts +18 -2
- package/dist/tenant/commands.js +111 -115
- package/dist/tenant/context.d.ts +101 -21
- package/dist/tenant/context.js +14 -10
- package/dist/tenant/delivery-token.d.ts +41 -0
- package/dist/tenant/delivery-token.js +104 -0
- package/dist/tenant/delivery.d.ts +62 -0
- package/dist/tenant/delivery.js +481 -0
- package/dist/tenant/effects.d.ts +20 -1
- package/dist/tenant/effects.js +159 -42
- package/dist/tenant/endpoints.d.ts +67 -0
- package/dist/tenant/endpoints.js +90 -0
- package/dist/tenant/ephemeral.d.ts +22 -7
- package/dist/tenant/ephemeral.js +83 -125
- package/dist/tenant/history.d.ts +64 -0
- package/dist/tenant/history.js +120 -0
- 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/model-setting.d.ts +2 -2
- package/dist/tenant/module.d.ts +17 -28
- package/dist/tenant/module.js +133 -279
- package/dist/tenant/outbound.d.ts +44 -0
- package/dist/tenant/outbound.js +127 -0
- package/dist/tenant/paths.d.ts +11 -16
- package/dist/tenant/paths.js +24 -68
- package/dist/tenant/pool.d.ts +1 -3
- package/dist/tenant/pool.js +1 -19
- package/dist/tenant/principals.d.ts +23 -11
- package/dist/tenant/principals.js +61 -49
- package/dist/tenant/reset.d.ts +0 -4
- package/dist/tenant/reset.js +0 -5
- package/dist/tenant/runtime.d.ts +28 -20
- package/dist/tenant/runtime.js +95 -64
- package/dist/tenant/scheduler.d.ts +10 -3
- package/dist/tenant/scheduler.js +9 -5
- package/dist/tenant/session-streams.d.ts +127 -0
- package/dist/tenant/session-streams.js +404 -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 +3 -3
- package/dist/tenant/status.js +20 -13
- package/dist/tenant/store-pg.d.ts +9 -6
- package/dist/tenant/store-pg.js +60 -125
- package/dist/tenant/streams.d.ts +62 -85
- package/dist/tenant/streams.js +143 -226
- 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 +180 -0
- package/dist/tenant/transcript.d.ts +48 -5
- package/dist/tenant/transcript.js +58 -1
- package/dist/tenant/types.d.ts +69 -98
- package/dist/tenant/types.js +4 -15
- package/dist/tenant/worker.d.ts +3 -1
- package/dist/tenant/worker.js +13 -7
- package/dist/vault/host-model.d.ts +31 -0
- package/dist/vault/host-model.js +57 -0
- package/dist/vault/service.d.ts +44 -17
- package/dist/vault/service.js +126 -121
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +25 -9
- package/dist/core/executors.d.ts +0 -44
- package/dist/core/executors.js +0 -95
- package/dist/store/memory.d.ts +0 -57
- package/dist/store/memory.js +0 -645
- package/dist/store/postgres/migrations/001_initial.d.ts +0 -27
- package/dist/store/postgres/migrations/001_initial.js +0 -196
- package/dist/store/postgres/migrations/002_session_owner.d.ts +0 -6
- package/dist/store/postgres/migrations/002_session_owner.js +0 -13
- package/dist/store/postgres/migrations/index.d.ts +0 -49
- package/dist/store/postgres/migrations/index.js +0 -76
- package/dist/store/postgres/names.d.ts +0 -11
- package/dist/store/postgres/names.js +0 -42
- package/dist/store/postgres/tenants.d.ts +0 -90
- package/dist/store/postgres/tenants.js +0 -214
- package/dist/streams/relay.d.ts +0 -37
- package/dist/streams/relay.js +0 -254
- package/dist/tenant/envelope.d.ts +0 -7
- package/dist/tenant/envelope.js +0 -22
- package/dist/tenant/live.d.ts +0 -92
- package/dist/tenant/live.js +0 -290
- package/dist/tenant/quarantine-error.d.ts +0 -6
- package/dist/tenant/quarantine-error.js +0 -9
- package/dist/tenant/quarantine.d.ts +0 -27
- package/dist/tenant/quarantine.js +0 -72
- 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/dist/tenant/store-memory.d.ts +0 -16
- package/dist/tenant/store-memory.js +0 -111
- /package/dist/{store → record}/cursor.d.ts +0 -0
- /package/dist/{store → record}/cursor.js +0 -0
package/dist/streams/types.js
CHANGED
|
@@ -1,24 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The Durable Streams seam (
|
|
2
|
+
* The Durable Streams seam (Durable Streams §8).
|
|
3
3
|
*
|
|
4
|
-
* Durable Streams
|
|
5
|
-
*
|
|
4
|
+
* Durable Streams deliver what the record holds. Each Tenant has one S2 basin per basin
|
|
5
|
+
* generation (`streams/basin.ts`); inside it:
|
|
6
6
|
*
|
|
7
7
|
* | Stream | Contents | Written by | Read by |
|
|
8
8
|
* | --- | --- | --- | --- |
|
|
9
|
-
* | `sessions/<sessionId
|
|
10
|
-
* | `tenant/
|
|
11
|
-
* | `tenant/control` | `session.cancel` and `sessions.reset` signals | API nodes | every process with the Tenant open |
|
|
9
|
+
* | `sessions/<sessionId>` | every event of the session, in sequence | the stream relay, from the record | history and session SSE |
|
|
10
|
+
* | `tenant/control` | `session.cancel`, `sessions.reset` and `subject.revoked` signals | API nodes | every process with the Tenant open |
|
|
12
11
|
*
|
|
13
|
-
* **
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* starting at sequence 0: nothing ever deletes and re-creates the same stream.
|
|
18
|
-
* Abandoned streams are deleted best effort afterwards
|
|
19
|
-
* (`collectSessionStreams` in `tenant/streams.ts`). The cursor stays
|
|
20
|
-
* `base64url("<sessionId>:<seq>")`; readers resolve the incarnation from the
|
|
21
|
-
* session.
|
|
12
|
+
* **Basin generations.** A session id is unique within its Tenant's basin generation. A
|
|
13
|
+
* Tenant reset, the only path that frees ids, moves the Tenant to the next generation, so
|
|
14
|
+
* a session created again with the same id starts in an empty basin at sequence 0; the old
|
|
15
|
+
* basin is deleted afterwards. The cursor is `base64url("<sessionId>:<seq>")`.
|
|
22
16
|
*
|
|
23
17
|
* S2 is the supported implementation (`adapters/streams/s2.ts`, the only file
|
|
24
18
|
* importing the S2 SDK); `streams/memory.ts` is the in-memory fake.
|
|
@@ -31,56 +25,27 @@
|
|
|
31
25
|
* - **Conditional appends.** With `matchSeq`, a batch is appended only when the
|
|
32
26
|
* tail equals `matchSeq`; otherwise nothing is written and the result is a
|
|
33
27
|
* `SeqMismatch` carrying the current tail. The relay appends a session
|
|
34
|
-
* stream with `matchSeq` set to the
|
|
28
|
+
* stream with `matchSeq` set to the record row's sequence, so a retried
|
|
35
29
|
* append after an unacknowledged success is detected and never duplicated.
|
|
36
30
|
* - **Batches are atomic.** A batch is appended entirely or not at all.
|
|
37
31
|
* - **Reads resume.** `read` from `fromSeq` yields every record with
|
|
38
32
|
* `seq >= fromSeq` in order, with no gap between history and the live tail.
|
|
39
|
-
* - **Tenant scope.**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
33
|
+
* - **Tenant scope.** Methods take a Tenant id, or a basin key from `basinOf`
|
|
34
|
+
* for a later generation. `ensureTenant` creates the basin (idempotent) and
|
|
35
|
+
* must run before appends; streams are created on first append or read.
|
|
36
|
+
* `deleteTenant` removes the basin and every stream in it (with
|
|
37
|
+
* `allGenerations`, every generation's basin of the Tenant).
|
|
42
38
|
* - **Records are JSON.** Bodies are JSON-serializable values; implementations
|
|
43
39
|
* encode them as they need.
|
|
44
40
|
*/
|
|
45
|
-
import { randomBytes } from "node:crypto";
|
|
46
41
|
// ---------------------------------------------------------------------------
|
|
47
42
|
// Stream names and signal records
|
|
48
43
|
export const SESSION_STREAM_PREFIX = "sessions/";
|
|
49
|
-
/** `work_available` signals for executor connections. */
|
|
50
|
-
export const WORK_STREAM = "tenant/work";
|
|
51
44
|
/** `session.cancel` and `sessions.reset` signals for every process with the Tenant open. */
|
|
52
45
|
export const CONTROL_STREAM = "tenant/control";
|
|
53
|
-
/**
|
|
54
|
-
|
|
55
|
-
* Random incarnations are 12 characters, so never this.
|
|
56
|
-
*/
|
|
57
|
-
export const LEGACY_INCARNATION = "0";
|
|
58
|
-
/** A new session incarnation: 12 random base64url characters. */
|
|
59
|
-
export function newStreamIncarnation() {
|
|
60
|
-
return randomBytes(9).toString("base64url");
|
|
61
|
-
}
|
|
62
|
-
/** The stream of one incarnation of a session: `sessions/<sessionId>/<incarnation>`. */
|
|
63
|
-
export function sessionStream(sessionId, incarnation) {
|
|
46
|
+
/** The stream of a session: `sessions/<sessionId>`. */
|
|
47
|
+
export function sessionStream(sessionId) {
|
|
64
48
|
if (!sessionId)
|
|
65
49
|
throw new Error("sessionId is required");
|
|
66
|
-
|
|
67
|
-
throw new Error("incarnation must be non-empty and contain no '/'");
|
|
68
|
-
return `${SESSION_STREAM_PREFIX}${sessionId}/${incarnation}`;
|
|
69
|
-
}
|
|
70
|
-
/** The stream of a session as stored now. */
|
|
71
|
-
export function streamOfSession(session) {
|
|
72
|
-
return sessionStream(session.id, session.streamIncarnation ?? LEGACY_INCARNATION);
|
|
73
|
-
}
|
|
74
|
-
/** The session id and incarnation of a session stream, or undefined for other streams. */
|
|
75
|
-
export function parseSessionStream(stream) {
|
|
76
|
-
if (!stream.startsWith(SESSION_STREAM_PREFIX))
|
|
77
|
-
return undefined;
|
|
78
|
-
const rest = stream.slice(SESSION_STREAM_PREFIX.length);
|
|
79
|
-
const slash = rest.lastIndexOf("/");
|
|
80
|
-
if (slash <= 0 || slash === rest.length - 1)
|
|
81
|
-
return undefined;
|
|
82
|
-
return { sessionId: rest.slice(0, slash), incarnation: rest.slice(slash + 1) };
|
|
50
|
+
return `${SESSION_STREAM_PREFIX}${sessionId}`;
|
|
83
51
|
}
|
|
84
|
-
export const WORK_AVAILABLE = Object.freeze({
|
|
85
|
-
type: "work_available",
|
|
86
|
-
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Tenant's access policy (Host feature `subject-tokens`): the roles subject tokens are
|
|
3
|
+
* minted for, what a publishable key grants alone (`anon`), and how long tokens live. One
|
|
4
|
+
* validated JSON document in the Tenant settings; a Tenant that never set one has no roles,
|
|
5
|
+
* so nothing can be minted.
|
|
6
|
+
*
|
|
7
|
+
* A token's permissions are resolved from the policy on every request, so editing a role
|
|
8
|
+
* changes outstanding tokens at their next request and removing one ends them.
|
|
9
|
+
*/
|
|
10
|
+
import { type AccessPolicy, type RoleLimits, type TokenScope } from "@nylorun/core/contracts";
|
|
11
|
+
import type { Tx } from "../store/types.js";
|
|
12
|
+
export declare const ACCESS_POLICY_SETTING = "access.policy";
|
|
13
|
+
export declare function readPolicy(t: Tx): Promise<AccessPolicy>;
|
|
14
|
+
export declare function writePolicy(t: Tx, policy: AccessPolicy): Promise<void>;
|
|
15
|
+
/** What a token may do right now: its role narrowed by what the mint asked for. */
|
|
16
|
+
export interface EffectiveAccess {
|
|
17
|
+
readonly role: string;
|
|
18
|
+
readonly scopes: ReadonlySet<TokenScope>;
|
|
19
|
+
readonly agents: ReadonlySet<string> | "*";
|
|
20
|
+
readonly limits?: RoleLimits;
|
|
21
|
+
}
|
|
22
|
+
/** Agents both lists allow; `"*"` allows every agent. */
|
|
23
|
+
export declare function intersectAgents(a: readonly string[] | "*", b: readonly string[] | "*" | undefined): ReadonlySet<string> | "*";
|
|
24
|
+
/**
|
|
25
|
+
* The role's permissions narrowed to `scopes` and `agents`, or undefined when the role no
|
|
26
|
+
* longer exists.
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveRole(policy: AccessPolicy, role: string, scopes: readonly TokenScope[], agents?: readonly string[]): EffectiveAccess | undefined;
|
|
29
|
+
/** True when `agentId` is allowed by `agents`. */
|
|
30
|
+
export declare function agentAllowed(agents: ReadonlySet<string> | "*", agentId: string): boolean;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Tenant's access policy (Host feature `subject-tokens`): the roles subject tokens are
|
|
3
|
+
* minted for, what a publishable key grants alone (`anon`), and how long tokens live. One
|
|
4
|
+
* validated JSON document in the Tenant settings; a Tenant that never set one has no roles,
|
|
5
|
+
* so nothing can be minted.
|
|
6
|
+
*
|
|
7
|
+
* A token's permissions are resolved from the policy on every request, so editing a role
|
|
8
|
+
* changes outstanding tokens at their next request and removing one ends them.
|
|
9
|
+
*/
|
|
10
|
+
import { AccessPolicySchema, DEFAULT_ACCESS_POLICY, } from "@nylorun/core/contracts";
|
|
11
|
+
export const ACCESS_POLICY_SETTING = "access.policy";
|
|
12
|
+
export async function readPolicy(t) {
|
|
13
|
+
const stored = await t.getSetting(ACCESS_POLICY_SETTING);
|
|
14
|
+
if (stored === undefined)
|
|
15
|
+
return DEFAULT_ACCESS_POLICY;
|
|
16
|
+
// Only `writePolicy` stores it, after validation.
|
|
17
|
+
return AccessPolicySchema.parse(JSON.parse(stored));
|
|
18
|
+
}
|
|
19
|
+
export async function writePolicy(t, policy) {
|
|
20
|
+
await t.putSetting(ACCESS_POLICY_SETTING, JSON.stringify(AccessPolicySchema.parse(policy)));
|
|
21
|
+
}
|
|
22
|
+
/** Agents both lists allow; `"*"` allows every agent. */
|
|
23
|
+
export function intersectAgents(a, b) {
|
|
24
|
+
if (b === undefined || b === "*")
|
|
25
|
+
return a === "*" ? "*" : new Set(a);
|
|
26
|
+
if (a === "*")
|
|
27
|
+
return new Set(b);
|
|
28
|
+
const allowed = new Set(a);
|
|
29
|
+
return new Set(b.filter((agent) => allowed.has(agent)));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The role's permissions narrowed to `scopes` and `agents`, or undefined when the role no
|
|
33
|
+
* longer exists.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveRole(policy, role, scopes, agents) {
|
|
36
|
+
const entry = Object.hasOwn(policy.roles, role)
|
|
37
|
+
? policy.roles[role]
|
|
38
|
+
: undefined;
|
|
39
|
+
if (!entry)
|
|
40
|
+
return undefined;
|
|
41
|
+
const allowed = new Set(entry.scopes);
|
|
42
|
+
return {
|
|
43
|
+
role,
|
|
44
|
+
scopes: new Set(scopes.filter((scope) => allowed.has(scope))),
|
|
45
|
+
agents: intersectAgents(entry.agents, agents),
|
|
46
|
+
...(entry.limits ? { limits: entry.limits } : {}),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** True when `agentId` is allowed by `agents`. */
|
|
50
|
+
export function agentAllowed(agents, agentId) {
|
|
51
|
+
return agents === "*" || agents.has(agentId);
|
|
52
|
+
}
|
package/dist/tenant/actions.d.ts
CHANGED
|
@@ -1,153 +1,14 @@
|
|
|
1
|
-
import type { IncomingMessage } from "node:http";
|
|
2
|
-
import { type RegisterExecutorsRequestSchema } from "@nylorun/core/contracts";
|
|
3
|
-
import { type ExecutorRecord } from "../core/executors.js";
|
|
4
1
|
import { type SandboxRouteDeps } from "../core/sandbox-routes.js";
|
|
5
|
-
import { type
|
|
6
|
-
type
|
|
2
|
+
import { type TenantContext } from "./context.js";
|
|
3
|
+
import type { DeliveryScope } from "./delivery-token.js";
|
|
7
4
|
/** Session and Action lookups for the sandbox route handlers. */
|
|
8
5
|
export declare function sandboxRouteDeps(ctx: TenantContext): SandboxRouteDeps;
|
|
9
|
-
/** `
|
|
10
|
-
export declare function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
implementationVersion: string;
|
|
18
|
-
input: unknown;
|
|
19
|
-
context: Record<string, unknown>;
|
|
20
|
-
status: "cancelled" | "claimed" | "completed" | "pending" | "uncertain";
|
|
21
|
-
generation: number;
|
|
22
|
-
claimId: string | null;
|
|
23
|
-
leaseExpiresAt: string | null;
|
|
24
|
-
agent?: {
|
|
25
|
-
id: string;
|
|
26
|
-
path: string;
|
|
27
|
-
delegationId?: string | undefined;
|
|
28
|
-
} | undefined;
|
|
29
|
-
kind: "tool";
|
|
30
|
-
capabilityId: string;
|
|
31
|
-
toolName: string;
|
|
32
|
-
inputSchema?: Record<string, unknown> | undefined;
|
|
33
|
-
outputSchema?: Record<string, unknown> | undefined;
|
|
34
|
-
} | {
|
|
35
|
-
actionId: string;
|
|
36
|
-
sessionId: string;
|
|
37
|
-
turnId: string;
|
|
38
|
-
agentId: string;
|
|
39
|
-
manifestHash: string;
|
|
40
|
-
implementationVersion: string;
|
|
41
|
-
input: unknown;
|
|
42
|
-
context: Record<string, unknown>;
|
|
43
|
-
status: "cancelled" | "claimed" | "completed" | "pending" | "uncertain";
|
|
44
|
-
generation: number;
|
|
45
|
-
claimId: string | null;
|
|
46
|
-
leaseExpiresAt: string | null;
|
|
47
|
-
agent?: {
|
|
48
|
-
id: string;
|
|
49
|
-
path: string;
|
|
50
|
-
delegationId?: string | undefined;
|
|
51
|
-
} | undefined;
|
|
52
|
-
kind: "tool";
|
|
53
|
-
path: string;
|
|
54
|
-
key: string;
|
|
55
|
-
inputSchema?: Record<string, unknown> | undefined;
|
|
56
|
-
outputSchema?: Record<string, unknown> | undefined;
|
|
57
|
-
} | {
|
|
58
|
-
actionId: string;
|
|
59
|
-
sessionId: string;
|
|
60
|
-
turnId: string;
|
|
61
|
-
agentId: string;
|
|
62
|
-
manifestHash: string;
|
|
63
|
-
implementationVersion: string;
|
|
64
|
-
input: unknown;
|
|
65
|
-
context: Record<string, unknown>;
|
|
66
|
-
status: "cancelled" | "claimed" | "completed" | "pending" | "uncertain";
|
|
67
|
-
generation: number;
|
|
68
|
-
claimId: string | null;
|
|
69
|
-
leaseExpiresAt: string | null;
|
|
70
|
-
agent?: {
|
|
71
|
-
id: string;
|
|
72
|
-
path: string;
|
|
73
|
-
delegationId?: string | undefined;
|
|
74
|
-
} | undefined;
|
|
75
|
-
kind: "hook";
|
|
76
|
-
hook: {
|
|
77
|
-
at: "after" | "before";
|
|
78
|
-
scope: "step" | "turn";
|
|
79
|
-
capabilityIds: string[];
|
|
80
|
-
};
|
|
81
|
-
} | {
|
|
82
|
-
actionId: string;
|
|
83
|
-
sessionId: string;
|
|
84
|
-
turnId: string;
|
|
85
|
-
agentId: string;
|
|
86
|
-
manifestHash: string;
|
|
87
|
-
implementationVersion: string;
|
|
88
|
-
input: unknown;
|
|
89
|
-
context: Record<string, unknown>;
|
|
90
|
-
status: "cancelled" | "claimed" | "completed" | "pending" | "uncertain";
|
|
91
|
-
generation: number;
|
|
92
|
-
claimId: string | null;
|
|
93
|
-
leaseExpiresAt: string | null;
|
|
94
|
-
agent?: {
|
|
95
|
-
id: string;
|
|
96
|
-
path: string;
|
|
97
|
-
delegationId?: string | undefined;
|
|
98
|
-
} | undefined;
|
|
99
|
-
kind: "fn";
|
|
100
|
-
path: string;
|
|
101
|
-
key: string;
|
|
102
|
-
} | {
|
|
103
|
-
actionId: string;
|
|
104
|
-
sessionId: string;
|
|
105
|
-
turnId: string;
|
|
106
|
-
agentId: string;
|
|
107
|
-
manifestHash: string;
|
|
108
|
-
implementationVersion: string;
|
|
109
|
-
input: unknown;
|
|
110
|
-
context: Record<string, unknown>;
|
|
111
|
-
status: "cancelled" | "claimed" | "completed" | "pending" | "uncertain";
|
|
112
|
-
generation: number;
|
|
113
|
-
claimId: string | null;
|
|
114
|
-
leaseExpiresAt: string | null;
|
|
115
|
-
agent?: {
|
|
116
|
-
id: string;
|
|
117
|
-
path: string;
|
|
118
|
-
delegationId?: string | undefined;
|
|
119
|
-
} | undefined;
|
|
120
|
-
kind: "verify";
|
|
121
|
-
path: string;
|
|
122
|
-
key: string;
|
|
123
|
-
})[];
|
|
6
|
+
/** `POST /v1/actions/:id/sandbox/:tool`: a sandbox tool call for the Action being delivered. */
|
|
7
|
+
export declare function actionSandboxTool(ctx: TenantContext, scope: DeliveryScope, actionId: string, toolName: string, body: () => Promise<unknown>, signal: AbortSignal): Promise<{
|
|
8
|
+
kind: "completed";
|
|
9
|
+
output: unknown;
|
|
10
|
+
} | {
|
|
11
|
+
kind: "failed";
|
|
12
|
+
code: string;
|
|
13
|
+
message: string;
|
|
124
14
|
}>;
|
|
125
|
-
/** `POST /v1/actions/:id/sandbox/:tool`: a claim-scoped sandbox tool call. */
|
|
126
|
-
export declare function actionSandboxTool(ctx: TenantContext, scope: AuthScope, actionId: string, toolName: string, request: IncomingMessage): Promise<import("../sandbox/tools.js").SandboxToolOutcome>;
|
|
127
|
-
/** `POST /v1/actions/:id/claim` and `/heartbeat`; anything else under the Action is a 404. */
|
|
128
|
-
export declare function updateAction(ctx: TenantContext, scope: AuthScope, actionId: string, method: string | undefined, operation: string | undefined, body: unknown): Promise<unknown>;
|
|
129
|
-
/** `GET /v1/executors`. */
|
|
130
|
-
export declare function listExecutors(ctx: TenantContext): {
|
|
131
|
-
executors: {
|
|
132
|
-
agentId: string;
|
|
133
|
-
implementationVersion: string;
|
|
134
|
-
manifestHash?: string | undefined;
|
|
135
|
-
connected: boolean;
|
|
136
|
-
updatedAt: string;
|
|
137
|
-
}[];
|
|
138
|
-
};
|
|
139
|
-
/** `PUT /v1/executors`: persist the batch, then update the registry and end rotated streams. */
|
|
140
|
-
export declare function registerExecutors(ctx: TenantContext, principalId: string, body: RegisterExecutorsRequest): Promise<{
|
|
141
|
-
executors: {
|
|
142
|
-
agentId: string;
|
|
143
|
-
implementationVersion: string;
|
|
144
|
-
rotated: boolean;
|
|
145
|
-
replacedBy?: "different-credential" | undefined;
|
|
146
|
-
}[];
|
|
147
|
-
}>;
|
|
148
|
-
/** `DELETE /v1/executors/:agentId`: forget the executor and end its streams. */
|
|
149
|
-
export declare function deleteExecutor(ctx: TenantContext, agentId: string): Promise<{
|
|
150
|
-
agentId: string;
|
|
151
|
-
deleted: boolean;
|
|
152
|
-
}>;
|
|
153
|
-
export {};
|
package/dist/tenant/actions.js
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Action service and the executor registry: discover pending Actions, claim, heartbeat,
|
|
3
|
-
* claim-scoped sandbox tool calls, and executor registration, listing and removal.
|
|
4
|
-
*
|
|
5
|
-
* A claim or heartbeat locks the Action's session and commits in one transaction; the
|
|
6
|
-
* registry is updated only after the executors table commits.
|
|
7
|
-
*
|
|
8
|
-
* Later waves: Wave 2 / Y reads the executor `connected` flag from the work stream instead
|
|
9
|
-
* of `executorStreams`.
|
|
10
|
-
*/
|
|
11
|
-
import { randomUUID } from "node:crypto";
|
|
12
|
-
import { ActionClaimRequestSchema, ActionHeartbeatRequestSchema, } from "@nylorun/core/contracts";
|
|
13
|
-
import { assertExecutorCredential, hashToken, } from "../core/executors.js";
|
|
14
1
|
import { SandboxRouteError, handleActionSandboxTool, } from "../core/sandbox-routes.js";
|
|
15
|
-
import { lockedSession, sandboxLookup, sessionOf, } from "./context.js";
|
|
16
|
-
import { fail, readBody, requestAborted } from "./http.js";
|
|
17
2
|
import { scoped } from "./auth.js";
|
|
18
|
-
import {
|
|
3
|
+
import { sandboxLookup, sessionOf } from "./context.js";
|
|
4
|
+
import { fail } from "./http.js";
|
|
19
5
|
/** Session and Action lookups for the sandbox route handlers. */
|
|
20
6
|
export function sandboxRouteDeps(ctx) {
|
|
21
7
|
return {
|
|
@@ -27,19 +13,13 @@ export function sandboxRouteDeps(ctx) {
|
|
|
27
13
|
getAction: (id) => ctx.store.tx((t) => t.get("actions", id)),
|
|
28
14
|
};
|
|
29
15
|
}
|
|
30
|
-
/** `
|
|
31
|
-
export async function
|
|
32
|
-
return {
|
|
33
|
-
actions: await ctx.store.tx((t) => t.pendingActions(executor.agentId)),
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
/** `POST /v1/actions/:id/sandbox/:tool`: a claim-scoped sandbox tool call. */
|
|
37
|
-
export async function actionSandboxTool(ctx, scope, actionId, toolName, request) {
|
|
16
|
+
/** `POST /v1/actions/:id/sandbox/:tool`: a sandbox tool call for the Action being delivered. */
|
|
17
|
+
export async function actionSandboxTool(ctx, scope, actionId, toolName, body, signal) {
|
|
38
18
|
const action = (await ctx.store.tx((t) => t.get("actions", actionId))) ??
|
|
39
19
|
fail(404, "Action not found");
|
|
40
20
|
scoped(scope, action);
|
|
41
21
|
try {
|
|
42
|
-
return await handleActionSandboxTool(sandboxRouteDeps(ctx), actionId, toolName, await
|
|
22
|
+
return await handleActionSandboxTool(sandboxRouteDeps(ctx), actionId, toolName, await body(), signal, { generation: scope.generation });
|
|
43
23
|
}
|
|
44
24
|
catch (error) {
|
|
45
25
|
if (error instanceof SandboxRouteError)
|
|
@@ -47,145 +27,3 @@ export async function actionSandboxTool(ctx, scope, actionId, toolName, request)
|
|
|
47
27
|
throw error;
|
|
48
28
|
}
|
|
49
29
|
}
|
|
50
|
-
/** `POST /v1/actions/:id/claim` and `/heartbeat`; anything else under the Action is a 404. */
|
|
51
|
-
export function updateAction(ctx, scope, actionId, method, operation, body) {
|
|
52
|
-
return ctx.store.tx(async (t) => {
|
|
53
|
-
const found = (await t.get("actions", actionId)) ??
|
|
54
|
-
fail(404, "Action not found");
|
|
55
|
-
scoped(scope, found);
|
|
56
|
-
const s = await lockedSession(t, found.sessionId);
|
|
57
|
-
// Read again under the session lock.
|
|
58
|
-
const action = (await t.get("actions", actionId)) ??
|
|
59
|
-
fail(404, "Action not found");
|
|
60
|
-
if (method === "POST" && operation === "claim") {
|
|
61
|
-
ActionClaimRequestSchema.parse(body);
|
|
62
|
-
if (action.status !== "pending" ||
|
|
63
|
-
s.status === "cancelled" ||
|
|
64
|
-
s.activeTurnId !== action.turnId)
|
|
65
|
-
fail(409, "Action unavailable");
|
|
66
|
-
action.status = "claimed";
|
|
67
|
-
action.generation++;
|
|
68
|
-
action.claimId = randomUUID();
|
|
69
|
-
action.leaseExpiresAt = new Date(Date.now() + (ctx.config.leaseMs ?? 30000)).toISOString();
|
|
70
|
-
await t.put("actions", actionId, action);
|
|
71
|
-
await t.event(action.sessionId, action.turnId, "action.claimed", {
|
|
72
|
-
actionId,
|
|
73
|
-
generation: action.generation,
|
|
74
|
-
...(action.agent ? { agent: action.agent } : {}),
|
|
75
|
-
});
|
|
76
|
-
return {
|
|
77
|
-
action,
|
|
78
|
-
claimId: action.claimId,
|
|
79
|
-
generation: action.generation,
|
|
80
|
-
leaseExpiresAt: action.leaseExpiresAt,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
if (method === "POST" && operation === "heartbeat") {
|
|
84
|
-
const beat = ActionHeartbeatRequestSchema.parse(body);
|
|
85
|
-
if (s.activeTurnId !== action.turnId ||
|
|
86
|
-
action.status !== "claimed" ||
|
|
87
|
-
action.claimId !== beat.claimId ||
|
|
88
|
-
action.generation !== beat.generation ||
|
|
89
|
-
Date.parse(action.leaseExpiresAt) <= Date.now())
|
|
90
|
-
fail(409, "Stale or expired claim");
|
|
91
|
-
action.leaseExpiresAt = new Date(Date.now() + (ctx.config.leaseMs ?? 30000)).toISOString();
|
|
92
|
-
await t.put("actions", actionId, action);
|
|
93
|
-
return { leaseExpiresAt: action.leaseExpiresAt };
|
|
94
|
-
}
|
|
95
|
-
return fail(404, "Route not found");
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
/** `GET /v1/executors`. */
|
|
99
|
-
export function listExecutors(ctx) {
|
|
100
|
-
return {
|
|
101
|
-
executors: ctx.registry.list().map((e) => ({
|
|
102
|
-
agentId: e.agentId,
|
|
103
|
-
implementationVersion: e.implementationVersion,
|
|
104
|
-
...(e.manifestHash === undefined ? {} : { manifestHash: e.manifestHash }),
|
|
105
|
-
connected: executorConnected(ctx.live, e.tokenHash),
|
|
106
|
-
updatedAt: e.updatedAt,
|
|
107
|
-
})),
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
/** `PUT /v1/executors`: persist the batch, then update the registry and end rotated streams. */
|
|
111
|
-
export async function registerExecutors(ctx, principalId, body) {
|
|
112
|
-
const { store, registry } = ctx;
|
|
113
|
-
// Credential rules are shared with startup validation, which throws plainly; on the
|
|
114
|
-
// wire a rejected registration is a bad request, not a server fault.
|
|
115
|
-
const applicationHashes = await store.tx((t) => t.applicationTokenHashes());
|
|
116
|
-
try {
|
|
117
|
-
for (const executor of body.executors)
|
|
118
|
-
assertExecutorCredential(executor, applicationHashes);
|
|
119
|
-
}
|
|
120
|
-
catch (error) {
|
|
121
|
-
fail(400, error instanceof Error ? error.message : String(error));
|
|
122
|
-
}
|
|
123
|
-
if (new Set(body.executors.map((e) => e.agentId)).size !==
|
|
124
|
-
body.executors.length ||
|
|
125
|
-
new Set(body.executors.map((e) => e.token)).size !== body.executors.length)
|
|
126
|
-
fail(400, "Executor registrations must be unique per agent and token");
|
|
127
|
-
const updatedAt = new Date().toISOString();
|
|
128
|
-
const records = body.executors.map((executor) => ({
|
|
129
|
-
agentId: executor.agentId,
|
|
130
|
-
implementationVersion: executor.implementationVersion,
|
|
131
|
-
...(executor.manifestHash === undefined
|
|
132
|
-
? {}
|
|
133
|
-
: { manifestHash: executor.manifestHash }),
|
|
134
|
-
tokenHash: hashToken(executor.token),
|
|
135
|
-
persisted: true,
|
|
136
|
-
updatedAt,
|
|
137
|
-
principalId,
|
|
138
|
-
}));
|
|
139
|
-
for (const record of records) {
|
|
140
|
-
const collision = registry.find(record.tokenHash);
|
|
141
|
-
if (collision && collision.agentId !== record.agentId)
|
|
142
|
-
fail(409, "Executor tokens must be unique");
|
|
143
|
-
// A token hash may not appear in both principals and executors (D3).
|
|
144
|
-
if (applicationHashes.includes(record.tokenHash))
|
|
145
|
-
fail(400, "Executor tokens require independent credentials and an agent id");
|
|
146
|
-
}
|
|
147
|
-
// Persist the whole batch first; the in-memory registry must never run ahead of the store.
|
|
148
|
-
await store.tx(async (t) => {
|
|
149
|
-
for (const record of records)
|
|
150
|
-
await t.putExecutor({
|
|
151
|
-
agentId: record.agentId,
|
|
152
|
-
tokenHash: record.tokenHash,
|
|
153
|
-
implementationVersion: record.implementationVersion,
|
|
154
|
-
...(record.manifestHash === undefined
|
|
155
|
-
? {}
|
|
156
|
-
: { manifestHash: record.manifestHash }),
|
|
157
|
-
principalId: record.principalId,
|
|
158
|
-
updatedAt,
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
const results = records.map((record) => {
|
|
162
|
-
const previous = registry.get(record.agentId);
|
|
163
|
-
const { rotated, previousHash } = registry.upsert(record);
|
|
164
|
-
if (rotated && previousHash)
|
|
165
|
-
endExecutorStreams(ctx.live, previousHash);
|
|
166
|
-
const replacedByDifferent = previous?.principalId !== undefined &&
|
|
167
|
-
previous.principalId !== principalId;
|
|
168
|
-
if (replacedByDifferent)
|
|
169
|
-
ctx.config.logger.warn("executor registration replaced by different application credential", {
|
|
170
|
-
agentId: record.agentId,
|
|
171
|
-
previousPrincipalId: previous.principalId,
|
|
172
|
-
});
|
|
173
|
-
return {
|
|
174
|
-
agentId: record.agentId,
|
|
175
|
-
implementationVersion: record.implementationVersion,
|
|
176
|
-
rotated,
|
|
177
|
-
...(replacedByDifferent
|
|
178
|
-
? { replacedBy: "different-credential" }
|
|
179
|
-
: {}),
|
|
180
|
-
};
|
|
181
|
-
});
|
|
182
|
-
return { executors: results };
|
|
183
|
-
}
|
|
184
|
-
/** `DELETE /v1/executors/:agentId`: forget the executor and end its streams. */
|
|
185
|
-
export async function deleteExecutor(ctx, agentId) {
|
|
186
|
-
const existing = ctx.registry.get(agentId) ?? fail(404, "Executor not found");
|
|
187
|
-
await ctx.store.tx((t) => t.deleteExecutor(agentId));
|
|
188
|
-
ctx.registry.remove(agentId);
|
|
189
|
-
endExecutorStreams(ctx.live, existing.tokenHash);
|
|
190
|
-
return { agentId, deleted: true };
|
|
191
|
-
}
|
package/dist/tenant/advance.d.ts
CHANGED
|
@@ -8,8 +8,13 @@ import type { Session, TenantContext } from "./context.js";
|
|
|
8
8
|
export declare function advance(ctx: TenantContext, id: string, signal: AbortSignal): Promise<AdvanceResult>;
|
|
9
9
|
/**
|
|
10
10
|
* Takeover (§10.5 step 2, §11.4), inside the transaction that took ownership: the dead
|
|
11
|
-
* owner's `invoking` effects become `uncertain` and are never invoked again
|
|
11
|
+
* owner's `invoking` effects become `uncertain` and are never invoked again, except model
|
|
12
|
+
* calls when the gate recovers them (P1.2) and remote MCP calls when the Tool Gate does (F4.1
|
|
13
|
+
* G3): those stay `invoking`, and the replay re-sends them. When one belongs
|
|
12
14
|
* to the active turn, the session becomes `uncertain` too, with an `effect.uncertain` event.
|
|
13
15
|
* Mutates and writes `s`. Returns the effect ids it marked.
|
|
14
16
|
*/
|
|
15
|
-
export declare function takeOver(t: Tx, s: Session
|
|
17
|
+
export declare function takeOver(t: Tx, s: Session, options?: {
|
|
18
|
+
recoversModelCalls?: boolean;
|
|
19
|
+
recoversMcpCalls?: boolean;
|
|
20
|
+
}): Promise<string[]>;
|