@telorun/runner-core 0.7.0 → 0.8.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/dist/backend.d.ts +1 -1
- package/dist/contract.d.ts +5 -12
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/routes/apps.d.ts +29 -0
- package/dist/routes/apps.d.ts.map +1 -0
- package/dist/routes/apps.js +64 -0
- package/dist/routes/apps.js.map +1 -0
- package/dist/routes/session-start.d.ts +59 -0
- package/dist/routes/session-start.d.ts.map +1 -0
- package/dist/routes/session-start.js +129 -0
- package/dist/routes/session-start.js.map +1 -0
- package/dist/routes/sessions.d.ts +2 -7
- package/dist/routes/sessions.d.ts.map +1 -1
- package/dist/routes/sessions.js +28 -175
- package/dist/routes/sessions.js.map +1 -1
- package/dist/server.d.ts +2 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +8 -1
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/src/backend.ts +1 -1
- package/src/contract.ts +5 -12
- package/src/index.ts +1 -0
- package/src/routes/apps.ts +106 -0
- package/src/routes/session-start.ts +174 -0
- package/src/routes/sessions.ts +34 -196
- package/src/server.ts +12 -2
package/dist/backend.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export interface BackendStartSpec {
|
|
|
34
34
|
env: Record<string, string>;
|
|
35
35
|
ports: PortMapping[];
|
|
36
36
|
config: SessionConfig;
|
|
37
|
-
/** True for an operator-predefined app session (`
|
|
37
|
+
/** True for an operator-predefined app session (`POST /v1/apps/:name/sessions`):
|
|
38
38
|
* `config.image` is self-contained (app + controllers baked in), so the
|
|
39
39
|
* backend runs the image's own entrypoint and stages no bundle — `bundle`
|
|
40
40
|
* is an empty placeholder. */
|
package/dist/contract.d.ts
CHANGED
|
@@ -29,8 +29,8 @@ export interface RunnerCapabilities {
|
|
|
29
29
|
* matching `terms.version`. The editor surfaces it and records acceptance. */
|
|
30
30
|
terms?: RunnerTerms;
|
|
31
31
|
/** Operator-predefined applications this runner can launch by name
|
|
32
|
-
* (`
|
|
33
|
-
* hide the corresponding entry points. */
|
|
32
|
+
* (`POST /v1/apps/:name/sessions`). Absent/empty when none are offered —
|
|
33
|
+
* clients hide the corresponding entry points. */
|
|
34
34
|
apps?: RunnerAppDescriptor[];
|
|
35
35
|
}
|
|
36
36
|
/** An operator-defined agreement. `version` is opaque and operator-controlled;
|
|
@@ -54,7 +54,7 @@ export interface RunnerFeatures {
|
|
|
54
54
|
* secrets. Which apps exist is pure operator configuration (`RUNNER_APPS`);
|
|
55
55
|
* the runner has no built-in knowledge of any specific app. */
|
|
56
56
|
export interface RunnerAppDescriptor {
|
|
57
|
-
/** Wire id
|
|
57
|
+
/** Wire id: an app session is created via `POST /v1/apps/<name>/sessions`. */
|
|
58
58
|
name: string;
|
|
59
59
|
title?: string;
|
|
60
60
|
description?: string;
|
|
@@ -113,17 +113,10 @@ export interface RunnerEndpoint {
|
|
|
113
113
|
url?: string;
|
|
114
114
|
}
|
|
115
115
|
export interface StartSessionRequest {
|
|
116
|
-
|
|
117
|
-
* {@link RunnerAppDescriptor}) instead of a client bundle. The runner
|
|
118
|
-
* resolves the image and injects the app's operator env server-side;
|
|
119
|
-
* `bundle` and `config.image` are ignored. */
|
|
120
|
-
app?: string;
|
|
121
|
-
/** Required unless `app` is set. */
|
|
122
|
-
bundle?: RunBundle;
|
|
116
|
+
bundle: RunBundle;
|
|
123
117
|
env: Record<string, string>;
|
|
124
118
|
ports?: PortMapping[];
|
|
125
|
-
|
|
126
|
-
config?: SessionConfig;
|
|
119
|
+
config: SessionConfig;
|
|
127
120
|
/** Request the kernel debug stream. When true the runner launches the
|
|
128
121
|
* workload with `--inspect`, subscribes to the in-workload inspect endpoint
|
|
129
122
|
* (reachable only by the runner — never published outward), and relays each
|
package/dist/contract.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAExD;;;;;;;;GAQG;AACH,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QAAE,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB;;;;mFAI+E;IAC/E,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
|
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;AAuH7D,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;AAeD,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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export { healthRoute } from "./routes/health.js";
|
|
|
14
14
|
export { capabilitiesRoute } from "./routes/capabilities.js";
|
|
15
15
|
export { probeRoute, type ProbeRouteDeps } from "./routes/probe.js";
|
|
16
16
|
export { sessionsRoute, type SessionsRouteDeps } from "./routes/sessions.js";
|
|
17
|
+
export { appsRoute, type AppsRouteDeps } from "./routes/apps.js";
|
|
17
18
|
export { ioRoute, type IoRouteDeps } from "./routes/io.js";
|
|
18
19
|
export { relayDebugStream, type DebugRelayOptions } from "./debug/relay.js";
|
|
19
20
|
export { watchReachability, type WatchReachabilityOptions, } from "./reachability.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,GAClB,MAAM,uBAAuB,CAAC;AAC/B,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,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,MAAM,sBAAsB,CAAC;AAC7E,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"}
|
|
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,GAClB,MAAM,uBAAuB,CAAC;AAC/B,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,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,MAAM,sBAAsB,CAAC;AAC7E,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
|
@@ -14,6 +14,7 @@ export { healthRoute } from "./routes/health.js";
|
|
|
14
14
|
export { capabilitiesRoute } from "./routes/capabilities.js";
|
|
15
15
|
export { probeRoute } from "./routes/probe.js";
|
|
16
16
|
export { sessionsRoute } from "./routes/sessions.js";
|
|
17
|
+
export { appsRoute } from "./routes/apps.js";
|
|
17
18
|
export { ioRoute } from "./routes/io.js";
|
|
18
19
|
export { relayDebugStream } from "./debug/relay.js";
|
|
19
20
|
export { watchReachability, } from "./reachability.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,GAGpB,MAAM,uBAAuB,CAAC;AAC/B,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,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,EAA0B,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAoB,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAA0B,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EACL,iBAAiB,GAElB,MAAM,mBAAmB,CAAC"}
|
|
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,GAGpB,MAAM,uBAAuB,CAAC;AAC/B,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,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,EAA0B,MAAM,sBAAsB,CAAC;AAC7E,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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { FastifyPluginAsync } from "fastify";
|
|
2
|
+
import type { RunnerBackend } from "../backend.js";
|
|
3
|
+
import type { ResolvedRunnerApp } from "../config.js";
|
|
4
|
+
import type { RunnerTerms } from "../contract.js";
|
|
5
|
+
import type { SessionRegistry } from "../session/registry.js";
|
|
6
|
+
export interface AppsRouteDeps {
|
|
7
|
+
backend: RunnerBackend;
|
|
8
|
+
registry: SessionRegistry;
|
|
9
|
+
/** The runner's own default registry URL, surfaced to the workload as
|
|
10
|
+
* TELO_REGISTRY_URL when the request doesn't override it. */
|
|
11
|
+
defaultRegistryUrl?: string;
|
|
12
|
+
/** Terms gate shared with `POST /v1/sessions` — app sessions execute on the
|
|
13
|
+
* operator's infrastructure just like runs, so they ride the same 428. */
|
|
14
|
+
terms?: RunnerTerms;
|
|
15
|
+
/** Operator-predefined applications launchable by name. The catalog is the
|
|
16
|
+
* whole gate: the client picks a name, never an image, and the operator env
|
|
17
|
+
* is injected server-side. */
|
|
18
|
+
apps?: Record<string, ResolvedRunnerApp>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Creation door for operator-predefined app sessions. A client launches an app
|
|
22
|
+
* by name; the runner resolves the image and injects the app's operator env
|
|
23
|
+
* from the catalog (`RUNNER_APPS`). The created session lives in the SAME
|
|
24
|
+
* session collection as bundle sessions — the 201 carries the shared
|
|
25
|
+
* `/v1/sessions/:id/events` stream URL, and status/DELETE/io are served by the
|
|
26
|
+
* sessions routes.
|
|
27
|
+
*/
|
|
28
|
+
export declare function appsRoute(deps: AppsRouteDeps): FastifyPluginAsync;
|
|
29
|
+
//# sourceMappingURL=apps.d.ts.map
|
|
@@ -0,0 +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,EAAe,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC/D,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,CAwDjE"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { enforceTerms, portsSchema, startWorkloadSession } from "./session-start.js";
|
|
2
|
+
const startAppBodySchema = {
|
|
3
|
+
type: "object",
|
|
4
|
+
properties: {
|
|
5
|
+
env: {
|
|
6
|
+
type: "object",
|
|
7
|
+
additionalProperties: { type: "string" },
|
|
8
|
+
},
|
|
9
|
+
ports: portsSchema,
|
|
10
|
+
inspect: { type: "boolean" },
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Creation door for operator-predefined app sessions. A client launches an app
|
|
15
|
+
* by name; the runner resolves the image and injects the app's operator env
|
|
16
|
+
* from the catalog (`RUNNER_APPS`). The created session lives in the SAME
|
|
17
|
+
* session collection as bundle sessions — the 201 carries the shared
|
|
18
|
+
* `/v1/sessions/:id/events` stream URL, and status/DELETE/io are served by the
|
|
19
|
+
* sessions routes.
|
|
20
|
+
*/
|
|
21
|
+
export function appsRoute(deps) {
|
|
22
|
+
return async (app) => {
|
|
23
|
+
app.post("/v1/apps/:name/sessions", { schema: { body: startAppBodySchema } }, async (req, reply) => {
|
|
24
|
+
// Resolve the app before the terms gate: an unknown name is a 404
|
|
25
|
+
// regardless of terms (there's no workload to gate), and the catalog is
|
|
26
|
+
// already public on /v1/capabilities, so this leaks nothing.
|
|
27
|
+
const appEntry = deps.apps?.[req.params.name];
|
|
28
|
+
if (!appEntry) {
|
|
29
|
+
const offered = Object.keys(deps.apps ?? {});
|
|
30
|
+
reply.code(404).send({
|
|
31
|
+
error: "unknown_app",
|
|
32
|
+
message: `app '${req.params.name}' is not offered by this runner` +
|
|
33
|
+
(offered.length > 0
|
|
34
|
+
? ` — offered apps: ${offered.join(", ")}`
|
|
35
|
+
: " — it offers no predefined applications") +
|
|
36
|
+
" (see /v1/capabilities).",
|
|
37
|
+
});
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (!enforceTerms(req, reply, deps.terms))
|
|
41
|
+
return;
|
|
42
|
+
// Drop client-supplied values for any env key the catalog defines (a
|
|
43
|
+
// client must never override operator-held values, which include
|
|
44
|
+
// secrets), then inject the operator's values.
|
|
45
|
+
const clientEnv = req.body?.env ?? {};
|
|
46
|
+
const env = {
|
|
47
|
+
...Object.fromEntries(Object.entries(clientEnv).filter(([key]) => !(key in appEntry.env))),
|
|
48
|
+
...appEntry.env,
|
|
49
|
+
};
|
|
50
|
+
return startWorkloadSession(app, deps, {
|
|
51
|
+
// Self-contained image — no bundle to deliver; the entry path is an
|
|
52
|
+
// unused placeholder so the backend spec stays total.
|
|
53
|
+
bundle: { entryRelativePath: "telo.yaml", files: [] },
|
|
54
|
+
entryRelativePath: "telo.yaml",
|
|
55
|
+
env,
|
|
56
|
+
ports: req.body?.ports ?? [],
|
|
57
|
+
config: { image: appEntry.image, pullPolicy: appEntry.pullPolicy },
|
|
58
|
+
selfContained: true,
|
|
59
|
+
inspect: req.body?.inspect ?? false,
|
|
60
|
+
}, reply);
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=apps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/routes/apps.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAuBrF,MAAM,kBAAkB,GAAG;IACzB,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,GAAG,EAAE;YACH,IAAI,EAAE,QAAQ;YACd,oBAAoB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;SACzC;QACD,KAAK,EAAE,WAAW;QAClB,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;KAC7B;CACO,CAAC;AAEX;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,IAAmB;IAC3C,OAAO,KAAK,EAAE,GAAoB,EAAE,EAAE;QACpC,GAAG,CAAC,IAAI,CACN,yBAAyB,EACzB,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,EAAE,EACxC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;YACnB,kEAAkE;YAClE,wEAAwE;YACxE,6DAA6D;YAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;gBAC7C,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,KAAK,EAAE,aAAa;oBACpB,OAAO,EACL,QAAQ,GAAG,CAAC,MAAM,CAAC,IAAI,iCAAiC;wBACxD,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;4BACjB,CAAC,CAAC,oBAAoB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;4BAC1C,CAAC,CAAC,yCAAyC,CAAC;wBAC9C,0BAA0B;iBAC7B,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC;gBAAE,OAAO;YAElD,qEAAqE;YACrE,iEAAiE;YACjE,+CAA+C;YAC/C,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;YACtC,MAAM,GAAG,GAAG;gBACV,GAAG,MAAM,CAAC,WAAW,CACnB,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CACpE;gBACD,GAAG,QAAQ,CAAC,GAAG;aAChB,CAAC;YAEF,OAAO,oBAAoB,CACzB,GAAG,EACH,IAAI,EACJ;gBACE,oEAAoE;gBACpE,sDAAsD;gBACtD,MAAM,EAAE,EAAE,iBAAiB,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE;gBACrD,iBAAiB,EAAE,WAAW;gBAC9B,GAAG;gBACH,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;gBAC5B,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE;gBAClE,aAAa,EAAE,IAAI;gBACnB,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,IAAI,KAAK;aACpC,EACD,KAAK,CACN,CAAC;QACJ,CAAC,CACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
|
|
2
|
+
import type { RunnerBackend } from "../backend.js";
|
|
3
|
+
import { type PortMapping, type RunBundle, type RunnerTerms, type SessionConfig } from "../contract.js";
|
|
4
|
+
import { type SessionRegistry } from "../session/registry.js";
|
|
5
|
+
/** JSON Schema for the `ports` body field, shared by every session-creating
|
|
6
|
+
* route so bundle and app sessions validate port mappings identically. */
|
|
7
|
+
export declare const portsSchema: {
|
|
8
|
+
readonly type: "array";
|
|
9
|
+
readonly items: {
|
|
10
|
+
readonly type: "object";
|
|
11
|
+
readonly required: readonly ["port", "protocol"];
|
|
12
|
+
readonly properties: {
|
|
13
|
+
readonly port: {
|
|
14
|
+
readonly type: "integer";
|
|
15
|
+
readonly minimum: 1;
|
|
16
|
+
readonly maximum: 65535;
|
|
17
|
+
};
|
|
18
|
+
readonly protocol: {
|
|
19
|
+
readonly type: "string";
|
|
20
|
+
readonly enum: readonly ["tcp", "udp"];
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Terms enforcement shared by every session-creating route — the server is the
|
|
27
|
+
* source of truth, so a client that skips the editor gate still can't start a
|
|
28
|
+
* workload without acknowledging the current terms version. Sends the 428 and
|
|
29
|
+
* returns false when the gate is closed.
|
|
30
|
+
*/
|
|
31
|
+
export declare function enforceTerms(req: FastifyRequest, reply: FastifyReply, terms: RunnerTerms | undefined): boolean;
|
|
32
|
+
/** Dependencies the shared session-creation leaf needs, independent of which
|
|
33
|
+
* route drives it. Both `SessionsRouteDeps` and `AppsRouteDeps` satisfy it. */
|
|
34
|
+
export interface WorkloadStartDeps {
|
|
35
|
+
backend: RunnerBackend;
|
|
36
|
+
registry: SessionRegistry;
|
|
37
|
+
/** The runner's own default registry URL, surfaced to the workload as
|
|
38
|
+
* TELO_REGISTRY_URL when the request doesn't override it. */
|
|
39
|
+
defaultRegistryUrl?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface WorkloadStartArgs {
|
|
42
|
+
bundle: RunBundle;
|
|
43
|
+
entryRelativePath: string;
|
|
44
|
+
env: Record<string, string>;
|
|
45
|
+
ports: PortMapping[];
|
|
46
|
+
config: SessionConfig;
|
|
47
|
+
selfContained: boolean;
|
|
48
|
+
inspect: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The session-creation leaf shared by `POST /v1/sessions` (bundle sessions) and
|
|
52
|
+
* `POST /v1/apps/:name/sessions` (operator-predefined apps): registers the
|
|
53
|
+
* session, responds 201 with the shared `/v1/sessions/:id/events` stream URL,
|
|
54
|
+
* and starts the workload in the background. Whatever door a session was
|
|
55
|
+
* created through, everything after creation lives in the one session
|
|
56
|
+
* collection (status, DELETE, events, io).
|
|
57
|
+
*/
|
|
58
|
+
export declare function startWorkloadSession(app: FastifyInstance, deps: WorkloadStartDeps, args: WorkloadStartArgs, reply: FastifyReply): Promise<void>;
|
|
59
|
+
//# sourceMappingURL=session-start.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-start.d.ts","sourceRoot":"","sources":["../../src/routes/session-start.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,aAAa,EACnB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEjF;2EAC2E;AAC3E,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;CAUd,CAAC;AAEX;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,WAAW,GAAG,SAAS,GAC7B,OAAO,CAST;AAED;gFACgF;AAChF,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,eAAe,CAAC;IAC1B;kEAC8D;IAC9D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,SAAS,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,MAAM,EAAE,aAAa,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,iBAAiB,EACvB,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CA0Ff"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { isEventFrame } from "@telorun/debug-wire";
|
|
2
|
+
import { ACCEPTED_TERMS_HEADER, SessionStartError, } from "../contract.js";
|
|
3
|
+
import { generateSessionId } from "../session/session-id.js";
|
|
4
|
+
import { SessionLimitError } from "../session/registry.js";
|
|
5
|
+
/** JSON Schema for the `ports` body field, shared by every session-creating
|
|
6
|
+
* route so bundle and app sessions validate port mappings identically. */
|
|
7
|
+
export const portsSchema = {
|
|
8
|
+
type: "array",
|
|
9
|
+
items: {
|
|
10
|
+
type: "object",
|
|
11
|
+
required: ["port", "protocol"],
|
|
12
|
+
properties: {
|
|
13
|
+
port: { type: "integer", minimum: 1, maximum: 65535 },
|
|
14
|
+
protocol: { type: "string", enum: ["tcp", "udp"] },
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Terms enforcement shared by every session-creating route — the server is the
|
|
20
|
+
* source of truth, so a client that skips the editor gate still can't start a
|
|
21
|
+
* workload without acknowledging the current terms version. Sends the 428 and
|
|
22
|
+
* returns false when the gate is closed.
|
|
23
|
+
*/
|
|
24
|
+
export function enforceTerms(req, reply, terms) {
|
|
25
|
+
if (!terms)
|
|
26
|
+
return true;
|
|
27
|
+
const raw = req.headers[ACCEPTED_TERMS_HEADER];
|
|
28
|
+
const accepted = Array.isArray(raw) ? raw[0] : raw;
|
|
29
|
+
if (accepted !== terms.version) {
|
|
30
|
+
reply.code(428).send({ error: "terms_required", terms });
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The session-creation leaf shared by `POST /v1/sessions` (bundle sessions) and
|
|
37
|
+
* `POST /v1/apps/:name/sessions` (operator-predefined apps): registers the
|
|
38
|
+
* session, responds 201 with the shared `/v1/sessions/:id/events` stream URL,
|
|
39
|
+
* and starts the workload in the background. Whatever door a session was
|
|
40
|
+
* created through, everything after creation lives in the one session
|
|
41
|
+
* collection (status, DELETE, events, io).
|
|
42
|
+
*/
|
|
43
|
+
export async function startWorkloadSession(app, deps, args, reply) {
|
|
44
|
+
const sessionId = generateSessionId();
|
|
45
|
+
let entry;
|
|
46
|
+
try {
|
|
47
|
+
entry = deps.registry.register({ sessionId });
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
if (err instanceof SessionLimitError) {
|
|
51
|
+
reply.code(409).send({ error: "too_many_sessions", message: err.message });
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
56
|
+
// Surface a TELO_REGISTRY_URL to the workload so the telo CLI inside picks
|
|
57
|
+
// it up. Precedence: explicit env value > config.registryUrl (per-request
|
|
58
|
+
// override) > runner's own default. Trim client-supplied URLs so stray
|
|
59
|
+
// whitespace from an editor input doesn't flow into the workload.
|
|
60
|
+
const configRegistryUrl = args.config.registryUrl?.trim() || undefined;
|
|
61
|
+
const registryUrl = configRegistryUrl ?? deps.defaultRegistryUrl;
|
|
62
|
+
const sessionEnv = registryUrl && !("TELO_REGISTRY_URL" in args.env)
|
|
63
|
+
? { ...args.env, TELO_REGISTRY_URL: registryUrl }
|
|
64
|
+
: args.env;
|
|
65
|
+
// Respond as soon as the session is registered — BEFORE the backend starts.
|
|
66
|
+
// `backend.start()` now spans the on-cluster image build and pod bring-up,
|
|
67
|
+
// which can take seconds-to-minutes; awaiting it here would hide the event
|
|
68
|
+
// stream until the workload is already up, so the client never sees build /
|
|
69
|
+
// provision / boot progress live. Returning the streamUrl first lets the
|
|
70
|
+
// client connect immediately; start runs in the background and its progress,
|
|
71
|
+
// output, and terminal status flow over the stream.
|
|
72
|
+
reply.code(201).send({
|
|
73
|
+
sessionId,
|
|
74
|
+
streamUrl: `/v1/sessions/${sessionId}/events`,
|
|
75
|
+
createdAt: entry.createdAt.toISOString(),
|
|
76
|
+
});
|
|
77
|
+
deps.backend
|
|
78
|
+
.start({
|
|
79
|
+
sessionId,
|
|
80
|
+
bundle: args.bundle,
|
|
81
|
+
entryRelativePath: args.entryRelativePath,
|
|
82
|
+
env: sessionEnv,
|
|
83
|
+
ports: args.ports,
|
|
84
|
+
config: args.config,
|
|
85
|
+
selfContained: args.selfContained,
|
|
86
|
+
inspect: args.inspect,
|
|
87
|
+
onStatus: (status) => deps.registry.emit(sessionId, { type: "status", status }),
|
|
88
|
+
onProgress: (phase, message, done) => deps.registry.emit(sessionId, { type: "progress", phase, message, done }),
|
|
89
|
+
onOutput: (chunk) => deps.registry.pushBytes(sessionId, chunk),
|
|
90
|
+
// Relay only kernel *event* frames to the client. stdout/stderr already
|
|
91
|
+
// arrive over the byte channel (onOutput), so forwarding log frames would
|
|
92
|
+
// double the traffic and let log spam evict lifecycle events from the
|
|
93
|
+
// byte-capped replay buffer. The editor discards relayed logs anyway.
|
|
94
|
+
onDebug: (frame) => {
|
|
95
|
+
if (isEventFrame(frame))
|
|
96
|
+
deps.registry.emit(sessionId, { type: "debug", frame });
|
|
97
|
+
},
|
|
98
|
+
onReachability: (port, state) => deps.registry.emit(sessionId, { type: "reachability", port, state }),
|
|
99
|
+
isUserStopped: () => entry.userStopped,
|
|
100
|
+
})
|
|
101
|
+
.then(async (session) => {
|
|
102
|
+
entry.session = session;
|
|
103
|
+
// Pre-start DELETE race: a DELETE received during backend.start (e.g.
|
|
104
|
+
// while an image build was running) can't stop a workload that didn't
|
|
105
|
+
// exist yet — it set userStopped and returned 204. Now that the workload
|
|
106
|
+
// is live, honor the earlier DELETE.
|
|
107
|
+
if (entry.userStopped) {
|
|
108
|
+
try {
|
|
109
|
+
await session.stop();
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
app.log.warn({ err, sessionId }, "failed to stop after race with pre-start DELETE");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
.catch((err) => {
|
|
117
|
+
// The 201 is already sent, so a start failure surfaces as a terminal
|
|
118
|
+
// `failed` status on the stream (the registry schedules eviction on a
|
|
119
|
+
// terminal status; the SSE channel delivers it, then closes).
|
|
120
|
+
const message = err instanceof SessionStartError
|
|
121
|
+
? `${err.stage}: ${err.message}`
|
|
122
|
+
: err instanceof Error
|
|
123
|
+
? err.message
|
|
124
|
+
: String(err);
|
|
125
|
+
app.log.error({ err, sessionId }, "session start failed");
|
|
126
|
+
deps.registry.emit(sessionId, { type: "status", status: { kind: "failed", message } });
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=session-start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-start.js","sourceRoot":"","sources":["../../src/routes/session-start.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { FastifyPluginAsync } from "fastify";
|
|
2
2
|
import type { RunnerBackend } from "../backend.js";
|
|
3
|
-
import {
|
|
4
|
-
import type {
|
|
5
|
-
import { type SessionRegistry } from "../session/registry.js";
|
|
3
|
+
import type { RunnerTerms, SessionConfig } from "../contract.js";
|
|
4
|
+
import type { SessionRegistry } from "../session/registry.js";
|
|
6
5
|
export interface SessionsRouteDeps {
|
|
7
6
|
backend: RunnerBackend;
|
|
8
7
|
registry: SessionRegistry;
|
|
@@ -13,10 +12,6 @@ export interface SessionsRouteDeps {
|
|
|
13
12
|
/** When set, a session may only start if the client acknowledges this exact
|
|
14
13
|
* terms version via the `x-telo-accepted-terms` header. */
|
|
15
14
|
terms?: RunnerTerms;
|
|
16
|
-
/** Operator-predefined applications launchable by name
|
|
17
|
-
* (`StartSessionRequest.app`), with their operator env already resolved.
|
|
18
|
-
* The catalog is the whole gate — an unknown name is rejected. */
|
|
19
|
-
apps?: Record<string, ResolvedRunnerApp>;
|
|
20
15
|
/** Backend-supplied config gate. Returns an error message to reject the
|
|
21
16
|
* request with `400 invalid_config`, or `undefined` to accept. The runner is
|
|
22
17
|
* the source of truth, so this re-checks what `/v1/capabilities` advertises
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,kBAAkB,EAAgB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,kBAAkB,EAAgB,MAAM,SAAS,CAAC;AAEjF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAuB,MAAM,gBAAgB,CAAC;AAEtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,eAAe,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IAC5B;kEAC8D;IAC9D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;gEAC4D;IAC5D,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;gFAG4E;IAC5E,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,MAAM,GAAG,SAAS,CAAC;CAChE;AA0CD,wBAAgB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,kBAAkB,CAwDzE"}
|