@nylorun/runtime 0.25.0-beta → 0.27.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 +169 -0
- package/README.md +26 -16
- package/dist/adapters/execution/restate.d.ts +15 -18
- package/dist/adapters/execution/restate.js +31 -27
- package/dist/adapters/replication/pgoutput.d.ts +1 -1
- package/dist/adapters/replication/pgoutput.js +3 -2
- package/dist/adapters/sandbox/local.js +8 -5
- package/dist/adapters/sandbox/virtual.js +2 -2
- package/dist/adapters/streams/s2.d.ts +1 -1
- package/dist/adapters/streams/s2.js +18 -14
- package/dist/api/a2a/card.js +1 -1
- package/dist/api/a2a/endpoint.js +3 -4
- package/dist/api/a2a/protocol.js +4 -0
- package/dist/api/a2a/routes.d.ts +2 -6
- package/dist/api/a2a/routes.js +12 -18
- package/dist/api/ag-ui/endpoint.js +2 -3
- package/dist/api/ag-ui/routes.js +4 -4
- package/dist/api/components.d.ts +326 -45
- package/dist/api/components.js +5 -1
- package/dist/api/gate/keys.js +7 -4
- package/dist/api/gate/routes.d.ts +6 -2
- package/dist/api/gate/routes.js +15 -11
- package/dist/api/http/app.d.ts +2 -2
- package/dist/api/http/app.js +2 -2
- package/dist/api/http/body.d.ts +15 -3
- package/dist/api/http/body.js +15 -7
- package/dist/api/http/define.d.ts +1 -1
- package/dist/api/http/respond.js +7 -3
- package/dist/api/http/routes/access.js +5 -4
- package/dist/api/http/routes/artifacts.js +19 -7
- package/dist/api/http/routes/coverage.js +1 -1
- package/dist/api/http/routes/environment-manifests.js +1 -1
- package/dist/api/http/routes/environments.js +6 -6
- package/dist/api/http/routes/files.d.ts +2 -1
- package/dist/api/http/routes/files.js +31 -5
- package/dist/api/http/routes/mcp.js +1 -1
- package/dist/api/http/routes/reads.d.ts +35 -0
- package/dist/api/http/routes/reads.js +50 -22
- package/dist/api/http/routes/sessions.js +12 -11
- package/dist/api/http/routes/tenant.d.ts +2 -2
- package/dist/api/http/routes/tenant.js +69 -16
- package/dist/api/inbound-files.d.ts +3 -9
- package/dist/api/inbound-files.js +18 -24
- package/dist/api/openapi.js +6 -2
- package/dist/artifacts/disk.d.ts +0 -4
- package/dist/artifacts/disk.js +77 -73
- package/dist/artifacts/files.d.ts +13 -4
- package/dist/artifacts/files.js +27 -9
- package/dist/artifacts/folder-upload.d.ts +75 -0
- package/dist/artifacts/folder-upload.js +263 -0
- package/dist/artifacts/folders.d.ts +14 -8
- package/dist/artifacts/folders.js +19 -11
- package/dist/artifacts/links.js +7 -6
- package/dist/artifacts/parts.d.ts +9 -14
- package/dist/artifacts/parts.js +11 -9
- package/dist/artifacts/pipe.d.ts +15 -0
- package/dist/artifacts/pipe.js +71 -0
- package/dist/artifacts/quota.d.ts +36 -0
- package/dist/artifacts/quota.js +44 -0
- package/dist/artifacts/service.d.ts +25 -1
- package/dist/artifacts/service.js +70 -25
- package/dist/blob/fs.js +2 -1
- package/dist/blob/s3.d.ts +6 -2
- package/dist/blob/s3.js +9 -7
- package/dist/blob/types.d.ts +1 -1
- package/dist/blob/types.js +1 -1
- package/dist/core/limits.d.ts +11 -35
- package/dist/core/limits.js +5 -73
- package/dist/core/sandbox-routes.js +0 -1
- package/dist/core/turn-manifest.d.ts +1 -2
- package/dist/core/turn-manifest.js +4 -28
- package/dist/execution/memory.d.ts +8 -5
- package/dist/execution/memory.js +8 -6
- package/dist/execution/types.d.ts +1 -6
- package/dist/execution/types.js +0 -5
- package/dist/gates/contract.d.ts +3 -2
- package/dist/gates/contract.js +1 -1
- package/dist/gates/egress-credentials.js +4 -3
- package/dist/gates/egress.d.ts +9 -9
- package/dist/gates/egress.js +19 -19
- package/dist/gates/fixture-model.js +13 -2
- package/dist/gates/handler.d.ts +1 -3
- package/dist/gates/handler.js +4 -3
- package/dist/gates/http-client.d.ts +4 -3
- package/dist/gates/http-client.js +5 -7
- package/dist/gates/http-tool.d.ts +24 -4
- package/dist/gates/http-tool.js +53 -17
- package/dist/gates/in-process.d.ts +2 -1
- package/dist/gates/in-process.js +17 -9
- package/dist/gates/inflight.d.ts +2 -2
- package/dist/gates/inflight.js +3 -2
- package/dist/gates/journal.js +5 -7
- package/dist/gates/mcp-handler.d.ts +4 -3
- package/dist/gates/mcp-handler.js +15 -5
- package/dist/gates/model-gate.d.ts +11 -2
- package/dist/gates/policy.d.ts +28 -5
- package/dist/gates/policy.js +60 -17
- package/dist/gates/provider-gate.d.ts +22 -0
- package/dist/gates/provider-gate.js +30 -0
- package/dist/gates/tool-calls.d.ts +1 -3
- package/dist/gates/tool-calls.js +2 -3
- package/dist/gates/tool-client.d.ts +1 -1
- package/dist/gates/tool-client.js +5 -6
- package/dist/gates/tool-contract.d.ts +8 -5
- package/dist/gates/tool-contract.js +1 -1
- package/dist/gates/tool-gate.d.ts +18 -7
- package/dist/gates/tool-gate.js +49 -7
- package/dist/harness/calls.d.ts +27 -25
- package/dist/harness/calls.js +40 -46
- package/dist/harness/executors.d.ts +10 -3
- package/dist/harness/executors.js +53 -23
- package/dist/harness/main.js +2 -2
- package/dist/harness/pod.d.ts +0 -2
- package/dist/harness/pod.js +7 -6
- package/dist/harness/run-tokens.d.ts +4 -1
- package/dist/harness/run-tokens.js +6 -2
- package/dist/harness/service.d.ts +17 -14
- package/dist/harness/service.js +21 -35
- package/dist/harness/setup.d.ts +0 -2
- package/dist/harness/setup.js +4 -9
- package/dist/harness/ws-client.d.ts +2 -2
- package/dist/harness/ws-client.js +7 -5
- package/dist/harness/ws-port.d.ts +3 -4
- package/dist/harness/ws-port.js +3 -4
- package/dist/harness-api/artifacts.d.ts +20 -0
- package/dist/harness-api/artifacts.js +478 -0
- package/dist/harness-api/in-process.d.ts +2 -2
- package/dist/harness-api/in-process.js +18 -16
- package/dist/harness-api/record.d.ts +10 -9
- package/dist/harness-api/record.js +102 -157
- package/dist/harness-api/renew.d.ts +1 -1
- package/dist/harness-api/renew.js +2 -2
- package/dist/harness-api/server.d.ts +1 -16
- package/dist/harness-api/server.js +82 -73
- package/dist/harness-api/start.d.ts +20 -2
- package/dist/harness-api/start.js +57 -18
- package/dist/harness-api/tool-journal.d.ts +15 -10
- package/dist/harness-api/tool-journal.js +26 -24
- package/dist/harness-api/workspace.d.ts +0 -4
- package/dist/harness-api/workspace.js +2 -45
- package/dist/harness-api/ws-server.js +10 -10
- package/dist/host/create-host.js +2 -3
- package/dist/host/execution.js +2 -3
- package/dist/host/gates.d.ts +2 -9
- package/dist/host/gates.js +15 -12
- package/dist/host/http.d.ts +0 -2
- package/dist/host/http.js +0 -27
- package/dist/host/main.js +10 -3
- package/dist/host/operate.js +12 -3
- package/dist/host/stack-config.d.ts +11 -0
- package/dist/host/stack-config.js +21 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/infra/index.js +2 -1
- package/dist/infra/readiness.d.ts +0 -2
- package/dist/infra/readiness.js +4 -3
- package/dist/keys/client.d.ts +1 -0
- package/dist/keys/client.js +2 -3
- package/dist/keys/contract.d.ts +1 -3
- package/dist/keys/contract.js +1 -3
- package/dist/keys/egress-ca.d.ts +0 -2
- package/dist/keys/egress-ca.js +2 -3
- package/dist/keys/keys.js +6 -1
- package/dist/keys/x509.d.ts +8 -4
- package/dist/keys/x509.js +14 -5
- package/dist/management-openapi.json +1961 -994
- package/dist/mcp/connect.d.ts +35 -26
- package/dist/mcp/connect.js +112 -141
- package/dist/mcp/pool.d.ts +27 -22
- package/dist/mcp/pool.js +34 -48
- package/dist/mcp/preview.d.ts +13 -6
- package/dist/mcp/preview.js +37 -20
- package/dist/mcp/snapshot.d.ts +35 -86
- package/dist/mcp/snapshot.js +93 -135
- package/dist/model/auth-store.js +5 -3
- package/dist/model/capabilities.d.ts +1 -1
- package/dist/model/catalog.d.ts +9 -36
- package/dist/model/catalog.js +6 -33
- package/dist/model/descriptor.d.ts +51 -0
- package/dist/model/descriptor.js +83 -0
- package/dist/model/models.d.ts +0 -3
- package/dist/model/models.js +3 -5
- package/dist/model/native-blocks.js +1 -1
- package/dist/model/pi-model.d.ts +16 -5
- package/dist/model/pi-model.js +86 -105
- package/dist/openapi.json +866 -1218
- package/dist/reads/cursor.js +3 -1
- package/dist/record/append.d.ts +34 -2
- package/dist/record/append.js +50 -1
- package/dist/record/environment.d.ts +2 -0
- package/dist/record/environment.js +2 -0
- package/dist/record/index.d.ts +1 -1
- package/dist/record/index.js +1 -1
- package/dist/redact.d.ts +1 -1
- package/dist/redact.js +3 -2
- package/dist/sandbox/egress-token.d.ts +3 -3
- package/dist/sandbox/egress-token.js +3 -3
- package/dist/sandbox/join.js +3 -2
- package/dist/sandbox/manager.d.ts +41 -41
- package/dist/sandbox/manager.js +112 -44
- package/dist/sandbox/placement.d.ts +1 -1
- package/dist/sandbox/placement.js +5 -8
- package/dist/sandbox/pods/client.d.ts +1 -10
- package/dist/sandbox/pods/client.js +8 -4
- package/dist/sandbox/pods/lifecycle.d.ts +19 -11
- package/dist/sandbox/pods/lifecycle.js +45 -23
- package/dist/sandbox/pods/network-gate.d.ts +4 -5
- package/dist/sandbox/pods/network-gate.js +7 -7
- package/dist/sandbox/pods/reconcile.js +4 -1
- package/dist/sandbox/pods/spec.js +8 -5
- package/dist/sandbox/policy.d.ts +7 -1
- package/dist/sandbox/policy.js +10 -3
- package/dist/sandbox/resolve.d.ts +8 -3
- package/dist/sandbox/resolve.js +12 -2
- package/dist/sandbox/setup.d.ts +3 -1
- package/dist/sandbox/setup.js +34 -11
- package/dist/sandbox/share.d.ts +5 -14
- package/dist/sandbox/share.js +5 -34
- package/dist/sandbox/skills.d.ts +7 -13
- package/dist/sandbox/skills.js +16 -31
- package/dist/sandbox/tenant-config.d.ts +2 -2
- package/dist/sandbox/tenant-config.js +4 -3
- package/dist/sandbox/tools.d.ts +7 -1
- package/dist/sandbox/tools.js +26 -26
- package/dist/sandbox/types.d.ts +10 -3
- package/dist/sandbox/types.js +9 -0
- package/dist/store/postgres/connect.d.ts +6 -5
- package/dist/store/postgres/connect.js +14 -11
- package/dist/store/postgres/control.js +13 -13
- package/dist/store/postgres/drizzle/0028_artifact_write_keys.sql +2 -0
- package/dist/store/postgres/drizzle/0029_protocol_15.sql +11 -0
- package/dist/store/postgres/drizzle/0030_protocol_15_runtime_block.sql +11 -0
- package/dist/store/postgres/drizzle/0031_protocol_15_mcp_snapshot.sql +8 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +28 -0
- package/dist/store/postgres/migrate.js +1 -1
- package/dist/store/postgres/reads.js +10 -2
- package/dist/store/postgres/schema.d.ts +19 -0
- package/dist/store/postgres/schema.js +7 -0
- package/dist/store/postgres/store.js +55 -26
- package/dist/store/types.d.ts +17 -7
- package/dist/streams/relay/core.d.ts +3 -3
- package/dist/streams/relay/core.js +9 -10
- package/dist/tenant/advance.js +21 -31
- package/dist/tenant/commands.js +9 -16
- package/dist/tenant/context.d.ts +14 -17
- package/dist/tenant/definition-files.d.ts +25 -4
- package/dist/tenant/definition-files.js +85 -47
- package/dist/tenant/effects.js +9 -36
- package/dist/tenant/environment-manifests.js +9 -1
- package/dist/tenant/environments.d.ts +0 -2
- package/dist/tenant/environments.js +54 -30
- package/dist/tenant/ephemeral.d.ts +1 -1
- package/dist/tenant/ephemeral.js +2 -1
- package/dist/tenant/history.d.ts +1 -1
- package/dist/tenant/history.js +1 -1
- package/dist/tenant/host-token.d.ts +3 -3
- package/dist/tenant/host-token.js +12 -11
- package/dist/tenant/http.d.ts +5 -8
- package/dist/tenant/http.js +9 -0
- package/dist/tenant/identity-file.d.ts +24 -1
- package/dist/tenant/identity-file.js +35 -7
- package/dist/tenant/issuers.d.ts +5 -5
- package/dist/tenant/issuers.js +31 -23
- package/dist/tenant/jwt.d.ts +8 -2
- package/dist/tenant/jwt.js +10 -2
- package/dist/tenant/limits.d.ts +90 -0
- package/dist/tenant/limits.js +175 -0
- package/dist/tenant/module.d.ts +4 -1
- package/dist/tenant/module.js +9 -8
- package/dist/tenant/outbound.d.ts +17 -19
- package/dist/tenant/outbound.js +18 -21
- package/dist/tenant/run-grants.js +3 -2
- package/dist/tenant/run-token.d.ts +0 -4
- package/dist/tenant/run-token.js +6 -11
- package/dist/tenant/runtime-limits.d.ts +24 -0
- package/dist/tenant/runtime-limits.js +27 -0
- package/dist/tenant/runtime.js +30 -43
- package/dist/tenant/session-streams.js +7 -6
- package/dist/tenant/session.d.ts +1 -1
- package/dist/tenant/session.js +1 -1
- package/dist/tenant/sessions.js +32 -29
- package/dist/tenant/signing-keys.d.ts +1 -1
- package/dist/tenant/signing-keys.js +5 -6
- package/dist/tenant/status.js +4 -3
- package/dist/tenant/streams.js +18 -20
- package/dist/tenant/sweep.d.ts +1 -21
- package/dist/tenant/sweep.js +39 -48
- package/dist/tenant/transcript.d.ts +70 -23
- package/dist/tenant/transcript.js +28 -22
- package/dist/tenant/types.d.ts +11 -16
- package/dist/tenant/worker.d.ts +2 -10
- package/dist/tenant/worker.js +5 -14
- package/dist/traces/ids.js +5 -1
- package/dist/traces/map.d.ts +9 -6
- package/dist/traces/map.js +9 -11
- package/dist/traces/otlp.d.ts +3 -3
- package/dist/traces/otlp.js +5 -3
- package/dist/traces/projector.d.ts +9 -4
- package/dist/traces/projector.js +13 -7
- package/dist/traces/read.js +6 -1
- package/dist/tuning.d.ts +383 -0
- package/dist/tuning.js +658 -0
- package/dist/vault/headers.js +4 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/dist/artifacts/export.d.ts +0 -8
- package/dist/artifacts/export.js +0 -204
- package/dist/artifacts/media-types.d.ts +0 -30
- package/dist/artifacts/media-types.js +0 -137
- package/dist/artifacts/workspace.d.ts +0 -60
- package/dist/artifacts/workspace.js +0 -45
- package/dist/media.d.ts +0 -10
- package/dist/media.js +0 -58
- package/dist/sandbox/runtime-tools.d.ts +0 -9
- package/dist/sandbox/runtime-tools.js +0 -16
- package/dist/sandbox/session-sandbox.d.ts +0 -16
- package/dist/sandbox/session-sandbox.js +0 -77
- package/dist/tenant/artifact-tool.d.ts +0 -13
- package/dist/tenant/artifact-tool.js +0 -243
- package/dist/tenant/skill-tool.d.ts +0 -20
- package/dist/tenant/skill-tool.js +0 -67
- package/dist/tenant/tool-results.d.ts +0 -57
- package/dist/tenant/tool-results.js +0 -298
- package/dist/tenant/tool-search.d.ts +0 -39
- package/dist/tenant/tool-search.js +0 -103
package/dist/reads/cursor.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { decodeCursor } from "../record/index.js";
|
|
4
4
|
import { fail } from "../tenant/http.js";
|
|
5
|
+
import { maxHeaderSize } from "node:http";
|
|
5
6
|
const schema = z
|
|
6
7
|
.object({
|
|
7
8
|
version: z.literal(1),
|
|
@@ -23,7 +24,8 @@ export function readCursor(tenant, route, filters) {
|
|
|
23
24
|
decode(value) {
|
|
24
25
|
if (value === undefined)
|
|
25
26
|
return undefined;
|
|
26
|
-
|
|
27
|
+
// A cursor comes back in a URL, which Node refuses past `http.maxHeaderSize` anyway.
|
|
28
|
+
if (value.length > maxHeaderSize || !/^[A-Za-z0-9_-]+$/.test(value))
|
|
27
29
|
return fail(400, "Invalid cursor", { code: "cursor_invalid" });
|
|
28
30
|
let parsed;
|
|
29
31
|
try {
|
package/dist/record/append.d.ts
CHANGED
|
@@ -9,8 +9,37 @@
|
|
|
9
9
|
* The two statements run through `RecordWriter`, which the store implements on its
|
|
10
10
|
* transaction (`store/postgres/record-writer.ts`): the database driver stays behind
|
|
11
11
|
* `store/postgres/` (session-store.md §3), and this module decides what is written.
|
|
12
|
+
*
|
|
13
|
+
* Every entry is held to the Tenant's Runtime limit `recordEntryBytes`, which the caller reads
|
|
14
|
+
* and passes: an event whose payload is larger is refused (`RecordEntryTooLargeError`) before
|
|
15
|
+
* anything is written, whoever wrote it, so no record reaches S2 past its 1 MiB.
|
|
16
|
+
*/
|
|
17
|
+
import { type EventPayload, type EventType, type EventWriter, type LiveEvent, type SessionEventOf } from "@nylorun/core/contracts";
|
|
18
|
+
/**
|
|
19
|
+
* An entry larger than the Tenant's `recordEntryBytes`: `limit_exceeded`, `413` to an API client
|
|
20
|
+
* and the Harness API error code to a harness.
|
|
12
21
|
*/
|
|
13
|
-
|
|
22
|
+
export declare class RecordEntryTooLargeError extends Error {
|
|
23
|
+
readonly bytes: number;
|
|
24
|
+
readonly maxBytes: number;
|
|
25
|
+
readonly code: "limit_exceeded";
|
|
26
|
+
readonly status = 413;
|
|
27
|
+
readonly rejection: {
|
|
28
|
+
readonly code: "limit_exceeded";
|
|
29
|
+
readonly details: {
|
|
30
|
+
readonly limit: "recordEntryBytes";
|
|
31
|
+
readonly bytes: number;
|
|
32
|
+
readonly maxBytes: number;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
constructor(
|
|
36
|
+
/** What was refused, as the message names it: "The message.user event's payload". */
|
|
37
|
+
what: string, bytes: number, maxBytes: number);
|
|
38
|
+
}
|
|
39
|
+
/** The JSON size of an entry, in bytes: what the record holds of it. */
|
|
40
|
+
export declare function entryBytes(value: unknown): number;
|
|
41
|
+
/** Throws `RecordEntryTooLargeError` when `entry` is larger than `maxBytes`; `what` names it. */
|
|
42
|
+
export declare function checkEntry(what: string, entry: unknown, maxBytes: number): void;
|
|
14
43
|
/** The record's two statements, in the caller's transaction. */
|
|
15
44
|
export interface RecordWriter {
|
|
16
45
|
/**
|
|
@@ -42,10 +71,13 @@ export interface AppendInput<T extends EventType> {
|
|
|
42
71
|
payload: EventPayload<T>;
|
|
43
72
|
/** Who wrote it (R4.9). */
|
|
44
73
|
writer?: EventWriter;
|
|
74
|
+
/** The Tenant's Runtime limit `recordEntryBytes`: the most bytes the payload may hold, as JSON. */
|
|
75
|
+
maxEntryBytes: number;
|
|
45
76
|
}
|
|
46
77
|
/**
|
|
47
78
|
* Appends one event through `writer`. An event the catalog does not describe throws
|
|
48
|
-
* `InvalidEventError` before its row is
|
|
79
|
+
* `InvalidEventError`, and one past `maxEntryBytes` `RecordEntryTooLargeError`, before its row is
|
|
80
|
+
* written; the caller's transaction then rolls back.
|
|
49
81
|
*/
|
|
50
82
|
export declare function appendEvent<T extends EventType>(writer: RecordWriter, input: AppendInput<T>): Promise<{
|
|
51
83
|
event: SessionEventOf<T>;
|
package/dist/record/append.js
CHANGED
|
@@ -1,9 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The only write path into the record (Durable Streams §6, blueprint D27): the session's log
|
|
3
|
+
* head allocates the next sequence, the event is built on the envelope and checked against the
|
|
4
|
+
* catalog, and its row is written, both in the caller's transaction. The database holds one
|
|
5
|
+
* Tenant, so rows are keyed by session alone; the Tenant id is the caller's and goes into the
|
|
6
|
+
* envelope only. The caller holds the session row lock, which orders the session's appends,
|
|
7
|
+
* and passes the epoch it read under that lock.
|
|
8
|
+
*
|
|
9
|
+
* The two statements run through `RecordWriter`, which the store implements on its
|
|
10
|
+
* transaction (`store/postgres/record-writer.ts`): the database driver stays behind
|
|
11
|
+
* `store/postgres/` (session-store.md §3), and this module decides what is written.
|
|
12
|
+
*
|
|
13
|
+
* Every entry is held to the Tenant's Runtime limit `recordEntryBytes`, which the caller reads
|
|
14
|
+
* and passes: an event whose payload is larger is refused (`RecordEntryTooLargeError`) before
|
|
15
|
+
* anything is written, whoever wrote it, so no record reaches S2 past its 1 MiB.
|
|
16
|
+
*/
|
|
17
|
+
import { limitExceededMessage, } from "@nylorun/core/contracts";
|
|
1
18
|
import { buildEvent } from "./envelope.js";
|
|
19
|
+
/**
|
|
20
|
+
* An entry larger than the Tenant's `recordEntryBytes`: `limit_exceeded`, `413` to an API client
|
|
21
|
+
* and the Harness API error code to a harness.
|
|
22
|
+
*/
|
|
23
|
+
export class RecordEntryTooLargeError extends Error {
|
|
24
|
+
bytes;
|
|
25
|
+
maxBytes;
|
|
26
|
+
code = "limit_exceeded";
|
|
27
|
+
status = 413;
|
|
28
|
+
rejection;
|
|
29
|
+
constructor(
|
|
30
|
+
/** What was refused, as the message names it: "The message.user event's payload". */
|
|
31
|
+
what, bytes, maxBytes) {
|
|
32
|
+
super(limitExceededMessage(what, bytes, "recordEntryBytes", maxBytes));
|
|
33
|
+
this.bytes = bytes;
|
|
34
|
+
this.maxBytes = maxBytes;
|
|
35
|
+
this.name = "RecordEntryTooLargeError";
|
|
36
|
+
this.rejection = { code: "limit_exceeded", details: { limit: "recordEntryBytes", bytes, maxBytes } };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** The JSON size of an entry, in bytes: what the record holds of it. */
|
|
40
|
+
export function entryBytes(value) {
|
|
41
|
+
return Buffer.byteLength(JSON.stringify(value) ?? "null");
|
|
42
|
+
}
|
|
43
|
+
/** Throws `RecordEntryTooLargeError` when `entry` is larger than `maxBytes`; `what` names it. */
|
|
44
|
+
export function checkEntry(what, entry, maxBytes) {
|
|
45
|
+
const bytes = entryBytes(entry);
|
|
46
|
+
if (bytes > maxBytes)
|
|
47
|
+
throw new RecordEntryTooLargeError(what, bytes, maxBytes);
|
|
48
|
+
}
|
|
2
49
|
/**
|
|
3
50
|
* Appends one event through `writer`. An event the catalog does not describe throws
|
|
4
|
-
* `InvalidEventError` before its row is
|
|
51
|
+
* `InvalidEventError`, and one past `maxEntryBytes` `RecordEntryTooLargeError`, before its row is
|
|
52
|
+
* written; the caller's transaction then rolls back.
|
|
5
53
|
*/
|
|
6
54
|
export async function appendEvent(writer, input) {
|
|
55
|
+
checkEntry(`The ${input.type} event's payload`, input.payload, input.maxEntryBytes);
|
|
7
56
|
const { seq, generation } = await writer.advance(input.sessionId);
|
|
8
57
|
const event = buildEvent({
|
|
9
58
|
tenantId: input.tenantId,
|
|
@@ -16,6 +16,8 @@ export interface EnvironmentAppendInput<T extends EnvironmentEventType> {
|
|
|
16
16
|
time: Date;
|
|
17
17
|
type: T;
|
|
18
18
|
payload: EnvironmentEventPayload<T>;
|
|
19
|
+
/** The Tenant's Runtime limit `recordEntryBytes`, as for a session's events. */
|
|
20
|
+
maxEntryBytes: number;
|
|
19
21
|
}
|
|
20
22
|
/** Builds the event and checks it against the Environment event catalog. */
|
|
21
23
|
export declare function buildEnvironmentEvent<T extends EnvironmentEventType>(input: EnvironmentAppendInput<T> & {
|
|
@@ -14,6 +14,7 @@ import { randomUUID } from "node:crypto";
|
|
|
14
14
|
import { z } from "zod";
|
|
15
15
|
import { ENVIRONMENT_EVENT_PAYLOADS, ENVIRONMENT_EVENT_SCHEMA, EnvironmentEventSchema, } from "@nylorun/core/contracts";
|
|
16
16
|
import { InvalidEventError } from "./envelope.js";
|
|
17
|
+
import { checkEntry } from "./append.js";
|
|
17
18
|
/** Builds the event and checks it against the Environment event catalog. */
|
|
18
19
|
export function buildEnvironmentEvent(input) {
|
|
19
20
|
const payload = ENVIRONMENT_EVENT_PAYLOADS[input.type];
|
|
@@ -37,6 +38,7 @@ export function buildEnvironmentEvent(input) {
|
|
|
37
38
|
}
|
|
38
39
|
/** Appends one event to the Environment's stream through `writer`. */
|
|
39
40
|
export async function appendEnvironmentEvent(writer, input) {
|
|
41
|
+
checkEntry(`The ${input.type} event's payload`, input.payload, input.maxEntryBytes);
|
|
40
42
|
const seq = await writer.nextSeq(input.environmentId);
|
|
41
43
|
const event = buildEnvironmentEvent({ ...input, seq });
|
|
42
44
|
await writer.insert({ environmentId: input.environmentId, seq, type: input.type, body: event });
|
package/dist/record/index.d.ts
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export { buildEvent, InvalidEventError, type EventInput } from "./envelope.js";
|
|
10
10
|
export { decodeCursor, encodeCursor } from "./cursor.js";
|
|
11
|
-
export { appendEvent, type AppendInput, type RecordWriter } from "./append.js";
|
|
11
|
+
export { RecordEntryTooLargeError, appendEvent, checkEntry, entryBytes, type AppendInput, type RecordWriter, } from "./append.js";
|
|
12
12
|
export { appendEnvironmentEvent, buildEnvironmentEvent, type EnvironmentAppendInput, type EnvironmentRecordWriter, } from "./environment.js";
|
package/dist/record/index.js
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export { buildEvent, InvalidEventError } from "./envelope.js";
|
|
10
10
|
export { decodeCursor, encodeCursor } from "./cursor.js";
|
|
11
|
-
export { appendEvent } from "./append.js";
|
|
11
|
+
export { RecordEntryTooLargeError, appendEvent, checkEntry, entryBytes, } from "./append.js";
|
|
12
12
|
export { appendEnvironmentEvent, buildEnvironmentEvent, } from "./environment.js";
|
package/dist/redact.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export interface ScrubOptions {
|
|
|
8
8
|
readonly counted?: (replacements: number) => void;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
* `value` with each of `secrets` (those of at least 8
|
|
11
|
+
* `value` with each of `secrets` (those of at least `harness.scrubMinChars`, 8 by default) replaced by `[redacted]`. By
|
|
12
12
|
* default also any value under a key such as `token` or `secret`, and inline image data.
|
|
13
13
|
*/
|
|
14
14
|
export declare function scrub(value: unknown, secrets: readonly string[], options?: ScrubOptions): unknown;
|
package/dist/redact.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { hostTuning } from "./tuning.js";
|
|
1
2
|
/**
|
|
2
|
-
* `value` with each of `secrets` (those of at least 8
|
|
3
|
+
* `value` with each of `secrets` (those of at least `harness.scrubMinChars`, 8 by default) replaced by `[redacted]`. By
|
|
3
4
|
* default also any value under a key such as `token` or `secret`, and inline image data.
|
|
4
5
|
*/
|
|
5
6
|
export function scrub(value, secrets, options = {}) {
|
|
6
7
|
// The longest first, so a header value goes whole before the token inside it.
|
|
7
|
-
const sorted = secrets.filter((secret) => secret.length >=
|
|
8
|
+
const sorted = secrets.filter((secret) => secret.length >= hostTuning().harness.scrubMinChars).sort((a, b) => b.length - a.length);
|
|
8
9
|
let replaced = 0;
|
|
9
10
|
const walk = (item) => {
|
|
10
11
|
if (typeof item === "string") {
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
* check (`EgressSandboxes.live`).
|
|
15
15
|
*/
|
|
16
16
|
import type { SessionStore } from "../store/types.js";
|
|
17
|
-
import { EGRESS_TOKEN_AUD, EGRESS_TOKEN_TYP, mintEgressToken, type EgressTokenRequest, type HostClaims, type HostTokenKeyCache, type HostTokenVerdict } from "../tenant/host-token.js";
|
|
17
|
+
import { EGRESS_TOKEN_AUD, EGRESS_TOKEN_TYP, hostTokenTtlSeconds, mintEgressToken, type EgressTokenRequest, type HostClaims, type HostTokenKeyCache, type HostTokenVerdict } from "../tenant/host-token.js";
|
|
18
18
|
export { EGRESS_TOKEN_AUD, EGRESS_TOKEN_TYP, mintEgressToken, type EgressTokenRequest };
|
|
19
|
-
/** The longest lifetime an egress token has: a host token's. */
|
|
20
|
-
export declare const
|
|
19
|
+
/** The longest lifetime an egress token has: a host token's (`keys.hostTokenTtlSeconds`). */
|
|
20
|
+
export declare const egressTokenMaxTtlSeconds: typeof hostTokenTtlSeconds;
|
|
21
21
|
export type EgressClaims = HostClaims;
|
|
22
22
|
export type EgressTokenVerdict = HostTokenVerdict;
|
|
23
23
|
/** Public keys imported by key id; the key row is still read on every verification. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { EGRESS_TOKEN_AUD, EGRESS_TOKEN_TYP,
|
|
1
|
+
import { EGRESS_TOKEN_AUD, EGRESS_TOKEN_TYP, hostTokenTtlSeconds, mintEgressToken, verifyHostToken, } from "../tenant/host-token.js";
|
|
2
2
|
export { EGRESS_TOKEN_AUD, EGRESS_TOKEN_TYP, mintEgressToken };
|
|
3
|
-
/** The longest lifetime an egress token has: a host token's. */
|
|
4
|
-
export const
|
|
3
|
+
/** The longest lifetime an egress token has: a host token's (`keys.hostTokenTtlSeconds`). */
|
|
4
|
+
export const egressTokenMaxTtlSeconds = hostTokenTtlSeconds;
|
|
5
5
|
/** Verifies an egress token of Tenant `tenantId`; refusal reasons are `egress_token_*`. */
|
|
6
6
|
export function verifyEgressToken(store, tenantId, raw, cache = new Map()) {
|
|
7
7
|
return verifyHostToken(store, tenantId, raw, "egress", cache);
|
package/dist/sandbox/join.js
CHANGED
|
@@ -36,6 +36,7 @@ import { isEnvironmentId } from "@nylorun/core/contracts";
|
|
|
36
36
|
import { recoverLostVolume, runPendingSeed } from "../artifacts/disk.js";
|
|
37
37
|
import { recordSetup, setupFile, setupPlanOf, setupState, } from "./setup.js";
|
|
38
38
|
import { mintHostTokens, staleHost, verifyHostToken, } from "../tenant/host-token.js";
|
|
39
|
+
import { JOIN_TOKEN_MAX, POD_UID_PATTERN } from "@nylorun/core/harness-api";
|
|
39
40
|
/** A refused join, renewal or host connection. */
|
|
40
41
|
export class HostAuthError extends Error {
|
|
41
42
|
status;
|
|
@@ -49,7 +50,7 @@ export class HostAuthError extends Error {
|
|
|
49
50
|
this.reason = reason;
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
|
-
const POD_UID =
|
|
53
|
+
const POD_UID = POD_UID_PATTERN;
|
|
53
54
|
const REFUSED = "The join was refused";
|
|
54
55
|
export function sha256Hex(value) {
|
|
55
56
|
return createHash("sha256").update(value).digest("hex");
|
|
@@ -91,7 +92,7 @@ export function hostAuthority(ctx) {
|
|
|
91
92
|
!POD_UID.test(podUid) ||
|
|
92
93
|
typeof joinToken !== "string" ||
|
|
93
94
|
joinToken.length === 0 ||
|
|
94
|
-
joinToken.length >
|
|
95
|
+
joinToken.length > JOIN_TOKEN_MAX ||
|
|
95
96
|
(volumeId !== undefined && (typeof volumeId !== "string" || !POD_UID.test(volumeId))))
|
|
96
97
|
throw new HostAuthError(400, "A join is { sandboxId, podUid, joinToken }");
|
|
97
98
|
const pods = ctx.pods;
|
|
@@ -1,38 +1,17 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sandbox Manager: owns sandbox lifecycle for the Runtime. One workspace per sandbox resource
|
|
3
|
-
* (`sandbox: { id }`, keyed by the sandbox id), or per owning session for a sandbox chosen
|
|
4
|
-
* inline or by the Tenant default (keyed by the session id); created on the first sandbox tool
|
|
5
|
-
* call, stopped after its idle timeout, reattached on the next call. Each session's calls on a
|
|
6
|
-
* workspace run in the order it sends them, and different sessions' calls run at the same time
|
|
7
|
-
* (D66): the sessions of one Environment run their turns at once. Opening, stopping and removing
|
|
8
|
-
* a workspace run alone: a stop or removal waits for the calls running, and calls that come after
|
|
9
|
-
* it wait for it.
|
|
10
|
-
*
|
|
11
|
-
* The manager keeps no timers and reaches no store: it keeps its compute records through a
|
|
12
|
-
* `SandboxRecords` port (the Tenant's `sandboxes` table in core's process, a file in a harness's)
|
|
13
|
-
* and writes its events through `emit`. Its owner drives it: `stopIdle` stops sandboxes idle
|
|
14
|
-
* past their timeout and marks records of compute this process no longer holds as stopped
|
|
15
|
-
* (after a restart); `reconcile` removes workspaces whose owner is gone. `sweep` does both, the
|
|
16
|
-
* reconcile once per process, as the Tenant sweep does in core's process.
|
|
17
|
-
*
|
|
18
|
-
* A session's skills (track R2 M4) are mounted on its workspace, read-only, one folder per
|
|
19
|
-
* version (`/skills/<name>@<hash>/`, D66), before the first call that needs them (`skills.ts`);
|
|
20
|
-
* their bytes come through the `definitionFile` port.
|
|
21
|
-
*/
|
|
22
1
|
import type { EventPayload } from "@nylorun/core/contracts";
|
|
23
|
-
import { type
|
|
2
|
+
import { type SandboxManifest, type SandboxToolName } from "@nylorun/core/define";
|
|
24
3
|
import { type SandboxRecord, type SandboxRecords } from "./records.js";
|
|
25
4
|
import { type SandboxSelection, type SandboxSelectionReport } from "./select.js";
|
|
5
|
+
import { type FolderFiles } from "./skills.js";
|
|
6
|
+
import { type SandboxToolLimits } from "@nylorun/harness";
|
|
26
7
|
import { type DiskAnswer, type DiskOp } from "./disk-fs.js";
|
|
27
8
|
import { type SandboxToolOutcome } from "./tools.js";
|
|
28
|
-
import { type SandboxBackend, type SandboxListing } from "./types.js";
|
|
29
|
-
export { sandboxToolSpec } from "./runtime-tools.js";
|
|
9
|
+
import { type SandboxBackend, type SandboxFileBytes, type SandboxListing } from "./types.js";
|
|
30
10
|
export type { SandboxRecord, SandboxRecords, SandboxState } from "./records.js";
|
|
31
11
|
export interface SandboxSessionRef {
|
|
32
12
|
/** The session whose log records the workspace's events: the owning session. */
|
|
33
13
|
readonly id: string;
|
|
34
14
|
readonly activeTurnId: string | null;
|
|
35
|
-
readonly manifest?: AgentManifest;
|
|
36
15
|
/**
|
|
37
16
|
* The sandbox resource the owning session is attached to. Its workspace is keyed by this id,
|
|
38
17
|
* so every session attached to it shares the files; absent, the workspace is the session's.
|
|
@@ -76,12 +55,6 @@ export interface SandboxManagerOptions {
|
|
|
76
55
|
readonly preference: string | undefined;
|
|
77
56
|
/** Delete sandboxes on close (the Runtime's store does not outlive the process). */
|
|
78
57
|
readonly ephemeral: boolean;
|
|
79
|
-
/**
|
|
80
|
-
* A definition file's bytes by `sha256:<hex>`, for the skills a session's workspace mounts:
|
|
81
|
-
* the Tenant's Object store in core's process, core's answer in a harness (for the run that
|
|
82
|
-
* made the call, `session.claim`). Without it no skills are mounted.
|
|
83
|
-
*/
|
|
84
|
-
readonly definitionFile?: (sha256: string, session: SandboxSessionRef) => Promise<Uint8Array>;
|
|
85
58
|
/** Writes a session event (in core, in its own transaction; in a harness, as a claim). */
|
|
86
59
|
readonly emit: <T extends SandboxEventType>(sessionId: string, turnId: string | null, type: T, payload: EventPayload<T>, meta: SandboxEventMeta) => void | Promise<void>;
|
|
87
60
|
}
|
|
@@ -119,7 +92,11 @@ export declare class SandboxManager {
|
|
|
119
92
|
report(): Promise<SandboxSelectionReport & {
|
|
120
93
|
readonly defaultImage: string;
|
|
121
94
|
}>;
|
|
122
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Runs sandbox operation `toolName` in the session's sandbox, held to `limits`: the harness's
|
|
97
|
+
* sandbox tool limits (`DEFAULT_SANDBOX_TOOL_LIMITS` when it names none).
|
|
98
|
+
*/
|
|
99
|
+
run(session: SandboxSessionRef, sandbox: SandboxManifest | undefined, toolName: SandboxToolName, input: unknown, signal: AbortSignal, limits?: SandboxToolLimits): Promise<SandboxToolOutcome>;
|
|
123
100
|
/**
|
|
124
101
|
* Runs `call` in session `sessionId`'s queue on `live`: after its earlier calls, and after any
|
|
125
102
|
* stop or removal pending, beside other sessions' calls (D66).
|
|
@@ -130,8 +107,8 @@ export declare class SandboxManager {
|
|
|
130
107
|
/** The workspace's handle, opened once for the calls that need it at the same time. */
|
|
131
108
|
private handleOf;
|
|
132
109
|
/**
|
|
133
|
-
* The bytes of one file in the session's sandbox, for `save_artifact`
|
|
134
|
-
* as its tool calls: `missing` when there is no such file, a failed outcome when the sandbox
|
|
110
|
+
* The bytes of one file in the session's sandbox, for our engine's `save_artifact` and its
|
|
111
|
+
* outputs folder (`files.read`), in the same queue as its tool calls: `missing` when there is no such file, a failed outcome when the sandbox
|
|
135
112
|
* cannot open or the file is larger than `maxBytes`. Relative paths resolve in the workspace.
|
|
136
113
|
*/
|
|
137
114
|
readBytes(session: SandboxSessionRef, sandbox: SandboxManifest | undefined, path: string, maxBytes: number, signal: AbortSignal): Promise<{
|
|
@@ -145,8 +122,20 @@ export declare class SandboxManager {
|
|
|
145
122
|
kind: "failed";
|
|
146
123
|
}>>;
|
|
147
124
|
/**
|
|
148
|
-
*
|
|
149
|
-
* the same queue as its tool calls
|
|
125
|
+
* Writes `body` to one file of the session's sandbox, as it comes, for our engine's
|
|
126
|
+
* `read_artifact` with `path` (protocol 15), in the same queue as its tool calls: its folders
|
|
127
|
+
* are made first, and a file there is replaced. Relative paths resolve in the workspace.
|
|
128
|
+
*/
|
|
129
|
+
writeBytes(session: SandboxSessionRef, sandbox: SandboxManifest | undefined, path: string, body: SandboxFileBytes, signal: AbortSignal): Promise<{
|
|
130
|
+
kind: "written";
|
|
131
|
+
path: string;
|
|
132
|
+
size: number;
|
|
133
|
+
} | Extract<SandboxToolOutcome, {
|
|
134
|
+
kind: "failed";
|
|
135
|
+
}>>;
|
|
136
|
+
/**
|
|
137
|
+
* The files under directory `dir` of the session's sandbox, for our engine's outputs folder
|
|
138
|
+
* (`files.list`, protocol 15), in the same queue as its tool calls. `missing` when the sandbox was never created (nothing is
|
|
150
139
|
* started to look) or `dir` is not a directory. Relative paths resolve in the workspace.
|
|
151
140
|
*/
|
|
152
141
|
listFiles(session: SandboxSessionRef, sandbox: SandboxManifest | undefined, dir: string, maxEntries: number, signal: AbortSignal): Promise<{
|
|
@@ -171,14 +160,25 @@ export declare class SandboxManager {
|
|
|
171
160
|
/** The session's live sandbox entry and spec, or why it cannot run here. */
|
|
172
161
|
private prepare;
|
|
173
162
|
private execute;
|
|
163
|
+
/**
|
|
164
|
+
* The workspace's handle, opened when there is none. A start that fails is recorded as stopped
|
|
165
|
+
* and answered as a failed outcome: nothing ran yet, so it is definite, not uncertain.
|
|
166
|
+
*/
|
|
167
|
+
private started;
|
|
174
168
|
private executeOpen;
|
|
175
169
|
/**
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
170
|
+
* Writes `files` (path in `folder` to `sha256:<hex>`) to `folder` of the session's sandbox,
|
|
171
|
+
* read-only, each one's bytes from `read`, in the session's queue (protocol 15: the harness
|
|
172
|
+
* decides which folders, and when). A folder the open handle already holds is `present` without
|
|
173
|
+
* an exec; calls that need one folder at once share its mount. A failed outcome when the sandbox
|
|
174
|
+
* cannot start or the folder cannot be written; it is not marked mounted then, so the next call
|
|
175
|
+
* tries again. A reopened handle holds none.
|
|
180
176
|
*/
|
|
181
|
-
|
|
177
|
+
mountFolder(session: SandboxSessionRef, sandbox: SandboxManifest | undefined, folder: string, files: FolderFiles, read: (sha256: string) => SandboxFileBytes | Promise<SandboxFileBytes>, signal: AbortSignal): Promise<{
|
|
178
|
+
kind: "mounted" | "present";
|
|
179
|
+
} | Extract<SandboxToolOutcome, {
|
|
180
|
+
kind: "failed";
|
|
181
|
+
}>>;
|
|
182
182
|
private open;
|
|
183
183
|
private stop;
|
|
184
184
|
private record;
|