@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/tenant/types.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
-
import type {
|
|
2
|
+
import type { HostAggregate, HostTenant, TenantEnvelope } from "@nylorun/core/contracts";
|
|
3
3
|
import type { FlowLimits } from "../core/limits.js";
|
|
4
4
|
import type { SessionStore } from "../store/types.js";
|
|
5
5
|
import type { SandboxBackend } from "../sandbox/types.js";
|
|
6
|
+
import type { TenantCause } from "./cause.js";
|
|
7
|
+
import type { OutboundPolicy } from "./outbound.js";
|
|
6
8
|
import type { TenantWorker } from "./worker.js";
|
|
7
9
|
export type TenantMode = "shared" | "ephemeral" | "test";
|
|
8
10
|
/**
|
|
9
|
-
* The Tenant directory on the Host root. The Tenant's data lives in
|
|
10
|
-
*
|
|
11
|
+
* The Tenant directory on the Host root (`<Host root>/tenant/`). The Tenant's data lives in
|
|
12
|
+
* its database; this holds what stays on the Host: the vault key, plugin data, logs, and the
|
|
11
13
|
* private home, tmp and sandbox directories.
|
|
12
14
|
*/
|
|
13
15
|
export interface TenantPaths {
|
|
@@ -22,10 +24,6 @@ export interface TenantPaths {
|
|
|
22
24
|
}
|
|
23
25
|
export type TenantModelConfig = {
|
|
24
26
|
kind: "vault";
|
|
25
|
-
} | {
|
|
26
|
-
kind: "gateway";
|
|
27
|
-
url: string;
|
|
28
|
-
model: string;
|
|
29
27
|
} | {
|
|
30
28
|
kind: "fixture";
|
|
31
29
|
} | {
|
|
@@ -41,8 +39,21 @@ export interface TenantConfig {
|
|
|
41
39
|
backends?: readonly SandboxBackend[];
|
|
42
40
|
};
|
|
43
41
|
model: TenantModelConfig;
|
|
42
|
+
/**
|
|
43
|
+
* Segment rollover (Model Calls §10): a turn ends its segment at a step boundary after this
|
|
44
|
+
* many steps or milliseconds and continues in a new one, so no advance reaches its
|
|
45
|
+
* deadline. Default 50 steps or 20 minutes.
|
|
46
|
+
*/
|
|
47
|
+
rollover?: {
|
|
48
|
+
steps?: number;
|
|
49
|
+
ms?: number;
|
|
50
|
+
};
|
|
51
|
+
/** Retries and timeouts for model calls (Model Calls §5, §6). Defaults in `piModel`. */
|
|
52
|
+
modelCall?: import("../gates/model-gate.js").ModelCallSettings;
|
|
44
53
|
childEnv: Readonly<Record<string, string>>;
|
|
45
54
|
/** Action claim lease. Default 30 s. */
|
|
55
|
+
/** How the Runtime may call Action endpoints (Host settings). Default: http and private addresses allowed. */
|
|
56
|
+
delivery?: OutboundPolicy;
|
|
46
57
|
leaseMs?: number;
|
|
47
58
|
/** Ownership lease of an advance (§10.6); renewed every third while it runs. Default 30 s. */
|
|
48
59
|
ownerLeaseMs?: number;
|
|
@@ -69,135 +80,95 @@ export interface Logger {
|
|
|
69
80
|
export interface TenantSummary {
|
|
70
81
|
ready: boolean;
|
|
71
82
|
runningSessions: number;
|
|
72
|
-
|
|
83
|
+
/** Deliveries to Action endpoints in flight on this process. */
|
|
84
|
+
inFlightDeliveries: number;
|
|
73
85
|
pendingActions: number;
|
|
74
86
|
uncertainEffects: number;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The Node request and response behind a `Request`, for what still writes to Node directly
|
|
90
|
+
* (event streams). The shape of `@hono/node-server`'s `HttpBindings`.
|
|
91
|
+
*/
|
|
92
|
+
export interface NodeBindings {
|
|
93
|
+
readonly incoming: IncomingMessage;
|
|
94
|
+
readonly outgoing: ServerResponse;
|
|
79
95
|
}
|
|
80
96
|
/** An open Tenant Runtime. Created only by the Tenant module. */
|
|
81
97
|
export interface TenantHandle {
|
|
82
98
|
readonly envelope: TenantEnvelope;
|
|
83
99
|
/** The handlers Durable Session Execution calls for this Tenant (`worker.ts`). */
|
|
84
100
|
readonly worker?: TenantWorker;
|
|
85
|
-
/**
|
|
86
|
-
|
|
101
|
+
/**
|
|
102
|
+
* A Tenant API request whose headers the Host has validated: authenticates, authorizes,
|
|
103
|
+
* dispatches. A response already written to `node.outgoing` is `RESPONSE_ALREADY_SENT`.
|
|
104
|
+
*/
|
|
105
|
+
fetch(request: Request, node: NodeBindings): Promise<Response>;
|
|
87
106
|
summary(): Promise<TenantSummary>;
|
|
88
107
|
/** Stop scheduling; wait for or cancel active turns. */
|
|
89
108
|
drain(activeWork: "drain" | "cancel", timeoutMs?: number): Promise<void>;
|
|
90
109
|
close(): Promise<void>;
|
|
91
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* The Host's Tenant for a request: open, or unavailable. `cause` says why when opening it
|
|
113
|
+
* failed; without one the Host is starting or closing. Either way the request gets the opaque
|
|
114
|
+
* 404.
|
|
115
|
+
*/
|
|
92
116
|
export type TenantResolution = {
|
|
93
117
|
kind: "open";
|
|
94
118
|
handle: TenantHandle;
|
|
95
119
|
} | {
|
|
96
|
-
kind: "
|
|
97
|
-
|
|
98
|
-
kind: "quarantined";
|
|
99
|
-
quarantine: Quarantine;
|
|
120
|
+
kind: "unavailable";
|
|
121
|
+
cause?: TenantCause;
|
|
100
122
|
};
|
|
101
|
-
export interface Quarantine {
|
|
102
|
-
code: "kek-missing" | "corrupt" | "schema-too-new" | "migration-failed" | "envelope-invalid" | "open-timeout" | "open-failed";
|
|
103
|
-
message: string;
|
|
104
|
-
repair: string;
|
|
105
|
-
}
|
|
106
|
-
export interface BootstrapPrincipal {
|
|
107
|
-
principalId: string;
|
|
108
|
-
credentialHash: string;
|
|
109
|
-
idempotencyKey: string;
|
|
110
|
-
/** When set, also registers application principal `studio` with this hash. */
|
|
111
|
-
studioCredentialHash?: string;
|
|
112
|
-
/** Application principals whose keys the admin key derives (feature `derived-principals`). */
|
|
113
|
-
derivedPrincipals?: readonly DerivedPrincipal[];
|
|
114
|
-
}
|
|
115
|
-
export interface DerivedPrincipal {
|
|
116
|
-
id: string;
|
|
117
|
-
credentialHash: string;
|
|
118
|
-
}
|
|
119
123
|
/**
|
|
120
|
-
* The deep module (§8)
|
|
124
|
+
* The deep module (§8): the one Tenant a Host serves (tenancy.md §5). HTTP, the Worker and
|
|
125
|
+
* tests use only this.
|
|
121
126
|
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
127
|
+
* `start` opens the Tenant; the Host has it open from readiness to shutdown. There is no
|
|
128
|
+
* Tenant list, no opening on demand of other Tenants and no quarantine cache: when opening
|
|
129
|
+
* fails for a reason in the Tenant (a `TenantCause`), the Host fails readiness and reports
|
|
130
|
+
* the cause until it is restarted. A failure outside the Tenant (`TenantUnavailableError`:
|
|
131
|
+
* Postgres unreachable) is retried in the background and by the next request.
|
|
126
132
|
*/
|
|
127
133
|
export interface TenantModule {
|
|
128
|
-
/**
|
|
134
|
+
/** Opens the Tenant. Never rejects: a failure is recorded and reported by `tenant()`. */
|
|
129
135
|
start(): Promise<void>;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
resolve(id: string): Promise<TenantResolution>;
|
|
136
|
+
/** The Tenant is open (`/ready`). */
|
|
137
|
+
readonly ready: boolean;
|
|
133
138
|
/**
|
|
134
|
-
* The Tenant
|
|
135
|
-
*
|
|
136
|
-
* module is closed.
|
|
139
|
+
* The open Tenant, waiting for an open in progress. Rejects with `TenantUnavailableError`
|
|
140
|
+
* when it cannot be reached for a reason outside it.
|
|
137
141
|
*/
|
|
138
|
-
|
|
139
|
-
create(input: {
|
|
140
|
-
tenantId: string;
|
|
141
|
-
name: string;
|
|
142
|
-
} & BootstrapPrincipal): Promise<{
|
|
143
|
-
envelope: TenantEnvelope;
|
|
144
|
-
created: boolean;
|
|
145
|
-
}>;
|
|
142
|
+
resolve(): Promise<TenantResolution>;
|
|
146
143
|
/**
|
|
147
|
-
*
|
|
148
|
-
*
|
|
144
|
+
* The Tenant's Worker handlers when `id` is the open Tenant's, for `TenantWorkers.resolve`.
|
|
145
|
+
* Undefined otherwise, or once the module is closed.
|
|
149
146
|
*/
|
|
150
|
-
|
|
151
|
-
status
|
|
152
|
-
|
|
147
|
+
worker(id: string): Promise<TenantWorker | undefined>;
|
|
148
|
+
/** The Tenant as `/v1/admin/status` reports it. */
|
|
149
|
+
tenant(): HostTenant;
|
|
153
150
|
summarize(): Promise<HostAggregate>;
|
|
154
151
|
close(): Promise<void>;
|
|
155
152
|
}
|
|
156
153
|
/**
|
|
157
|
-
*
|
|
158
|
-
*
|
|
154
|
+
* Opens the Host's Tenant (`store-pg.ts`): migrates its database, creates the Tenant when it
|
|
155
|
+
* has none, and opens the Tenant Runtime. Rejects with a `TenantOpenError` (`cause.ts`) when
|
|
156
|
+
* the Tenant itself cannot be opened, and with `TenantUnavailableError` when something
|
|
157
|
+
* outside it failed.
|
|
159
158
|
*/
|
|
160
|
-
export
|
|
161
|
-
/** Ids of every Tenant the store holds. */
|
|
162
|
-
enumerate(): Promise<readonly string[]>;
|
|
163
|
-
/** Throws a quarantine error when unreadable, `TenantNotFoundError` when gone. */
|
|
164
|
-
readEnvelope(id: string): Promise<TenantEnvelope>;
|
|
165
|
-
/**
|
|
166
|
-
* Creates the Tenant, or returns `exists` when it already exists (whatever its bootstrap
|
|
167
|
-
* material; the module compares it with `bootstrapMatches`). The stored envelope's
|
|
168
|
-
* `schemaVersion` is the store's own; read it back with `readEnvelope`.
|
|
169
|
-
*/
|
|
170
|
-
create(envelope: TenantEnvelope, bootstrap: BootstrapPrincipal): Promise<"created" | "exists">;
|
|
171
|
-
bootstrapMatches(id: string, bootstrap: BootstrapPrincipal): Promise<boolean>;
|
|
172
|
-
/**
|
|
173
|
-
* Opens the Tenant Runtime; runs migration. Throws `TenantNotFoundError` when the Tenant
|
|
174
|
-
* does not exist, `TenantUnavailableError` when something outside the Tenant failed, and
|
|
175
|
-
* any other error (a quarantine error, ideally) when the Tenant itself cannot be opened.
|
|
176
|
-
*/
|
|
177
|
-
open(id: string): Promise<TenantHandle>;
|
|
178
|
-
/** Removes the Tenant: its data and its Tenant directory. */
|
|
179
|
-
trash(id: string, now: Date): Promise<void>;
|
|
180
|
-
/** Removes what a failed `create` left, never an existing Tenant. */
|
|
181
|
-
removePartial(id: string): Promise<void>;
|
|
182
|
-
}
|
|
159
|
+
export type TenantOpener = () => Promise<TenantHandle>;
|
|
183
160
|
/**
|
|
184
|
-
* Thrown
|
|
185
|
-
*
|
|
186
|
-
*
|
|
161
|
+
* Thrown when the Tenant cannot be reached for a reason outside it (the database or Durable
|
|
162
|
+
* Session Execution is unavailable). Not a cause: the next use tries again. The Host answers
|
|
163
|
+
* 503.
|
|
187
164
|
*/
|
|
188
165
|
export declare class TenantUnavailableError extends Error {
|
|
189
|
-
readonly tenantId: string;
|
|
190
166
|
readonly status = 503;
|
|
191
|
-
constructor(
|
|
167
|
+
constructor(options?: {
|
|
192
168
|
cause?: unknown;
|
|
193
169
|
});
|
|
194
170
|
}
|
|
195
|
-
/**
|
|
196
|
-
export declare class TenantNotFoundError extends Error {
|
|
197
|
-
readonly tenantId: string;
|
|
198
|
-
constructor(tenantId: string);
|
|
199
|
-
}
|
|
200
|
-
/** What a Tenant store hands the Tenant Runtime it opens. */
|
|
171
|
+
/** What the Tenant opener hands the Tenant Runtime it opens. */
|
|
201
172
|
export interface OpenedTenant {
|
|
202
173
|
/**
|
|
203
174
|
* The Tenant's opened Session Store. The Tenant Runtime owns it from here on and closes it
|
|
@@ -207,5 +178,5 @@ export interface OpenedTenant {
|
|
|
207
178
|
/** The Tenant envelope as its store reports it. */
|
|
208
179
|
envelope: TenantEnvelope;
|
|
209
180
|
}
|
|
210
|
-
/** Opens the Tenant Runtime on
|
|
181
|
+
/** Opens the Tenant Runtime on an opened store (injected, so tests can fake it). */
|
|
211
182
|
export type OpenTenantRuntime = (config: TenantConfig, opened: OpenedTenant) => Promise<TenantHandle>;
|
package/dist/tenant/types.js
CHANGED
|
@@ -1,23 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Thrown
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Thrown when the Tenant cannot be reached for a reason outside it (the database or Durable
|
|
3
|
+
* Session Execution is unavailable). Not a cause: the next use tries again. The Host answers
|
|
4
|
+
* 503.
|
|
5
5
|
*/
|
|
6
6
|
export class TenantUnavailableError extends Error {
|
|
7
|
-
tenantId;
|
|
8
7
|
status = 503;
|
|
9
|
-
constructor(
|
|
8
|
+
constructor(options) {
|
|
10
9
|
super("Tenant is temporarily unavailable", options);
|
|
11
|
-
this.tenantId = tenantId;
|
|
12
10
|
this.name = "TenantUnavailableError";
|
|
13
11
|
}
|
|
14
12
|
}
|
|
15
|
-
/** Thrown by `TenantStore.open` for a Tenant that does not exist. */
|
|
16
|
-
export class TenantNotFoundError extends Error {
|
|
17
|
-
tenantId;
|
|
18
|
-
constructor(tenantId) {
|
|
19
|
-
super(`Tenant ${tenantId} not found`);
|
|
20
|
-
this.tenantId = tenantId;
|
|
21
|
-
this.name = "TenantNotFoundError";
|
|
22
|
-
}
|
|
23
|
-
}
|
package/dist/tenant/worker.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AdvanceResult, DurableExecution, StuckInvocation, WorkerHandlers } from "../execution/types.js";
|
|
1
|
+
import type { AdvanceResult, DeliverResult, DurableExecution, StuckInvocation, WorkerHandlers } from "../execution/types.js";
|
|
2
2
|
import type { Logger } from "./types.js";
|
|
3
3
|
/** This process's Worker id: the `owner` it writes on the sessions it advances (§10.6). */
|
|
4
4
|
export declare const WORKER_ID: string;
|
|
@@ -38,6 +38,8 @@ export interface TenantWorker {
|
|
|
38
38
|
advance(sessionId: string, signal: AbortSignal): Promise<AdvanceResult>;
|
|
39
39
|
/** One pass of the Tenant sweep. */
|
|
40
40
|
sweep(): Promise<void>;
|
|
41
|
+
/** Delivers one Action to its endpoint. Only infrastructure errors throw. */
|
|
42
|
+
deliver?(actionId: string, signal: AbortSignal): Promise<DeliverResult>;
|
|
41
43
|
}
|
|
42
44
|
export interface TenantWorkersOptions {
|
|
43
45
|
/** Finds or opens a Tenant that is not registered on this process. */
|
package/dist/tenant/worker.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The Worker side of Durable Session Execution (architecture §12.3): what a `DurableExecution`
|
|
3
|
-
* calls for
|
|
4
|
-
* this process.
|
|
3
|
+
* calls for the Tenant, and the registry its handlers dispatch through by Tenant id.
|
|
5
4
|
*
|
|
6
5
|
* - `TenantWorker` is one open Tenant's handlers: `advance(sessionId, signal)` (§10.5, in
|
|
7
|
-
* `advance.ts`)
|
|
6
|
+
* `advance.ts`), `sweep()` (the Tenant sweep, in `sweep.ts`) and, optionally,
|
|
7
|
+
* `deliver(actionId, signal)` (one Action to its Action endpoint).
|
|
8
8
|
* - `TenantWorkers` is the registry. Its `handlers` are the `WorkerHandlers` an execution is
|
|
9
9
|
* started with; they dispatch by `tenantId` to the registered `TenantWorker`. A Tenant
|
|
10
10
|
* registers when it opens and unregisters when it closes. A call for a Tenant that is not
|
|
11
|
-
* open here asks the optional `resolve` hook (the Host
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* open here asks the optional `resolve` hook (the Host's, which waits for its Tenant to
|
|
12
|
+
* open, and knows no other); without one,
|
|
13
|
+
* the advance and the delivery return `done` and the sweep does nothing. Nothing is lost:
|
|
14
|
+
* the Tenant's sweep re-wakes its orphaned sessions once it is open again, and an Action
|
|
15
|
+
* that was not delivered stays pending.
|
|
14
16
|
* - `TenantExecution` pairs an execution with its registry. The Host creates one per process
|
|
15
|
-
* (`host/execution.ts`) and passes it to
|
|
17
|
+
* (`host/execution.ts`) and passes it to its Tenant; a Tenant opened without one
|
|
16
18
|
* (tests, ephemeral) gets its own in-process `MemoryExecution`.
|
|
17
19
|
*
|
|
18
20
|
* ## Advance deadline
|
|
@@ -132,6 +134,10 @@ export class TenantWorkers {
|
|
|
132
134
|
sweep: async (tenantId) => {
|
|
133
135
|
await (await this.find(tenantId))?.sweep();
|
|
134
136
|
},
|
|
137
|
+
deliver: async (tenantId, actionId, signal) => {
|
|
138
|
+
const worker = await this.find(tenantId);
|
|
139
|
+
return worker?.deliver ? worker.deliver(actionId, signal) : DONE;
|
|
140
|
+
},
|
|
135
141
|
};
|
|
136
142
|
/** Runs one advance under the deadline and the grace period (see the module comment). */
|
|
137
143
|
async bounded(tenantId, sessionId, worker, signal) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Tenant's host model credential in plaintext: reading it to call the provider, and
|
|
3
|
+
* writing back a credential the provider adapter refreshed (OAuth). Only the Model Gate holds
|
|
4
|
+
* one (`gates/`; `scripts/check-boundaries.mjs` enforces it), so the loop process never reads a
|
|
5
|
+
* model credential. `VaultService` seals the credential but never reads it back.
|
|
6
|
+
*
|
|
7
|
+
* Decryption runs after the read commits; the key is resolved before the write's transaction.
|
|
8
|
+
*/
|
|
9
|
+
import type { SessionStore } from "../store/types.js";
|
|
10
|
+
import { type HostModelSecret } from "./service.js";
|
|
11
|
+
export interface HostModelVaultOptions {
|
|
12
|
+
readonly store: SessionStore;
|
|
13
|
+
/** The Tenant's key-encryption key; may throw when it is missing. */
|
|
14
|
+
readonly kek: () => Buffer;
|
|
15
|
+
}
|
|
16
|
+
export declare class HostModelVault {
|
|
17
|
+
private readonly store;
|
|
18
|
+
private readonly kek;
|
|
19
|
+
constructor(options: HostModelVaultOptions);
|
|
20
|
+
/** Reads the active host model secret. Decrypts after the read commits. */
|
|
21
|
+
readHostModel(): Promise<HostModelSecret | undefined>;
|
|
22
|
+
/** Replaces the active host model's secret, keeping its binding. */
|
|
23
|
+
updateHostCredential(credential: {
|
|
24
|
+
type: "api_key" | "oauth";
|
|
25
|
+
key?: string;
|
|
26
|
+
env?: Record<string, string>;
|
|
27
|
+
refresh?: string;
|
|
28
|
+
access?: string;
|
|
29
|
+
expires?: number;
|
|
30
|
+
}): Promise<void>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { encryptSecret } from "./crypto.js";
|
|
2
|
+
import { VaultError } from "./error.js";
|
|
3
|
+
import { activeHostCredentialRow, HOST_VAULT_ID, hostModelAad, modelBinding, readHostPayload, } from "./service.js";
|
|
4
|
+
export class HostModelVault {
|
|
5
|
+
store;
|
|
6
|
+
kek;
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.store = options.store;
|
|
9
|
+
this.kek = options.kek;
|
|
10
|
+
}
|
|
11
|
+
/** Reads the active host model secret. Decrypts after the read commits. */
|
|
12
|
+
async readHostModel() {
|
|
13
|
+
const row = await this.store.tx((t) => activeHostCredentialRow(t));
|
|
14
|
+
if (!row)
|
|
15
|
+
return undefined;
|
|
16
|
+
const binding = modelBinding(row);
|
|
17
|
+
const payload = readHostPayload(this.kek(), row, binding);
|
|
18
|
+
const credential = binding.authType === "oauth"
|
|
19
|
+
? { type: "oauth", ...payload.oauth }
|
|
20
|
+
: {
|
|
21
|
+
type: "api_key",
|
|
22
|
+
key: payload.apiKey,
|
|
23
|
+
...(payload.env ? { env: payload.env } : {}),
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
provider: binding.provider,
|
|
27
|
+
model: binding.model,
|
|
28
|
+
...(binding.baseUrl ? { baseUrl: binding.baseUrl } : {}),
|
|
29
|
+
...(binding.settings ? { settings: binding.settings } : {}),
|
|
30
|
+
authType: binding.authType,
|
|
31
|
+
credential,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Replaces the active host model's secret, keeping its binding. */
|
|
35
|
+
async updateHostCredential(credential) {
|
|
36
|
+
const kek = this.kek();
|
|
37
|
+
await this.store.tx(async (t) => {
|
|
38
|
+
const row = await activeHostCredentialRow(t);
|
|
39
|
+
if (!row)
|
|
40
|
+
throw new VaultError(404, "Model provider is not configured");
|
|
41
|
+
const binding = modelBinding(row);
|
|
42
|
+
const payload = credential.type === "oauth"
|
|
43
|
+
? { oauth: credential }
|
|
44
|
+
: {
|
|
45
|
+
apiKey: credential.key,
|
|
46
|
+
...(credential.env ? { env: credential.env } : {}),
|
|
47
|
+
};
|
|
48
|
+
const sealed = encryptSecret(kek, hostModelAad(binding.provider, binding.model), Buffer.from(JSON.stringify(payload), "utf8"));
|
|
49
|
+
await t.updateCredential(HOST_VAULT_ID, row.id, {
|
|
50
|
+
type: "model",
|
|
51
|
+
bindingJson: JSON.stringify({ ...binding, authType: credential.type }),
|
|
52
|
+
...sealed,
|
|
53
|
+
rotatedAt: new Date().toISOString(),
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
package/dist/vault/service.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import type { CreateCredentialRequest, CreateVaultRequest, CredentialInfo, CredentialSelection, HostModelProviderInfo, HostModelView, PutHostModelRequest, RotateCredentialRequest, SelectHostModelRequest, VaultInfo } from "@nylorun/core/contracts";
|
|
2
|
-
import type { SessionStore, Tx } from "../store/types.js";
|
|
1
|
+
import type { CreateCredentialRequest, CreateVaultRequest, CredentialInfo, CredentialSelection, HostModelProviderInfo, HostModelView, PutHostModelRequest, CustomModelSettings, RotateCredentialRequest, SelectHostModelRequest, VaultInfo } from "@nylorun/core/contracts";
|
|
2
|
+
import type { SessionStore, Tx, VaultCredentialRow } from "../store/types.js";
|
|
3
|
+
export declare const HOST_VAULT_ID = "host";
|
|
3
4
|
export type HostModelSecret = {
|
|
4
5
|
provider: string;
|
|
5
6
|
model: string;
|
|
6
7
|
baseUrl?: string;
|
|
8
|
+
/** A custom endpoint's window, output limit, reasoning and pi-ai compat (Model Calls §7). */
|
|
9
|
+
settings?: CustomModelSettings;
|
|
7
10
|
authType: "api_key" | "oauth";
|
|
8
11
|
credential: {
|
|
9
12
|
type: "api_key" | "oauth";
|
|
@@ -37,11 +40,16 @@ export interface VaultServiceOptions {
|
|
|
37
40
|
kek: () => Buffer;
|
|
38
41
|
/** Used only for OAuth refresh, always outside a transaction. */
|
|
39
42
|
fetch: typeof fetch;
|
|
43
|
+
/** How long a token endpoint may take to answer a refresh. Default 30 s. */
|
|
44
|
+
refreshTimeoutMs?: number;
|
|
40
45
|
}
|
|
41
46
|
export declare class VaultService {
|
|
42
47
|
private readonly store;
|
|
43
48
|
private readonly kek;
|
|
44
49
|
private readonly fetchImpl;
|
|
50
|
+
private readonly refreshTimeoutMs;
|
|
51
|
+
/** Refreshes in progress by credential id: concurrent uses share one. */
|
|
52
|
+
private readonly refreshing;
|
|
45
53
|
constructor(options: VaultServiceOptions);
|
|
46
54
|
createVault(body: CreateVaultRequest): Promise<VaultInfo>;
|
|
47
55
|
listVaults(ownerUserId: string): Promise<VaultInfo[]>;
|
|
@@ -80,18 +88,17 @@ export declare class VaultService {
|
|
|
80
88
|
}>;
|
|
81
89
|
putHostModel(body: PutHostModelRequest): Promise<HostModelView>;
|
|
82
90
|
selectHostModel(body: SelectHostModelRequest): Promise<HostModelView>;
|
|
83
|
-
/** Reads the active host model secret. Decrypts after the read commits. */
|
|
84
|
-
readHostModel(): Promise<HostModelSecret | undefined>;
|
|
85
|
-
updateHostCredential(credential: {
|
|
86
|
-
type: "api_key" | "oauth";
|
|
87
|
-
key?: string;
|
|
88
|
-
env?: Record<string, string>;
|
|
89
|
-
refresh?: string;
|
|
90
|
-
access?: string;
|
|
91
|
-
expires?: number;
|
|
92
|
-
}): Promise<void>;
|
|
93
|
-
reject(route: string): Promise<void>;
|
|
94
91
|
/** Calls the token endpoint outside any transaction, then stores the result. */
|
|
92
|
+
/**
|
|
93
|
+
* Refreshes an OAuth grant once for every concurrent use in this process. A rotating refresh
|
|
94
|
+
* token is valid once, so two refreshes with it would fail the second, or make the provider
|
|
95
|
+
* revoke the grant.
|
|
96
|
+
*/
|
|
97
|
+
private refreshShared;
|
|
98
|
+
/** Uses a token another process refreshed instead of refreshing again, before and after. */
|
|
99
|
+
private refreshLatest;
|
|
100
|
+
/** The credential's payload when it was rotated after `row` was read and is not due. */
|
|
101
|
+
private rotatedSince;
|
|
95
102
|
private refresh;
|
|
96
103
|
private replay;
|
|
97
104
|
/** Re-seals a user credential's payload and returns the updated row. */
|
|
@@ -101,12 +108,32 @@ export declare class VaultService {
|
|
|
101
108
|
private validateHostModel;
|
|
102
109
|
private insertHostCredential;
|
|
103
110
|
private hostModelView;
|
|
104
|
-
private hostModelRows;
|
|
105
|
-
private hostCredentialRowFor;
|
|
106
|
-
private activeHostCredentialRow;
|
|
107
|
-
private activeProviderId;
|
|
108
111
|
private setActiveProvider;
|
|
109
112
|
private deleteHostProviderRows;
|
|
110
113
|
private credentialRow;
|
|
111
114
|
private audit;
|
|
112
115
|
}
|
|
116
|
+
/** The host vault's model credential rows that parse. */
|
|
117
|
+
export declare function hostModelRows(t: Tx): Promise<VaultCredentialRow[]>;
|
|
118
|
+
/** The host model credential of `provider`. */
|
|
119
|
+
export declare function hostCredentialRowFor(t: Tx, provider: string): Promise<VaultCredentialRow | undefined>;
|
|
120
|
+
/** The provider the host model selection names, or the only (or legacy) one configured. */
|
|
121
|
+
export declare function activeProviderId(t: Tx): Promise<string | undefined>;
|
|
122
|
+
/** The active host model credential row (ciphertext), in `t`. */
|
|
123
|
+
export declare function activeHostCredentialRow(t: Tx): Promise<VaultCredentialRow | undefined>;
|
|
124
|
+
export declare function readHostPayload(kek: Buffer, row: VaultCredentialRow, binding: ModelBinding): HostSecretPayload;
|
|
125
|
+
type ModelBinding = {
|
|
126
|
+
provider: string;
|
|
127
|
+
model: string;
|
|
128
|
+
baseUrl?: string;
|
|
129
|
+
settings?: CustomModelSettings;
|
|
130
|
+
authType: "api_key" | "oauth";
|
|
131
|
+
};
|
|
132
|
+
type HostSecretPayload = {
|
|
133
|
+
apiKey?: string;
|
|
134
|
+
env?: Record<string, string>;
|
|
135
|
+
oauth?: HostModelSecret["credential"];
|
|
136
|
+
};
|
|
137
|
+
export declare function modelBinding(row: VaultCredentialRow): ModelBinding;
|
|
138
|
+
export declare function hostModelAad(provider: string, model: string): Buffer;
|
|
139
|
+
export {};
|