withruntime 0.12.0 → 0.16.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/BLAXEL.md +97 -32
- package/COMPATIBILITY.md +120 -5
- package/DAYTONA.md +34 -3
- package/E2B.md +34 -5
- package/README.md +36 -3
- package/README.src.md +35 -2
- package/VERCEL.md +52 -5
- package/compatibility-lock.json +71 -111
- package/dist/billing-cli.js +8 -4
- package/dist/blaxel/client.d.ts +11 -0
- package/dist/blaxel/client.js +28 -0
- package/dist/blaxel/errors.d.ts +65 -0
- package/dist/blaxel/errors.js +114 -0
- package/dist/blaxel/index.d.ts +10 -3
- package/dist/blaxel/index.js +23 -4
- package/dist/blaxel/preview.d.ts +29 -4
- package/dist/blaxel/preview.js +79 -5
- package/dist/blaxel/sandbox.d.ts +1 -1
- package/dist/blaxel/sandbox.js +2 -1
- package/dist/blaxel/session.js +4 -2
- package/dist/cli-extras.js +2 -1
- package/dist/cli-words.js +1 -0
- package/dist/cli.d.ts +17 -2
- package/dist/cli.js +291 -85
- package/dist/client.d.ts +1 -1
- package/dist/credentials.d.ts +3 -0
- package/dist/credentials.js +15 -0
- package/dist/daytona/client.d.ts +4 -0
- package/dist/daytona/client.js +8 -3
- package/dist/daytona/daytona.d.ts +4 -1
- package/dist/daytona/daytona.js +3 -2
- package/dist/e2b/sandbox.d.ts +7 -6
- package/dist/e2b/sandbox.js +9 -12
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -1
- package/dist/freestyle/index.d.ts +77 -5
- package/dist/freestyle/index.js +380 -48
- package/dist/identity.js +36 -18
- package/dist/index.d.ts +4 -3
- package/dist/machine.d.ts +39 -13
- package/dist/machine.js +72 -25
- package/dist/mcp.js +157 -20
- package/dist/modal/index.d.ts +15 -0
- package/dist/modal/index.js +35 -7
- package/dist/morph/index.d.ts +255 -0
- package/dist/morph/index.js +641 -0
- package/dist/network-cli.js +2 -2
- package/dist/product-names.d.ts +2 -2
- package/dist/product-names.js +2 -2
- package/dist/products/api-keys.d.ts +73 -0
- package/dist/products/api-keys.js +23 -0
- package/dist/products/apps.d.ts +12 -31
- package/dist/products/apps.js +8 -113
- package/dist/products/balancers.d.ts +87 -0
- package/dist/products/balancers.js +8 -0
- package/dist/products/builds.d.ts +30 -0
- package/dist/products/builds.js +6 -0
- package/dist/products/index.d.ts +2 -0
- package/dist/products/index.js +2 -0
- package/dist/products/jobs.d.ts +2 -2
- package/dist/products/jobs.js +1 -1
- package/dist/products/limits.d.ts +16 -2
- package/dist/products/limits.js +2 -2
- package/dist/products/mcp.d.ts +5 -0
- package/dist/products/network-products.d.ts +21 -3
- package/dist/products/network-products.js +3 -1
- package/dist/products/observability.d.ts +7 -2
- package/dist/products/previews.d.ts +6 -3
- package/dist/products/previews.js +1 -1
- package/dist/products/resources.d.ts +54 -0
- package/dist/products/resources.js +122 -0
- package/dist/products/secrets.d.ts +22 -0
- package/dist/products/secrets.js +8 -0
- package/dist/products/volumes.d.ts +3 -0
- package/dist/sandbox.d.ts +4 -0
- package/dist/sandbox.js +27 -2
- package/dist/snapshots.d.ts +4 -0
- package/dist/ssh.d.ts +35 -0
- package/dist/ssh.js +93 -1
- package/dist/transport.d.ts +14 -8
- package/dist/transport.js +70 -15
- package/dist/types.d.ts +33 -5
- package/dist/vercel/command.d.ts +48 -1
- package/dist/vercel/command.js +237 -6
- package/dist/vercel/sandbox-user.js +2 -1
- package/dist/vercel/sandbox.d.ts +17 -3
- package/dist/vercel/sandbox.js +46 -3
- package/dist/wallet.d.ts +4 -1
- package/dist/wallet.js +2 -1
- package/package.json +7 -14
- package/dist/cli/logs.test.d.ts +0 -1
- package/dist/cli/logs.test.js +0 -272
- package/dist/products/logs.test.d.ts +0 -1
- package/dist/products/logs.test.js +0 -343
package/dist/blaxel/errors.js
CHANGED
|
@@ -198,3 +198,117 @@ export function codeOf(error) {
|
|
|
198
198
|
return error.runtimeCode;
|
|
199
199
|
return undefined;
|
|
200
200
|
}
|
|
201
|
+
function readProperty(value, key) {
|
|
202
|
+
try {
|
|
203
|
+
return typeof value === "object" && value !== null
|
|
204
|
+
? value[key]
|
|
205
|
+
: undefined;
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const isCode = (value) => (typeof value === "string" && value.length > 0) ||
|
|
212
|
+
(typeof value === "number" && Number.isFinite(value));
|
|
213
|
+
const isStatus = (value) => typeof value === "number" && Number.isInteger(value) && value >= 100 && value <= 599;
|
|
214
|
+
/** True for an error this package throws for an API failure (ResponseError,
|
|
215
|
+
* SandboxGatewayError, SandboxCreationTimeoutError) or a raw Blaxel error body
|
|
216
|
+
* (`{ error, code }`, `{ code, message, status_code }`,
|
|
217
|
+
* `{ error: { code, message, status } }`). False for plain errors, strings and
|
|
218
|
+
* NotSupportedError, which is a refusal made here, not an API failure. Never
|
|
219
|
+
* throws. */
|
|
220
|
+
export function isBlaxelError(err) {
|
|
221
|
+
try {
|
|
222
|
+
if (err instanceof Error)
|
|
223
|
+
return err instanceof ResponseError || err instanceof SandboxCreationTimeoutError;
|
|
224
|
+
if (typeof err !== "object" || err === null || Array.isArray(err))
|
|
225
|
+
return false;
|
|
226
|
+
const error = readProperty(err, "error");
|
|
227
|
+
if (typeof error === "string")
|
|
228
|
+
return isStatus(readProperty(err, "code"));
|
|
229
|
+
if (typeof readProperty(err, "code") === "string" &&
|
|
230
|
+
typeof readProperty(err, "message") === "string" &&
|
|
231
|
+
isStatus(readProperty(err, "status_code")))
|
|
232
|
+
return true;
|
|
233
|
+
return (typeof error === "object" &&
|
|
234
|
+
error !== null &&
|
|
235
|
+
!Array.isArray(error) &&
|
|
236
|
+
typeof readProperty(error, "code") === "string" &&
|
|
237
|
+
typeof readProperty(error, "message") === "string" &&
|
|
238
|
+
isStatus(readProperty(error, "status")));
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function errorCandidates(err) {
|
|
245
|
+
const bodies = [err, readProperty(err, "error"), readProperty(err, "data")];
|
|
246
|
+
return bodies.flatMap((body) => [body, readProperty(body, "error")]);
|
|
247
|
+
}
|
|
248
|
+
function readHeader(err, name) {
|
|
249
|
+
try {
|
|
250
|
+
const headers = readProperty(readProperty(err, "response"), "headers");
|
|
251
|
+
const get = readProperty(headers, "get");
|
|
252
|
+
if (typeof get !== "function")
|
|
253
|
+
return undefined;
|
|
254
|
+
const value = Reflect.apply(get, headers, [name]);
|
|
255
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/** The error's code, then its body's, then the X-Blaxel-Error-Code header. A
|
|
262
|
+
* ResponseError from Runtime answers its HTTP status (its `code`); Runtime's
|
|
263
|
+
* own code is `runtimeCode`. Never throws. */
|
|
264
|
+
export function getBlaxelErrorCode(err) {
|
|
265
|
+
for (const candidate of errorCandidates(err)) {
|
|
266
|
+
const code = readProperty(candidate, "code");
|
|
267
|
+
if (isCode(code))
|
|
268
|
+
return code;
|
|
269
|
+
}
|
|
270
|
+
return readHeader(err, "x-blaxel-error-code");
|
|
271
|
+
}
|
|
272
|
+
/** The HTTP status: the error's, its response's, then its body's (`status`,
|
|
273
|
+
* `status_code` or a numeric `code`). Never throws. */
|
|
274
|
+
export function getBlaxelErrorStatus(err) {
|
|
275
|
+
const status = readProperty(err, "status");
|
|
276
|
+
if (isStatus(status))
|
|
277
|
+
return status;
|
|
278
|
+
const responseStatus = readProperty(readProperty(err, "response"), "status");
|
|
279
|
+
if (isStatus(responseStatus))
|
|
280
|
+
return responseStatus;
|
|
281
|
+
for (const candidate of errorCandidates(err))
|
|
282
|
+
for (const key of ["status", "status_code", "code"]) {
|
|
283
|
+
const value = readProperty(candidate, key);
|
|
284
|
+
if (isStatus(value))
|
|
285
|
+
return value;
|
|
286
|
+
}
|
|
287
|
+
return undefined;
|
|
288
|
+
}
|
|
289
|
+
/** The error's message, else its body's message or error text. Never throws. */
|
|
290
|
+
export function getBlaxelErrorMessage(err) {
|
|
291
|
+
for (const candidate of errorCandidates(err)) {
|
|
292
|
+
const message = typeof candidate === "string" ? candidate : readProperty(candidate, "message");
|
|
293
|
+
if (typeof message === "string" && message.length > 0)
|
|
294
|
+
return message;
|
|
295
|
+
}
|
|
296
|
+
return undefined;
|
|
297
|
+
}
|
|
298
|
+
/** Blaxel's request id headers (X-Cf-Request-Id, X-Amz-Cf-Id, CF-Ray) on the
|
|
299
|
+
* error's response, else the Runtime request id a ResponseError carries
|
|
300
|
+
* (`requestId`). Never throws. */
|
|
301
|
+
export function getBlaxelErrorRequestId(err) {
|
|
302
|
+
for (const name of ["x-cf-request-id", "x-amz-cf-id", "cf-ray"]) {
|
|
303
|
+
const value = readHeader(err, name);
|
|
304
|
+
if (value !== undefined)
|
|
305
|
+
return value;
|
|
306
|
+
}
|
|
307
|
+
try {
|
|
308
|
+
const runtime = err instanceof ResponseError ? err.requestId : undefined;
|
|
309
|
+
return typeof runtime === "string" && runtime.length > 0 ? runtime : undefined;
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
return undefined;
|
|
313
|
+
}
|
|
314
|
+
}
|
package/dist/blaxel/index.d.ts
CHANGED
|
@@ -3,9 +3,9 @@ export { SandboxInstance, DEFAULT_IMAGE, DEFAULT_MEMORY, MEMORY_PER_VCPU, durati
|
|
|
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";
|
|
6
|
-
export { SandboxPreview, SandboxPreviews, SandboxPreviewToken, SandboxPreviewTokens, type Preview, type PreviewMetadata, type PreviewSpec, type PreviewToken, } from "./preview.js";
|
|
6
|
+
export { SandboxPreview, SandboxPreviews, SandboxPreviewToken, SandboxPreviewTokens, type Preview, type PreviewMetadata, type PreviewSpec, type PreviewToken, type SandboxPreviewCreateConfiguration, } from "./preview.js";
|
|
7
7
|
export { Snapshot, SandboxSnapshotsResource, type Env, type SandboxSnapshot, type SandboxSnapshotSource, type SandboxSnapshotSpec, type SandboxForkResponse, type SandboxRestoreResponse, type SnapshotCreateConfiguration, type SnapshotForkOptions, type SnapshotListQuery, } from "./snapshot.js";
|
|
8
|
-
export { ResponseError, SandboxCreationTimeoutError, isCreationTimeoutError, SandboxGatewayError, isGatewayError, isGatewayTimeout, CredentialsError, NotSupportedError, } from "./errors.js";
|
|
8
|
+
export { ResponseError, SandboxCreationTimeoutError, isCreationTimeoutError, SandboxGatewayError, isGatewayError, isGatewayTimeout, CredentialsError, NotSupportedError, isBlaxelError, getBlaxelErrorCode, getBlaxelErrorStatus, getBlaxelErrorMessage, getBlaxelErrorRequestId, type BlaxelGatewayErrorCode, type BlaxelAuthErrorCode, type BlaxelSandboxCreationErrorCode, type BlaxelErrorCode, type BlaxelErrorCodeValue, type BlaxelApiErrorBody, type BlaxelActionErrorBody, type BlaxelPlatformErrorBody, type BlaxelSandboxApiErrorBody, type BlaxelErrorLike, } from "./errors.js";
|
|
9
9
|
export { createPaginatedList, unwrapListData, type PaginatedList, type PaginatedListMeta, type ListResponse, type CursorPaginationQuery, type AutoPagingEachCallback, type AutoPagingToArrayOptions, } from "./pagination.js";
|
|
10
10
|
export { normalizePorts, normalizeEnvs, normalizeVolumes, type Status, type Port, type EnvVar, type ExpirationPolicy, type SandboxLifecycle, type SandboxNetwork, type VolumeBinding, type VolumeAttachment, type Metadata, type SandboxRuntime, type SandboxSpec, type CoreEvent, type Sandbox, type SandboxConfiguration, type SandboxCreateConfiguration, type SandboxUpdateMetadata, type SandboxUpdateNetwork, type SessionCreateOptions, type SessionWithToken, } from "./types.js";
|
|
11
11
|
export { initialize, type Config, type WithRuntime, type RuntimeOptions } from "./client.js";
|
|
@@ -35,11 +35,13 @@ export declare const logger: {
|
|
|
35
35
|
error: (...message: unknown[]) => void;
|
|
36
36
|
};
|
|
37
37
|
/** Blaxel's settings, as far as they mean anything on Runtime. `setConfig`
|
|
38
|
-
* takes a Runtime key as `apikey`;
|
|
38
|
+
* takes a Runtime key as `apikey`; `integration` is kept but never sent;
|
|
39
|
+
* anything else throws NotSupportedError. */
|
|
39
40
|
export declare const settings: {
|
|
40
41
|
readonly env: string;
|
|
41
42
|
readonly region: string | undefined;
|
|
42
43
|
readonly workspace: string;
|
|
44
|
+
integration: string;
|
|
43
45
|
setConfig(config: Config): void;
|
|
44
46
|
authenticate(): Promise<void>;
|
|
45
47
|
readonly [key: string]: unknown;
|
|
@@ -124,6 +126,7 @@ export declare const updateDrive: import("./unsupported.js").Unsupported;
|
|
|
124
126
|
export declare const createDriveAccessToken: import("./unsupported.js").Unsupported;
|
|
125
127
|
export declare const getDriveByExternalId: import("./unsupported.js").Unsupported;
|
|
126
128
|
export declare const getDriveJwks: import("./unsupported.js").Unsupported;
|
|
129
|
+
export declare const deleteDriveFolder: import("./unsupported.js").Unsupported;
|
|
127
130
|
export declare const listAllEgressGateways: import("./unsupported.js").Unsupported;
|
|
128
131
|
export declare const getEgressGatewayUsage: import("./unsupported.js").Unsupported;
|
|
129
132
|
export declare const listAllEgressIps: import("./unsupported.js").Unsupported;
|
|
@@ -214,6 +217,10 @@ export declare const getSandboxByExternalId: import("./unsupported.js").Unsuppor
|
|
|
214
217
|
export declare const listScheduleExecutions: import("./unsupported.js").Unsupported;
|
|
215
218
|
export declare const listSchedules: import("./unsupported.js").Unsupported;
|
|
216
219
|
export declare const getSandboxScheduleMetrics: import("./unsupported.js").Unsupported;
|
|
220
|
+
export declare const listSecrets: import("./unsupported.js").Unsupported;
|
|
221
|
+
export declare const upsertSecret: import("./unsupported.js").Unsupported;
|
|
222
|
+
export declare const deleteSecret: import("./unsupported.js").Unsupported;
|
|
223
|
+
export declare const deleteSecretByQuery: import("./unsupported.js").Unsupported;
|
|
217
224
|
export declare const getWorkspaceServiceAccounts: import("./unsupported.js").Unsupported;
|
|
218
225
|
export declare const createWorkspaceServiceAccount: import("./unsupported.js").Unsupported;
|
|
219
226
|
export declare const deleteWorkspaceServiceAccount: import("./unsupported.js").Unsupported;
|
package/dist/blaxel/index.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* import { SandboxInstance } from "withruntime/blaxel"; // was: from "@blaxel/core"
|
|
5
5
|
*
|
|
6
6
|
* and set RUNTIME_API_KEY, or run `npx withruntime login` once. A Blaxel key
|
|
7
|
-
* (BL_API_KEY) is never sent anywhere. Every name `@blaxel/core` 0.3.
|
|
7
|
+
* (BL_API_KEY) is never sent anywhere. Every name `@blaxel/core` 0.3.30
|
|
8
8
|
* exports can be imported; what Runtime cannot do the way Blaxel does throws
|
|
9
9
|
* NotSupportedError, naming what to use. */
|
|
10
10
|
import { RuntimeError } from "../errors.js";
|
|
11
|
-
import { initialize } from "./client.js";
|
|
11
|
+
import { initialize, integrationToken, setIntegrationToken } from "./client.js";
|
|
12
12
|
import { NotSupportedError } from "./errors.js";
|
|
13
13
|
import { CODEGEN, DRIVES, SCHEDULES, SYSTEM, unsupportedExport } from "./unsupported.js";
|
|
14
14
|
export { SandboxInstance, DEFAULT_IMAGE, DEFAULT_MEMORY, MEMORY_PER_VCPU, durationMs, imageRef, lifetimeOf, networkRules, MAX_CREATION_TIMEOUT_SECONDS, } from "./sandbox.js";
|
|
@@ -17,7 +17,7 @@ export { SandboxFileSystem, retryOnTransient, } from "./filesystem.js";
|
|
|
17
17
|
export { SandboxProcess, } from "./process.js";
|
|
18
18
|
export { SandboxPreview, SandboxPreviews, SandboxPreviewToken, SandboxPreviewTokens, } from "./preview.js";
|
|
19
19
|
export { Snapshot, SandboxSnapshotsResource, } from "./snapshot.js";
|
|
20
|
-
export { ResponseError, SandboxCreationTimeoutError, isCreationTimeoutError, SandboxGatewayError, isGatewayError, isGatewayTimeout, CredentialsError, NotSupportedError, } from "./errors.js";
|
|
20
|
+
export { ResponseError, SandboxCreationTimeoutError, isCreationTimeoutError, SandboxGatewayError, isGatewayError, isGatewayTimeout, CredentialsError, NotSupportedError, isBlaxelError, getBlaxelErrorCode, getBlaxelErrorStatus, getBlaxelErrorMessage, getBlaxelErrorRequestId, } from "./errors.js";
|
|
21
21
|
export { createPaginatedList, unwrapListData, } from "./pagination.js";
|
|
22
22
|
export { normalizePorts, normalizeEnvs, normalizeVolumes, } from "./types.js";
|
|
23
23
|
export { initialize } from "./client.js";
|
|
@@ -54,7 +54,8 @@ export const logger = {
|
|
|
54
54
|
error: (...message) => sink.error(text(message)),
|
|
55
55
|
};
|
|
56
56
|
/** Blaxel's settings, as far as they mean anything on Runtime. `setConfig`
|
|
57
|
-
* takes a Runtime key as `apikey`;
|
|
57
|
+
* takes a Runtime key as `apikey`; `integration` is kept but never sent;
|
|
58
|
+
* anything else throws NotSupportedError. */
|
|
58
59
|
export const settings = new Proxy({
|
|
59
60
|
get env() {
|
|
60
61
|
return "prod";
|
|
@@ -65,6 +66,14 @@ export const settings = new Proxy({
|
|
|
65
66
|
get workspace() {
|
|
66
67
|
return env.BL_WORKSPACE ?? "";
|
|
67
68
|
},
|
|
69
|
+
/* Blaxel's product token for an integration (0.3.29): checked and kept
|
|
70
|
+
as Blaxel does, never sent; Runtime does not attribute traffic by it. */
|
|
71
|
+
get integration() {
|
|
72
|
+
return integrationToken();
|
|
73
|
+
},
|
|
74
|
+
set integration(value) {
|
|
75
|
+
setIntegrationToken(value);
|
|
76
|
+
},
|
|
68
77
|
setConfig: (config) => initialize(config),
|
|
69
78
|
authenticate,
|
|
70
79
|
}, {
|
|
@@ -176,6 +185,7 @@ export const updateDrive = api("updateDrive");
|
|
|
176
185
|
export const createDriveAccessToken = api("createDriveAccessToken");
|
|
177
186
|
export const getDriveByExternalId = api("getDriveByExternalId");
|
|
178
187
|
export const getDriveJwks = api("getDriveJwks");
|
|
188
|
+
export const deleteDriveFolder = api("deleteDriveFolder");
|
|
179
189
|
export const listAllEgressGateways = api("listAllEgressGateways");
|
|
180
190
|
export const getEgressGatewayUsage = api("getEgressGatewayUsage");
|
|
181
191
|
export const listAllEgressIps = api("listAllEgressIps");
|
|
@@ -266,6 +276,15 @@ export const getSandboxByExternalId = api("getSandboxByExternalId");
|
|
|
266
276
|
export const listScheduleExecutions = api("listScheduleExecutions");
|
|
267
277
|
export const listSchedules = api("listSchedules");
|
|
268
278
|
export const getSandboxScheduleMetrics = api("getSandboxScheduleMetrics");
|
|
279
|
+
/* @blaxel/core 0.3.30's workspace secrets, which Blaxel's proxy puts into a
|
|
280
|
+
sandbox's routing as {{SECRET:name}}. Runtime's secrets are bound to the
|
|
281
|
+
hosts they may reach, which Blaxel's calls do not name. */
|
|
282
|
+
const SECRETS = 'Use Runtime secrets, which name the hosts a secret may reach: runtime.secrets.set(name, { value, hosts }) (`import { Runtime } from "withruntime"`); the egress proxy adds the value on HTTPS to those hosts and the sandbox never sees it.';
|
|
283
|
+
const secretApi = (name) => unsupportedExport(`API function ${name}`, SECRETS);
|
|
284
|
+
export const listSecrets = secretApi("listSecrets");
|
|
285
|
+
export const upsertSecret = secretApi("upsertSecret");
|
|
286
|
+
export const deleteSecret = secretApi("deleteSecret");
|
|
287
|
+
export const deleteSecretByQuery = secretApi("deleteSecretByQuery");
|
|
269
288
|
export const getWorkspaceServiceAccounts = api("getWorkspaceServiceAccounts");
|
|
270
289
|
export const createWorkspaceServiceAccount = api("createWorkspaceServiceAccount");
|
|
271
290
|
export const deleteWorkspaceServiceAccount = api("deleteWorkspaceServiceAccount");
|
package/dist/blaxel/preview.d.ts
CHANGED
|
@@ -30,6 +30,14 @@ export type Preview = {
|
|
|
30
30
|
spec: PreviewSpec;
|
|
31
31
|
status?: string;
|
|
32
32
|
};
|
|
33
|
+
/** @blaxel/core 0.3.29's shorthand for `previews.create` and
|
|
34
|
+
* `createIfNotExists`: a port, with a name (`preview-<port>` when left out)
|
|
35
|
+
* and public (false when left out). */
|
|
36
|
+
export type SandboxPreviewCreateConfiguration = {
|
|
37
|
+
port: number;
|
|
38
|
+
name?: string;
|
|
39
|
+
public?: boolean;
|
|
40
|
+
};
|
|
33
41
|
export type PreviewToken = {
|
|
34
42
|
metadata: {
|
|
35
43
|
name: string;
|
|
@@ -45,6 +53,9 @@ export type PreviewToken = {
|
|
|
45
53
|
/** What the previews need from their sandbox. */
|
|
46
54
|
export interface PreviewContext {
|
|
47
55
|
readonly sandboxName: string;
|
|
56
|
+
/** The Runtime sandbox's id, when known: tokens made for a sandbox are
|
|
57
|
+
* never reused for another of the same name. */
|
|
58
|
+
readonly sandboxId?: string;
|
|
48
59
|
run<T>(work: (runtime: RuntimeSandbox) => Promise<T>): Promise<T>;
|
|
49
60
|
/** The sandbox's labels as last read. */
|
|
50
61
|
labels(): Record<string, string>;
|
|
@@ -56,6 +67,7 @@ export interface PreviewContext {
|
|
|
56
67
|
export declare class SandboxPreviewToken {
|
|
57
68
|
#private;
|
|
58
69
|
constructor(previewToken: PreviewToken);
|
|
70
|
+
get name(): string;
|
|
59
71
|
get value(): string;
|
|
60
72
|
get expiresAt(): string | Date;
|
|
61
73
|
get expired(): boolean;
|
|
@@ -70,6 +82,13 @@ export declare class SandboxPreviewTokens {
|
|
|
70
82
|
/** A token bounded by `expiresAt`; native signing floors milliseconds and
|
|
71
83
|
* caps it to the caller's session. Older servers refuse without a TTL fallback. */
|
|
72
84
|
create(expiresAt: Date): Promise<SandboxPreviewToken>;
|
|
85
|
+
/** Blaxel's (0.3.29): the latest token lasting at least `minValidity` ms
|
|
86
|
+
* more (an hour unless given) and not past `expiresAt` (a day from now
|
|
87
|
+
* unless given), else a new one until `expiresAt`. Blaxel picks among the
|
|
88
|
+
* preview's listed tokens; Runtime keeps no list, so the one reused is the
|
|
89
|
+
* token this call made last in this process for this sandbox's port, and a
|
|
90
|
+
* new process makes a new one. Arguments are checked as Blaxel does. */
|
|
91
|
+
createIfExpired(expiresAt?: Date, minValidity?: number): Promise<SandboxPreviewToken>;
|
|
73
92
|
list(): Promise<never>;
|
|
74
93
|
/** Revokes the preview's tokens. Runtime cannot revoke one token alone, so
|
|
75
94
|
* every token issued for this preview stops working. */
|
|
@@ -85,6 +104,8 @@ export declare class SandboxPreview {
|
|
|
85
104
|
get name(): string;
|
|
86
105
|
get metadata(): PreviewMetadata;
|
|
87
106
|
get spec(): PreviewSpec;
|
|
107
|
+
/** The preview's address (`spec.url`), or `""`. */
|
|
108
|
+
get url(): string;
|
|
88
109
|
}
|
|
89
110
|
/** `sandbox.previews`. */
|
|
90
111
|
export declare class SandboxPreviews {
|
|
@@ -94,10 +115,14 @@ export declare class SandboxPreviews {
|
|
|
94
115
|
/** Every shared port. One Runtime shared without a Blaxel name is named
|
|
95
116
|
* `preview-<port>`. */
|
|
96
117
|
list(): Promise<SandboxPreview[]>;
|
|
97
|
-
/** Shares `spec.port`: public with `spec.public`, else behind a token.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
118
|
+
/** Shares `spec.port`: public with `spec.public`, else behind a token.
|
|
119
|
+
* Blaxel's shorthand `{ port, name?, public? }` is a private
|
|
120
|
+
* `preview-<port>` unless it says otherwise. */
|
|
121
|
+
create(input: Preview | SandboxPreviewCreateConfiguration, _force?: boolean): Promise<SandboxPreview>;
|
|
122
|
+
/** The named preview, or a new one when there is none. An existing
|
|
123
|
+
* preview is answered as it is: the shorthand's private default applies
|
|
124
|
+
* only to a new one. */
|
|
125
|
+
createIfNotExists(input: Preview | SandboxPreviewCreateConfiguration, force?: boolean): Promise<SandboxPreview>;
|
|
101
126
|
get(previewName: string): Promise<SandboxPreview>;
|
|
102
127
|
/** Stops sharing the port; its open connections are closed before this returns. */
|
|
103
128
|
delete(previewName: string): Promise<Preview>;
|
package/dist/blaxel/preview.js
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
import { guard, isNotFound, NotSupportedError, responseError } from "./errors.js";
|
|
2
2
|
import { PREVIEW } from "./lookup.js";
|
|
3
|
+
const isShorthand = (preview) => !("metadata" in preview || "spec" in preview);
|
|
4
|
+
/** Blaxel's shorthand as the full shape, with Blaxel's checks and messages. */
|
|
5
|
+
function normalizePreview(preview) {
|
|
6
|
+
if (!isShorthand(preview))
|
|
7
|
+
return preview;
|
|
8
|
+
const short = preview;
|
|
9
|
+
if (!Number.isInteger(short.port) || short.port < 1 || short.port > 65535)
|
|
10
|
+
throw new RangeError("Preview port must be an integer between 1 and 65535");
|
|
11
|
+
if (short.name !== undefined && (typeof short.name !== "string" || short.name.length === 0))
|
|
12
|
+
throw new RangeError("Preview name must be a nonempty string");
|
|
13
|
+
if (short.public !== undefined && typeof short.public !== "boolean")
|
|
14
|
+
throw new RangeError("Preview public must be a boolean");
|
|
15
|
+
return {
|
|
16
|
+
metadata: { name: short.name ?? `preview-${short.port}` },
|
|
17
|
+
spec: { port: short.port, public: short.public ?? false },
|
|
18
|
+
};
|
|
19
|
+
}
|
|
3
20
|
function checkName(name) {
|
|
4
21
|
if (!/^[A-Za-z0-9._-]{1,48}$/.test(name))
|
|
5
22
|
throw new NotSupportedError(`The preview name "${name}"`, "Use 1 to 48 letters, digits, dots, dashes or underscores.");
|
|
@@ -27,6 +44,9 @@ export class SandboxPreviewToken {
|
|
|
27
44
|
constructor(previewToken) {
|
|
28
45
|
this.#token = previewToken;
|
|
29
46
|
}
|
|
47
|
+
get name() {
|
|
48
|
+
return this.#token.metadata?.name ?? "";
|
|
49
|
+
}
|
|
30
50
|
get value() {
|
|
31
51
|
return this.#token.spec.token ?? "";
|
|
32
52
|
}
|
|
@@ -38,6 +58,9 @@ export class SandboxPreviewToken {
|
|
|
38
58
|
return at !== undefined && Date.parse(at) <= Date.now();
|
|
39
59
|
}
|
|
40
60
|
}
|
|
61
|
+
/** The token createIfExpired made last, per sandbox and port, in this
|
|
62
|
+
* process: Runtime keeps no list of the tokens it signed. */
|
|
63
|
+
const madeTokens = new Map();
|
|
41
64
|
/** A preview's tokens. Runtime signs a token for a duration; it keeps no
|
|
42
65
|
* list of the tokens issued. */
|
|
43
66
|
export class SandboxPreviewTokens {
|
|
@@ -53,6 +76,9 @@ export class SandboxPreviewTokens {
|
|
|
53
76
|
get resourceName() {
|
|
54
77
|
return this.#ctx.sandboxName;
|
|
55
78
|
}
|
|
79
|
+
#key() {
|
|
80
|
+
return `${this.#ctx.sandboxId ?? this.#ctx.sandboxName}:${this.#preview.spec.port}`;
|
|
81
|
+
}
|
|
56
82
|
/** A token bounded by `expiresAt`; native signing floors milliseconds and
|
|
57
83
|
* caps it to the caller's session. Older servers refuse without a TTL fallback. */
|
|
58
84
|
async create(expiresAt) {
|
|
@@ -73,6 +99,35 @@ export class SandboxPreviewTokens {
|
|
|
73
99
|
spec: { token: got.token, expiresAt: got.tokenExpiresAt },
|
|
74
100
|
});
|
|
75
101
|
}
|
|
102
|
+
/** Blaxel's (0.3.29): the latest token lasting at least `minValidity` ms
|
|
103
|
+
* more (an hour unless given) and not past `expiresAt` (a day from now
|
|
104
|
+
* unless given), else a new one until `expiresAt`. Blaxel picks among the
|
|
105
|
+
* preview's listed tokens; Runtime keeps no list, so the one reused is the
|
|
106
|
+
* token this call made last in this process for this sandbox's port, and a
|
|
107
|
+
* new process makes a new one. Arguments are checked as Blaxel does. */
|
|
108
|
+
async createIfExpired(expiresAt, minValidity = 3_600_000) {
|
|
109
|
+
const now = Date.now();
|
|
110
|
+
if (!Number.isFinite(minValidity) || minValidity < 0)
|
|
111
|
+
throw new RangeError("minValidity must be finite and non-negative");
|
|
112
|
+
const requested = expiresAt ?? new Date(now + 86_400_000);
|
|
113
|
+
const ceiling = requested instanceof Date ? requested.getTime() : Number.NaN;
|
|
114
|
+
if (!Number.isFinite(ceiling) || ceiling <= now || ceiling < now + minValidity)
|
|
115
|
+
throw new RangeError("expiresAt must be a valid future date at least minValidity from now");
|
|
116
|
+
if (this.#preview.spec.public === true)
|
|
117
|
+
throw new Error("Cannot create or reuse a token for a public preview");
|
|
118
|
+
const key = this.#key();
|
|
119
|
+
const kept = madeTokens.get(key);
|
|
120
|
+
if (kept &&
|
|
121
|
+
kept.expiresAt > now &&
|
|
122
|
+
kept.expiresAt >= now + minValidity &&
|
|
123
|
+
kept.expiresAt <= ceiling)
|
|
124
|
+
return kept.token;
|
|
125
|
+
const token = await this.create(requested);
|
|
126
|
+
const until = Date.parse(String(token.expiresAt));
|
|
127
|
+
if (Number.isFinite(until))
|
|
128
|
+
madeTokens.set(key, { token, expiresAt: until });
|
|
129
|
+
return token;
|
|
130
|
+
}
|
|
76
131
|
list() {
|
|
77
132
|
return Promise.reject(new NotSupportedError("Listing a preview's tokens", "Runtime keeps no list of issued tokens: keep the ones you create, or create a new one."));
|
|
78
133
|
}
|
|
@@ -81,6 +136,7 @@ export class SandboxPreviewTokens {
|
|
|
81
136
|
async delete(_tokenName) {
|
|
82
137
|
const port = this.#preview.spec.port;
|
|
83
138
|
await this.#ctx.run((runtime) => runtime.previews.rotate(port));
|
|
139
|
+
madeTokens.delete(this.#key());
|
|
84
140
|
return { message: "Every token of this preview was revoked" };
|
|
85
141
|
}
|
|
86
142
|
}
|
|
@@ -101,6 +157,10 @@ export class SandboxPreview {
|
|
|
101
157
|
get spec() {
|
|
102
158
|
return this.#preview.spec;
|
|
103
159
|
}
|
|
160
|
+
/** The preview's address (`spec.url`), or `""`. */
|
|
161
|
+
get url() {
|
|
162
|
+
return this.#preview.spec?.url ?? "";
|
|
163
|
+
}
|
|
104
164
|
}
|
|
105
165
|
/** `sandbox.previews`. */
|
|
106
166
|
export class SandboxPreviews {
|
|
@@ -133,8 +193,11 @@ export class SandboxPreviews {
|
|
|
133
193
|
const names = this.#names();
|
|
134
194
|
return previews.map((one) => new SandboxPreview(modelOf(one, names.get(one.port) ?? `preview-${one.port}`, this.sandboxName), this.#ctx));
|
|
135
195
|
}
|
|
136
|
-
/** Shares `spec.port`: public with `spec.public`, else behind a token.
|
|
137
|
-
|
|
196
|
+
/** Shares `spec.port`: public with `spec.public`, else behind a token.
|
|
197
|
+
* Blaxel's shorthand `{ port, name?, public? }` is a private
|
|
198
|
+
* `preview-<port>` unless it says otherwise. */
|
|
199
|
+
async create(input, _force) {
|
|
200
|
+
const preview = input && typeof input === "object" ? normalizePreview(input) : input;
|
|
138
201
|
const spec = preview?.spec ?? {};
|
|
139
202
|
const name = preview?.metadata?.name;
|
|
140
203
|
const refusals = [
|
|
@@ -177,15 +240,26 @@ export class SandboxPreviews {
|
|
|
177
240
|
]);
|
|
178
241
|
return new SandboxPreview(modelOf(made, name ?? `preview-${port}`, this.sandboxName), this.#ctx);
|
|
179
242
|
}
|
|
180
|
-
/** The named preview, or a new one when there is none.
|
|
181
|
-
|
|
243
|
+
/** The named preview, or a new one when there is none. An existing
|
|
244
|
+
* preview is answered as it is: the shorthand's private default applies
|
|
245
|
+
* only to a new one. */
|
|
246
|
+
async createIfNotExists(input, force) {
|
|
247
|
+
const preview = normalizePreview(input);
|
|
182
248
|
try {
|
|
183
249
|
return await this.get(preview.metadata.name);
|
|
184
250
|
}
|
|
185
251
|
catch (error) {
|
|
186
252
|
if (!isNotFound(error))
|
|
187
253
|
throw error;
|
|
188
|
-
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
return await this.create(preview, force);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
// Blaxel's race: another caller made it first.
|
|
260
|
+
if (!isShorthand(input) || error?.status !== 409)
|
|
261
|
+
throw error;
|
|
262
|
+
return this.get(preview.metadata.name);
|
|
189
263
|
}
|
|
190
264
|
}
|
|
191
265
|
async get(previewName) {
|
package/dist/blaxel/sandbox.d.ts
CHANGED
|
@@ -139,7 +139,7 @@ export declare class SandboxInstance {
|
|
|
139
139
|
get expiresIn(): number | undefined;
|
|
140
140
|
/** Creates a sandbox and answers once it runs. Blaxel's defaults: the base
|
|
141
141
|
* image (Runtime's stock image) and 4096 MB, with vCPUs at one per 2048 MB.
|
|
142
|
-
* Funding is left to Runtime: the
|
|
142
|
+
* Funding is left to Runtime: the free usage first, then prepaid credit. A name another live sandbox holds is refused
|
|
143
143
|
* with a 409, as in Blaxel. */
|
|
144
144
|
static create<T extends typeof SandboxInstance>(this: T, sandbox?: SandboxCreateConfiguration | SandboxModel, options?: SandboxCreateOptions): Promise<InstanceType<T>>;
|
|
145
145
|
/** The named sandbox, or a new one when no live sandbox has the name.
|
package/dist/blaxel/sandbox.js
CHANGED
|
@@ -332,6 +332,7 @@ export class SandboxInstance {
|
|
|
332
332
|
});
|
|
333
333
|
this.previews = new SandboxPreviews({
|
|
334
334
|
sandboxName: this.name,
|
|
335
|
+
sandboxId: this.#rt.id,
|
|
335
336
|
run,
|
|
336
337
|
labels: () => this.#rt.info.labels,
|
|
337
338
|
setLabels: (changes) => this.#setLabels(changes),
|
|
@@ -573,7 +574,7 @@ export class SandboxInstance {
|
|
|
573
574
|
// ---- create, get, list ---------------------------------------------------
|
|
574
575
|
/** Creates a sandbox and answers once it runs. Blaxel's defaults: the base
|
|
575
576
|
* image (Runtime's stock image) and 4096 MB, with vCPUs at one per 2048 MB.
|
|
576
|
-
* Funding is left to Runtime: the
|
|
577
|
+
* Funding is left to Runtime: the free usage first, then prepaid credit. A name another live sandbox holds is refused
|
|
577
578
|
* with a 409, as in Blaxel. */
|
|
578
579
|
static async create(sandbox, options = {}) {
|
|
579
580
|
const { createIfNotExist = false, safe = false } = options;
|
package/dist/blaxel/session.js
CHANGED
|
@@ -44,8 +44,10 @@ function origins(headers = {}) {
|
|
|
44
44
|
return found;
|
|
45
45
|
}
|
|
46
46
|
function seconds(expiresAt) {
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
// Blaxel's default is a day; counted from a moment ago it would be a second short.
|
|
48
|
+
if (!expiresAt)
|
|
49
|
+
return DAY_MS / 1000;
|
|
50
|
+
const left = Math.floor((expiresAt.getTime() - Date.now()) / 1000);
|
|
49
51
|
if (!Number.isFinite(left) || left < 60)
|
|
50
52
|
throw responseError(400, "A session must last at least a minute.");
|
|
51
53
|
if (left > DAY_MS / 1000 + 5)
|
package/dist/cli-extras.js
CHANGED
|
@@ -108,7 +108,7 @@ export async function mcpCommand(sbx, argv, out, kit) {
|
|
|
108
108
|
};
|
|
109
109
|
switch (action) {
|
|
110
110
|
case "start": {
|
|
111
|
-
const args = parse(rest, ["replace"], ["secret", "env", "option", "port"]);
|
|
111
|
+
const args = parse(rest, ["replace", "public"], ["secret", "env", "option", "port"]);
|
|
112
112
|
if (!args.positional.length)
|
|
113
113
|
throw usage("Name the servers: runtime sandboxes mcp <id> start github fetch");
|
|
114
114
|
const scoped = (name) => {
|
|
@@ -133,6 +133,7 @@ export async function mcpCommand(sbx, argv, out, kit) {
|
|
|
133
133
|
const gw = await sbx.mcp.start(servers, {
|
|
134
134
|
...(integer(args, "port") ? { port: integer(args, "port") } : {}),
|
|
135
135
|
...(has(args, "replace") ? { replace: true } : {}),
|
|
136
|
+
...(has(args, "public") ? { public: true } : {}),
|
|
136
137
|
});
|
|
137
138
|
print(`${show(gw)}\nServers are installing; \`${me} sandboxes mcp ${sbx.id}\` shows when they are ready.`, gw);
|
|
138
139
|
return 0;
|
package/dist/cli-words.js
CHANGED
|
@@ -24,6 +24,7 @@ const OPTIONS = {
|
|
|
24
24
|
funding: { flag: "--trial / --paid" },
|
|
25
25
|
image: { flag: "--image" },
|
|
26
26
|
snapshot: { flag: "--snapshot" },
|
|
27
|
+
spreadFrom: { flag: "--spread-from" },
|
|
27
28
|
volumes: { flag: "--volume" },
|
|
28
29
|
network: { flag: "--allow / --deny / --connect / --no-internet" },
|
|
29
30
|
maxCostMicros: { flag: "--max-cost", micros: true },
|
package/dist/cli.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { RuntimeError } from "./errors.js";
|
|
3
3
|
import type { OutOfMemory, Usage } from "./types.js";
|
|
4
4
|
import type { SwitchProvider } from "./products/switching.js";
|
|
5
|
-
import type { SecretRule } from "./products/secrets.js";
|
|
5
|
+
import type { SecretRule, SecretScope } from "./products/secrets.js";
|
|
6
6
|
type Out = {
|
|
7
7
|
json: boolean;
|
|
8
8
|
write: (text: string) => void;
|
|
@@ -30,7 +30,7 @@ declare const kit: {
|
|
|
30
30
|
};
|
|
31
31
|
export type CliKit = typeof kit;
|
|
32
32
|
export declare function run(argv: string[], env?: NodeJS.ProcessEnv, out?: Out): Promise<number>;
|
|
33
|
-
/** `runtime usage` for a person: the balance, the
|
|
33
|
+
/** `runtime usage` for a person: the balance, the free usage and what each kind
|
|
34
34
|
* of resource was charged, in dollars. --json keeps every figure, and each
|
|
35
35
|
* resource with its rates and CPU time. */
|
|
36
36
|
/** One row per resource, for a spreadsheet: when it ran, how big it was, how
|
|
@@ -44,12 +44,27 @@ export declare function usageCsv(u: Usage): string;
|
|
|
44
44
|
export declare function outOfMemoryLines(memory: OutOfMemory | undefined): string | undefined;
|
|
45
45
|
/** How to move a rival's code across, when one import does it. */
|
|
46
46
|
export declare function dropInLines(provider: SwitchProvider | undefined): string[];
|
|
47
|
+
/** A secret's value, from standard input only, so it never sits in shell
|
|
48
|
+
* history or a process list. Piped: everything, less one trailing newline.
|
|
49
|
+
* A terminal: one line, not shown. */
|
|
50
|
+
/** A pasted secret as the header it becomes: no line breaks (a token copied
|
|
51
|
+
* from a terminal arrives wrapped), no bracketed-paste markers, no space at
|
|
52
|
+
* either end. 13 October 2026: a user's pasted Claude token was refused as
|
|
53
|
+
* "not visible ASCII". A header cannot hold a line break, so none is lost. */
|
|
54
|
+
export declare function cleanSecret(raw: string): string;
|
|
47
55
|
/** `--allow` values as secret rules: each is `[METHOD[,METHOD]...] PATH`, and
|
|
48
56
|
* rules naming the same methods share one rule's paths. Only the shape is read
|
|
49
57
|
* here; the API holds every rule to the same check the host makes
|
|
50
58
|
* (ARCHITECTURE.md section 10, "Per-path rules on an egress secret") and says
|
|
51
59
|
* which one it refused. */
|
|
52
60
|
export declare function parseSecretRules(values: string[]): SecretRule[];
|
|
61
|
+
/** `--only-label role=hub,tier=x --only-sandbox <id>`: a sandbox whose labels
|
|
62
|
+
* hold every pair of any one --only-label gets the secret, and so does each
|
|
63
|
+
* --only-sandbox. `--all-sandboxes`: every sandbox again. Nothing: undefined,
|
|
64
|
+
* so a replacement keeps the scope it has. */
|
|
65
|
+
export declare function parseSecretScope(labels: string[] | undefined, sandboxes: string[] | undefined, all: boolean): SecretScope | undefined;
|
|
66
|
+
/** Who gets a secret, in a few words. */
|
|
67
|
+
export declare const scopeText: (only: SecretScope | undefined) => string;
|
|
53
68
|
export declare function secretsCommand(argv: string[], env: NodeJS.ProcessEnv, out: Out,
|
|
54
69
|
/** Tests give the value here; the CLI reads standard input. */
|
|
55
70
|
read?: () => Promise<string>): Promise<number>;
|