@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/effects.js
CHANGED
|
@@ -3,34 +3,50 @@ import { countActiveFlowWork, deriveAgentEffectSessionId, isFlowEffect, isFlowTo
|
|
|
3
3
|
import { mayDispatchMore } from "../core/limits.js";
|
|
4
4
|
import { canonical } from "../store/canonical.js";
|
|
5
5
|
import { isOwnershipLost } from "../store/ownership.js";
|
|
6
|
-
import { newStreamIncarnation } from "../streams/types.js";
|
|
7
|
-
import { piModel } from "../model/pi-model.js";
|
|
8
6
|
import { scrub } from "../redact.js";
|
|
9
|
-
import { serversOf } from "../mcp/pool.js";
|
|
7
|
+
import { findServer, serversOf } from "../mcp/pool.js";
|
|
10
8
|
import { sandboxCapabilityOf } from "../sandbox/manager.js";
|
|
11
|
-
import { owningSandboxSessionId, sandboxSpecOf } from "../sandbox/share.js";
|
|
9
|
+
import { owningSandboxSessionId, sandboxSpecOf, sessionSandboxSpec, } from "../sandbox/share.js";
|
|
10
|
+
import { withSandboxCapability } from "../sandbox/session-sandbox.js";
|
|
12
11
|
import { loadSession, ownedSession, sandboxLookup, sessionOf, } from "./context.js";
|
|
13
12
|
import { fail } from "./http.js";
|
|
14
13
|
import { actionTarget, linkedAgentOutput, manifestFor, mcpToolOf, pinnedTool, turnManifestOf, } from "./session.js";
|
|
15
14
|
import { command } from "./commands.js";
|
|
16
|
-
import {
|
|
15
|
+
import { offerAction } from "./delivery.js";
|
|
16
|
+
import { assistantMessage, contextCompacted, modelFailed, toolCompleted, toolIds, } from "./transcript.js";
|
|
17
|
+
import { classifyThrown } from "../model/classify.js";
|
|
17
18
|
import { abortKind } from "./worker.js";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Call the model for one effect. A provider failure comes back as a failure outcome
|
|
21
|
+
* (Model Calls §6), whichever provider serves the call; only an abort throws, and the
|
|
22
|
+
* advance decides what the abort means.
|
|
23
|
+
*/
|
|
24
|
+
export async function invokeModel(ctx, request, signal, model) {
|
|
25
|
+
try {
|
|
26
|
+
if (model)
|
|
27
|
+
return await model(request, signal);
|
|
28
|
+
if (!ctx.useVaultModel)
|
|
29
|
+
return await ctx.modelProvider(request, signal);
|
|
30
|
+
return await ctx.modelGate.call({
|
|
31
|
+
tenantId: ctx.config.tenantId,
|
|
32
|
+
sessionId: request.sessionId,
|
|
33
|
+
turnId: request.turnId,
|
|
34
|
+
agentId: request.agentId,
|
|
35
|
+
effectId: request.effectId,
|
|
36
|
+
invocationId: String(request.context.invocationId),
|
|
37
|
+
call: request.input,
|
|
38
|
+
}, signal);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (signal.aborted) {
|
|
42
|
+
// A call that outlives this process stops only when told to: on a user cancel. After a
|
|
43
|
+
// shutdown or a lost lease the next owner re-sends it and picks up its outcome (P1.2).
|
|
44
|
+
if (!model && ctx.useVaultModel && abortKind(signal) === "cancel" && ctx.modelGate.cancel)
|
|
45
|
+
await ctx.modelGate.cancel({ tenantId: ctx.config.tenantId, effectId: request.effectId });
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
return classifyThrown(error);
|
|
49
|
+
}
|
|
34
50
|
}
|
|
35
51
|
/**
|
|
36
52
|
* The outcome of a flow `agent` effect once the linked turn it started ended, or undefined
|
|
@@ -53,6 +69,32 @@ async function linkedOutcome(t, effect, agent) {
|
|
|
53
69
|
},
|
|
54
70
|
};
|
|
55
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* True when this Tenant's remote MCP calls outlive the process that sent them (the gates
|
|
74
|
+
* service, F4.1 G3): after a takeover or a shutdown, the journaled call is re-sent and joins
|
|
75
|
+
* the running call or gets its answer, instead of becoming `uncertain`.
|
|
76
|
+
*/
|
|
77
|
+
export function recoversMcpCalls(ctx) {
|
|
78
|
+
return ctx.toolGate.recovers === true;
|
|
79
|
+
}
|
|
80
|
+
/** True when `request` calls a tool of a remote (`streamable-http` or `sse`) MCP server. */
|
|
81
|
+
export function isRemoteMcpEffect(s, request) {
|
|
82
|
+
if (request.kind !== "tool")
|
|
83
|
+
return false;
|
|
84
|
+
const tool = mcpToolOf(s, request);
|
|
85
|
+
if (!tool)
|
|
86
|
+
return false;
|
|
87
|
+
const declared = findServer(s.manifest, tool.agentId, tool.capabilityId, tool.serverName);
|
|
88
|
+
return declared !== undefined && declared.server.type !== "stdio";
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* True when this Tenant's vault-backed model calls outlive the process that sent them (the
|
|
92
|
+
* gates service, P1.2): after a takeover or a shutdown, the journaled call is re-sent and joins
|
|
93
|
+
* the running call or gets its outcome, instead of becoming `uncertain`.
|
|
94
|
+
*/
|
|
95
|
+
export function recoversModelCalls(ctx) {
|
|
96
|
+
return ctx.useVaultModel && ctx.modelGate.recovers === true;
|
|
97
|
+
}
|
|
56
98
|
/**
|
|
57
99
|
* What an effect's journal row must match on replay. A delegation's context carries only the
|
|
58
100
|
* parent's tool call id, for its events; rows journaled before it existed still match.
|
|
@@ -85,6 +127,22 @@ export async function resolveEffect(ctx, request, signal, lease, segment = {}) {
|
|
|
85
127
|
throw new Error("Effect identity request drift");
|
|
86
128
|
if (existing.status === "completed")
|
|
87
129
|
return resolved({ status: "completed", outcome: existing.outcome });
|
|
130
|
+
// A model call its previous owner left running at the gate: re-send it, same key and
|
|
131
|
+
// request, to join it or collect its outcome.
|
|
132
|
+
if (existing.status === "invoking" &&
|
|
133
|
+
request.kind === "model" &&
|
|
134
|
+
recoversModelCalls(ctx))
|
|
135
|
+
return { kind: "invoke", invoke: "model", journaled: existing.request };
|
|
136
|
+
// A remote MCP call its previous owner left running at the gate: the same, by effect id.
|
|
137
|
+
if (existing.status === "invoking" &&
|
|
138
|
+
recoversMcpCalls(ctx) &&
|
|
139
|
+
isRemoteMcpEffect(s, existing.request))
|
|
140
|
+
return {
|
|
141
|
+
kind: "invoke",
|
|
142
|
+
invoke: "mcp",
|
|
143
|
+
journaled: existing.request,
|
|
144
|
+
remote: true,
|
|
145
|
+
};
|
|
88
146
|
if (request.kind === "agent" && existing.status === "pending") {
|
|
89
147
|
const agentSessionId = existing.agentSessionId;
|
|
90
148
|
if (agentSessionId) {
|
|
@@ -144,6 +202,7 @@ export async function resolveEffect(ctx, request, signal, lease, segment = {}) {
|
|
|
144
202
|
return {
|
|
145
203
|
kind: "invoke",
|
|
146
204
|
invoke: mcpTool ? "mcp" : sandboxTool ? "sandbox" : "model",
|
|
205
|
+
...(mcpTool && isRemoteMcpEffect(s, request) ? { remote: true } : {}),
|
|
147
206
|
};
|
|
148
207
|
const tool = request.kind === "tool"
|
|
149
208
|
? pinnedTool(agentManifest, request.capabilityId, request.toolName)
|
|
@@ -159,8 +218,6 @@ export async function resolveEffect(ctx, request, signal, lease, segment = {}) {
|
|
|
159
218
|
context: request.context,
|
|
160
219
|
status: "pending",
|
|
161
220
|
generation: 0,
|
|
162
|
-
claimId: null,
|
|
163
|
-
leaseExpiresAt: null,
|
|
164
221
|
...(request.agent ? { agent: request.agent } : {}),
|
|
165
222
|
};
|
|
166
223
|
const action = request.kind === "hook"
|
|
@@ -189,7 +246,7 @@ export async function resolveEffect(ctx, request, signal, lease, segment = {}) {
|
|
|
189
246
|
...(action.kind === "tool" ? toolIds(request.context) : {}),
|
|
190
247
|
input: action.input,
|
|
191
248
|
});
|
|
192
|
-
t
|
|
249
|
+
await offerAction(t, ctx, action);
|
|
193
250
|
return resolved({ status: "pending" });
|
|
194
251
|
});
|
|
195
252
|
if (journaled.kind === "resolved")
|
|
@@ -203,10 +260,10 @@ export async function resolveEffect(ctx, request, signal, lease, segment = {}) {
|
|
|
203
260
|
try {
|
|
204
261
|
// The intent is committed; the call itself runs outside any transaction.
|
|
205
262
|
const value = invoke === "mcp"
|
|
206
|
-
? await callMcpTool(ctx, request)
|
|
263
|
+
? await callMcpTool(ctx, journaled.journaled ?? request, abortOn(signal, journaled.remote && recoversMcpCalls(ctx) ? ["cancel", "shutdown"] : ["cancel"]))
|
|
207
264
|
: invoke === "sandbox"
|
|
208
265
|
? await callSandboxTool(ctx, request, signal)
|
|
209
|
-
: await invokeModel(ctx, request, signal, segment.model);
|
|
266
|
+
: await invokeModel(ctx, journaled.journaled ?? request, signal, segment.model);
|
|
210
267
|
return await store.tx(async (t) => {
|
|
211
268
|
const s = await ownedSession(t, lease, request.sessionId);
|
|
212
269
|
// Only a cancel discards an outcome in hand (§10.7). After any other abort (shutdown,
|
|
@@ -219,11 +276,23 @@ export async function resolveEffect(ctx, request, signal, lease, segment = {}) {
|
|
|
219
276
|
effect.status = "completed";
|
|
220
277
|
effect.outcome = { value };
|
|
221
278
|
await t.put("effects", request.effectId, effect);
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
279
|
+
const failed = invoke === "model" ? modelFailed(request, value) : undefined;
|
|
280
|
+
// A summary call is never an assistant message; the last one publishes context.compacted.
|
|
281
|
+
const summarizing = invoke === "model" && Boolean(request.context.compaction);
|
|
282
|
+
const compacted = summarizing && !failed ? contextCompacted(request, value) : undefined;
|
|
283
|
+
const transcript = failed || summarizing
|
|
284
|
+
? undefined
|
|
285
|
+
: invoke === "model"
|
|
286
|
+
? assistantMessage(request, value)
|
|
287
|
+
: toolCompleted(request, value);
|
|
288
|
+
if (failed)
|
|
289
|
+
await t.event(s.id, request.turnId, "model.failed", failed);
|
|
290
|
+
if (compacted)
|
|
291
|
+
await t.event(s.id, request.turnId, "context.compacted", compacted);
|
|
292
|
+
if (transcript && invoke === "model")
|
|
293
|
+
await t.event(s.id, request.turnId, "message.assistant", transcript);
|
|
294
|
+
else if (transcript)
|
|
295
|
+
await t.event(s.id, request.turnId, "tool.completed", transcript);
|
|
227
296
|
return { status: "completed", outcome: effect.outcome };
|
|
228
297
|
});
|
|
229
298
|
}
|
|
@@ -231,6 +300,18 @@ export async function resolveEffect(ctx, request, signal, lease, segment = {}) {
|
|
|
231
300
|
// A lost epoch writes nothing: the new owner decides what the effect became.
|
|
232
301
|
if (isOwnershipLost(error))
|
|
233
302
|
throw error;
|
|
303
|
+
// A shutdown leaves a model call running at the gate, still `invoking`: the next advance
|
|
304
|
+
// re-sends it (P1.2). The segment stops for the shutdown as usual.
|
|
305
|
+
if (invoke === "model" && recoversModelCalls(ctx) && abortKind(signal) === "shutdown")
|
|
306
|
+
throw error;
|
|
307
|
+
// The same for a remote MCP call at the Tool Gate (G3). A user cancel stops it there: a
|
|
308
|
+
// keyed call outlives the request that sent it.
|
|
309
|
+
if (invoke === "mcp" && journaled.remote && recoversMcpCalls(ctx)) {
|
|
310
|
+
if (abortKind(signal) === "shutdown")
|
|
311
|
+
throw error;
|
|
312
|
+
if (abortKind(signal) === "cancel" && ctx.toolGate.cancel)
|
|
313
|
+
await ctx.toolGate.cancel({ tenantId: ctx.config.tenantId, effectId: request.effectId });
|
|
314
|
+
}
|
|
234
315
|
await store.tx(async (t) => {
|
|
235
316
|
const s = request.sessionId === lease.sessionId
|
|
236
317
|
? await t.assertEpoch(request.sessionId, lease.epoch)
|
|
@@ -312,8 +393,6 @@ export async function resolveNewFlowEffect(ctx, request, signal, lease) {
|
|
|
312
393
|
context: request.context,
|
|
313
394
|
status: "pending",
|
|
314
395
|
generation: 0,
|
|
315
|
-
claimId: null,
|
|
316
|
-
leaseExpiresAt: null,
|
|
317
396
|
kind: request.kind,
|
|
318
397
|
path: request.path,
|
|
319
398
|
key: request.key,
|
|
@@ -329,8 +408,6 @@ export async function resolveNewFlowEffect(ctx, request, signal, lease) {
|
|
|
329
408
|
context: request.context,
|
|
330
409
|
status: "pending",
|
|
331
410
|
generation: 0,
|
|
332
|
-
claimId: null,
|
|
333
|
-
leaseExpiresAt: null,
|
|
334
411
|
kind: "tool",
|
|
335
412
|
path: request.path,
|
|
336
413
|
key: request.key,
|
|
@@ -353,7 +430,7 @@ export async function resolveNewFlowEffect(ctx, request, signal, lease) {
|
|
|
353
430
|
key: action.key,
|
|
354
431
|
input: action.input,
|
|
355
432
|
});
|
|
356
|
-
t
|
|
433
|
+
await offerAction(t, ctx, action);
|
|
357
434
|
return resolved({ status: "pending" });
|
|
358
435
|
}
|
|
359
436
|
return { kind: "agent", workflow };
|
|
@@ -388,15 +465,18 @@ export async function resolveNewFlowEffect(ctx, request, signal, lease) {
|
|
|
388
465
|
if (exists)
|
|
389
466
|
return;
|
|
390
467
|
const definition = await leafDefinition(t, workflow, body, request);
|
|
391
|
-
const
|
|
392
|
-
|
|
468
|
+
const lookup = await sandboxLookup(t, workflow.sandboxOwnerId);
|
|
469
|
+
const sandboxOwnerId = sessionSandboxSpec(workflow) || workflow.sandboxOwnerId
|
|
470
|
+
? owningSandboxSessionId(workflow, lookup)
|
|
393
471
|
: undefined;
|
|
472
|
+
// A sandbox chosen when the tree was opened reaches every agent in it, with its tools.
|
|
473
|
+
const inherited = inheritedSandbox(sandboxOwnerId === undefined ? undefined : lookup(sandboxOwnerId) ?? workflow, definition);
|
|
394
474
|
const created = {
|
|
395
475
|
id: agentSessionId,
|
|
396
476
|
agentId: body.agentId,
|
|
397
477
|
ownerUserId: workflow.ownerUserId,
|
|
398
|
-
manifest: definition.manifest,
|
|
399
|
-
manifestHash: definition.manifestHash,
|
|
478
|
+
manifest: inherited?.manifest ?? definition.manifest,
|
|
479
|
+
manifestHash: inherited?.manifestHash ?? definition.manifestHash,
|
|
400
480
|
implementationVersion: definition.implementationVersion,
|
|
401
481
|
status: "idle",
|
|
402
482
|
activeTurnId: null,
|
|
@@ -410,7 +490,9 @@ export async function resolveNewFlowEffect(ctx, request, signal, lease) {
|
|
|
410
490
|
credentialSelections: workflow.credentialSelections,
|
|
411
491
|
pluginRoots: definition.pluginRoots ?? {},
|
|
412
492
|
...(sandboxOwnerId ? { sandboxOwnerId } : {}),
|
|
413
|
-
|
|
493
|
+
...(inherited
|
|
494
|
+
? { sandbox: inherited.spec, sandboxSource: "shared" }
|
|
495
|
+
: {}),
|
|
414
496
|
};
|
|
415
497
|
await t.put("sessions", agentSessionId, created);
|
|
416
498
|
});
|
|
@@ -518,7 +600,25 @@ export async function prepareMcp(ctx, lease, signal) {
|
|
|
518
600
|
await t.put("sessions", id, current);
|
|
519
601
|
});
|
|
520
602
|
}
|
|
521
|
-
|
|
603
|
+
/**
|
|
604
|
+
* A signal that follows `signal` only for the abort kinds in `kinds`. An MCP call stops on a
|
|
605
|
+
* cancel; at the Tool Gate it also stops waiting on a shutdown, since the gate keeps the call
|
|
606
|
+
* for the next owner. Otherwise a shutdown or a deadline lets the call finish and records it,
|
|
607
|
+
* so the next advance replays it.
|
|
608
|
+
*/
|
|
609
|
+
function abortOn(signal, kinds) {
|
|
610
|
+
const controller = new AbortController();
|
|
611
|
+
const follow = () => {
|
|
612
|
+
if (kinds.includes(abortKind(signal)))
|
|
613
|
+
controller.abort(signal.reason);
|
|
614
|
+
};
|
|
615
|
+
if (signal.aborted)
|
|
616
|
+
follow();
|
|
617
|
+
else
|
|
618
|
+
signal.addEventListener("abort", follow, { once: true });
|
|
619
|
+
return controller.signal;
|
|
620
|
+
}
|
|
621
|
+
async function callMcpTool(ctx, request, signal) {
|
|
522
622
|
const s = await loadSession(ctx, request.sessionId);
|
|
523
623
|
const tool = mcpToolOf(s, request);
|
|
524
624
|
if (!tool)
|
|
@@ -532,8 +632,25 @@ async function callMcpTool(ctx, request) {
|
|
|
532
632
|
args: request.input,
|
|
533
633
|
manifest: s.manifest,
|
|
534
634
|
pluginRoots: s.pluginRoots ?? {},
|
|
635
|
+
effectId: request.effectId,
|
|
636
|
+
signal,
|
|
535
637
|
});
|
|
536
638
|
}
|
|
639
|
+
/**
|
|
640
|
+
* The sandbox a linked session inherits from its tree's owner when that sandbox was chosen at
|
|
641
|
+
* open (pinned on the owner). A definition that declares its own sandbox keeps it, as before.
|
|
642
|
+
*/
|
|
643
|
+
function inheritedSandbox(owner, definition) {
|
|
644
|
+
const spec = owner?.sandbox;
|
|
645
|
+
if (!spec || sandboxSpecOf(definition.manifest))
|
|
646
|
+
return undefined;
|
|
647
|
+
if (isWorkflowManifest(definition.manifest))
|
|
648
|
+
return { spec };
|
|
649
|
+
const sandboxed = withSandboxCapability(definition.manifest, spec);
|
|
650
|
+
if (!sandboxed.ok)
|
|
651
|
+
throw new Error(sandboxed.message);
|
|
652
|
+
return { spec, manifest: sandboxed.manifest, manifestHash: sandboxed.manifestHash };
|
|
653
|
+
}
|
|
537
654
|
async function callSandboxTool(ctx, request, signal) {
|
|
538
655
|
const { s, ownerId } = await ctx.store.tx(async (t) => {
|
|
539
656
|
const s = await sessionOf(t, request.sessionId);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action endpoints (design: Action endpoints §4.2): where the Runtime delivers each agent's
|
|
3
|
+
* Actions, registered with the application key.
|
|
4
|
+
*/
|
|
5
|
+
import { type Endpoint, type PutEndpointsRequest } from "@nylorun/core/contracts";
|
|
6
|
+
import type { EndpointRow } from "../store/types.js";
|
|
7
|
+
import type { TenantContext } from "./context.js";
|
|
8
|
+
/** An endpoint as the Tenant API answers it. */
|
|
9
|
+
export declare function endpointView(row: EndpointRow): Endpoint;
|
|
10
|
+
/** `GET /v1/endpoints`. */
|
|
11
|
+
export declare function listEndpoints(ctx: TenantContext): Promise<{
|
|
12
|
+
endpoints: {
|
|
13
|
+
agentId: string;
|
|
14
|
+
url: string;
|
|
15
|
+
implementationVersion: string;
|
|
16
|
+
manifestHash?: string | undefined;
|
|
17
|
+
timeoutMs: number;
|
|
18
|
+
maxConcurrent: number;
|
|
19
|
+
health: {
|
|
20
|
+
lastDeliveryAt?: string | undefined;
|
|
21
|
+
lastSuccessAt?: string | undefined;
|
|
22
|
+
lastError?: {
|
|
23
|
+
code: string;
|
|
24
|
+
message: string;
|
|
25
|
+
} | undefined;
|
|
26
|
+
consecutiveFailures: number;
|
|
27
|
+
served?: {
|
|
28
|
+
implementationVersion: string;
|
|
29
|
+
manifestHash?: string | undefined;
|
|
30
|
+
} | undefined;
|
|
31
|
+
};
|
|
32
|
+
updatedAt: string;
|
|
33
|
+
}[];
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* `PUT /v1/endpoints`: upsert the batch in one transaction, then send the Actions already
|
|
37
|
+
* waiting for these agents. Answers every registered endpoint of the batch.
|
|
38
|
+
*/
|
|
39
|
+
export declare function putEndpoints(ctx: TenantContext, principalId: string, body: PutEndpointsRequest): Promise<{
|
|
40
|
+
endpoints: {
|
|
41
|
+
agentId: string;
|
|
42
|
+
url: string;
|
|
43
|
+
implementationVersion: string;
|
|
44
|
+
manifestHash?: string | undefined;
|
|
45
|
+
timeoutMs: number;
|
|
46
|
+
maxConcurrent: number;
|
|
47
|
+
health: {
|
|
48
|
+
lastDeliveryAt?: string | undefined;
|
|
49
|
+
lastSuccessAt?: string | undefined;
|
|
50
|
+
lastError?: {
|
|
51
|
+
code: string;
|
|
52
|
+
message: string;
|
|
53
|
+
} | undefined;
|
|
54
|
+
consecutiveFailures: number;
|
|
55
|
+
served?: {
|
|
56
|
+
implementationVersion: string;
|
|
57
|
+
manifestHash?: string | undefined;
|
|
58
|
+
} | undefined;
|
|
59
|
+
};
|
|
60
|
+
updatedAt: string;
|
|
61
|
+
}[];
|
|
62
|
+
}>;
|
|
63
|
+
/** `DELETE /v1/endpoints/:agentId`. The agent's pending Actions wait for a new endpoint. */
|
|
64
|
+
export declare function deleteEndpoint(ctx: TenantContext, agentId: string): Promise<{
|
|
65
|
+
agentId: string;
|
|
66
|
+
deleted: true;
|
|
67
|
+
}>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action endpoints (design: Action endpoints §4.2): where the Runtime delivers each agent's
|
|
3
|
+
* Actions, registered with the application key.
|
|
4
|
+
*/
|
|
5
|
+
import { ENDPOINT_MAX_CONCURRENT_DEFAULT, ENDPOINT_TIMEOUT_DEFAULT_MS, } from "@nylorun/core/contracts";
|
|
6
|
+
import { fail } from "./http.js";
|
|
7
|
+
/** An endpoint as the Tenant API answers it. */
|
|
8
|
+
export function endpointView(row) {
|
|
9
|
+
const served = row.servedImplementationVersion === undefined
|
|
10
|
+
? undefined
|
|
11
|
+
: {
|
|
12
|
+
implementationVersion: row.servedImplementationVersion,
|
|
13
|
+
...(row.servedManifestHash === undefined
|
|
14
|
+
? {}
|
|
15
|
+
: { manifestHash: row.servedManifestHash }),
|
|
16
|
+
};
|
|
17
|
+
return {
|
|
18
|
+
agentId: row.agentId,
|
|
19
|
+
url: row.url,
|
|
20
|
+
implementationVersion: row.implementationVersion,
|
|
21
|
+
...(row.manifestHash === undefined ? {} : { manifestHash: row.manifestHash }),
|
|
22
|
+
timeoutMs: row.timeoutMs,
|
|
23
|
+
maxConcurrent: row.maxConcurrent,
|
|
24
|
+
health: {
|
|
25
|
+
...(row.lastDeliveryAt === undefined ? {} : { lastDeliveryAt: row.lastDeliveryAt }),
|
|
26
|
+
...(row.lastSuccessAt === undefined ? {} : { lastSuccessAt: row.lastSuccessAt }),
|
|
27
|
+
...(row.lastErrorCode === undefined
|
|
28
|
+
? {}
|
|
29
|
+
: {
|
|
30
|
+
lastError: {
|
|
31
|
+
code: row.lastErrorCode,
|
|
32
|
+
message: row.lastErrorMessage ?? "",
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
consecutiveFailures: row.consecutiveFailures,
|
|
36
|
+
...(served ? { served } : {}),
|
|
37
|
+
},
|
|
38
|
+
updatedAt: row.updatedAt,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/** `GET /v1/endpoints`. */
|
|
42
|
+
export async function listEndpoints(ctx) {
|
|
43
|
+
const rows = await ctx.store.tx((t) => t.listEndpoints());
|
|
44
|
+
return { endpoints: rows.map(endpointView) };
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* `PUT /v1/endpoints`: upsert the batch in one transaction, then send the Actions already
|
|
48
|
+
* waiting for these agents. Answers every registered endpoint of the batch.
|
|
49
|
+
*/
|
|
50
|
+
export async function putEndpoints(ctx, principalId, body) {
|
|
51
|
+
const updatedAt = new Date().toISOString();
|
|
52
|
+
const rows = await ctx.store.tx(async (t) => {
|
|
53
|
+
const saved = [];
|
|
54
|
+
for (const endpoint of body.endpoints) {
|
|
55
|
+
await t.putEndpoint({
|
|
56
|
+
agentId: endpoint.agentId,
|
|
57
|
+
url: endpoint.url,
|
|
58
|
+
implementationVersion: endpoint.implementationVersion,
|
|
59
|
+
...(endpoint.manifestHash === undefined
|
|
60
|
+
? {}
|
|
61
|
+
: { manifestHash: endpoint.manifestHash }),
|
|
62
|
+
timeoutMs: endpoint.timeoutMs ?? ENDPOINT_TIMEOUT_DEFAULT_MS,
|
|
63
|
+
maxConcurrent: endpoint.maxConcurrent ?? ENDPOINT_MAX_CONCURRENT_DEFAULT,
|
|
64
|
+
principalId,
|
|
65
|
+
updatedAt,
|
|
66
|
+
});
|
|
67
|
+
saved.push((await t.getEndpoint(endpoint.agentId)));
|
|
68
|
+
}
|
|
69
|
+
return saved;
|
|
70
|
+
});
|
|
71
|
+
// Actions already waiting for these agents go to their endpoint now.
|
|
72
|
+
const waiting = await ctx.store.tx(async (t) => {
|
|
73
|
+
const actions = [];
|
|
74
|
+
for (const endpoint of body.endpoints)
|
|
75
|
+
actions.push(...(await t.pendingActions(endpoint.agentId)));
|
|
76
|
+
return actions;
|
|
77
|
+
});
|
|
78
|
+
for (const action of waiting)
|
|
79
|
+
await ctx.deliver(action.actionId);
|
|
80
|
+
return { endpoints: rows.map(endpointView) };
|
|
81
|
+
}
|
|
82
|
+
/** `DELETE /v1/endpoints/:agentId`. The agent's pending Actions wait for a new endpoint. */
|
|
83
|
+
export async function deleteEndpoint(ctx, agentId) {
|
|
84
|
+
await ctx.store.tx(async (t) => {
|
|
85
|
+
if (!(await t.getEndpoint(agentId)))
|
|
86
|
+
fail(404, "Endpoint not found");
|
|
87
|
+
await t.deleteEndpoint(agentId);
|
|
88
|
+
});
|
|
89
|
+
return { agentId, deleted: true };
|
|
90
|
+
}
|
|
@@ -1,17 +1,23 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type PostgresClient } from "../store/postgres/connect.js";
|
|
2
2
|
import type { Logger, TenantModelConfig } from "./types.js";
|
|
3
3
|
export interface StartEphemeralRuntimeOptions {
|
|
4
4
|
/**
|
|
5
|
-
* Absolute Host root for `host.json`, the admin key and
|
|
5
|
+
* Absolute Host root for `host.json`, the admin key and the Tenant's files (vault key,
|
|
6
6
|
* home, sandboxes). Caller creates any temporary directory. Session data never lands here.
|
|
7
7
|
*/
|
|
8
8
|
hostRoot: string;
|
|
9
|
+
/** The Tenant's id when the database holds no Tenant yet. Default: a new id. */
|
|
9
10
|
tenantId?: string;
|
|
11
|
+
/** The Tenant's name when the database holds no Tenant yet. Default `ephemeral`. */
|
|
10
12
|
name?: string;
|
|
13
|
+
/** An application key for an application principal of the Tenant. Default: a new key. */
|
|
11
14
|
applicationKey?: string;
|
|
12
15
|
adminKey?: string;
|
|
13
16
|
principalId?: string;
|
|
14
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* SHA-256 of the Studio key; registers principal `studio` with it. Default: the key the
|
|
19
|
+
* admin key derives (`deriveStudioToken` in `@nylorun/admin`).
|
|
20
|
+
*/
|
|
15
21
|
studioCredentialHash?: string;
|
|
16
22
|
/** Allowlisted baseline for childEnv (e.g. PATH). Never read from ambient here. */
|
|
17
23
|
baseline?: Readonly<Record<string, string>>;
|
|
@@ -19,15 +25,23 @@ export interface StartEphemeralRuntimeOptions {
|
|
|
19
25
|
sandboxBackend?: "auto" | "virtual";
|
|
20
26
|
/** When true, close() leaves hostRoot on disk. */
|
|
21
27
|
retainRoot?: boolean;
|
|
28
|
+
/** Allow browser requests (an `Origin` with a publishable key). Default off. */
|
|
29
|
+
browserAccess?: boolean;
|
|
30
|
+
/** Serve the Admin API on its own loopback listener (`adminUrl`). Default off. */
|
|
31
|
+
operatorListener?: boolean;
|
|
22
32
|
logger?: Logger;
|
|
23
33
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
34
|
+
* The Postgres database of the Tenant (one Tenant per database): a pool, which the caller
|
|
35
|
+
* ends, or a URL, for which the Runtime opens a pool and ends it on `close()`. A database
|
|
36
|
+
* that already holds a Tenant serves that one. The data stays after `close()`; a test drops
|
|
37
|
+
* its database.
|
|
26
38
|
*/
|
|
27
|
-
database
|
|
39
|
+
database: PostgresClient | string;
|
|
28
40
|
}
|
|
29
41
|
export interface EphemeralRuntime {
|
|
30
42
|
url: string;
|
|
43
|
+
/** Where the Admin API answers: `url`, or the operator listener when requested. */
|
|
44
|
+
adminUrl: string;
|
|
31
45
|
tenantId: string;
|
|
32
46
|
applicationKey: string;
|
|
33
47
|
adminKey: string;
|
|
@@ -36,7 +50,8 @@ export interface EphemeralRuntime {
|
|
|
36
50
|
close(): Promise<void>;
|
|
37
51
|
}
|
|
38
52
|
/**
|
|
39
|
-
* Private Host on port 0
|
|
53
|
+
* Private Host on port 0 serving one Tenant (D9 / A19). Durable only in its database (see the
|
|
54
|
+
* module comment).
|
|
40
55
|
* Exported from `@nylorun/runtime` and `@nylorun/runtime/core`.
|
|
41
56
|
*/
|
|
42
57
|
export declare function startEphemeralRuntime(options: StartEphemeralRuntimeOptions): Promise<EphemeralRuntime>;
|