@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/sandbox/tools.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The six
|
|
3
|
-
*
|
|
2
|
+
* The six sandbox operations, implemented once over `SandboxHandle` so every backend behaves the
|
|
3
|
+
* same, held to the harness's sandbox tool limits (`SandboxToolLimits`, the numbers its tools'
|
|
4
|
+
* schemas name). Expected problems are returned as failed outcomes; only infrastructure errors
|
|
5
|
+
* throw.
|
|
4
6
|
*/
|
|
5
7
|
import { posix } from "node:path";
|
|
6
8
|
import { SANDBOX_WORKSPACE } from "@nylorun/core/define";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
9
|
+
import { DEFAULT_SANDBOX_TOOL_LIMITS } from "@nylorun/harness";
|
|
10
|
+
import { hostTuning } from "../tuning.js";
|
|
11
|
+
/**
|
|
12
|
+
* How long a command the Runtime runs for itself in a sandbox may take (making a file's folder,
|
|
13
|
+
* mounting a skill, a tool's own helper command): `harness.helperCommandTimeoutMs`.
|
|
14
|
+
*/
|
|
15
|
+
export const helperCommandTimeoutMs = () => hostTuning().harness.helperCommandTimeoutMs;
|
|
14
16
|
export function quote(value) {
|
|
15
17
|
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
16
18
|
}
|
|
@@ -24,7 +26,7 @@ export function resolveSandboxPath(path, workspace = SANDBOX_WORKSPACE) {
|
|
|
24
26
|
return posix.normalize(path.startsWith("/") ? path : posix.join(workspace, path));
|
|
25
27
|
}
|
|
26
28
|
/** Keep the head and tail of long output so the model sees both the start and the error. */
|
|
27
|
-
export function truncateMiddle(value, limit =
|
|
29
|
+
export function truncateMiddle(value, limit = DEFAULT_SANDBOX_TOOL_LIMITS.outputChars) {
|
|
28
30
|
if (value.length <= limit)
|
|
29
31
|
return { text: value, truncated: false };
|
|
30
32
|
const half = Math.floor(limit / 2);
|
|
@@ -39,20 +41,21 @@ const failed = (code, message) => ({
|
|
|
39
41
|
code,
|
|
40
42
|
message,
|
|
41
43
|
});
|
|
42
|
-
export async function runSandboxTool(handle, name, input, signal, report,
|
|
44
|
+
export async function runSandboxTool(handle, name, input, signal, report, limits = DEFAULT_SANDBOX_TOOL_LIMITS,
|
|
43
45
|
/** Variables every command gets (R2c): secret names set to the sentinel, plain values. */
|
|
44
46
|
environment) {
|
|
47
|
+
const lineOf = (line) => (line.length > limits.lineChars ? `${line.slice(0, limits.lineChars)}…` : line);
|
|
45
48
|
const workspace = handle.workspace ?? SANDBOX_WORKSPACE;
|
|
46
49
|
const resolvePath = (path) => resolveSandboxPath(path, workspace);
|
|
47
|
-
const exec = (command, timeoutMs =
|
|
50
|
+
const exec = (command, timeoutMs = helperCommandTimeoutMs()) => handle.exec({ command, cwd: workspace, timeoutMs, ...(environment ? { env: environment } : {}) }, signal);
|
|
48
51
|
switch (name) {
|
|
49
52
|
case "bash": {
|
|
50
53
|
const command = String(input.command);
|
|
51
|
-
const timeout = (input.timeout ??
|
|
54
|
+
const timeout = Math.min(input.timeout ?? limits.defaultTimeoutS, limits.maxTimeoutS) * 1000;
|
|
52
55
|
const result = await exec(command, timeout);
|
|
53
56
|
report({ command, exitCode: result.exitCode, killed: result.killed });
|
|
54
|
-
const stdout = truncateMiddle(result.stdout);
|
|
55
|
-
const stderr = truncateMiddle(result.stderr);
|
|
57
|
+
const stdout = truncateMiddle(result.stdout, limits.outputChars);
|
|
58
|
+
const stderr = truncateMiddle(result.stderr, limits.outputChars);
|
|
56
59
|
return {
|
|
57
60
|
kind: "completed",
|
|
58
61
|
output: {
|
|
@@ -76,14 +79,11 @@ environment) {
|
|
|
76
79
|
if (lines.at(-1) === "")
|
|
77
80
|
lines.pop();
|
|
78
81
|
const start = (input.offset ?? 1) - 1;
|
|
79
|
-
const limit = input.limit ??
|
|
82
|
+
const limit = Math.min(input.limit ?? limits.readLines, limits.maxReadLines);
|
|
80
83
|
const slice = lines.slice(start, start + limit);
|
|
81
84
|
const width = String(start + slice.length).length;
|
|
82
85
|
const text = slice
|
|
83
|
-
.map((line, index) => {
|
|
84
|
-
const clipped = line.length > LINE_LIMIT ? `${line.slice(0, LINE_LIMIT)}…` : line;
|
|
85
|
-
return `${String(start + index + 1).padStart(width, " ")}\t${clipped}`;
|
|
86
|
-
})
|
|
86
|
+
.map((line, index) => `${String(start + index + 1).padStart(width, " ")}\t${lineOf(line)}`)
|
|
87
87
|
.join("\n");
|
|
88
88
|
const remaining = lines.length - (start + slice.length);
|
|
89
89
|
return {
|
|
@@ -124,7 +124,7 @@ environment) {
|
|
|
124
124
|
return { kind: "completed", output: { path, replacements: input.replace_all === true ? count : 1 } };
|
|
125
125
|
}
|
|
126
126
|
case "grep": {
|
|
127
|
-
const max = input.max_results ??
|
|
127
|
+
const max = Math.min(input.max_results ?? limits.grepResults, limits.maxGrepResults);
|
|
128
128
|
const target = input.path ? String(input.path) : ".";
|
|
129
129
|
const flags = ["-rnE", ...(input.ignore_case ? ["-i"] : [])];
|
|
130
130
|
const include = input.glob ? ` --include=${quote(String(input.glob))}` : "";
|
|
@@ -137,7 +137,7 @@ environment) {
|
|
|
137
137
|
return result.stderr.trim()
|
|
138
138
|
? failed("sandbox.grep_failed", result.stderr.trim())
|
|
139
139
|
: { kind: "completed", output: "No matches." };
|
|
140
|
-
const shown = lines.slice(0, max).map(
|
|
140
|
+
const shown = lines.slice(0, max).map(lineOf);
|
|
141
141
|
return {
|
|
142
142
|
kind: "completed",
|
|
143
143
|
output: lines.length > max ? `${shown.join("\n")}\n… more matches omitted; narrow the search.` : shown.join("\n"),
|
|
@@ -146,7 +146,7 @@ environment) {
|
|
|
146
146
|
case "glob": {
|
|
147
147
|
const root = resolvePath(input.path ? String(input.path) : ".");
|
|
148
148
|
const pattern = String(input.pattern);
|
|
149
|
-
const command = `find ${quote(root)} -type f -not -path '*/.git/*' 2>/dev/null | head -n ${
|
|
149
|
+
const command = `find ${quote(root)} -type f -not -path '*/.git/*' 2>/dev/null | head -n ${limits.globScan}`;
|
|
150
150
|
report({ command });
|
|
151
151
|
const result = await exec(command);
|
|
152
152
|
const byBasename = !pattern.includes("/");
|
|
@@ -157,7 +157,7 @@ environment) {
|
|
|
157
157
|
const relative = posix.relative(root, file);
|
|
158
158
|
if (posix.matchesGlob(byBasename ? posix.basename(relative) : relative, pattern)) {
|
|
159
159
|
matches.push(file);
|
|
160
|
-
if (matches.length >
|
|
160
|
+
if (matches.length > limits.globResults)
|
|
161
161
|
break;
|
|
162
162
|
}
|
|
163
163
|
}
|
|
@@ -166,8 +166,8 @@ environment) {
|
|
|
166
166
|
matches.sort();
|
|
167
167
|
return {
|
|
168
168
|
kind: "completed",
|
|
169
|
-
output: matches.length >
|
|
170
|
-
? `${matches.slice(0,
|
|
169
|
+
output: matches.length > limits.globResults
|
|
170
|
+
? `${matches.slice(0, limits.globResults).join("\n")}\n… more files omitted; narrow the pattern.`
|
|
171
171
|
: matches.join("\n"),
|
|
172
172
|
};
|
|
173
173
|
}
|
package/dist/sandbox/types.d.ts
CHANGED
|
@@ -51,6 +51,10 @@ export interface ExecResult {
|
|
|
51
51
|
readonly killed: boolean;
|
|
52
52
|
readonly timedOut: boolean;
|
|
53
53
|
}
|
|
54
|
+
/** A file's bytes: whole, or as chunks to write as they come. */
|
|
55
|
+
export type SandboxFileBytes = Uint8Array | AsyncIterable<Uint8Array>;
|
|
56
|
+
/** `content` whole, for a backend that writes a file at once. */
|
|
57
|
+
export declare function wholeBytes(content: SandboxFileBytes): Promise<Uint8Array>;
|
|
54
58
|
export interface SandboxHandle {
|
|
55
59
|
/** The directory tools run in and resolve relative paths against. Default: `/workspace`. */
|
|
56
60
|
readonly workspace?: string;
|
|
@@ -61,7 +65,7 @@ export interface SandboxHandle {
|
|
|
61
65
|
readFile(path: string): Promise<string | undefined>;
|
|
62
66
|
/**
|
|
63
67
|
* The file's bytes, or undefined when it does not exist; refuses one larger than `maxBytes`
|
|
64
|
-
* (`SandboxFileTooLargeError`). For `save_artifact
|
|
68
|
+
* (`SandboxFileTooLargeError`). For `save_artifact` and the export, which keep binary files intact.
|
|
65
69
|
*/
|
|
66
70
|
readBytes?(path: string, maxBytes: number): Promise<Uint8Array | undefined>;
|
|
67
71
|
/**
|
|
@@ -70,8 +74,11 @@ export interface SandboxHandle {
|
|
|
70
74
|
* directory. Stops after `maxEntries + 1` files (`truncated`). For the turn-end export (F8.2).
|
|
71
75
|
*/
|
|
72
76
|
listFiles?(dir: string, maxEntries: number): Promise<SandboxListing | undefined>;
|
|
73
|
-
/**
|
|
74
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Text is written as UTF-8, bytes as they are, chunks as they come (a skill's file, which may
|
|
79
|
+
* be too large to hold at once). Parent directories must already exist.
|
|
80
|
+
*/
|
|
81
|
+
writeFile(path: string, content: string | SandboxFileBytes): Promise<void>;
|
|
75
82
|
/** Release compute; files persist. */
|
|
76
83
|
stop(): Promise<void>;
|
|
77
84
|
/**
|
package/dist/sandbox/types.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/** `content` whole, for a backend that writes a file at once. */
|
|
2
|
+
export async function wholeBytes(content) {
|
|
3
|
+
if (content instanceof Uint8Array)
|
|
4
|
+
return content;
|
|
5
|
+
const chunks = [];
|
|
6
|
+
for await (const chunk of content)
|
|
7
|
+
chunks.push(chunk);
|
|
8
|
+
return Buffer.concat(chunks);
|
|
9
|
+
}
|
|
1
10
|
/** A sandbox file read with `readBytes` is larger than the caller allows. */
|
|
2
11
|
export class SandboxFileTooLargeError extends Error {
|
|
3
12
|
path;
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { type Sql } from "postgres";
|
|
2
2
|
export type PostgresClient = Sql;
|
|
3
3
|
export interface PostgresClientOptions {
|
|
4
|
-
/** Pool size. Default 10. */
|
|
4
|
+
/** Pool size. Default `postgres.poolSize` (Host tuning, 10). */
|
|
5
5
|
max?: number;
|
|
6
|
-
/** Seconds before an idle connection closes. Default 30. */
|
|
6
|
+
/** Seconds before an idle connection closes. Default `postgres.idleTimeoutSeconds` (30). */
|
|
7
7
|
idleTimeoutSeconds?: number;
|
|
8
|
-
/** Seconds to wait for a connection. Default 10. */
|
|
8
|
+
/** Seconds to wait for a connection. Default `postgres.connectTimeoutSeconds` (10). */
|
|
9
9
|
connectTimeoutSeconds?: number;
|
|
10
10
|
/** `application_name` on every connection. Default `nylorun-runtime`. */
|
|
11
11
|
applicationName?: string;
|
|
12
12
|
/**
|
|
13
13
|
* `statement_timeout`: a statement running or waiting for a lock longer fails. Default
|
|
14
|
-
* 60 s; 0 turns it off. Migrations lift it (`lockMigrations` in `migrate.ts`).
|
|
14
|
+
* `postgres.statementTimeoutMs` (60 s); 0 turns it off. Migrations lift it (`lockMigrations` in `migrate.ts`).
|
|
15
15
|
*/
|
|
16
16
|
statementTimeoutMs?: number;
|
|
17
17
|
/**
|
|
18
18
|
* `idle_in_transaction_session_timeout`: a transaction left idle this long is ended and its
|
|
19
|
-
* connection closed, releasing its locks. Default 60 s; 0
|
|
19
|
+
* connection closed, releasing its locks. Default `postgres.idleInTransactionTimeoutMs` (60 s); 0
|
|
20
|
+
* turns it off.
|
|
20
21
|
*/
|
|
21
22
|
idleInTransactionTimeoutMs?: number;
|
|
22
23
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import postgres, {} from "postgres";
|
|
2
|
+
import { hostTuning } from "../../tuning.js";
|
|
2
3
|
/**
|
|
3
4
|
* Opens a connection pool on the Tenant's database, for its Session Store and the Tenant
|
|
4
5
|
* bootstrap (`tenant.ts`). Stores never end it, so the caller calls `client.end()` at
|
|
@@ -13,15 +14,16 @@ import postgres, {} from "postgres";
|
|
|
13
14
|
* not hold a connection forever: both are bounded by default.
|
|
14
15
|
*/
|
|
15
16
|
export function createPostgresClient(url, options = {}) {
|
|
17
|
+
const tuning = hostTuning().postgres;
|
|
16
18
|
return postgres(url, {
|
|
17
|
-
max: options.max ??
|
|
18
|
-
idle_timeout: options.idleTimeoutSeconds ??
|
|
19
|
-
connect_timeout: options.connectTimeoutSeconds ??
|
|
19
|
+
max: options.max ?? tuning.poolSize,
|
|
20
|
+
idle_timeout: options.idleTimeoutSeconds ?? tuning.idleTimeoutSeconds,
|
|
21
|
+
connect_timeout: options.connectTimeoutSeconds ?? tuning.connectTimeoutSeconds,
|
|
20
22
|
onnotice: () => { },
|
|
21
23
|
connection: {
|
|
22
24
|
application_name: options.applicationName ?? "nylorun-runtime",
|
|
23
|
-
statement_timeout: options.statementTimeoutMs ??
|
|
24
|
-
idle_in_transaction_session_timeout: options.idleInTransactionTimeoutMs ??
|
|
25
|
+
statement_timeout: options.statementTimeoutMs ?? tuning.statementTimeoutMs,
|
|
26
|
+
idle_in_transaction_session_timeout: options.idleInTransactionTimeoutMs ?? tuning.idleInTransactionTimeoutMs,
|
|
25
27
|
},
|
|
26
28
|
});
|
|
27
29
|
}
|
|
@@ -58,17 +60,18 @@ function connectionOf(source) {
|
|
|
58
60
|
}
|
|
59
61
|
/** Separate, bounded pool for read projections; inherits the Tenant connection credentials. */
|
|
60
62
|
export function createPostgresReadClient(source) {
|
|
63
|
+
const tuning = hostTuning().postgres;
|
|
61
64
|
const options = {
|
|
62
65
|
...connectionOf(source),
|
|
63
|
-
max:
|
|
64
|
-
idle_timeout:
|
|
65
|
-
connect_timeout:
|
|
66
|
+
max: tuning.readPoolSize,
|
|
67
|
+
idle_timeout: tuning.idleTimeoutSeconds,
|
|
68
|
+
connect_timeout: tuning.readConnectTimeoutSeconds,
|
|
66
69
|
onnotice() { },
|
|
67
70
|
connection: {
|
|
68
71
|
...source.options.connection,
|
|
69
72
|
application_name: "nylorun-reads",
|
|
70
|
-
statement_timeout:
|
|
71
|
-
idle_in_transaction_session_timeout:
|
|
73
|
+
statement_timeout: tuning.readStatementTimeoutMs,
|
|
74
|
+
idle_in_transaction_session_timeout: tuning.readStatementTimeoutMs,
|
|
72
75
|
default_transaction_read_only: true,
|
|
73
76
|
},
|
|
74
77
|
};
|
|
@@ -87,7 +90,7 @@ export function createPostgresListenClient(source, handlers) {
|
|
|
87
90
|
max: 1,
|
|
88
91
|
idle_timeout: 0,
|
|
89
92
|
max_lifetime: null,
|
|
90
|
-
connect_timeout:
|
|
93
|
+
connect_timeout: hostTuning().postgres.connectTimeoutSeconds,
|
|
91
94
|
fetch_types: false,
|
|
92
95
|
onnotice() { },
|
|
93
96
|
onnotify: handlers.onNotify,
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
* exists exactly when what it announces committed.
|
|
12
12
|
* - **Follow.** `followControlSignals` holds one connection of its own that LISTENs (a pooled
|
|
13
13
|
* connection cannot). Each notification reads back the signals of the last
|
|
14
|
-
* `
|
|
15
|
-
* every `pollMs
|
|
14
|
+
* `postgres.controlWindowSeconds` (Host tuning) and delivers those this follower has not delivered yet. So does a poll
|
|
15
|
+
* every `pollMs` (`postgres.controlPollMs`), and every LISTEN after a reconnect: Postgres does not queue notifications
|
|
16
16
|
* for a session that is not connected, and the rows are what catches up. Ids are never read
|
|
17
17
|
* as a cursor: they are allocated at insert and commit out of order, so a later id can be
|
|
18
18
|
* visible first.
|
|
@@ -23,14 +23,10 @@
|
|
|
23
23
|
*/
|
|
24
24
|
import { gte, lt, sql } from "drizzle-orm";
|
|
25
25
|
import { createPostgresListenClient } from "./connect.js";
|
|
26
|
+
import { hostTuning } from "../../tuning.js";
|
|
26
27
|
import { controlSignals } from "./schema.js";
|
|
27
28
|
/** The channel every signal is notified on. */
|
|
28
29
|
export const CONTROL_CHANNEL = "nylorun_control";
|
|
29
|
-
/** How far back a read-back looks. Longer than the poll, so a missed notification is caught. */
|
|
30
|
-
const WINDOW_SECONDS = 120;
|
|
31
|
-
const POLL_MS = 5000;
|
|
32
|
-
const RETRY_MIN_MS = 100;
|
|
33
|
-
const RETRY_MAX_MS = 5000;
|
|
34
30
|
const SIGNAL = {
|
|
35
31
|
id: controlSignals.id,
|
|
36
32
|
kind: controlSignals.kind,
|
|
@@ -69,7 +65,11 @@ export async function pruneSignals(db, before) {
|
|
|
69
65
|
* start is fixed; the first LISTEN may still be retrying, and the poll covers it meanwhile.
|
|
70
66
|
*/
|
|
71
67
|
export async function followControlSignals(source, db, onSignal, options = {}) {
|
|
72
|
-
const
|
|
68
|
+
const tuning = hostTuning().postgres;
|
|
69
|
+
const pollMs = options.pollMs ?? tuning.controlPollMs;
|
|
70
|
+
// How far back a read-back looks: longer than the poll, so a missed notification is caught.
|
|
71
|
+
const windowSeconds = tuning.controlWindowSeconds;
|
|
72
|
+
const { minMs: retryMinMs, maxMs: retryMaxMs } = tuning.controlRetry;
|
|
73
73
|
const onError = options.onError ?? (() => { });
|
|
74
74
|
// Drizzle leaves timestamps to its column types, so a raw read of one is text.
|
|
75
75
|
const [start] = await db.execute(sql `SELECT clock_timestamp()::text AS now`);
|
|
@@ -78,7 +78,7 @@ export async function followControlSignals(source, db, onSignal, options = {}) {
|
|
|
78
78
|
const delivered = new Map();
|
|
79
79
|
let stopped = false;
|
|
80
80
|
let retry;
|
|
81
|
-
let delay =
|
|
81
|
+
let delay = retryMinMs;
|
|
82
82
|
let draining;
|
|
83
83
|
let again = false;
|
|
84
84
|
const client = createPostgresListenClient(source, {
|
|
@@ -98,14 +98,14 @@ export async function followControlSignals(source, db, onSignal, options = {}) {
|
|
|
98
98
|
void listen();
|
|
99
99
|
}, delay);
|
|
100
100
|
retry.unref();
|
|
101
|
-
delay = Math.min(delay * 2,
|
|
101
|
+
delay = Math.min(delay * 2, retryMaxMs);
|
|
102
102
|
}
|
|
103
103
|
async function listen() {
|
|
104
104
|
if (stopped)
|
|
105
105
|
return;
|
|
106
106
|
try {
|
|
107
107
|
await client.unsafe(`LISTEN ${CONTROL_CHANNEL}`);
|
|
108
|
-
delay =
|
|
108
|
+
delay = retryMinMs;
|
|
109
109
|
drain();
|
|
110
110
|
}
|
|
111
111
|
catch (error) {
|
|
@@ -129,7 +129,7 @@ export async function followControlSignals(source, db, onSignal, options = {}) {
|
|
|
129
129
|
const rows = await db
|
|
130
130
|
.select(SIGNAL)
|
|
131
131
|
.from(controlSignals)
|
|
132
|
-
.where(gte(controlSignals.createdAt, sql `greatest(${since}::timestamptz, clock_timestamp() - make_interval(secs => ${
|
|
132
|
+
.where(gte(controlSignals.createdAt, sql `greatest(${since}::timestamptz, clock_timestamp() - make_interval(secs => ${windowSeconds}))`))
|
|
133
133
|
.orderBy(controlSignals.id);
|
|
134
134
|
for (const row of rows)
|
|
135
135
|
deliver(row);
|
|
@@ -160,7 +160,7 @@ export async function followControlSignals(source, db, onSignal, options = {}) {
|
|
|
160
160
|
}
|
|
161
161
|
/** A row a read-back can still return is younger than the window: keep twice that. */
|
|
162
162
|
function forgetOld() {
|
|
163
|
-
const before = Date.now() - 2 *
|
|
163
|
+
const before = Date.now() - 2 * windowSeconds * 1000;
|
|
164
164
|
for (const [id, at] of delivered)
|
|
165
165
|
if (at < before)
|
|
166
166
|
delivered.delete(id);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- Protocol 15: the harness boundary. `read_artifact` and `save_artifact` are our harness's own
|
|
2
|
+
-- tools, no longer the Runtime's: the manifest schema refuses a pinned `runtime` block that holds
|
|
3
|
+
-- them. A fresh start for the sessions that pinned one (every agent session since protocol 12):
|
|
4
|
+
-- each is closed (`session_closed`) and its history stays readable. Workflow sessions pin no
|
|
5
|
+
-- `runtime` block and carry over.
|
|
6
|
+
UPDATE "nylorun"."sessions" SET "body" = ("body"::jsonb || '{"closedReason":"protocol_15"}'::jsonb)::json
|
|
7
|
+
WHERE nylorun.doc("body") ->> 'closedReason' IS NULL
|
|
8
|
+
AND jsonb_path_exists(
|
|
9
|
+
nylorun.doc("body") -> 'manifest' -> 'runtime' -> 'tools',
|
|
10
|
+
'$[*] ? (@.name == "read_artifact" || @.name == "save_artifact")'
|
|
11
|
+
);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- Protocol 15: the harness writes the model's instructions and defines the sandbox and skill
|
|
2
|
+
-- tools, so the manifest schema refuses a pinned `runtime` block, and a session pins its
|
|
3
|
+
-- definition as registered. A fresh start for the agent sessions that still pinned one (opened
|
|
4
|
+
-- by a build of protocol 15 before this change, on the root agent or an agent it uses as a tool):
|
|
5
|
+
-- each is closed (`session_closed`) and its history stays readable. The others carry over.
|
|
6
|
+
UPDATE "nylorun"."sessions" SET "body" = ("body"::jsonb || '{"closedReason":"protocol_15"}'::jsonb)::json
|
|
7
|
+
WHERE nylorun.doc("body") ->> 'closedReason' IS NULL
|
|
8
|
+
AND (
|
|
9
|
+
jsonb_path_exists(nylorun.doc("body") -> 'manifest', 'lax $.runtime')
|
|
10
|
+
OR jsonb_path_exists(nylorun.doc("body") -> 'manifest', 'lax $.tools[*].agent.runtime')
|
|
11
|
+
);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
-- Protocol 15: the harness names a session's MCP tools and decides which to defer, so the
|
|
2
|
+
-- session pins what its servers listed, raw (`snapshotSchemaVersion` 2), and every MCP call names
|
|
3
|
+
-- its tool by `{server, tool}`. A session that pinned the former snapshot (model-facing names,
|
|
4
|
+
-- deferral decided by core) cannot run its next turn: each still open is closed
|
|
5
|
+
-- (`session_closed`) and its history stays readable. The others carry over.
|
|
6
|
+
UPDATE "nylorun"."sessions" SET "body" = ("body"::jsonb || '{"closedReason":"protocol_15"}'::jsonb)::json
|
|
7
|
+
WHERE nylorun.doc("body") ->> 'closedReason' IS NULL
|
|
8
|
+
AND nylorun.doc("body") -> 'mcpSnapshot' ->> 'snapshotSchemaVersion' = '1';
|
|
@@ -197,6 +197,34 @@
|
|
|
197
197
|
"when": 1791997067694,
|
|
198
198
|
"tag": "0027_environment_image_digest",
|
|
199
199
|
"breakpoints": true
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"idx": 28,
|
|
203
|
+
"version": "7",
|
|
204
|
+
"when": 1792084466204,
|
|
205
|
+
"tag": "0028_artifact_write_keys",
|
|
206
|
+
"breakpoints": true
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"idx": 29,
|
|
210
|
+
"version": "7",
|
|
211
|
+
"when": 1792086180701,
|
|
212
|
+
"tag": "0029_protocol_15",
|
|
213
|
+
"breakpoints": true
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"idx": 30,
|
|
217
|
+
"version": "7",
|
|
218
|
+
"when": 1792091020175,
|
|
219
|
+
"tag": "0030_protocol_15_runtime_block",
|
|
220
|
+
"breakpoints": true
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"idx": 31,
|
|
224
|
+
"version": "7",
|
|
225
|
+
"when": 1792094620175,
|
|
226
|
+
"tag": "0031_protocol_15_mcp_snapshot",
|
|
227
|
+
"breakpoints": true
|
|
200
228
|
}
|
|
201
229
|
]
|
|
202
230
|
}
|
|
@@ -96,7 +96,7 @@ export async function assertCurrentLayout(q) {
|
|
|
96
96
|
if (row?.versioned)
|
|
97
97
|
throw openError("database-layout-old", "The database was created by a pre-release build of one Tenant per database, whose " +
|
|
98
98
|
"migrations this release replaces. It is never changed: point the Runtime at a new " +
|
|
99
|
-
"database (locally, `nylorun reset` and then `nylorun start`).");
|
|
99
|
+
"database (locally, `nylorun local reset` and then `nylorun start`).");
|
|
100
100
|
}
|
|
101
101
|
/**
|
|
102
102
|
* The database's schema version: the number of migrations its journal records, or undefined
|
|
@@ -4,12 +4,14 @@ import { and, asc, desc, eq, exists, gt, inArray, isNull, lt, ne, or, sql, } fro
|
|
|
4
4
|
import { isArtifactId } from "@nylorun/core/compatibility";
|
|
5
5
|
import { readCursor } from "../../reads/cursor.js";
|
|
6
6
|
import { fail } from "../../tenant/http.js";
|
|
7
|
+
import { limitsInForce, readTenantLimits } from "../../tenant/limits.js";
|
|
7
8
|
import { artifactView } from "../../artifacts/service.js";
|
|
8
9
|
import { sandboxWorkspaceKey } from "../../sandbox/records.js";
|
|
9
10
|
import { database, driverError } from "./db.js";
|
|
10
11
|
import { createPostgresReadClient } from "./connect.js";
|
|
12
|
+
import { hostTuning } from "../../tuning.js";
|
|
11
13
|
import { toolCallDuration, toolCallStatus } from "../../harness-api/tool-status.js";
|
|
12
|
-
import { effects, artifacts, modelUsage, environments, sandboxes, sessions, sessionEvents, } from "./schema.js";
|
|
14
|
+
import { effects, artifacts, modelUsage, environments, sandboxes, sessions, sessionEvents, tenantSettings, } from "./schema.js";
|
|
13
15
|
const sessionFields = {
|
|
14
16
|
id: sessions.id,
|
|
15
17
|
agentId: sessions.agentId,
|
|
@@ -64,6 +66,7 @@ function publicToolCall(body) {
|
|
|
64
66
|
toolName: request.toolName ?? null,
|
|
65
67
|
kind: body.toolKind ?? null,
|
|
66
68
|
server: body.server ?? null,
|
|
69
|
+
tool: body.tool ?? null,
|
|
67
70
|
skill: body.skill ?? null,
|
|
68
71
|
plugin: body.plugin ?? null,
|
|
69
72
|
status,
|
|
@@ -118,7 +121,7 @@ export function createPostgresReadStore(source, tenantId) {
|
|
|
118
121
|
return row.id;
|
|
119
122
|
}
|
|
120
123
|
return {
|
|
121
|
-
close: () => pool.end({ timeout:
|
|
124
|
+
close: () => pool.end({ timeout: hostTuning().postgres.readCloseTimeoutSeconds }),
|
|
122
125
|
artifacts: (filters, page, access) => read(async (tx) => {
|
|
123
126
|
if (filters.sessionId !== undefined)
|
|
124
127
|
await requireSession(tx, filters.sessionId, access);
|
|
@@ -315,6 +318,10 @@ export function createPostgresReadStore(source, tenantId) {
|
|
|
315
318
|
.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
319
|
.orderBy(asc(environments.id))
|
|
317
320
|
.limit(page.limit + 1);
|
|
321
|
+
const tenantLimits = await readTenantLimits({
|
|
322
|
+
getSetting: async (setting) => (await tx.select({ value: tenantSettings.value }).from(tenantSettings).where(eq(tenantSettings.key, setting)))[0]
|
|
323
|
+
?.value,
|
|
324
|
+
});
|
|
318
325
|
const items = [];
|
|
319
326
|
for (const row of rows.slice(0, page.limit)) {
|
|
320
327
|
const [related] = await tx
|
|
@@ -337,6 +344,7 @@ export function createPostgresReadStore(source, tenantId) {
|
|
|
337
344
|
...(row.manifestName === null ? {} : { manifestName: row.manifestName }),
|
|
338
345
|
...(row.manifestVersion === null ? {} : { manifestVersion: row.manifestVersion }),
|
|
339
346
|
...(row.manifestHash === null ? {} : { manifestHash: row.manifestHash }),
|
|
347
|
+
limits: limitsInForce(tenantLimits, row.recipe.limits),
|
|
340
348
|
...(row.forkedFrom ? { forkedFrom: row.forkedFrom } : {}),
|
|
341
349
|
version: row.version,
|
|
342
350
|
appliedVersion: row.appliedVersion,
|
|
@@ -3348,6 +3348,25 @@ export declare const artifactVersions: import("drizzle-orm/pg-core").PgTableWith
|
|
|
3348
3348
|
}, {}, {
|
|
3349
3349
|
pgColumnBuilderBrand: 'PgCustomColumnBuilderBrand';
|
|
3350
3350
|
}>;
|
|
3351
|
+
writeKey: import("drizzle-orm/pg-core").PgColumn<{
|
|
3352
|
+
name: "writeKey";
|
|
3353
|
+
tableName: "artifact_versions";
|
|
3354
|
+
dataType: "custom";
|
|
3355
|
+
columnType: "PgCustomColumn";
|
|
3356
|
+
data: string;
|
|
3357
|
+
driverParam: string;
|
|
3358
|
+
notNull: false;
|
|
3359
|
+
hasDefault: false;
|
|
3360
|
+
isPrimaryKey: false;
|
|
3361
|
+
isAutoincrement: false;
|
|
3362
|
+
hasRuntimeDefault: false;
|
|
3363
|
+
enumValues: undefined;
|
|
3364
|
+
baseColumn: never;
|
|
3365
|
+
identity: undefined;
|
|
3366
|
+
generated: undefined;
|
|
3367
|
+
}, {}, {
|
|
3368
|
+
pgColumnBuilderBrand: 'PgCustomColumnBuilderBrand';
|
|
3369
|
+
}>;
|
|
3351
3370
|
};
|
|
3352
3371
|
dialect: 'pg';
|
|
3353
3372
|
}>;
|
|
@@ -409,8 +409,15 @@ export const artifactVersions = nylorun.table("artifact_versions", {
|
|
|
409
409
|
contentType: text().notNull(),
|
|
410
410
|
source: text({ enum: ["upload", "engine", "export", "snapshot"] }).notNull(),
|
|
411
411
|
createdAt: textC().notNull(),
|
|
412
|
+
/**
|
|
413
|
+
* The idempotency key of the harness write that stored the version (the artifact seam,
|
|
414
|
+
* protocol 15): the SHA-256 of its session and the harness's key, so a repeated write answers
|
|
415
|
+
* this version. Null for every other write.
|
|
416
|
+
*/
|
|
417
|
+
writeKey: textC(),
|
|
412
418
|
}, (t) => [
|
|
413
419
|
primaryKey({ name: "artifact_versions_pkey", columns: [t.artifactId, t.version] }),
|
|
420
|
+
uniqueIndex("artifact_versions_write_key").on(t.writeKey).where(sql `write_key IS NOT NULL`),
|
|
414
421
|
foreignKey({
|
|
415
422
|
name: "artifact_versions_artifact_id_fkey",
|
|
416
423
|
columns: [t.artifactId],
|