@nylorun/runtime 0.37.0-beta → 0.38.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 +21 -0
- package/dist/api/components.d.ts +6 -0
- package/dist/harness/image-engine.d.ts +14 -0
- package/dist/harness/image-engine.js +16 -0
- package/dist/harness/pod.d.ts +2 -0
- package/dist/harness/pod.js +5 -0
- package/dist/harness-api/ws-server.js +7 -1
- package/dist/management-openapi.json +33 -1
- package/dist/openapi.json +1 -1
- package/dist/sandbox/join.d.ts +7 -1
- package/dist/sandbox/join.js +5 -1
- package/dist/sandbox/pods/builtin.d.ts +18 -0
- package/dist/sandbox/pods/builtin.js +33 -0
- package/dist/sandbox/pods/client.d.ts +5 -4
- package/dist/sandbox/pods/spec.js +14 -1
- package/dist/store/postgres/drizzle/0042_worker_engine_image.sql +1 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +7 -0
- package/dist/store/postgres/schema.d.ts +19 -0
- package/dist/store/postgres/schema.js +2 -0
- package/dist/store/postgres/store.js +2 -0
- package/dist/store/types.d.ts +9 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.38.0-beta
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 63a6217: An image can carry the Runtime's engine (ADR-99). A pod of an image the Tenant lists in
|
|
8
|
+
`engine.images` (`PUT /v1/tenant/sandbox`) runs the engine under `/opt/nylorun` with nothing copied
|
|
9
|
+
in: the sandboxes service's new `entrypoint: "builtin"`, without the `nylo-copy` init container and
|
|
10
|
+
the `/nylo` volume. Such an engine reports its Runtime version at join (header
|
|
11
|
+
`nylorun-image-engine`), the Agent's record keeps it beside its pinned image digest, and a pod runs
|
|
12
|
+
it only while it is the Runtime's own version; otherwise the engine is copied in as for any image.
|
|
13
|
+
New column `agents.engine_image` (migration 0042).
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Pin core to the tested release.
|
|
18
|
+
- Pin harness to the tested release.
|
|
19
|
+
- Updated dependencies [63a6217]
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
- @nylorun/core@0.33.0-beta
|
|
22
|
+
- @nylorun/harness@0.30.1-beta
|
|
23
|
+
|
|
3
24
|
## 0.37.0-beta
|
|
4
25
|
|
|
5
26
|
### Minor Changes
|
package/dist/api/components.d.ts
CHANGED
|
@@ -13921,6 +13921,9 @@ export declare const SeedTenantConfigRequest: z.ZodObject<{
|
|
|
13921
13921
|
lifecycle: z.ZodOptional<z.ZodObject<{
|
|
13922
13922
|
stopGrace: z.ZodOptional<z.ZodString>;
|
|
13923
13923
|
}, z.core.$strict>>;
|
|
13924
|
+
engine: z.ZodOptional<z.ZodObject<{
|
|
13925
|
+
images: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
13926
|
+
}, z.core.$strict>>;
|
|
13924
13927
|
placement: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
13925
13928
|
hosts: z.ZodArray<z.ZodEnum<{
|
|
13926
13929
|
"harness-container": "harness-container";
|
|
@@ -14214,6 +14217,9 @@ export declare const PutTenantEnvironmentsRequest: z.ZodObject<{
|
|
|
14214
14217
|
lifecycle: z.ZodOptional<z.ZodObject<{
|
|
14215
14218
|
stopGrace: z.ZodOptional<z.ZodString>;
|
|
14216
14219
|
}, z.core.$strict>>;
|
|
14220
|
+
engine: z.ZodOptional<z.ZodObject<{
|
|
14221
|
+
images: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
14222
|
+
}, z.core.$strict>>;
|
|
14217
14223
|
placement: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
14218
14224
|
hosts: z.ZodArray<z.ZodEnum<{
|
|
14219
14225
|
"harness-container": "harness-container";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An engine the workload image carries (ADR-99): the Runtime image's tini, node and bundled engine
|
|
3
|
+
* under `/opt/nylorun`, run by the sandboxes service with `entrypoint: "builtin"`. Such an engine is
|
|
4
|
+
* the Runtime version the image was built from, so it says which at `host/join`; the Runtime decides
|
|
5
|
+
* from it whether the next pod runs it or copies its own in (`sandbox/pods/builtin.ts`).
|
|
6
|
+
*/
|
|
7
|
+
/** Where an image keeps the engine it carries. */
|
|
8
|
+
export declare const BUILTIN_ENGINE_ROOT = "/opt/nylorun";
|
|
9
|
+
/** Sent at `host/join` only by an engine running from `BUILTIN_ENGINE_ROOT`: its Runtime version. */
|
|
10
|
+
export declare const IMAGE_ENGINE_HEADER = "nylorun-image-engine";
|
|
11
|
+
/** A Runtime version, as the header carries it. */
|
|
12
|
+
export declare const ENGINE_VERSION_PATTERN: RegExp;
|
|
13
|
+
/** Whether code at `moduleUrl` runs from an image's engine (the engine passes its own URL). */
|
|
14
|
+
export declare function isBuiltinEngine(moduleUrl: string): boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An engine the workload image carries (ADR-99): the Runtime image's tini, node and bundled engine
|
|
3
|
+
* under `/opt/nylorun`, run by the sandboxes service with `entrypoint: "builtin"`. Such an engine is
|
|
4
|
+
* the Runtime version the image was built from, so it says which at `host/join`; the Runtime decides
|
|
5
|
+
* from it whether the next pod runs it or copies its own in (`sandbox/pods/builtin.ts`).
|
|
6
|
+
*/
|
|
7
|
+
/** Where an image keeps the engine it carries. */
|
|
8
|
+
export const BUILTIN_ENGINE_ROOT = "/opt/nylorun";
|
|
9
|
+
/** Sent at `host/join` only by an engine running from `BUILTIN_ENGINE_ROOT`: its Runtime version. */
|
|
10
|
+
export const IMAGE_ENGINE_HEADER = "nylorun-image-engine";
|
|
11
|
+
/** A Runtime version, as the header carries it. */
|
|
12
|
+
export const ENGINE_VERSION_PATTERN = /^[0-9A-Za-z.+-]{1,64}$/;
|
|
13
|
+
/** Whether code at `moduleUrl` runs from an image's engine (the engine passes its own URL). */
|
|
14
|
+
export function isBuiltinEngine(moduleUrl) {
|
|
15
|
+
return moduleUrl.startsWith(`file://${BUILTIN_ENGINE_ROOT}/`);
|
|
16
|
+
}
|
package/dist/harness/pod.d.ts
CHANGED
|
@@ -59,4 +59,6 @@ export declare function podHost(config: PodHostConfig, logger: {
|
|
|
59
59
|
volumeFile?: string;
|
|
60
60
|
/** Where the engine writes the trust bundle: the public roots and the egress CA (R2c). */
|
|
61
61
|
caBundleFile?: string;
|
|
62
|
+
/** Whether this engine runs from the workload image (default: from where its code is). */
|
|
63
|
+
imageEngine?: boolean;
|
|
62
64
|
}): PodHost;
|
package/dist/harness/pod.js
CHANGED
|
@@ -16,6 +16,8 @@ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
|
16
16
|
import { rootCertificates } from "node:tls";
|
|
17
17
|
import { dirname } from "node:path";
|
|
18
18
|
import { hostTuning } from "../tuning.js";
|
|
19
|
+
import { RUNTIME_VERSION } from "../version.js";
|
|
20
|
+
import { IMAGE_ENGINE_HEADER, isBuiltinEngine } from "./image-engine.js";
|
|
19
21
|
/** The variables CLIs read their trust bundle from: OpenSSL, Node, Python, curl, git, AWS. */
|
|
20
22
|
const TRUST_VARIABLES = [
|
|
21
23
|
"SSL_CERT_FILE",
|
|
@@ -29,6 +31,7 @@ class Refused extends Error {
|
|
|
29
31
|
}
|
|
30
32
|
export function podHost(config, logger, options = {}) {
|
|
31
33
|
const call = options.fetch ?? fetch;
|
|
34
|
+
const imageEngine = options.imageEngine ?? isBuiltinEngine(import.meta.url);
|
|
32
35
|
let held;
|
|
33
36
|
let setup;
|
|
34
37
|
let seeded = false;
|
|
@@ -41,6 +44,8 @@ export function podHost(config, logger, options = {}) {
|
|
|
41
44
|
headers: {
|
|
42
45
|
...(init.body === undefined ? {} : { "content-type": "application/json" }),
|
|
43
46
|
...(init.bearer ? { authorization: `Bearer ${init.bearer}` } : {}),
|
|
47
|
+
// An engine the workload image carries says which Runtime it came from (ADR-99).
|
|
48
|
+
...(path === "join" && imageEngine ? { [IMAGE_ENGINE_HEADER]: RUNTIME_VERSION } : {}),
|
|
44
49
|
},
|
|
45
50
|
...(init.body === undefined ? {} : { body: JSON.stringify(init.body) }),
|
|
46
51
|
signal: AbortSignal.timeout(hostTuning().harness.podJoinTimeoutMs),
|
|
@@ -31,6 +31,7 @@ import { HOST_TOKEN_TYP } from "../tenant/host-token.js";
|
|
|
31
31
|
import { HostAuthError } from "../sandbox/join.js";
|
|
32
32
|
import { parseSetupReport } from "../sandbox/setup.js";
|
|
33
33
|
import { hostTuning } from "../tuning.js";
|
|
34
|
+
import { ENGINE_VERSION_PATTERN, IMAGE_ENGINE_HEADER } from "../harness/image-engine.js";
|
|
34
35
|
export { HOST_JOIN_PATH, HOST_RENEW_PATH };
|
|
35
36
|
/** Where a pod's engine reads its setup and reports it (R2d step 2, `sandbox/setup.ts`). */
|
|
36
37
|
export const HOST_SETUP_PATH = `${HARNESS_API_PATH}/host/setup`;
|
|
@@ -45,6 +46,11 @@ function refuse(socket, status, text, headers = {}) {
|
|
|
45
46
|
];
|
|
46
47
|
socket.end(`${lines.join("\r\n")}\r\n\r\n`);
|
|
47
48
|
}
|
|
49
|
+
/** The Runtime version an engine built into the image reports at join (ADR-99), when well formed. */
|
|
50
|
+
function imageEngineOf(request) {
|
|
51
|
+
const value = request.headers[IMAGE_ENGINE_HEADER];
|
|
52
|
+
return typeof value === "string" && ENGINE_VERSION_PATTERN.test(value) ? value : undefined;
|
|
53
|
+
}
|
|
48
54
|
function bearerOf(header) {
|
|
49
55
|
return /^Bearer\s+(\S+)$/i.exec(header?.trim() ?? "")?.[1];
|
|
50
56
|
}
|
|
@@ -110,7 +116,7 @@ export async function startHarnessListener(options) {
|
|
|
110
116
|
return reply(response, 503, { error: { code: "unavailable", message: "Try again" } });
|
|
111
117
|
try {
|
|
112
118
|
const answer = path === HOST_JOIN_PATH
|
|
113
|
-
? await authority.join(parseJoin(await readBody(request)))
|
|
119
|
+
? await authority.join(parseJoin(await readBody(request)), { imageEngine: imageEngineOf(request) })
|
|
114
120
|
: await authority.renew(bearerOf(request.headers.authorization) ?? "");
|
|
115
121
|
return reply(response, 200, answer);
|
|
116
122
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.2.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Nylorun Management API",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.38.0-beta",
|
|
6
6
|
"x-nylorun-protocol": {
|
|
7
7
|
"min": 16,
|
|
8
8
|
"max": 18,
|
|
@@ -931,6 +931,22 @@
|
|
|
931
931
|
},
|
|
932
932
|
"additionalProperties": false
|
|
933
933
|
},
|
|
934
|
+
"engine": {
|
|
935
|
+
"type": "object",
|
|
936
|
+
"properties": {
|
|
937
|
+
"images": {
|
|
938
|
+
"type": "array",
|
|
939
|
+
"items": {
|
|
940
|
+
"type": "string",
|
|
941
|
+
"minLength": 1,
|
|
942
|
+
"maxLength": 256,
|
|
943
|
+
"pattern": "^[a-z0-9]([a-z0-9._:/-]*[a-z0-9])?$"
|
|
944
|
+
},
|
|
945
|
+
"maxItems": 32
|
|
946
|
+
}
|
|
947
|
+
},
|
|
948
|
+
"additionalProperties": false
|
|
949
|
+
},
|
|
934
950
|
"placement": {
|
|
935
951
|
"type": "object",
|
|
936
952
|
"additionalProperties": {
|
|
@@ -2321,6 +2337,22 @@
|
|
|
2321
2337
|
},
|
|
2322
2338
|
"additionalProperties": false
|
|
2323
2339
|
},
|
|
2340
|
+
"engine": {
|
|
2341
|
+
"type": "object",
|
|
2342
|
+
"properties": {
|
|
2343
|
+
"images": {
|
|
2344
|
+
"type": "array",
|
|
2345
|
+
"items": {
|
|
2346
|
+
"type": "string",
|
|
2347
|
+
"minLength": 1,
|
|
2348
|
+
"maxLength": 256,
|
|
2349
|
+
"pattern": "^[a-z0-9]([a-z0-9._:/-]*[a-z0-9])?$"
|
|
2350
|
+
},
|
|
2351
|
+
"maxItems": 32
|
|
2352
|
+
}
|
|
2353
|
+
},
|
|
2354
|
+
"additionalProperties": false
|
|
2355
|
+
},
|
|
2324
2356
|
"placement": {
|
|
2325
2357
|
"type": "object",
|
|
2326
2358
|
"additionalProperties": {
|
package/dist/openapi.json
CHANGED
package/dist/sandbox/join.d.ts
CHANGED
|
@@ -20,7 +20,13 @@ export declare class HostAuthError extends Error {
|
|
|
20
20
|
}
|
|
21
21
|
/** The Tenant's side of the exchange, as the Harness API listener calls it. */
|
|
22
22
|
export interface HostAuthority {
|
|
23
|
-
|
|
23
|
+
/**
|
|
24
|
+
* `imageEngine`: the Runtime version an engine the workload image carries reported (ADR-99);
|
|
25
|
+
* absent for an engine copied in.
|
|
26
|
+
*/
|
|
27
|
+
join(request: HostJoinRequest, from?: {
|
|
28
|
+
imageEngine?: string;
|
|
29
|
+
}): Promise<HostJoinAnswer>;
|
|
24
30
|
renew(hostToken: string): Promise<HostJoinAnswer>;
|
|
25
31
|
/** The claims of a current host's token, for a connection; refuses a stale one. */
|
|
26
32
|
verify(hostToken: string): Promise<HostClaims>;
|
package/dist/sandbox/join.js
CHANGED
|
@@ -85,7 +85,7 @@ export function hostAuthority(ctx) {
|
|
|
85
85
|
return verdict.claims;
|
|
86
86
|
};
|
|
87
87
|
return {
|
|
88
|
-
async join(request) {
|
|
88
|
+
async join(request, from) {
|
|
89
89
|
const { sandboxId, podUid, joinToken, volumeId } = request;
|
|
90
90
|
if (!isAgentId(sandboxId) ||
|
|
91
91
|
typeof podUid !== "string" ||
|
|
@@ -146,6 +146,10 @@ export function hostAuthority(ctx) {
|
|
|
146
146
|
hostEpoch: epoch,
|
|
147
147
|
podUid,
|
|
148
148
|
...(pod.volumeId === undefined && volumeId !== undefined ? { volumeId } : {}),
|
|
149
|
+
// The engine the image carries, against the digest this pod runs (ADR-99).
|
|
150
|
+
...(from?.imageEngine === undefined
|
|
151
|
+
? {}
|
|
152
|
+
: { engineImage: { version: from.imageEngine, ...(pod.imageDigest ? { digest: pod.imageDigest } : {}) } }),
|
|
149
153
|
...(pod.desired === "running" ? { observed: "running", reason: null } : {}),
|
|
150
154
|
}, now);
|
|
151
155
|
if (pod.podUid !== podUid) {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { BUILTIN_ENGINE_ROOT, ENGINE_VERSION_PATTERN, IMAGE_ENGINE_HEADER } from "../../harness/image-engine.js";
|
|
2
|
+
/** The engine an image carries, as the pod's record keeps it: its version, seen on `digest`. */
|
|
3
|
+
export interface EngineImage {
|
|
4
|
+
readonly version: string;
|
|
5
|
+
readonly digest?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Whether a pod of `image` (its pinned digest, or as asked) runs the engine the image carries:
|
|
9
|
+
* the Tenant lists its repository, and the engine recorded for that digest is this Runtime's
|
|
10
|
+
* version or not known yet.
|
|
11
|
+
*/
|
|
12
|
+
export declare function runsBuiltinEngine(input: {
|
|
13
|
+
readonly image: string | undefined;
|
|
14
|
+
readonly imageDigest: string | undefined;
|
|
15
|
+
readonly engineImage: EngineImage | undefined;
|
|
16
|
+
readonly listed: readonly string[] | undefined;
|
|
17
|
+
readonly runtimeVersion?: string;
|
|
18
|
+
}): boolean;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An engine built into the workload's image (ADR-99): the Runtime image's tini, node and bundled
|
|
3
|
+
* engine under `/opt/nylorun`, which the sandboxes service runs with `entrypoint: "builtin"` and
|
|
4
|
+
* nothing copied in.
|
|
5
|
+
*
|
|
6
|
+
* The Tenant lists the images that carry one (`engine.images`, by repository). Such an engine is
|
|
7
|
+
* whichever Runtime version the image was built from, so it reports that version when it joins
|
|
8
|
+
* (`IMAGE_ENGINE_HEADER`, sent only by an engine running from `/opt/nylorun`), and the pod's
|
|
9
|
+
* record keeps it beside the digest it ran (`engineImage`). A pod runs the image's engine while
|
|
10
|
+
* that version is the Runtime's own, or not known yet for the digest it runs (a first start, which
|
|
11
|
+
* the Harness API version check at `hello` still guards); otherwise the engine is copied in, so a
|
|
12
|
+
* Runtime upgrade never leaves a pod on an older engine for more than that first turn.
|
|
13
|
+
*/
|
|
14
|
+
import { RUNTIME_VERSION } from "../../version.js";
|
|
15
|
+
import { repositoryOf } from "./lifecycle.js";
|
|
16
|
+
export { BUILTIN_ENGINE_ROOT, ENGINE_VERSION_PATTERN, IMAGE_ENGINE_HEADER } from "../../harness/image-engine.js";
|
|
17
|
+
/**
|
|
18
|
+
* Whether a pod of `image` (its pinned digest, or as asked) runs the engine the image carries:
|
|
19
|
+
* the Tenant lists its repository, and the engine recorded for that digest is this Runtime's
|
|
20
|
+
* version or not known yet.
|
|
21
|
+
*/
|
|
22
|
+
export function runsBuiltinEngine(input) {
|
|
23
|
+
const image = input.imageDigest ?? input.image;
|
|
24
|
+
if (!image || !input.listed?.length)
|
|
25
|
+
return false;
|
|
26
|
+
const repository = repositoryOf(image);
|
|
27
|
+
if (!input.listed.some((entry) => repositoryOf(entry) === repository))
|
|
28
|
+
return false;
|
|
29
|
+
const known = input.engineImage !== undefined && input.imageDigest !== undefined && input.engineImage.digest === input.imageDigest
|
|
30
|
+
? input.engineImage.version
|
|
31
|
+
: undefined;
|
|
32
|
+
return known === undefined || known === (input.runtimeVersion ?? RUNTIME_VERSION);
|
|
33
|
+
}
|
|
@@ -5,11 +5,12 @@ export interface PodSpec {
|
|
|
5
5
|
/** The workload image; the service defaults it to `python:3.13-slim`. */
|
|
6
6
|
readonly image?: string;
|
|
7
7
|
/**
|
|
8
|
-
* What the workload runs: `engine` (default), our engine copied from `harnessImage
|
|
9
|
-
* `
|
|
8
|
+
* What the workload runs: `engine` (default), our engine copied from `harnessImage`;
|
|
9
|
+
* `builtin`, our engine the image carries under `/opt/nylorun` (ADR-99); or `image`, the image's
|
|
10
|
+
* own entrypoint, for a custom harness built into it (R4.4).
|
|
10
11
|
*/
|
|
11
|
-
readonly entrypoint?: "engine" | "image";
|
|
12
|
-
/** The Runtime image the engine is copied from; not with `entrypoint: "image"`. */
|
|
12
|
+
readonly entrypoint?: "engine" | "builtin" | "image";
|
|
13
|
+
/** The Runtime image the engine is copied from; not with `entrypoint: "builtin"` or `"image"`. */
|
|
13
14
|
readonly harnessImage?: string;
|
|
14
15
|
/** Replaces the engine command (diagnostics). */
|
|
15
16
|
readonly command?: readonly string[];
|
|
@@ -8,6 +8,7 @@ import { DEFAULT_HARNESS } from "@nylorun/core/contracts";
|
|
|
8
8
|
import { idleMsOf, memoryMiBOf } from "../policy.js";
|
|
9
9
|
import { podTuningEnv } from "../../tuning.js";
|
|
10
10
|
import { opIdOf } from "./lifecycle.js";
|
|
11
|
+
import { runsBuiltinEngine } from "./builtin.js";
|
|
11
12
|
/** The pod's grace period to stop when the Tenant sets none (D34). */
|
|
12
13
|
export const DEFAULT_STOP_GRACE_SECONDS = 10;
|
|
13
14
|
/** The volume's size when the sandbox asks for none. */
|
|
@@ -40,12 +41,24 @@ export function podSpecOf(input) {
|
|
|
40
41
|
// Pinned by digest once a pod ran it (Q14).
|
|
41
42
|
const image = pod.imageDigest ?? spec.image;
|
|
42
43
|
const ours = (input.harness ?? DEFAULT_HARNESS) === DEFAULT_HARNESS;
|
|
44
|
+
// Our engine, built into an image the Tenant lists, while it is this Runtime's (ADR-99).
|
|
45
|
+
const builtin = ours &&
|
|
46
|
+
runsBuiltinEngine({
|
|
47
|
+
image: spec.image,
|
|
48
|
+
imageDigest: pod.imageDigest,
|
|
49
|
+
engineImage: pod.engineImage,
|
|
50
|
+
listed: config.engine?.images,
|
|
51
|
+
});
|
|
43
52
|
return {
|
|
44
53
|
opId: opIdOf(pod),
|
|
45
54
|
mode: input.mode,
|
|
46
55
|
...(image ? { image } : {}),
|
|
47
56
|
// A custom harness is its image: the pod runs the image's entrypoint, nothing copied in.
|
|
48
|
-
...(ours
|
|
57
|
+
...(!ours
|
|
58
|
+
? { entrypoint: "image" }
|
|
59
|
+
: builtin
|
|
60
|
+
? { entrypoint: "builtin" }
|
|
61
|
+
: { harnessImage: input.harnessImage }),
|
|
49
62
|
cpus: spec.resources?.cpus ?? 1,
|
|
50
63
|
memoryMiB: memoryMiBOf(spec),
|
|
51
64
|
storageGiB: storageGiBOf(spec),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ALTER TABLE "nylorun"."agents" ADD COLUMN "engine_image" json;
|
|
@@ -295,6 +295,13 @@
|
|
|
295
295
|
"when": 1793448353003,
|
|
296
296
|
"tag": "0041_turn_index_backfill",
|
|
297
297
|
"breakpoints": true
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"idx": 42,
|
|
301
|
+
"version": "7",
|
|
302
|
+
"when": 1793509192153,
|
|
303
|
+
"tag": "0042_worker_engine_image",
|
|
304
|
+
"breakpoints": true
|
|
298
305
|
}
|
|
299
306
|
]
|
|
300
307
|
}
|
|
@@ -1302,6 +1302,25 @@ export declare const agents: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
|
1302
1302
|
}, {}, {
|
|
1303
1303
|
pgColumnBuilderBrand: 'PgCustomColumnBuilderBrand';
|
|
1304
1304
|
}>;
|
|
1305
|
+
engineImage: import("drizzle-orm/pg-core").PgColumn<{
|
|
1306
|
+
name: "engineImage";
|
|
1307
|
+
tableName: "agents";
|
|
1308
|
+
dataType: "custom";
|
|
1309
|
+
columnType: "PgCustomColumn";
|
|
1310
|
+
data: unknown;
|
|
1311
|
+
driverParam: unknown;
|
|
1312
|
+
notNull: false;
|
|
1313
|
+
hasDefault: false;
|
|
1314
|
+
isPrimaryKey: false;
|
|
1315
|
+
isAutoincrement: false;
|
|
1316
|
+
hasRuntimeDefault: false;
|
|
1317
|
+
enumValues: undefined;
|
|
1318
|
+
baseColumn: never;
|
|
1319
|
+
identity: undefined;
|
|
1320
|
+
generated: undefined;
|
|
1321
|
+
}, {}, {
|
|
1322
|
+
pgColumnBuilderBrand: 'PgCustomColumnBuilderBrand';
|
|
1323
|
+
}>;
|
|
1305
1324
|
diskOp: import("drizzle-orm/pg-core").PgColumn<{
|
|
1306
1325
|
name: "diskOp";
|
|
1307
1326
|
tableName: "agents";
|
|
@@ -171,6 +171,8 @@ export const agents = nylorun.table("agents", {
|
|
|
171
171
|
volumeId: text(),
|
|
172
172
|
/** The workload image by digest, from the first ready pod on (Q14): later pods run it. */
|
|
173
173
|
imageDigest: textC(),
|
|
174
|
+
/** The engine the image carries (ADR-99): `{ version, digest? }`, from a join of its engine. */
|
|
175
|
+
engineImage: jsonText(),
|
|
174
176
|
/**
|
|
175
177
|
* The disk lease (R2d step 3): `{ kind, version?, startedAt, until }` while a snapshot, a
|
|
176
178
|
* restore or a seed copies the disk; turns are refused until it ends or `until` passes.
|
|
@@ -283,6 +283,7 @@ function environmentOf(row) {
|
|
|
283
283
|
...(row.retiring !== null ? { retiring: row.retiring } : {}),
|
|
284
284
|
...(row.volumeId !== null ? { volumeId: row.volumeId } : {}),
|
|
285
285
|
...(row.imageDigest !== null ? { imageDigest: row.imageDigest } : {}),
|
|
286
|
+
...(row.engineImage ? { engineImage: row.engineImage } : {}),
|
|
286
287
|
},
|
|
287
288
|
}
|
|
288
289
|
: {}),
|
|
@@ -317,6 +318,7 @@ function podColumns(patch) {
|
|
|
317
318
|
retiring: patch.retiring,
|
|
318
319
|
volumeId: patch.volumeId,
|
|
319
320
|
imageDigest: patch.imageDigest,
|
|
321
|
+
engineImage: patch.engineImage,
|
|
320
322
|
};
|
|
321
323
|
return Object.fromEntries(Object.entries(columns).filter(([, value]) => value !== undefined));
|
|
322
324
|
}
|
package/dist/store/types.d.ts
CHANGED
|
@@ -260,6 +260,15 @@ export interface SandboxPodState {
|
|
|
260
260
|
* Environment is ready (Q14): every later pod, after a stop, a relaunch or a reset, runs it.
|
|
261
261
|
*/
|
|
262
262
|
imageDigest?: string;
|
|
263
|
+
/**
|
|
264
|
+
* The engine the workload image carries (ADR-99, `sandbox/pods/builtin.ts`): its Runtime
|
|
265
|
+
* version, as its engine reported at join, and the digest that pod ran. It counts only while
|
|
266
|
+
* that digest is `imageDigest`.
|
|
267
|
+
*/
|
|
268
|
+
engineImage?: {
|
|
269
|
+
version: string;
|
|
270
|
+
digest?: string;
|
|
271
|
+
};
|
|
263
272
|
}
|
|
264
273
|
/** A change to a pod's columns: `null` clears an optional one. */
|
|
265
274
|
export type SandboxPodPatch = {
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const RUNTIME_VERSION = "0.
|
|
1
|
+
export declare const RUNTIME_VERSION = "0.38.0-beta";
|
package/dist/version.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// Kept in step with package.json by runtime/server/scripts/check-package.mjs, which runs in npm run check.
|
|
2
2
|
// release:prepare also rewrites this when it bumps @nylorun/runtime.
|
|
3
|
-
export const RUNTIME_VERSION = "0.
|
|
3
|
+
export const RUNTIME_VERSION = "0.38.0-beta";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nylorun/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0-beta",
|
|
4
4
|
"description": "Nylorun Runtime: the agent execution Host on Postgres, Restate and S2, and model providers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"@hono/node-server": "^2.1.5",
|
|
66
66
|
"@hono/zod-openapi": "^1.6.3",
|
|
67
67
|
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
68
|
-
"@nylorun/core": "0.
|
|
69
|
-
"@nylorun/harness": "0.30.
|
|
68
|
+
"@nylorun/core": "0.33.0-beta",
|
|
69
|
+
"@nylorun/harness": "0.30.1-beta",
|
|
70
70
|
"@restatedev/restate-sdk": "1.17.3",
|
|
71
71
|
"@restatedev/restate-sdk-clients": "1.17.3",
|
|
72
72
|
"@s2-dev/streamstore": "0.28.0",
|