@telorun/runner-core 0.8.2 → 0.10.0
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/README.md +33 -2
- package/dist/backend.d.ts +107 -23
- package/dist/backend.d.ts.map +1 -1
- package/dist/config.d.ts +56 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +36 -0
- package/dist/config.js.map +1 -1
- package/dist/contract.d.ts +210 -15
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +9 -0
- package/dist/contract.js.map +1 -1
- package/dist/debug/ports-resolved.d.ts +26 -0
- package/dist/debug/ports-resolved.d.ts.map +1 -0
- package/dist/debug/ports-resolved.js +42 -0
- package/dist/debug/ports-resolved.js.map +1 -0
- package/dist/debug/relay.d.ts.map +1 -1
- package/dist/debug/relay.js +34 -6
- package/dist/debug/relay.js.map +1 -1
- package/dist/debug/run-projection.d.ts +53 -0
- package/dist/debug/run-projection.d.ts.map +1 -0
- package/dist/debug/run-projection.js +115 -0
- package/dist/debug/run-projection.js.map +1 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/routes/apps.d.ts +1 -1
- package/dist/routes/apps.d.ts.map +1 -1
- package/dist/routes/apps.js +14 -4
- package/dist/routes/apps.js.map +1 -1
- package/dist/routes/io.d.ts.map +1 -1
- package/dist/routes/io.js +42 -9
- package/dist/routes/io.js.map +1 -1
- package/dist/routes/session-start.d.ts +18 -13
- package/dist/routes/session-start.d.ts.map +1 -1
- package/dist/routes/session-start.js +95 -14
- package/dist/routes/session-start.js.map +1 -1
- package/dist/routes/sessions.d.ts +11 -1
- package/dist/routes/sessions.d.ts.map +1 -1
- package/dist/routes/sessions.js +465 -5
- package/dist/routes/sessions.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +21 -1
- package/dist/server.js.map +1 -1
- package/dist/session/byte-ring-buffer.d.ts +6 -1
- package/dist/session/byte-ring-buffer.d.ts.map +1 -1
- package/dist/session/byte-ring-buffer.js +2 -2
- package/dist/session/byte-ring-buffer.js.map +1 -1
- package/dist/session/registry.d.ts +144 -13
- package/dist/session/registry.d.ts.map +1 -1
- package/dist/session/registry.js +166 -25
- package/dist/session/registry.js.map +1 -1
- package/dist/session/watch-supervisor.d.ts +42 -0
- package/dist/session/watch-supervisor.d.ts.map +1 -0
- package/dist/session/watch-supervisor.js +99 -0
- package/dist/session/watch-supervisor.js.map +1 -0
- package/dist/session/workspace-app.d.ts +4 -0
- package/dist/session/workspace-app.d.ts.map +1 -0
- package/dist/session/workspace-app.js +26 -0
- package/dist/session/workspace-app.js.map +1 -0
- package/dist/session/workspace-client.d.ts +33 -0
- package/dist/session/workspace-client.d.ts.map +1 -0
- package/dist/session/workspace-client.js +62 -0
- package/dist/session/workspace-client.js.map +1 -0
- package/dist/session/workspace-marker.d.ts +25 -0
- package/dist/session/workspace-marker.d.ts.map +1 -0
- package/dist/session/workspace-marker.js +35 -0
- package/dist/session/workspace-marker.js.map +1 -0
- package/dist/sse/channel.d.ts.map +1 -1
- package/dist/sse/channel.js +4 -0
- package/dist/sse/channel.js.map +1 -1
- package/package.json +4 -3
- package/src/app-catalog.test.ts +49 -1
- package/src/backend.ts +111 -22
- package/src/config.ts +98 -0
- package/src/contract.ts +213 -16
- package/src/debug/ports-resolved.test.ts +66 -0
- package/src/debug/ports-resolved.ts +43 -0
- package/src/debug/relay.ts +32 -4
- package/src/debug/run-projection.test.ts +155 -0
- package/src/debug/run-projection.ts +122 -0
- package/src/index.ts +20 -1
- package/src/routes/apps.ts +14 -5
- package/src/routes/io.ts +58 -12
- package/src/routes/session-start.ts +115 -27
- package/src/routes/sessions.ts +538 -7
- package/src/server.ts +22 -1
- package/src/session/byte-ring-buffer.ts +8 -2
- package/src/session/registry.ts +288 -28
- package/src/session/ring-buffer.test.ts +4 -3
- package/src/session/watch-lifetime.test.ts +203 -0
- package/src/session/watch-supervisor.ts +112 -0
- package/src/session/workspace-app.ts +27 -0
- package/src/session/workspace-client.ts +80 -0
- package/src/session/workspace-marker.test.ts +35 -0
- package/src/session/workspace-marker.ts +39 -0
- package/src/sse/channel.ts +5 -0
- package/workspace-app/telo.yaml +228 -0
package/README.md
CHANGED
|
@@ -9,6 +9,14 @@ and [`k8s-runner`](../../apps/k8s-runner)). It owns everything about a run
|
|
|
9
9
|
`/v1/sessions/:id/io` WebSocket PTY);
|
|
10
10
|
- the in-memory **session registry**, event/byte **ring buffers** (SSE + PTY
|
|
11
11
|
replay with gap detection), and bundle-path traversal guards;
|
|
12
|
+
- the **run projection** — per-app run outcomes derived from the kernel
|
|
13
|
+
lifecycle events already on the debug stream, so the runner never parses a
|
|
14
|
+
terminal to learn how a run ended;
|
|
15
|
+
- the **watch supervisor** — the workspace checkpoint timer and the idle reaper;
|
|
16
|
+
- the **workspace application** (`workspace-app/telo.yaml`), the manifest a watch
|
|
17
|
+
session's `workspace` container runs. It lives here because the workspace
|
|
18
|
+
surface is part of the `/v1` contract: both backends mount the same bytes, and
|
|
19
|
+
a copy per backend would be two manifests to hold in agreement;
|
|
12
20
|
- graceful-shutdown helpers and base config parsing.
|
|
13
21
|
|
|
14
22
|
## The seam: `RunnerBackend`
|
|
@@ -25,11 +33,34 @@ interface RunnerBackend {
|
|
|
25
33
|
}
|
|
26
34
|
```
|
|
27
35
|
|
|
36
|
+
Every callback is qualified by the application it belongs to. A session runs one
|
|
37
|
+
container per application — usually exactly one — and each has its own terminal,
|
|
38
|
+
so the byte channel is keyed `(session, app)` rather than labelled on a merged
|
|
39
|
+
stream. A single-app session carries the qualifier too, so no client needs two
|
|
40
|
+
readings.
|
|
41
|
+
|
|
42
|
+
A watch session's `BackendSession` additionally exposes `workspace`, `reload`,
|
|
43
|
+
`setApps` and `suspend`: it is a workspace that runs continuously rather than one
|
|
44
|
+
run, so its lifetime outlives every run inside it.
|
|
45
|
+
|
|
28
46
|
Bundle delivery is the backend's responsibility (docker writes a shared-volume
|
|
29
|
-
workdir; k8s stages a tarball for an initContainer fetch
|
|
30
|
-
|
|
47
|
+
workdir; k8s stages a tarball for an initContainer fetch, and a watch session
|
|
48
|
+
seeds through the workspace container's own routes), so `start` receives the raw
|
|
49
|
+
`bundle` rather than a pre-resolved path. `buildServer({ backend, config,
|
|
31
50
|
version })` wires a backend into the full `/v1` app.
|
|
32
51
|
|
|
52
|
+
## Two nouns, one stream
|
|
53
|
+
|
|
54
|
+
`status` is the SESSION's state; `run` is one application's outcome. They are
|
|
55
|
+
separate because a session can outlive its runs: a one-shot Runnable finishing in
|
|
56
|
+
a watch session emits `run` with `phase: "completed"` and leaves `status:
|
|
57
|
+
running`, so the next edit starts that app's next generation.
|
|
58
|
+
|
|
59
|
+
Workload output travels neither — it goes over the byte channel (`/io`), which
|
|
60
|
+
exists precisely because per-chunk events are wasteful for high-volume output.
|
|
61
|
+
The `stdout` / `stderr` `RunEvent` variants that used to be declared here were
|
|
62
|
+
emitted by nothing; they are gone rather than qualified.
|
|
63
|
+
|
|
33
64
|
## Development
|
|
34
65
|
|
|
35
66
|
```bash
|
package/dist/backend.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DebugFrame } from "@telorun/debug-wire";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ResolvedRunnerApp } from "./config.js";
|
|
3
|
+
import type { AvailabilityReport, ByteStreamTag, IoMode, PortMapping, ProbeConfig, ReachabilityState, RunBundle, RunnerEndpoint, RunPhase, RunStatus, SessionConfig, SessionMode, WorkspaceChangeSet, WorkspaceCheckpointFile, WorkspaceTree } from "./contract.js";
|
|
3
4
|
/**
|
|
4
5
|
* The seam between backend-neutral session machinery (routes, registry, SSE)
|
|
5
6
|
* and a concrete workload runtime (docker container, kubernetes pod).
|
|
@@ -26,55 +27,138 @@ export interface RunnerBackend {
|
|
|
26
27
|
* in-memory, so a restart otherwise leaks running workloads. */
|
|
27
28
|
reapOrphans?(): Promise<void>;
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
/** Bundle-relative entry path, already traversal-normalized by core.
|
|
30
|
+
/** One application container the backend must stand up. */
|
|
31
|
+
export interface BackendAppSpec {
|
|
32
|
+
name: string;
|
|
33
|
+
/** Bundle-relative entry path, already traversal-normalized by core. Empty for
|
|
34
|
+
* a self-contained app session, where the image's own entrypoint runs. */
|
|
33
35
|
entryRelativePath: string;
|
|
34
|
-
env: Record<string, string>;
|
|
35
36
|
ports: PortMapping[];
|
|
37
|
+
io: IoMode;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The DATA half of a workload launch — everything a start needs that is not a
|
|
41
|
+
* callback. Retained on the session entry so `resume` can build a fresh pod
|
|
42
|
+
* under the same session id from the same description, rather than a second,
|
|
43
|
+
* drifting copy of it.
|
|
44
|
+
*/
|
|
45
|
+
export interface WorkloadLaunch {
|
|
46
|
+
bundle: RunBundle;
|
|
47
|
+
env: Record<string, string>;
|
|
36
48
|
config: SessionConfig;
|
|
37
49
|
/** True for an operator-predefined app session (`POST /v1/apps/:name/sessions`):
|
|
38
50
|
* `config.image` is self-contained (app + controllers baked in), so the
|
|
39
51
|
* backend runs the image's own entrypoint and stages no bundle — `bundle`
|
|
40
52
|
* is an empty placeholder. */
|
|
41
53
|
selfContained: boolean;
|
|
42
|
-
/** When true, launch
|
|
54
|
+
/** When true, launch each app with `--inspect` and relay its kernel debug
|
|
43
55
|
* stream via `onDebug`. The inspect endpoint stays reachable only by the
|
|
44
|
-
* runner — never published outward.
|
|
56
|
+
* runner — never published outward. Always true for a watch session: that
|
|
57
|
+
* stream is where `run` events are projected from. */
|
|
45
58
|
inspect: boolean;
|
|
59
|
+
/** `run` (one pod, terminal on exit, today's shape) or `watch` (a workspace
|
|
60
|
+
* volume, `telo run --watch` per app, the pod outliving its runs). */
|
|
61
|
+
mode: SessionMode;
|
|
62
|
+
/** The applications to run, one container each. Never empty — core defaults a
|
|
63
|
+
* request with no `apps` to a single entry. */
|
|
64
|
+
apps: BackendAppSpec[];
|
|
65
|
+
/** The resolved catalog entry for a co-resident agent container, when one was
|
|
66
|
+
* requested. Its operator env goes on THAT container and nowhere else — the
|
|
67
|
+
* credential boundary used to be structural (two pods) and is now a code
|
|
68
|
+
* invariant (containers in one pod). */
|
|
69
|
+
agent?: ResolvedRunnerApp;
|
|
70
|
+
}
|
|
71
|
+
export interface BackendStartSpec extends WorkloadLaunch {
|
|
72
|
+
sessionId: string;
|
|
46
73
|
/** Emit a lifecycle status. The backend drives `starting` → `running` →
|
|
47
|
-
* terminal (`exited`/`failed`/`stopped`). */
|
|
74
|
+
* terminal (`exited`/`failed`/`stopped`), or `suspended` on an idle reap. */
|
|
48
75
|
onStatus(status: RunStatus): void;
|
|
49
76
|
/** Emit a progress message for a coming-up phase (build / provision / boot).
|
|
50
77
|
* Additive to status — surfaces what's happening while the session is still
|
|
51
|
-
* `starting
|
|
52
|
-
onProgress(phase: RunPhase, message: string, done?: boolean): void;
|
|
53
|
-
/**
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
78
|
+
* `starting`. `app` is omitted for session-scoped provisioning. */
|
|
79
|
+
onProgress(phase: RunPhase, message: string, done?: boolean, app?: string): void;
|
|
80
|
+
/** Bytes from one app's terminal. `stream` is `tty` under a terminal attach
|
|
81
|
+
* and `stdout`/`stderr` only where the transport genuinely separated them. */
|
|
82
|
+
onOutput(app: string, chunk: Buffer, stream: ByteStreamTag): void;
|
|
83
|
+
/** A frame relayed from one app's kernel debug stream. Only called when
|
|
84
|
+
* `inspect` is true and the backend has connected to that app's endpoint. */
|
|
85
|
+
onDebug(app: string, frame: DebugFrame): void;
|
|
58
86
|
/** Report a declared port's reachability from the runner network — `checking`
|
|
59
87
|
* while the workload comes up, then `reachable`, or `unreachable` after a
|
|
60
88
|
* timeout. Surfaced on the editor's endpoint badge, not the log stream. */
|
|
61
|
-
onReachability(port: number, state: ReachabilityState): void;
|
|
89
|
+
onReachability(app: string, port: number, state: ReachabilityState): void;
|
|
90
|
+
/** One app's workload ended on its own. A run session's workload ending IS the
|
|
91
|
+
* session ending, so this is a watch-session concern: under `--watch` a
|
|
92
|
+
* finished run leaves the container up, and a container that goes away has
|
|
93
|
+
* died. Reported through the contract rather than by synthesizing a kernel
|
|
94
|
+
* frame — that stream's contract is "frames relayed from the workload", and a
|
|
95
|
+
* backend writing into it puts an event on the wire no kernel emitted. */
|
|
96
|
+
onRunEnded(app: string, outcome: {
|
|
97
|
+
code?: number;
|
|
98
|
+
reason?: string;
|
|
99
|
+
}): void;
|
|
100
|
+
/** An app's routable endpoint set changed after a reload re-read its declared
|
|
101
|
+
* ports. */
|
|
102
|
+
onEndpoints(app: string, change: {
|
|
103
|
+
added?: RunnerEndpoint[];
|
|
104
|
+
removed?: RunnerEndpoint[];
|
|
105
|
+
rejected?: Array<{
|
|
106
|
+
port: number;
|
|
107
|
+
reason: string;
|
|
108
|
+
}>;
|
|
109
|
+
}): void;
|
|
62
110
|
/** True once a user stop / shutdown has been requested — lets the backend
|
|
63
111
|
* classify a kill as `stopped` rather than `failed`. */
|
|
64
112
|
isUserStopped(): boolean;
|
|
65
113
|
}
|
|
66
114
|
export interface BackendSession {
|
|
67
|
-
/** Write bytes to
|
|
68
|
-
*
|
|
69
|
-
writeStdin(bytes: Uint8Array): void;
|
|
70
|
-
/** Resize
|
|
71
|
-
|
|
115
|
+
/** Write bytes to one app's stdin. A no-op once that workload has terminated,
|
|
116
|
+
* so callers need not track liveness. */
|
|
117
|
+
writeStdin(app: string, bytes: Uint8Array): void;
|
|
118
|
+
/** Resize one app's PTY. A no-op for an app running under `io: "streams"` —
|
|
119
|
+
* the route rejects such a resize before it reaches here. */
|
|
120
|
+
resize(app: string, cols: number, rows: number): void;
|
|
72
121
|
/** Resolves after the workload terminates and its terminal status has been
|
|
73
122
|
* emitted via `onStatus`. Never rejects — terminal failures surface as a
|
|
74
|
-
* `failed` status.
|
|
123
|
+
* `failed` status. A watch session's workload outlives its runs, so this
|
|
124
|
+
* settles only on stop, suspend, or the pod deadline. */
|
|
75
125
|
readonly done: Promise<void>;
|
|
76
126
|
/** Force-stop the workload. Idempotent and safe to call after natural exit
|
|
77
127
|
* (a backend should treat an already-gone workload as a no-op). */
|
|
78
128
|
stop(): Promise<void>;
|
|
129
|
+
/** The workspace surface, present only on a watch session. Everything outside
|
|
130
|
+
* the pod writes through here; the agent (inside it) writes the volume with
|
|
131
|
+
* its own filesystem tools. */
|
|
132
|
+
readonly workspace?: WorkspaceAccess;
|
|
133
|
+
/** Re-run one app with no file change (`POST /v1/sessions/:id/reload`), by
|
|
134
|
+
* touching its entry manifest through the same path every other write takes.
|
|
135
|
+
* No signalling into the container, no shared PID namespace, no `exec` — RBAC
|
|
136
|
+
* is unchanged. Watch sessions only. */
|
|
137
|
+
reload?(app: string): Promise<void>;
|
|
138
|
+
/** Replace the running app set. A pod's container list is fixed at creation,
|
|
139
|
+
* so this checkpoints, deletes the pod and creates one with the new set —
|
|
140
|
+
* the suspend/resume path, reused because it has to be. */
|
|
141
|
+
setApps?(apps: BackendAppSpec[]): Promise<void>;
|
|
142
|
+
/** Delete the workload, keeping nothing but what the caller already
|
|
143
|
+
* checkpointed. `resume` builds a fresh one from that checkpoint. */
|
|
144
|
+
suspend?(): Promise<void>;
|
|
145
|
+
}
|
|
146
|
+
/** The `workspace` container's routes, proxied by the runner. Reading and
|
|
147
|
+
* applying a change set are the only two shapes: a single-file write route
|
|
148
|
+
* would be a second set of concurrency rules over the same directory. */
|
|
149
|
+
export interface WorkspaceAccess {
|
|
150
|
+
tree(): Promise<WorkspaceTree>;
|
|
151
|
+
readFile(path: string): Promise<{
|
|
152
|
+
content: string;
|
|
153
|
+
size: number;
|
|
154
|
+
}>;
|
|
155
|
+
apply(changes: WorkspaceChangeSet): Promise<{
|
|
156
|
+
written: number;
|
|
157
|
+
deleted: number;
|
|
158
|
+
}>;
|
|
159
|
+
/** Whole-tree pull for the checkpoint timer and for suspend. Whole tree rather
|
|
160
|
+
* than a delta log: a manifest workspace is small, and one shape is easier to
|
|
161
|
+
* reason about than a replay that has to be correct. */
|
|
162
|
+
snapshot(): Promise<WorkspaceCheckpointFile[]>;
|
|
79
163
|
}
|
|
80
164
|
//# sourceMappingURL=backend.d.ts.map
|
package/dist/backend.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,KAAK,EACV,kBAAkB,EAClB,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,QAAQ,EACR,SAAS,EACT,aAAa,EACd,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,aAAa;IAC5B;wEACoE;IACpE,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAExD;;8DAE0D;IAC1D,KAAK,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAEvD;;qEAEiE;IACjE,WAAW,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -11,6 +11,32 @@ export interface RunnerCoreConfig {
|
|
|
11
11
|
exitTtlMs: number;
|
|
12
12
|
replayBufferBytes: number;
|
|
13
13
|
corsOrigins: string[] | "*";
|
|
14
|
+
watch: WatchSessionConfig;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Watch-session policy. Off by default and separately ceilinged, because a watch
|
|
18
|
+
* session is a materially different resource shape from a run: a pod that
|
|
19
|
+
* outlives its runs, whose concurrency is bounded by simultaneous EDITORS rather
|
|
20
|
+
* than simultaneous runs. Inheriting a run session's ceilings would size it for
|
|
21
|
+
* the opposite assumption.
|
|
22
|
+
*/
|
|
23
|
+
export interface WatchSessionConfig {
|
|
24
|
+
/** Server-side gate. Watch sessions are never client-requestable when off. */
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
/** No SSE/WS subscriber for this long → suspend (pod deleted, checkpoint held). */
|
|
27
|
+
idleMs: number;
|
|
28
|
+
/** Pod deadline for a watch session. The agent and app containers share one
|
|
29
|
+
* pod, so one deadline covers both: take the longer (agent) ceiling and let
|
|
30
|
+
* idleness do the real work, or the conversation dies at an hour mid-turn. */
|
|
31
|
+
maxTtlSeconds: number;
|
|
32
|
+
maxSessions: number;
|
|
33
|
+
reloadLimitPerMinute: number;
|
|
34
|
+
/** How long a SUSPENDED record is retained before eviction. Deliberately not
|
|
35
|
+
* the pod deadline: that bounds a pod, so on its own nothing would ever evict
|
|
36
|
+
* a suspended record. */
|
|
37
|
+
suspendedTtlMs: number;
|
|
38
|
+
/** How often the runner pulls a whole-tree workspace snapshot. */
|
|
39
|
+
checkpointMs: number;
|
|
14
40
|
}
|
|
15
41
|
export declare class RunnerConfigError extends Error {
|
|
16
42
|
}
|
|
@@ -49,6 +75,15 @@ export interface RunnerAppConfig {
|
|
|
49
75
|
/** Workload image pull policy (default `missing`); `always` keeps a moving
|
|
50
76
|
* tag like `latest-slim` fresh. */
|
|
51
77
|
pullPolicy?: PullPolicy;
|
|
78
|
+
/** The tcp port this image listens on, published by the runner when the entry
|
|
79
|
+
* is used as a session's co-resident `agent` — a client cannot supply it,
|
|
80
|
+
* because what gets published is the operator's decision, not the caller's.
|
|
81
|
+
* There is deliberately NO default: the catalog is pure operator
|
|
82
|
+
* configuration and the runner has no built-in knowledge of any specific
|
|
83
|
+
* app, so guessing 8080 would be exactly that knowledge. An entry without it
|
|
84
|
+
* still works as a standalone app session (where the client declares the
|
|
85
|
+
* ports it wants published); only `agent` use requires it. */
|
|
86
|
+
port?: number;
|
|
52
87
|
title?: string;
|
|
53
88
|
description?: string;
|
|
54
89
|
}
|
|
@@ -58,6 +93,9 @@ export interface ResolvedRunnerApp {
|
|
|
58
93
|
image: string;
|
|
59
94
|
env: Record<string, string>;
|
|
60
95
|
pullPolicy: PullPolicy;
|
|
96
|
+
/** See {@link RunnerAppConfig.port} — undefined when the operator declared
|
|
97
|
+
* none, which is what makes the entry unusable as an `agent`. */
|
|
98
|
+
port?: number;
|
|
61
99
|
title?: string;
|
|
62
100
|
description?: string;
|
|
63
101
|
}
|
|
@@ -68,6 +106,23 @@ export interface ResolvedRunnerApp {
|
|
|
68
106
|
* the apps.
|
|
69
107
|
*/
|
|
70
108
|
export declare function loadAppsFromEnv(env: NodeJS.ProcessEnv): Record<string, RunnerAppConfig> | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* Which catalog entries may be a session's co-resident `agent` — the ones that
|
|
111
|
+
* declare a `port`, because the session route refuses the rest and a runner
|
|
112
|
+
* must not advertise what it will reject.
|
|
113
|
+
*
|
|
114
|
+
* Derived here rather than in each runner's capabilities call because this IS
|
|
115
|
+
* the acceptance condition: the two used to be one list by construction
|
|
116
|
+
* (`Object.keys`), and adding a second condition to the route without adding it
|
|
117
|
+
* here is exactly how they drift. An operator upgrading with an existing
|
|
118
|
+
* catalog has no `port` anywhere — the field is new — so an unfiltered
|
|
119
|
+
* advertisement makes the editor attach an agent to every run and every run is
|
|
120
|
+
* refused.
|
|
121
|
+
*
|
|
122
|
+
* Per entry, not per catalog: declaring a port opts an app into co-resident
|
|
123
|
+
* use, omitting one leaves it launchable on its own.
|
|
124
|
+
*/
|
|
125
|
+
export declare function coResidentAgentNames(apps: Record<string, ResolvedRunnerApp>): string[];
|
|
71
126
|
/** The catalog runners pass to `buildServer`: `RUNNER_APPS` validated with
|
|
72
127
|
* defaults applied; empty when unset. The catalog is pure operator
|
|
73
128
|
* configuration — runner-core knows nothing about any specific app. */
|
|
@@ -76,4 +131,5 @@ export declare function parseCorsOrigins(raw: string | undefined): string[] | "*
|
|
|
76
131
|
export declare function loadCoreConfig(env: NodeJS.ProcessEnv, defaults?: {
|
|
77
132
|
port?: number;
|
|
78
133
|
}): RunnerCoreConfig;
|
|
134
|
+
export declare function loadWatchConfig(env: NodeJS.ProcessEnv): WatchSessionConfig;
|
|
79
135
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE7D;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
CHANGED
|
@@ -120,6 +120,10 @@ function validateAppEntry(name, value) {
|
|
|
120
120
|
if (entry.pullPolicy !== undefined && !PULL_POLICIES.includes(entry.pullPolicy)) {
|
|
121
121
|
fail(`has an invalid 'pullPolicy' — expected one of ${PULL_POLICIES.join(", ")}.`);
|
|
122
122
|
}
|
|
123
|
+
if (entry.port !== undefined &&
|
|
124
|
+
(typeof entry.port !== "number" || !Number.isInteger(entry.port) || entry.port < 1 || entry.port > 65535)) {
|
|
125
|
+
fail("has an invalid 'port' — expected an integer in 1..65535.");
|
|
126
|
+
}
|
|
123
127
|
for (const key of ["title", "description"]) {
|
|
124
128
|
if (entry[key] !== undefined && typeof entry[key] !== "string") {
|
|
125
129
|
fail(`has an invalid '${key}' — expected a string.`);
|
|
@@ -127,6 +131,25 @@ function validateAppEntry(name, value) {
|
|
|
127
131
|
}
|
|
128
132
|
return entry;
|
|
129
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Which catalog entries may be a session's co-resident `agent` — the ones that
|
|
136
|
+
* declare a `port`, because the session route refuses the rest and a runner
|
|
137
|
+
* must not advertise what it will reject.
|
|
138
|
+
*
|
|
139
|
+
* Derived here rather than in each runner's capabilities call because this IS
|
|
140
|
+
* the acceptance condition: the two used to be one list by construction
|
|
141
|
+
* (`Object.keys`), and adding a second condition to the route without adding it
|
|
142
|
+
* here is exactly how they drift. An operator upgrading with an existing
|
|
143
|
+
* catalog has no `port` anywhere — the field is new — so an unfiltered
|
|
144
|
+
* advertisement makes the editor attach an agent to every run and every run is
|
|
145
|
+
* refused.
|
|
146
|
+
*
|
|
147
|
+
* Per entry, not per catalog: declaring a port opts an app into co-resident
|
|
148
|
+
* use, omitting one leaves it launchable on its own.
|
|
149
|
+
*/
|
|
150
|
+
export function coResidentAgentNames(apps) {
|
|
151
|
+
return Object.keys(apps).filter((name) => apps[name]?.port !== undefined);
|
|
152
|
+
}
|
|
130
153
|
/** The catalog runners pass to `buildServer`: `RUNNER_APPS` validated with
|
|
131
154
|
* defaults applied; empty when unset. The catalog is pure operator
|
|
132
155
|
* configuration — runner-core knows nothing about any specific app. */
|
|
@@ -139,6 +162,7 @@ export function loadResolvedApps(env) {
|
|
|
139
162
|
image: entry.image,
|
|
140
163
|
env: entry.env ?? {},
|
|
141
164
|
pullPolicy: entry.pullPolicy ?? "missing",
|
|
165
|
+
port: entry.port,
|
|
142
166
|
title: entry.title,
|
|
143
167
|
description: entry.description,
|
|
144
168
|
};
|
|
@@ -165,6 +189,18 @@ export function loadCoreConfig(env, defaults = {}) {
|
|
|
165
189
|
exitTtlMs: parsePositiveInt(env.RUNNER_EXIT_TTL_MS, 4 * 60 * 60 * 1000, "RUNNER_EXIT_TTL_MS"),
|
|
166
190
|
replayBufferBytes: parsePositiveInt(env.RUNNER_REPLAY_BUFFER_BYTES, 5_000_000, "RUNNER_REPLAY_BUFFER_BYTES"),
|
|
167
191
|
corsOrigins: parseCorsOrigins(env.RUNNER_CORS_ORIGINS),
|
|
192
|
+
watch: loadWatchConfig(env),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
export function loadWatchConfig(env) {
|
|
196
|
+
return {
|
|
197
|
+
enabled: parseBool(env.RUNNER_WATCH_SESSIONS, false, "RUNNER_WATCH_SESSIONS"),
|
|
198
|
+
idleMs: parsePositiveInt(env.RUNNER_WATCH_IDLE_SECONDS, 300, "RUNNER_WATCH_IDLE_SECONDS") * 1000,
|
|
199
|
+
maxTtlSeconds: parsePositiveInt(env.RUNNER_WATCH_MAX_TTL_SECONDS, 21600, "RUNNER_WATCH_MAX_TTL_SECONDS"),
|
|
200
|
+
maxSessions: parsePositiveInt(env.RUNNER_WATCH_MAX_SESSIONS, 8, "RUNNER_WATCH_MAX_SESSIONS"),
|
|
201
|
+
reloadLimitPerMinute: parsePositiveInt(env.RUNNER_WATCH_RELOAD_LIMIT, 30, "RUNNER_WATCH_RELOAD_LIMIT"),
|
|
202
|
+
suspendedTtlMs: parsePositiveInt(env.RUNNER_WATCH_SUSPENDED_TTL_SECONDS, 86400, "RUNNER_WATCH_SUSPENDED_TTL_SECONDS") * 1000,
|
|
203
|
+
checkpointMs: parsePositiveInt(env.RUNNER_WORKSPACE_CHECKPOINT_SECONDS, 30, "RUNNER_WORKSPACE_CHECKPOINT_SECONDS") * 1000,
|
|
168
204
|
};
|
|
169
205
|
}
|
|
170
206
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|