@telorun/runner-core 0.8.1 → 0.9.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 +27 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +12 -0
- package/dist/config.js.map +1 -1
- package/dist/contract.d.ts +199 -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 +12 -12
- package/dist/routes/session-start.d.ts.map +1 -1
- package/dist/routes/session-start.js +86 -13
- 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 +429 -4
- 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 +5 -4
- package/src/backend.ts +111 -22
- package/src/config.ts +59 -0
- package/src/contract.ts +197 -15
- 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 +106 -27
- package/src/routes/sessions.ts +498 -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/dist/contract.js
CHANGED
|
@@ -6,6 +6,15 @@
|
|
|
6
6
|
*/
|
|
7
7
|
/** HTTP header carrying the accepted terms version on `POST /v1/sessions`. */
|
|
8
8
|
export const ACCEPTED_TERMS_HEADER = "x-telo-accepted-terms";
|
|
9
|
+
/** The name a single-app session's one application takes when the request
|
|
10
|
+
* declares no `apps` — so every `run` / `debug` / `endpoints` event names an
|
|
11
|
+
* app, and no client needs two readings of the same stream. */
|
|
12
|
+
export const DEFAULT_APP_NAME = "app";
|
|
13
|
+
/**
|
|
14
|
+
* Terminal = the session is over and the registry may schedule eviction.
|
|
15
|
+
* `suspended` is deliberately NOT terminal: the session record and its workspace
|
|
16
|
+
* checkpoint outlive the pod, and `resume` brings it back under the same id.
|
|
17
|
+
*/
|
|
9
18
|
export function isTerminal(status) {
|
|
10
19
|
return status.kind === "exited" || status.kind === "failed" || status.kind === "stopped";
|
|
11
20
|
}
|
package/dist/contract.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwCH,8EAA8E;AAC9E,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwCH,8EAA8E;AAC9E,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AA8G7D;;gEAEgE;AAChE,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AA4ItC;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,MAAiB;IAC1C,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC;AAC3F,CAAC;AA0DD,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAExB;IACA;IAEA;IAJlB,YACkB,IAAoC,EACpC,KAAwB,EACxC,OAAe,EACC,aAAsB;QAEtC,KAAK,CAAC,OAAO,CAAC,CAAC;QALC,SAAI,GAAJ,IAAI,CAAgC;QACpC,UAAK,GAAL,KAAK,CAAmB;QAExB,kBAAa,GAAb,aAAa,CAAS;QAGtC,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type DebugFrame } from "@telorun/debug-wire";
|
|
2
|
+
import type { PortMapping } from "../contract.js";
|
|
3
|
+
/** The kernel says this once per load: the Application's `ports:` block has
|
|
4
|
+
* resolved to these integers. It re-fires on every watch reload, which is what
|
|
5
|
+
* lets a host re-route without parsing a manifest. */
|
|
6
|
+
export declare const PORTS_RESOLVED_EVENT = "Kernel.PortsResolved";
|
|
7
|
+
/**
|
|
8
|
+
* The declared port set carried by a `Kernel.PortsResolved` frame, or undefined
|
|
9
|
+
* for any other frame.
|
|
10
|
+
*
|
|
11
|
+
* DECLARED, not bound. A runner routes what the manifest asked for; whether
|
|
12
|
+
* anything actually bound it is the reachability watcher's question, and it
|
|
13
|
+
* already answers it per port. Routing what happened to be bound instead would
|
|
14
|
+
* expose a port the manifest never declared, and would rest on a per-module
|
|
15
|
+
* convention — a transport whose kind does not emit a listening event would
|
|
16
|
+
* silently get no routing at all.
|
|
17
|
+
*
|
|
18
|
+
* Tolerant of a payload that is not the expected shape: a runner reads this off
|
|
19
|
+
* a stream produced by a kernel it does not version together with, so a frame it
|
|
20
|
+
* cannot make sense of is one to ignore, not to fail on.
|
|
21
|
+
*/
|
|
22
|
+
export declare function portsResolvedFrom(frame: DebugFrame): PortMapping[] | undefined;
|
|
23
|
+
/** Identity of a port within a session: the pair, since tcp/3000 and udp/3000
|
|
24
|
+
* are different endpoints. */
|
|
25
|
+
export declare function portKey(mapping: PortMapping): string;
|
|
26
|
+
//# sourceMappingURL=ports-resolved.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports-resolved.d.ts","sourceRoot":"","sources":["../../src/debug/ports-resolved.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEpE,OAAO,KAAK,EAAE,WAAW,EAAgB,MAAM,gBAAgB,CAAC;AAEhE;;uDAEuD;AACvD,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAE3D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,EAAE,GAAG,SAAS,CAY9E;AAED;+BAC+B;AAC/B,wBAAgB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAEpD"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { isEventFrame } from "@telorun/debug-wire";
|
|
2
|
+
/** The kernel says this once per load: the Application's `ports:` block has
|
|
3
|
+
* resolved to these integers. It re-fires on every watch reload, which is what
|
|
4
|
+
* lets a host re-route without parsing a manifest. */
|
|
5
|
+
export const PORTS_RESOLVED_EVENT = "Kernel.PortsResolved";
|
|
6
|
+
/**
|
|
7
|
+
* The declared port set carried by a `Kernel.PortsResolved` frame, or undefined
|
|
8
|
+
* for any other frame.
|
|
9
|
+
*
|
|
10
|
+
* DECLARED, not bound. A runner routes what the manifest asked for; whether
|
|
11
|
+
* anything actually bound it is the reachability watcher's question, and it
|
|
12
|
+
* already answers it per port. Routing what happened to be bound instead would
|
|
13
|
+
* expose a port the manifest never declared, and would rest on a per-module
|
|
14
|
+
* convention — a transport whose kind does not emit a listening event would
|
|
15
|
+
* silently get no routing at all.
|
|
16
|
+
*
|
|
17
|
+
* Tolerant of a payload that is not the expected shape: a runner reads this off
|
|
18
|
+
* a stream produced by a kernel it does not version together with, so a frame it
|
|
19
|
+
* cannot make sense of is one to ignore, not to fail on.
|
|
20
|
+
*/
|
|
21
|
+
export function portsResolvedFrom(frame) {
|
|
22
|
+
if (!isEventFrame(frame) || frame.event !== PORTS_RESOLVED_EVENT)
|
|
23
|
+
return undefined;
|
|
24
|
+
const raw = frame.payload?.ports;
|
|
25
|
+
if (!Array.isArray(raw))
|
|
26
|
+
return undefined;
|
|
27
|
+
const ports = [];
|
|
28
|
+
for (const entry of raw) {
|
|
29
|
+
const port = entry?.port;
|
|
30
|
+
const protocol = entry?.protocol;
|
|
31
|
+
if (typeof port !== "number" || !Number.isInteger(port))
|
|
32
|
+
continue;
|
|
33
|
+
ports.push({ port, protocol: protocol === "udp" ? "udp" : "tcp" });
|
|
34
|
+
}
|
|
35
|
+
return ports;
|
|
36
|
+
}
|
|
37
|
+
/** Identity of a port within a session: the pair, since tcp/3000 and udp/3000
|
|
38
|
+
* are different endpoints. */
|
|
39
|
+
export function portKey(mapping) {
|
|
40
|
+
return `${mapping.protocol}/${mapping.port}`;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=ports-resolved.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports-resolved.js","sourceRoot":"","sources":["../../src/debug/ports-resolved.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAmB,MAAM,qBAAqB,CAAC;AAIpE;;uDAEuD;AACvD,MAAM,CAAC,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAE3D;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAiB;IACjD,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,KAAK,oBAAoB;QAAE,OAAO,SAAS,CAAC;IACnF,MAAM,GAAG,GAAI,KAAK,CAAC,OAA2C,EAAE,KAAK,CAAC;IACtE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;QACxB,MAAM,IAAI,GAAI,KAA4B,EAAE,IAAI,CAAC;QACjD,MAAM,QAAQ,GAAI,KAAgC,EAAE,QAAQ,CAAC;QAC7D,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;YAAE,SAAS;QAClE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,KAAsB,EAAE,CAAC,CAAC;IACvF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;+BAC+B;AAC/B,MAAM,UAAU,OAAO,CAAC,OAAoB;IAC1C,OAAO,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;AAC/C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay.d.ts","sourceRoot":"","sources":["../../src/debug/relay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAItD,MAAM,WAAW,iBAAiB;IAChC;2EACuE;IACvE,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,wCAAwC;IACxC,MAAM,EAAE,WAAW,CAAC;IACpB;;qDAEiD;IACjD,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC;AAID;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"relay.d.ts","sourceRoot":"","sources":["../../src/debug/relay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAItD,MAAM,WAAW,iBAAiB;IAChC;2EACuE;IACvE,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,wCAAwC;IACxC,MAAM,EAAE,WAAW,CAAC;IACpB;;qDAEiD;IACjD,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC;AAID;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B7E"}
|
package/dist/debug/relay.js
CHANGED
|
@@ -11,17 +11,27 @@ const RECONNECT_DELAY_MS = 500;
|
|
|
11
11
|
*/
|
|
12
12
|
export async function relayDebugStream(opts) {
|
|
13
13
|
const { url, onFrame, signal } = opts;
|
|
14
|
+
// The last id delivered, carried across reconnects. Without it a drop replays
|
|
15
|
+
// the producer's whole buffer, and a consumer that DERIVES state from the
|
|
16
|
+
// stream — the run projection counting generations — re-counts every reload
|
|
17
|
+
// still in that buffer. In a watch session that is one pair per save.
|
|
18
|
+
let lastEventId = 0;
|
|
14
19
|
while (!signal.aborted) {
|
|
15
20
|
try {
|
|
16
21
|
const res = await fetch(url, {
|
|
17
22
|
signal,
|
|
18
|
-
headers: {
|
|
23
|
+
headers: {
|
|
24
|
+
accept: "text/event-stream",
|
|
25
|
+
...(lastEventId > 0 ? { "last-event-id": String(lastEventId) } : {}),
|
|
26
|
+
},
|
|
19
27
|
});
|
|
20
28
|
if (!res.ok || !res.body) {
|
|
21
29
|
await abortableDelay(RECONNECT_DELAY_MS, signal);
|
|
22
30
|
continue;
|
|
23
31
|
}
|
|
24
|
-
await pump(res.body, onFrame, signal)
|
|
32
|
+
await pump(res.body, onFrame, signal, (id) => {
|
|
33
|
+
lastEventId = id;
|
|
34
|
+
});
|
|
25
35
|
}
|
|
26
36
|
catch (err) {
|
|
27
37
|
if (signal.aborted)
|
|
@@ -31,7 +41,7 @@ export async function relayDebugStream(opts) {
|
|
|
31
41
|
await abortableDelay(RECONNECT_DELAY_MS, signal);
|
|
32
42
|
}
|
|
33
43
|
}
|
|
34
|
-
async function pump(body, onFrame, signal) {
|
|
44
|
+
async function pump(body, onFrame, signal, onId) {
|
|
35
45
|
const reader = body.getReader();
|
|
36
46
|
const decoder = new TextDecoder();
|
|
37
47
|
let buf = "";
|
|
@@ -44,10 +54,17 @@ async function pump(body, onFrame, signal) {
|
|
|
44
54
|
let sep;
|
|
45
55
|
// SSE frames are separated by a blank line.
|
|
46
56
|
while ((sep = buf.indexOf("\n\n")) >= 0) {
|
|
47
|
-
const
|
|
57
|
+
const block = buf.slice(0, sep);
|
|
48
58
|
buf = buf.slice(sep + 2);
|
|
49
|
-
|
|
50
|
-
|
|
59
|
+
const frame = parseSseData(block);
|
|
60
|
+
if (!frame)
|
|
61
|
+
continue;
|
|
62
|
+
onFrame(frame);
|
|
63
|
+
// Checkpoint AFTER delivery, so a frame the consumer never saw is not
|
|
64
|
+
// skipped on the next reconnect.
|
|
65
|
+
const id = parseSseId(block);
|
|
66
|
+
if (id !== null)
|
|
67
|
+
onId(id);
|
|
51
68
|
}
|
|
52
69
|
}
|
|
53
70
|
}
|
|
@@ -55,6 +72,17 @@ async function pump(body, onFrame, signal) {
|
|
|
55
72
|
reader.cancel().catch(() => undefined);
|
|
56
73
|
}
|
|
57
74
|
}
|
|
75
|
+
/** The `id:` of one SSE frame, or null when the producer sent none — an older
|
|
76
|
+
* kernel, whose stream simply has no resume point. */
|
|
77
|
+
function parseSseId(block) {
|
|
78
|
+
for (const line of block.split("\n")) {
|
|
79
|
+
if (!line.startsWith("id:"))
|
|
80
|
+
continue;
|
|
81
|
+
const parsed = Number.parseInt(line.slice(3).trim(), 10);
|
|
82
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
58
86
|
/** Extract and parse the `data:` payload of one SSE frame. Ignores comment
|
|
59
87
|
* lines (`: heartbeat`) and unparseable frames. */
|
|
60
88
|
function parseSseData(block) {
|
package/dist/debug/relay.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay.js","sourceRoot":"","sources":["../../src/debug/relay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAgBvD,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAE/B;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAuB;IAC5D,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACtC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,MAAM;gBACN,OAAO,EAAE,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"relay.js","sourceRoot":"","sources":["../../src/debug/relay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAgBvD,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAE/B;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAuB;IAC5D,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACtC,8EAA8E;IAC9E,0EAA0E;IAC1E,4EAA4E;IAC5E,sEAAsE;IACtE,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,MAAM;gBACN,OAAO,EAAE;oBACP,MAAM,EAAE,mBAAmB;oBAC3B,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACrE;aACF,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;gBACzB,MAAM,cAAc,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;gBACjD,SAAS;YACX,CAAC;YACD,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE;gBAC3C,WAAW,GAAG,EAAE,CAAC;YACnB,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,MAAM,CAAC,OAAO;gBAAE,OAAO;YAC3B,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,cAAc,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI,CACjB,IAAgC,EAChC,OAAoC,EACpC,MAAmB,EACnB,IAA0B;IAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACvB,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,OAAO;YACjB,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/C,IAAI,GAAW,CAAC;YAChB,4CAA4C;YAC5C,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;gBAChC,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;gBACzB,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;gBAClC,IAAI,CAAC,KAAK;oBAAE,SAAS;gBACrB,OAAO,CAAC,KAAK,CAAC,CAAC;gBACf,sEAAsE;gBACtE,iCAAiC;gBACjC,MAAM,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;gBAC7B,IAAI,EAAE,KAAK,IAAI;oBAAE,IAAI,CAAC,EAAE,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED;uDACuD;AACvD,SAAS,UAAU,CAAC,KAAa;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,SAAS;QACtC,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACzD,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IACjD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;oDACoD;AACpD,SAAS,YAAY,CAAC,KAAa;IACjC,MAAM,IAAI,GAAG,KAAK;SACf,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;SAC1C,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;SACxC,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type DebugFrame } from "@telorun/debug-wire";
|
|
2
|
+
import type { RunTrigger } from "../contract.js";
|
|
3
|
+
import type { SessionRegistry } from "../session/registry.js";
|
|
4
|
+
/**
|
|
5
|
+
* Projects per-app `run` events out of the kernel lifecycle events the debug
|
|
6
|
+
* stream already carries.
|
|
7
|
+
*
|
|
8
|
+
* The runner cannot see inside the container, and parsing the merged PTY stream
|
|
9
|
+
* is not a contract — so a watch session always runs with the kernel debug
|
|
10
|
+
* stream on and this reads it. A watch reload is a stop/start pair on ONE debug
|
|
11
|
+
* connection, so `generation` is counted here and the kernel is asked for
|
|
12
|
+
* nothing.
|
|
13
|
+
*
|
|
14
|
+
* Three event names are read, and only three:
|
|
15
|
+
* - `Kernel.Starting` → the generation began
|
|
16
|
+
* - `Kernel.Stopped` → it ended, carrying `exitCode`
|
|
17
|
+
* - `Kernel.RunFailed` → it never reached a running state, carrying why
|
|
18
|
+
*
|
|
19
|
+
* `Kernel.Started` is deliberately ignored: it and `Kernel.Starting` bracket the
|
|
20
|
+
* same transition, and one `started` per generation is the contract.
|
|
21
|
+
*/
|
|
22
|
+
export declare class RunProjection {
|
|
23
|
+
private readonly registry;
|
|
24
|
+
private readonly sessionId;
|
|
25
|
+
/** What to attribute the NEXT generation of each app to. A reload is a watch
|
|
26
|
+
* reload unless something told us otherwise, so `watch` is the resting value
|
|
27
|
+
* and `initial` / `manual` / `resume` are set by whoever caused them. */
|
|
28
|
+
private readonly triggers;
|
|
29
|
+
constructor(registry: SessionRegistry, sessionId: string);
|
|
30
|
+
/** Attribute an app's next generation. Called with `initial` when the session
|
|
31
|
+
* comes up, `manual` from the reload route, `resume` after a pod recreate. */
|
|
32
|
+
expect(app: string, trigger: RunTrigger): void;
|
|
33
|
+
/** Attribute every app's next generation — the session-wide cases (initial,
|
|
34
|
+
* resume) always move all of them together. */
|
|
35
|
+
expectAll(trigger: RunTrigger): void;
|
|
36
|
+
/** Feed one frame from `app`'s debug stream. Frames that are not one of the
|
|
37
|
+
* three lifecycle events pass through untouched. */
|
|
38
|
+
frame(app: string, frame: DebugFrame): void;
|
|
39
|
+
/**
|
|
40
|
+
* Close the open generation because its WORKLOAD ended, not because the kernel
|
|
41
|
+
* said so. A container that goes away under `--watch` emits no `Kernel.Stopped`
|
|
42
|
+
* — there is nothing left to emit it — so the backend reports the ending and
|
|
43
|
+
* this turns it into the same run outcome the kernel path produces.
|
|
44
|
+
*/
|
|
45
|
+
endGeneration(app: string, outcome: {
|
|
46
|
+
code?: number;
|
|
47
|
+
reason?: string;
|
|
48
|
+
}): void;
|
|
49
|
+
/** Open a generation unless one is already open — `Kernel.Starting` followed
|
|
50
|
+
* by a `Kernel.RunFailed` from the boot phase must not count twice. */
|
|
51
|
+
private begin;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=run-projection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-projection.d.ts","sourceRoot":"","sources":["../../src/debug/run-projection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,aAAa;IAOtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAP5B;;8EAE0E;IAC1E,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;gBAGvC,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,MAAM;IAGpC;mFAC+E;IAC/E,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI;IAI9C;oDACgD;IAChD,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAKpC;yDACqD;IACrD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI;IA4B3C;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAY7E;4EACwE;IACxE,OAAO,CAAC,KAAK;CASd"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { isEventFrame } from "@telorun/debug-wire";
|
|
2
|
+
/**
|
|
3
|
+
* Projects per-app `run` events out of the kernel lifecycle events the debug
|
|
4
|
+
* stream already carries.
|
|
5
|
+
*
|
|
6
|
+
* The runner cannot see inside the container, and parsing the merged PTY stream
|
|
7
|
+
* is not a contract — so a watch session always runs with the kernel debug
|
|
8
|
+
* stream on and this reads it. A watch reload is a stop/start pair on ONE debug
|
|
9
|
+
* connection, so `generation` is counted here and the kernel is asked for
|
|
10
|
+
* nothing.
|
|
11
|
+
*
|
|
12
|
+
* Three event names are read, and only three:
|
|
13
|
+
* - `Kernel.Starting` → the generation began
|
|
14
|
+
* - `Kernel.Stopped` → it ended, carrying `exitCode`
|
|
15
|
+
* - `Kernel.RunFailed` → it never reached a running state, carrying why
|
|
16
|
+
*
|
|
17
|
+
* `Kernel.Started` is deliberately ignored: it and `Kernel.Starting` bracket the
|
|
18
|
+
* same transition, and one `started` per generation is the contract.
|
|
19
|
+
*/
|
|
20
|
+
export class RunProjection {
|
|
21
|
+
registry;
|
|
22
|
+
sessionId;
|
|
23
|
+
/** What to attribute the NEXT generation of each app to. A reload is a watch
|
|
24
|
+
* reload unless something told us otherwise, so `watch` is the resting value
|
|
25
|
+
* and `initial` / `manual` / `resume` are set by whoever caused them. */
|
|
26
|
+
triggers = new Map();
|
|
27
|
+
constructor(registry, sessionId) {
|
|
28
|
+
this.registry = registry;
|
|
29
|
+
this.sessionId = sessionId;
|
|
30
|
+
}
|
|
31
|
+
/** Attribute an app's next generation. Called with `initial` when the session
|
|
32
|
+
* comes up, `manual` from the reload route, `resume` after a pod recreate. */
|
|
33
|
+
expect(app, trigger) {
|
|
34
|
+
this.triggers.set(app, trigger);
|
|
35
|
+
}
|
|
36
|
+
/** Attribute every app's next generation — the session-wide cases (initial,
|
|
37
|
+
* resume) always move all of them together. */
|
|
38
|
+
expectAll(trigger) {
|
|
39
|
+
const entry = this.registry.get(this.sessionId);
|
|
40
|
+
for (const app of entry?.apps.keys() ?? [])
|
|
41
|
+
this.triggers.set(app, trigger);
|
|
42
|
+
}
|
|
43
|
+
/** Feed one frame from `app`'s debug stream. Frames that are not one of the
|
|
44
|
+
* three lifecycle events pass through untouched. */
|
|
45
|
+
frame(app, frame) {
|
|
46
|
+
if (!isEventFrame(frame))
|
|
47
|
+
return;
|
|
48
|
+
switch (frame.event) {
|
|
49
|
+
case "Kernel.Starting":
|
|
50
|
+
this.begin(app);
|
|
51
|
+
return;
|
|
52
|
+
case "Kernel.Stopped":
|
|
53
|
+
this.registry.finishGeneration(this.sessionId, app, {
|
|
54
|
+
phase: "completed",
|
|
55
|
+
code: exitCodeOf(frame.payload),
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
58
|
+
case "Kernel.RunFailed":
|
|
59
|
+
// A LOAD failure emits no `Kernel.Starting` — the kernel never got that
|
|
60
|
+
// far — so open the generation here rather than reporting a failure of a
|
|
61
|
+
// generation the client never saw start. The pair is what a consumer
|
|
62
|
+
// reads as "this attempt happened and did not survive".
|
|
63
|
+
this.begin(app);
|
|
64
|
+
this.registry.finishGeneration(this.sessionId, app, {
|
|
65
|
+
phase: "failed",
|
|
66
|
+
reason: failureReason(frame.payload),
|
|
67
|
+
});
|
|
68
|
+
return;
|
|
69
|
+
default:
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Close the open generation because its WORKLOAD ended, not because the kernel
|
|
75
|
+
* said so. A container that goes away under `--watch` emits no `Kernel.Stopped`
|
|
76
|
+
* — there is nothing left to emit it — so the backend reports the ending and
|
|
77
|
+
* this turns it into the same run outcome the kernel path produces.
|
|
78
|
+
*/
|
|
79
|
+
endGeneration(app, outcome) {
|
|
80
|
+
const channel = this.registry.get(this.sessionId)?.apps.get(app);
|
|
81
|
+
if (!channel || channel.startedAt === null)
|
|
82
|
+
return;
|
|
83
|
+
this.registry.finishGeneration(this.sessionId, app, outcome.reason === undefined && outcome.code !== undefined
|
|
84
|
+
? { phase: "completed", code: outcome.code }
|
|
85
|
+
: { phase: "failed", reason: outcome.reason ?? "workload ended" });
|
|
86
|
+
}
|
|
87
|
+
/** Open a generation unless one is already open — `Kernel.Starting` followed
|
|
88
|
+
* by a `Kernel.RunFailed` from the boot phase must not count twice. */
|
|
89
|
+
begin(app) {
|
|
90
|
+
const channel = this.registry.get(this.sessionId)?.apps.get(app);
|
|
91
|
+
if (!channel || channel.startedAt !== null)
|
|
92
|
+
return;
|
|
93
|
+
const trigger = this.triggers.get(app) ?? "watch";
|
|
94
|
+
// Consumed: the next generation is a plain watch reload unless something
|
|
95
|
+
// says otherwise again.
|
|
96
|
+
this.triggers.delete(app);
|
|
97
|
+
this.registry.startGeneration(this.sessionId, app, trigger);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function exitCodeOf(payload) {
|
|
101
|
+
const code = payload?.exitCode;
|
|
102
|
+
return typeof code === "number" ? code : 0;
|
|
103
|
+
}
|
|
104
|
+
/** The most actionable thing the failure carries: a diagnostic code when the
|
|
105
|
+
* kernel had one (`CEL_UNKNOWN_FIELD`, `ERR_MANIFEST_VALIDATION_FAILED`), else
|
|
106
|
+
* its message. A code is what a reader — an agent above all — branches on. */
|
|
107
|
+
function failureReason(payload) {
|
|
108
|
+
const p = payload;
|
|
109
|
+
if (typeof p?.code === "string" && p.code !== "")
|
|
110
|
+
return p.code;
|
|
111
|
+
if (typeof p?.message === "string" && p.message !== "")
|
|
112
|
+
return p.message;
|
|
113
|
+
return "run failed";
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=run-projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-projection.js","sourceRoot":"","sources":["../../src/debug/run-projection.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,15 +5,21 @@ export * from "./server.js";
|
|
|
5
5
|
export { sessionConfigSchema, type SessionConfigSchemaOptions } from "./capabilities-schema.js";
|
|
6
6
|
export { BaseImageCatalog, filterTags, parseDockerHubRef, resolveTagDigest, type TagFilter, type BaseImageCatalogOptions, } from "./base-image-catalog.js";
|
|
7
7
|
export { extractDependencyKey, type DependencyKey } from "./dependency-key.js";
|
|
8
|
-
export { SessionRegistry, SessionLimitError, SessionEvictedError, type SessionEntry, type RegistryDeps, } from "./session/registry.js";
|
|
8
|
+
export { SessionRegistry, SessionLimitError, SessionEvictedError, UnknownAppError, type AppChannel, type RunAttribution, type SessionEntry, type RegisterArgs, type RegistryDeps, type WorkspaceCheckpoint, } from "./session/registry.js";
|
|
9
|
+
export { WatchSupervisor, type WatchSupervisorDeps } from "./session/watch-supervisor.js";
|
|
10
|
+
export { RunProjection } from "./debug/run-projection.js";
|
|
11
|
+
export { portKey, portsResolvedFrom, PORTS_RESOLVED_EVENT, } from "./debug/ports-resolved.js";
|
|
9
12
|
export { EventRingBuffer, type BufferedEvent } from "./session/ring-buffer.js";
|
|
10
13
|
export { ByteRingBuffer, type BufferedBytes } from "./session/byte-ring-buffer.js";
|
|
11
14
|
export { normalizeBundlePath, validateSessionId, BundlePathError } from "./session/bundle-path.js";
|
|
15
|
+
export { WorkspaceClient } from "./session/workspace-client.js";
|
|
16
|
+
export { workspaceAppManifest, WORKSPACE_APP_FILENAME } from "./session/workspace-app.js";
|
|
17
|
+
export { workspaceMarkerWrite, WORKSPACE_MARKER_CONTENTS, WORKSPACE_MARKER_FILENAME, } from "./session/workspace-marker.js";
|
|
12
18
|
export { streamSessionEvents, type SseStreamArgs } from "./sse/channel.js";
|
|
13
19
|
export { healthRoute } from "./routes/health.js";
|
|
14
20
|
export { capabilitiesRoute } from "./routes/capabilities.js";
|
|
15
21
|
export { probeRoute, type ProbeRouteDeps } from "./routes/probe.js";
|
|
16
|
-
export { sessionsRoute, type SessionsRouteDeps } from "./routes/sessions.js";
|
|
22
|
+
export { sessionsRoute, type SessionsRouteDeps, type WatchConfig } from "./routes/sessions.js";
|
|
17
23
|
export { appsRoute, type AppsRouteDeps } from "./routes/apps.js";
|
|
18
24
|
export { ioRoute, type IoRouteDeps } from "./routes/io.js";
|
|
19
25
|
export { relayDebugStream, type DebugRelayOptions } from "./debug/relay.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,KAAK,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAChG,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,SAAS,EACd,KAAK,uBAAuB,GAC7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE/E,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,KAAK,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAChG,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,SAAS,EACd,KAAK,uBAAuB,GAC7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE/E,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,mBAAmB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,KAAK,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EACL,OAAO,EACP,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAC1F,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC/F,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,10 +5,16 @@ export * from "./server.js";
|
|
|
5
5
|
export { sessionConfigSchema } from "./capabilities-schema.js";
|
|
6
6
|
export { BaseImageCatalog, filterTags, parseDockerHubRef, resolveTagDigest, } from "./base-image-catalog.js";
|
|
7
7
|
export { extractDependencyKey } from "./dependency-key.js";
|
|
8
|
-
export { SessionRegistry, SessionLimitError, SessionEvictedError, } from "./session/registry.js";
|
|
8
|
+
export { SessionRegistry, SessionLimitError, SessionEvictedError, UnknownAppError, } from "./session/registry.js";
|
|
9
|
+
export { WatchSupervisor } from "./session/watch-supervisor.js";
|
|
10
|
+
export { RunProjection } from "./debug/run-projection.js";
|
|
11
|
+
export { portKey, portsResolvedFrom, PORTS_RESOLVED_EVENT, } from "./debug/ports-resolved.js";
|
|
9
12
|
export { EventRingBuffer } from "./session/ring-buffer.js";
|
|
10
13
|
export { ByteRingBuffer } from "./session/byte-ring-buffer.js";
|
|
11
14
|
export { normalizeBundlePath, validateSessionId, BundlePathError } from "./session/bundle-path.js";
|
|
15
|
+
export { WorkspaceClient } from "./session/workspace-client.js";
|
|
16
|
+
export { workspaceAppManifest, WORKSPACE_APP_FILENAME } from "./session/workspace-app.js";
|
|
17
|
+
export { workspaceMarkerWrite, WORKSPACE_MARKER_CONTENTS, WORKSPACE_MARKER_FILENAME, } from "./session/workspace-marker.js";
|
|
12
18
|
export { streamSessionEvents } from "./sse/channel.js";
|
|
13
19
|
export { healthRoute } from "./routes/health.js";
|
|
14
20
|
export { capabilitiesRoute } from "./routes/capabilities.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAmC,MAAM,0BAA0B,CAAC;AAChG,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,gBAAgB,GAGjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAsB,MAAM,qBAAqB,CAAC;AAE/E,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAmC,MAAM,0BAA0B,CAAC;AAChG,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,gBAAgB,GAGjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAsB,MAAM,qBAAqB,CAAC;AAE/E,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,GAOhB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAA4B,MAAM,+BAA+B,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EACL,OAAO,EACP,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,eAAe,EAAsB,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAsB,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAC1F,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAsB,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAuB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,aAAa,EAA4C,MAAM,sBAAsB,CAAC;AAC/F,OAAO,EAAE,SAAS,EAAsB,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAoB,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAA0B,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EACL,iBAAiB,GAElB,MAAM,mBAAmB,CAAC"}
|
package/dist/routes/apps.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FastifyPluginAsync } from "fastify";
|
|
2
2
|
import type { RunnerBackend } from "../backend.js";
|
|
3
3
|
import type { ResolvedRunnerApp } from "../config.js";
|
|
4
|
-
import type
|
|
4
|
+
import { type RunnerTerms } from "../contract.js";
|
|
5
5
|
import type { SessionRegistry } from "../session/registry.js";
|
|
6
6
|
export interface AppsRouteDeps {
|
|
7
7
|
backend: RunnerBackend;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/routes/apps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAEnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/routes/apps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAEnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAsC,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,eAAe,CAAC;IAC1B;kEAC8D;IAC9D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;+EAC2E;IAC3E,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;mCAE+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC1C;AAoBD;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,kBAAkB,CAiEjE"}
|
package/dist/routes/apps.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DEFAULT_APP_NAME } from "../contract.js";
|
|
1
2
|
import { enforceTerms, portsSchema, startWorkloadSession } from "./session-start.js";
|
|
2
3
|
const startAppBodySchema = {
|
|
3
4
|
type: "object",
|
|
@@ -48,15 +49,24 @@ export function appsRoute(deps) {
|
|
|
48
49
|
...appEntry.env,
|
|
49
50
|
};
|
|
50
51
|
return startWorkloadSession(app, deps, {
|
|
51
|
-
// Self-contained image — no bundle to deliver
|
|
52
|
-
//
|
|
52
|
+
// Self-contained image — no bundle to deliver, and no entry path:
|
|
53
|
+
// the image's own entrypoint runs.
|
|
53
54
|
bundle: { entryRelativePath: "telo.yaml", files: [] },
|
|
54
|
-
entryRelativePath: "telo.yaml",
|
|
55
55
|
env,
|
|
56
|
-
ports: req.body?.ports ?? [],
|
|
57
56
|
config: { image: appEntry.image, pullPolicy: appEntry.pullPolicy },
|
|
58
57
|
selfContained: true,
|
|
59
58
|
inspect: req.body?.inspect ?? false,
|
|
59
|
+
// An operator-predefined app session is one run of one application.
|
|
60
|
+
// Watch is a workspace shape, and this door carries no workspace.
|
|
61
|
+
mode: "run",
|
|
62
|
+
apps: [
|
|
63
|
+
{
|
|
64
|
+
name: DEFAULT_APP_NAME,
|
|
65
|
+
entryRelativePath: "",
|
|
66
|
+
ports: req.body?.ports ?? [],
|
|
67
|
+
io: "tty",
|
|
68
|
+
},
|
|
69
|
+
],
|
|
60
70
|
}, reply);
|
|
61
71
|
});
|
|
62
72
|
};
|
package/dist/routes/apps.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/routes/apps.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/routes/apps.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/io.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../../src/routes/io.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,kBAAkB,EAAkB,MAAM,SAAS,CAAC;AAKnF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,eAAe,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;CAC7B;
|
|
1
|
+
{"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../../src/routes/io.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,kBAAkB,EAAkB,MAAM,SAAS,CAAC;AAKnF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,eAAe,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;CAC7B;AAuBD,wBAAgB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,kBAAkB,CAQ7D"}
|