@solarisdk/core 0.1.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/LICENSE +17 -0
- package/README.md +21 -0
- package/dist/desktop.d.ts +106 -0
- package/dist/desktop.d.ts.map +1 -0
- package/dist/desktop.js +170 -0
- package/dist/desktop.js.map +1 -0
- package/dist/errors.d.ts +50 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +91 -0
- package/dist/errors.js.map +1 -0
- package/dist/handle.d.ts +169 -0
- package/dist/handle.d.ts.map +1 -0
- package/dist/handle.js +386 -0
- package/dist/handle.js.map +1 -0
- package/dist/http.d.ts +35 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +106 -0
- package/dist/http.js.map +1 -0
- package/dist/image.d.ts +85 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +126 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/sandbox.d.ts +8 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +15 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/template-client.d.ts +35 -0
- package/dist/template-client.d.ts.map +1 -0
- package/dist/template-client.js +95 -0
- package/dist/template-client.js.map +1 -0
- package/dist/transport.d.ts +108 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +337 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +591 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/ws.d.ts +18 -0
- package/dist/ws.d.ts.map +1 -0
- package/dist/ws.js +63 -0
- package/dist/ws.js.map +1 -0
- package/package.json +44 -0
package/dist/http.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Shared HTTP transport for the SDK ⇆ Gateway REST API. Both `DesktopClient`
|
|
2
|
+
// and `SandboxClient` delegate here, so there is ONE place that owns auth
|
|
3
|
+
// headers, error mapping, retries/backoff, idempotency keys, and timeouts.
|
|
4
|
+
//
|
|
5
|
+
// Retry policy: idempotent requests (GET, DELETE, or any request carrying an
|
|
6
|
+
// Idempotency-Key) are retried on network errors, HTTP 5xx, 429, and bodies
|
|
7
|
+
// flagged `retryable`, with exponential backoff + jitter. Non-idempotent writes
|
|
8
|
+
// are never silently retried (could double-create) — pass an idempotencyKey to
|
|
9
|
+
// opt a create into safe retries.
|
|
10
|
+
import { ConnectionError, mapGatewayError, PinetreeError } from "./errors.js";
|
|
11
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
12
|
+
/** A fresh idempotency key (UUID where available). */
|
|
13
|
+
export function newIdempotencyKey() {
|
|
14
|
+
const c = globalThis.crypto;
|
|
15
|
+
return c?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2, 12)}`;
|
|
16
|
+
}
|
|
17
|
+
export class HttpTransport {
|
|
18
|
+
apiKey;
|
|
19
|
+
baseUrl;
|
|
20
|
+
fetchImpl;
|
|
21
|
+
maxRetries;
|
|
22
|
+
requestTimeoutMs;
|
|
23
|
+
retryDelayMs;
|
|
24
|
+
constructor(o) {
|
|
25
|
+
if (!o.apiKey)
|
|
26
|
+
throw new PinetreeError("HttpTransport requires an apiKey");
|
|
27
|
+
if (!o.baseUrl)
|
|
28
|
+
throw new PinetreeError("HttpTransport requires a baseUrl");
|
|
29
|
+
this.apiKey = o.apiKey;
|
|
30
|
+
this.baseUrl = o.baseUrl.replace(/\/+$/, "");
|
|
31
|
+
const f = o.fetch ?? globalThis.fetch;
|
|
32
|
+
if (typeof f !== "function") {
|
|
33
|
+
throw new PinetreeError("No fetch implementation available; pass `fetch` in options");
|
|
34
|
+
}
|
|
35
|
+
this.fetchImpl = f;
|
|
36
|
+
this.maxRetries = o.maxRetries ?? 3;
|
|
37
|
+
this.requestTimeoutMs = o.requestTimeoutMs ?? 30_000;
|
|
38
|
+
this.retryDelayMs = o.retryDelayMs;
|
|
39
|
+
}
|
|
40
|
+
/** `Authorization` header for handles + WS upgrades. */
|
|
41
|
+
authHeaders() {
|
|
42
|
+
return { Authorization: `Bearer ${this.apiKey}` };
|
|
43
|
+
}
|
|
44
|
+
/** ws:// (or wss://) origin derived from the gateway base URL. */
|
|
45
|
+
wsOrigin() {
|
|
46
|
+
return this.baseUrl.replace(/^http/, "ws");
|
|
47
|
+
}
|
|
48
|
+
async request(method, path, body, opts = {}) {
|
|
49
|
+
const idempotent = method === "GET" || method === "DELETE" || opts.idempotencyKey !== undefined;
|
|
50
|
+
const headers = {
|
|
51
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
52
|
+
Accept: "application/json",
|
|
53
|
+
};
|
|
54
|
+
if (body !== undefined)
|
|
55
|
+
headers["Content-Type"] = "application/json";
|
|
56
|
+
if (opts.idempotencyKey)
|
|
57
|
+
headers["Idempotency-Key"] = opts.idempotencyKey;
|
|
58
|
+
let attempt = 0;
|
|
59
|
+
for (;;) {
|
|
60
|
+
let res;
|
|
61
|
+
try {
|
|
62
|
+
res = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
63
|
+
method,
|
|
64
|
+
headers,
|
|
65
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
66
|
+
signal: AbortSignal.timeout(this.requestTimeoutMs),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
if (idempotent && attempt < this.maxRetries) {
|
|
71
|
+
await sleep(this.backoffMs(attempt++));
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
throw new ConnectionError(`${method} ${path} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
75
|
+
}
|
|
76
|
+
if (!res.ok) {
|
|
77
|
+
let errBody;
|
|
78
|
+
try {
|
|
79
|
+
errBody = (await res.json());
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
errBody = undefined;
|
|
83
|
+
}
|
|
84
|
+
// 5xx or an explicit `retryable` hint. NOT 429 — that's our
|
|
85
|
+
// ConcurrencyLimitError (org at its session cap); retrying won't help.
|
|
86
|
+
const retryable = res.status >= 500 || errBody?.retryable === true;
|
|
87
|
+
if (idempotent && retryable && attempt < this.maxRetries) {
|
|
88
|
+
await sleep(this.backoffMs(attempt++));
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
throw mapGatewayError(res.status, errBody);
|
|
92
|
+
}
|
|
93
|
+
// DELETE / empty bodies have no JSON.
|
|
94
|
+
const text = await res.text();
|
|
95
|
+
if (text.length === 0)
|
|
96
|
+
return undefined;
|
|
97
|
+
return JSON.parse(text);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
backoffMs(attempt) {
|
|
101
|
+
if (this.retryDelayMs !== undefined)
|
|
102
|
+
return this.retryDelayMs;
|
|
103
|
+
return Math.min(1000 * 2 ** attempt, 8000) + Math.floor(Math.random() * 250);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
package/dist/image.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export type ImageKind = "sandbox" | "desktop";
|
|
2
|
+
/** A local file/dir to stage into the build context (under `template-files/`). */
|
|
3
|
+
export interface LocalCopy {
|
|
4
|
+
src: string;
|
|
5
|
+
dest: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* A single ordered build operation. This is the backend-agnostic, structured
|
|
9
|
+
* form of the build recipe: the snapshot-based exec orchestrator (approach A)
|
|
10
|
+
* runs these directly (no Dockerfile parsing), while the Docker rootfs-rebuild
|
|
11
|
+
* path (approach B) renders them back to a `Dockerfile.fragment`. See
|
|
12
|
+
* docs/TEMPLATE-BUILD-PIPELINE.md.
|
|
13
|
+
*/
|
|
14
|
+
export type ImageStep = {
|
|
15
|
+
op: "pip";
|
|
16
|
+
packages: string[];
|
|
17
|
+
} | {
|
|
18
|
+
op: "run";
|
|
19
|
+
command: string;
|
|
20
|
+
} | {
|
|
21
|
+
op: "env";
|
|
22
|
+
key: string;
|
|
23
|
+
value: string;
|
|
24
|
+
} | {
|
|
25
|
+
op: "workdir";
|
|
26
|
+
dir: string;
|
|
27
|
+
} | {
|
|
28
|
+
op: "entrypoint";
|
|
29
|
+
command: string[];
|
|
30
|
+
} | {
|
|
31
|
+
op: "cmd";
|
|
32
|
+
command: string[];
|
|
33
|
+
};
|
|
34
|
+
/** The build-context inputs the pipeline consumes. */
|
|
35
|
+
export interface CompiledImage {
|
|
36
|
+
kind: ImageKind;
|
|
37
|
+
/** Conceptual base image (informational; the pipeline layers on Dockerfile.base/.sandbox). */
|
|
38
|
+
base?: string;
|
|
39
|
+
/** Build on top of an existing named template instead of a raw base. */
|
|
40
|
+
fromTemplate?: string;
|
|
41
|
+
/** apt packages → `template.packages` (installed before `steps`). */
|
|
42
|
+
packages: string[];
|
|
43
|
+
/** Ordered post-apt operations (approach A: exec'd in order). */
|
|
44
|
+
steps: ImageStep[];
|
|
45
|
+
/** Extra Dockerfile instructions rendered from `steps` (approach B: `Dockerfile.fragment`). */
|
|
46
|
+
fragment: string;
|
|
47
|
+
/** Local files staged into the context (copied to `/` preserving paths). */
|
|
48
|
+
localFiles: LocalCopy[];
|
|
49
|
+
}
|
|
50
|
+
export declare class Image {
|
|
51
|
+
private _kind;
|
|
52
|
+
private _base;
|
|
53
|
+
private _fromTemplate;
|
|
54
|
+
private readonly _packages;
|
|
55
|
+
private readonly _steps;
|
|
56
|
+
private readonly _localFiles;
|
|
57
|
+
private constructor();
|
|
58
|
+
/** Start from a base OS image (e.g. `"ubuntu:22.04"`). */
|
|
59
|
+
static base(image: string): Image;
|
|
60
|
+
/** Start from an existing Pinetree template (e.g. `"workstation"`). */
|
|
61
|
+
static fromTemplate(name: string): Image;
|
|
62
|
+
/** Set the session kind this image is for (`"sandbox"` headless or `"desktop"` GUI). */
|
|
63
|
+
kind(k: ImageKind): this;
|
|
64
|
+
/** apt packages installed by the pipeline's apt step. */
|
|
65
|
+
aptInstall(pkgs: string[]): this;
|
|
66
|
+
/** `RUN pip3 install …`. */
|
|
67
|
+
pipInstall(pkgs: string[]): this;
|
|
68
|
+
/** One `RUN` per command. */
|
|
69
|
+
runCommands(...cmds: string[]): this;
|
|
70
|
+
/** `ENV` vars. */
|
|
71
|
+
env(vars: Record<string, string>): this;
|
|
72
|
+
/** `WORKDIR`. */
|
|
73
|
+
workdir(dir: string): this;
|
|
74
|
+
/** `ENTRYPOINT` (exec form). */
|
|
75
|
+
entrypoint(cmd: string[]): this;
|
|
76
|
+
/** `CMD` (exec form). */
|
|
77
|
+
cmd(cmd: string[]): this;
|
|
78
|
+
/** Stage a local file into the guest at `dest` (copied via `template-files/`). */
|
|
79
|
+
addLocalFile(src: string, dest: string): this;
|
|
80
|
+
/** Stage a local directory into the guest at `dest`. */
|
|
81
|
+
addLocalDir(src: string, dest: string): this;
|
|
82
|
+
/** Compile to the build-context inputs. Pure + offline. */
|
|
83
|
+
compile(): CompiledImage;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAoBA,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAE9C,kFAAkF;AAClF,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GACjB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,GACjC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,EAAE,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GACvC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAErC,sDAAsD;AACtD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,8FAA8F;IAC9F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,iEAAiE;IACjE,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,+FAA+F;IAC/F,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAwBD,qBAAa,KAAK;IAChB,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmB;IAE/C,OAAO;IAEP,0DAA0D;IAC1D,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK;IAMjC,uEAAuE;IACvE,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK;IAMxC,wFAAwF;IACxF,IAAI,CAAC,CAAC,EAAE,SAAS,GAAG,IAAI;IAKxB,yDAAyD;IACzD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAKhC,4BAA4B;IAC5B,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAKhC,6BAA6B;IAC7B,WAAW,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAKpC,kBAAkB;IAClB,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAKvC,iBAAiB;IACjB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK1B,gCAAgC;IAChC,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI;IAK/B,yBAAyB;IACzB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI;IAKxB,kFAAkF;IAClF,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAK7C,wDAAwD;IACxD,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAK5C,2DAA2D;IAC3D,OAAO,IAAI,aAAa;CAWzB"}
|
package/dist/image.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// Declarative Image builder (Daytona-style). A fluent chain that compiles to
|
|
2
|
+
// the inputs our golden pipeline (`build-rootfs.sh`) already consumes per
|
|
3
|
+
// template: an apt `packages` list, a `Dockerfile.fragment`, and local files
|
|
4
|
+
// staged into `template-files/` (which the base Dockerfile COPYs to `/`).
|
|
5
|
+
//
|
|
6
|
+
// const img = Image.base("ubuntu:22.04")
|
|
7
|
+
// .aptInstall(["ffmpeg"])
|
|
8
|
+
// .pipInstall(["pandas", "matplotlib"])
|
|
9
|
+
// .runCommands("curl -fsSL https://example.com/i.sh | sh")
|
|
10
|
+
// .addLocalDir("./assets", "/opt/assets")
|
|
11
|
+
// .env({ TZ: "UTC" })
|
|
12
|
+
// .workdir("/work");
|
|
13
|
+
// const tpl = await pt.templates.build(img, { name: "data-sci", kind: "sandbox" });
|
|
14
|
+
//
|
|
15
|
+
// `.compile()` emits a structured `steps[]` (typed ops the snapshot
|
|
16
|
+
// exec-orchestrator runs directly) plus a byte-identical `Dockerfile.fragment`
|
|
17
|
+
// (the Docker rebuild path). NOTE: `.compile()` is pure + offline (unit-tested);
|
|
18
|
+
// actually BUILDING a template (pt.templates.build) requires the gateway
|
|
19
|
+
// `/templates` backend — Phases 2-6 in docs/TEMPLATE-BUILD-PIPELINE.md.
|
|
20
|
+
function envValue(v) {
|
|
21
|
+
return /\s/.test(v) ? JSON.stringify(v) : v;
|
|
22
|
+
}
|
|
23
|
+
/** Render one structured step to its Dockerfile line (approach B). */
|
|
24
|
+
function renderDockerfile(step) {
|
|
25
|
+
switch (step.op) {
|
|
26
|
+
case "pip":
|
|
27
|
+
return `RUN pip3 install --no-cache-dir ${step.packages.join(" ")}`;
|
|
28
|
+
case "run":
|
|
29
|
+
return `RUN ${step.command}`;
|
|
30
|
+
case "env":
|
|
31
|
+
return `ENV ${step.key}=${envValue(step.value)}`;
|
|
32
|
+
case "workdir":
|
|
33
|
+
return `WORKDIR ${step.dir}`;
|
|
34
|
+
case "entrypoint":
|
|
35
|
+
return `ENTRYPOINT ${JSON.stringify(step.command)}`;
|
|
36
|
+
case "cmd":
|
|
37
|
+
return `CMD ${JSON.stringify(step.command)}`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export class Image {
|
|
41
|
+
_kind = "sandbox";
|
|
42
|
+
_base;
|
|
43
|
+
_fromTemplate;
|
|
44
|
+
_packages = [];
|
|
45
|
+
_steps = [];
|
|
46
|
+
_localFiles = [];
|
|
47
|
+
constructor() { }
|
|
48
|
+
/** Start from a base OS image (e.g. `"ubuntu:22.04"`). */
|
|
49
|
+
static base(image) {
|
|
50
|
+
const i = new Image();
|
|
51
|
+
i._base = image;
|
|
52
|
+
return i;
|
|
53
|
+
}
|
|
54
|
+
/** Start from an existing Pinetree template (e.g. `"workstation"`). */
|
|
55
|
+
static fromTemplate(name) {
|
|
56
|
+
const i = new Image();
|
|
57
|
+
i._fromTemplate = name;
|
|
58
|
+
return i;
|
|
59
|
+
}
|
|
60
|
+
/** Set the session kind this image is for (`"sandbox"` headless or `"desktop"` GUI). */
|
|
61
|
+
kind(k) {
|
|
62
|
+
this._kind = k;
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
/** apt packages installed by the pipeline's apt step. */
|
|
66
|
+
aptInstall(pkgs) {
|
|
67
|
+
this._packages.push(...pkgs);
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
/** `RUN pip3 install …`. */
|
|
71
|
+
pipInstall(pkgs) {
|
|
72
|
+
if (pkgs.length)
|
|
73
|
+
this._steps.push({ op: "pip", packages: [...pkgs] });
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
/** One `RUN` per command. */
|
|
77
|
+
runCommands(...cmds) {
|
|
78
|
+
for (const c of cmds)
|
|
79
|
+
this._steps.push({ op: "run", command: c });
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
/** `ENV` vars. */
|
|
83
|
+
env(vars) {
|
|
84
|
+
for (const [k, v] of Object.entries(vars))
|
|
85
|
+
this._steps.push({ op: "env", key: k, value: v });
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
/** `WORKDIR`. */
|
|
89
|
+
workdir(dir) {
|
|
90
|
+
this._steps.push({ op: "workdir", dir });
|
|
91
|
+
return this;
|
|
92
|
+
}
|
|
93
|
+
/** `ENTRYPOINT` (exec form). */
|
|
94
|
+
entrypoint(cmd) {
|
|
95
|
+
this._steps.push({ op: "entrypoint", command: [...cmd] });
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
/** `CMD` (exec form). */
|
|
99
|
+
cmd(cmd) {
|
|
100
|
+
this._steps.push({ op: "cmd", command: [...cmd] });
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
/** Stage a local file into the guest at `dest` (copied via `template-files/`). */
|
|
104
|
+
addLocalFile(src, dest) {
|
|
105
|
+
this._localFiles.push({ src, dest });
|
|
106
|
+
return this;
|
|
107
|
+
}
|
|
108
|
+
/** Stage a local directory into the guest at `dest`. */
|
|
109
|
+
addLocalDir(src, dest) {
|
|
110
|
+
this._localFiles.push({ src, dest });
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
/** Compile to the build-context inputs. Pure + offline. */
|
|
114
|
+
compile() {
|
|
115
|
+
return {
|
|
116
|
+
kind: this._kind,
|
|
117
|
+
...(this._base !== undefined ? { base: this._base } : {}),
|
|
118
|
+
...(this._fromTemplate !== undefined ? { fromTemplate: this._fromTemplate } : {}),
|
|
119
|
+
packages: [...this._packages],
|
|
120
|
+
steps: this._steps.map((s) => ({ ...s })),
|
|
121
|
+
fragment: this._steps.length ? this._steps.map(renderDockerfile).join("\n") + "\n" : "",
|
|
122
|
+
localFiles: [...this._localFiles],
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { SessionHandle } from "./handle.js";
|
|
2
|
+
export type { SessionConfig, SessionHooks } from "./handle.js";
|
|
3
|
+
export { Desktop } from "./desktop.js";
|
|
4
|
+
export type { DesktopConfig } from "./desktop.js";
|
|
5
|
+
export { Sandbox } from "./sandbox.js";
|
|
6
|
+
export { Image } from "./image.js";
|
|
7
|
+
export type { CompiledImage, ImageKind, ImageStep, LocalCopy } from "./image.js";
|
|
8
|
+
export { TemplateClient } from "./template-client.js";
|
|
9
|
+
export type { TemplateClientOptions } from "./template-client.js";
|
|
10
|
+
export { HttpTransport, newIdempotencyKey } from "./http.js";
|
|
11
|
+
export { ActionError, AuthError, ConcurrencyLimitError, ConnectionError, GatewayError, NoCapacityError, PinetreeError, PlanError, TimeoutError, } from "./errors.js";
|
|
12
|
+
export type * from "./types.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEjF,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,EACL,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,eAAe,EACf,YAAY,EACZ,eAAe,EACf,aAAa,EACb,SAAS,EACT,YAAY,GACb,MAAM,aAAa,CAAC;AAErB,mBAAmB,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// @solarisdk/core — shared runtime for @solarisdk/desktop and @solarisdk/sandbox.
|
|
2
|
+
export { SessionHandle } from "./handle.js";
|
|
3
|
+
export { Desktop } from "./desktop.js";
|
|
4
|
+
export { Sandbox } from "./sandbox.js";
|
|
5
|
+
export { Image } from "./image.js";
|
|
6
|
+
export { TemplateClient } from "./template-client.js";
|
|
7
|
+
export { HttpTransport, newIdempotencyKey } from "./http.js";
|
|
8
|
+
export { ActionError, AuthError, ConcurrencyLimitError, ConnectionError, GatewayError, NoCapacityError, PinetreeError, PlanError, TimeoutError, } from "./errors.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAElF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,EACL,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,eAAe,EACf,YAAY,EACZ,eAAe,EACf,aAAa,EACb,SAAS,EACT,YAAY,GACb,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SessionHandle, type SessionConfig } from "./handle.js";
|
|
2
|
+
import type { CreateSandboxResponse } from "./types.js";
|
|
3
|
+
export declare class Sandbox extends SessionHandle {
|
|
4
|
+
/** The sandbox id (alias of {@link SessionHandle.id}). */
|
|
5
|
+
get sandboxId(): string;
|
|
6
|
+
constructor(session: CreateSandboxResponse, config?: SessionConfig);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD,qBAAa,OAAQ,SAAQ,aAAa;IACxC,0DAA0D;IAC1D,IAAI,SAAS,IAAI,MAAM,CAEtB;gBAEW,OAAO,EAAE,qBAAqB,EAAE,MAAM,GAAE,aAAkB;CAGvE"}
|
package/dist/sandbox.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// `Sandbox` — a handle to one live headless session. All of its surface lives
|
|
2
|
+
// on the shared {@link SessionHandle} base (commands, pty, runCode, files,
|
|
3
|
+
// volumes, metrics, snapshot, revert, pause/resume, setTimeout, env,
|
|
4
|
+
// kill). Construct via {@link SandboxClient}.
|
|
5
|
+
import { SessionHandle } from "./handle.js";
|
|
6
|
+
export class Sandbox extends SessionHandle {
|
|
7
|
+
/** The sandbox id (alias of {@link SessionHandle.id}). */
|
|
8
|
+
get sandboxId() {
|
|
9
|
+
return this.id;
|
|
10
|
+
}
|
|
11
|
+
constructor(session, config = {}) {
|
|
12
|
+
super(session.sandboxId, session.controlUrl, session.expiresAt, config);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2EAA2E;AAC3E,qEAAqE;AACrE,8CAA8C;AAE9C,OAAO,EAAE,aAAa,EAAsB,MAAM,aAAa,CAAC;AAGhE,MAAM,OAAO,OAAQ,SAAQ,aAAa;IACxC,0DAA0D;IAC1D,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,EAAE,CAAC;IACjB,CAAC;IAED,YAAY,OAA8B,EAAE,SAAwB,EAAE;QACpE,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC1E,CAAC;CACF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Image, type CompiledImage } from "./image.js";
|
|
2
|
+
import type { BuildTemplateOptions, BuildTemplateResponse, TemplateView } from "./types.js";
|
|
3
|
+
export interface TemplateClientOptions {
|
|
4
|
+
apiKey: string;
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
fetch?: typeof fetch;
|
|
7
|
+
/** Injectable sleep (tests drive the clock); defaults to real setTimeout. */
|
|
8
|
+
sleep?: (ms: number) => Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export declare class TemplateClient {
|
|
11
|
+
private readonly http;
|
|
12
|
+
private readonly sleep;
|
|
13
|
+
constructor(options: TemplateClientOptions);
|
|
14
|
+
/**
|
|
15
|
+
* Build a custom template from an {@link Image} (or a pre-{@link CompiledImage}).
|
|
16
|
+
* Kicks off the async gateway build then waits until it is `ready` (or throws
|
|
17
|
+
* on `failed`/timeout). Returns the final template view.
|
|
18
|
+
*/
|
|
19
|
+
build(image: Image | CompiledImage, opts: BuildTemplateOptions): Promise<TemplateView>;
|
|
20
|
+
/** Start a build without waiting (`POST /templates`). Returns ids immediately. */
|
|
21
|
+
buildRaw(image: Image | CompiledImage, opts: BuildTemplateOptions): Promise<BuildTemplateResponse>;
|
|
22
|
+
/** List templates — built-ins + this org's custom templates (`GET /templates`). */
|
|
23
|
+
list(): Promise<TemplateView[]>;
|
|
24
|
+
/** Get one template's status/metadata (`GET /templates/:id`). */
|
|
25
|
+
get(templateId: string): Promise<TemplateView>;
|
|
26
|
+
/** Delete a custom template (`DELETE /templates/:id`; refused while live sessions depend on it). */
|
|
27
|
+
delete(templateId: string): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Poll `GET /templates/:id` until it leaves `building`. Resolves on `ready`,
|
|
30
|
+
* throws on `failed`, throws on timeout. `onLog` is invoked best-effort as the
|
|
31
|
+
* gateway exposes build logs (a no-op until the log stream ships).
|
|
32
|
+
*/
|
|
33
|
+
waitUntilReady(templateId: string, opts: BuildTemplateOptions): Promise<TemplateView>;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=template-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-client.d.ts","sourceRoot":"","sources":["../src/template-client.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EACV,oBAAoB,EAEpB,qBAAqB,EAErB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAOD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;gBAE1C,OAAO,EAAE,qBAAqB;IAW1C;;;;OAIG;IACG,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,aAAa,EAAE,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,YAAY,CAAC;IAO5F,kFAAkF;IAC5E,QAAQ,CACZ,KAAK,EAAE,KAAK,GAAG,aAAa,EAC5B,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,qBAAqB,CAAC;IAcjC,mFAAmF;IAC7E,IAAI,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAKrC,iEAAiE;IACjE,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAO9C,oGAAoG;IAC9F,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/C;;;;OAIG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,YAAY,CAAC;CAsB5F"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// `TemplateClient` — talks the SDK ⇆ Gateway `/templates` HTTP API and turns a
|
|
2
|
+
// declarative {@link Image} into a reusable template a session can launch:
|
|
3
|
+
//
|
|
4
|
+
// const img = Image.base("ubuntu:22.04").aptInstall(["ffmpeg"]).kind("sandbox");
|
|
5
|
+
// const tpl = await pt.templates.build(img, { name: "media" });
|
|
6
|
+
// const sbx = await pt.sandboxes.create({ template: tpl.templateId });
|
|
7
|
+
//
|
|
8
|
+
// `build()` POSTs the compiled recipe (async build on the gateway) and then
|
|
9
|
+
// polls to completion. See docs/TEMPLATE-BUILD-PIPELINE.md.
|
|
10
|
+
import { PinetreeError } from "./errors.js";
|
|
11
|
+
import { HttpTransport, newIdempotencyKey } from "./http.js";
|
|
12
|
+
import { Image } from "./image.js";
|
|
13
|
+
const DEFAULT_BUILD_TIMEOUT_MS = 900_000; // 15 min
|
|
14
|
+
const DEFAULT_POLL_INTERVAL_MS = 3_000;
|
|
15
|
+
const realSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
16
|
+
export class TemplateClient {
|
|
17
|
+
http;
|
|
18
|
+
sleep;
|
|
19
|
+
constructor(options) {
|
|
20
|
+
if (!options.apiKey)
|
|
21
|
+
throw new PinetreeError("TemplateClient requires an apiKey");
|
|
22
|
+
if (!options.baseUrl)
|
|
23
|
+
throw new PinetreeError("TemplateClient requires a baseUrl");
|
|
24
|
+
this.sleep = options.sleep ?? realSleep;
|
|
25
|
+
this.http = new HttpTransport({
|
|
26
|
+
apiKey: options.apiKey,
|
|
27
|
+
baseUrl: options.baseUrl,
|
|
28
|
+
...(options.fetch ? { fetch: options.fetch } : {}),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Build a custom template from an {@link Image} (or a pre-{@link CompiledImage}).
|
|
33
|
+
* Kicks off the async gateway build then waits until it is `ready` (or throws
|
|
34
|
+
* on `failed`/timeout). Returns the final template view.
|
|
35
|
+
*/
|
|
36
|
+
async build(image, opts) {
|
|
37
|
+
if (!opts?.name)
|
|
38
|
+
throw new PinetreeError("templates.build requires a name");
|
|
39
|
+
const { buildId, templateId } = await this.buildRaw(image, opts);
|
|
40
|
+
void buildId; // reserved for future log-stream correlation
|
|
41
|
+
return this.waitUntilReady(templateId, opts);
|
|
42
|
+
}
|
|
43
|
+
/** Start a build without waiting (`POST /templates`). Returns ids immediately. */
|
|
44
|
+
async buildRaw(image, opts) {
|
|
45
|
+
const compiled = image instanceof Image ? image.compile() : image;
|
|
46
|
+
const body = {
|
|
47
|
+
name: opts.name,
|
|
48
|
+
kind: opts.kind ?? compiled.kind,
|
|
49
|
+
...(opts.cpu !== undefined ? { cpu: opts.cpu } : {}),
|
|
50
|
+
...(opts.memMb !== undefined ? { memMb: opts.memMb } : {}),
|
|
51
|
+
compiled,
|
|
52
|
+
};
|
|
53
|
+
return this.http.request("POST", "/templates", body, {
|
|
54
|
+
idempotencyKey: newIdempotencyKey(),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/** List templates — built-ins + this org's custom templates (`GET /templates`). */
|
|
58
|
+
async list() {
|
|
59
|
+
const res = await this.http.request("GET", "/templates");
|
|
60
|
+
return res.templates;
|
|
61
|
+
}
|
|
62
|
+
/** Get one template's status/metadata (`GET /templates/:id`). */
|
|
63
|
+
get(templateId) {
|
|
64
|
+
return this.http.request("GET", `/templates/${encodeURIComponent(templateId)}`);
|
|
65
|
+
}
|
|
66
|
+
/** Delete a custom template (`DELETE /templates/:id`; refused while live sessions depend on it). */
|
|
67
|
+
async delete(templateId) {
|
|
68
|
+
await this.http.request("DELETE", `/templates/${encodeURIComponent(templateId)}`);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Poll `GET /templates/:id` until it leaves `building`. Resolves on `ready`,
|
|
72
|
+
* throws on `failed`, throws on timeout. `onLog` is invoked best-effort as the
|
|
73
|
+
* gateway exposes build logs (a no-op until the log stream ships).
|
|
74
|
+
*/
|
|
75
|
+
async waitUntilReady(templateId, opts) {
|
|
76
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_BUILD_TIMEOUT_MS;
|
|
77
|
+
const pollMs = opts.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
78
|
+
const deadline = timeoutMs; // relative budget; decremented per poll (clock-free for tests)
|
|
79
|
+
let waited = 0;
|
|
80
|
+
for (;;) {
|
|
81
|
+
const view = await this.get(templateId);
|
|
82
|
+
if (view.status === "ready")
|
|
83
|
+
return view;
|
|
84
|
+
if (view.status === "failed") {
|
|
85
|
+
throw new PinetreeError(`template build failed for ${templateId}: ${view.error ?? "unknown error"}`);
|
|
86
|
+
}
|
|
87
|
+
if (waited >= deadline) {
|
|
88
|
+
throw new PinetreeError(`template build for ${templateId} did not complete within ${timeoutMs}ms`);
|
|
89
|
+
}
|
|
90
|
+
await this.sleep(pollMs);
|
|
91
|
+
waited += pollMs;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=template-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-client.js","sourceRoot":"","sources":["../src/template-client.ts"],"names":[],"mappings":"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"}
|