@nylorun/runtime 0.23.0-beta → 0.25.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 +252 -0
- package/README.md +87 -28
- package/dist/adapters/execution/restate.js +1 -1
- package/dist/adapters/replication/pgoutput.d.ts +2 -0
- package/dist/adapters/replication/pgoutput.js +6 -3
- package/dist/adapters/sandbox/local.d.ts +9 -1
- package/dist/adapters/sandbox/local.js +16 -4
- package/dist/adapters/sandbox/virtual.js +4 -1
- package/dist/api/a2a/card.d.ts +11 -1
- package/dist/api/a2a/card.js +26 -2
- package/dist/api/a2a/endpoint.js +9 -3
- package/dist/api/a2a/protocol.d.ts +25 -2
- package/dist/api/a2a/protocol.js +20 -3
- package/dist/api/a2a/routes.d.ts +6 -1
- package/dist/api/a2a/routes.js +67 -9
- package/dist/api/a2a/tasks.js +2 -1
- package/dist/api/ag-ui/endpoint.js +8 -3
- package/dist/api/ag-ui/history.d.ts +6 -1
- package/dist/api/ag-ui/history.js +39 -3
- package/dist/api/ag-ui/routes.d.ts +4 -1
- package/dist/api/ag-ui/routes.js +63 -20
- package/dist/api/ag-ui/translate.js +3 -2
- package/dist/api/components.d.ts +5327 -1091
- package/dist/api/components.js +40 -16
- package/dist/api/gate/keys.d.ts +2 -1
- package/dist/api/gate/keys.js +14 -1
- package/dist/api/gate/routes.d.ts +6 -0
- package/dist/api/gate/routes.js +52 -3
- package/dist/api/http/app.js +17 -6
- package/dist/api/http/body.d.ts +3 -3
- package/dist/api/http/body.js +7 -7
- package/dist/api/http/define.d.ts +6 -0
- package/dist/api/http/define.js +13 -1
- package/dist/api/http/respond.js +1 -1
- package/dist/api/http/routes/artifacts.js +35 -8
- package/dist/api/http/routes/coverage.d.ts +9 -0
- package/dist/api/http/routes/coverage.js +34 -0
- package/dist/api/http/routes/environment-manifests.d.ts +9 -0
- package/dist/api/http/routes/environment-manifests.js +118 -0
- package/dist/api/http/routes/environments.d.ts +11 -0
- package/dist/api/http/routes/environments.js +332 -0
- package/dist/api/http/routes/mcp.d.ts +1 -1
- package/dist/api/http/routes/mcp.js +2 -2
- package/dist/api/http/routes/me.js +1 -1
- package/dist/api/http/routes/reads.d.ts +94 -9
- package/dist/api/http/routes/reads.js +54 -5
- package/dist/api/http/routes/sessions.js +24 -9
- package/dist/api/http/routes/tenant.js +65 -15
- package/dist/api/inbound-files.d.ts +65 -0
- package/dist/api/inbound-files.js +115 -0
- package/dist/api/openapi.js +48 -28
- package/dist/artifacts/disk.d.ts +59 -0
- package/dist/artifacts/disk.js +569 -0
- package/dist/artifacts/export.d.ts +1 -1
- package/dist/artifacts/export.js +2 -3
- package/dist/artifacts/folders.d.ts +6 -3
- package/dist/artifacts/folders.js +17 -12
- package/dist/artifacts/media-types.d.ts +15 -0
- package/dist/artifacts/media-types.js +56 -4
- package/dist/artifacts/parts.d.ts +12 -3
- package/dist/artifacts/parts.js +15 -4
- package/dist/artifacts/service.d.ts +2 -1
- package/dist/artifacts/service.js +6 -1
- package/dist/artifacts/workspace.d.ts +5 -5
- package/dist/artifacts/workspace.js +7 -19
- package/dist/core/flow-host.d.ts +3 -4
- package/dist/core/flow-host.js +5 -2
- package/dist/core/provider.d.ts +3 -2
- package/dist/core/provider.js +5 -37
- package/dist/core/sandbox-routes.d.ts +2 -21
- package/dist/core/sandbox-routes.js +11 -44
- package/dist/core/turn-manifest.d.ts +3 -2
- package/dist/core/turn-manifest.js +29 -5
- package/dist/execution/types.d.ts +1 -1
- package/dist/gates/contract.d.ts +3 -24
- package/dist/gates/contract.js +1 -36
- package/dist/gates/egress-credentials.d.ts +9 -0
- package/dist/gates/egress-credentials.js +11 -4
- package/dist/gates/egress.d.ts +22 -1
- package/dist/gates/egress.js +116 -10
- package/dist/gates/fixture-model.d.ts +28 -0
- package/dist/gates/fixture-model.js +92 -0
- package/dist/gates/handler.js +4 -4
- package/dist/gates/http-tool.d.ts +9 -6
- package/dist/gates/http-tool.js +11 -17
- package/dist/gates/in-process.d.ts +5 -0
- package/dist/gates/in-process.js +12 -1
- package/dist/gates/journal.d.ts +30 -0
- package/dist/gates/journal.js +51 -0
- package/dist/gates/mcp-handler.d.ts +4 -0
- package/dist/gates/mcp-handler.js +7 -4
- package/dist/gates/meter.d.ts +10 -2
- package/dist/gates/meter.js +20 -5
- package/dist/gates/policy.d.ts +49 -0
- package/dist/gates/policy.js +132 -0
- package/dist/gates/tenant-vaults.d.ts +7 -7
- package/dist/gates/tenant-vaults.js +5 -5
- package/dist/gates/tool-calls.d.ts +10 -5
- package/dist/gates/tool-calls.js +28 -10
- package/dist/gates/tool-client.d.ts +8 -0
- package/dist/gates/tool-client.js +27 -11
- package/dist/gates/tool-contract.d.ts +11 -69
- package/dist/gates/tool-contract.js +1 -85
- package/dist/gates/tool-gate.d.ts +1 -1
- package/dist/harness/calls.d.ts +14 -7
- package/dist/harness/calls.js +30 -24
- package/dist/harness/executors.js +12 -9
- package/dist/harness/main.js +24 -5
- package/dist/harness/pod.d.ts +39 -0
- package/dist/harness/pod.js +46 -0
- package/dist/harness/service.d.ts +0 -1
- package/dist/harness/service.js +17 -9
- package/dist/harness/setup.d.ts +29 -0
- package/dist/harness/setup.js +174 -0
- package/dist/harness/ws-client.js +3 -2
- package/dist/harness/ws-port.d.ts +1 -5
- package/dist/harness/ws-port.js +1 -5
- package/dist/harness-api/in-process.js +3 -3
- package/dist/harness-api/record.d.ts +15 -1
- package/dist/harness-api/record.js +180 -50
- package/dist/harness-api/redact.d.ts +3 -0
- package/dist/harness-api/redact.js +45 -0
- package/dist/harness-api/server.d.ts +35 -4
- package/dist/harness-api/server.js +130 -17
- package/dist/harness-api/start.d.ts +10 -3
- package/dist/harness-api/start.js +40 -10
- package/dist/harness-api/tool-journal.d.ts +105 -0
- package/dist/harness-api/tool-journal.js +132 -0
- package/dist/harness-api/tool-status.d.ts +13 -0
- package/dist/harness-api/tool-status.js +26 -0
- package/dist/harness-api/workspace.d.ts +12 -7
- package/dist/harness-api/workspace.js +47 -25
- package/dist/harness-api/ws-server.d.ts +11 -3
- package/dist/harness-api/ws-server.js +94 -15
- package/dist/host/gates.d.ts +2 -1
- package/dist/host/gates.js +10 -2
- package/dist/host/main.js +54 -5
- package/dist/host/operate.js +67 -5
- package/dist/host/stack-config.d.ts +64 -0
- package/dist/host/stack-config.js +62 -2
- package/dist/keys/client.js +4 -1
- package/dist/keys/keys.d.ts +13 -6
- package/dist/keys/keys.js +9 -8
- package/dist/management-openapi.json +1264 -2171
- package/dist/mcp/connect.d.ts +26 -22
- package/dist/mcp/connect.js +30 -34
- package/dist/mcp/pool.d.ts +3 -6
- package/dist/mcp/pool.js +14 -28
- package/dist/mcp/preview.d.ts +3 -3
- package/dist/mcp/preview.js +10 -21
- package/dist/mcp/snapshot.d.ts +16 -24
- package/dist/mcp/snapshot.js +33 -45
- package/dist/model/capabilities.d.ts +26 -0
- package/dist/model/capabilities.js +44 -0
- package/dist/model/catalog.d.ts +34 -3
- package/dist/model/catalog.js +38 -2
- package/dist/model/models.d.ts +2 -0
- package/dist/model/models.js +1 -1
- package/dist/model/native-blocks.d.ts +35 -0
- package/dist/model/native-blocks.js +170 -0
- package/dist/model/pi-model.js +114 -94
- package/dist/openapi.json +12822 -3943
- package/dist/reads/types.d.ts +16 -3
- package/dist/record/append.d.ts +3 -1
- package/dist/record/append.js +1 -0
- package/dist/record/envelope.d.ts +5 -1
- package/dist/record/envelope.js +7 -3
- package/dist/record/environment.d.ts +25 -0
- package/dist/record/environment.js +44 -0
- package/dist/record/index.d.ts +1 -1
- package/dist/record/index.js +1 -1
- package/dist/sandbox/disk-fs.d.ts +95 -0
- package/dist/sandbox/disk-fs.js +206 -0
- package/dist/sandbox/join.d.ts +17 -18
- package/dist/sandbox/join.js +46 -15
- package/dist/sandbox/manager.d.ts +47 -21
- package/dist/sandbox/manager.js +162 -107
- package/dist/sandbox/placement.d.ts +14 -13
- package/dist/sandbox/placement.js +31 -14
- package/dist/sandbox/pods/client.d.ts +9 -2
- package/dist/sandbox/pods/lifecycle.d.ts +36 -27
- package/dist/sandbox/pods/lifecycle.js +29 -26
- package/dist/sandbox/pods/reconcile.js +18 -12
- package/dist/sandbox/pods/spec.d.ts +15 -13
- package/dist/sandbox/pods/spec.js +17 -20
- package/dist/sandbox/records.d.ts +2 -2
- package/dist/sandbox/records.js +3 -3
- package/dist/sandbox/resolve.d.ts +37 -27
- package/dist/sandbox/resolve.js +73 -41
- package/dist/sandbox/runtime-tools.d.ts +9 -0
- package/dist/sandbox/runtime-tools.js +16 -0
- package/dist/sandbox/session-sandbox.d.ts +4 -6
- package/dist/sandbox/session-sandbox.js +47 -94
- package/dist/sandbox/setup.d.ts +64 -0
- package/dist/sandbox/setup.js +160 -0
- package/dist/sandbox/share.d.ts +21 -26
- package/dist/sandbox/share.js +36 -63
- package/dist/sandbox/skills.d.ts +8 -6
- package/dist/sandbox/skills.js +24 -23
- package/dist/sandbox/tenant-config.d.ts +12 -14
- package/dist/sandbox/tenant-config.js +12 -17
- package/dist/sandbox/types.d.ts +6 -0
- package/dist/store/postgres/drizzle/0020_environments.sql +63 -0
- package/dist/store/postgres/drizzle/0021_disk_versions.sql +7 -0
- package/dist/store/postgres/drizzle/0022_model_usage_timing.sql +5 -0
- package/dist/store/postgres/drizzle/0023_artifact_pages.sql +1 -0
- package/dist/store/postgres/drizzle/0024_flat_manifest.sql +7 -0
- package/dist/store/postgres/drizzle/0025_environment_manifests.sql +14 -0
- package/dist/store/postgres/drizzle/0026_environment_forks.sql +1 -0
- package/dist/store/postgres/drizzle/0027_environment_image_digest.sql +1 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +56 -0
- package/dist/store/postgres/reads.js +123 -17
- package/dist/store/postgres/record-writer.d.ts +4 -4
- package/dist/store/postgres/record-writer.js +9 -9
- package/dist/store/postgres/record.d.ts +7 -0
- package/dist/store/postgres/record.js +23 -2
- package/dist/store/postgres/schema.d.ts +1126 -736
- package/dist/store/postgres/schema.js +136 -73
- package/dist/store/postgres/store.js +195 -67
- package/dist/store/types.d.ts +165 -50
- package/dist/tenant/advance.d.ts +7 -6
- package/dist/tenant/advance.js +118 -42
- package/dist/tenant/artifact-tool.d.ts +1 -1
- package/dist/tenant/artifact-tool.js +46 -26
- package/dist/tenant/commands.d.ts +15 -2
- package/dist/tenant/commands.js +115 -14
- package/dist/tenant/context.d.ts +56 -24
- package/dist/tenant/context.js +4 -15
- package/dist/tenant/effects.d.ts +1 -1
- package/dist/tenant/effects.js +44 -29
- package/dist/tenant/environment-manifests.d.ts +57 -0
- package/dist/tenant/environment-manifests.js +200 -0
- package/dist/tenant/environments.d.ts +174 -0
- package/dist/tenant/environments.js +1044 -0
- package/dist/tenant/harness-tokens.d.ts +21 -0
- package/dist/tenant/harness-tokens.js +61 -0
- package/dist/tenant/host-token.d.ts +1 -1
- package/dist/tenant/host-token.js +2 -4
- package/dist/tenant/identity-file.d.ts +4 -4
- package/dist/tenant/identity-file.js +17 -8
- package/dist/tenant/issuers.js +3 -3
- package/dist/tenant/model-setting.d.ts +14 -0
- package/dist/tenant/model-setting.js +51 -0
- package/dist/tenant/principals.js +1 -1
- package/dist/tenant/reset.js +3 -3
- package/dist/tenant/runtime.d.ts +6 -1
- package/dist/tenant/runtime.js +7 -1
- package/dist/tenant/session.d.ts +3 -3
- package/dist/tenant/session.js +0 -14
- package/dist/tenant/sessions.d.ts +18 -14
- package/dist/tenant/sessions.js +99 -143
- package/dist/tenant/signing-keys.d.ts +5 -1
- package/dist/tenant/skill-tool.d.ts +3 -3
- package/dist/tenant/skill-tool.js +6 -11
- package/dist/tenant/status.js +3 -3
- package/dist/tenant/sweep.js +13 -7
- package/dist/tenant/tool-results.js +1 -1
- package/dist/tenant/tool-search.d.ts +7 -11
- package/dist/tenant/tool-search.js +8 -5
- package/dist/tenant/transcript.d.ts +245 -36
- package/dist/tenant/transcript.js +64 -12
- package/dist/tenant/turn-timing.d.ts +43 -0
- package/dist/tenant/turn-timing.js +39 -0
- package/dist/tenant/types.d.ts +2 -0
- package/dist/traces/ids.d.ts +41 -0
- package/dist/traces/ids.js +81 -0
- package/dist/traces/key.d.ts +6 -0
- package/dist/traces/key.js +37 -0
- package/dist/traces/map.d.ts +113 -0
- package/dist/traces/map.js +289 -0
- package/dist/traces/options.d.ts +7 -0
- package/dist/traces/options.js +1 -0
- package/dist/traces/otlp.d.ts +42 -0
- package/dist/traces/otlp.js +84 -0
- package/dist/traces/projector.d.ts +58 -0
- package/dist/traces/projector.js +200 -0
- package/dist/traces/read.d.ts +23 -0
- package/dist/traces/read.js +16 -0
- package/dist/vault/coverage.d.ts +26 -0
- package/dist/vault/coverage.js +62 -0
- package/dist/vault/error.d.ts +11 -1
- package/dist/vault/error.js +5 -1
- package/dist/vault/host-model.d.ts +4 -1
- package/dist/vault/host-model.js +10 -2
- package/dist/vault/service.d.ts +92 -48
- package/dist/vault/service.js +462 -376
- package/dist/vault/sources.d.ts +5 -16
- package/dist/vault/sources.js +6 -8
- package/dist/version.d.ts +1 -1
- package/dist/version.js +2 -2
- package/package.json +13 -13
- package/dist/api/http/routes/sandboxes.d.ts +0 -9
- package/dist/api/http/routes/sandboxes.js +0 -153
- package/dist/api/http/routes/vaults.d.ts +0 -10
- package/dist/api/http/routes/vaults.js +0 -139
- package/dist/record/sandbox.d.ts +0 -25
- package/dist/record/sandbox.js +0 -43
- package/dist/sandbox/capability.d.ts +0 -3
- package/dist/sandbox/capability.js +0 -10
- package/dist/tenant/sandboxes.d.ts +0 -123
- package/dist/tenant/sandboxes.js +0 -566
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
/** Drizzle read projections on a separate, read-only Tenant pool. */
|
|
3
|
-
import { and, asc, desc, eq, gt, inArray, isNull, lt, ne, or, sql, } from "drizzle-orm";
|
|
3
|
+
import { and, asc, desc, eq, exists, gt, inArray, isNull, lt, ne, or, sql, } from "drizzle-orm";
|
|
4
|
+
import { isArtifactId } from "@nylorun/core/compatibility";
|
|
4
5
|
import { readCursor } from "../../reads/cursor.js";
|
|
5
6
|
import { fail } from "../../tenant/http.js";
|
|
7
|
+
import { artifactView } from "../../artifacts/service.js";
|
|
6
8
|
import { sandboxWorkspaceKey } from "../../sandbox/records.js";
|
|
7
9
|
import { database, driverError } from "./db.js";
|
|
8
10
|
import { createPostgresReadClient } from "./connect.js";
|
|
9
|
-
import {
|
|
11
|
+
import { toolCallDuration, toolCallStatus } from "../../harness-api/tool-status.js";
|
|
12
|
+
import { effects, artifacts, modelUsage, environments, sandboxes, sessions, sessionEvents, } from "./schema.js";
|
|
10
13
|
const sessionFields = {
|
|
11
14
|
id: sessions.id,
|
|
12
15
|
agentId: sessions.agentId,
|
|
@@ -14,7 +17,7 @@ const sessionFields = {
|
|
|
14
17
|
status: sessions.status,
|
|
15
18
|
activeTurnId: sql `${sessions.body}->>'activeTurnId'`,
|
|
16
19
|
lastTurnId: sql `${sessions.body}->>'lastTurnId'`,
|
|
17
|
-
|
|
20
|
+
environmentId: sessions.environmentId,
|
|
18
21
|
createdAt: sessions.createdAt,
|
|
19
22
|
};
|
|
20
23
|
function accessWhere(access) {
|
|
@@ -23,6 +26,7 @@ function accessWhere(access) {
|
|
|
23
26
|
function publicCall(row) {
|
|
24
27
|
return {
|
|
25
28
|
id: row.id,
|
|
29
|
+
effectId: row.effectKey,
|
|
26
30
|
sessionId: row.sessionId,
|
|
27
31
|
turnId: row.turnId,
|
|
28
32
|
agentId: row.agentId,
|
|
@@ -44,6 +48,34 @@ function publicCall(row) {
|
|
|
44
48
|
},
|
|
45
49
|
};
|
|
46
50
|
}
|
|
51
|
+
function publicToolCall(body) {
|
|
52
|
+
const { request } = body;
|
|
53
|
+
const status = toolCallStatus(body);
|
|
54
|
+
const value = body.outcome?.value;
|
|
55
|
+
const error = value?.kind === "failed"
|
|
56
|
+
? { code: String(value.code ?? "tool.failed"), message: String(value.message ?? "") }
|
|
57
|
+
: status === "uncertain"
|
|
58
|
+
? { code: "uncertain", message: body.error ?? "" }
|
|
59
|
+
: null;
|
|
60
|
+
return {
|
|
61
|
+
effectId: request.effectId,
|
|
62
|
+
turnId: request.turnId,
|
|
63
|
+
callId: typeof request.context?.callId === "string" ? request.context.callId : null,
|
|
64
|
+
toolName: request.toolName ?? null,
|
|
65
|
+
kind: body.toolKind ?? null,
|
|
66
|
+
server: body.server ?? null,
|
|
67
|
+
skill: body.skill ?? null,
|
|
68
|
+
plugin: body.plugin ?? null,
|
|
69
|
+
status,
|
|
70
|
+
// A row written before R5 counted no sends: it was sent once.
|
|
71
|
+
attempts: body.attempts ?? 1,
|
|
72
|
+
input: request.input ?? null,
|
|
73
|
+
error,
|
|
74
|
+
startedAt: body.startedAt ?? null,
|
|
75
|
+
settledAt: body.settledAt ?? null,
|
|
76
|
+
durationMs: toolCallDuration(body) ?? null,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
47
79
|
function keyOf(key, length, timestamp = false, nullable = false) {
|
|
48
80
|
if (key &&
|
|
49
81
|
(key.length !== length ||
|
|
@@ -87,6 +119,39 @@ export function createPostgresReadStore(source, tenantId) {
|
|
|
87
119
|
}
|
|
88
120
|
return {
|
|
89
121
|
close: () => pool.end({ timeout: 2 }),
|
|
122
|
+
artifacts: (filters, page, access) => read(async (tx) => {
|
|
123
|
+
if (filters.sessionId !== undefined)
|
|
124
|
+
await requireSession(tx, filters.sessionId, access);
|
|
125
|
+
const cursor = readCursor(tenantId, "artifacts", {
|
|
126
|
+
sessionId: filters.sessionId ?? null,
|
|
127
|
+
kind: filters.kind ?? null,
|
|
128
|
+
labels: Object.entries(filters.labels).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)),
|
|
129
|
+
});
|
|
130
|
+
const key = keyOf(cursor.decode(page.cursor), 2, true);
|
|
131
|
+
if (key && !isArtifactId(key[1]))
|
|
132
|
+
fail(400, "Invalid artifact cursor key", { code: "cursor_invalid" });
|
|
133
|
+
const rows = await tx
|
|
134
|
+
.select()
|
|
135
|
+
.from(artifacts)
|
|
136
|
+
.where(and(access.owner === undefined && access.agents === undefined
|
|
137
|
+
? undefined
|
|
138
|
+
: exists(tx.select({ id: sessions.id })
|
|
139
|
+
.from(sessions)
|
|
140
|
+
.where(and(eq(sessions.id, artifacts.sessionId), accessWhere(access)))), filters.sessionId === undefined
|
|
141
|
+
? undefined
|
|
142
|
+
: eq(artifacts.sessionId, filters.sessionId), filters.kind === undefined ? undefined : eq(artifacts.kind, filters.kind),
|
|
143
|
+
// Labels are a flat string map serialized by JSON.stringify. Match its exact
|
|
144
|
+
// key/value pair: jsonb rejects NUL/unpaired surrogate escapes labels may hold.
|
|
145
|
+
...Object.entries(filters.labels).map(([k, v]) => sql `strpos(${artifacts.labelsJson}, ${JSON.stringify(k) + ":" + JSON.stringify(v)}) > 0`), key ? sql `(${artifacts.createdAt}, ${artifacts.id}) < (${key[0]}, ${key[1]})` : undefined))
|
|
146
|
+
.orderBy(desc(artifacts.createdAt), desc(artifacts.id))
|
|
147
|
+
.limit(page.limit + 1);
|
|
148
|
+
const items = rows.slice(0, page.limit);
|
|
149
|
+
const last = items.at(-1);
|
|
150
|
+
return {
|
|
151
|
+
artifacts: items.map((row) => artifactView(row)),
|
|
152
|
+
nextCursor: rows.length > page.limit && last ? cursor.encode([last.createdAt, last.id]) : null,
|
|
153
|
+
};
|
|
154
|
+
}),
|
|
90
155
|
sessions: (filters, page, access) => read(async (tx) => {
|
|
91
156
|
const cursor = readCursor(tenantId, "sessions", filters);
|
|
92
157
|
const key = keyOf(cursor.decode(page.cursor), 2, true, true);
|
|
@@ -98,9 +163,9 @@ export function createPostgresReadStore(source, tenantId) {
|
|
|
98
163
|
const rows = await tx
|
|
99
164
|
.select(fields)
|
|
100
165
|
.from(sessions)
|
|
101
|
-
.where(and(accessWhere(access), position, filters.agentId === undefined ? undefined : eq(sessions.agentId, filters.agentId), filters.status === undefined ? undefined : eq(sessions.status, filters.status), filters.
|
|
166
|
+
.where(and(accessWhere(access), position, filters.agentId === undefined ? undefined : eq(sessions.agentId, filters.agentId), filters.status === undefined ? undefined : eq(sessions.status, filters.status), filters.environmentId === undefined
|
|
102
167
|
? undefined
|
|
103
|
-
: eq(sessions.
|
|
168
|
+
: eq(sessions.environmentId, filters.environmentId), filters.ownerUserId === undefined
|
|
104
169
|
? undefined
|
|
105
170
|
: eq(sessions.ownerUserId, filters.ownerUserId)))
|
|
106
171
|
.orderBy(sql `${sessions.createdAt} desc nulls last`, desc(sessions.id))
|
|
@@ -182,6 +247,37 @@ export function createPostgresReadStore(source, tenantId) {
|
|
|
182
247
|
asOf: new Date().toISOString(),
|
|
183
248
|
};
|
|
184
249
|
}),
|
|
250
|
+
toolCalls: (id, turnId, page, access) => read(async (tx) => {
|
|
251
|
+
await requireSession(tx, id, access);
|
|
252
|
+
const cursor = readCursor(tenantId, "tool-calls", { sessionId: id, turnId });
|
|
253
|
+
const key = keyOf(cursor.decode(page.cursor), 2);
|
|
254
|
+
// In the order of their first send; a row written before R5 has no `startedAt`.
|
|
255
|
+
const startedAt = sql `coalesce(${effects.body}->>'startedAt', '')`;
|
|
256
|
+
const rows = await tx
|
|
257
|
+
.select({ id: effects.id, body: effects.body, startedAt })
|
|
258
|
+
.from(effects)
|
|
259
|
+
.where(and(eq(effects.sessionId, id), eq(effects.kind, "tool"), turnId === undefined ? undefined : eq(effects.turnId, turnId), key ? sql `(${startedAt}, ${effects.id}) > (${key[0]}, ${key[1]})` : undefined))
|
|
260
|
+
.orderBy(asc(startedAt), asc(effects.id))
|
|
261
|
+
.limit(page.limit + 1);
|
|
262
|
+
const items = rows.slice(0, page.limit);
|
|
263
|
+
const last = items.at(-1);
|
|
264
|
+
return {
|
|
265
|
+
calls: items.map((row) => publicToolCall(row.body)),
|
|
266
|
+
nextCursor: rows.length > page.limit && last ? cursor.encode([last.startedAt, last.id]) : null,
|
|
267
|
+
asOf: new Date().toISOString(),
|
|
268
|
+
};
|
|
269
|
+
}),
|
|
270
|
+
turnEvents: (id, turnId, access) => read(async (tx) => {
|
|
271
|
+
await requireSession(tx, id, access);
|
|
272
|
+
// The record has no turn column: one session's rows, on the turn id in the event (no
|
|
273
|
+
// index yet, R8).
|
|
274
|
+
const rows = await tx
|
|
275
|
+
.select({ body: sessionEvents.body })
|
|
276
|
+
.from(sessionEvents)
|
|
277
|
+
.where(and(eq(sessionEvents.sessionId, id), sql `${sessionEvents.body}->>'turnId' = ${turnId}`))
|
|
278
|
+
.orderBy(asc(sessionEvents.seq));
|
|
279
|
+
return rows.map((row) => row.body);
|
|
280
|
+
}),
|
|
185
281
|
exportModel: (after, limit) => read(async (tx) => {
|
|
186
282
|
const cursor = readCursor(tenantId, "model-export", {});
|
|
187
283
|
const key = keyOf(cursor.decode(after), 2);
|
|
@@ -205,19 +301,19 @@ export function createPostgresReadStore(source, tenantId) {
|
|
|
205
301
|
asOf: new Date().toISOString(),
|
|
206
302
|
};
|
|
207
303
|
}),
|
|
208
|
-
|
|
209
|
-
const cursor = readCursor(tenantId, "
|
|
304
|
+
environments: (labels, page, access, grants) => read(async (tx) => {
|
|
305
|
+
const cursor = readCursor(tenantId, "environments", labels);
|
|
210
306
|
const key = keyOf(cursor.decode(page.cursor), 1);
|
|
211
307
|
const allowed = grants === undefined
|
|
212
308
|
? undefined
|
|
213
309
|
: or(...grants.map((grant) => grant.endsWith("/*")
|
|
214
|
-
? sql `starts_with(${
|
|
215
|
-
: eq(
|
|
310
|
+
? sql `starts_with(${environments.id}, ${grant.slice(0, -1)})`
|
|
311
|
+
: eq(environments.id, grant)));
|
|
216
312
|
const rows = await tx
|
|
217
313
|
.select()
|
|
218
|
-
.from(
|
|
219
|
-
.where(and(grants?.length === 0 ? sql `false` : allowed, key ? gt(
|
|
220
|
-
.orderBy(asc(
|
|
314
|
+
.from(environments)
|
|
315
|
+
.where(and(grants?.length === 0 ? sql `false` : allowed, key ? gt(environments.id, key[0]) : undefined, or(isNull(environments.desired), ne(environments.desired, "deleted")), ...Object.entries(labels).map(([k, v]) => sql `${environments.labels}::jsonb->>${k} = ${v}`)))
|
|
316
|
+
.orderBy(asc(environments.id))
|
|
221
317
|
.limit(page.limit + 1);
|
|
222
318
|
const items = [];
|
|
223
319
|
for (const row of rows.slice(0, page.limit)) {
|
|
@@ -226,7 +322,7 @@ export function createPostgresReadStore(source, tenantId) {
|
|
|
226
322
|
items: sql `coalesce(json_agg(json_build_object('id', ${sessions.id}, 'activeTurnId', ${sessions.body}->>'activeTurnId') order by ${sessions.id}), '[]'::json)`,
|
|
227
323
|
})
|
|
228
324
|
.from(sessions)
|
|
229
|
-
.where(and(eq(sessions.
|
|
325
|
+
.where(and(eq(sessions.environmentId, row.id), accessWhere(access)));
|
|
230
326
|
const [compute] = await tx
|
|
231
327
|
.select({ body: sandboxes.body })
|
|
232
328
|
.from(sandboxes)
|
|
@@ -237,14 +333,23 @@ export function createPostgresReadStore(source, tenantId) {
|
|
|
237
333
|
id: row.id,
|
|
238
334
|
kind: row.kind,
|
|
239
335
|
labels: row.labels,
|
|
240
|
-
|
|
336
|
+
manifest: row.recipe,
|
|
337
|
+
...(row.manifestName === null ? {} : { manifestName: row.manifestName }),
|
|
338
|
+
...(row.manifestVersion === null ? {} : { manifestVersion: row.manifestVersion }),
|
|
339
|
+
...(row.manifestHash === null ? {} : { manifestHash: row.manifestHash }),
|
|
340
|
+
...(row.forkedFrom ? { forkedFrom: row.forkedFrom } : {}),
|
|
341
|
+
version: row.version,
|
|
342
|
+
appliedVersion: row.appliedVersion,
|
|
343
|
+
ownerUserId: row.ownerUserId,
|
|
241
344
|
state: isPod
|
|
242
345
|
? row.observed === "running"
|
|
243
346
|
? "running"
|
|
244
347
|
: row.observed === "creating"
|
|
245
348
|
? "creating"
|
|
246
349
|
: "stopped"
|
|
247
|
-
:
|
|
350
|
+
: row.kind === "none"
|
|
351
|
+
? "ready"
|
|
352
|
+
: (compute?.body?.state ?? "ready"),
|
|
248
353
|
...(isPod
|
|
249
354
|
? {
|
|
250
355
|
pod: {
|
|
@@ -252,11 +357,12 @@ export function createPostgresReadStore(source, tenantId) {
|
|
|
252
357
|
observed: row.observed,
|
|
253
358
|
volumeGeneration: row.volumeGen,
|
|
254
359
|
hostEpoch: row.hostEpoch,
|
|
255
|
-
...(row.expiresAt ? { expiresAt: new Date(row.expiresAt).toISOString() } : {}),
|
|
256
360
|
...(row.reason ? { reason: row.reason } : {}),
|
|
361
|
+
...(row.imageDigest ? { imageDigest: row.imageDigest } : {}),
|
|
257
362
|
},
|
|
258
363
|
}
|
|
259
364
|
: {}),
|
|
365
|
+
lastUsedAt: new Date(row.lastUsedAt).toISOString(),
|
|
260
366
|
sessions: related.items,
|
|
261
367
|
createdAt: row.createdAt,
|
|
262
368
|
updatedAt: row.updatedAt,
|
|
@@ -264,7 +370,7 @@ export function createPostgresReadStore(source, tenantId) {
|
|
|
264
370
|
}
|
|
265
371
|
const last = items.at(-1);
|
|
266
372
|
return {
|
|
267
|
-
|
|
373
|
+
environments: items,
|
|
268
374
|
nextCursor: rows.length > page.limit && last ? cursor.encode([last.id]) : null,
|
|
269
375
|
};
|
|
270
376
|
}),
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { RecordWriter,
|
|
1
|
+
import type { RecordWriter, EnvironmentRecordWriter } from "../../record/index.js";
|
|
2
2
|
import type { Transaction } from "./db.js";
|
|
3
3
|
/**
|
|
4
|
-
* The
|
|
5
|
-
* `
|
|
4
|
+
* The Environment stream writer of transaction `db` (`record/environment.ts`): the only inserts
|
|
5
|
+
* into `environment_events`. The caller holds the Environment row's lock, which orders its events.
|
|
6
6
|
*/
|
|
7
|
-
export declare function
|
|
7
|
+
export declare function postgresEnvironmentRecordWriter(db: Transaction): EnvironmentRecordWriter;
|
|
8
8
|
/** The record writer of transaction `db`. */
|
|
9
9
|
export declare function postgresRecordWriter(db: Transaction): RecordWriter;
|
|
@@ -5,22 +5,22 @@
|
|
|
5
5
|
* run in the store's transaction under the caller's session row lock.
|
|
6
6
|
*/
|
|
7
7
|
import { eq, sql } from "drizzle-orm";
|
|
8
|
-
import {
|
|
8
|
+
import { environmentEvents, sessionEvents, sessionLogHeads, tenant } from "./schema.js";
|
|
9
9
|
/**
|
|
10
|
-
* The
|
|
11
|
-
* `
|
|
10
|
+
* The Environment stream writer of transaction `db` (`record/environment.ts`): the only inserts
|
|
11
|
+
* into `environment_events`. The caller holds the Environment row's lock, which orders its events.
|
|
12
12
|
*/
|
|
13
|
-
export function
|
|
13
|
+
export function postgresEnvironmentRecordWriter(db) {
|
|
14
14
|
return {
|
|
15
|
-
async nextSeq(
|
|
15
|
+
async nextSeq(environmentId) {
|
|
16
16
|
const [row] = await db
|
|
17
|
-
.select({ next: sql `coalesce(max(${
|
|
18
|
-
.from(
|
|
19
|
-
.where(eq(
|
|
17
|
+
.select({ next: sql `coalesce(max(${environmentEvents.seq}) + 1, 0)`.mapWith(Number) })
|
|
18
|
+
.from(environmentEvents)
|
|
19
|
+
.where(eq(environmentEvents.environmentId, environmentId));
|
|
20
20
|
return row?.next ?? 0;
|
|
21
21
|
},
|
|
22
22
|
async insert(row) {
|
|
23
|
-
await db.insert(
|
|
23
|
+
await db.insert(environmentEvents).values(row);
|
|
24
24
|
},
|
|
25
25
|
};
|
|
26
26
|
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
import type { LiveEvent } from "@nylorun/core/contracts";
|
|
1
2
|
import type { Sql } from "postgres";
|
|
2
3
|
import type { RecordReader } from "../../streams/relay/types.js";
|
|
3
4
|
export declare function createPostgresRecordReader(sql: Sql, options: {
|
|
4
5
|
tenantId: string;
|
|
5
6
|
}): RecordReader;
|
|
7
|
+
/**
|
|
8
|
+
* The trace projector's read of a turn's start (R7.2): the `command.message` that started turn
|
|
9
|
+
* `turnId` of `sessionId`, or undefined when the log has none. One session's rows, filtered on
|
|
10
|
+
* the turn id in the event (the record has no turn column; no index yet, R8).
|
|
11
|
+
*/
|
|
12
|
+
export declare function createPostgresTurnMessages(sql: Sql): (sessionId: string, turnId: string) => Promise<LiveEvent | undefined>;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Reads the record back for the stream relay (Durable Streams §7.2–7.3): a session's rows to
|
|
3
3
|
* refill a gap in S2, every log head to reconcile after a fresh slot, and the Tenant's current
|
|
4
|
-
* basin generation to tell obsolete rows apart.
|
|
4
|
+
* basin generation to tell obsolete rows apart. The trace projector reads a turn's start
|
|
5
|
+
* (`createPostgresTurnMessages`).
|
|
5
6
|
*
|
|
6
7
|
* The database holds one Tenant, so the record has no Tenant column: the reader is made for
|
|
7
8
|
* that Tenant (`tenantId`), fills `RecordRow.tenantId` and `LogHead.tenantId` with it, and
|
|
8
9
|
* reads nothing for any other id.
|
|
9
10
|
*/
|
|
10
|
-
import { and, asc, eq, gt, gte, lt } from "drizzle-orm";
|
|
11
|
+
import { and, asc, eq, gt, gte, lt, sql as sql_ } from "drizzle-orm";
|
|
11
12
|
import { database, driverError } from "./db.js";
|
|
12
13
|
import { sessionEvents, sessionLogHeads, tenant } from "./schema.js";
|
|
13
14
|
export function createPostgresRecordReader(sql, options) {
|
|
@@ -58,3 +59,23 @@ export function createPostgresRecordReader(sql, options) {
|
|
|
58
59
|
},
|
|
59
60
|
};
|
|
60
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* The trace projector's read of a turn's start (R7.2): the `command.message` that started turn
|
|
64
|
+
* `turnId` of `sessionId`, or undefined when the log has none. One session's rows, filtered on
|
|
65
|
+
* the turn id in the event (the record has no turn column; no index yet, R8).
|
|
66
|
+
*/
|
|
67
|
+
export function createPostgresTurnMessages(sql) {
|
|
68
|
+
const db = database(sql);
|
|
69
|
+
return async (sessionId, turnId) => {
|
|
70
|
+
const [row] = await db
|
|
71
|
+
.select({ body: sessionEvents.body })
|
|
72
|
+
.from(sessionEvents)
|
|
73
|
+
.where(and(eq(sessionEvents.sessionId, sessionId), eq(sessionEvents.type, "command.message"), sql_ `${sessionEvents.body}->>'turnId' = ${turnId}`))
|
|
74
|
+
.orderBy(asc(sessionEvents.seq))
|
|
75
|
+
.limit(1)
|
|
76
|
+
.catch((error) => {
|
|
77
|
+
throw driverError(error);
|
|
78
|
+
});
|
|
79
|
+
return row?.body;
|
|
80
|
+
};
|
|
81
|
+
}
|