@alibaba-group/opensandbox 0.1.1 → 0.1.2-dev1
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/chunk-5AELQBW6.js +938 -0
- package/dist/chunk-5AELQBW6.js.map +1 -0
- package/dist/cjs/index.cjs +1637 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/internal.cjs +932 -0
- package/dist/cjs/internal.cjs.map +1 -0
- package/dist/index.d.ts +367 -22
- package/dist/index.js +678 -20
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +2513 -19
- package/dist/internal.js +18 -30
- package/dist/internal.js.map +1 -1
- package/dist/sandboxes-HBCO9ttf.d.ts +352 -0
- package/package.json +7 -2
- package/src/api/lifecycle.ts +32 -0
- package/src/openapi/createClient.ts +41 -0
- package/src/openapi/execdClient.ts +1 -1
- package/src/openapi/lifecycleClient.ts +1 -1
- package/dist/adapters/commandsAdapter.d.ts +0 -22
- package/dist/adapters/commandsAdapter.d.ts.map +0 -1
- package/dist/adapters/commandsAdapter.js +0 -77
- package/dist/adapters/commandsAdapter.js.map +0 -1
- package/dist/adapters/filesystemAdapter.d.ts +0 -52
- package/dist/adapters/filesystemAdapter.d.ts.map +0 -1
- package/dist/adapters/filesystemAdapter.js +0 -443
- package/dist/adapters/filesystemAdapter.js.map +0 -1
- package/dist/adapters/healthAdapter.d.ts +0 -8
- package/dist/adapters/healthAdapter.d.ts.map +0 -1
- package/dist/adapters/healthAdapter.js +0 -26
- package/dist/adapters/healthAdapter.js.map +0 -1
- package/dist/adapters/metricsAdapter.d.ts +0 -9
- package/dist/adapters/metricsAdapter.d.ts.map +0 -1
- package/dist/adapters/metricsAdapter.js +0 -44
- package/dist/adapters/metricsAdapter.js.map +0 -1
- package/dist/adapters/openapiError.d.ts +0 -5
- package/dist/adapters/openapiError.d.ts.map +0 -1
- package/dist/adapters/openapiError.js +0 -34
- package/dist/adapters/openapiError.js.map +0 -1
- package/dist/adapters/sandboxesAdapter.d.ts +0 -18
- package/dist/adapters/sandboxesAdapter.d.ts.map +0 -1
- package/dist/adapters/sandboxesAdapter.js +0 -147
- package/dist/adapters/sandboxesAdapter.js.map +0 -1
- package/dist/adapters/sse.d.ts +0 -9
- package/dist/adapters/sse.d.ts.map +0 -1
- package/dist/adapters/sse.js +0 -87
- package/dist/adapters/sse.js.map +0 -1
- package/dist/api/execd.d.ts +0 -1555
- package/dist/api/execd.d.ts.map +0 -1
- package/dist/api/execd.js +0 -15
- package/dist/api/execd.js.map +0 -1
- package/dist/api/lifecycle.d.ts +0 -787
- package/dist/api/lifecycle.d.ts.map +0 -1
- package/dist/api/lifecycle.js +0 -15
- package/dist/api/lifecycle.js.map +0 -1
- package/dist/config/connection.d.ts +0 -69
- package/dist/config/connection.d.ts.map +0 -1
- package/dist/config/connection.js +0 -282
- package/dist/config/connection.js.map +0 -1
- package/dist/core/constants.d.ts +0 -9
- package/dist/core/constants.d.ts.map +0 -1
- package/dist/core/constants.js +0 -25
- package/dist/core/constants.js.map +0 -1
- package/dist/core/exceptions.d.ts +0 -74
- package/dist/core/exceptions.d.ts.map +0 -1
- package/dist/core/exceptions.js +0 -104
- package/dist/core/exceptions.js.map +0 -1
- package/dist/factory/adapterFactory.d.ts +0 -33
- package/dist/factory/adapterFactory.d.ts.map +0 -1
- package/dist/factory/adapterFactory.js +0 -15
- package/dist/factory/adapterFactory.js.map +0 -1
- package/dist/factory/defaultAdapterFactory.d.ts +0 -7
- package/dist/factory/defaultAdapterFactory.d.ts.map +0 -1
- package/dist/factory/defaultAdapterFactory.js +0 -61
- package/dist/factory/defaultAdapterFactory.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/internal.d.ts.map +0 -1
- package/dist/manager.d.ts +0 -42
- package/dist/manager.d.ts.map +0 -1
- package/dist/manager.js +0 -86
- package/dist/manager.js.map +0 -1
- package/dist/models/execd.d.ts +0 -54
- package/dist/models/execd.d.ts.map +0 -1
- package/dist/models/execd.js +0 -15
- package/dist/models/execd.js.map +0 -1
- package/dist/models/execution.d.ts +0 -52
- package/dist/models/execution.d.ts.map +0 -1
- package/dist/models/execution.js +0 -15
- package/dist/models/execution.js.map +0 -1
- package/dist/models/executionEventDispatcher.d.ts +0 -15
- package/dist/models/executionEventDispatcher.d.ts.map +0 -1
- package/dist/models/executionEventDispatcher.js +0 -96
- package/dist/models/executionEventDispatcher.js.map +0 -1
- package/dist/models/filesystem.d.ts +0 -77
- package/dist/models/filesystem.d.ts.map +0 -1
- package/dist/models/filesystem.js +0 -15
- package/dist/models/filesystem.js.map +0 -1
- package/dist/models/sandboxes.d.ts +0 -105
- package/dist/models/sandboxes.d.ts.map +0 -1
- package/dist/models/sandboxes.js +0 -16
- package/dist/models/sandboxes.js.map +0 -1
- package/dist/openapi/execdClient.d.ts +0 -25
- package/dist/openapi/execdClient.d.ts.map +0 -1
- package/dist/openapi/execdClient.js +0 -22
- package/dist/openapi/execdClient.js.map +0 -1
- package/dist/openapi/lifecycleClient.d.ts +0 -28
- package/dist/openapi/lifecycleClient.d.ts.map +0 -1
- package/dist/openapi/lifecycleClient.js +0 -36
- package/dist/openapi/lifecycleClient.js.map +0 -1
- package/dist/sandbox.d.ts +0 -136
- package/dist/sandbox.d.ts.map +0 -1
- package/dist/sandbox.js +0 -303
- package/dist/sandbox.js.map +0 -1
- package/dist/services/execdCommands.d.ts +0 -19
- package/dist/services/execdCommands.d.ts.map +0 -1
- package/dist/services/execdCommands.js +0 -15
- package/dist/services/execdCommands.js.map +0 -1
- package/dist/services/execdHealth.d.ts +0 -4
- package/dist/services/execdHealth.d.ts.map +0 -1
- package/dist/services/execdHealth.js +0 -15
- package/dist/services/execdHealth.js.map +0 -1
- package/dist/services/execdMetrics.d.ts +0 -5
- package/dist/services/execdMetrics.d.ts.map +0 -1
- package/dist/services/execdMetrics.js +0 -15
- package/dist/services/execdMetrics.js.map +0 -1
- package/dist/services/filesystem.d.ts +0 -30
- package/dist/services/filesystem.d.ts.map +0 -1
- package/dist/services/filesystem.js +0 -15
- package/dist/services/filesystem.js.map +0 -1
- package/dist/services/sandboxes.d.ts +0 -12
- package/dist/services/sandboxes.d.ts.map +0 -1
- package/dist/services/sandboxes.js +0 -15
- package/dist/services/sandboxes.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,21 +1,679 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
import {
|
|
2
|
+
CommandsAdapter,
|
|
3
|
+
ExecutionEventDispatcher,
|
|
4
|
+
FilesystemAdapter,
|
|
5
|
+
HealthAdapter,
|
|
6
|
+
InvalidArgumentException,
|
|
7
|
+
MetricsAdapter,
|
|
8
|
+
SandboxApiException,
|
|
9
|
+
SandboxError,
|
|
10
|
+
SandboxException,
|
|
11
|
+
SandboxInternalException,
|
|
12
|
+
SandboxReadyTimeoutException,
|
|
13
|
+
SandboxUnhealthyException,
|
|
14
|
+
SandboxesAdapter,
|
|
15
|
+
createExecdClient,
|
|
16
|
+
createLifecycleClient
|
|
17
|
+
} from "./chunk-5AELQBW6.js";
|
|
18
|
+
|
|
19
|
+
// src/factory/defaultAdapterFactory.ts
|
|
20
|
+
var DefaultAdapterFactory = class {
|
|
21
|
+
createLifecycleStack(opts) {
|
|
22
|
+
const lifecycleClient = createLifecycleClient({
|
|
23
|
+
baseUrl: opts.lifecycleBaseUrl,
|
|
24
|
+
apiKey: opts.connectionConfig.apiKey,
|
|
25
|
+
headers: opts.connectionConfig.headers,
|
|
26
|
+
fetch: opts.connectionConfig.fetch
|
|
27
|
+
});
|
|
28
|
+
const sandboxes = new SandboxesAdapter(lifecycleClient);
|
|
29
|
+
return { sandboxes };
|
|
30
|
+
}
|
|
31
|
+
createExecdStack(opts) {
|
|
32
|
+
const execdClient = createExecdClient({
|
|
33
|
+
baseUrl: opts.execdBaseUrl,
|
|
34
|
+
headers: opts.connectionConfig.headers,
|
|
35
|
+
fetch: opts.connectionConfig.fetch
|
|
36
|
+
});
|
|
37
|
+
const health = new HealthAdapter(execdClient);
|
|
38
|
+
const metrics = new MetricsAdapter(execdClient);
|
|
39
|
+
const files = new FilesystemAdapter(execdClient, {
|
|
40
|
+
baseUrl: opts.execdBaseUrl,
|
|
41
|
+
fetch: opts.connectionConfig.fetch,
|
|
42
|
+
headers: opts.connectionConfig.headers
|
|
43
|
+
});
|
|
44
|
+
const commands = new CommandsAdapter(execdClient, {
|
|
45
|
+
baseUrl: opts.execdBaseUrl,
|
|
46
|
+
fetch: opts.connectionConfig.sseFetch,
|
|
47
|
+
headers: opts.connectionConfig.headers
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
commands,
|
|
51
|
+
files,
|
|
52
|
+
health,
|
|
53
|
+
metrics
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
function createDefaultAdapterFactory() {
|
|
58
|
+
return new DefaultAdapterFactory();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/core/constants.ts
|
|
62
|
+
var DEFAULT_EXECD_PORT = 44772;
|
|
63
|
+
var DEFAULT_ENTRYPOINT = ["tail", "-f", "/dev/null"];
|
|
64
|
+
var DEFAULT_RESOURCE_LIMITS = {
|
|
65
|
+
cpu: "1",
|
|
66
|
+
memory: "2Gi"
|
|
67
|
+
};
|
|
68
|
+
var DEFAULT_TIMEOUT_SECONDS = 600;
|
|
69
|
+
var DEFAULT_READY_TIMEOUT_SECONDS = 30;
|
|
70
|
+
var DEFAULT_HEALTH_CHECK_POLLING_INTERVAL_MILLIS = 200;
|
|
71
|
+
var DEFAULT_REQUEST_TIMEOUT_SECONDS = 30;
|
|
72
|
+
var DEFAULT_USER_AGENT = "OpenSandbox-JS-SDK/0.1.1";
|
|
73
|
+
|
|
74
|
+
// src/config/connection.ts
|
|
75
|
+
function isNodeRuntime() {
|
|
76
|
+
const p = globalThis?.process;
|
|
77
|
+
return !!p?.versions?.node;
|
|
78
|
+
}
|
|
79
|
+
function redactHeaders(headers) {
|
|
80
|
+
const out = { ...headers };
|
|
81
|
+
for (const k of Object.keys(out)) {
|
|
82
|
+
if (k.toLowerCase() === "open-sandbox-api-key") out[k] = "***";
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
function readEnv(name) {
|
|
87
|
+
const env = globalThis?.process?.env;
|
|
88
|
+
const v = env?.[name];
|
|
89
|
+
return typeof v === "string" && v.length ? v : void 0;
|
|
90
|
+
}
|
|
91
|
+
function stripTrailingSlashes(s) {
|
|
92
|
+
return s.replace(/\/+$/, "");
|
|
93
|
+
}
|
|
94
|
+
function stripV1Suffix(s) {
|
|
95
|
+
const trimmed = stripTrailingSlashes(s);
|
|
96
|
+
return trimmed.endsWith("/v1") ? trimmed.slice(0, -3) : trimmed;
|
|
97
|
+
}
|
|
98
|
+
var DEFAULT_KEEPALIVE_TIMEOUT_MS = 3e4;
|
|
99
|
+
function normalizeDomainBase(input) {
|
|
100
|
+
if (input.startsWith("http://") || input.startsWith("https://")) {
|
|
101
|
+
const u = new URL(input);
|
|
102
|
+
const proto = u.protocol === "https:" ? "https" : "http";
|
|
103
|
+
const base = `${u.origin}${u.pathname}`;
|
|
104
|
+
return { protocol: proto, domainBase: stripV1Suffix(base) };
|
|
105
|
+
}
|
|
106
|
+
return { domainBase: stripV1Suffix(input) };
|
|
107
|
+
}
|
|
108
|
+
function createNodeFetch() {
|
|
109
|
+
if (!isNodeRuntime()) {
|
|
110
|
+
return {
|
|
111
|
+
fetch,
|
|
112
|
+
close: async () => {
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const baseFetch = fetch;
|
|
117
|
+
let dispatcher;
|
|
118
|
+
let dispatcherPromise = null;
|
|
119
|
+
const nodeFetch = async (input, init) => {
|
|
120
|
+
dispatcherPromise ??= (async () => {
|
|
121
|
+
try {
|
|
122
|
+
const mod = await import("undici");
|
|
123
|
+
const Agent = mod.Agent;
|
|
124
|
+
if (!Agent) {
|
|
125
|
+
return void 0;
|
|
126
|
+
}
|
|
127
|
+
dispatcher = new Agent({
|
|
128
|
+
keepAliveTimeout: DEFAULT_KEEPALIVE_TIMEOUT_MS,
|
|
129
|
+
keepAliveMaxTimeout: DEFAULT_KEEPALIVE_TIMEOUT_MS
|
|
130
|
+
});
|
|
131
|
+
return dispatcher;
|
|
132
|
+
} catch {
|
|
133
|
+
return void 0;
|
|
134
|
+
}
|
|
135
|
+
})();
|
|
136
|
+
if (dispatcherPromise) {
|
|
137
|
+
await dispatcherPromise;
|
|
138
|
+
}
|
|
139
|
+
if (dispatcher) {
|
|
140
|
+
const mergedInit = { ...init ?? {}, dispatcher };
|
|
141
|
+
return baseFetch(input, mergedInit);
|
|
142
|
+
}
|
|
143
|
+
return baseFetch(input, init);
|
|
144
|
+
};
|
|
145
|
+
return {
|
|
146
|
+
fetch: nodeFetch,
|
|
147
|
+
close: async () => {
|
|
148
|
+
if (dispatcherPromise) {
|
|
149
|
+
await dispatcherPromise.catch(() => void 0);
|
|
150
|
+
}
|
|
151
|
+
if (dispatcher && typeof dispatcher === "object" && typeof dispatcher.close === "function") {
|
|
152
|
+
try {
|
|
153
|
+
await dispatcher.close();
|
|
154
|
+
} catch {
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function createTimedFetch(opts) {
|
|
161
|
+
const baseFetch = opts.baseFetch;
|
|
162
|
+
const timeoutSeconds = opts.timeoutSeconds;
|
|
163
|
+
const debug = opts.debug;
|
|
164
|
+
const defaultHeaders = opts.defaultHeaders ?? {};
|
|
165
|
+
const label = opts.label;
|
|
166
|
+
return async (input, init) => {
|
|
167
|
+
const method = init?.method ?? "GET";
|
|
168
|
+
const url = typeof input === "string" ? input : input?.toString?.() ?? String(input);
|
|
169
|
+
const ac = new AbortController();
|
|
170
|
+
const timeoutMs = Math.floor(timeoutSeconds * 1e3);
|
|
171
|
+
const t = Number.isFinite(timeoutMs) && timeoutMs > 0 ? setTimeout(
|
|
172
|
+
() => ac.abort(
|
|
173
|
+
new Error(
|
|
174
|
+
`[${label}] Request timed out (timeoutSeconds=${timeoutSeconds})`
|
|
175
|
+
)
|
|
176
|
+
),
|
|
177
|
+
timeoutMs
|
|
178
|
+
) : void 0;
|
|
179
|
+
const onAbort = () => ac.abort(init?.signal?.reason ?? new Error("Aborted"));
|
|
180
|
+
if (init?.signal) {
|
|
181
|
+
if (init.signal.aborted) onAbort();
|
|
182
|
+
else
|
|
183
|
+
init.signal.addEventListener("abort", onAbort, { once: true });
|
|
184
|
+
}
|
|
185
|
+
const mergedInit = {
|
|
186
|
+
...init,
|
|
187
|
+
signal: ac.signal
|
|
188
|
+
};
|
|
189
|
+
if (debug) {
|
|
190
|
+
const mergedHeaders = {
|
|
191
|
+
...defaultHeaders,
|
|
192
|
+
...init?.headers ?? {}
|
|
193
|
+
};
|
|
194
|
+
console.log(
|
|
195
|
+
`[opensandbox:${label}] ->`,
|
|
196
|
+
method,
|
|
197
|
+
url,
|
|
198
|
+
redactHeaders(mergedHeaders)
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
const res = await baseFetch(input, mergedInit);
|
|
203
|
+
if (debug) {
|
|
204
|
+
console.log(`[opensandbox:${label}] <-`, method, url, res.status);
|
|
205
|
+
}
|
|
206
|
+
return res;
|
|
207
|
+
} finally {
|
|
208
|
+
if (t) clearTimeout(t);
|
|
209
|
+
if (init?.signal)
|
|
210
|
+
init.signal.removeEventListener("abort", onAbort);
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
var ConnectionConfig = class _ConnectionConfig {
|
|
215
|
+
protocol;
|
|
216
|
+
domain;
|
|
217
|
+
apiKey;
|
|
218
|
+
headers;
|
|
219
|
+
_fetch;
|
|
220
|
+
_sseFetch;
|
|
221
|
+
requestTimeoutSeconds;
|
|
222
|
+
debug;
|
|
223
|
+
userAgent = DEFAULT_USER_AGENT;
|
|
224
|
+
_closeTransport;
|
|
225
|
+
_closePromise = null;
|
|
226
|
+
_transportInitialized = false;
|
|
227
|
+
/**
|
|
228
|
+
* Create a connection configuration.
|
|
229
|
+
*
|
|
230
|
+
* Environment variables (optional):
|
|
231
|
+
* - `OPEN_SANDBOX_DOMAIN` (default: `localhost:8080`)
|
|
232
|
+
* - `OPEN_SANDBOX_API_KEY`
|
|
233
|
+
*/
|
|
234
|
+
constructor(opts = {}) {
|
|
235
|
+
const envDomain = readEnv("OPEN_SANDBOX_DOMAIN");
|
|
236
|
+
const envApiKey = readEnv("OPEN_SANDBOX_API_KEY");
|
|
237
|
+
const rawDomain = opts.domain ?? envDomain ?? "localhost:8080";
|
|
238
|
+
const normalized = normalizeDomainBase(rawDomain);
|
|
239
|
+
this.protocol = normalized.protocol ?? opts.protocol ?? "http";
|
|
240
|
+
this.domain = normalized.domainBase;
|
|
241
|
+
this.apiKey = opts.apiKey ?? envApiKey;
|
|
242
|
+
this.requestTimeoutSeconds = typeof opts.requestTimeoutSeconds === "number" ? opts.requestTimeoutSeconds : 30;
|
|
243
|
+
this.debug = !!opts.debug;
|
|
244
|
+
const headers = { ...opts.headers ?? {} };
|
|
245
|
+
if (this.apiKey && !headers["OPEN-SANDBOX-API-KEY"]) {
|
|
246
|
+
headers["OPEN-SANDBOX-API-KEY"] = this.apiKey;
|
|
247
|
+
}
|
|
248
|
+
if (isNodeRuntime() && this.userAgent && !headers["user-agent"] && !headers["User-Agent"]) {
|
|
249
|
+
headers["user-agent"] = this.userAgent;
|
|
250
|
+
}
|
|
251
|
+
this.headers = headers;
|
|
252
|
+
this._fetch = null;
|
|
253
|
+
this._sseFetch = null;
|
|
254
|
+
this._closeTransport = async () => {
|
|
255
|
+
};
|
|
256
|
+
this._transportInitialized = false;
|
|
257
|
+
}
|
|
258
|
+
get fetch() {
|
|
259
|
+
return this._fetch ?? fetch;
|
|
260
|
+
}
|
|
261
|
+
get sseFetch() {
|
|
262
|
+
return this._sseFetch ?? fetch;
|
|
263
|
+
}
|
|
264
|
+
getBaseUrl() {
|
|
265
|
+
if (this.domain.startsWith("http://") || this.domain.startsWith("https://")) {
|
|
266
|
+
return `${stripV1Suffix(this.domain)}/v1`;
|
|
267
|
+
}
|
|
268
|
+
return `${this.protocol}://${stripV1Suffix(this.domain)}/v1`;
|
|
269
|
+
}
|
|
270
|
+
initializeTransport() {
|
|
271
|
+
if (this._transportInitialized) return;
|
|
272
|
+
const { fetch: baseFetch, close } = createNodeFetch();
|
|
273
|
+
this._fetch = createTimedFetch({
|
|
274
|
+
baseFetch,
|
|
275
|
+
timeoutSeconds: this.requestTimeoutSeconds,
|
|
276
|
+
debug: this.debug,
|
|
277
|
+
defaultHeaders: this.headers,
|
|
278
|
+
label: "http"
|
|
279
|
+
});
|
|
280
|
+
this._sseFetch = createTimedFetch({
|
|
281
|
+
baseFetch,
|
|
282
|
+
timeoutSeconds: 0,
|
|
283
|
+
debug: this.debug,
|
|
284
|
+
defaultHeaders: this.headers,
|
|
285
|
+
label: "sse"
|
|
286
|
+
});
|
|
287
|
+
this._closeTransport = close;
|
|
288
|
+
this._transportInitialized = true;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Ensure this configuration has transport helpers (fetch/SSE) allocated.
|
|
292
|
+
*
|
|
293
|
+
* On Node.js this creates a dedicated `undici` dispatcher; on browsers it
|
|
294
|
+
* simply reuses the global fetch. Returns either `this` or a cloned config
|
|
295
|
+
* with the transport initialized.
|
|
296
|
+
*/
|
|
297
|
+
withTransportIfMissing() {
|
|
298
|
+
if (this._transportInitialized) {
|
|
299
|
+
return this;
|
|
300
|
+
}
|
|
301
|
+
const clone = new _ConnectionConfig({
|
|
302
|
+
domain: this.domain,
|
|
303
|
+
protocol: this.protocol,
|
|
304
|
+
apiKey: this.apiKey,
|
|
305
|
+
headers: { ...this.headers },
|
|
306
|
+
requestTimeoutSeconds: this.requestTimeoutSeconds,
|
|
307
|
+
debug: this.debug
|
|
308
|
+
});
|
|
309
|
+
clone.initializeTransport();
|
|
310
|
+
return clone;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Close the Node.js agent owned by this configuration.
|
|
314
|
+
*/
|
|
315
|
+
async closeTransport() {
|
|
316
|
+
if (!this._transportInitialized) return;
|
|
317
|
+
this._closePromise ??= this._closeTransport();
|
|
318
|
+
await this._closePromise;
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
// src/manager.ts
|
|
323
|
+
var SandboxManager = class _SandboxManager {
|
|
324
|
+
sandboxes;
|
|
325
|
+
connectionConfig;
|
|
326
|
+
constructor(opts) {
|
|
327
|
+
this.sandboxes = opts.sandboxes;
|
|
328
|
+
this.connectionConfig = opts.connectionConfig;
|
|
329
|
+
}
|
|
330
|
+
static create(opts = {}) {
|
|
331
|
+
const baseConnectionConfig = opts.connectionConfig instanceof ConnectionConfig ? opts.connectionConfig : new ConnectionConfig(opts.connectionConfig);
|
|
332
|
+
const connectionConfig = baseConnectionConfig.withTransportIfMissing();
|
|
333
|
+
const lifecycleBaseUrl = connectionConfig.getBaseUrl();
|
|
334
|
+
const adapterFactory = opts.adapterFactory ?? createDefaultAdapterFactory();
|
|
335
|
+
let sandboxes;
|
|
336
|
+
try {
|
|
337
|
+
sandboxes = adapterFactory.createLifecycleStack({
|
|
338
|
+
connectionConfig,
|
|
339
|
+
lifecycleBaseUrl
|
|
340
|
+
}).sandboxes;
|
|
341
|
+
} catch (err) {
|
|
342
|
+
void connectionConfig.closeTransport().catch(() => void 0);
|
|
343
|
+
throw err;
|
|
344
|
+
}
|
|
345
|
+
return new _SandboxManager({ sandboxes, connectionConfig });
|
|
346
|
+
}
|
|
347
|
+
listSandboxInfos(filter = {}) {
|
|
348
|
+
return this.sandboxes.listSandboxes({
|
|
349
|
+
states: filter.states,
|
|
350
|
+
metadata: filter.metadata,
|
|
351
|
+
page: filter.page,
|
|
352
|
+
pageSize: filter.pageSize
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
getSandboxInfo(sandboxId) {
|
|
356
|
+
return this.sandboxes.getSandbox(sandboxId);
|
|
357
|
+
}
|
|
358
|
+
killSandbox(sandboxId) {
|
|
359
|
+
return this.sandboxes.deleteSandbox(sandboxId);
|
|
360
|
+
}
|
|
361
|
+
pauseSandbox(sandboxId) {
|
|
362
|
+
return this.sandboxes.pauseSandbox(sandboxId);
|
|
363
|
+
}
|
|
364
|
+
resumeSandbox(sandboxId) {
|
|
365
|
+
return this.sandboxes.resumeSandbox(sandboxId);
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Renew expiration by setting expiresAt to now + timeoutSeconds.
|
|
369
|
+
*/
|
|
370
|
+
async renewSandbox(sandboxId, timeoutSeconds) {
|
|
371
|
+
const expiresAt = new Date(Date.now() + timeoutSeconds * 1e3).toISOString();
|
|
372
|
+
await this.sandboxes.renewSandboxExpiration(sandboxId, { expiresAt });
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Release the HTTP agent resources allocated for this manager instance.
|
|
376
|
+
*
|
|
377
|
+
* Each manager clone owns a scoped `ConnectionConfig` clone.
|
|
378
|
+
*
|
|
379
|
+
* This mirrors the Python SDK's default transport lifecycle.
|
|
380
|
+
*/
|
|
381
|
+
async close() {
|
|
382
|
+
await this.connectionConfig.closeTransport();
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
// src/sandbox.ts
|
|
387
|
+
function sleep(ms) {
|
|
388
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
389
|
+
}
|
|
390
|
+
function toImageSpec(image) {
|
|
391
|
+
if (typeof image === "string") return { uri: image };
|
|
392
|
+
return { uri: image.uri, auth: image.auth };
|
|
393
|
+
}
|
|
394
|
+
var Sandbox = class _Sandbox {
|
|
395
|
+
id;
|
|
396
|
+
connectionConfig;
|
|
397
|
+
/**
|
|
398
|
+
* Lifecycle (sandbox management) service.
|
|
399
|
+
*/
|
|
400
|
+
sandboxes;
|
|
401
|
+
/**
|
|
402
|
+
* Execd services.
|
|
403
|
+
*/
|
|
404
|
+
commands;
|
|
405
|
+
/**
|
|
406
|
+
* High-level filesystem facade (JS-friendly).
|
|
407
|
+
*/
|
|
408
|
+
files;
|
|
409
|
+
health;
|
|
410
|
+
metrics;
|
|
411
|
+
/**
|
|
412
|
+
* Internal state kept out of the public instance shape.
|
|
413
|
+
*
|
|
414
|
+
* This avoids nominal typing issues when multiple copies of the SDK exist in a dependency graph.
|
|
415
|
+
*/
|
|
416
|
+
static _priv = /* @__PURE__ */ new WeakMap();
|
|
417
|
+
constructor(opts) {
|
|
418
|
+
this.id = opts.id;
|
|
419
|
+
this.connectionConfig = opts.connectionConfig;
|
|
420
|
+
_Sandbox._priv.set(this, {
|
|
421
|
+
adapterFactory: opts.adapterFactory,
|
|
422
|
+
lifecycleBaseUrl: opts.lifecycleBaseUrl,
|
|
423
|
+
execdBaseUrl: opts.execdBaseUrl
|
|
424
|
+
});
|
|
425
|
+
this.sandboxes = opts.sandboxes;
|
|
426
|
+
this.commands = opts.commands;
|
|
427
|
+
this.files = opts.files;
|
|
428
|
+
this.health = opts.health;
|
|
429
|
+
this.metrics = opts.metrics;
|
|
430
|
+
}
|
|
431
|
+
static async create(opts) {
|
|
432
|
+
const baseConnectionConfig = opts.connectionConfig instanceof ConnectionConfig ? opts.connectionConfig : new ConnectionConfig(opts.connectionConfig);
|
|
433
|
+
const connectionConfig = baseConnectionConfig.withTransportIfMissing();
|
|
434
|
+
const lifecycleBaseUrl = connectionConfig.getBaseUrl();
|
|
435
|
+
const adapterFactory = opts.adapterFactory ?? createDefaultAdapterFactory();
|
|
436
|
+
let sandboxes;
|
|
437
|
+
try {
|
|
438
|
+
sandboxes = adapterFactory.createLifecycleStack({
|
|
439
|
+
connectionConfig,
|
|
440
|
+
lifecycleBaseUrl
|
|
441
|
+
}).sandboxes;
|
|
442
|
+
} catch (err) {
|
|
443
|
+
await connectionConfig.closeTransport();
|
|
444
|
+
throw err;
|
|
445
|
+
}
|
|
446
|
+
const req = {
|
|
447
|
+
image: toImageSpec(opts.image),
|
|
448
|
+
entrypoint: opts.entrypoint ?? DEFAULT_ENTRYPOINT,
|
|
449
|
+
timeout: Math.floor(opts.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS),
|
|
450
|
+
resourceLimits: opts.resource ?? DEFAULT_RESOURCE_LIMITS,
|
|
451
|
+
env: opts.env ?? {},
|
|
452
|
+
metadata: opts.metadata ?? {},
|
|
453
|
+
extensions: opts.extensions ?? {}
|
|
454
|
+
};
|
|
455
|
+
let sandboxId;
|
|
456
|
+
try {
|
|
457
|
+
const created = await sandboxes.createSandbox(req);
|
|
458
|
+
sandboxId = created.id;
|
|
459
|
+
const endpoint = await sandboxes.getSandboxEndpoint(
|
|
460
|
+
sandboxId,
|
|
461
|
+
DEFAULT_EXECD_PORT
|
|
462
|
+
);
|
|
463
|
+
const execdBaseUrl = `${connectionConfig.protocol}://${endpoint.endpoint}`;
|
|
464
|
+
const { commands, files, health, metrics } = adapterFactory.createExecdStack({
|
|
465
|
+
connectionConfig,
|
|
466
|
+
execdBaseUrl
|
|
467
|
+
});
|
|
468
|
+
const sbx = new _Sandbox({
|
|
469
|
+
id: sandboxId,
|
|
470
|
+
connectionConfig,
|
|
471
|
+
adapterFactory,
|
|
472
|
+
lifecycleBaseUrl,
|
|
473
|
+
execdBaseUrl,
|
|
474
|
+
sandboxes,
|
|
475
|
+
commands,
|
|
476
|
+
files,
|
|
477
|
+
health,
|
|
478
|
+
metrics
|
|
479
|
+
});
|
|
480
|
+
if (!(opts.skipHealthCheck ?? false)) {
|
|
481
|
+
await sbx.waitUntilReady({
|
|
482
|
+
readyTimeoutSeconds: opts.readyTimeoutSeconds ?? DEFAULT_READY_TIMEOUT_SECONDS,
|
|
483
|
+
pollingIntervalMillis: opts.healthCheckPollingInterval ?? DEFAULT_HEALTH_CHECK_POLLING_INTERVAL_MILLIS,
|
|
484
|
+
healthCheck: opts.healthCheck
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
return sbx;
|
|
488
|
+
} catch (err) {
|
|
489
|
+
if (sandboxId) {
|
|
490
|
+
try {
|
|
491
|
+
await sandboxes.deleteSandbox(sandboxId);
|
|
492
|
+
} catch {
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
await connectionConfig.closeTransport();
|
|
496
|
+
throw err;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
static async connect(opts) {
|
|
500
|
+
const baseConnectionConfig = opts.connectionConfig instanceof ConnectionConfig ? opts.connectionConfig : new ConnectionConfig(opts.connectionConfig);
|
|
501
|
+
const connectionConfig = baseConnectionConfig.withTransportIfMissing();
|
|
502
|
+
const adapterFactory = opts.adapterFactory ?? createDefaultAdapterFactory();
|
|
503
|
+
const lifecycleBaseUrl = connectionConfig.getBaseUrl();
|
|
504
|
+
let sandboxes;
|
|
505
|
+
try {
|
|
506
|
+
sandboxes = adapterFactory.createLifecycleStack({
|
|
507
|
+
connectionConfig,
|
|
508
|
+
lifecycleBaseUrl
|
|
509
|
+
}).sandboxes;
|
|
510
|
+
} catch (err) {
|
|
511
|
+
await connectionConfig.closeTransport();
|
|
512
|
+
throw err;
|
|
513
|
+
}
|
|
514
|
+
try {
|
|
515
|
+
const endpoint = await sandboxes.getSandboxEndpoint(
|
|
516
|
+
opts.sandboxId,
|
|
517
|
+
DEFAULT_EXECD_PORT
|
|
518
|
+
);
|
|
519
|
+
const execdBaseUrl = `${connectionConfig.protocol}://${endpoint.endpoint}`;
|
|
520
|
+
const { commands, files, health, metrics } = adapterFactory.createExecdStack({
|
|
521
|
+
connectionConfig,
|
|
522
|
+
execdBaseUrl
|
|
523
|
+
});
|
|
524
|
+
const sbx = new _Sandbox({
|
|
525
|
+
id: opts.sandboxId,
|
|
526
|
+
connectionConfig,
|
|
527
|
+
adapterFactory,
|
|
528
|
+
lifecycleBaseUrl,
|
|
529
|
+
execdBaseUrl,
|
|
530
|
+
sandboxes,
|
|
531
|
+
commands,
|
|
532
|
+
files,
|
|
533
|
+
health,
|
|
534
|
+
metrics
|
|
535
|
+
});
|
|
536
|
+
if (!(opts.skipHealthCheck ?? false)) {
|
|
537
|
+
await sbx.waitUntilReady({
|
|
538
|
+
readyTimeoutSeconds: opts.readyTimeoutSeconds ?? DEFAULT_READY_TIMEOUT_SECONDS,
|
|
539
|
+
pollingIntervalMillis: opts.healthCheckPollingInterval ?? DEFAULT_HEALTH_CHECK_POLLING_INTERVAL_MILLIS,
|
|
540
|
+
healthCheck: opts.healthCheck
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
return sbx;
|
|
544
|
+
} catch (err) {
|
|
545
|
+
await connectionConfig.closeTransport();
|
|
546
|
+
throw err;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
async getInfo() {
|
|
550
|
+
return await this.sandboxes.getSandbox(this.id);
|
|
551
|
+
}
|
|
552
|
+
async isHealthy() {
|
|
553
|
+
try {
|
|
554
|
+
return await this.health.ping();
|
|
555
|
+
} catch {
|
|
556
|
+
return false;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
async getMetrics() {
|
|
560
|
+
return await this.metrics.getMetrics();
|
|
561
|
+
}
|
|
562
|
+
async pause() {
|
|
563
|
+
await this.sandboxes.pauseSandbox(this.id);
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Resume a paused sandbox and return a fresh, connected Sandbox instance.
|
|
567
|
+
*
|
|
568
|
+
* After resume, the execd endpoint may change, so this method returns a new
|
|
569
|
+
* {@link Sandbox} instance with a refreshed execd base URL.
|
|
570
|
+
*/
|
|
571
|
+
async resume(opts = {}) {
|
|
572
|
+
await this.sandboxes.resumeSandbox(this.id);
|
|
573
|
+
return await _Sandbox.connect({
|
|
574
|
+
sandboxId: this.id,
|
|
575
|
+
connectionConfig: this.connectionConfig,
|
|
576
|
+
adapterFactory: _Sandbox._priv.get(this).adapterFactory,
|
|
577
|
+
skipHealthCheck: opts.skipHealthCheck ?? false,
|
|
578
|
+
readyTimeoutSeconds: opts.readyTimeoutSeconds,
|
|
579
|
+
healthCheckPollingInterval: opts.healthCheckPollingInterval
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Resume a paused sandbox by id, then connect to its execd endpoint.
|
|
584
|
+
*/
|
|
585
|
+
static async resume(opts) {
|
|
586
|
+
const baseConnectionConfig = opts.connectionConfig instanceof ConnectionConfig ? opts.connectionConfig : new ConnectionConfig(opts.connectionConfig);
|
|
587
|
+
const adapterFactory = opts.adapterFactory ?? createDefaultAdapterFactory();
|
|
588
|
+
const resumeConnectionConfig = baseConnectionConfig.withTransportIfMissing();
|
|
589
|
+
const lifecycleBaseUrl = resumeConnectionConfig.getBaseUrl();
|
|
590
|
+
let sandboxes;
|
|
591
|
+
try {
|
|
592
|
+
sandboxes = adapterFactory.createLifecycleStack({
|
|
593
|
+
connectionConfig: resumeConnectionConfig,
|
|
594
|
+
lifecycleBaseUrl
|
|
595
|
+
}).sandboxes;
|
|
596
|
+
await sandboxes.resumeSandbox(opts.sandboxId);
|
|
597
|
+
} catch (err) {
|
|
598
|
+
await resumeConnectionConfig.closeTransport();
|
|
599
|
+
throw err;
|
|
600
|
+
}
|
|
601
|
+
await resumeConnectionConfig.closeTransport();
|
|
602
|
+
return await _Sandbox.connect({ ...opts, connectionConfig: baseConnectionConfig, adapterFactory });
|
|
603
|
+
}
|
|
604
|
+
async kill() {
|
|
605
|
+
await this.sandboxes.deleteSandbox(this.id);
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Release any client-side resources (e.g. Node.js HTTP agents) owned by this Sandbox instance.
|
|
609
|
+
*/
|
|
610
|
+
async close() {
|
|
611
|
+
await this.connectionConfig.closeTransport();
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Renew expiration by setting expiresAt to now + timeoutSeconds.
|
|
615
|
+
*/
|
|
616
|
+
async renew(timeoutSeconds) {
|
|
617
|
+
const expiresAt = new Date(
|
|
618
|
+
Date.now() + timeoutSeconds * 1e3
|
|
619
|
+
).toISOString();
|
|
620
|
+
return await this.sandboxes.renewSandboxExpiration(this.id, { expiresAt });
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Get sandbox endpoint for a port (STRICT: no scheme), e.g. "localhost:44772" or "domain/route/.../44772".
|
|
624
|
+
*/
|
|
625
|
+
async getEndpoint(port) {
|
|
626
|
+
return await this.sandboxes.getSandboxEndpoint(this.id, port);
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Get absolute endpoint URL with scheme (convenience for HTTP clients).
|
|
630
|
+
*/
|
|
631
|
+
async getEndpointUrl(port) {
|
|
632
|
+
const ep = await this.getEndpoint(port);
|
|
633
|
+
return `${this.connectionConfig.protocol}://${ep.endpoint}`;
|
|
634
|
+
}
|
|
635
|
+
async waitUntilReady(opts) {
|
|
636
|
+
const deadline = Date.now() + opts.readyTimeoutSeconds * 1e3;
|
|
637
|
+
while (true) {
|
|
638
|
+
if (Date.now() > deadline) {
|
|
639
|
+
throw new SandboxReadyTimeoutException({
|
|
640
|
+
message: `Sandbox not ready: timed out waiting for health check (timeoutSeconds=${opts.readyTimeoutSeconds})`
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
try {
|
|
644
|
+
if (opts.healthCheck) {
|
|
645
|
+
const ok = await opts.healthCheck(this);
|
|
646
|
+
if (ok) return;
|
|
647
|
+
} else {
|
|
648
|
+
const ok = await this.health.ping();
|
|
649
|
+
if (ok) return;
|
|
650
|
+
}
|
|
651
|
+
} catch {
|
|
652
|
+
}
|
|
653
|
+
await sleep(opts.pollingIntervalMillis);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
export {
|
|
658
|
+
ConnectionConfig,
|
|
659
|
+
DEFAULT_ENTRYPOINT,
|
|
660
|
+
DEFAULT_EXECD_PORT,
|
|
661
|
+
DEFAULT_HEALTH_CHECK_POLLING_INTERVAL_MILLIS,
|
|
662
|
+
DEFAULT_READY_TIMEOUT_SECONDS,
|
|
663
|
+
DEFAULT_REQUEST_TIMEOUT_SECONDS,
|
|
664
|
+
DEFAULT_RESOURCE_LIMITS,
|
|
665
|
+
DEFAULT_TIMEOUT_SECONDS,
|
|
666
|
+
DefaultAdapterFactory,
|
|
667
|
+
ExecutionEventDispatcher,
|
|
668
|
+
InvalidArgumentException,
|
|
669
|
+
Sandbox,
|
|
670
|
+
SandboxApiException,
|
|
671
|
+
SandboxError,
|
|
672
|
+
SandboxException,
|
|
673
|
+
SandboxInternalException,
|
|
674
|
+
SandboxManager,
|
|
675
|
+
SandboxReadyTimeoutException,
|
|
676
|
+
SandboxUnhealthyException,
|
|
677
|
+
createDefaultAdapterFactory
|
|
678
|
+
};
|
|
21
679
|
//# sourceMappingURL=index.js.map
|