@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/store/memory.js
DELETED
|
@@ -1,645 +0,0 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
-
import { randomUUID } from "node:crypto";
|
|
3
|
-
import { encodeCursor } from "./cursor.js";
|
|
4
|
-
import { OwnershipLostError } from "./ownership.js";
|
|
5
|
-
import { DOC_TABLES, } from "./types.js";
|
|
6
|
-
/** Schema version the fake reports; it has no migrations. */
|
|
7
|
-
export const MEMORY_SCHEMA_VERSION = 1;
|
|
8
|
-
function emptyState() {
|
|
9
|
-
return {
|
|
10
|
-
docs: Object.fromEntries(DOC_TABLES.map((table) => [table, new Map()])),
|
|
11
|
-
sessionMeta: new Map(),
|
|
12
|
-
outbox: new Map(),
|
|
13
|
-
executors: new Map(),
|
|
14
|
-
principals: new Map(),
|
|
15
|
-
vaults: new Map(),
|
|
16
|
-
credentials: new Map(),
|
|
17
|
-
audit: [],
|
|
18
|
-
idempotency: new Map(),
|
|
19
|
-
settings: new Map(),
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
const OWNERSHIP_KEYS = new Set(["owner", "epoch", "ownerExpiresAt"]);
|
|
23
|
-
const OPEN_SESSION = new Set(["running", "runnable"]);
|
|
24
|
-
const byId = (entries) => [...entries].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
|
|
25
|
-
const copy = (value) => structuredClone(value);
|
|
26
|
-
/**
|
|
27
|
-
* The data behind in-memory Session Stores: what a database is to its connections. Several
|
|
28
|
-
* `MemorySessionStore`s on one `MemoryStoreData` see each other's commits and serialize their
|
|
29
|
-
* transactions together, as several processes on one Tenant schema would; it outlives them,
|
|
30
|
-
* so a test can close a Tenant and open it again.
|
|
31
|
-
*/
|
|
32
|
-
export class MemoryStoreData {
|
|
33
|
-
/** @internal */ state = emptyState();
|
|
34
|
-
/** @internal */ queue = Promise.resolve();
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* In-memory `SessionStore` for unit tests. Not a supported profile.
|
|
38
|
-
*
|
|
39
|
-
* Transactions are serialized (one at a time), each works on a copy of the
|
|
40
|
-
* state and replaces it on commit, so a throw rolls back everything: documents,
|
|
41
|
-
* sequences, outbox rows, `afterCommit` callbacks and `signalWork`. Commit listeners see
|
|
42
|
-
* only this store's commits, as with a Postgres connection.
|
|
43
|
-
*/
|
|
44
|
-
export class MemorySessionStore {
|
|
45
|
-
data;
|
|
46
|
-
tenantId;
|
|
47
|
-
active = new AsyncLocalStorage();
|
|
48
|
-
listeners = new Set();
|
|
49
|
-
now;
|
|
50
|
-
onError;
|
|
51
|
-
closed = false;
|
|
52
|
-
constructor(options,
|
|
53
|
-
/** Shared with other stores on the same data; a fresh, private one by default. */
|
|
54
|
-
data = new MemoryStoreData()) {
|
|
55
|
-
this.data = data;
|
|
56
|
-
this.tenantId = options.tenantId;
|
|
57
|
-
this.now = options.now ?? (() => new Date());
|
|
58
|
-
this.onError =
|
|
59
|
-
options.onError ??
|
|
60
|
-
((error) => queueMicrotask(() => {
|
|
61
|
-
throw error;
|
|
62
|
-
}));
|
|
63
|
-
}
|
|
64
|
-
async tx(fn) {
|
|
65
|
-
if (this.closed)
|
|
66
|
-
throw new Error("SessionStore is closed");
|
|
67
|
-
if (this.active.getStore() === this)
|
|
68
|
-
throw new Error("Nested SessionStore.tx is not allowed");
|
|
69
|
-
const release = await this.acquire();
|
|
70
|
-
let t;
|
|
71
|
-
let result;
|
|
72
|
-
try {
|
|
73
|
-
const working = copy(this.data.state);
|
|
74
|
-
t = new MemoryTx(working, this.tenantId, this.now);
|
|
75
|
-
try {
|
|
76
|
-
result = await this.active.run(this, () => fn(t));
|
|
77
|
-
}
|
|
78
|
-
finally {
|
|
79
|
-
t.closed = true;
|
|
80
|
-
}
|
|
81
|
-
this.data.state = working;
|
|
82
|
-
if (t.events.length > 0 || t.workAvailable) {
|
|
83
|
-
const commit = {
|
|
84
|
-
events: t.events,
|
|
85
|
-
incarnations: t.incarnations,
|
|
86
|
-
workAvailable: t.workAvailable,
|
|
87
|
-
};
|
|
88
|
-
for (const listener of this.listeners) {
|
|
89
|
-
try {
|
|
90
|
-
listener(commit);
|
|
91
|
-
}
|
|
92
|
-
catch (error) {
|
|
93
|
-
this.onError(error);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
finally {
|
|
99
|
-
release();
|
|
100
|
-
}
|
|
101
|
-
for (const callback of t.callbacks) {
|
|
102
|
-
try {
|
|
103
|
-
await callback();
|
|
104
|
-
}
|
|
105
|
-
catch (error) {
|
|
106
|
-
this.onError(error);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return result;
|
|
110
|
-
}
|
|
111
|
-
onCommit(listener) {
|
|
112
|
-
this.listeners.add(listener);
|
|
113
|
-
return () => this.listeners.delete(listener);
|
|
114
|
-
}
|
|
115
|
-
async health() {
|
|
116
|
-
return {
|
|
117
|
-
ok: !this.closed,
|
|
118
|
-
schemaVersion: MEMORY_SCHEMA_VERSION,
|
|
119
|
-
expectedSchemaVersion: MEMORY_SCHEMA_VERSION,
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
async close() {
|
|
123
|
-
this.closed = true;
|
|
124
|
-
await this.data.queue;
|
|
125
|
-
}
|
|
126
|
-
acquire() {
|
|
127
|
-
let release;
|
|
128
|
-
const next = new Promise((resolve) => (release = resolve));
|
|
129
|
-
const ready = this.data.queue.then(() => release);
|
|
130
|
-
this.data.queue = this.data.queue.then(() => next);
|
|
131
|
-
return ready;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
class MemoryTx {
|
|
135
|
-
s;
|
|
136
|
-
tenantId;
|
|
137
|
-
now;
|
|
138
|
-
closed = false;
|
|
139
|
-
events = [];
|
|
140
|
-
incarnations = [];
|
|
141
|
-
callbacks = [];
|
|
142
|
-
workAvailable = false;
|
|
143
|
-
constructor(s, tenantId, now) {
|
|
144
|
-
this.s = s;
|
|
145
|
-
this.tenantId = tenantId;
|
|
146
|
-
this.now = now;
|
|
147
|
-
}
|
|
148
|
-
check() {
|
|
149
|
-
if (this.closed)
|
|
150
|
-
throw new Error("Tx used after its transaction ended");
|
|
151
|
-
}
|
|
152
|
-
// --- documents -----------------------------------------------------------
|
|
153
|
-
async get(table, id) {
|
|
154
|
-
this.check();
|
|
155
|
-
const raw = this.s.docs[table].get(id);
|
|
156
|
-
if (raw === undefined)
|
|
157
|
-
return undefined;
|
|
158
|
-
return (table === "sessions" ? this.session(id) : JSON.parse(raw));
|
|
159
|
-
}
|
|
160
|
-
async put(table, id, body) {
|
|
161
|
-
this.check();
|
|
162
|
-
let value = body;
|
|
163
|
-
if (table === "sessions" && body && typeof body === "object") {
|
|
164
|
-
value = Object.fromEntries(Object.entries(body).filter(([key]) => !OWNERSHIP_KEYS.has(key)));
|
|
165
|
-
if (!this.s.sessionMeta.has(id))
|
|
166
|
-
this.s.sessionMeta.set(id, {
|
|
167
|
-
owner: null,
|
|
168
|
-
epoch: 0,
|
|
169
|
-
ownerExpiresAt: null,
|
|
170
|
-
nextSeq: 0,
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
const json = JSON.stringify(value);
|
|
174
|
-
if (json === undefined)
|
|
175
|
-
throw new Error("Document body must be JSON");
|
|
176
|
-
this.s.docs[table].set(id, json);
|
|
177
|
-
}
|
|
178
|
-
async delete(table, id) {
|
|
179
|
-
this.check();
|
|
180
|
-
this.s.docs[table].delete(id);
|
|
181
|
-
if (table === "sessions") {
|
|
182
|
-
this.s.sessionMeta.delete(id);
|
|
183
|
-
this.s.outbox.delete(id);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
session(id) {
|
|
187
|
-
const raw = this.s.docs.sessions.get(id);
|
|
188
|
-
const meta = this.s.sessionMeta.get(id);
|
|
189
|
-
if (raw === undefined || !meta)
|
|
190
|
-
return undefined;
|
|
191
|
-
return {
|
|
192
|
-
...JSON.parse(raw),
|
|
193
|
-
owner: meta.owner,
|
|
194
|
-
epoch: meta.epoch,
|
|
195
|
-
ownerExpiresAt: meta.ownerExpiresAt,
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
docs(table) {
|
|
199
|
-
return byId(this.s.docs[table]).map(([id, raw]) => [
|
|
200
|
-
id,
|
|
201
|
-
JSON.parse(raw),
|
|
202
|
-
]);
|
|
203
|
-
}
|
|
204
|
-
sessions() {
|
|
205
|
-
return byId(this.s.docs.sessions).map(([id]) => this.session(id));
|
|
206
|
-
}
|
|
207
|
-
// --- ordering ------------------------------------------------------------
|
|
208
|
-
async lockSession(id) {
|
|
209
|
-
this.check();
|
|
210
|
-
// Transactions are serialized, so the whole store is already locked.
|
|
211
|
-
return this.session(id);
|
|
212
|
-
}
|
|
213
|
-
async event(sessionId, turnId, type, payload) {
|
|
214
|
-
this.check();
|
|
215
|
-
const meta = this.s.sessionMeta.get(sessionId);
|
|
216
|
-
if (!meta)
|
|
217
|
-
throw new Error(`Session ${sessionId} not found`);
|
|
218
|
-
const seq = meta.nextSeq++;
|
|
219
|
-
const event = JSON.parse(JSON.stringify({
|
|
220
|
-
eventId: randomUUID(),
|
|
221
|
-
sessionId,
|
|
222
|
-
tenantId: this.tenantId,
|
|
223
|
-
turnId,
|
|
224
|
-
cursor: encodeCursor(sessionId, seq),
|
|
225
|
-
createdAt: this.now().toISOString(),
|
|
226
|
-
type,
|
|
227
|
-
payload,
|
|
228
|
-
}));
|
|
229
|
-
let rows = this.s.outbox.get(sessionId);
|
|
230
|
-
if (!rows)
|
|
231
|
-
this.s.outbox.set(sessionId, (rows = new Map()));
|
|
232
|
-
rows.set(seq, JSON.stringify(event));
|
|
233
|
-
this.events.push(event);
|
|
234
|
-
const doc = JSON.parse(this.s.docs.sessions.get(sessionId));
|
|
235
|
-
this.incarnations.push(doc.streamIncarnation ?? null);
|
|
236
|
-
return copy(event);
|
|
237
|
-
}
|
|
238
|
-
afterCommit(fn) {
|
|
239
|
-
this.check();
|
|
240
|
-
this.callbacks.push(fn);
|
|
241
|
-
}
|
|
242
|
-
signalWork() {
|
|
243
|
-
this.check();
|
|
244
|
-
this.workAvailable = true;
|
|
245
|
-
}
|
|
246
|
-
// --- ownership -----------------------------------------------------------
|
|
247
|
-
async takeOwnership(sessionId, claim) {
|
|
248
|
-
this.check();
|
|
249
|
-
const meta = this.s.sessionMeta.get(sessionId);
|
|
250
|
-
if (!meta)
|
|
251
|
-
return { status: "missing" };
|
|
252
|
-
if (meta.owner !== null &&
|
|
253
|
-
meta.ownerExpiresAt !== null &&
|
|
254
|
-
Date.parse(meta.ownerExpiresAt) > claim.now.getTime())
|
|
255
|
-
return {
|
|
256
|
-
status: "busy",
|
|
257
|
-
owner: meta.owner,
|
|
258
|
-
ownerExpiresAt: meta.ownerExpiresAt,
|
|
259
|
-
};
|
|
260
|
-
const previous = {
|
|
261
|
-
owner: meta.owner,
|
|
262
|
-
epoch: meta.epoch,
|
|
263
|
-
ownerExpiresAt: meta.ownerExpiresAt,
|
|
264
|
-
};
|
|
265
|
-
meta.epoch += 1;
|
|
266
|
-
meta.owner = claim.owner;
|
|
267
|
-
meta.ownerExpiresAt = new Date(claim.now.getTime() + claim.leaseMs).toISOString();
|
|
268
|
-
return {
|
|
269
|
-
status: "owned",
|
|
270
|
-
epoch: meta.epoch,
|
|
271
|
-
takeover: previous.owner !== null,
|
|
272
|
-
previous,
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
async renewOwnership(sessionId, owner, epoch, until) {
|
|
276
|
-
this.check();
|
|
277
|
-
const meta = this.s.sessionMeta.get(sessionId);
|
|
278
|
-
if (!meta || meta.owner !== owner || meta.epoch !== epoch)
|
|
279
|
-
return false;
|
|
280
|
-
meta.ownerExpiresAt = until.toISOString();
|
|
281
|
-
return true;
|
|
282
|
-
}
|
|
283
|
-
async releaseOwnership(sessionId, owner, epoch) {
|
|
284
|
-
this.check();
|
|
285
|
-
const meta = this.s.sessionMeta.get(sessionId);
|
|
286
|
-
if (!meta || meta.owner !== owner || meta.epoch !== epoch)
|
|
287
|
-
return false;
|
|
288
|
-
meta.owner = null;
|
|
289
|
-
meta.ownerExpiresAt = null;
|
|
290
|
-
return true;
|
|
291
|
-
}
|
|
292
|
-
async assertEpoch(sessionId, epoch) {
|
|
293
|
-
this.check();
|
|
294
|
-
const session = this.session(sessionId);
|
|
295
|
-
if (!session)
|
|
296
|
-
throw new OwnershipLostError(sessionId, epoch, undefined);
|
|
297
|
-
if (session.epoch !== epoch)
|
|
298
|
-
throw new OwnershipLostError(sessionId, epoch, session.epoch);
|
|
299
|
-
return session;
|
|
300
|
-
}
|
|
301
|
-
// --- typed queries -------------------------------------------------------
|
|
302
|
-
async sessionsWithStatus(statuses) {
|
|
303
|
-
this.check();
|
|
304
|
-
return this.sessions().filter((s) => statuses.includes(s.status));
|
|
305
|
-
}
|
|
306
|
-
async orphanedSessions(now, limit) {
|
|
307
|
-
this.check();
|
|
308
|
-
const lease = (s) => s.owner === null || s.ownerExpiresAt === null
|
|
309
|
-
? -Infinity
|
|
310
|
-
: Date.parse(s.ownerExpiresAt);
|
|
311
|
-
return this.sessions()
|
|
312
|
-
.filter((s) => OPEN_SESSION.has(s.status) && lease(s) <= now.getTime())
|
|
313
|
-
.sort((a, b) => lease(a) - lease(b) || (a.id < b.id ? -1 : 1))
|
|
314
|
-
.slice(0, limit);
|
|
315
|
-
}
|
|
316
|
-
async listSessions(filter = {}) {
|
|
317
|
-
this.check();
|
|
318
|
-
return this.sessions().filter((s) => (filter.agentId === undefined || s.agentId === filter.agentId) &&
|
|
319
|
-
(filter.ownerUserId === undefined ||
|
|
320
|
-
s.ownerUserId === filter.ownerUserId));
|
|
321
|
-
}
|
|
322
|
-
async listDefinitions() {
|
|
323
|
-
this.check();
|
|
324
|
-
return this.docs("definitions").map(([, doc]) => doc);
|
|
325
|
-
}
|
|
326
|
-
async listSandboxes() {
|
|
327
|
-
this.check();
|
|
328
|
-
return this.docs("sandboxes").map(([, doc]) => doc);
|
|
329
|
-
}
|
|
330
|
-
actions() {
|
|
331
|
-
return this.docs("actions").map(([, doc]) => doc);
|
|
332
|
-
}
|
|
333
|
-
async expiredClaims(now, limit) {
|
|
334
|
-
this.check();
|
|
335
|
-
return this.actions()
|
|
336
|
-
.filter((a) => a.status === "claimed" &&
|
|
337
|
-
a.leaseExpiresAt !== null &&
|
|
338
|
-
Date.parse(a.leaseExpiresAt) <= now.getTime())
|
|
339
|
-
.sort((a, b) => Date.parse(a.leaseExpiresAt) - Date.parse(b.leaseExpiresAt) ||
|
|
340
|
-
(a.actionId < b.actionId ? -1 : 1))
|
|
341
|
-
.slice(0, limit);
|
|
342
|
-
}
|
|
343
|
-
async pendingActions(agentId) {
|
|
344
|
-
this.check();
|
|
345
|
-
return this.actions().filter((a) => a.status === "pending" && a.agentId === agentId);
|
|
346
|
-
}
|
|
347
|
-
async actionsForSession(sessionId, filter = {}) {
|
|
348
|
-
this.check();
|
|
349
|
-
return this.actions().filter((a) => a.sessionId === sessionId &&
|
|
350
|
-
(filter.turnId === undefined || a.turnId === filter.turnId) &&
|
|
351
|
-
(filter.statuses === undefined || filter.statuses.includes(a.status)));
|
|
352
|
-
}
|
|
353
|
-
async actionsWithStatus(statuses, filter = {}) {
|
|
354
|
-
this.check();
|
|
355
|
-
return this.actions().filter((a) => statuses.includes(a.status) &&
|
|
356
|
-
(filter.kinds === undefined || filter.kinds.includes(a.kind)));
|
|
357
|
-
}
|
|
358
|
-
effects() {
|
|
359
|
-
return this.docs("effects").map(([, doc]) => doc);
|
|
360
|
-
}
|
|
361
|
-
async invokingEffects(sessionId) {
|
|
362
|
-
return this.effectsForSession(sessionId, { statuses: ["invoking"] });
|
|
363
|
-
}
|
|
364
|
-
async effectsForSession(sessionId, filter = {}) {
|
|
365
|
-
this.check();
|
|
366
|
-
return this.effects().filter((e) => e.request?.sessionId === sessionId &&
|
|
367
|
-
(filter.turnId === undefined || e.request.turnId === filter.turnId) &&
|
|
368
|
-
(filter.statuses === undefined || filter.statuses.includes(e.status)));
|
|
369
|
-
}
|
|
370
|
-
async effectsForTurn(sessionId, turnId, statuses) {
|
|
371
|
-
return this.effectsForSession(sessionId, { turnId, statuses });
|
|
372
|
-
}
|
|
373
|
-
async effectsWithStatus(statuses, filter = {}) {
|
|
374
|
-
this.check();
|
|
375
|
-
return this.effects().filter((e) => statuses.includes(e.status) &&
|
|
376
|
-
(filter.kinds === undefined || filter.kinds.includes(e.request?.kind)));
|
|
377
|
-
}
|
|
378
|
-
async linkedSessions(workflowSessionId) {
|
|
379
|
-
this.check();
|
|
380
|
-
const out = [];
|
|
381
|
-
for (const [agentSessionId, link] of this.docs("links")) {
|
|
382
|
-
if (link.workflowSessionId !== workflowSessionId)
|
|
383
|
-
continue;
|
|
384
|
-
const session = this.session(agentSessionId);
|
|
385
|
-
if (session)
|
|
386
|
-
out.push({ agentSessionId, link, session });
|
|
387
|
-
}
|
|
388
|
-
return out;
|
|
389
|
-
}
|
|
390
|
-
async counts() {
|
|
391
|
-
this.check();
|
|
392
|
-
const sessions = this.sessions();
|
|
393
|
-
return {
|
|
394
|
-
sessions: sessions.length,
|
|
395
|
-
runningSessions: sessions.filter((s) => OPEN_SESSION.has(s.status))
|
|
396
|
-
.length,
|
|
397
|
-
pendingActions: this.actions().filter((a) => a.status === "pending" || a.status === "claimed").length,
|
|
398
|
-
uncertainEffects: this.effects().filter((e) => e.status === "uncertain")
|
|
399
|
-
.length,
|
|
400
|
-
sandboxes: this.s.docs.sandboxes.size,
|
|
401
|
-
definitions: this.s.docs.definitions.size,
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
// --- outbox --------------------------------------------------------------
|
|
405
|
-
async outbox(limit, filter = {}) {
|
|
406
|
-
this.check();
|
|
407
|
-
const rows = [];
|
|
408
|
-
for (const [sessionId, bySeq] of byId(this.s.outbox)) {
|
|
409
|
-
if (filter.sessionId !== undefined && filter.sessionId !== sessionId)
|
|
410
|
-
continue;
|
|
411
|
-
for (const seq of [...bySeq.keys()].sort((a, b) => a - b)) {
|
|
412
|
-
if (rows.length >= limit)
|
|
413
|
-
return rows;
|
|
414
|
-
rows.push({ sessionId, seq, event: JSON.parse(bySeq.get(seq)) });
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
return rows;
|
|
418
|
-
}
|
|
419
|
-
async deleteOutbox(sessionId, throughSeq, incarnation) {
|
|
420
|
-
this.check();
|
|
421
|
-
const rows = this.s.outbox.get(sessionId);
|
|
422
|
-
if (!rows)
|
|
423
|
-
return 0;
|
|
424
|
-
if (incarnation !== undefined) {
|
|
425
|
-
const doc = this.s.docs.sessions.get(sessionId);
|
|
426
|
-
if (doc === undefined ||
|
|
427
|
-
(JSON.parse(doc).streamIncarnation ?? null) !== incarnation)
|
|
428
|
-
return 0;
|
|
429
|
-
}
|
|
430
|
-
let n = 0;
|
|
431
|
-
for (const seq of [...rows.keys()])
|
|
432
|
-
if (seq <= throughSeq) {
|
|
433
|
-
rows.delete(seq);
|
|
434
|
-
n += 1;
|
|
435
|
-
}
|
|
436
|
-
if (rows.size === 0)
|
|
437
|
-
this.s.outbox.delete(sessionId);
|
|
438
|
-
return n;
|
|
439
|
-
}
|
|
440
|
-
async outboxStats() {
|
|
441
|
-
this.check();
|
|
442
|
-
let depth = 0;
|
|
443
|
-
let oldestCreatedAt = null;
|
|
444
|
-
for (const rows of this.s.outbox.values())
|
|
445
|
-
for (const body of rows.values()) {
|
|
446
|
-
depth += 1;
|
|
447
|
-
const createdAt = JSON.parse(body).createdAt;
|
|
448
|
-
if (oldestCreatedAt === null || createdAt < oldestCreatedAt)
|
|
449
|
-
oldestCreatedAt = createdAt;
|
|
450
|
-
}
|
|
451
|
-
return { depth, oldestCreatedAt };
|
|
452
|
-
}
|
|
453
|
-
// --- executors -----------------------------------------------------------
|
|
454
|
-
async listExecutors() {
|
|
455
|
-
this.check();
|
|
456
|
-
return byId(this.s.executors).map(([, row]) => copy(row));
|
|
457
|
-
}
|
|
458
|
-
async getExecutor(agentId) {
|
|
459
|
-
this.check();
|
|
460
|
-
const row = this.s.executors.get(agentId);
|
|
461
|
-
return row && copy(row);
|
|
462
|
-
}
|
|
463
|
-
async putExecutor(row) {
|
|
464
|
-
this.check();
|
|
465
|
-
for (const other of this.s.executors.values())
|
|
466
|
-
if (other.tokenHash === row.tokenHash && other.agentId !== row.agentId)
|
|
467
|
-
throw new Error("executors.token_hash must be unique");
|
|
468
|
-
const existing = this.s.executors.get(row.agentId);
|
|
469
|
-
this.s.executors.set(row.agentId, {
|
|
470
|
-
...copy(row),
|
|
471
|
-
createdAt: existing?.createdAt ?? row.updatedAt,
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
async deleteExecutor(agentId) {
|
|
475
|
-
this.check();
|
|
476
|
-
this.s.executors.delete(agentId);
|
|
477
|
-
}
|
|
478
|
-
// --- principals ----------------------------------------------------------
|
|
479
|
-
async insertPrincipal(row) {
|
|
480
|
-
this.check();
|
|
481
|
-
if (this.s.principals.has(row.id))
|
|
482
|
-
throw new Error("principals.id must be unique");
|
|
483
|
-
for (const other of this.s.principals.values())
|
|
484
|
-
if (other.tokenHash === row.tokenHash)
|
|
485
|
-
throw new Error("principals.token_hash must be unique");
|
|
486
|
-
this.s.principals.set(row.id, copy(row));
|
|
487
|
-
}
|
|
488
|
-
async principalByTokenHash(tokenHash) {
|
|
489
|
-
this.check();
|
|
490
|
-
for (const row of this.s.principals.values())
|
|
491
|
-
if (row.tokenHash === tokenHash)
|
|
492
|
-
return copy(row);
|
|
493
|
-
return undefined;
|
|
494
|
-
}
|
|
495
|
-
async principalById(id) {
|
|
496
|
-
this.check();
|
|
497
|
-
const row = this.s.principals.get(id);
|
|
498
|
-
return row && copy(row);
|
|
499
|
-
}
|
|
500
|
-
async applicationTokenHashes() {
|
|
501
|
-
this.check();
|
|
502
|
-
return byId(this.s.principals)
|
|
503
|
-
.filter(([, row]) => row.role === "application")
|
|
504
|
-
.map(([, row]) => row.tokenHash);
|
|
505
|
-
}
|
|
506
|
-
// --- vault ---------------------------------------------------------------
|
|
507
|
-
async insertVault(row) {
|
|
508
|
-
this.check();
|
|
509
|
-
if (this.s.vaults.has(row.id))
|
|
510
|
-
throw new Error("vaults.id must be unique");
|
|
511
|
-
if (row.scope === "host" &&
|
|
512
|
-
[...this.s.vaults.values()].some((v) => v.scope === "host"))
|
|
513
|
-
throw new Error("Only one host vault is allowed");
|
|
514
|
-
this.s.vaults.set(row.id, copy(row));
|
|
515
|
-
}
|
|
516
|
-
async getVault(id) {
|
|
517
|
-
this.check();
|
|
518
|
-
const row = this.s.vaults.get(id);
|
|
519
|
-
return row && copy(row);
|
|
520
|
-
}
|
|
521
|
-
async vaultsByOwner(ownerUserId) {
|
|
522
|
-
this.check();
|
|
523
|
-
return [...this.s.vaults.values()]
|
|
524
|
-
.filter((v) => v.ownerUserId === ownerUserId && v.scope === "user")
|
|
525
|
-
.sort(byCreated)
|
|
526
|
-
.map(copy);
|
|
527
|
-
}
|
|
528
|
-
async updateVaultMetadata(id, metadataJson) {
|
|
529
|
-
this.check();
|
|
530
|
-
const row = this.s.vaults.get(id);
|
|
531
|
-
if (row)
|
|
532
|
-
row.metadataJson = metadataJson;
|
|
533
|
-
}
|
|
534
|
-
async deleteVault(id) {
|
|
535
|
-
this.check();
|
|
536
|
-
for (const [credentialId, row] of this.s.credentials)
|
|
537
|
-
if (row.vaultId === id)
|
|
538
|
-
this.s.credentials.delete(credentialId);
|
|
539
|
-
this.s.vaults.delete(id);
|
|
540
|
-
}
|
|
541
|
-
async insertCredential(row) {
|
|
542
|
-
this.check();
|
|
543
|
-
if (this.s.credentials.has(row.id))
|
|
544
|
-
throw new Error("vault_credentials.id must be unique");
|
|
545
|
-
if (!this.s.vaults.has(row.vaultId))
|
|
546
|
-
throw new Error("vault_credentials.vault_id references a missing vault");
|
|
547
|
-
this.s.credentials.set(row.id, copy(row));
|
|
548
|
-
}
|
|
549
|
-
async getCredential(id) {
|
|
550
|
-
this.check();
|
|
551
|
-
const row = this.s.credentials.get(id);
|
|
552
|
-
return row && copy(row);
|
|
553
|
-
}
|
|
554
|
-
async credentialsForVault(vaultId, filter = {}) {
|
|
555
|
-
this.check();
|
|
556
|
-
return [...this.s.credentials.values()]
|
|
557
|
-
.filter((c) => c.vaultId === vaultId &&
|
|
558
|
-
(filter.type === undefined || c.type === filter.type))
|
|
559
|
-
.sort(byCreated)
|
|
560
|
-
.map(copy);
|
|
561
|
-
}
|
|
562
|
-
async updateCredential(vaultId, id, patch) {
|
|
563
|
-
this.check();
|
|
564
|
-
const row = this.s.credentials.get(id);
|
|
565
|
-
if (!row || row.vaultId !== vaultId)
|
|
566
|
-
return false;
|
|
567
|
-
const defined = Object.fromEntries(Object.entries(copy(patch)).filter(([, value]) => value !== undefined));
|
|
568
|
-
this.s.credentials.set(id, { ...row, ...defined });
|
|
569
|
-
return true;
|
|
570
|
-
}
|
|
571
|
-
async deleteCredential(vaultId, id) {
|
|
572
|
-
this.check();
|
|
573
|
-
const row = this.s.credentials.get(id);
|
|
574
|
-
if (!row || row.vaultId !== vaultId)
|
|
575
|
-
return false;
|
|
576
|
-
this.s.credentials.delete(id);
|
|
577
|
-
return true;
|
|
578
|
-
}
|
|
579
|
-
async countCredentials() {
|
|
580
|
-
this.check();
|
|
581
|
-
return this.s.credentials.size;
|
|
582
|
-
}
|
|
583
|
-
async insertVaultAudit(row) {
|
|
584
|
-
this.check();
|
|
585
|
-
this.s.audit.push(copy(row));
|
|
586
|
-
}
|
|
587
|
-
async vaultAudit(filter = {}) {
|
|
588
|
-
this.check();
|
|
589
|
-
return this.s.audit
|
|
590
|
-
.filter((r) => filter.vaultId === undefined || r.vaultId === filter.vaultId)
|
|
591
|
-
.slice(0, filter.limit ?? Infinity)
|
|
592
|
-
.map(copy);
|
|
593
|
-
}
|
|
594
|
-
async getVaultIdempotency(id) {
|
|
595
|
-
this.check();
|
|
596
|
-
const row = this.s.idempotency.get(id);
|
|
597
|
-
return row && copy(row);
|
|
598
|
-
}
|
|
599
|
-
async insertVaultIdempotency(row) {
|
|
600
|
-
this.check();
|
|
601
|
-
if (this.s.idempotency.has(row.id))
|
|
602
|
-
throw new Error("vault_idempotency.id must be unique");
|
|
603
|
-
this.s.idempotency.set(row.id, copy(row));
|
|
604
|
-
}
|
|
605
|
-
// --- settings ------------------------------------------------------------
|
|
606
|
-
async getSetting(key) {
|
|
607
|
-
this.check();
|
|
608
|
-
return this.s.settings.get(key);
|
|
609
|
-
}
|
|
610
|
-
async putSetting(key, value) {
|
|
611
|
-
this.check();
|
|
612
|
-
this.s.settings.set(key, value);
|
|
613
|
-
}
|
|
614
|
-
// --- reset ---------------------------------------------------------------
|
|
615
|
-
async reset(scope) {
|
|
616
|
-
this.check();
|
|
617
|
-
if (scope === "sessions" || scope === "all") {
|
|
618
|
-
for (const table of [
|
|
619
|
-
"sessions",
|
|
620
|
-
"commands",
|
|
621
|
-
"checkpoints",
|
|
622
|
-
"effects",
|
|
623
|
-
"actions",
|
|
624
|
-
"links",
|
|
625
|
-
])
|
|
626
|
-
this.s.docs[table].clear();
|
|
627
|
-
this.s.sessionMeta.clear();
|
|
628
|
-
this.s.outbox.clear();
|
|
629
|
-
}
|
|
630
|
-
if (scope === "sandboxes" || scope === "all")
|
|
631
|
-
this.s.docs.sandboxes.clear();
|
|
632
|
-
if (scope === "all") {
|
|
633
|
-
this.s.docs.definitions.clear();
|
|
634
|
-
this.s.executors.clear();
|
|
635
|
-
for (const vault of [...this.s.vaults.values()])
|
|
636
|
-
if (vault.scope !== "host")
|
|
637
|
-
await this.deleteVault(vault.id);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
function byCreated(a, b) {
|
|
642
|
-
if (a.createdAt !== b.createdAt)
|
|
643
|
-
return a.createdAt < b.createdAt ? -1 : 1;
|
|
644
|
-
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
645
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { Migration } from "./index.js";
|
|
2
|
-
/**
|
|
3
|
-
* The first Postgres Tenant schema.
|
|
4
|
-
*
|
|
5
|
-
* - `tenant` holds the Tenant envelope (one row).
|
|
6
|
-
* - Document tables keep `id text primary key, body json`. The fields typed
|
|
7
|
-
* queries filter on are stored generated columns with indexes. Ids and
|
|
8
|
-
* timestamps compared as text use `COLLATE "C"`, so ordering is by code
|
|
9
|
-
* point, like the in-memory fake, whatever the database collation.
|
|
10
|
-
* - Bodies are `json`, not `jsonb`, so every string round-trips exactly as
|
|
11
|
-
* `JSON.stringify` wrote it. `jsonb` rejects the escapes `\u0000` (`22P05`)
|
|
12
|
-
* and unpaired surrogates (`\ud800`), which tool output can contain and
|
|
13
|
-
* which the in-memory store accepts. `json` stores the text
|
|
14
|
-
* verbatim and checks only its syntax. The generated columns read the body
|
|
15
|
-
* through `doc(body)`, which casts to `jsonb` after replacing those two
|
|
16
|
-
* escapes with `\ufffd`: the stored body is untouched, and only an indexed
|
|
17
|
-
* field that itself contained one (never an id, status or timestamp) would
|
|
18
|
-
* see U+FFFD. Bodies with no `\u` escape at all take the plain cast. Queries
|
|
19
|
-
* never apply `->`/`->>` to a `json` body (Postgres de-escapes the whole text
|
|
20
|
-
* and fails on the same escapes); they read generated columns.
|
|
21
|
-
* - `sessions` carries the store-managed `next_event_seq` and ownership
|
|
22
|
-
* columns (`owner`, `epoch`, `owner_expires_at`), which are never in `body`.
|
|
23
|
-
* - `outbox(session_id, seq, body)` holds committed, unrelayed events.
|
|
24
|
-
* - Executors, principals, vault and settings keep typed columns. Vault
|
|
25
|
-
* ciphertext is `bytea` columns, never inside a JSON body.
|
|
26
|
-
*/
|
|
27
|
-
export declare const initial: Migration;
|