@sealant/sdk 0.15.0 → 0.17.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/effect/api-client.d.ts +18 -2
- package/dist/facade/workspace.js +3 -0
- package/dist/internal/blueprint.js +6 -1
- package/dist/types.d.ts +20 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -105,8 +105,9 @@ and injects them at launch.
|
|
|
105
105
|
|
|
106
106
|
## Workspace tools and services
|
|
107
107
|
|
|
108
|
-
Choose a supported operating-system family
|
|
109
|
-
that need runtime support rather than a
|
|
108
|
+
Choose a supported operating-system family — `fedora` (the default), `arch`, `nix`, or `ubuntu` —
|
|
109
|
+
request portable package names, and opt into services that need runtime support rather than a
|
|
110
|
+
package install:
|
|
110
111
|
|
|
111
112
|
```ts
|
|
112
113
|
const workspace = await sealant.workspaces.create({
|
|
@@ -123,6 +124,36 @@ const workspace = await sealant.workspaces.create({
|
|
|
123
124
|
rootless daemon at launch. The workspace receives `DOCKER_HOST`; Sealant never mounts the host
|
|
124
125
|
Docker socket. GitHub credentials provide both `GH_TOKEN` and `GITHUB_TOKEN` to the workspace.
|
|
125
126
|
|
|
127
|
+
## Custom base images
|
|
128
|
+
|
|
129
|
+
Instead of a managed OS family, a workspace image can be built from any image reference you already
|
|
130
|
+
trust:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
const workspace = await sealant.workspaces.create({
|
|
134
|
+
repository: "github.com/acme/billing-service",
|
|
135
|
+
harness: codex(),
|
|
136
|
+
baseImage: "node:22-bookworm",
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Distro package installs are skipped entirely — the build overlays only the `sealantd` supervisor
|
|
141
|
+
(PID 1), the harness CLIs (installed with `npm`), and a fully static `socat` (the control-socket
|
|
142
|
+
relay), all copied in as static binaries. This is the **base-image contract**, checked at build time
|
|
143
|
+
with readable failures:
|
|
144
|
+
|
|
145
|
+
- **Any Linux base, `amd64`/`arm64`**, with a **POSIX shell** at `/bin/sh`. Shells beyond that are
|
|
146
|
+
not assumed: the workspace login shell is `/bin/sh`, and `defaultShell` selection is not supported
|
|
147
|
+
with `baseImage`.
|
|
148
|
+
- **Node.js + npm** at or above the harness CLIs' floor (the CLIs are installed with
|
|
149
|
+
`npm install -g` and run on the base's node).
|
|
150
|
+
- **git**, for clone- and mount-sourced workspaces.
|
|
151
|
+
|
|
152
|
+
`packages` still works: names pass through **verbatim** (no portable-name resolution) to the base's
|
|
153
|
+
own package manager — `apt`, `apk`, `dnf`, or `pacman`, autodetected — and the build fails with a
|
|
154
|
+
readable error when the base has none. Dotfiles are not supported with `baseImage`. `baseImage` and
|
|
155
|
+
`os` are mutually exclusive.
|
|
156
|
+
|
|
126
157
|
## Inference on connected accounts
|
|
127
158
|
|
|
128
159
|
Run short, tool-calling inference loops on the caller's own subscription — server-side, through the
|
|
@@ -294,7 +294,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
294
294
|
readonly resolvePackage: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
295
295
|
readonly query: {
|
|
296
296
|
readonly query: string;
|
|
297
|
-
readonly targetOs?: "arch" | "fedora" | "nix" | undefined;
|
|
297
|
+
readonly targetOs?: "arch" | "fedora" | "nix" | "ubuntu" | undefined;
|
|
298
298
|
};
|
|
299
299
|
readonly responseMode?: Mode;
|
|
300
300
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
@@ -329,6 +329,14 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
329
329
|
readonly version?: string | undefined;
|
|
330
330
|
readonly status?: string | undefined;
|
|
331
331
|
};
|
|
332
|
+
readonly ubuntu: {
|
|
333
|
+
readonly supported: boolean;
|
|
334
|
+
readonly repo?: string | undefined;
|
|
335
|
+
readonly packageName?: string | undefined;
|
|
336
|
+
readonly projectName?: string | undefined;
|
|
337
|
+
readonly version?: string | undefined;
|
|
338
|
+
readonly status?: string | undefined;
|
|
339
|
+
};
|
|
332
340
|
};
|
|
333
341
|
readonly alternatives: readonly {
|
|
334
342
|
readonly projectName: string;
|
|
@@ -1604,7 +1612,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1604
1612
|
readonly resolvePackage: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1605
1613
|
readonly query: {
|
|
1606
1614
|
readonly query: string;
|
|
1607
|
-
readonly targetOs?: "arch" | "fedora" | "nix" | undefined;
|
|
1615
|
+
readonly targetOs?: "arch" | "fedora" | "nix" | "ubuntu" | undefined;
|
|
1608
1616
|
};
|
|
1609
1617
|
readonly responseMode?: Mode;
|
|
1610
1618
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
@@ -1639,6 +1647,14 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1639
1647
|
readonly version?: string | undefined;
|
|
1640
1648
|
readonly status?: string | undefined;
|
|
1641
1649
|
};
|
|
1650
|
+
readonly ubuntu: {
|
|
1651
|
+
readonly supported: boolean;
|
|
1652
|
+
readonly repo?: string | undefined;
|
|
1653
|
+
readonly packageName?: string | undefined;
|
|
1654
|
+
readonly projectName?: string | undefined;
|
|
1655
|
+
readonly version?: string | undefined;
|
|
1656
|
+
readonly status?: string | undefined;
|
|
1657
|
+
};
|
|
1642
1658
|
};
|
|
1643
1659
|
readonly alternatives: readonly {
|
|
1644
1660
|
readonly projectName: string;
|
package/dist/facade/workspace.js
CHANGED
|
@@ -210,6 +210,9 @@ const openForward = (ctx, workspaceId, port, options) => {
|
|
|
210
210
|
if (options?.host !== undefined) {
|
|
211
211
|
url.searchParams.set("host", options.host);
|
|
212
212
|
}
|
|
213
|
+
if (options?.protocol === "udp") {
|
|
214
|
+
url.searchParams.set("protocol", "udp");
|
|
215
|
+
}
|
|
213
216
|
if (config.apiKey === undefined) {
|
|
214
217
|
url.searchParams.set("ownerUserId", config.hostLocal.ownerUserId);
|
|
215
218
|
}
|
|
@@ -38,6 +38,9 @@ export const buildCreateWorkspaceRequest = (options, config) => {
|
|
|
38
38
|
code: "invalid_create_options",
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
|
+
if (options.os !== undefined && options.baseImage !== undefined) {
|
|
42
|
+
throw new SealantError("workspaces.create accepts either `os` (a managed OS family) or `baseImage` (a custom base image reference), not both.", { code: "invalid_create_options" });
|
|
43
|
+
}
|
|
41
44
|
const sourceName = options.repository ?? options.source?.path ?? "workspace";
|
|
42
45
|
const tail = sourceName
|
|
43
46
|
.split("/")
|
|
@@ -95,7 +98,9 @@ export const buildCreateWorkspaceRequest = (options, config) => {
|
|
|
95
98
|
harness: { id: options.harness.id },
|
|
96
99
|
customization: { enableSealantd: true },
|
|
97
100
|
target: {
|
|
98
|
-
os:
|
|
101
|
+
os: options.baseImage !== undefined
|
|
102
|
+
? { family: "custom", mode: "require", baseImage: options.baseImage }
|
|
103
|
+
: { family: options.os ?? "fedora", mode: "prefer" },
|
|
99
104
|
runtime: { family: "docker", mode: "require" },
|
|
100
105
|
},
|
|
101
106
|
lifecycle: {
|
package/dist/types.d.ts
CHANGED
|
@@ -65,7 +65,8 @@ export interface WorkspaceEvent {
|
|
|
65
65
|
readonly message?: string;
|
|
66
66
|
}
|
|
67
67
|
/** The supported workspace OS families (maps to the blueprint target). */
|
|
68
|
-
|
|
68
|
+
/** Supported workspace image OS families. `fedora` is the default when `os` is omitted. */
|
|
69
|
+
export type WorkspaceOs = "fedora" | "arch" | "nix" | "ubuntu";
|
|
69
70
|
/**
|
|
70
71
|
* Connected-account credentials to attach to a workspace at creation time, per provider — so the
|
|
71
72
|
* harness inside the workspace authenticates as the caller's own Claude / Codex / GitHub identity
|
|
@@ -146,8 +147,17 @@ export interface CreateOptions {
|
|
|
146
147
|
readonly ref?: string;
|
|
147
148
|
/** Human-friendly name for the workspace. */
|
|
148
149
|
readonly name?: string;
|
|
149
|
-
/** OS family for the workspace image. */
|
|
150
|
+
/** OS family for the workspace image. Mutually exclusive with `baseImage`. */
|
|
150
151
|
readonly os?: WorkspaceOs;
|
|
152
|
+
/**
|
|
153
|
+
* Build the workspace image FROM this arbitrary OCI image reference instead of a managed OS
|
|
154
|
+
* family (e.g. `"node:22-bookworm"`). Distro package installs are skipped; the build overlays
|
|
155
|
+
* only the sealantd supervisor, the harness CLIs (npm), and a static socat relay. See "Custom
|
|
156
|
+
* base images" in the SDK README for the base-image contract. Mutually exclusive with `os`;
|
|
157
|
+
* `packages` install through the base's own package manager (apt/apk/dnf/pacman) and fail the
|
|
158
|
+
* build readable when it has none.
|
|
159
|
+
*/
|
|
160
|
+
readonly baseImage?: string;
|
|
151
161
|
/** Extra OS packages to install in the workspace. */
|
|
152
162
|
readonly packages?: readonly string[];
|
|
153
163
|
/** Runtime-managed services that need more than installing an OS package. */
|
|
@@ -221,7 +231,7 @@ export interface Workspace {
|
|
|
221
231
|
readonly in?: string | null;
|
|
222
232
|
}): Promise<void>;
|
|
223
233
|
/**
|
|
224
|
-
* Open a raw TCP byte pipe INSIDE the workspace — the primitive for
|
|
234
|
+
* Open a raw TCP byte pipe (or a UDP datagram pipe) INSIDE the workspace — the primitive for
|
|
225
235
|
* reaching a dev server or database the workspace runs. Protocol-agnostic:
|
|
226
236
|
* nothing inspects or records the payload. One held WebSocket per forward;
|
|
227
237
|
* rejects when nothing accepts the connection. The target host is a CLOSED
|
|
@@ -235,6 +245,13 @@ export interface Workspace {
|
|
|
235
245
|
export interface WorkspaceForwardOptions {
|
|
236
246
|
/** Target inside the workspace: its loopback (default) or the Docker sidecar. */
|
|
237
247
|
readonly host?: "127.0.0.1" | "localhost" | "docker";
|
|
248
|
+
/**
|
|
249
|
+
* Forward transport. TCP (default) is a byte stream; `"udp"` opens a
|
|
250
|
+
* connected UDP socket where one frame on this pipe is exactly one
|
|
251
|
+
* datagram, both directions. UDP has no connection handshake: opening
|
|
252
|
+
* succeeds even when nothing listens yet — datagrams simply drop.
|
|
253
|
+
*/
|
|
254
|
+
readonly protocol?: "tcp" | "udp";
|
|
238
255
|
}
|
|
239
256
|
/**
|
|
240
257
|
* A live port forward — one WebSocket, held until `close()` or the remote
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sealant/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "The fluent public SDK for Sealant — create a workspace, run a harness, replay the record.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@sealant/api-contracts": "^0.
|
|
29
|
+
"@sealant/api-contracts": "^0.17.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@effect/vitest": "4.0.0-beta.85",
|