withruntime 0.8.0 → 0.8.1
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/BLAXEL.md +29 -18
- package/dist/blaxel/errors.js +28 -5
- package/dist/blaxel/index.d.ts +1 -1
- package/dist/blaxel/index.js +1 -1
- package/dist/blaxel/sandbox.d.ts +7 -0
- package/dist/blaxel/sandbox.js +21 -8
- package/dist/cli.js +2 -2
- package/dist/transport.d.ts +1 -1
- package/dist/transport.js +1 -1
- package/package.json +1 -1
package/BLAXEL.md
CHANGED
|
@@ -24,15 +24,26 @@ anywhere: in `BL_API_KEY` it is ignored, and passed to `initialize` while
|
|
|
24
24
|
nothing on Runtime. With no Runtime key at all, the first call throws
|
|
25
25
|
`CredentialsError` saying what to set.
|
|
26
26
|
|
|
27
|
+
**A key sees only the sandboxes it created.** A sandbox made with another of
|
|
28
|
+
the account's keys answers 404, though its name stays taken
|
|
29
|
+
([teams](https://withruntime.com/docs/teams)). Services that share sandboxes by
|
|
30
|
+
name, or through `getByExternalId`, use the same Runtime key.
|
|
31
|
+
|
|
27
32
|
## What a sandbox gets
|
|
28
33
|
|
|
29
34
|
- **Machine:** Blaxel's default of 4096 MB. vCPUs follow Blaxel's rule of one
|
|
30
|
-
per 2048 MB (at least one, at most 16): 2 for the default, 4 for 8192 MB.
|
|
35
|
+
per 2048 MB (at least one, at most 16): 2 for the default, 4 for 8192 MB. A
|
|
36
|
+
trial sandbox has at most 4096 MB (2 vCPUs); `memory: 8192` or more needs
|
|
37
|
+
prepaid credit, and on the trial is refused with a 400 (`invalid_trial`)
|
|
38
|
+
saying so.
|
|
31
39
|
- **Image:** Blaxel's `base-image`, `py-app`, `ts-app`, `node`,
|
|
32
40
|
`docker-in-sandbox` and `jupyter-server` are Runtime's stock image (Ubuntu
|
|
33
41
|
24.04 with Node.js 24, Python 3.12, Bun, git and a compiler; Docker after
|
|
34
|
-
`sudo enable-docker`). Any other name
|
|
35
|
-
name
|
|
42
|
+
`sudo enable-docker`). Any other image `ns/name:tag` is the ready Runtime
|
|
43
|
+
image named `ns-name` (every `/` becomes `-`, as Runtime names hold none) at
|
|
44
|
+
tag `tag` (`latest` when none is given). Build it once with
|
|
45
|
+
`npx withruntime image build --dockerfile Dockerfile --name ns-name -t ns-name:tag`,
|
|
46
|
+
and the code keeps `image: "ns/name:tag"` as it is.
|
|
36
47
|
- **Standby and lifetime:** a Blaxel sandbox goes to standby when unused and
|
|
37
48
|
resumes on the next call. On Runtime it pauses after 60 seconds without a
|
|
38
49
|
call (Runtime's shortest idle pause; Blaxel's is about 15 seconds), keeping
|
|
@@ -107,21 +118,21 @@ nothing on Runtime. With no Runtime key at all, the first call throws
|
|
|
107
118
|
Each of these throws `NotSupportedError` before anything happens. Its `feature`
|
|
108
119
|
names the gap and its `alternative` says what to use.
|
|
109
120
|
|
|
110
|
-
| Blaxel | Use instead
|
|
111
|
-
| ------------------------------------------------------------------------------------------------------------------------ |
|
|
112
|
-
| An `image` with no Runtime image of
|
|
113
|
-
| A region outside the US | Runtime runs in one US region.
|
|
114
|
-
| `extraArgs` other than `iptables`; network `egress`, `firewall`, `subnet`, and a `proxy` with more than its domain lists | Remove them; `allowedDomains` and `forbiddenDomains` (on the network or its proxy); Runtime secrets.
|
|
115
|
-
| Read-only and ephemeral volumes; a volume with no Runtime volume of that name | Mount read-write; write scratch files under `/workspace`; `runtime.volumes.create`.
|
|
116
|
-
| `snapshots.restore`, `restore` | Fork from the snapshot into a new sandbox.
|
|
117
|
-
| Forking into an application | Fork into a sandbox and share its port.
|
|
118
|
-
| A preview's `prefixUrl`, `customDomain`, `requestHeaders`, `responseHeaders`, `ttl` | Runtime's fixed preview address; set headers (CORS) in your server; delete the preview.
|
|
119
|
-
| `preview.tokens.list()`; a token for over a week | Keep the tokens you create; create a new one when it runs out.
|
|
120
|
-
| `runCode` with `envs` for one run; a language Runtime's interpreter lacks | Sandbox envs at create, or set them in the code; `process.exec`.
|
|
121
|
-
| Listing by `cursor`, `q`, `anchor`, a status other than `DEPLOYED`, or newest first | List and filter the result yourself; `nextPage()` walks the pages.
|
|
122
|
-
| `sandbox.sessions`, `schedules`, `codegen`, `system`, `drives`; `fromSession` | Previews and tokens; your own scheduler; `fs.write`; nothing to upgrade; Runtime volumes.
|
|
123
|
-
| Agents, models, tools, MCP transports, jobs, applications, images, volumes, drives | Your own agent with Runtime sandboxes, `withruntime/tools`, `npx withruntime mcp`, `runtime.images`, `runtime.volumes`.
|
|
124
|
-
| Blaxel's generated API functions (`createSandbox`, `postProcess`, ...) | `SandboxInstance` here, or `import { Runtime } from "withruntime"`.
|
|
121
|
+
| Blaxel | Use instead |
|
|
122
|
+
| ------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
123
|
+
| An `image` with no ready Runtime image of the name it maps to (Blaxel's other templates too) | Build it: `npx withruntime image build --dockerfile Dockerfile --name ns-name -t ns-name:tag`; the error gives the exact command. |
|
|
124
|
+
| A region outside the US | Runtime runs in one US region. |
|
|
125
|
+
| `extraArgs` other than `iptables`; network `egress`, `firewall`, `subnet`, and a `proxy` with more than its domain lists | Remove them; `allowedDomains` and `forbiddenDomains` (on the network or its proxy); Runtime secrets. |
|
|
126
|
+
| Read-only and ephemeral volumes; a volume with no Runtime volume of that name | Mount read-write; write scratch files under `/workspace`; `runtime.volumes.create`. |
|
|
127
|
+
| `snapshots.restore`, `restore` | Fork from the snapshot into a new sandbox. |
|
|
128
|
+
| Forking into an application | Fork into a sandbox and share its port. |
|
|
129
|
+
| A preview's `prefixUrl`, `customDomain`, `requestHeaders`, `responseHeaders`, `ttl` | Runtime's fixed preview address; set headers (CORS) in your server; delete the preview. |
|
|
130
|
+
| `preview.tokens.list()`; a token for over a week | Keep the tokens you create; create a new one when it runs out. |
|
|
131
|
+
| `runCode` with `envs` for one run; a language Runtime's interpreter lacks | Sandbox envs at create, or set them in the code; `process.exec`. |
|
|
132
|
+
| Listing by `cursor`, `q`, `anchor`, a status other than `DEPLOYED`, or newest first | List and filter the result yourself; `nextPage()` walks the pages. |
|
|
133
|
+
| `sandbox.sessions`, `schedules`, `codegen`, `system`, `drives`; `fromSession` | Previews and tokens; your own scheduler; `fs.write`; nothing to upgrade; Runtime volumes. |
|
|
134
|
+
| Agents, models, tools, MCP transports, jobs, applications, images, volumes, drives | Your own agent with Runtime sandboxes, `withruntime/tools`, `npx withruntime mcp`, `runtime.images`, `runtime.volumes`. |
|
|
135
|
+
| Blaxel's generated API functions (`createSandbox`, `postProcess`, ...) | `SandboxInstance` here, or `import { Runtime } from "withruntime"`. |
|
|
125
136
|
|
|
126
137
|
Some differences are not refusals:
|
|
127
138
|
|
package/dist/blaxel/errors.js
CHANGED
|
@@ -82,6 +82,27 @@ export function responseError(status, message) {
|
|
|
82
82
|
headers: { "content-type": "application/json" },
|
|
83
83
|
}), data, data);
|
|
84
84
|
}
|
|
85
|
+
const LS = "List the directory with sandbox.fs.ls(path).";
|
|
86
|
+
/** Runtime's hints that name Runtime's calls, in the Blaxel calls a Blaxel
|
|
87
|
+
* program makes (the Python adapter uses the same words). */
|
|
88
|
+
const AGAIN = "Try again in a moment.";
|
|
89
|
+
const BLAXEL_HINTS = {
|
|
90
|
+
name_taken: "SandboxInstance.createIfNotExists({ name }) answers the sandbox that has the name.",
|
|
91
|
+
file_not_found: LS,
|
|
92
|
+
path_not_found: LS,
|
|
93
|
+
is_a_directory: "That path is a directory: list it with sandbox.fs.ls(path), or name a file in it.",
|
|
94
|
+
cwd_not_found: "Make the directory with sandbox.fs.mkdir(path), or pass an existing workingDir to sandbox.process.exec.",
|
|
95
|
+
sandbox_paused: "Call sandbox.unarchive(), then try again.",
|
|
96
|
+
not_running: "The sandbox is not running: call sandbox.unarchive() if it was archived, or make a new one with SandboxInstance.create if it was deleted.",
|
|
97
|
+
trial_busy: "The trial's sandboxes are all in use: delete one you no longer need (sandbox.delete()) or archive it (sandbox.archive()), then try again. Moving to paid credit is the account owner's decision.",
|
|
98
|
+
public_preview_not_allowed: "On the trial, share the port privately: sandbox.previews.create({ metadata: { name }, spec: { port, public: false } }) and a token from preview.tokens.create(expiresAt). A public preview needs a paid sandbox, which is the account owner's decision.",
|
|
99
|
+
busy: AGAIN,
|
|
100
|
+
guest_busy: AGAIN,
|
|
101
|
+
rate_limited: AGAIN,
|
|
102
|
+
unauthorized: "Set RUNTIME_API_KEY to a Runtime key (https://withruntime.com/account/keys), or run `npx withruntime login` once. A Blaxel key (BL_API_KEY) is never sent.",
|
|
103
|
+
};
|
|
104
|
+
/** A trial create over the trial's size, in Blaxel's field. */
|
|
105
|
+
const TRIAL_CAP = "A trial sandbox has at most 4096 MB of memory (2 vCPUs); pass memory 4096 or add credit.";
|
|
85
106
|
/** A Runtime SDK error as Blaxel's: ResponseError (SandboxGatewayError for a
|
|
86
107
|
* 502, 503 or 504), NotSupportedError for a product Runtime has switched off,
|
|
87
108
|
* CredentialsError when there is no Runtime key. Anything else passes through
|
|
@@ -97,9 +118,11 @@ export function translate(error) {
|
|
|
97
118
|
return new NotSupportedError(error.code.replace(/_unavailable$/, ""), error.hint ?? "", error.message);
|
|
98
119
|
if (error.status < 200 || error.status > 599)
|
|
99
120
|
return error;
|
|
121
|
+
const trialCap = error.code === "invalid_trial";
|
|
122
|
+
const hint = trialCap ? undefined : (BLAXEL_HINTS[error.code] ?? error.hint);
|
|
100
123
|
const message = [
|
|
101
|
-
error.message,
|
|
102
|
-
|
|
124
|
+
trialCap ? TRIAL_CAP : error.message,
|
|
125
|
+
hint ? `Hint: ${hint}` : "",
|
|
103
126
|
error.requestId ? `Request: ${error.requestId}` : "",
|
|
104
127
|
]
|
|
105
128
|
.filter(Boolean)
|
|
@@ -107,7 +130,7 @@ export function translate(error) {
|
|
|
107
130
|
const data = {
|
|
108
131
|
error: message,
|
|
109
132
|
code: error.code,
|
|
110
|
-
...(
|
|
133
|
+
...(hint ? { hint } : {}),
|
|
111
134
|
...(error.requestId ? { requestId: error.requestId } : {}),
|
|
112
135
|
};
|
|
113
136
|
const Kind = GATEWAY.has(error.status) ? SandboxGatewayError : ResponseError;
|
|
@@ -116,8 +139,8 @@ export function translate(error) {
|
|
|
116
139
|
headers: { "content-type": "application/json" },
|
|
117
140
|
}), data, data);
|
|
118
141
|
out.runtimeCode = error.code;
|
|
119
|
-
if (
|
|
120
|
-
out.hint =
|
|
142
|
+
if (hint)
|
|
143
|
+
out.hint = hint;
|
|
121
144
|
if (error.requestId)
|
|
122
145
|
out.requestId = error.requestId;
|
|
123
146
|
out.cause = error;
|
package/dist/blaxel/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Config } from "./client.js";
|
|
2
|
-
export { SandboxInstance, DEFAULT_IMAGE, DEFAULT_MEMORY, MEMORY_PER_VCPU, durationMs, lifetimeOf, networkRules, type SandboxListQuery, type SandboxForkOptions, type SandboxArchiveOptions, } from "./sandbox.js";
|
|
2
|
+
export { SandboxInstance, DEFAULT_IMAGE, DEFAULT_MEMORY, MEMORY_PER_VCPU, durationMs, imageRef, lifetimeOf, networkRules, type SandboxListQuery, type SandboxForkOptions, type SandboxArchiveOptions, } from "./sandbox.js";
|
|
3
3
|
export { CodeInterpreter } from "./interpreter.js";
|
|
4
4
|
export { SandboxFileSystem, retryOnTransient, type File, type FileWithContent, type Subdirectory, type Directory, type SuccessResponse, type FindMatch, type FindResponse, type FuzzySearchMatch, type FuzzySearchResponse, type ContentSearchMatch, type ContentSearchResponse, type CopyResponse, type WatchEvent, type SandboxFilesystemFile, type FilesystemSearchOptions, type FilesystemFindOptions, type FilesystemGrepOptions, } from "./filesystem.js";
|
|
5
5
|
export { SandboxProcess, type ProcessRequest, type ProcessResponse, type ProcessRequestWithLog, type ProcessResponseWithLog, type PostProcessResponse, type GetProcessResponse, type GetProcessByIdentifierResponse, type DeleteProcessByIdentifierResponse, type DeleteProcessByIdentifierKillResponse, type ProcessLogs, } from "./process.js";
|
package/dist/blaxel/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { RuntimeError } from "../errors.js";
|
|
|
11
11
|
import { initialize } from "./client.js";
|
|
12
12
|
import { NotSupportedError } from "./errors.js";
|
|
13
13
|
import { CODEGEN, DRIVES, SCHEDULES, SESSIONS, SYSTEM, unsupportedExport } from "./unsupported.js";
|
|
14
|
-
export { SandboxInstance, DEFAULT_IMAGE, DEFAULT_MEMORY, MEMORY_PER_VCPU, durationMs, lifetimeOf, networkRules, } from "./sandbox.js";
|
|
14
|
+
export { SandboxInstance, DEFAULT_IMAGE, DEFAULT_MEMORY, MEMORY_PER_VCPU, durationMs, imageRef, lifetimeOf, networkRules, } from "./sandbox.js";
|
|
15
15
|
export { CodeInterpreter } from "./interpreter.js";
|
|
16
16
|
export { SandboxFileSystem, retryOnTransient, } from "./filesystem.js";
|
|
17
17
|
export { SandboxProcess, } from "./process.js";
|
package/dist/blaxel/sandbox.d.ts
CHANGED
|
@@ -72,6 +72,13 @@ export declare function lifetimeOf(asked: {
|
|
|
72
72
|
* domains, from the network itself or from its proxy (Blaxel's current
|
|
73
73
|
* place for them). Anything else of the proxy is refused. */
|
|
74
74
|
export declare function networkRules(network: SandboxNetwork): NonNullable<RuntimeCreate["network"]>;
|
|
75
|
+
/** A Blaxel image `ns/name:tag` as the Runtime image name and tag it maps to
|
|
76
|
+
* (Runtime names allow no "/"): every "/" becomes "-" (`ns-name`), and the
|
|
77
|
+
* tag is `latest` when none is given. The Python adapter maps the same way. */
|
|
78
|
+
export declare function imageRef(image: string): {
|
|
79
|
+
name: string;
|
|
80
|
+
tag: string;
|
|
81
|
+
};
|
|
75
82
|
/** A sandbox with Blaxel's methods. `sandbox.withruntime` is the Runtime
|
|
76
83
|
* sandbox underneath, for anything Blaxel has no name for. */
|
|
77
84
|
export declare class SandboxInstance {
|
package/dist/blaxel/sandbox.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RuntimeError } from "../errors.js";
|
|
1
2
|
import { clientFor, defaultRegion, } from "./client.js";
|
|
2
3
|
import { checkEnvNames, envFileCommand, envFileLines, parseProcessLine, toRuntimePath, } from "./context.js";
|
|
3
4
|
import { codeOf, guard, NotSupportedError, responseError, translate } from "./errors.js";
|
|
@@ -178,26 +179,38 @@ function checkRegion(region) {
|
|
|
178
179
|
if (region !== undefined && region !== "" && !US_REGIONS.has(region))
|
|
179
180
|
throw new NotSupportedError(`The region ${region}`, "Runtime runs in one US region: remove region (and BL_REGION), or use us-was-1.");
|
|
180
181
|
}
|
|
181
|
-
/**
|
|
182
|
-
*
|
|
182
|
+
/** A Blaxel image `ns/name:tag` as the Runtime image name and tag it maps to
|
|
183
|
+
* (Runtime names allow no "/"): every "/" becomes "-" (`ns-name`), and the
|
|
184
|
+
* tag is `latest` when none is given. The Python adapter maps the same way. */
|
|
185
|
+
export function imageRef(image) {
|
|
186
|
+
const slash = image.lastIndexOf("/");
|
|
187
|
+
const colon = image.lastIndexOf(":");
|
|
188
|
+
const [name, tag] = colon > slash ? [image.slice(0, colon), image.slice(colon + 1)] : [image, ""];
|
|
189
|
+
return { name: name.replaceAll("/", "-"), tag: tag || "latest" };
|
|
190
|
+
}
|
|
191
|
+
/** Where an image sends the create: Runtime's stock image, or the ready
|
|
192
|
+
* Runtime image `imageRef` maps it to. */
|
|
183
193
|
async function resolveImage(client, image) {
|
|
184
194
|
if (image === undefined || STOCK_IMAGE.test(image))
|
|
185
195
|
return {};
|
|
186
196
|
if (UUID.test(image))
|
|
187
197
|
return { image };
|
|
188
|
-
const name = image
|
|
198
|
+
const { name, tag } = imageRef(image);
|
|
189
199
|
let found;
|
|
190
200
|
try {
|
|
191
|
-
found =
|
|
201
|
+
found = await client.images.resolve(`${name}:${tag}`);
|
|
192
202
|
}
|
|
193
203
|
catch (error) {
|
|
194
|
-
//
|
|
195
|
-
|
|
204
|
+
// Not an image, or a name Runtime could not hold: the same answer.
|
|
205
|
+
const status = error instanceof RuntimeError ? error.status : undefined;
|
|
206
|
+
if (status !== 400 && status !== 404)
|
|
196
207
|
throw translate(error);
|
|
197
208
|
}
|
|
198
|
-
if (found)
|
|
209
|
+
if (found && found.state === "ready")
|
|
199
210
|
return { image: found.id };
|
|
200
|
-
|
|
211
|
+
const feature = `The image ${image}, which is not a Runtime image`;
|
|
212
|
+
const alternative = `Build it as a Runtime image named ${name}: \`npx withruntime image build --dockerfile Dockerfile --name ${name} -t ${name}:${tag}\`. The code can keep "${image}": the adapter starts from ${name}:${tag}.`;
|
|
213
|
+
throw new NotSupportedError(feature, alternative, `${feature}, is not supported on Runtime. ${alternative}`);
|
|
201
214
|
}
|
|
202
215
|
/** Blaxel volumes (by name) as Runtime volumes. */
|
|
203
216
|
async function resolveVolumes(client, volumes) {
|
package/dist/cli.js
CHANGED
|
@@ -2150,8 +2150,8 @@ async function snapshot(argv, env, out) {
|
|
|
2150
2150
|
}
|
|
2151
2151
|
const IMAGE_HELP = `runtime image <command>
|
|
2152
2152
|
|
|
2153
|
-
build [<folder>] [
|
|
2154
|
-
[
|
|
2153
|
+
build [<folder>] [--dockerfile|-f <Dockerfile>] | --from <image> | --pip <pkg>... --apt <pkg>... --npm <pkg>...
|
|
2154
|
+
[--name <name>] [--tag|-t name[:tag]]... [--target <stage>] [--build-arg K=V]... [--no-cache]
|
|
2155
2155
|
[--start <command>] [--ready-port <port> | --ready-command <command>]
|
|
2156
2156
|
[--max-image-mib 8192] [--disk-mib <1024-32768>] [--timeout <seconds>]
|
|
2157
2157
|
Build and stream the log; prints the image id when ready.
|
package/dist/transport.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RuntimeError } from "./errors.js";
|
|
2
|
-
export declare const VERSION = "0.8.
|
|
2
|
+
export declare const VERSION = "0.8.1";
|
|
3
3
|
export declare const DEFAULT_BASE_URL = "https://api.withruntime.com";
|
|
4
4
|
export type RequestOptions = {
|
|
5
5
|
/** Sent as Idempotency-Key. Omit it: the SDK makes one per call and keeps
|
package/dist/transport.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConnectionError, errorFor, RuntimeError, WAITS_FOR_ROOM } from "./errors.js";
|
|
2
2
|
import { describeRoute, envFetch, openWebSocket } from "./proxy.js";
|
|
3
|
-
export const VERSION = "0.8.
|
|
3
|
+
export const VERSION = "0.8.1";
|
|
4
4
|
export const DEFAULT_BASE_URL = "https://api.withruntime.com";
|
|
5
5
|
export function apiOrigin(value) {
|
|
6
6
|
const url = new URL(value);
|