@alibaba-group/opensandbox 0.1.3 → 0.1.4

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/README.md CHANGED
@@ -179,6 +179,7 @@ Runtime notes:
179
179
  | `requestTimeoutSeconds` | Request timeout applied to SDK HTTP calls | `30` | - |
180
180
  | `debug` | Enable basic HTTP debug logging | `false` | - |
181
181
  | `headers` | Extra headers applied to every request | `{}` | - |
182
+ | `useServerProxy` | Use sandbox server as proxy for execd/endpoint requests (e.g. when client cannot reach the sandbox directly) | `false` | - |
182
183
 
183
184
  ```ts
184
185
  import { ConnectionConfig } from "@alibaba-group/opensandbox";
@@ -267,11 +267,27 @@ function joinUrl(baseUrl, pathname) {
267
267
  return `${base}${path}`;
268
268
  }
269
269
  function toRunCommandRequest(command, opts) {
270
- return {
270
+ const body = {
271
271
  command,
272
272
  cwd: opts?.workingDirectory,
273
273
  background: !!opts?.background
274
274
  };
275
+ if (opts?.timeoutSeconds != null) {
276
+ body.timeout = Math.round(opts.timeoutSeconds * 1e3);
277
+ }
278
+ return body;
279
+ }
280
+ function parseOptionalDate(value, field) {
281
+ if (value == null) return void 0;
282
+ if (value instanceof Date) return value;
283
+ if (typeof value !== "string") {
284
+ throw new Error(`Invalid ${field}: expected ISO string, got ${typeof value}`);
285
+ }
286
+ const parsed = new Date(value);
287
+ if (Number.isNaN(parsed.getTime())) {
288
+ throw new Error(`Invalid ${field}: ${value}`);
289
+ }
290
+ return parsed;
275
291
  }
276
292
  var CommandsAdapter = class {
277
293
  constructor(client, opts) {
@@ -286,6 +302,42 @@ var CommandsAdapter = class {
286
302
  });
287
303
  throwOnOpenApiFetchError({ error, response }, "Interrupt command failed");
288
304
  }
305
+ async getCommandStatus(commandId) {
306
+ const { data, error, response } = await this.client.GET("/command/status/{id}", {
307
+ params: { path: { id: commandId } }
308
+ });
309
+ throwOnOpenApiFetchError({ error, response }, "Get command status failed");
310
+ const ok = data;
311
+ if (!ok || typeof ok !== "object") {
312
+ throw new Error("Get command status failed: unexpected response shape");
313
+ }
314
+ return {
315
+ id: ok.id,
316
+ content: ok.content,
317
+ running: ok.running,
318
+ exitCode: ok.exit_code ?? null,
319
+ error: ok.error,
320
+ startedAt: parseOptionalDate(ok.started_at, "startedAt"),
321
+ finishedAt: parseOptionalDate(ok.finished_at, "finishedAt") ?? null
322
+ };
323
+ }
324
+ async getBackgroundCommandLogs(commandId, cursor) {
325
+ const { data, error, response } = await this.client.GET("/command/{id}/logs", {
326
+ params: { path: { id: commandId }, query: cursor == null ? {} : { cursor } },
327
+ parseAs: "text"
328
+ });
329
+ throwOnOpenApiFetchError({ error, response }, "Get command logs failed");
330
+ const ok = data;
331
+ if (typeof ok !== "string") {
332
+ throw new Error("Get command logs failed: unexpected response shape");
333
+ }
334
+ const cursorHeader = response.headers.get("EXECD-COMMANDS-TAIL-CURSOR");
335
+ const parsedCursor = cursorHeader != null && cursorHeader !== "" ? Number(cursorHeader) : void 0;
336
+ return {
337
+ content: ok,
338
+ cursor: Number.isFinite(parsedCursor ?? NaN) ? parsedCursor : void 0
339
+ };
340
+ }
289
341
  async *runStream(command, opts, signal) {
290
342
  const url = joinUrl(this.opts.baseUrl, "/command");
291
343
  const body = JSON.stringify(toRunCommandRequest(command, opts));
@@ -895,9 +947,9 @@ var SandboxesAdapter = class {
895
947
  expiresAt: raw?.expiresAt ? this.parseIsoDate("expiresAt", raw.expiresAt) : void 0
896
948
  };
897
949
  }
898
- async getSandboxEndpoint(sandboxId, port) {
950
+ async getSandboxEndpoint(sandboxId, port, useServerProxy = false) {
899
951
  const { data, error, response } = await this.client.GET("/sandboxes/{sandboxId}/endpoints/{port}", {
900
- params: { path: { sandboxId, port } }
952
+ params: { path: { sandboxId, port }, query: { use_server_proxy: useServerProxy } }
901
953
  });
902
954
  throwOnOpenApiFetchError({ error, response }, "Get sandbox endpoint failed");
903
955
  const ok = data;
@@ -925,4 +977,4 @@ export {
925
977
  MetricsAdapter,
926
978
  SandboxesAdapter
927
979
  };
928
- //# sourceMappingURL=chunk-4EF4ODU2.js.map
980
+ //# sourceMappingURL=chunk-OYTPXLWE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/exceptions.ts","../src/openapi/execdClient.ts","../src/openapi/lifecycleClient.ts","../src/models/executionEventDispatcher.ts","../src/adapters/openapiError.ts","../src/adapters/sse.ts","../src/adapters/commandsAdapter.ts","../src/adapters/filesystemAdapter.ts","../src/adapters/healthAdapter.ts","../src/adapters/metricsAdapter.ts","../src/adapters/sandboxesAdapter.ts"],"sourcesContent":["// Copyright 2026 Alibaba Group Holding Ltd.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// \n// http://www.apache.org/licenses/LICENSE-2.0\n// \n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nexport type SandboxErrorCode =\n | \"INTERNAL_UNKNOWN_ERROR\"\n | \"READY_TIMEOUT\"\n | \"UNHEALTHY\"\n | \"INVALID_ARGUMENT\"\n | \"UNEXPECTED_RESPONSE\"\n // Allow server-defined codes as well.\n | (string & {});\n\n/**\n * Structured error payload carried by {@link SandboxException}.\n *\n * - `code`: stable programmatic identifier\n * - `message`: optional human-readable message\n */\nexport class SandboxError {\n static readonly INTERNAL_UNKNOWN_ERROR: SandboxErrorCode = \"INTERNAL_UNKNOWN_ERROR\";\n static readonly READY_TIMEOUT: SandboxErrorCode = \"READY_TIMEOUT\";\n static readonly UNHEALTHY: SandboxErrorCode = \"UNHEALTHY\";\n static readonly INVALID_ARGUMENT: SandboxErrorCode = \"INVALID_ARGUMENT\";\n static readonly UNEXPECTED_RESPONSE: SandboxErrorCode = \"UNEXPECTED_RESPONSE\";\n\n constructor(\n readonly code: SandboxErrorCode,\n readonly message?: string,\n ) {}\n}\n\ninterface SandboxExceptionOpts {\n message?: string;\n cause?: unknown;\n error?: SandboxError;\n}\n\n/**\n * Base exception class for all SDK errors.\n *\n * All errors thrown by this SDK are subclasses of {@link SandboxException}.\n */\nexport class SandboxException extends Error {\n readonly name: string = \"SandboxException\";\n readonly error: SandboxError;\n readonly cause?: unknown;\n\n constructor(opts: SandboxExceptionOpts = {}) {\n super(opts.message);\n this.cause = opts.cause;\n this.error = opts.error ?? new SandboxError(SandboxError.INTERNAL_UNKNOWN_ERROR);\n }\n}\n\nexport class SandboxApiException extends SandboxException {\n readonly name: string = \"SandboxApiException\";\n readonly statusCode?: number;\n readonly requestId?: string;\n readonly rawBody?: unknown;\n\n constructor(opts: SandboxExceptionOpts & {\n statusCode?: number;\n requestId?: string;\n rawBody?: unknown;\n }) {\n super({\n message: opts.message,\n cause: opts.cause,\n error: opts.error ?? new SandboxError(SandboxError.UNEXPECTED_RESPONSE, opts.message),\n });\n this.statusCode = opts.statusCode;\n this.requestId = opts.requestId;\n this.rawBody = opts.rawBody;\n }\n}\n\nexport class SandboxInternalException extends SandboxException {\n readonly name: string = \"SandboxInternalException\";\n\n constructor(opts: { message?: string; cause?: unknown }) {\n super({\n message: opts.message,\n cause: opts.cause,\n error: new SandboxError(SandboxError.INTERNAL_UNKNOWN_ERROR, opts.message),\n });\n }\n}\n\nexport class SandboxUnhealthyException extends SandboxException {\n readonly name: string = \"SandboxUnhealthyException\";\n\n constructor(opts: { message?: string; cause?: unknown }) {\n super({\n message: opts.message,\n cause: opts.cause,\n error: new SandboxError(SandboxError.UNHEALTHY, opts.message),\n });\n }\n}\n\nexport class SandboxReadyTimeoutException extends SandboxException {\n readonly name: string = \"SandboxReadyTimeoutException\";\n\n constructor(opts: { message?: string; cause?: unknown }) {\n super({\n message: opts.message,\n cause: opts.cause,\n error: new SandboxError(SandboxError.READY_TIMEOUT, opts.message),\n });\n }\n}\n\nexport class InvalidArgumentException extends SandboxException {\n readonly name: string = \"InvalidArgumentException\";\n\n constructor(opts: { message?: string; cause?: unknown }) {\n super({\n message: opts.message,\n cause: opts.cause,\n error: new SandboxError(SandboxError.INVALID_ARGUMENT, opts.message),\n });\n }\n}","// Copyright 2026 Alibaba Group Holding Ltd.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// \n// http://www.apache.org/licenses/LICENSE-2.0\n// \n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport createClient from \"openapi-fetch\";\nimport type { Client } from \"openapi-fetch\";\n\nimport type { paths as ExecdPaths } from \"../api/execd.js\";\n\nexport type ExecdClient = Client<ExecdPaths>;\n\nexport interface CreateExecdClientOptions {\n /**\n * Base URL to the Execd API (no `/v1` prefix).\n * Examples:\n * - `http://localhost:44772`\n * - `http://api.opensandbox.io/sandboxes/<id>/port/44772`\n */\n baseUrl: string;\n /**\n * Extra headers applied to every request.\n */\n headers?: Record<string, string>;\n /**\n * Custom fetch implementation.\n *\n * Useful for proxies, custom TLS, request tracing, retries, or running in environments\n * where a global `fetch` is not available.\n */\n fetch?: typeof fetch;\n}\n\nexport function createExecdClient(opts: CreateExecdClientOptions): ExecdClient {\n const createClientFn =\n (createClient as unknown as { default?: typeof createClient }).default ?? createClient;\n return createClientFn<ExecdPaths>({\n baseUrl: opts.baseUrl,\n headers: opts.headers,\n fetch: opts.fetch,\n });\n}","// Copyright 2026 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport createClient from \"openapi-fetch\";\nimport type { Client } from \"openapi-fetch\";\n\nimport type { paths as LifecyclePaths } from \"../api/lifecycle.js\";\n\nexport type LifecycleClient = Client<LifecyclePaths>;\n\nexport interface CreateLifecycleClientOptions {\n /**\n * Base URL to OpenSandbox Lifecycle API, including the `/v1` prefix.\n * Example: `http://localhost:8080/v1`\n */\n baseUrl?: string;\n /**\n * API key for `OPEN-SANDBOX-API-KEY` header.\n * If omitted, reads from `process.env.OPEN_SANDBOX_API_KEY` when available.\n */\n apiKey?: string;\n /**\n * Extra headers applied to every request.\n */\n headers?: Record<string, string>;\n /**\n * Custom fetch implementation.\n *\n * Useful for proxies, custom TLS, request tracing, retries, or running in environments\n * where a global `fetch` is not available.\n */\n fetch?: typeof fetch;\n}\n\nfunction readEnvApiKey(): string | undefined {\n // Avoid requiring @types/node by not referencing `process` directly.\n // In Node, `globalThis.process.env` exists; in browsers it won't.\n const env = (globalThis as any)?.process?.env;\n const v = env?.OPEN_SANDBOX_API_KEY;\n return typeof v === \"string\" && v.length ? v : undefined;\n}\n\nexport function createLifecycleClient(opts: CreateLifecycleClientOptions = {}): LifecycleClient {\n const apiKey = opts.apiKey ?? readEnvApiKey();\n\n const headers: Record<string, string> = {\n ...(opts.headers ?? {}),\n };\n\n if (apiKey && !headers[\"OPEN-SANDBOX-API-KEY\"]) {\n headers[\"OPEN-SANDBOX-API-KEY\"] = apiKey;\n }\n\n const createClientFn =\n (createClient as unknown as { default?: typeof createClient }).default ?? createClient;\n return createClientFn<LifecyclePaths>({\n baseUrl: opts.baseUrl ?? \"http://localhost:8080/v1\",\n headers,\n fetch: opts.fetch,\n });\n}","// Copyright 2026 Alibaba Group Holding Ltd.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// \n// http://www.apache.org/licenses/LICENSE-2.0\n// \n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { Execution, ExecutionComplete, ExecutionError, ExecutionHandlers, ExecutionInit, ExecutionResult, OutputMessage } from \"./execution.js\";\nimport type { ServerStreamEvent } from \"./execd.js\";\n\nfunction extractText(results: ServerStreamEvent[\"results\"] | undefined): string | undefined {\n if (!results || typeof results !== \"object\") return undefined;\n const r = results as any;\n const v = r[\"text/plain\"] ?? r.text ?? r.textPlain;\n return v == null ? undefined : String(v);\n}\n\n/**\n * Dispatches streamed execution events to handlers.\n *\n * This mutates the provided `execution` object (appending logs/results and setting fields like\n * `id`, `executionCount`, and `complete`) and invokes optional callbacks in {@link ExecutionHandlers}.\n */\nexport class ExecutionEventDispatcher {\n constructor(\n private readonly execution: Execution,\n private readonly handlers?: ExecutionHandlers,\n ) {}\n\n async dispatch(ev: ServerStreamEvent): Promise<void> {\n await this.handlers?.onEvent?.(ev);\n\n const ts = ev.timestamp ?? Date.now();\n switch (ev.type) {\n case \"init\": {\n const id = ev.text ?? \"\";\n if (id) this.execution.id = id;\n const init: ExecutionInit = { id, timestamp: ts };\n await this.handlers?.onInit?.(init);\n return;\n }\n case \"stdout\": {\n const msg: OutputMessage = { text: ev.text ?? \"\", timestamp: ts, isError: false };\n this.execution.logs.stdout.push(msg);\n await this.handlers?.onStdout?.(msg);\n return;\n }\n case \"stderr\": {\n const msg: OutputMessage = { text: ev.text ?? \"\", timestamp: ts, isError: true };\n this.execution.logs.stderr.push(msg);\n await this.handlers?.onStderr?.(msg);\n return;\n }\n case \"result\": {\n const r: ExecutionResult = { text: extractText(ev.results), timestamp: ts, raw: ev.results as any };\n this.execution.result.push(r);\n await this.handlers?.onResult?.(r);\n return;\n }\n case \"execution_count\": {\n const c = (ev as any).execution_count;\n if (typeof c === \"number\") this.execution.executionCount = c;\n return;\n }\n case \"execution_complete\": {\n const ms = (ev as any).execution_time;\n const complete: ExecutionComplete = { timestamp: ts, executionTimeMs: typeof ms === \"number\" ? ms : 0 };\n this.execution.complete = complete;\n await this.handlers?.onExecutionComplete?.(complete);\n return;\n }\n case \"error\": {\n const e = ev.error as any;\n if (e) {\n const err: ExecutionError = {\n name: String(e.ename ?? e.name ?? \"\"),\n value: String(e.evalue ?? e.value ?? \"\"),\n timestamp: ts,\n traceback: Array.isArray(e.traceback) ? e.traceback.map(String) : [],\n };\n this.execution.error = err;\n await this.handlers?.onError?.(err);\n }\n return;\n }\n default:\n return;\n }\n }\n}","// Copyright 2026 Alibaba Group Holding Ltd.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// \n// http://www.apache.org/licenses/LICENSE-2.0\n// \n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { SandboxApiException, SandboxError } from \"../core/exceptions.js\";\n\nexport function throwOnOpenApiFetchError(\n result: { error?: unknown; response: Response },\n fallbackMessage: string,\n): void {\n if (!result.error) return;\n\n const requestId = result.response.headers.get(\"x-request-id\") ?? undefined;\n const status = (result.response as any).status ?? 0;\n\n const err = result.error as any;\n const message =\n err?.message ??\n err?.error?.message ??\n fallbackMessage;\n\n const code = err?.code ?? err?.error?.code;\n const msg = err?.message ?? err?.error?.message ?? message;\n\n throw new SandboxApiException({\n message: msg,\n statusCode: status,\n requestId,\n error: code ? new SandboxError(String(code), String(msg ?? \"\")) : new SandboxError(SandboxError.UNEXPECTED_RESPONSE, String(msg ?? \"\")),\n rawBody: result.error,\n });\n}","// Copyright 2026 Alibaba Group Holding Ltd.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// \n// http://www.apache.org/licenses/LICENSE-2.0\n// \n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { SandboxApiException, SandboxError } from \"../core/exceptions.js\";\n\nfunction tryParseJson(line: string): unknown | undefined {\n try {\n return JSON.parse(line);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Parses an SSE-like stream that may be either:\n * - standard SSE frames (`data: {...}\\n\\n`)\n * - newline-delimited JSON (one JSON object per line)\n */\nexport async function* parseJsonEventStream<T>(\n res: Response,\n opts?: { fallbackErrorMessage?: string },\n): AsyncIterable<T> {\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n const parsed = tryParseJson(text);\n const err = parsed && typeof parsed === \"object\" ? (parsed as any) : undefined;\n const requestId = res.headers.get(\"x-request-id\") ?? undefined;\n const message = err?.message ?? opts?.fallbackErrorMessage ?? `Stream request failed (status=${res.status})`;\n const code = err?.code ? String(err.code) : SandboxError.UNEXPECTED_RESPONSE;\n throw new SandboxApiException({\n message,\n statusCode: res.status,\n requestId,\n error: new SandboxError(code, err?.message ? String(err.message) : message),\n rawBody: parsed ?? text,\n });\n }\n\n if (!res.body) {\n return;\n }\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder(\"utf-8\");\n let buf = \"\";\n\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n\n buf += decoder.decode(value, { stream: true });\n let idx: number;\n\n while ((idx = buf.indexOf(\"\\n\")) >= 0) {\n const rawLine = buf.slice(0, idx);\n buf = buf.slice(idx + 1);\n\n const line = rawLine.trim();\n if (!line) continue;\n\n // Support standard SSE \"data:\" prefix\n if (line.startsWith(\":\")) continue;\n if (line.startsWith(\"event:\") || line.startsWith(\"id:\") || line.startsWith(\"retry:\")) continue;\n\n const jsonLine = line.startsWith(\"data:\") ? line.slice(\"data:\".length).trim() : line;\n if (!jsonLine) continue;\n\n const parsed = tryParseJson(jsonLine);\n if (!parsed) continue;\n yield parsed as T;\n }\n }\n\n // Flush any buffered UTF-8 bytes from the decoder.\n buf += decoder.decode();\n\n // flush last line if exists\n const last = buf.trim();\n if (last) {\n const jsonLine = last.startsWith(\"data:\") ? last.slice(\"data:\".length).trim() : last;\n const parsed = tryParseJson(jsonLine);\n if (parsed) yield parsed as T;\n }\n}","// Copyright 2026 Alibaba Group Holding Ltd.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// \n// http://www.apache.org/licenses/LICENSE-2.0\n// \n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { ExecdClient } from \"../openapi/execdClient.js\";\nimport { throwOnOpenApiFetchError } from \"./openapiError.js\";\nimport { parseJsonEventStream } from \"./sse.js\";\nimport type { paths as ExecdPaths } from \"../api/execd.js\";\nimport type {\n CommandExecution,\n CommandLogs,\n CommandStatus,\n RunCommandOpts,\n ServerStreamEvent,\n} from \"../models/execd.js\";\nimport type { ExecdCommands } from \"../services/execdCommands.js\";\nimport type { ExecutionHandlers } from \"../models/execution.js\";\nimport { ExecutionEventDispatcher } from \"../models/executionEventDispatcher.js\";\n\nfunction joinUrl(baseUrl: string, pathname: string): string {\n const base = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n const path = pathname.startsWith(\"/\") ? pathname : `/${pathname}`;\n return `${base}${path}`;\n}\n\ntype ApiRunCommandRequest =\n ExecdPaths[\"/command\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"];\ntype ApiCommandStatusOk =\n ExecdPaths[\"/command/status/{id}\"][\"get\"][\"responses\"][200][\"content\"][\"application/json\"];\ntype ApiCommandLogsOk =\n ExecdPaths[\"/command/{id}/logs\"][\"get\"][\"responses\"][200][\"content\"][\"text/plain\"];\n\nfunction toRunCommandRequest(command: string, opts?: RunCommandOpts): ApiRunCommandRequest {\n const body: ApiRunCommandRequest = {\n command,\n cwd: opts?.workingDirectory,\n background: !!opts?.background,\n };\n if (opts?.timeoutSeconds != null) {\n body.timeout = Math.round(opts.timeoutSeconds * 1000);\n }\n return body;\n}\n\nfunction parseOptionalDate(value: unknown, field: string): Date | undefined {\n if (value == null) return undefined;\n if (value instanceof Date) return value;\n if (typeof value !== \"string\") {\n throw new Error(`Invalid ${field}: expected ISO string, got ${typeof value}`);\n }\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n throw new Error(`Invalid ${field}: ${value}`);\n }\n return parsed;\n}\n\nexport interface CommandsAdapterOptions {\n /**\n * Must match the baseUrl used by the ExecdClient.\n */\n baseUrl: string;\n fetch?: typeof fetch;\n headers?: Record<string, string>;\n}\n\nexport class CommandsAdapter implements ExecdCommands {\n private readonly fetch: typeof fetch;\n\n constructor(\n private readonly client: ExecdClient,\n private readonly opts: CommandsAdapterOptions,\n ) {\n this.fetch = opts.fetch ?? fetch;\n }\n\n async interrupt(sessionId: string): Promise<void> {\n const { error, response } = await this.client.DELETE(\"/command\", {\n params: { query: { id: sessionId } },\n });\n throwOnOpenApiFetchError({ error, response }, \"Interrupt command failed\");\n }\n\n async getCommandStatus(commandId: string): Promise<CommandStatus> {\n const { data, error, response } = await this.client.GET(\"/command/status/{id}\", {\n params: { path: { id: commandId } },\n });\n throwOnOpenApiFetchError({ error, response }, \"Get command status failed\");\n const ok = data as ApiCommandStatusOk | undefined;\n if (!ok || typeof ok !== \"object\") {\n throw new Error(\"Get command status failed: unexpected response shape\");\n }\n return {\n id: ok.id,\n content: ok.content,\n running: ok.running,\n exitCode: ok.exit_code ?? null,\n error: ok.error,\n startedAt: parseOptionalDate(ok.started_at, \"startedAt\"),\n finishedAt: parseOptionalDate(ok.finished_at, \"finishedAt\") ?? null,\n };\n }\n\n async getBackgroundCommandLogs(commandId: string, cursor?: number): Promise<CommandLogs> {\n const { data, error, response } = await this.client.GET(\"/command/{id}/logs\", {\n params: { path: { id: commandId }, query: cursor == null ? {} : { cursor } },\n parseAs: \"text\",\n });\n throwOnOpenApiFetchError({ error, response }, \"Get command logs failed\");\n const ok = data as ApiCommandLogsOk | undefined;\n if (typeof ok !== \"string\") {\n throw new Error(\"Get command logs failed: unexpected response shape\");\n }\n const cursorHeader = response.headers.get(\"EXECD-COMMANDS-TAIL-CURSOR\");\n const parsedCursor = (cursorHeader != null && cursorHeader !== \"\") ? Number(cursorHeader) : undefined;\n return {\n content: ok,\n cursor: Number.isFinite(parsedCursor ?? NaN) ? parsedCursor : undefined,\n };\n }\n\n async *runStream(\n command: string,\n opts?: RunCommandOpts,\n signal?: AbortSignal,\n ): AsyncIterable<ServerStreamEvent> {\n const url = joinUrl(this.opts.baseUrl, \"/command\");\n const body = JSON.stringify(toRunCommandRequest(command, opts));\n\n const res = await this.fetch(url, {\n method: \"POST\",\n headers: {\n \"accept\": \"text/event-stream\",\n \"content-type\": \"application/json\",\n ...(this.opts.headers ?? {}),\n },\n body,\n signal,\n });\n\n for await (const ev of parseJsonEventStream<ServerStreamEvent>(res, { fallbackErrorMessage: \"Run command failed\" })) {\n yield ev;\n }\n }\n\n async run(\n command: string,\n opts?: RunCommandOpts,\n handlers?: ExecutionHandlers,\n signal?: AbortSignal,\n ): Promise<CommandExecution> {\n const execution: CommandExecution = {\n logs: { stdout: [], stderr: [] },\n result: [],\n };\n const dispatcher = new ExecutionEventDispatcher(execution, handlers);\n for await (const ev of this.runStream(command, opts, signal)) {\n // Keep legacy behavior: if server sends \"init\" with empty id, preserve previous id.\n if (ev.type === \"init\" && (ev.text ?? \"\") === \"\" && execution.id) {\n (ev as any).text = execution.id;\n }\n await dispatcher.dispatch(ev as any);\n }\n\n return execution;\n }\n}","// Copyright 2026 Alibaba Group Holding Ltd.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// \n// http://www.apache.org/licenses/LICENSE-2.0\n// \n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { ExecdClient } from \"../openapi/execdClient.js\";\nimport { throwOnOpenApiFetchError } from \"./openapiError.js\";\nimport type { SandboxFiles } from \"../services/filesystem.js\";\nimport type { paths as ExecdPaths } from \"../api/execd.js\";\nimport type {\n ContentReplaceEntry,\n FileInfo,\n FileMetadata,\n FilesInfoResponse,\n MoveEntry,\n Permission,\n RenameFileItem,\n ReplaceFileContentItem,\n SearchEntry,\n SearchFilesResponse,\n SetPermissionEntry,\n WriteEntry,\n} from \"../models/filesystem.js\";\nimport { SandboxApiException, SandboxError } from \"../core/exceptions.js\";\n\nfunction joinUrl(baseUrl: string, pathname: string): string {\n const base = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n const path = pathname.startsWith(\"/\") ? pathname : `/${pathname}`;\n return `${base}${path}`;\n}\n\nfunction toUploadBlob(data: Blob | Uint8Array | ArrayBuffer | string): Blob {\n if (typeof data === \"string\") return new Blob([data]);\n if (data instanceof Blob) return data;\n if (data instanceof ArrayBuffer) return new Blob([data]);\n // Copy into a new Uint8Array backed by ArrayBuffer (not SharedArrayBuffer)\n const copied = Uint8Array.from(data);\n return new Blob([copied.buffer]);\n}\n\nfunction isReadableStream(v: unknown): v is ReadableStream<Uint8Array> {\n return !!v && typeof (v as any).getReader === \"function\";\n}\n\nfunction isAsyncIterable(v: unknown): v is AsyncIterable<Uint8Array> {\n return !!v && typeof (v as any)[Symbol.asyncIterator] === \"function\";\n}\n\nfunction isNodeRuntime(): boolean {\n const p = (globalThis as any)?.process;\n return !!(p?.versions?.node);\n}\n\nasync function collectBytes(\n source: ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>\n): Promise<Uint8Array> {\n const chunks: Uint8Array[] = [];\n let total = 0;\n\n if (isReadableStream(source)) {\n const reader = source.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) {\n chunks.push(value);\n total += value.length;\n }\n }\n } finally {\n reader.releaseLock();\n }\n } else {\n for await (const chunk of source) {\n chunks.push(chunk);\n total += chunk.length;\n }\n }\n\n const out = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n out.set(chunk, offset);\n offset += chunk.length;\n }\n return out;\n}\n\nfunction toReadableStream(\n it: AsyncIterable<Uint8Array>\n): ReadableStream<Uint8Array> {\n const RS: any = ReadableStream as any;\n if (typeof RS?.from === \"function\") return RS.from(it);\n const iterator = it[Symbol.asyncIterator]();\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n const r = await iterator.next();\n if (r.done) {\n controller.close();\n return;\n }\n controller.enqueue(r.value);\n },\n async cancel() {\n await iterator.return?.();\n },\n });\n}\n\nfunction basename(p: string): string {\n const parts = p.split(\"/\").filter(Boolean);\n return parts.length ? parts[parts.length - 1] : \"file\";\n}\n\nfunction encodeUtf8(s: string): Uint8Array {\n return new TextEncoder().encode(s);\n}\n\nasync function* multipartUploadBody(opts: {\n boundary: string;\n metadataJson: string;\n fileName: string;\n fileContentType: string;\n file: ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>;\n}): AsyncIterable<Uint8Array> {\n const b = opts.boundary;\n\n // Part 1: metadata (application/json)\n yield encodeUtf8(`--${b}\\r\\n`);\n yield encodeUtf8(\n `Content-Disposition: form-data; name=\"metadata\"; filename=\"metadata\"\\r\\n`\n );\n yield encodeUtf8(`Content-Type: application/json\\r\\n\\r\\n`);\n yield encodeUtf8(opts.metadataJson);\n yield encodeUtf8(`\\r\\n`);\n\n // Part 2: file\n yield encodeUtf8(`--${b}\\r\\n`);\n yield encodeUtf8(\n `Content-Disposition: form-data; name=\"file\"; filename=\"${opts.fileName}\"\\r\\n`\n );\n yield encodeUtf8(`Content-Type: ${opts.fileContentType}\\r\\n\\r\\n`);\n\n if (isReadableStream(opts.file)) {\n const reader = opts.file.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) yield value;\n }\n } finally {\n reader.releaseLock();\n }\n } else {\n for await (const chunk of opts.file) {\n yield chunk;\n }\n }\n\n yield encodeUtf8(`\\r\\n--${b}--\\r\\n`);\n}\n\nexport interface FilesystemAdapterOptions {\n /**\n * Must match the baseUrl used by the ExecdClient, used for binary endpoints\n * like download/upload where we bypass JSON parsing.\n */\n baseUrl: string;\n fetch?: typeof fetch;\n headers?: Record<string, string>;\n}\n\nfunction toPermission(e: {\n mode?: number;\n owner?: string;\n group?: string;\n}): Permission {\n return {\n mode: e.mode ?? 755,\n owner: e.owner,\n group: e.group,\n } as Permission;\n}\n\n/**\n * Filesystem adapter that exposes user-facing file APIs (`sandbox.files`).\n *\n * This adapter owns all request/response conversions:\n * - Maps friendly method shapes to API payloads\n * - Parses timestamps into `Date`\n * - Implements streaming upload/download helpers\n */\nexport class FilesystemAdapter implements SandboxFiles {\n private readonly fetch: typeof fetch;\n\n private static readonly Api = {\n // This is intentionally derived from OpenAPI schema types so API changes surface quickly.\n SearchFilesOk:\n null as unknown as ExecdPaths[\"/files/search\"][\"get\"][\"responses\"][200][\"content\"][\"application/json\"],\n FilesInfoOk:\n null as unknown as ExecdPaths[\"/files/info\"][\"get\"][\"responses\"][200][\"content\"][\"application/json\"],\n MakeDirsRequest:\n null as unknown as ExecdPaths[\"/directories\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n SetPermissionsRequest:\n null as unknown as ExecdPaths[\"/files/permissions\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n MoveFilesRequest:\n null as unknown as ExecdPaths[\"/files/mv\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ReplaceContentsRequest:\n null as unknown as ExecdPaths[\"/files/replace\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n };\n\n constructor(\n private readonly client: ExecdClient,\n private readonly opts: FilesystemAdapterOptions\n ) {\n this.fetch = opts.fetch ?? fetch;\n }\n\n private parseIsoDate(field: string, v: unknown): Date {\n if (typeof v !== \"string\" || !v) {\n throw new Error(`Invalid ${field}: expected ISO string, got ${typeof v}`);\n }\n const d = new Date(v);\n if (Number.isNaN(d.getTime())) {\n throw new Error(`Invalid ${field}: ${v}`);\n }\n return d;\n }\n\n private static readonly _ApiFileInfo =\n null as unknown as (typeof FilesystemAdapter.Api.SearchFilesOk)[number];\n\n private mapApiFileInfo(raw: typeof FilesystemAdapter._ApiFileInfo): FileInfo {\n const { path, size, created_at, modified_at, mode, owner, group, ...rest } =\n raw;\n\n return {\n ...rest,\n path,\n size,\n mode,\n owner,\n group,\n createdAt: created_at\n ? this.parseIsoDate(\"createdAt\", created_at)\n : undefined,\n modifiedAt: modified_at\n ? this.parseIsoDate(\"modifiedAt\", modified_at)\n : undefined,\n };\n }\n\n async getFileInfo(paths: string[]): Promise<Record<string, FileInfo>> {\n const { data, error, response } = await this.client.GET(\"/files/info\", {\n params: { query: { path: paths } },\n });\n throwOnOpenApiFetchError({ error, response }, \"Get file info failed\");\n const raw = data as typeof FilesystemAdapter.Api.FilesInfoOk | undefined;\n if (!raw) return {} as FilesInfoResponse;\n if (typeof raw !== \"object\") {\n throw new Error(\n `Get file info failed: unexpected response shape (got ${typeof raw})`\n );\n }\n const out: Record<string, FileInfo> = {};\n for (const [k, v] of Object.entries(raw as Record<string, unknown>)) {\n if (!v || typeof v !== \"object\") {\n throw new Error(\n `Get file info failed: invalid file info for path=${k}`\n );\n }\n out[k] = this.mapApiFileInfo(v as typeof FilesystemAdapter._ApiFileInfo);\n }\n return out as FilesInfoResponse;\n }\n\n async deleteFiles(paths: string[]): Promise<void> {\n const { error, response } = await this.client.DELETE(\"/files\", {\n params: { query: { path: paths } },\n });\n throwOnOpenApiFetchError({ error, response }, \"Delete files failed\");\n }\n\n async createDirectories(\n entries: Pick<WriteEntry, \"path\" | \"mode\" | \"owner\" | \"group\">[]\n ): Promise<void> {\n const map: Record<string, Permission> = {};\n for (const e of entries) {\n map[e.path] = toPermission(e);\n }\n const body = map as unknown as typeof FilesystemAdapter.Api.MakeDirsRequest;\n const { error, response } = await this.client.POST(\"/directories\", {\n body,\n });\n throwOnOpenApiFetchError({ error, response }, \"Create directories failed\");\n }\n\n async deleteDirectories(paths: string[]): Promise<void> {\n const { error, response } = await this.client.DELETE(\"/directories\", {\n params: { query: { path: paths } },\n });\n throwOnOpenApiFetchError({ error, response }, \"Delete directories failed\");\n }\n\n async setPermissions(entries: SetPermissionEntry[]): Promise<void> {\n const req: Record<string, Permission> = {};\n for (const e of entries) {\n req[e.path] = toPermission(e);\n }\n const body =\n req as unknown as typeof FilesystemAdapter.Api.SetPermissionsRequest;\n const { error, response } = await this.client.POST(\"/files/permissions\", {\n body,\n });\n throwOnOpenApiFetchError({ error, response }, \"Set permissions failed\");\n }\n\n async moveFiles(entries: MoveEntry[]): Promise<void> {\n const req: RenameFileItem[] = entries.map((e) => ({\n src: e.src,\n dest: e.dest,\n }));\n const body =\n req as unknown as typeof FilesystemAdapter.Api.MoveFilesRequest;\n const { error, response } = await this.client.POST(\"/files/mv\", {\n body,\n });\n throwOnOpenApiFetchError({ error, response }, \"Move files failed\");\n }\n\n async replaceContents(entries: ContentReplaceEntry[]): Promise<void> {\n const req: Record<string, ReplaceFileContentItem> = {};\n for (const e of entries) {\n req[e.path] = { old: e.oldContent, new: e.newContent };\n }\n const body =\n req as unknown as typeof FilesystemAdapter.Api.ReplaceContentsRequest;\n const { error, response } = await this.client.POST(\"/files/replace\", {\n body,\n });\n throwOnOpenApiFetchError({ error, response }, \"Replace contents failed\");\n }\n\n async search(entry: SearchEntry): Promise<SearchFilesResponse> {\n const { data, error, response } = await this.client.GET(\"/files/search\", {\n params: { query: { path: entry.path, pattern: entry.pattern } },\n });\n throwOnOpenApiFetchError({ error, response }, \"Search files failed\");\n\n // Make the OpenAPI contract explicit (and fail loudly on unexpected shapes).\n const ok = data as typeof FilesystemAdapter.Api.SearchFilesOk | undefined;\n if (!ok) return [];\n if (!Array.isArray(ok)) {\n throw new Error(\n `Search files failed: unexpected response shape (expected array, got ${typeof ok})`\n );\n }\n return ok.map((x) => this.mapApiFileInfo(x));\n }\n\n private async uploadFile(\n meta: FileMetadata,\n data:\n | Blob\n | Uint8Array\n | ArrayBuffer\n | string\n | AsyncIterable<Uint8Array>\n | ReadableStream<Uint8Array>\n ): Promise<void> {\n const url = joinUrl(this.opts.baseUrl, \"/files/upload\");\n const fileName = basename(meta.path);\n const metadataJson = JSON.stringify(meta);\n\n // Streaming path (large files): build multipart body manually to avoid buffering.\n if (isReadableStream(data) || isAsyncIterable(data)) {\n // Browsers do not allow streaming multipart requests with custom boundaries.\n // Fall back to in-memory uploads when streaming is unavailable.\n if (!isNodeRuntime()) {\n const bytes = await collectBytes(data);\n return await this.uploadFile(meta, bytes);\n }\n const boundary = `opensandbox_${Math.random()\n .toString(16)\n .slice(2)}_${Date.now()}`;\n const bodyIt = multipartUploadBody({\n boundary,\n metadataJson,\n fileName,\n fileContentType: \"application/octet-stream\",\n file: data,\n });\n const stream = toReadableStream(bodyIt);\n\n const res = await this.fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": `multipart/form-data; boundary=${boundary}`,\n ...(this.opts.headers ?? {}),\n },\n body: stream as any,\n // Node fetch (undici) requires duplex for streaming request bodies.\n duplex: \"half\" as any,\n } as any);\n\n if (!res.ok) {\n const requestId = res.headers.get(\"x-request-id\") ?? undefined;\n const rawBody = await res.text().catch(() => undefined);\n throw new SandboxApiException({\n message: `Upload failed (status=${res.status})`,\n statusCode: res.status,\n requestId,\n error: new SandboxError(\n SandboxError.UNEXPECTED_RESPONSE,\n \"Upload failed\"\n ),\n rawBody,\n });\n }\n return;\n }\n\n // In-memory path (small files): use FormData.\n const form = new FormData();\n form.append(\n \"metadata\",\n new Blob([metadataJson], { type: \"application/json\" }),\n \"metadata\"\n );\n\n if (typeof data === \"string\") {\n const textBlob = new Blob([data], { type: \"text/plain; charset=utf-8\" });\n form.append(\"file\", textBlob, fileName);\n } else {\n const blob = toUploadBlob(data);\n const fileBlob = blob.type\n ? blob\n : new Blob([blob], { type: \"application/octet-stream\" });\n form.append(\"file\", fileBlob, fileName);\n }\n\n const res = await this.fetch(url, {\n method: \"POST\",\n headers: {\n ...(this.opts.headers ?? {}),\n },\n body: form,\n });\n\n if (!res.ok) {\n const requestId = res.headers.get(\"x-request-id\") ?? undefined;\n const rawBody = await res.text().catch(() => undefined);\n throw new SandboxApiException({\n message: `Upload failed (status=${res.status})`,\n statusCode: res.status,\n requestId,\n error: new SandboxError(\n SandboxError.UNEXPECTED_RESPONSE,\n \"Upload failed\"\n ),\n rawBody,\n });\n }\n }\n\n async readBytes(\n path: string,\n opts?: { range?: string }\n ): Promise<Uint8Array> {\n const url =\n joinUrl(this.opts.baseUrl, \"/files/download\") +\n `?path=${encodeURIComponent(path)}`;\n const res = await this.fetch(url, {\n method: \"GET\",\n headers: {\n ...(this.opts.headers ?? {}),\n ...(opts?.range ? { Range: opts.range } : {}),\n },\n });\n if (!res.ok) {\n const requestId = res.headers.get(\"x-request-id\") ?? undefined;\n const rawBody = await res.text().catch(() => undefined);\n throw new SandboxApiException({\n message: \"Download failed\",\n statusCode: res.status,\n requestId,\n error: new SandboxError(\n SandboxError.UNEXPECTED_RESPONSE,\n \"Download failed\"\n ),\n rawBody,\n });\n }\n const ab = await res.arrayBuffer();\n return new Uint8Array(ab);\n }\n\n readBytesStream(\n path: string,\n opts?: { range?: string }\n ): AsyncIterable<Uint8Array> {\n return this.downloadStream(path, opts);\n }\n\n private async *downloadStream(\n path: string,\n opts?: { range?: string }\n ): AsyncIterable<Uint8Array> {\n const url =\n joinUrl(this.opts.baseUrl, \"/files/download\") +\n `?path=${encodeURIComponent(path)}`;\n const res = await this.fetch(url, {\n method: \"GET\",\n headers: {\n ...(this.opts.headers ?? {}),\n ...(opts?.range ? { Range: opts.range } : {}),\n },\n });\n if (!res.ok) {\n const requestId = res.headers.get(\"x-request-id\") ?? undefined;\n const rawBody = await res.text().catch(() => undefined);\n throw new SandboxApiException({\n message: \"Download stream failed\",\n statusCode: res.status,\n requestId,\n error: new SandboxError(\n SandboxError.UNEXPECTED_RESPONSE,\n \"Download stream failed\"\n ),\n rawBody,\n });\n }\n\n const body = res.body as ReadableStream<Uint8Array> | null;\n if (!body) return;\n const reader = body.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) return;\n if (value) yield value;\n }\n }\n\n async readFile(\n path: string,\n opts?: { encoding?: string; range?: string }\n ): Promise<string> {\n const bytes = await this.readBytes(path, { range: opts?.range });\n const encoding = opts?.encoding ?? \"utf-8\";\n return new TextDecoder(encoding).decode(bytes);\n }\n\n async writeFiles(entries: WriteEntry[]): Promise<void> {\n for (const e of entries) {\n const meta: FileMetadata = {\n path: e.path,\n owner: e.owner,\n group: e.group,\n mode: e.mode,\n };\n await this.uploadFile(meta, e.data ?? \"\");\n }\n }\n}","// Copyright 2026 Alibaba Group Holding Ltd.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// \n// http://www.apache.org/licenses/LICENSE-2.0\n// \n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { ExecdClient } from \"../openapi/execdClient.js\";\nimport { throwOnOpenApiFetchError } from \"./openapiError.js\";\nimport type { ExecdHealth } from \"../services/execdHealth.js\";\n\nexport class HealthAdapter implements ExecdHealth {\n constructor(private readonly client: ExecdClient) {}\n\n async ping(): Promise<boolean> {\n const { error, response } = await this.client.GET(\"/ping\");\n throwOnOpenApiFetchError({ error, response }, \"Execd ping failed\");\n return true;\n }\n}","// Copyright 2026 Alibaba Group Holding Ltd.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// \n// http://www.apache.org/licenses/LICENSE-2.0\n// \n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { ExecdClient } from \"../openapi/execdClient.js\";\nimport { throwOnOpenApiFetchError } from \"./openapiError.js\";\nimport type { paths as ExecdPaths } from \"../api/execd.js\";\nimport type { SandboxMetrics } from \"../models/execd.js\";\nimport type { ExecdMetrics } from \"../services/execdMetrics.js\";\n\ntype ApiMetricsOk =\n ExecdPaths[\"/metrics\"][\"get\"][\"responses\"][200][\"content\"][\"application/json\"];\n\nfunction normalizeMetrics(m: ApiMetricsOk): SandboxMetrics {\n const cpuCount = m.cpu_count ?? 0;\n const cpuUsedPercentage = m.cpu_used_pct ?? 0;\n const memoryTotalMiB = m.mem_total_mib ?? 0;\n const memoryUsedMiB = m.mem_used_mib ?? 0;\n const timestamp = m.timestamp ?? 0;\n return {\n cpuCount: Number(cpuCount),\n cpuUsedPercentage: Number(cpuUsedPercentage),\n memoryTotalMiB: Number(memoryTotalMiB),\n memoryUsedMiB: Number(memoryUsedMiB),\n timestamp: Number(timestamp),\n };\n}\n\nexport class MetricsAdapter implements ExecdMetrics {\n constructor(private readonly client: ExecdClient) {}\n\n async getMetrics(): Promise<SandboxMetrics> {\n const { data, error, response } = await this.client.GET(\"/metrics\");\n throwOnOpenApiFetchError({ error, response }, \"Get execd metrics failed\");\n const ok = data as ApiMetricsOk | undefined;\n if (!ok || typeof ok !== \"object\") {\n throw new Error(\"Get execd metrics failed: unexpected response shape\");\n }\n return normalizeMetrics(ok);\n }\n}","// Copyright 2026 Alibaba Group Holding Ltd.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// \n// http://www.apache.org/licenses/LICENSE-2.0\n// \n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { LifecycleClient } from \"../openapi/lifecycleClient.js\";\nimport { throwOnOpenApiFetchError } from \"./openapiError.js\";\nimport type { paths as LifecyclePaths } from \"../api/lifecycle.js\";\nimport type {\n Sandboxes,\n} from \"../services/sandboxes.js\";\nimport type {\n CreateSandboxRequest,\n CreateSandboxResponse,\n Endpoint,\n ListSandboxesParams,\n ListSandboxesResponse,\n RenewSandboxExpirationRequest,\n RenewSandboxExpirationResponse,\n SandboxId,\n SandboxInfo,\n} from \"../models/sandboxes.js\";\n\ntype ApiCreateSandboxRequest =\n LifecyclePaths[\"/sandboxes\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"];\ntype ApiCreateSandboxOk =\n LifecyclePaths[\"/sandboxes\"][\"post\"][\"responses\"][202][\"content\"][\"application/json\"];\ntype ApiGetSandboxOk =\n LifecyclePaths[\"/sandboxes/{sandboxId}\"][\"get\"][\"responses\"][200][\"content\"][\"application/json\"];\ntype ApiListSandboxesOk =\n LifecyclePaths[\"/sandboxes\"][\"get\"][\"responses\"][200][\"content\"][\"application/json\"];\ntype ApiRenewSandboxExpirationRequest =\n LifecyclePaths[\"/sandboxes/{sandboxId}/renew-expiration\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"];\ntype ApiRenewSandboxExpirationOk =\n LifecyclePaths[\"/sandboxes/{sandboxId}/renew-expiration\"][\"post\"][\"responses\"][200][\"content\"][\"application/json\"];\ntype ApiEndpointOk =\n LifecyclePaths[\"/sandboxes/{sandboxId}/endpoints/{port}\"][\"get\"][\"responses\"][200][\"content\"][\"application/json\"];\n\nfunction encodeMetadataFilter(metadata: Record<string, string>): string {\n // The Lifecycle API expects a single `metadata` query parameter whose value is `k=v&k2=v2`.\n // The query serializer will URL-encode the value (e.g. `=` -> %3D and `&` -> %26).\n const parts: string[] = [];\n for (const [k, v] of Object.entries(metadata)) {\n parts.push(`${k}=${v}`);\n }\n return parts.join(\"&\");\n}\n\nexport class SandboxesAdapter implements Sandboxes {\n constructor(private readonly client: LifecycleClient) {}\n\n private parseIsoDate(field: string, v: unknown): Date {\n if (typeof v !== \"string\" || !v) {\n throw new Error(`Invalid ${field}: expected ISO string, got ${typeof v}`);\n }\n const d = new Date(v);\n if (Number.isNaN(d.getTime())) {\n throw new Error(`Invalid ${field}: ${v}`);\n }\n return d;\n }\n\n private mapSandboxInfo(raw: ApiGetSandboxOk): SandboxInfo {\n return {\n ...(raw ?? {}),\n createdAt: this.parseIsoDate(\"createdAt\", raw?.createdAt),\n expiresAt: this.parseIsoDate(\"expiresAt\", raw?.expiresAt),\n } as SandboxInfo;\n }\n\n async createSandbox(req: CreateSandboxRequest): Promise<CreateSandboxResponse> {\n // Make the OpenAPI contract explicit so backend schema changes surface quickly.\n const body: ApiCreateSandboxRequest = req as unknown as ApiCreateSandboxRequest;\n const { data, error, response } = await this.client.POST(\"/sandboxes\", {\n body,\n });\n throwOnOpenApiFetchError({ error, response }, \"Create sandbox failed\");\n const raw = data as ApiCreateSandboxOk | undefined;\n if (!raw || typeof raw !== \"object\") {\n throw new Error(\"Create sandbox failed: unexpected response shape\");\n }\n return {\n ...(raw ?? {}),\n createdAt: this.parseIsoDate(\"createdAt\", raw?.createdAt),\n expiresAt: this.parseIsoDate(\"expiresAt\", raw?.expiresAt),\n } as CreateSandboxResponse;\n }\n\n async getSandbox(sandboxId: SandboxId): Promise<SandboxInfo> {\n const { data, error, response } = await this.client.GET(\"/sandboxes/{sandboxId}\", {\n params: { path: { sandboxId } },\n });\n throwOnOpenApiFetchError({ error, response }, \"Get sandbox failed\");\n const ok = data as ApiGetSandboxOk | undefined;\n if (!ok || typeof ok !== \"object\") {\n throw new Error(\"Get sandbox failed: unexpected response shape\");\n }\n return this.mapSandboxInfo(ok);\n }\n\n async listSandboxes(params: ListSandboxesParams = {}): Promise<ListSandboxesResponse> {\n const query: Record<string, string | number | boolean | undefined | null | (string | number)[]> = {};\n if (params.states?.length) query.state = params.states;\n if (params.metadata && Object.keys(params.metadata).length) {\n query.metadata = encodeMetadataFilter(params.metadata);\n }\n if (params.page != null) query.page = params.page;\n if (params.pageSize != null) query.pageSize = params.pageSize;\n\n const { data, error, response } = await this.client.GET(\"/sandboxes\", {\n params: { query },\n });\n throwOnOpenApiFetchError({ error, response }, \"List sandboxes failed\");\n const raw = data as ApiListSandboxesOk | undefined;\n if (!raw || typeof raw !== \"object\") {\n throw new Error(\"List sandboxes failed: unexpected response shape\");\n }\n const itemsRaw = raw.items;\n if (!Array.isArray(itemsRaw)) throw new Error(\"List sandboxes failed: unexpected items shape\");\n return {\n ...(raw ?? {}),\n items: itemsRaw.map((x) => this.mapSandboxInfo(x)),\n } as ListSandboxesResponse;\n }\n\n async deleteSandbox(sandboxId: SandboxId): Promise<void> {\n const { error, response } = await this.client.DELETE(\"/sandboxes/{sandboxId}\", {\n params: { path: { sandboxId } },\n });\n throwOnOpenApiFetchError({ error, response }, \"Delete sandbox failed\");\n }\n\n async pauseSandbox(sandboxId: SandboxId): Promise<void> {\n const { error, response } = await this.client.POST(\"/sandboxes/{sandboxId}/pause\", {\n params: { path: { sandboxId } },\n });\n throwOnOpenApiFetchError({ error, response }, \"Pause sandbox failed\");\n }\n\n async resumeSandbox(sandboxId: SandboxId): Promise<void> {\n const { error, response } = await this.client.POST(\"/sandboxes/{sandboxId}/resume\", {\n params: { path: { sandboxId } },\n });\n throwOnOpenApiFetchError({ error, response }, \"Resume sandbox failed\");\n }\n\n async renewSandboxExpiration(\n sandboxId: SandboxId,\n req: RenewSandboxExpirationRequest,\n ): Promise<RenewSandboxExpirationResponse> {\n const body: ApiRenewSandboxExpirationRequest = req as unknown as ApiRenewSandboxExpirationRequest;\n const { data, error, response } = await this.client.POST(\"/sandboxes/{sandboxId}/renew-expiration\", {\n params: { path: { sandboxId } },\n body,\n });\n throwOnOpenApiFetchError({ error, response }, \"Renew sandbox expiration failed\");\n const raw = data as ApiRenewSandboxExpirationOk | undefined;\n if (!raw || typeof raw !== \"object\") {\n throw new Error(\"Renew sandbox expiration failed: unexpected response shape\");\n }\n return {\n ...(raw ?? {}),\n expiresAt: raw?.expiresAt ? this.parseIsoDate(\"expiresAt\", raw.expiresAt) : undefined,\n } as RenewSandboxExpirationResponse;\n }\n\n async getSandboxEndpoint(\n sandboxId: SandboxId,\n port: number,\n useServerProxy = false\n ): Promise<Endpoint> {\n const { data, error, response } = await this.client.GET(\"/sandboxes/{sandboxId}/endpoints/{port}\", {\n params: { path: { sandboxId, port }, query: { use_server_proxy: useServerProxy } },\n });\n throwOnOpenApiFetchError({ error, response }, \"Get sandbox endpoint failed\");\n const ok = data as ApiEndpointOk | undefined;\n if (!ok || typeof ok !== \"object\") {\n throw new Error(\"Get sandbox endpoint failed: unexpected response shape\");\n }\n return ok as unknown as Endpoint;\n }\n}"],"mappings":"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","names":["createClient","joinUrl","res"]}
@@ -322,11 +322,27 @@ function joinUrl(baseUrl, pathname) {
322
322
  return `${base}${path}`;
323
323
  }
324
324
  function toRunCommandRequest(command, opts) {
325
- return {
325
+ const body = {
326
326
  command,
327
327
  cwd: opts?.workingDirectory,
328
328
  background: !!opts?.background
329
329
  };
330
+ if (opts?.timeoutSeconds != null) {
331
+ body.timeout = Math.round(opts.timeoutSeconds * 1e3);
332
+ }
333
+ return body;
334
+ }
335
+ function parseOptionalDate(value, field) {
336
+ if (value == null) return void 0;
337
+ if (value instanceof Date) return value;
338
+ if (typeof value !== "string") {
339
+ throw new Error(`Invalid ${field}: expected ISO string, got ${typeof value}`);
340
+ }
341
+ const parsed = new Date(value);
342
+ if (Number.isNaN(parsed.getTime())) {
343
+ throw new Error(`Invalid ${field}: ${value}`);
344
+ }
345
+ return parsed;
330
346
  }
331
347
  var CommandsAdapter = class {
332
348
  constructor(client, opts) {
@@ -341,6 +357,42 @@ var CommandsAdapter = class {
341
357
  });
342
358
  throwOnOpenApiFetchError({ error, response }, "Interrupt command failed");
343
359
  }
360
+ async getCommandStatus(commandId) {
361
+ const { data, error, response } = await this.client.GET("/command/status/{id}", {
362
+ params: { path: { id: commandId } }
363
+ });
364
+ throwOnOpenApiFetchError({ error, response }, "Get command status failed");
365
+ const ok = data;
366
+ if (!ok || typeof ok !== "object") {
367
+ throw new Error("Get command status failed: unexpected response shape");
368
+ }
369
+ return {
370
+ id: ok.id,
371
+ content: ok.content,
372
+ running: ok.running,
373
+ exitCode: ok.exit_code ?? null,
374
+ error: ok.error,
375
+ startedAt: parseOptionalDate(ok.started_at, "startedAt"),
376
+ finishedAt: parseOptionalDate(ok.finished_at, "finishedAt") ?? null
377
+ };
378
+ }
379
+ async getBackgroundCommandLogs(commandId, cursor) {
380
+ const { data, error, response } = await this.client.GET("/command/{id}/logs", {
381
+ params: { path: { id: commandId }, query: cursor == null ? {} : { cursor } },
382
+ parseAs: "text"
383
+ });
384
+ throwOnOpenApiFetchError({ error, response }, "Get command logs failed");
385
+ const ok = data;
386
+ if (typeof ok !== "string") {
387
+ throw new Error("Get command logs failed: unexpected response shape");
388
+ }
389
+ const cursorHeader = response.headers.get("EXECD-COMMANDS-TAIL-CURSOR");
390
+ const parsedCursor = cursorHeader != null && cursorHeader !== "" ? Number(cursorHeader) : void 0;
391
+ return {
392
+ content: ok,
393
+ cursor: Number.isFinite(parsedCursor ?? NaN) ? parsedCursor : void 0
394
+ };
395
+ }
344
396
  async *runStream(command, opts, signal) {
345
397
  const url = joinUrl(this.opts.baseUrl, "/command");
346
398
  const body = JSON.stringify(toRunCommandRequest(command, opts));
@@ -950,9 +1002,9 @@ var SandboxesAdapter = class {
950
1002
  expiresAt: raw?.expiresAt ? this.parseIsoDate("expiresAt", raw.expiresAt) : void 0
951
1003
  };
952
1004
  }
953
- async getSandboxEndpoint(sandboxId, port) {
1005
+ async getSandboxEndpoint(sandboxId, port, useServerProxy = false) {
954
1006
  const { data, error, response } = await this.client.GET("/sandboxes/{sandboxId}/endpoints/{port}", {
955
- params: { path: { sandboxId, port } }
1007
+ params: { path: { sandboxId, port }, query: { use_server_proxy: useServerProxy } }
956
1008
  });
957
1009
  throwOnOpenApiFetchError({ error, response }, "Get sandbox endpoint failed");
958
1010
  const ok = data;
@@ -976,9 +1028,13 @@ var DefaultAdapterFactory = class {
976
1028
  return { sandboxes };
977
1029
  }
978
1030
  createExecdStack(opts) {
1031
+ const headers = {
1032
+ ...opts.connectionConfig.headers ?? {},
1033
+ ...opts.endpointHeaders ?? {}
1034
+ };
979
1035
  const execdClient = createExecdClient({
980
1036
  baseUrl: opts.execdBaseUrl,
981
- headers: opts.connectionConfig.headers,
1037
+ headers,
982
1038
  fetch: opts.connectionConfig.fetch
983
1039
  });
984
1040
  const health = new HealthAdapter(execdClient);
@@ -986,12 +1042,12 @@ var DefaultAdapterFactory = class {
986
1042
  const files = new FilesystemAdapter(execdClient, {
987
1043
  baseUrl: opts.execdBaseUrl,
988
1044
  fetch: opts.connectionConfig.fetch,
989
- headers: opts.connectionConfig.headers
1045
+ headers
990
1046
  });
991
1047
  const commands = new CommandsAdapter(execdClient, {
992
1048
  baseUrl: opts.execdBaseUrl,
993
1049
  fetch: opts.connectionConfig.sseFetch,
994
- headers: opts.connectionConfig.headers
1050
+ headers
995
1051
  });
996
1052
  return {
997
1053
  commands,
@@ -1016,7 +1072,7 @@ var DEFAULT_TIMEOUT_SECONDS = 600;
1016
1072
  var DEFAULT_READY_TIMEOUT_SECONDS = 30;
1017
1073
  var DEFAULT_HEALTH_CHECK_POLLING_INTERVAL_MILLIS = 200;
1018
1074
  var DEFAULT_REQUEST_TIMEOUT_SECONDS = 30;
1019
- var DEFAULT_USER_AGENT = "OpenSandbox-JS-SDK/0.1.1";
1075
+ var DEFAULT_USER_AGENT = "OpenSandbox-JS-SDK/0.1.4";
1020
1076
 
1021
1077
  // src/config/connection.ts
1022
1078
  function isNodeRuntime2() {
@@ -1168,6 +1224,10 @@ var ConnectionConfig = class _ConnectionConfig {
1168
1224
  requestTimeoutSeconds;
1169
1225
  debug;
1170
1226
  userAgent = DEFAULT_USER_AGENT;
1227
+ /**
1228
+ * Use sandbox server as proxy for endpoint requests (default false).
1229
+ */
1230
+ useServerProxy;
1171
1231
  _closeTransport;
1172
1232
  _closePromise = null;
1173
1233
  _transportInitialized = false;
@@ -1188,6 +1248,7 @@ var ConnectionConfig = class _ConnectionConfig {
1188
1248
  this.apiKey = opts.apiKey ?? envApiKey;
1189
1249
  this.requestTimeoutSeconds = typeof opts.requestTimeoutSeconds === "number" ? opts.requestTimeoutSeconds : 30;
1190
1250
  this.debug = !!opts.debug;
1251
+ this.useServerProxy = !!opts.useServerProxy;
1191
1252
  const headers = { ...opts.headers ?? {} };
1192
1253
  if (this.apiKey && !headers["OPEN-SANDBOX-API-KEY"]) {
1193
1254
  headers["OPEN-SANDBOX-API-KEY"] = this.apiKey;
@@ -1251,7 +1312,8 @@ var ConnectionConfig = class _ConnectionConfig {
1251
1312
  apiKey: this.apiKey,
1252
1313
  headers: { ...this.headers },
1253
1314
  requestTimeoutSeconds: this.requestTimeoutSeconds,
1254
- debug: this.debug
1315
+ debug: this.debug,
1316
+ useServerProxy: this.useServerProxy
1255
1317
  });
1256
1318
  clone.initializeTransport();
1257
1319
  return clone;
@@ -1390,6 +1452,21 @@ var Sandbox = class _Sandbox {
1390
1452
  await connectionConfig.closeTransport();
1391
1453
  throw err;
1392
1454
  }
1455
+ if (opts.volumes) {
1456
+ for (const vol of opts.volumes) {
1457
+ const backendsSpecified = [vol.host, vol.pvc].filter((b) => b !== void 0).length;
1458
+ if (backendsSpecified === 0) {
1459
+ throw new Error(
1460
+ `Volume '${vol.name}' must specify exactly one backend (host, pvc), but none was provided.`
1461
+ );
1462
+ }
1463
+ if (backendsSpecified > 1) {
1464
+ throw new Error(
1465
+ `Volume '${vol.name}' must specify exactly one backend (host, pvc), but multiple were provided.`
1466
+ );
1467
+ }
1468
+ }
1469
+ }
1393
1470
  const req = {
1394
1471
  image: toImageSpec(opts.image),
1395
1472
  entrypoint: opts.entrypoint ?? DEFAULT_ENTRYPOINT,
@@ -1401,6 +1478,7 @@ var Sandbox = class _Sandbox {
1401
1478
  ...opts.networkPolicy,
1402
1479
  defaultAction: opts.networkPolicy.defaultAction ?? "deny"
1403
1480
  } : void 0,
1481
+ volumes: opts.volumes,
1404
1482
  extensions: opts.extensions ?? {}
1405
1483
  };
1406
1484
  let sandboxId;
@@ -1409,12 +1487,14 @@ var Sandbox = class _Sandbox {
1409
1487
  sandboxId = created.id;
1410
1488
  const endpoint = await sandboxes.getSandboxEndpoint(
1411
1489
  sandboxId,
1412
- DEFAULT_EXECD_PORT
1490
+ DEFAULT_EXECD_PORT,
1491
+ connectionConfig.useServerProxy
1413
1492
  );
1414
1493
  const execdBaseUrl = `${connectionConfig.protocol}://${endpoint.endpoint}`;
1415
1494
  const { commands, files, health, metrics } = adapterFactory.createExecdStack({
1416
1495
  connectionConfig,
1417
- execdBaseUrl
1496
+ execdBaseUrl,
1497
+ endpointHeaders: endpoint.headers
1418
1498
  });
1419
1499
  const sbx = new _Sandbox({
1420
1500
  id: sandboxId,
@@ -1465,12 +1545,14 @@ var Sandbox = class _Sandbox {
1465
1545
  try {
1466
1546
  const endpoint = await sandboxes.getSandboxEndpoint(
1467
1547
  opts.sandboxId,
1468
- DEFAULT_EXECD_PORT
1548
+ DEFAULT_EXECD_PORT,
1549
+ connectionConfig.useServerProxy
1469
1550
  );
1470
1551
  const execdBaseUrl = `${connectionConfig.protocol}://${endpoint.endpoint}`;
1471
1552
  const { commands, files, health, metrics } = adapterFactory.createExecdStack({
1472
1553
  connectionConfig,
1473
- execdBaseUrl
1554
+ execdBaseUrl,
1555
+ endpointHeaders: endpoint.headers
1474
1556
  });
1475
1557
  const sbx = new _Sandbox({
1476
1558
  id: opts.sandboxId,
@@ -1574,7 +1656,11 @@ var Sandbox = class _Sandbox {
1574
1656
  * Get sandbox endpoint for a port (STRICT: no scheme), e.g. "localhost:44772" or "domain/route/.../44772".
1575
1657
  */
1576
1658
  async getEndpoint(port) {
1577
- return await this.sandboxes.getSandboxEndpoint(this.id, port);
1659
+ return await this.sandboxes.getSandboxEndpoint(
1660
+ this.id,
1661
+ port,
1662
+ this.connectionConfig.useServerProxy
1663
+ );
1578
1664
  }
1579
1665
  /**
1580
1666
  * Get absolute endpoint URL with scheme (convenience for HTTP clients).