@blaxel/core 0.3.26-preview.309 → 0.3.26-preview.311
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/common/error-types.js +133 -0
- package/dist/cjs/common/settings.js +2 -2
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/sandbox/index.js +1 -0
- package/dist/cjs/sandbox/preview.js +104 -1
- package/dist/cjs/types/common/error-types.d.ts +159 -0
- package/dist/cjs/types/index.d.ts +1 -0
- package/dist/cjs/types/sandbox/index.d.ts +1 -0
- package/dist/cjs/types/sandbox/preview.d.ts +12 -3
- package/dist/cjs/types/sandbox/types.d.ts +7 -0
- package/dist/cjs-browser/.tsbuildinfo +1 -1
- package/dist/cjs-browser/common/error-types.js +133 -0
- package/dist/cjs-browser/common/settings.js +2 -2
- package/dist/cjs-browser/index.js +1 -0
- package/dist/cjs-browser/sandbox/index.js +1 -0
- package/dist/cjs-browser/sandbox/preview.js +104 -1
- package/dist/cjs-browser/types/common/error-types.d.ts +159 -0
- package/dist/cjs-browser/types/index.d.ts +1 -0
- package/dist/cjs-browser/types/sandbox/index.d.ts +1 -0
- package/dist/cjs-browser/types/sandbox/preview.d.ts +12 -3
- package/dist/cjs-browser/types/sandbox/types.d.ts +7 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/common/error-types.js +126 -0
- package/dist/esm/common/settings.js +2 -2
- package/dist/esm/index.js +1 -0
- package/dist/esm/sandbox/index.js +1 -0
- package/dist/esm/sandbox/preview.js +104 -1
- package/dist/esm-browser/.tsbuildinfo +1 -1
- package/dist/esm-browser/common/error-types.js +126 -0
- package/dist/esm-browser/common/settings.js +2 -2
- package/dist/esm-browser/index.js +1 -0
- package/dist/esm-browser/sandbox/index.js +1 -0
- package/dist/esm-browser/sandbox/preview.js +104 -1
- package/package.json +1 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isBlaxelError = isBlaxelError;
|
|
4
|
+
exports.getBlaxelErrorCode = getBlaxelErrorCode;
|
|
5
|
+
exports.getBlaxelErrorStatus = getBlaxelErrorStatus;
|
|
6
|
+
exports.getBlaxelErrorMessage = getBlaxelErrorMessage;
|
|
7
|
+
exports.getBlaxelErrorRequestId = getBlaxelErrorRequestId;
|
|
8
|
+
const action_js_1 = require("../sandbox/action.js");
|
|
9
|
+
const sandbox_js_1 = require("../sandbox/sandbox.js");
|
|
10
|
+
function readProperty(value, key) {
|
|
11
|
+
try {
|
|
12
|
+
return typeof value === "object" && value !== null
|
|
13
|
+
? value[key]
|
|
14
|
+
: undefined;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Catch hostile getters and revoked proxies, including in custom transports.
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const isCode = (value) => (typeof value === "string" && value.length > 0) ||
|
|
22
|
+
(typeof value === "number" && Number.isFinite(value));
|
|
23
|
+
const isStatus = (value) => typeof value === "number" && Number.isInteger(value) && value >= 100 && value <= 599;
|
|
24
|
+
/**
|
|
25
|
+
* True only for a value that carries a Blaxel error code or HTTP status in a
|
|
26
|
+
* shape the SDK throws for API failures: a `ResponseError` (including
|
|
27
|
+
* `SandboxGatewayError`), a `SandboxCreationTimeoutError`, or a raw control-plane
|
|
28
|
+
* error body (`{ error, code }`, `{ code, message, status_code }` or
|
|
29
|
+
* `{ error: { code, message, status } }`). Plain `Error`s (including network
|
|
30
|
+
* errors with a `code` such as `ECONNRESET`), strings, raw HTML/text bodies, empty
|
|
31
|
+
* bodies and a bare `{ error: string }` are false: they carry neither. Matching
|
|
32
|
+
* `ResponseError` uses `instanceof`, so an error thrown by a second copy of
|
|
33
|
+
* `@blaxel/core` does not match. Does not wrap or mutate the value. Never throws.
|
|
34
|
+
* Like `is_blaxel_error` in the Python SDK, it is false for plain exceptions and
|
|
35
|
+
* strings.
|
|
36
|
+
*/
|
|
37
|
+
function isBlaxelError(err) {
|
|
38
|
+
try {
|
|
39
|
+
if (err instanceof Error) {
|
|
40
|
+
return err instanceof action_js_1.ResponseError || err instanceof sandbox_js_1.SandboxCreationTimeoutError;
|
|
41
|
+
}
|
|
42
|
+
if (typeof err !== "object" || err === null || Array.isArray(err))
|
|
43
|
+
return false;
|
|
44
|
+
const error = readProperty(err, "error");
|
|
45
|
+
if (typeof error === "string")
|
|
46
|
+
return isStatus(readProperty(err, "code"));
|
|
47
|
+
if (typeof readProperty(err, "code") === "string" &&
|
|
48
|
+
typeof readProperty(err, "message") === "string" &&
|
|
49
|
+
isStatus(readProperty(err, "status_code")))
|
|
50
|
+
return true;
|
|
51
|
+
return (typeof error === "object" && error !== null && !Array.isArray(error) &&
|
|
52
|
+
typeof readProperty(error, "code") === "string" &&
|
|
53
|
+
typeof readProperty(error, "message") === "string" &&
|
|
54
|
+
isStatus(readProperty(error, "status")));
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Fixed-depth inspection: ResponseError carries `error`/`data`; gateway bodies
|
|
61
|
+
// nest their fields once more in `error`. No recursion, including on cyclic input.
|
|
62
|
+
function errorCandidates(err) {
|
|
63
|
+
const bodies = [err, readProperty(err, "error"), readProperty(err, "data")];
|
|
64
|
+
return bodies.flatMap((body) => [body, readProperty(body, "error")]);
|
|
65
|
+
}
|
|
66
|
+
function readHeader(err, name) {
|
|
67
|
+
try {
|
|
68
|
+
const headers = readProperty(readProperty(err, "response"), "headers");
|
|
69
|
+
const get = readProperty(headers, "get");
|
|
70
|
+
if (typeof get !== "function")
|
|
71
|
+
return undefined;
|
|
72
|
+
const value = Reflect.apply(get, headers, [name]);
|
|
73
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Read a code from the existing error/body, then X-Blaxel-Error-Code. Never throws. */
|
|
80
|
+
function getBlaxelErrorCode(err) {
|
|
81
|
+
for (const candidate of errorCandidates(err)) {
|
|
82
|
+
const code = readProperty(candidate, "code");
|
|
83
|
+
if (isCode(code))
|
|
84
|
+
return code;
|
|
85
|
+
}
|
|
86
|
+
return readHeader(err, "x-blaxel-error-code");
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Read HTTP status from the existing error/response, then the body (`status`,
|
|
90
|
+
* `status_code`, or a numeric `code`). Raw text and plain Error have none.
|
|
91
|
+
* Never throws.
|
|
92
|
+
*/
|
|
93
|
+
function getBlaxelErrorStatus(err) {
|
|
94
|
+
const status = readProperty(err, "status");
|
|
95
|
+
if (isStatus(status))
|
|
96
|
+
return status;
|
|
97
|
+
const responseStatus = readProperty(readProperty(err, "response"), "status");
|
|
98
|
+
if (isStatus(responseStatus))
|
|
99
|
+
return responseStatus;
|
|
100
|
+
for (const candidate of errorCandidates(err)) {
|
|
101
|
+
for (const key of ["status", "status_code", "code"]) {
|
|
102
|
+
const value = readProperty(candidate, key);
|
|
103
|
+
if (isStatus(value))
|
|
104
|
+
return value;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Read the existing Error.message, body message/error text, or raw text/HTML.
|
|
111
|
+
* Returns undefined for an empty/unrecognized body. Never throws.
|
|
112
|
+
*/
|
|
113
|
+
function getBlaxelErrorMessage(err) {
|
|
114
|
+
for (const candidate of errorCandidates(err)) {
|
|
115
|
+
const message = typeof candidate === "string" ? candidate : readProperty(candidate, "message");
|
|
116
|
+
if (typeof message === "string" && message.length > 0)
|
|
117
|
+
return message;
|
|
118
|
+
}
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Read X-Cf-Request-Id, X-Amz-Cf-Id, then CF-Ray from a retained response.
|
|
123
|
+
* Raw control-plane bodies and SandboxCreationTimeoutError do not retain
|
|
124
|
+
* response headers, so their request ID is unavailable. Never throws.
|
|
125
|
+
*/
|
|
126
|
+
function getBlaxelErrorRequestId(err) {
|
|
127
|
+
for (const name of ["x-cf-request-id", "x-amz-cf-id", "cf-ray"]) {
|
|
128
|
+
const value = readHeader(err, name);
|
|
129
|
+
if (value !== undefined)
|
|
130
|
+
return value;
|
|
131
|
+
}
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
@@ -30,8 +30,8 @@ function missingCredentialsMessage() {
|
|
|
30
30
|
return "No Blaxel credentials found. Set the BL_API_KEY and BL_WORKSPACE environment variables, or run `bl login`.";
|
|
31
31
|
}
|
|
32
32
|
// Build info - these placeholders are replaced at build time by build:replace-imports
|
|
33
|
-
const BUILD_VERSION = "0.3.26-preview.
|
|
34
|
-
const BUILD_COMMIT = "
|
|
33
|
+
const BUILD_VERSION = "0.3.26-preview.311";
|
|
34
|
+
const BUILD_COMMIT = "a62496fa4537136926770cdd0d6e48ceb8506491";
|
|
35
35
|
const BUILD_SENTRY_DSN = "https://fd5e60e1c9820e1eef5ccebb84a07127@o4508714045276160.ingest.us.sentry.io/4510465864564736";
|
|
36
36
|
const BLAXEL_API_VERSION = "2026-09-22";
|
|
37
37
|
// Bun < 1.3.11 never sends connection-level WINDOW_UPDATE: the pooled h2
|
|
@@ -23,6 +23,7 @@ __exportStar(require("./common/env.js"), exports);
|
|
|
23
23
|
__exportStar(require("./common/h2-runtime.js"), exports);
|
|
24
24
|
__exportStar(require("./common/node.js"), exports);
|
|
25
25
|
__exportStar(require("./common/errors.js"), exports);
|
|
26
|
+
__exportStar(require("./common/error-types.js"), exports);
|
|
26
27
|
__exportStar(require("./common/internal.js"), exports);
|
|
27
28
|
__exportStar(require("./common/logger.js"), exports);
|
|
28
29
|
__exportStar(require("./common/pagination.js"), exports);
|
|
@@ -37,6 +37,7 @@ Object.defineProperty(exports, "ResponseError", { enumerable: true, get: functio
|
|
|
37
37
|
Object.defineProperty(exports, "SandboxGatewayError", { enumerable: true, get: function () { return action_js_1.SandboxGatewayError; } });
|
|
38
38
|
Object.defineProperty(exports, "isGatewayError", { enumerable: true, get: function () { return action_js_1.isGatewayError; } });
|
|
39
39
|
Object.defineProperty(exports, "isGatewayTimeout", { enumerable: true, get: function () { return action_js_1.isGatewayTimeout; } });
|
|
40
|
+
__exportStar(require("../common/error-types.js"), exports);
|
|
40
41
|
__exportStar(require("./filesystem/index.js"), exports);
|
|
41
42
|
__exportStar(require("./codegen/index.js"), exports);
|
|
42
43
|
var index_js_2 = require("./drive/index.js");
|
|
@@ -2,11 +2,48 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SandboxPreviews = exports.SandboxPreview = exports.SandboxPreviewTokens = exports.SandboxPreviewToken = void 0;
|
|
4
4
|
const index_js_1 = require("../client/index.js");
|
|
5
|
+
function isShorthand(preview) {
|
|
6
|
+
return !("metadata" in preview || "spec" in preview);
|
|
7
|
+
}
|
|
8
|
+
function normalizePreview(preview) {
|
|
9
|
+
if (!isShorthand(preview))
|
|
10
|
+
return preview;
|
|
11
|
+
if (!Number.isInteger(preview.port) || preview.port < 1 || preview.port > 65535) {
|
|
12
|
+
throw new RangeError("Preview port must be an integer between 1 and 65535");
|
|
13
|
+
}
|
|
14
|
+
if (preview.name !== undefined && (typeof preview.name !== "string" || preview.name.length === 0)) {
|
|
15
|
+
throw new RangeError("Preview name must be a nonempty string");
|
|
16
|
+
}
|
|
17
|
+
if (preview.public !== undefined && typeof preview.public !== "boolean") {
|
|
18
|
+
throw new RangeError("Preview public must be a boolean");
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
metadata: { name: preview.name ?? `preview-${preview.port}` },
|
|
22
|
+
spec: { port: preview.port, public: preview.public ?? false },
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
// Explicit HTTP status takes precedence over a legacy numeric service code.
|
|
26
|
+
function httpStatus(error) {
|
|
27
|
+
if (typeof error !== "object" || error === null)
|
|
28
|
+
return undefined;
|
|
29
|
+
const fields = error;
|
|
30
|
+
const response = fields.response;
|
|
31
|
+
const responseStatus = typeof response === "object" && response !== null && "status" in response
|
|
32
|
+
? response.status : undefined;
|
|
33
|
+
for (const status of [fields.status, fields.statusCode, responseStatus, fields.code]) {
|
|
34
|
+
if (typeof status === "number")
|
|
35
|
+
return status;
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
5
39
|
class SandboxPreviewToken {
|
|
6
40
|
previewToken;
|
|
7
41
|
constructor(previewToken) {
|
|
8
42
|
this.previewToken = previewToken;
|
|
9
43
|
}
|
|
44
|
+
get name() {
|
|
45
|
+
return this.previewToken.metadata?.name ?? "";
|
|
46
|
+
}
|
|
10
47
|
get value() {
|
|
11
48
|
return this.previewToken.spec.token ?? "";
|
|
12
49
|
}
|
|
@@ -47,6 +84,49 @@ class SandboxPreviewTokens {
|
|
|
47
84
|
});
|
|
48
85
|
return new SandboxPreviewToken(data);
|
|
49
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Reuse the latest token within the requested expiry ceiling, or mint one.
|
|
89
|
+
* minValidity is in milliseconds. Concurrent callers may create separate tokens.
|
|
90
|
+
*/
|
|
91
|
+
async createIfExpired(expiresAt, minValidity = 3_600_000) {
|
|
92
|
+
const now = Date.now();
|
|
93
|
+
if (!Number.isFinite(minValidity) || minValidity < 0) {
|
|
94
|
+
throw new RangeError("minValidity must be finite and non-negative");
|
|
95
|
+
}
|
|
96
|
+
const requestedExpiry = expiresAt ?? new Date(now + 86_400_000);
|
|
97
|
+
const ceiling = requestedExpiry instanceof Date ? requestedExpiry.getTime() : NaN;
|
|
98
|
+
if (!Number.isFinite(ceiling) || ceiling <= now || ceiling < now + minValidity) {
|
|
99
|
+
throw new RangeError("expiresAt must be a valid future date at least minValidity from now");
|
|
100
|
+
}
|
|
101
|
+
if (this.preview.spec?.public === true) {
|
|
102
|
+
throw new Error("Cannot create or reuse a token for a public preview");
|
|
103
|
+
}
|
|
104
|
+
const { data } = await (0, index_js_1.listSandboxPreviewTokens)({
|
|
105
|
+
path: {
|
|
106
|
+
sandboxName: this.resourceName,
|
|
107
|
+
previewName: this.previewName,
|
|
108
|
+
},
|
|
109
|
+
throwOnError: true,
|
|
110
|
+
});
|
|
111
|
+
if (!Array.isArray(data))
|
|
112
|
+
throw new Error("Failed to list preview tokens");
|
|
113
|
+
let selected;
|
|
114
|
+
let latestExpiry = -Infinity;
|
|
115
|
+
for (const token of data) {
|
|
116
|
+
const spec = token?.spec;
|
|
117
|
+
if (!spec || typeof spec.token !== "string" || spec.token.length === 0 || spec.expired === true ||
|
|
118
|
+
typeof spec.expiresAt !== "string")
|
|
119
|
+
continue;
|
|
120
|
+
const expiry = Date.parse(spec.expiresAt);
|
|
121
|
+
if (!Number.isFinite(expiry) || expiry <= now || expiry < now + minValidity || expiry > ceiling)
|
|
122
|
+
continue;
|
|
123
|
+
if (expiry > latestExpiry) {
|
|
124
|
+
selected = token;
|
|
125
|
+
latestExpiry = expiry;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return selected ? new SandboxPreviewToken(selected) : this.create(requestedExpiry);
|
|
129
|
+
}
|
|
50
130
|
async list() {
|
|
51
131
|
const { data } = await (0, index_js_1.listSandboxPreviewTokens)({
|
|
52
132
|
path: {
|
|
@@ -80,6 +160,9 @@ class SandboxPreview {
|
|
|
80
160
|
get name() {
|
|
81
161
|
return this.preview.metadata.name;
|
|
82
162
|
}
|
|
163
|
+
get url() {
|
|
164
|
+
return this.preview.spec?.url ?? "";
|
|
165
|
+
}
|
|
83
166
|
get metadata() {
|
|
84
167
|
return this.preview.metadata;
|
|
85
168
|
}
|
|
@@ -106,6 +189,7 @@ class SandboxPreviews {
|
|
|
106
189
|
return data.map((preview) => new SandboxPreview(preview));
|
|
107
190
|
}
|
|
108
191
|
async create(preview, force) {
|
|
192
|
+
const normalized = normalizePreview(preview);
|
|
109
193
|
const query = {};
|
|
110
194
|
if (force) {
|
|
111
195
|
query['force'] = 'true';
|
|
@@ -115,12 +199,31 @@ class SandboxPreviews {
|
|
|
115
199
|
sandboxName: this.sandboxName,
|
|
116
200
|
},
|
|
117
201
|
query,
|
|
118
|
-
body:
|
|
202
|
+
body: normalized,
|
|
119
203
|
throwOnError: true,
|
|
120
204
|
});
|
|
121
205
|
return new SandboxPreview(data);
|
|
122
206
|
}
|
|
207
|
+
/** Existing previews are returned as-is; shorthand's private default applies only on creation. */
|
|
123
208
|
async createIfNotExists(preview, force) {
|
|
209
|
+
if (isShorthand(preview)) {
|
|
210
|
+
const normalized = normalizePreview(preview);
|
|
211
|
+
try {
|
|
212
|
+
return await this.get(normalized.metadata.name);
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
if (httpStatus(error) !== 404)
|
|
216
|
+
throw error;
|
|
217
|
+
}
|
|
218
|
+
try {
|
|
219
|
+
return await this.create(normalized, force);
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
if (httpStatus(error) !== 409)
|
|
223
|
+
throw error;
|
|
224
|
+
return this.get(normalized.metadata.name);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
124
227
|
try {
|
|
125
228
|
const previewInstance = await this.get(preview.metadata.name);
|
|
126
229
|
return previewInstance;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { ResponseError } from "../sandbox/action.js";
|
|
2
|
+
import { SandboxCreationTimeoutError } from "../sandbox/sandbox.js";
|
|
3
|
+
/**
|
|
4
|
+
* Codes the edge gateway returns for sandbox, agent, function and MCP URLs,
|
|
5
|
+
* in `error.code` and the `X-Blaxel-Error-Code` header.
|
|
6
|
+
*/
|
|
7
|
+
export type BlaxelGatewayErrorCode =
|
|
8
|
+
/** 404: the URL does not map to a known workload. */
|
|
9
|
+
"ROUTE_NOT_FOUND"
|
|
10
|
+
/** 404 (401 for unauthenticated callers): the workload does not exist. */
|
|
11
|
+
| "WORKLOAD_NOT_FOUND"
|
|
12
|
+
/** 404: the workspace in the URL does not exist. */
|
|
13
|
+
| "WORKSPACE_NOT_FOUND"
|
|
14
|
+
/** 404, retryable: the workload exists but is not serving. */
|
|
15
|
+
| "WORKLOAD_UNAVAILABLE"
|
|
16
|
+
/** The workload failed and will not serve. */
|
|
17
|
+
| "WORKLOAD_FAILED"
|
|
18
|
+
/** Retryable: routing is briefly unavailable. */
|
|
19
|
+
| "ROUTING_UNAVAILABLE"
|
|
20
|
+
/** 401: no credentials were sent. */
|
|
21
|
+
| "AUTHENTICATION_REQUIRED"
|
|
22
|
+
/** 401: the credentials were rejected. */
|
|
23
|
+
| "AUTHENTICATION_FAILED"
|
|
24
|
+
/** 401: the token was revoked; get a new one. */
|
|
25
|
+
| "TOKEN_REVOKED"
|
|
26
|
+
/** 403: authenticated but not allowed on this resource. */
|
|
27
|
+
| "FORBIDDEN"
|
|
28
|
+
/** 400: malformed request. */
|
|
29
|
+
| "BAD_REQUEST"
|
|
30
|
+
/** 402: the workspace exceeded its plan's usage limits. */
|
|
31
|
+
| "USAGE_LIMIT_EXCEEDED"
|
|
32
|
+
/** Reserved: defined by the gateway but not currently returned. */
|
|
33
|
+
| "POLICY_VIOLATION"
|
|
34
|
+
/** Retryable: could not connect to the workload. */
|
|
35
|
+
| "UPSTREAM_CONNECT_FAILED"
|
|
36
|
+
/** Retryable: connecting to the workload timed out. */
|
|
37
|
+
| "UPSTREAM_CONNECT_TIMEOUT"
|
|
38
|
+
/** Retryable: the request to the workload failed. */
|
|
39
|
+
| "UPSTREAM_ERROR"
|
|
40
|
+
/** Retryable: the workload did not answer in time. */
|
|
41
|
+
| "UPSTREAM_TIMEOUT"
|
|
42
|
+
/** Retryable: the gateway itself failed. */
|
|
43
|
+
| "GATEWAY_INTERNAL_ERROR";
|
|
44
|
+
/**
|
|
45
|
+
* Authentication/authorization codes from sandbox creation and fork.
|
|
46
|
+
* `TOKEN_REVOKED` is also returned by every control-plane endpoint.
|
|
47
|
+
*/
|
|
48
|
+
export type BlaxelAuthErrorCode =
|
|
49
|
+
/** 401: the token was revoked; get a new one. */
|
|
50
|
+
"TOKEN_REVOKED"
|
|
51
|
+
/** 403: the credentials were rejected. */
|
|
52
|
+
| "UNAUTHORIZED"
|
|
53
|
+
/** 403: no (write) access to the requested workspace. */
|
|
54
|
+
| "UNAUTHORIZED_WORKSPACE"
|
|
55
|
+
/** 503, retryable: credentials could not be verified right now. */
|
|
56
|
+
| "AUTHENTICATION_UNAVAILABLE"
|
|
57
|
+
/** 400: the credentials reach several workspaces (or none); set one. */
|
|
58
|
+
| "WORKSPACE_REQUIRED";
|
|
59
|
+
/** Codes the control plane returns when creating or forking a sandbox. */
|
|
60
|
+
export type BlaxelSandboxCreationErrorCode = "READ_FAILED" | "PARSE_FAILED" | "VALIDATION_FAILED" | "VALIDATION_ERROR" | "INVALID_INPUT" | "INVALID_IMAGE" | "IMAGE_NOT_FOUND" | "UPLOAD_NOT_SUPPORTED" | "UNSUPPORTED_GENERATION" | "KERNEL_GENERATION_MISMATCH" | "INVALID_PORTS" | "INVALID_REGION" | "REGION_MISMATCH" | "INVALID_VOLUME" | "INVALID_VOLUME_COUNT" | "INVALID_VOLUME_REGION" | "VOLUME_ALREADY_ATTACHED" | "VOLUME_PROVIDER_MISMATCH" | "VOLUME_NOT_FOUND" | "WORKSPACE_NOT_FOUND" | "ACCOUNT_NOT_FOUND" | "SANDBOX_ALREADY_EXISTS" | "SANDBOX_DELETION_IN_PROGRESS" | "SANDBOX_DELETED" | "VOLUME_DELETED" | "CREATION_TIMEOUT" | "QUOTA_EXCEEDED" | "RATE_LIMIT_EXCEEDED" | "WORKSPACE_RATE_LIMIT_EXCEEDED" | "SERVICE_UNAVAILABLE" | "DATABASE_ERROR" | "LOCK_ACQUISITION_FAILED" | "VOLUME_LOOKUP_FAILED" | "BUILD_TRIGGER_ERROR" | "PRESIGNED_URL_ERROR" | "UPLOAD_UNAVAILABLE" | "DEPLOYMENT_FAILED" | "CLUSTER_GATEWAY_ERROR" | "LOCKDOWN_ERROR" | "PROXY_CONFIG_ERROR" | "VALIDATED_DATA_ERROR" | "WORKSPACE_DATA_MISSING" | "CALLBACK_SEND_FAILED" | "FORK_FAILED" | "HANDLER_ERROR" | "INTERNAL_ERROR" | "UNKNOWN_ERROR";
|
|
61
|
+
/** Known backend codes, including the reserved POLICY_VIOLATION code. */
|
|
62
|
+
export type BlaxelErrorCode = BlaxelGatewayErrorCode | BlaxelAuthErrorCode | BlaxelSandboxCreationErrorCode;
|
|
63
|
+
/** Known/new string codes, or the numeric HTTP code of a generic control-plane body. */
|
|
64
|
+
export type BlaxelErrorCodeValue = BlaxelErrorCode | (string & Record<never, never>) | number;
|
|
65
|
+
/** Generic control-plane error body, returned by most `/v0` endpoints. */
|
|
66
|
+
export type BlaxelApiErrorBody = {
|
|
67
|
+
/** Human-readable message. */
|
|
68
|
+
error: string;
|
|
69
|
+
/** HTTP status code (a number, not a string code). */
|
|
70
|
+
code: number;
|
|
71
|
+
};
|
|
72
|
+
/** Control-plane error body of sandbox creation and fork. */
|
|
73
|
+
export type BlaxelActionErrorBody = {
|
|
74
|
+
code: BlaxelSandboxCreationErrorCode | BlaxelAuthErrorCode | (string & Record<never, never>);
|
|
75
|
+
message: string;
|
|
76
|
+
/** HTTP status code. */
|
|
77
|
+
status_code: number;
|
|
78
|
+
/** Extra discriminant, e.g. "CREATION_IN_PROGRESS" on SANDBOX_ALREADY_EXISTS. */
|
|
79
|
+
reason?: string;
|
|
80
|
+
/** Creation step that failed. */
|
|
81
|
+
step?: string;
|
|
82
|
+
workspace?: string;
|
|
83
|
+
sandbox_name?: string;
|
|
84
|
+
timestamp?: string;
|
|
85
|
+
cause?: string;
|
|
86
|
+
details?: Record<string, unknown>;
|
|
87
|
+
};
|
|
88
|
+
/** Edge gateway error body; also used by the control plane for TOKEN_REVOKED. */
|
|
89
|
+
export type BlaxelPlatformErrorBody = {
|
|
90
|
+
error: {
|
|
91
|
+
code: BlaxelGatewayErrorCode | (string & Record<never, never>);
|
|
92
|
+
message: string;
|
|
93
|
+
/** HTTP status code. */
|
|
94
|
+
status: number;
|
|
95
|
+
/** When present, "platform": the gateway answered, not the workload. */
|
|
96
|
+
origin?: "platform";
|
|
97
|
+
/** Whether retrying the same request can succeed. */
|
|
98
|
+
retryable?: boolean;
|
|
99
|
+
/** Whether the workload may have seen the request before it failed. */
|
|
100
|
+
dispatch_state?: "not_dispatched" | "dispatched_unknown";
|
|
101
|
+
/** True only when retryable and the workload never saw the request. */
|
|
102
|
+
safe_to_retry_request?: boolean;
|
|
103
|
+
action?: string;
|
|
104
|
+
do_not?: string;
|
|
105
|
+
docs_url?: string;
|
|
106
|
+
timestamp?: string;
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Error body of the sandbox API (`sandbox.fs`, `sandbox.process`, ...). It has no
|
|
111
|
+
* code or status of its own: callers receive it inside `ResponseError`
|
|
112
|
+
* (`err.data` or `err.error`), which carries the HTTP status.
|
|
113
|
+
*/
|
|
114
|
+
export type BlaxelSandboxApiErrorBody = {
|
|
115
|
+
error: string;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Values {@link isBlaxelError} recognizes: the error classes the SDK throws for
|
|
119
|
+
* API failures (`ResponseError`, which includes `SandboxGatewayError`, and
|
|
120
|
+
* `SandboxCreationTimeoutError`) and the raw error bodies the control-plane
|
|
121
|
+
* client throws, each with its required code and status fields. This is a union
|
|
122
|
+
* of existing values, not a new error class or normalized shape.
|
|
123
|
+
*/
|
|
124
|
+
export type BlaxelErrorLike = ResponseError | SandboxCreationTimeoutError | BlaxelApiErrorBody | Pick<BlaxelActionErrorBody, "code" | "message" | "status_code"> | {
|
|
125
|
+
error: Pick<BlaxelPlatformErrorBody["error"], "code" | "message" | "status">;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* True only for a value that carries a Blaxel error code or HTTP status in a
|
|
129
|
+
* shape the SDK throws for API failures: a `ResponseError` (including
|
|
130
|
+
* `SandboxGatewayError`), a `SandboxCreationTimeoutError`, or a raw control-plane
|
|
131
|
+
* error body (`{ error, code }`, `{ code, message, status_code }` or
|
|
132
|
+
* `{ error: { code, message, status } }`). Plain `Error`s (including network
|
|
133
|
+
* errors with a `code` such as `ECONNRESET`), strings, raw HTML/text bodies, empty
|
|
134
|
+
* bodies and a bare `{ error: string }` are false: they carry neither. Matching
|
|
135
|
+
* `ResponseError` uses `instanceof`, so an error thrown by a second copy of
|
|
136
|
+
* `@blaxel/core` does not match. Does not wrap or mutate the value. Never throws.
|
|
137
|
+
* Like `is_blaxel_error` in the Python SDK, it is false for plain exceptions and
|
|
138
|
+
* strings.
|
|
139
|
+
*/
|
|
140
|
+
export declare function isBlaxelError(err: unknown): err is BlaxelErrorLike;
|
|
141
|
+
/** Read a code from the existing error/body, then X-Blaxel-Error-Code. Never throws. */
|
|
142
|
+
export declare function getBlaxelErrorCode(err: unknown): BlaxelErrorCodeValue | undefined;
|
|
143
|
+
/**
|
|
144
|
+
* Read HTTP status from the existing error/response, then the body (`status`,
|
|
145
|
+
* `status_code`, or a numeric `code`). Raw text and plain Error have none.
|
|
146
|
+
* Never throws.
|
|
147
|
+
*/
|
|
148
|
+
export declare function getBlaxelErrorStatus(err: unknown): number | undefined;
|
|
149
|
+
/**
|
|
150
|
+
* Read the existing Error.message, body message/error text, or raw text/HTML.
|
|
151
|
+
* Returns undefined for an empty/unrecognized body. Never throws.
|
|
152
|
+
*/
|
|
153
|
+
export declare function getBlaxelErrorMessage(err: unknown): string | undefined;
|
|
154
|
+
/**
|
|
155
|
+
* Read X-Cf-Request-Id, X-Amz-Cf-Id, then CF-Ray from a retained response.
|
|
156
|
+
* Raw control-plane bodies and SandboxCreationTimeoutError do not retain
|
|
157
|
+
* response headers, so their request ID is unavailable. Never throws.
|
|
158
|
+
*/
|
|
159
|
+
export declare function getBlaxelErrorRequestId(err: unknown): string | undefined;
|
|
@@ -7,6 +7,7 @@ export * from "./common/env.js";
|
|
|
7
7
|
export * from "./common/h2-runtime.js";
|
|
8
8
|
export * from "./common/node.js";
|
|
9
9
|
export * from "./common/errors.js";
|
|
10
|
+
export * from "./common/error-types.js";
|
|
10
11
|
export * from "./common/internal.js";
|
|
11
12
|
export * from "./common/logger.js";
|
|
12
13
|
export * from "./common/pagination.js";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { deleteFilesystemByPath, deleteNetworkProcessByPidMonitor, deleteProcessByIdentifier, deleteProcessByIdentifierKill, Directory, ErrorResponse, File, FileRequest, FileWithContent, getFilesystemByPath, getNetworkProcessByPidPorts, putCodegenFastapplyByPath, ApplyEditResponse, ApplyEditRequest, getCodegenRerankingByPath, RerankingResponse, getProcess, getProcessByIdentifier, getProcessByIdentifierLogs, getProcessByIdentifierLogsStream, PortMonitorRequest, postNetworkProcessByPidMonitor, postProcess, ProcessRequest, ProcessResponse, putFilesystemByPath, SuccessResponse } from "./client/index.js";
|
|
2
2
|
export { ResponseError, SandboxGatewayError, isGatewayError, isGatewayTimeout } from "./action.js";
|
|
3
|
+
export * from "../common/error-types.js";
|
|
3
4
|
export * from "./filesystem/index.js";
|
|
4
5
|
export * from "./codegen/index.js";
|
|
5
6
|
export { SandboxDrive, type DriveMountRequest, type DriveMountResponse, type DriveMountInfo, type DriveUnmountResponse } from "./drive/index.js";
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { Preview, PreviewToken, Sandbox } from "../client/index.js";
|
|
1
|
+
import type { Preview, PreviewToken, Sandbox } from "../client/index.js";
|
|
2
|
+
import type { SandboxPreviewCreateConfiguration } from "./types.js";
|
|
2
3
|
export declare class SandboxPreviewToken {
|
|
3
4
|
private previewToken;
|
|
4
5
|
constructor(previewToken: PreviewToken);
|
|
6
|
+
get name(): string;
|
|
5
7
|
get value(): string;
|
|
6
8
|
get expiresAt(): string | Date;
|
|
7
9
|
get expired(): boolean;
|
|
@@ -12,6 +14,11 @@ export declare class SandboxPreviewTokens {
|
|
|
12
14
|
get previewName(): string;
|
|
13
15
|
get resourceName(): string;
|
|
14
16
|
create(expiresAt: Date): Promise<SandboxPreviewToken>;
|
|
17
|
+
/**
|
|
18
|
+
* Reuse the latest token within the requested expiry ceiling, or mint one.
|
|
19
|
+
* minValidity is in milliseconds. Concurrent callers may create separate tokens.
|
|
20
|
+
*/
|
|
21
|
+
createIfExpired(expiresAt?: Date, minValidity?: number): Promise<SandboxPreviewToken>;
|
|
15
22
|
list(): Promise<SandboxPreviewToken[]>;
|
|
16
23
|
delete(tokenName: string): Promise<{
|
|
17
24
|
message?: string;
|
|
@@ -22,6 +29,7 @@ export declare class SandboxPreview {
|
|
|
22
29
|
tokens: SandboxPreviewTokens;
|
|
23
30
|
constructor(preview: Preview);
|
|
24
31
|
get name(): string;
|
|
32
|
+
get url(): string;
|
|
25
33
|
get metadata(): import("../client/types.gen.js").PreviewMetadata;
|
|
26
34
|
get spec(): import("../client/types.gen.js").PreviewSpec;
|
|
27
35
|
}
|
|
@@ -30,8 +38,9 @@ export declare class SandboxPreviews {
|
|
|
30
38
|
constructor(sandbox: Sandbox);
|
|
31
39
|
get sandboxName(): string;
|
|
32
40
|
list(): Promise<SandboxPreview[]>;
|
|
33
|
-
create(preview: Preview, force?: boolean): Promise<SandboxPreview>;
|
|
34
|
-
|
|
41
|
+
create(preview: Preview | SandboxPreviewCreateConfiguration, force?: boolean): Promise<SandboxPreview>;
|
|
42
|
+
/** Existing previews are returned as-is; shorthand's private default applies only on creation. */
|
|
43
|
+
createIfNotExists(preview: Preview | SandboxPreviewCreateConfiguration, force?: boolean): Promise<SandboxPreview>;
|
|
35
44
|
get(previewName: string): Promise<SandboxPreview>;
|
|
36
45
|
delete(previewName: string): Promise<Preview>;
|
|
37
46
|
private waitForDeletion;
|
|
@@ -38,6 +38,13 @@ export type SandboxUpdateMetadata = {
|
|
|
38
38
|
export type SandboxUpdateNetwork = {
|
|
39
39
|
network?: SandboxNetwork;
|
|
40
40
|
};
|
|
41
|
+
export type SandboxPreviewCreateConfiguration = {
|
|
42
|
+
port: number;
|
|
43
|
+
/** Defaults to preview-<port> within this sandbox. */
|
|
44
|
+
name?: string;
|
|
45
|
+
/** Defaults to false on creation; existing previews are not changed. */
|
|
46
|
+
public?: boolean;
|
|
47
|
+
};
|
|
41
48
|
export type SandboxCreateConfiguration = {
|
|
42
49
|
name?: string;
|
|
43
50
|
image?: string;
|