@alibaba-group/opensandbox 0.1.1-dev0 → 0.1.2-dev0

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.
Files changed (131) hide show
  1. package/dist/chunk-NFNOESEY.js +926 -0
  2. package/dist/chunk-NFNOESEY.js.map +1 -0
  3. package/dist/cjs/index.cjs +1625 -0
  4. package/dist/cjs/index.cjs.map +1 -0
  5. package/dist/cjs/internal.cjs +920 -0
  6. package/dist/cjs/internal.cjs.map +1 -0
  7. package/dist/index.d.ts +367 -22
  8. package/dist/index.js +678 -20
  9. package/dist/index.js.map +1 -1
  10. package/dist/internal.d.ts +2513 -19
  11. package/dist/internal.js +18 -30
  12. package/dist/internal.js.map +1 -1
  13. package/dist/sandboxes-HBCO9ttf.d.ts +352 -0
  14. package/package.json +7 -2
  15. package/src/api/lifecycle.ts +32 -0
  16. package/src/config/connection.ts +3 -1
  17. package/src/core/constants.ts +1 -1
  18. package/dist/adapters/commandsAdapter.d.ts +0 -22
  19. package/dist/adapters/commandsAdapter.d.ts.map +0 -1
  20. package/dist/adapters/commandsAdapter.js +0 -77
  21. package/dist/adapters/commandsAdapter.js.map +0 -1
  22. package/dist/adapters/filesystemAdapter.d.ts +0 -52
  23. package/dist/adapters/filesystemAdapter.d.ts.map +0 -1
  24. package/dist/adapters/filesystemAdapter.js +0 -443
  25. package/dist/adapters/filesystemAdapter.js.map +0 -1
  26. package/dist/adapters/healthAdapter.d.ts +0 -8
  27. package/dist/adapters/healthAdapter.d.ts.map +0 -1
  28. package/dist/adapters/healthAdapter.js +0 -26
  29. package/dist/adapters/healthAdapter.js.map +0 -1
  30. package/dist/adapters/metricsAdapter.d.ts +0 -9
  31. package/dist/adapters/metricsAdapter.d.ts.map +0 -1
  32. package/dist/adapters/metricsAdapter.js +0 -44
  33. package/dist/adapters/metricsAdapter.js.map +0 -1
  34. package/dist/adapters/openapiError.d.ts +0 -5
  35. package/dist/adapters/openapiError.d.ts.map +0 -1
  36. package/dist/adapters/openapiError.js +0 -34
  37. package/dist/adapters/openapiError.js.map +0 -1
  38. package/dist/adapters/sandboxesAdapter.d.ts +0 -18
  39. package/dist/adapters/sandboxesAdapter.d.ts.map +0 -1
  40. package/dist/adapters/sandboxesAdapter.js +0 -147
  41. package/dist/adapters/sandboxesAdapter.js.map +0 -1
  42. package/dist/adapters/sse.d.ts +0 -9
  43. package/dist/adapters/sse.d.ts.map +0 -1
  44. package/dist/adapters/sse.js +0 -87
  45. package/dist/adapters/sse.js.map +0 -1
  46. package/dist/api/execd.d.ts +0 -1555
  47. package/dist/api/execd.d.ts.map +0 -1
  48. package/dist/api/execd.js +0 -15
  49. package/dist/api/execd.js.map +0 -1
  50. package/dist/api/lifecycle.d.ts +0 -787
  51. package/dist/api/lifecycle.d.ts.map +0 -1
  52. package/dist/api/lifecycle.js +0 -15
  53. package/dist/api/lifecycle.js.map +0 -1
  54. package/dist/config/connection.d.ts +0 -69
  55. package/dist/config/connection.d.ts.map +0 -1
  56. package/dist/config/connection.js +0 -281
  57. package/dist/config/connection.js.map +0 -1
  58. package/dist/core/constants.d.ts +0 -9
  59. package/dist/core/constants.d.ts.map +0 -1
  60. package/dist/core/constants.js +0 -25
  61. package/dist/core/constants.js.map +0 -1
  62. package/dist/core/exceptions.d.ts +0 -74
  63. package/dist/core/exceptions.d.ts.map +0 -1
  64. package/dist/core/exceptions.js +0 -104
  65. package/dist/core/exceptions.js.map +0 -1
  66. package/dist/factory/adapterFactory.d.ts +0 -33
  67. package/dist/factory/adapterFactory.d.ts.map +0 -1
  68. package/dist/factory/adapterFactory.js +0 -15
  69. package/dist/factory/adapterFactory.js.map +0 -1
  70. package/dist/factory/defaultAdapterFactory.d.ts +0 -7
  71. package/dist/factory/defaultAdapterFactory.d.ts.map +0 -1
  72. package/dist/factory/defaultAdapterFactory.js +0 -61
  73. package/dist/factory/defaultAdapterFactory.js.map +0 -1
  74. package/dist/index.d.ts.map +0 -1
  75. package/dist/internal.d.ts.map +0 -1
  76. package/dist/manager.d.ts +0 -42
  77. package/dist/manager.d.ts.map +0 -1
  78. package/dist/manager.js +0 -86
  79. package/dist/manager.js.map +0 -1
  80. package/dist/models/execd.d.ts +0 -54
  81. package/dist/models/execd.d.ts.map +0 -1
  82. package/dist/models/execd.js +0 -15
  83. package/dist/models/execd.js.map +0 -1
  84. package/dist/models/execution.d.ts +0 -52
  85. package/dist/models/execution.d.ts.map +0 -1
  86. package/dist/models/execution.js +0 -15
  87. package/dist/models/execution.js.map +0 -1
  88. package/dist/models/executionEventDispatcher.d.ts +0 -15
  89. package/dist/models/executionEventDispatcher.d.ts.map +0 -1
  90. package/dist/models/executionEventDispatcher.js +0 -96
  91. package/dist/models/executionEventDispatcher.js.map +0 -1
  92. package/dist/models/filesystem.d.ts +0 -77
  93. package/dist/models/filesystem.d.ts.map +0 -1
  94. package/dist/models/filesystem.js +0 -15
  95. package/dist/models/filesystem.js.map +0 -1
  96. package/dist/models/sandboxes.d.ts +0 -105
  97. package/dist/models/sandboxes.d.ts.map +0 -1
  98. package/dist/models/sandboxes.js +0 -16
  99. package/dist/models/sandboxes.js.map +0 -1
  100. package/dist/openapi/execdClient.d.ts +0 -25
  101. package/dist/openapi/execdClient.d.ts.map +0 -1
  102. package/dist/openapi/execdClient.js +0 -22
  103. package/dist/openapi/execdClient.js.map +0 -1
  104. package/dist/openapi/lifecycleClient.d.ts +0 -28
  105. package/dist/openapi/lifecycleClient.d.ts.map +0 -1
  106. package/dist/openapi/lifecycleClient.js +0 -36
  107. package/dist/openapi/lifecycleClient.js.map +0 -1
  108. package/dist/sandbox.d.ts +0 -136
  109. package/dist/sandbox.d.ts.map +0 -1
  110. package/dist/sandbox.js +0 -303
  111. package/dist/sandbox.js.map +0 -1
  112. package/dist/services/execdCommands.d.ts +0 -19
  113. package/dist/services/execdCommands.d.ts.map +0 -1
  114. package/dist/services/execdCommands.js +0 -15
  115. package/dist/services/execdCommands.js.map +0 -1
  116. package/dist/services/execdHealth.d.ts +0 -4
  117. package/dist/services/execdHealth.d.ts.map +0 -1
  118. package/dist/services/execdHealth.js +0 -15
  119. package/dist/services/execdHealth.js.map +0 -1
  120. package/dist/services/execdMetrics.d.ts +0 -5
  121. package/dist/services/execdMetrics.d.ts.map +0 -1
  122. package/dist/services/execdMetrics.js +0 -15
  123. package/dist/services/execdMetrics.js.map +0 -1
  124. package/dist/services/filesystem.d.ts +0 -30
  125. package/dist/services/filesystem.d.ts.map +0 -1
  126. package/dist/services/filesystem.js +0 -15
  127. package/dist/services/filesystem.js.map +0 -1
  128. package/dist/services/sandboxes.d.ts +0 -12
  129. package/dist/services/sandboxes.d.ts.map +0 -1
  130. package/dist/services/sandboxes.js +0 -15
  131. package/dist/services/sandboxes.js.map +0 -1
@@ -0,0 +1,926 @@
1
+ // src/core/exceptions.ts
2
+ var SandboxError = class {
3
+ constructor(code, message) {
4
+ this.code = code;
5
+ this.message = message;
6
+ }
7
+ static INTERNAL_UNKNOWN_ERROR = "INTERNAL_UNKNOWN_ERROR";
8
+ static READY_TIMEOUT = "READY_TIMEOUT";
9
+ static UNHEALTHY = "UNHEALTHY";
10
+ static INVALID_ARGUMENT = "INVALID_ARGUMENT";
11
+ static UNEXPECTED_RESPONSE = "UNEXPECTED_RESPONSE";
12
+ };
13
+ var SandboxException = class extends Error {
14
+ name = "SandboxException";
15
+ error;
16
+ cause;
17
+ constructor(opts = {}) {
18
+ super(opts.message);
19
+ this.cause = opts.cause;
20
+ this.error = opts.error ?? new SandboxError(SandboxError.INTERNAL_UNKNOWN_ERROR);
21
+ }
22
+ };
23
+ var SandboxApiException = class extends SandboxException {
24
+ name = "SandboxApiException";
25
+ statusCode;
26
+ requestId;
27
+ rawBody;
28
+ constructor(opts) {
29
+ super({
30
+ message: opts.message,
31
+ cause: opts.cause,
32
+ error: opts.error ?? new SandboxError(SandboxError.UNEXPECTED_RESPONSE, opts.message)
33
+ });
34
+ this.statusCode = opts.statusCode;
35
+ this.requestId = opts.requestId;
36
+ this.rawBody = opts.rawBody;
37
+ }
38
+ };
39
+ var SandboxInternalException = class extends SandboxException {
40
+ name = "SandboxInternalException";
41
+ constructor(opts) {
42
+ super({
43
+ message: opts.message,
44
+ cause: opts.cause,
45
+ error: new SandboxError(SandboxError.INTERNAL_UNKNOWN_ERROR, opts.message)
46
+ });
47
+ }
48
+ };
49
+ var SandboxUnhealthyException = class extends SandboxException {
50
+ name = "SandboxUnhealthyException";
51
+ constructor(opts) {
52
+ super({
53
+ message: opts.message,
54
+ cause: opts.cause,
55
+ error: new SandboxError(SandboxError.UNHEALTHY, opts.message)
56
+ });
57
+ }
58
+ };
59
+ var SandboxReadyTimeoutException = class extends SandboxException {
60
+ name = "SandboxReadyTimeoutException";
61
+ constructor(opts) {
62
+ super({
63
+ message: opts.message,
64
+ cause: opts.cause,
65
+ error: new SandboxError(SandboxError.READY_TIMEOUT, opts.message)
66
+ });
67
+ }
68
+ };
69
+ var InvalidArgumentException = class extends SandboxException {
70
+ name = "InvalidArgumentException";
71
+ constructor(opts) {
72
+ super({
73
+ message: opts.message,
74
+ cause: opts.cause,
75
+ error: new SandboxError(SandboxError.INVALID_ARGUMENT, opts.message)
76
+ });
77
+ }
78
+ };
79
+
80
+ // src/openapi/execdClient.ts
81
+ import createClient from "openapi-fetch";
82
+ function createExecdClient(opts) {
83
+ return createClient({
84
+ baseUrl: opts.baseUrl,
85
+ headers: opts.headers,
86
+ fetch: opts.fetch
87
+ });
88
+ }
89
+
90
+ // src/openapi/lifecycleClient.ts
91
+ import createClient2 from "openapi-fetch";
92
+ function readEnvApiKey() {
93
+ const env = globalThis?.process?.env;
94
+ const v = env?.OPEN_SANDBOX_API_KEY;
95
+ return typeof v === "string" && v.length ? v : void 0;
96
+ }
97
+ function createLifecycleClient(opts = {}) {
98
+ const apiKey = opts.apiKey ?? readEnvApiKey();
99
+ const headers = {
100
+ ...opts.headers ?? {}
101
+ };
102
+ if (apiKey && !headers["OPEN-SANDBOX-API-KEY"]) {
103
+ headers["OPEN-SANDBOX-API-KEY"] = apiKey;
104
+ }
105
+ return createClient2({
106
+ baseUrl: opts.baseUrl ?? "http://localhost:8080/v1",
107
+ headers,
108
+ fetch: opts.fetch
109
+ });
110
+ }
111
+
112
+ // src/models/executionEventDispatcher.ts
113
+ function extractText(results) {
114
+ if (!results || typeof results !== "object") return void 0;
115
+ const r = results;
116
+ const v = r["text/plain"] ?? r.text ?? r.textPlain;
117
+ return v == null ? void 0 : String(v);
118
+ }
119
+ var ExecutionEventDispatcher = class {
120
+ constructor(execution, handlers) {
121
+ this.execution = execution;
122
+ this.handlers = handlers;
123
+ }
124
+ async dispatch(ev) {
125
+ await this.handlers?.onEvent?.(ev);
126
+ const ts = ev.timestamp ?? Date.now();
127
+ switch (ev.type) {
128
+ case "init": {
129
+ const id = ev.text ?? "";
130
+ if (id) this.execution.id = id;
131
+ const init = { id, timestamp: ts };
132
+ await this.handlers?.onInit?.(init);
133
+ return;
134
+ }
135
+ case "stdout": {
136
+ const msg = { text: ev.text ?? "", timestamp: ts, isError: false };
137
+ this.execution.logs.stdout.push(msg);
138
+ await this.handlers?.onStdout?.(msg);
139
+ return;
140
+ }
141
+ case "stderr": {
142
+ const msg = { text: ev.text ?? "", timestamp: ts, isError: true };
143
+ this.execution.logs.stderr.push(msg);
144
+ await this.handlers?.onStderr?.(msg);
145
+ return;
146
+ }
147
+ case "result": {
148
+ const r = { text: extractText(ev.results), timestamp: ts, raw: ev.results };
149
+ this.execution.result.push(r);
150
+ await this.handlers?.onResult?.(r);
151
+ return;
152
+ }
153
+ case "execution_count": {
154
+ const c = ev.execution_count;
155
+ if (typeof c === "number") this.execution.executionCount = c;
156
+ return;
157
+ }
158
+ case "execution_complete": {
159
+ const ms = ev.execution_time;
160
+ const complete = { timestamp: ts, executionTimeMs: typeof ms === "number" ? ms : 0 };
161
+ this.execution.complete = complete;
162
+ await this.handlers?.onExecutionComplete?.(complete);
163
+ return;
164
+ }
165
+ case "error": {
166
+ const e = ev.error;
167
+ if (e) {
168
+ const err = {
169
+ name: String(e.ename ?? e.name ?? ""),
170
+ value: String(e.evalue ?? e.value ?? ""),
171
+ timestamp: ts,
172
+ traceback: Array.isArray(e.traceback) ? e.traceback.map(String) : []
173
+ };
174
+ this.execution.error = err;
175
+ await this.handlers?.onError?.(err);
176
+ }
177
+ return;
178
+ }
179
+ default:
180
+ return;
181
+ }
182
+ }
183
+ };
184
+
185
+ // src/adapters/openapiError.ts
186
+ function throwOnOpenApiFetchError(result, fallbackMessage) {
187
+ if (!result.error) return;
188
+ const requestId = result.response.headers.get("x-request-id") ?? void 0;
189
+ const status = result.response.status ?? 0;
190
+ const err = result.error;
191
+ const message = err?.message ?? err?.error?.message ?? fallbackMessage;
192
+ const code = err?.code ?? err?.error?.code;
193
+ const msg = err?.message ?? err?.error?.message ?? message;
194
+ throw new SandboxApiException({
195
+ message: msg,
196
+ statusCode: status,
197
+ requestId,
198
+ error: code ? new SandboxError(String(code), String(msg ?? "")) : new SandboxError(SandboxError.UNEXPECTED_RESPONSE, String(msg ?? "")),
199
+ rawBody: result.error
200
+ });
201
+ }
202
+
203
+ // src/adapters/sse.ts
204
+ function tryParseJson(line) {
205
+ try {
206
+ return JSON.parse(line);
207
+ } catch {
208
+ return void 0;
209
+ }
210
+ }
211
+ async function* parseJsonEventStream(res, opts) {
212
+ if (!res.ok) {
213
+ const text = await res.text().catch(() => "");
214
+ const parsed = tryParseJson(text);
215
+ const err = parsed && typeof parsed === "object" ? parsed : void 0;
216
+ const requestId = res.headers.get("x-request-id") ?? void 0;
217
+ const message = err?.message ?? opts?.fallbackErrorMessage ?? `Stream request failed (status=${res.status})`;
218
+ const code = err?.code ? String(err.code) : SandboxError.UNEXPECTED_RESPONSE;
219
+ throw new SandboxApiException({
220
+ message,
221
+ statusCode: res.status,
222
+ requestId,
223
+ error: new SandboxError(code, err?.message ? String(err.message) : message),
224
+ rawBody: parsed ?? text
225
+ });
226
+ }
227
+ if (!res.body) {
228
+ return;
229
+ }
230
+ const reader = res.body.getReader();
231
+ const decoder = new TextDecoder("utf-8");
232
+ let buf = "";
233
+ while (true) {
234
+ const { value, done } = await reader.read();
235
+ if (done) break;
236
+ buf += decoder.decode(value, { stream: true });
237
+ let idx;
238
+ while ((idx = buf.indexOf("\n")) >= 0) {
239
+ const rawLine = buf.slice(0, idx);
240
+ buf = buf.slice(idx + 1);
241
+ const line = rawLine.trim();
242
+ if (!line) continue;
243
+ if (line.startsWith(":")) continue;
244
+ if (line.startsWith("event:") || line.startsWith("id:") || line.startsWith("retry:")) continue;
245
+ const jsonLine = line.startsWith("data:") ? line.slice("data:".length).trim() : line;
246
+ if (!jsonLine) continue;
247
+ const parsed = tryParseJson(jsonLine);
248
+ if (!parsed) continue;
249
+ yield parsed;
250
+ }
251
+ }
252
+ buf += decoder.decode();
253
+ const last = buf.trim();
254
+ if (last) {
255
+ const jsonLine = last.startsWith("data:") ? last.slice("data:".length).trim() : last;
256
+ const parsed = tryParseJson(jsonLine);
257
+ if (parsed) yield parsed;
258
+ }
259
+ }
260
+
261
+ // src/adapters/commandsAdapter.ts
262
+ function joinUrl(baseUrl, pathname) {
263
+ const base = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
264
+ const path = pathname.startsWith("/") ? pathname : `/${pathname}`;
265
+ return `${base}${path}`;
266
+ }
267
+ function toRunCommandRequest(command, opts) {
268
+ return {
269
+ command,
270
+ cwd: opts?.workingDirectory,
271
+ background: !!opts?.background
272
+ };
273
+ }
274
+ var CommandsAdapter = class {
275
+ constructor(client, opts) {
276
+ this.client = client;
277
+ this.opts = opts;
278
+ this.fetch = opts.fetch ?? fetch;
279
+ }
280
+ fetch;
281
+ async interrupt(sessionId) {
282
+ const { error, response } = await this.client.DELETE("/command", {
283
+ params: { query: { id: sessionId } }
284
+ });
285
+ throwOnOpenApiFetchError({ error, response }, "Interrupt command failed");
286
+ }
287
+ async *runStream(command, opts, signal) {
288
+ const url = joinUrl(this.opts.baseUrl, "/command");
289
+ const body = JSON.stringify(toRunCommandRequest(command, opts));
290
+ const res = await this.fetch(url, {
291
+ method: "POST",
292
+ headers: {
293
+ "accept": "text/event-stream",
294
+ "content-type": "application/json",
295
+ ...this.opts.headers ?? {}
296
+ },
297
+ body,
298
+ signal
299
+ });
300
+ for await (const ev of parseJsonEventStream(res, { fallbackErrorMessage: "Run command failed" })) {
301
+ yield ev;
302
+ }
303
+ }
304
+ async run(command, opts, handlers, signal) {
305
+ const execution = {
306
+ logs: { stdout: [], stderr: [] },
307
+ result: []
308
+ };
309
+ const dispatcher = new ExecutionEventDispatcher(execution, handlers);
310
+ for await (const ev of this.runStream(command, opts, signal)) {
311
+ if (ev.type === "init" && (ev.text ?? "") === "" && execution.id) {
312
+ ev.text = execution.id;
313
+ }
314
+ await dispatcher.dispatch(ev);
315
+ }
316
+ return execution;
317
+ }
318
+ };
319
+
320
+ // src/adapters/filesystemAdapter.ts
321
+ function joinUrl2(baseUrl, pathname) {
322
+ const base = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
323
+ const path = pathname.startsWith("/") ? pathname : `/${pathname}`;
324
+ return `${base}${path}`;
325
+ }
326
+ function toUploadBlob(data) {
327
+ if (typeof data === "string") return new Blob([data]);
328
+ if (data instanceof Blob) return data;
329
+ if (data instanceof ArrayBuffer) return new Blob([data]);
330
+ const copied = Uint8Array.from(data);
331
+ return new Blob([copied.buffer]);
332
+ }
333
+ function isReadableStream(v) {
334
+ return !!v && typeof v.getReader === "function";
335
+ }
336
+ function isAsyncIterable(v) {
337
+ return !!v && typeof v[Symbol.asyncIterator] === "function";
338
+ }
339
+ function isNodeRuntime() {
340
+ const p = globalThis?.process;
341
+ return !!p?.versions?.node;
342
+ }
343
+ async function collectBytes(source) {
344
+ const chunks = [];
345
+ let total = 0;
346
+ if (isReadableStream(source)) {
347
+ const reader = source.getReader();
348
+ try {
349
+ while (true) {
350
+ const { done, value } = await reader.read();
351
+ if (done) break;
352
+ if (value) {
353
+ chunks.push(value);
354
+ total += value.length;
355
+ }
356
+ }
357
+ } finally {
358
+ reader.releaseLock();
359
+ }
360
+ } else {
361
+ for await (const chunk of source) {
362
+ chunks.push(chunk);
363
+ total += chunk.length;
364
+ }
365
+ }
366
+ const out = new Uint8Array(total);
367
+ let offset = 0;
368
+ for (const chunk of chunks) {
369
+ out.set(chunk, offset);
370
+ offset += chunk.length;
371
+ }
372
+ return out;
373
+ }
374
+ function toReadableStream(it) {
375
+ const RS = ReadableStream;
376
+ if (typeof RS?.from === "function") return RS.from(it);
377
+ const iterator = it[Symbol.asyncIterator]();
378
+ return new ReadableStream({
379
+ async pull(controller) {
380
+ const r = await iterator.next();
381
+ if (r.done) {
382
+ controller.close();
383
+ return;
384
+ }
385
+ controller.enqueue(r.value);
386
+ },
387
+ async cancel() {
388
+ await iterator.return?.();
389
+ }
390
+ });
391
+ }
392
+ function basename(p) {
393
+ const parts = p.split("/").filter(Boolean);
394
+ return parts.length ? parts[parts.length - 1] : "file";
395
+ }
396
+ function encodeUtf8(s) {
397
+ return new TextEncoder().encode(s);
398
+ }
399
+ async function* multipartUploadBody(opts) {
400
+ const b = opts.boundary;
401
+ yield encodeUtf8(`--${b}\r
402
+ `);
403
+ yield encodeUtf8(
404
+ `Content-Disposition: form-data; name="metadata"; filename="metadata"\r
405
+ `
406
+ );
407
+ yield encodeUtf8(`Content-Type: application/json\r
408
+ \r
409
+ `);
410
+ yield encodeUtf8(opts.metadataJson);
411
+ yield encodeUtf8(`\r
412
+ `);
413
+ yield encodeUtf8(`--${b}\r
414
+ `);
415
+ yield encodeUtf8(
416
+ `Content-Disposition: form-data; name="file"; filename="${opts.fileName}"\r
417
+ `
418
+ );
419
+ yield encodeUtf8(`Content-Type: ${opts.fileContentType}\r
420
+ \r
421
+ `);
422
+ if (isReadableStream(opts.file)) {
423
+ const reader = opts.file.getReader();
424
+ try {
425
+ while (true) {
426
+ const { done, value } = await reader.read();
427
+ if (done) break;
428
+ if (value) yield value;
429
+ }
430
+ } finally {
431
+ reader.releaseLock();
432
+ }
433
+ } else {
434
+ for await (const chunk of opts.file) {
435
+ yield chunk;
436
+ }
437
+ }
438
+ yield encodeUtf8(`\r
439
+ --${b}--\r
440
+ `);
441
+ }
442
+ function toPermission(e) {
443
+ return {
444
+ mode: e.mode ?? 755,
445
+ owner: e.owner,
446
+ group: e.group
447
+ };
448
+ }
449
+ var FilesystemAdapter = class {
450
+ constructor(client, opts) {
451
+ this.client = client;
452
+ this.opts = opts;
453
+ this.fetch = opts.fetch ?? fetch;
454
+ }
455
+ fetch;
456
+ static Api = {
457
+ // This is intentionally derived from OpenAPI schema types so API changes surface quickly.
458
+ SearchFilesOk: null,
459
+ FilesInfoOk: null,
460
+ MakeDirsRequest: null,
461
+ SetPermissionsRequest: null,
462
+ MoveFilesRequest: null,
463
+ ReplaceContentsRequest: null
464
+ };
465
+ parseIsoDate(field, v) {
466
+ if (typeof v !== "string" || !v) {
467
+ throw new Error(`Invalid ${field}: expected ISO string, got ${typeof v}`);
468
+ }
469
+ const d = new Date(v);
470
+ if (Number.isNaN(d.getTime())) {
471
+ throw new Error(`Invalid ${field}: ${v}`);
472
+ }
473
+ return d;
474
+ }
475
+ static _ApiFileInfo = null;
476
+ mapApiFileInfo(raw) {
477
+ const { path, size, created_at, modified_at, mode, owner, group, ...rest } = raw;
478
+ return {
479
+ ...rest,
480
+ path,
481
+ size,
482
+ mode,
483
+ owner,
484
+ group,
485
+ createdAt: created_at ? this.parseIsoDate("createdAt", created_at) : void 0,
486
+ modifiedAt: modified_at ? this.parseIsoDate("modifiedAt", modified_at) : void 0
487
+ };
488
+ }
489
+ async getFileInfo(paths) {
490
+ const { data, error, response } = await this.client.GET("/files/info", {
491
+ params: { query: { path: paths } }
492
+ });
493
+ throwOnOpenApiFetchError({ error, response }, "Get file info failed");
494
+ const raw = data;
495
+ if (!raw) return {};
496
+ if (typeof raw !== "object") {
497
+ throw new Error(
498
+ `Get file info failed: unexpected response shape (got ${typeof raw})`
499
+ );
500
+ }
501
+ const out = {};
502
+ for (const [k, v] of Object.entries(raw)) {
503
+ if (!v || typeof v !== "object") {
504
+ throw new Error(
505
+ `Get file info failed: invalid file info for path=${k}`
506
+ );
507
+ }
508
+ out[k] = this.mapApiFileInfo(v);
509
+ }
510
+ return out;
511
+ }
512
+ async deleteFiles(paths) {
513
+ const { error, response } = await this.client.DELETE("/files", {
514
+ params: { query: { path: paths } }
515
+ });
516
+ throwOnOpenApiFetchError({ error, response }, "Delete files failed");
517
+ }
518
+ async createDirectories(entries) {
519
+ const map = {};
520
+ for (const e of entries) {
521
+ map[e.path] = toPermission(e);
522
+ }
523
+ const body = map;
524
+ const { error, response } = await this.client.POST("/directories", {
525
+ body
526
+ });
527
+ throwOnOpenApiFetchError({ error, response }, "Create directories failed");
528
+ }
529
+ async deleteDirectories(paths) {
530
+ const { error, response } = await this.client.DELETE("/directories", {
531
+ params: { query: { path: paths } }
532
+ });
533
+ throwOnOpenApiFetchError({ error, response }, "Delete directories failed");
534
+ }
535
+ async setPermissions(entries) {
536
+ const req = {};
537
+ for (const e of entries) {
538
+ req[e.path] = toPermission(e);
539
+ }
540
+ const body = req;
541
+ const { error, response } = await this.client.POST("/files/permissions", {
542
+ body
543
+ });
544
+ throwOnOpenApiFetchError({ error, response }, "Set permissions failed");
545
+ }
546
+ async moveFiles(entries) {
547
+ const req = entries.map((e) => ({
548
+ src: e.src,
549
+ dest: e.dest
550
+ }));
551
+ const body = req;
552
+ const { error, response } = await this.client.POST("/files/mv", {
553
+ body
554
+ });
555
+ throwOnOpenApiFetchError({ error, response }, "Move files failed");
556
+ }
557
+ async replaceContents(entries) {
558
+ const req = {};
559
+ for (const e of entries) {
560
+ req[e.path] = { old: e.oldContent, new: e.newContent };
561
+ }
562
+ const body = req;
563
+ const { error, response } = await this.client.POST("/files/replace", {
564
+ body
565
+ });
566
+ throwOnOpenApiFetchError({ error, response }, "Replace contents failed");
567
+ }
568
+ async search(entry) {
569
+ const { data, error, response } = await this.client.GET("/files/search", {
570
+ params: { query: { path: entry.path, pattern: entry.pattern } }
571
+ });
572
+ throwOnOpenApiFetchError({ error, response }, "Search files failed");
573
+ const ok = data;
574
+ if (!ok) return [];
575
+ if (!Array.isArray(ok)) {
576
+ throw new Error(
577
+ `Search files failed: unexpected response shape (expected array, got ${typeof ok})`
578
+ );
579
+ }
580
+ return ok.map((x) => this.mapApiFileInfo(x));
581
+ }
582
+ async uploadFile(meta, data) {
583
+ const url = joinUrl2(this.opts.baseUrl, "/files/upload");
584
+ const fileName = basename(meta.path);
585
+ const metadataJson = JSON.stringify(meta);
586
+ if (isReadableStream(data) || isAsyncIterable(data)) {
587
+ if (!isNodeRuntime()) {
588
+ const bytes = await collectBytes(data);
589
+ return await this.uploadFile(meta, bytes);
590
+ }
591
+ const boundary = `opensandbox_${Math.random().toString(16).slice(2)}_${Date.now()}`;
592
+ const bodyIt = multipartUploadBody({
593
+ boundary,
594
+ metadataJson,
595
+ fileName,
596
+ fileContentType: "application/octet-stream",
597
+ file: data
598
+ });
599
+ const stream = toReadableStream(bodyIt);
600
+ const res2 = await this.fetch(url, {
601
+ method: "POST",
602
+ headers: {
603
+ "content-type": `multipart/form-data; boundary=${boundary}`,
604
+ ...this.opts.headers ?? {}
605
+ },
606
+ body: stream,
607
+ // Node fetch (undici) requires duplex for streaming request bodies.
608
+ duplex: "half"
609
+ });
610
+ if (!res2.ok) {
611
+ const requestId = res2.headers.get("x-request-id") ?? void 0;
612
+ const rawBody = await res2.text().catch(() => void 0);
613
+ throw new SandboxApiException({
614
+ message: `Upload failed (status=${res2.status})`,
615
+ statusCode: res2.status,
616
+ requestId,
617
+ error: new SandboxError(
618
+ SandboxError.UNEXPECTED_RESPONSE,
619
+ "Upload failed"
620
+ ),
621
+ rawBody
622
+ });
623
+ }
624
+ return;
625
+ }
626
+ const form = new FormData();
627
+ form.append(
628
+ "metadata",
629
+ new Blob([metadataJson], { type: "application/json" }),
630
+ "metadata"
631
+ );
632
+ if (typeof data === "string") {
633
+ const textBlob = new Blob([data], { type: "text/plain; charset=utf-8" });
634
+ form.append("file", textBlob, fileName);
635
+ } else {
636
+ const blob = toUploadBlob(data);
637
+ const fileBlob = blob.type ? blob : new Blob([blob], { type: "application/octet-stream" });
638
+ form.append("file", fileBlob, fileName);
639
+ }
640
+ const res = await this.fetch(url, {
641
+ method: "POST",
642
+ headers: {
643
+ ...this.opts.headers ?? {}
644
+ },
645
+ body: form
646
+ });
647
+ if (!res.ok) {
648
+ const requestId = res.headers.get("x-request-id") ?? void 0;
649
+ const rawBody = await res.text().catch(() => void 0);
650
+ throw new SandboxApiException({
651
+ message: `Upload failed (status=${res.status})`,
652
+ statusCode: res.status,
653
+ requestId,
654
+ error: new SandboxError(
655
+ SandboxError.UNEXPECTED_RESPONSE,
656
+ "Upload failed"
657
+ ),
658
+ rawBody
659
+ });
660
+ }
661
+ }
662
+ async readBytes(path, opts) {
663
+ const url = joinUrl2(this.opts.baseUrl, "/files/download") + `?path=${encodeURIComponent(path)}`;
664
+ const res = await this.fetch(url, {
665
+ method: "GET",
666
+ headers: {
667
+ ...this.opts.headers ?? {},
668
+ ...opts?.range ? { Range: opts.range } : {}
669
+ }
670
+ });
671
+ if (!res.ok) {
672
+ const requestId = res.headers.get("x-request-id") ?? void 0;
673
+ const rawBody = await res.text().catch(() => void 0);
674
+ throw new SandboxApiException({
675
+ message: "Download failed",
676
+ statusCode: res.status,
677
+ requestId,
678
+ error: new SandboxError(
679
+ SandboxError.UNEXPECTED_RESPONSE,
680
+ "Download failed"
681
+ ),
682
+ rawBody
683
+ });
684
+ }
685
+ const ab = await res.arrayBuffer();
686
+ return new Uint8Array(ab);
687
+ }
688
+ readBytesStream(path, opts) {
689
+ return this.downloadStream(path, opts);
690
+ }
691
+ async *downloadStream(path, opts) {
692
+ const url = joinUrl2(this.opts.baseUrl, "/files/download") + `?path=${encodeURIComponent(path)}`;
693
+ const res = await this.fetch(url, {
694
+ method: "GET",
695
+ headers: {
696
+ ...this.opts.headers ?? {},
697
+ ...opts?.range ? { Range: opts.range } : {}
698
+ }
699
+ });
700
+ if (!res.ok) {
701
+ const requestId = res.headers.get("x-request-id") ?? void 0;
702
+ const rawBody = await res.text().catch(() => void 0);
703
+ throw new SandboxApiException({
704
+ message: "Download stream failed",
705
+ statusCode: res.status,
706
+ requestId,
707
+ error: new SandboxError(
708
+ SandboxError.UNEXPECTED_RESPONSE,
709
+ "Download stream failed"
710
+ ),
711
+ rawBody
712
+ });
713
+ }
714
+ const body = res.body;
715
+ if (!body) return;
716
+ const reader = body.getReader();
717
+ while (true) {
718
+ const { done, value } = await reader.read();
719
+ if (done) return;
720
+ if (value) yield value;
721
+ }
722
+ }
723
+ async readFile(path, opts) {
724
+ const bytes = await this.readBytes(path, { range: opts?.range });
725
+ const encoding = opts?.encoding ?? "utf-8";
726
+ return new TextDecoder(encoding).decode(bytes);
727
+ }
728
+ async writeFiles(entries) {
729
+ for (const e of entries) {
730
+ const meta = {
731
+ path: e.path,
732
+ owner: e.owner,
733
+ group: e.group,
734
+ mode: e.mode
735
+ };
736
+ await this.uploadFile(meta, e.data ?? "");
737
+ }
738
+ }
739
+ };
740
+
741
+ // src/adapters/healthAdapter.ts
742
+ var HealthAdapter = class {
743
+ constructor(client) {
744
+ this.client = client;
745
+ }
746
+ async ping() {
747
+ const { error, response } = await this.client.GET("/ping");
748
+ throwOnOpenApiFetchError({ error, response }, "Execd ping failed");
749
+ return true;
750
+ }
751
+ };
752
+
753
+ // src/adapters/metricsAdapter.ts
754
+ function normalizeMetrics(m) {
755
+ const cpuCount = m.cpu_count ?? 0;
756
+ const cpuUsedPercentage = m.cpu_used_pct ?? 0;
757
+ const memoryTotalMiB = m.mem_total_mib ?? 0;
758
+ const memoryUsedMiB = m.mem_used_mib ?? 0;
759
+ const timestamp = m.timestamp ?? 0;
760
+ return {
761
+ cpuCount: Number(cpuCount),
762
+ cpuUsedPercentage: Number(cpuUsedPercentage),
763
+ memoryTotalMiB: Number(memoryTotalMiB),
764
+ memoryUsedMiB: Number(memoryUsedMiB),
765
+ timestamp: Number(timestamp)
766
+ };
767
+ }
768
+ var MetricsAdapter = class {
769
+ constructor(client) {
770
+ this.client = client;
771
+ }
772
+ async getMetrics() {
773
+ const { data, error, response } = await this.client.GET("/metrics");
774
+ throwOnOpenApiFetchError({ error, response }, "Get execd metrics failed");
775
+ const ok = data;
776
+ if (!ok || typeof ok !== "object") {
777
+ throw new Error("Get execd metrics failed: unexpected response shape");
778
+ }
779
+ return normalizeMetrics(ok);
780
+ }
781
+ };
782
+
783
+ // src/adapters/sandboxesAdapter.ts
784
+ function encodeMetadataFilter(metadata) {
785
+ const parts = [];
786
+ for (const [k, v] of Object.entries(metadata)) {
787
+ parts.push(`${k}=${v}`);
788
+ }
789
+ return parts.join("&");
790
+ }
791
+ var SandboxesAdapter = class {
792
+ constructor(client) {
793
+ this.client = client;
794
+ }
795
+ parseIsoDate(field, v) {
796
+ if (typeof v !== "string" || !v) {
797
+ throw new Error(`Invalid ${field}: expected ISO string, got ${typeof v}`);
798
+ }
799
+ const d = new Date(v);
800
+ if (Number.isNaN(d.getTime())) {
801
+ throw new Error(`Invalid ${field}: ${v}`);
802
+ }
803
+ return d;
804
+ }
805
+ mapSandboxInfo(raw) {
806
+ return {
807
+ ...raw ?? {},
808
+ createdAt: this.parseIsoDate("createdAt", raw?.createdAt),
809
+ expiresAt: this.parseIsoDate("expiresAt", raw?.expiresAt)
810
+ };
811
+ }
812
+ async createSandbox(req) {
813
+ const body = req;
814
+ const { data, error, response } = await this.client.POST("/sandboxes", {
815
+ body
816
+ });
817
+ throwOnOpenApiFetchError({ error, response }, "Create sandbox failed");
818
+ const raw = data;
819
+ if (!raw || typeof raw !== "object") {
820
+ throw new Error("Create sandbox failed: unexpected response shape");
821
+ }
822
+ return {
823
+ ...raw ?? {},
824
+ createdAt: this.parseIsoDate("createdAt", raw?.createdAt),
825
+ expiresAt: this.parseIsoDate("expiresAt", raw?.expiresAt)
826
+ };
827
+ }
828
+ async getSandbox(sandboxId) {
829
+ const { data, error, response } = await this.client.GET("/sandboxes/{sandboxId}", {
830
+ params: { path: { sandboxId } }
831
+ });
832
+ throwOnOpenApiFetchError({ error, response }, "Get sandbox failed");
833
+ const ok = data;
834
+ if (!ok || typeof ok !== "object") {
835
+ throw new Error("Get sandbox failed: unexpected response shape");
836
+ }
837
+ return this.mapSandboxInfo(ok);
838
+ }
839
+ async listSandboxes(params = {}) {
840
+ const query = {};
841
+ if (params.states?.length) query.state = params.states;
842
+ if (params.metadata && Object.keys(params.metadata).length) {
843
+ query.metadata = encodeMetadataFilter(params.metadata);
844
+ }
845
+ if (params.page != null) query.page = params.page;
846
+ if (params.pageSize != null) query.pageSize = params.pageSize;
847
+ const { data, error, response } = await this.client.GET("/sandboxes", {
848
+ params: { query }
849
+ });
850
+ throwOnOpenApiFetchError({ error, response }, "List sandboxes failed");
851
+ const raw = data;
852
+ if (!raw || typeof raw !== "object") {
853
+ throw new Error("List sandboxes failed: unexpected response shape");
854
+ }
855
+ const itemsRaw = raw.items;
856
+ if (!Array.isArray(itemsRaw)) throw new Error("List sandboxes failed: unexpected items shape");
857
+ return {
858
+ ...raw ?? {},
859
+ items: itemsRaw.map((x) => this.mapSandboxInfo(x))
860
+ };
861
+ }
862
+ async deleteSandbox(sandboxId) {
863
+ const { error, response } = await this.client.DELETE("/sandboxes/{sandboxId}", {
864
+ params: { path: { sandboxId } }
865
+ });
866
+ throwOnOpenApiFetchError({ error, response }, "Delete sandbox failed");
867
+ }
868
+ async pauseSandbox(sandboxId) {
869
+ const { error, response } = await this.client.POST("/sandboxes/{sandboxId}/pause", {
870
+ params: { path: { sandboxId } }
871
+ });
872
+ throwOnOpenApiFetchError({ error, response }, "Pause sandbox failed");
873
+ }
874
+ async resumeSandbox(sandboxId) {
875
+ const { error, response } = await this.client.POST("/sandboxes/{sandboxId}/resume", {
876
+ params: { path: { sandboxId } }
877
+ });
878
+ throwOnOpenApiFetchError({ error, response }, "Resume sandbox failed");
879
+ }
880
+ async renewSandboxExpiration(sandboxId, req) {
881
+ const body = req;
882
+ const { data, error, response } = await this.client.POST("/sandboxes/{sandboxId}/renew-expiration", {
883
+ params: { path: { sandboxId } },
884
+ body
885
+ });
886
+ throwOnOpenApiFetchError({ error, response }, "Renew sandbox expiration failed");
887
+ const raw = data;
888
+ if (!raw || typeof raw !== "object") {
889
+ throw new Error("Renew sandbox expiration failed: unexpected response shape");
890
+ }
891
+ return {
892
+ ...raw ?? {},
893
+ expiresAt: raw?.expiresAt ? this.parseIsoDate("expiresAt", raw.expiresAt) : void 0
894
+ };
895
+ }
896
+ async getSandboxEndpoint(sandboxId, port) {
897
+ const { data, error, response } = await this.client.GET("/sandboxes/{sandboxId}/endpoints/{port}", {
898
+ params: { path: { sandboxId, port } }
899
+ });
900
+ throwOnOpenApiFetchError({ error, response }, "Get sandbox endpoint failed");
901
+ const ok = data;
902
+ if (!ok || typeof ok !== "object") {
903
+ throw new Error("Get sandbox endpoint failed: unexpected response shape");
904
+ }
905
+ return ok;
906
+ }
907
+ };
908
+
909
+ export {
910
+ SandboxError,
911
+ SandboxException,
912
+ SandboxApiException,
913
+ SandboxInternalException,
914
+ SandboxUnhealthyException,
915
+ SandboxReadyTimeoutException,
916
+ InvalidArgumentException,
917
+ createExecdClient,
918
+ createLifecycleClient,
919
+ ExecutionEventDispatcher,
920
+ CommandsAdapter,
921
+ FilesystemAdapter,
922
+ HealthAdapter,
923
+ MetricsAdapter,
924
+ SandboxesAdapter
925
+ };
926
+ //# sourceMappingURL=chunk-NFNOESEY.js.map