@cloudflare/sandbox 0.2.4 → 0.3.1

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 (43) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/Dockerfile +9 -11
  3. package/README.md +69 -7
  4. package/container_src/control-process.ts +784 -0
  5. package/container_src/handler/exec.ts +99 -254
  6. package/container_src/handler/file.ts +179 -837
  7. package/container_src/handler/git.ts +28 -80
  8. package/container_src/handler/process.ts +443 -515
  9. package/container_src/handler/session.ts +92 -0
  10. package/container_src/index.ts +68 -130
  11. package/container_src/isolation.ts +1038 -0
  12. package/container_src/shell-escape.ts +42 -0
  13. package/container_src/types.ts +27 -13
  14. package/dist/{chunk-HHUDRGPY.js → chunk-BEQUGUY4.js} +2 -2
  15. package/dist/{chunk-CKIGERRS.js → chunk-LFLJGISB.js} +240 -264
  16. package/dist/chunk-LFLJGISB.js.map +1 -0
  17. package/dist/{chunk-3CQ6THKA.js → chunk-SMUEY5JR.js} +85 -103
  18. package/dist/chunk-SMUEY5JR.js.map +1 -0
  19. package/dist/{client-Ce40ujDF.d.ts → client-Dny_ro_v.d.ts} +41 -25
  20. package/dist/client.d.ts +1 -1
  21. package/dist/client.js +1 -1
  22. package/dist/index.d.ts +2 -2
  23. package/dist/index.js +8 -9
  24. package/dist/interpreter.d.ts +1 -1
  25. package/dist/jupyter-client.d.ts +1 -1
  26. package/dist/jupyter-client.js +2 -2
  27. package/dist/request-handler.d.ts +1 -1
  28. package/dist/request-handler.js +3 -5
  29. package/dist/sandbox.d.ts +1 -1
  30. package/dist/sandbox.js +3 -5
  31. package/dist/types.d.ts +10 -21
  32. package/dist/types.js +35 -9
  33. package/dist/types.js.map +1 -1
  34. package/package.json +2 -2
  35. package/src/client.ts +120 -135
  36. package/src/index.ts +8 -0
  37. package/src/sandbox.ts +290 -331
  38. package/src/types.ts +15 -24
  39. package/dist/chunk-3CQ6THKA.js.map +0 -1
  40. package/dist/chunk-6EWSYSO7.js +0 -46
  41. package/dist/chunk-6EWSYSO7.js.map +0 -1
  42. package/dist/chunk-CKIGERRS.js.map +0 -1
  43. /package/dist/{chunk-HHUDRGPY.js.map → chunk-BEQUGUY4.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import { ISandbox, ExecOptions, ExecResult, ProcessOptions, Process, StreamOptions, GitCheckoutResponse, MkdirResponse, WriteFileResponse, DeleteFileResponse, RenameFileResponse, MoveFileResponse, ReadFileResponse, ListFilesResponse, BaseExecOptions, ExecuteResponse, StartProcessResponse, ListProcessesResponse, GetProcessResponse, GetProcessLogsResponse } from './types.js';
1
+ import { ISandbox, ExecOptions, ExecResult, ProcessOptions, Process, StreamOptions, GitCheckoutResponse, MkdirResponse, WriteFileResponse, DeleteFileResponse, RenameFileResponse, MoveFileResponse, ReadFileResponse, ListFilesResponse, ExecutionSession, BaseExecOptions, ExecuteResponse, StartProcessResponse, ListProcessesResponse, GetProcessResponse, GetProcessLogsResponse } from './types.js';
2
2
  import { Container } from '@cloudflare/containers';
3
3
  import { CreateContextOptions, CodeContext, OutputMessage, Result, ExecutionError, RunCodeOptions, ExecutionResult } from './interpreter-types.js';
4
4
 
@@ -35,6 +35,7 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
35
35
  client: JupyterClient;
36
36
  private sandboxName;
37
37
  private codeInterpreter;
38
+ private defaultSession;
38
39
  constructor(ctx: DurableObjectState, env: Env);
39
40
  setSandboxName(name: string): Promise<void>;
40
41
  setEnvVars(envVars: Record<string, string>): Promise<void>;
@@ -43,13 +44,12 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
43
44
  onError(error: unknown): void;
44
45
  fetch(request: Request): Promise<Response>;
45
46
  private determinePort;
47
+ private ensureDefaultSession;
46
48
  exec(command: string, options?: ExecOptions): Promise<ExecResult>;
47
- private executeWithStreaming;
48
- private mapExecuteResponseToExecResult;
49
49
  startProcess(command: string, options?: ProcessOptions): Promise<Process>;
50
50
  listProcesses(): Promise<Process[]>;
51
51
  getProcess(id: string): Promise<Process | null>;
52
- killProcess(id: string, _signal?: string): Promise<void>;
52
+ killProcess(id: string, signal?: string): Promise<void>;
53
53
  killAllProcesses(): Promise<number>;
54
54
  cleanupCompletedProcesses(): Promise<number>;
55
55
  getProcessLogs(id: string): Promise<{
@@ -116,6 +116,16 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
116
116
  * Delete a code context
117
117
  */
118
118
  deleteCodeContext(contextId: string): Promise<void>;
119
+ /**
120
+ * Create a new execution session with isolation
121
+ * Returns a session object with exec() method
122
+ */
123
+ createSession(options: {
124
+ id?: string;
125
+ env?: Record<string, string>;
126
+ cwd?: string;
127
+ isolation?: boolean;
128
+ }): Promise<ExecutionSession>;
119
129
  }
120
130
 
121
131
  interface PreviewInfo {
@@ -156,52 +166,58 @@ interface HttpClientOptions {
156
166
  declare class HttpClient {
157
167
  private baseUrl;
158
168
  private options;
159
- private sessionId;
160
169
  constructor(options?: HttpClientOptions);
161
170
  protected doFetch(path: string, options?: RequestInit): Promise<Response>;
162
- execute(command: string, options: Pick<BaseExecOptions, "sessionId" | "cwd" | "env">): Promise<ExecuteResponse>;
163
- executeCommandStream(command: string, sessionId?: string): Promise<ReadableStream<Uint8Array>>;
164
- gitCheckout(repoUrl: string, branch?: string, targetDir?: string, sessionId?: string): Promise<GitCheckoutResponse>;
165
- mkdir(path: string, recursive?: boolean, sessionId?: string): Promise<MkdirResponse>;
166
- writeFile(path: string, content: string, encoding?: string, sessionId?: string): Promise<WriteFileResponse>;
167
- readFile(path: string, encoding?: string, sessionId?: string): Promise<ReadFileResponse>;
168
- deleteFile(path: string, sessionId?: string): Promise<DeleteFileResponse>;
169
- renameFile(oldPath: string, newPath: string, sessionId?: string): Promise<RenameFileResponse>;
170
- moveFile(sourcePath: string, destinationPath: string, sessionId?: string): Promise<MoveFileResponse>;
171
- listFiles(path: string, options?: {
171
+ createSession(options: {
172
+ id: string;
173
+ env?: Record<string, string>;
174
+ cwd?: string;
175
+ isolation?: boolean;
176
+ }): Promise<{
177
+ success: boolean;
178
+ id: string;
179
+ message: string;
180
+ }>;
181
+ exec(sessionId: string, command: string, options?: Pick<BaseExecOptions, "cwd" | "env">): Promise<ExecuteResponse>;
182
+ execStream(sessionId: string, command: string): Promise<ReadableStream<Uint8Array>>;
183
+ gitCheckout(repoUrl: string, sessionId: string, branch?: string, targetDir?: string): Promise<GitCheckoutResponse>;
184
+ mkdir(path: string, recursive: boolean | undefined, sessionId: string): Promise<MkdirResponse>;
185
+ writeFile(path: string, content: string, encoding: string | undefined, sessionId: string): Promise<WriteFileResponse>;
186
+ readFile(path: string, encoding: string | undefined, sessionId: string): Promise<ReadFileResponse>;
187
+ deleteFile(path: string, sessionId: string): Promise<DeleteFileResponse>;
188
+ renameFile(oldPath: string, newPath: string, sessionId: string): Promise<RenameFileResponse>;
189
+ moveFile(sourcePath: string, destinationPath: string, sessionId: string): Promise<MoveFileResponse>;
190
+ listFiles(path: string, sessionId: string, options?: {
172
191
  recursive?: boolean;
173
192
  includeHidden?: boolean;
174
- }, sessionId?: string): Promise<ListFilesResponse>;
193
+ }): Promise<ListFilesResponse>;
175
194
  exposePort(port: number, name?: string): Promise<ExposePortResponse>;
176
195
  unexposePort(port: number): Promise<UnexposePortResponse>;
177
196
  getExposedPorts(): Promise<GetExposedPortsResponse>;
178
197
  ping(): Promise<string>;
179
- getCommands(): Promise<string[]>;
180
- getSessionId(): string | null;
181
- setSessionId(sessionId: string): void;
182
- clearSession(): void;
183
- startProcess(command: string, options?: {
198
+ startProcess(command: string, sessionId: string, options?: {
184
199
  processId?: string;
185
- sessionId?: string;
186
200
  timeout?: number;
187
201
  env?: Record<string, string>;
188
202
  cwd?: string;
189
203
  encoding?: string;
190
204
  autoCleanup?: boolean;
191
205
  }): Promise<StartProcessResponse>;
192
- listProcesses(): Promise<ListProcessesResponse>;
206
+ listProcesses(sessionId?: string): Promise<ListProcessesResponse>;
193
207
  getProcess(processId: string): Promise<GetProcessResponse>;
194
208
  killProcess(processId: string): Promise<{
195
209
  success: boolean;
196
210
  message: string;
197
211
  }>;
198
- killAllProcesses(): Promise<{
212
+ killAllProcesses(sessionId?: string): Promise<{
199
213
  success: boolean;
200
214
  killedCount: number;
201
215
  message: string;
202
216
  }>;
203
217
  getProcessLogs(processId: string): Promise<GetProcessLogsResponse>;
204
- streamProcessLogs(processId: string): Promise<ReadableStream<Uint8Array>>;
218
+ streamProcessLogs(processId: string, options?: {
219
+ signal?: AbortSignal;
220
+ }): Promise<ReadableStream<Uint8Array>>;
205
221
  }
206
222
 
207
223
  export { type ExecutionCallbacks as E, HttpClient as H, JupyterClient as J, Sandbox as S, getSandbox as g };
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { H as HttpClient } from './client-Ce40ujDF.js';
1
+ export { H as HttpClient } from './client-Dny_ro_v.js';
2
2
  import './types.js';
3
3
  import '@cloudflare/containers';
4
4
  import './interpreter-types.js';
package/dist/client.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  HttpClient
3
- } from "./chunk-3CQ6THKA.js";
3
+ } from "./chunk-SMUEY5JR.js";
4
4
  export {
5
5
  HttpClient
6
6
  };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { CodeExecutionError, ContainerNotReadyError, ContextNotFoundError, JupyterNotReadyError, SandboxError, SandboxErrorResponse, SandboxNetworkError, ServiceUnavailableError, isJupyterNotReadyError, isRetryableError, isSandboxError, parseErrorResponse } from './errors.js';
2
2
  export { ChartData, CodeContext, CreateContextOptions, Execution, ExecutionError, OutputMessage, Result, ResultImpl, RunCodeOptions } from './interpreter-types.js';
3
3
  export { RouteInfo, SandboxEnv, proxyToSandbox } from './request-handler.js';
4
- export { S as Sandbox, g as getSandbox } from './client-Ce40ujDF.js';
4
+ export { S as Sandbox, g as getSandbox } from './client-Dny_ro_v.js';
5
5
  export { asyncIterableToSSEStream, parseSSEStream, responseToAsyncIterable } from './sse-parser.js';
6
- export { DeleteFileResponse, ExecEvent, ExecuteResponse, GitCheckoutResponse, ListFilesResponse, LogEvent, MkdirResponse, MoveFileResponse, ReadFileResponse, RenameFileResponse, WriteFileResponse } from './types.js';
6
+ export { DeleteFileResponse, ExecEvent, ExecOptions, ExecResult, ExecuteResponse, ExecutionSession, GitCheckoutResponse, ISandbox, ListFilesResponse, LogEvent, MkdirResponse, MoveFileResponse, Process, ProcessOptions, ProcessStatus, ReadFileResponse, RenameFileResponse, StreamOptions, WriteFileResponse } from './types.js';
7
7
  import '@cloudflare/containers';
package/dist/index.js CHANGED
@@ -1,21 +1,20 @@
1
- import {
2
- Sandbox,
3
- getSandbox,
4
- proxyToSandbox
5
- } from "./chunk-CKIGERRS.js";
6
- import "./chunk-6UAWTJ5S.js";
7
1
  import {
8
2
  asyncIterableToSSEStream,
9
3
  parseSSEStream,
10
4
  responseToAsyncIterable
11
5
  } from "./chunk-NNGBXDMY.js";
12
- import "./chunk-6EWSYSO7.js";
6
+ import {
7
+ Sandbox,
8
+ getSandbox,
9
+ proxyToSandbox
10
+ } from "./chunk-LFLJGISB.js";
11
+ import "./chunk-6UAWTJ5S.js";
13
12
  import "./chunk-FKBV7CZS.js";
14
13
  import {
15
14
  ResultImpl
16
15
  } from "./chunk-EGC5IYXA.js";
17
- import "./chunk-HHUDRGPY.js";
18
- import "./chunk-3CQ6THKA.js";
16
+ import "./chunk-BEQUGUY4.js";
17
+ import "./chunk-SMUEY5JR.js";
19
18
  import {
20
19
  CodeExecutionError,
21
20
  ContainerNotReadyError,
@@ -1,5 +1,5 @@
1
1
  import { CreateContextOptions, CodeContext, RunCodeOptions, Execution } from './interpreter-types.js';
2
- import { S as Sandbox } from './client-Ce40ujDF.js';
2
+ import { S as Sandbox } from './client-Dny_ro_v.js';
3
3
  import './types.js';
4
4
  import '@cloudflare/containers';
5
5
 
@@ -1,4 +1,4 @@
1
- export { E as ExecutionCallbacks, J as JupyterClient } from './client-Ce40ujDF.js';
1
+ export { E as ExecutionCallbacks, J as JupyterClient } from './client-Dny_ro_v.js';
2
2
  import './interpreter-types.js';
3
3
  import './types.js';
4
4
  import '@cloudflare/containers';
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  JupyterClient
3
- } from "./chunk-HHUDRGPY.js";
4
- import "./chunk-3CQ6THKA.js";
3
+ } from "./chunk-BEQUGUY4.js";
4
+ import "./chunk-SMUEY5JR.js";
5
5
  import "./chunk-LALY4SFU.js";
6
6
  export {
7
7
  JupyterClient
@@ -1,4 +1,4 @@
1
- import { S as Sandbox } from './client-Ce40ujDF.js';
1
+ import { S as Sandbox } from './client-Dny_ro_v.js';
2
2
  import './types.js';
3
3
  import './interpreter-types.js';
4
4
  import '@cloudflare/containers';
@@ -1,14 +1,12 @@
1
1
  import {
2
2
  isLocalhostPattern,
3
3
  proxyToSandbox
4
- } from "./chunk-CKIGERRS.js";
4
+ } from "./chunk-LFLJGISB.js";
5
5
  import "./chunk-6UAWTJ5S.js";
6
- import "./chunk-NNGBXDMY.js";
7
- import "./chunk-6EWSYSO7.js";
8
6
  import "./chunk-FKBV7CZS.js";
9
7
  import "./chunk-EGC5IYXA.js";
10
- import "./chunk-HHUDRGPY.js";
11
- import "./chunk-3CQ6THKA.js";
8
+ import "./chunk-BEQUGUY4.js";
9
+ import "./chunk-SMUEY5JR.js";
12
10
  import "./chunk-LALY4SFU.js";
13
11
  export {
14
12
  isLocalhostPattern,
package/dist/sandbox.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import './types.js';
2
2
  import '@cloudflare/containers';
3
3
  import './interpreter-types.js';
4
- export { S as Sandbox, g as getSandbox } from './client-Ce40ujDF.js';
4
+ export { S as Sandbox, g as getSandbox } from './client-Dny_ro_v.js';
package/dist/sandbox.js CHANGED
@@ -1,14 +1,12 @@
1
1
  import {
2
2
  Sandbox,
3
3
  getSandbox
4
- } from "./chunk-CKIGERRS.js";
4
+ } from "./chunk-LFLJGISB.js";
5
5
  import "./chunk-6UAWTJ5S.js";
6
- import "./chunk-NNGBXDMY.js";
7
- import "./chunk-6EWSYSO7.js";
8
6
  import "./chunk-FKBV7CZS.js";
9
7
  import "./chunk-EGC5IYXA.js";
10
- import "./chunk-HHUDRGPY.js";
11
- import "./chunk-3CQ6THKA.js";
8
+ import "./chunk-BEQUGUY4.js";
9
+ import "./chunk-SMUEY5JR.js";
12
10
  import "./chunk-LALY4SFU.js";
13
11
  export {
14
12
  Sandbox,
package/dist/types.d.ts CHANGED
@@ -1,10 +1,6 @@
1
1
  import { CreateContextOptions, CodeContext, RunCodeOptions, ExecutionResult } from './interpreter-types.js';
2
2
 
3
3
  interface BaseExecOptions {
4
- /**
5
- * Session ID for grouping related commands
6
- */
7
- sessionId?: string;
8
4
  /**
9
5
  * Maximum execution time in milliseconds
10
6
  */
@@ -73,10 +69,6 @@ interface ExecResult {
73
69
  * ISO timestamp when command started
74
70
  */
75
71
  timestamp: string;
76
- /**
77
- * Session ID if provided
78
- */
79
- sessionId?: string;
80
72
  }
81
73
  interface ProcessOptions extends BaseExecOptions {
82
74
  /**
@@ -135,10 +127,6 @@ interface Process {
135
127
  * Process exit code (if completed)
136
128
  */
137
129
  readonly exitCode?: number;
138
- /**
139
- * Session ID if provided
140
- */
141
- readonly sessionId?: string;
142
130
  /**
143
131
  * Kill the process
144
132
  */
@@ -163,14 +151,12 @@ interface ExecEvent {
163
151
  exitCode?: number;
164
152
  result?: ExecResult;
165
153
  error?: string;
166
- sessionId?: string;
167
154
  }
168
155
  interface LogEvent {
169
156
  type: 'stdout' | 'stderr' | 'exit' | 'error';
170
157
  timestamp: string;
171
158
  data: string;
172
159
  processId: string;
173
- sessionId?: string;
174
160
  exitCode?: number;
175
161
  }
176
162
  interface StreamOptions extends BaseExecOptions {
@@ -204,8 +190,6 @@ interface ProcessRecord {
204
190
  startTime: Date;
205
191
  endTime?: Date;
206
192
  exitCode?: number;
207
- sessionId?: string;
208
- childProcess?: any;
209
193
  stdout: string;
210
194
  stderr: string;
211
195
  outputListeners: Set<(stream: 'stdout' | 'stderr', data: string) => void>;
@@ -215,7 +199,6 @@ interface StartProcessRequest {
215
199
  command: string;
216
200
  options?: {
217
201
  processId?: string;
218
- sessionId?: string;
219
202
  timeout?: number;
220
203
  env?: Record<string, string>;
221
204
  cwd?: string;
@@ -230,7 +213,9 @@ interface StartProcessResponse {
230
213
  command: string;
231
214
  status: ProcessStatus;
232
215
  startTime: string;
233
- sessionId?: string;
216
+ endTime?: string | null;
217
+ exitCode?: number | null;
218
+ sessionId: string;
234
219
  };
235
220
  }
236
221
  interface ListProcessesResponse {
@@ -242,7 +227,6 @@ interface ListProcessesResponse {
242
227
  startTime: string;
243
228
  endTime?: string;
244
229
  exitCode?: number;
245
- sessionId?: string;
246
230
  }>;
247
231
  }
248
232
  interface GetProcessResponse {
@@ -254,7 +238,6 @@ interface GetProcessResponse {
254
238
  startTime: string;
255
239
  endTime?: string;
256
240
  exitCode?: number;
257
- sessionId?: string;
258
241
  } | null;
259
242
  }
260
243
  interface GetProcessLogsResponse {
@@ -322,6 +305,12 @@ interface ISandbox {
322
305
  listCodeContexts(): Promise<CodeContext[]>;
323
306
  deleteCodeContext(contextId: string): Promise<void>;
324
307
  }
308
+ interface ExecutionSession extends Omit<ISandbox, 'createSession' | 'setSandboxName'> {
309
+ /**
310
+ * Session ID
311
+ */
312
+ id: string;
313
+ }
325
314
  interface ExecuteResponse {
326
315
  success: boolean;
327
316
  stdout: string;
@@ -406,4 +395,4 @@ declare function isExecResult(value: any): value is ExecResult;
406
395
  declare function isProcess(value: any): value is Process;
407
396
  declare function isProcessStatus(value: string): value is ProcessStatus;
408
397
 
409
- export { type BaseExecOptions, type DeleteFileResponse, type ExecEvent, type ExecOptions, type ExecResult, type ExecuteResponse, ExecutionTimeoutError, type GetProcessLogsResponse, type GetProcessResponse, type GitCheckoutResponse, type ISandbox, type ListFilesResponse, type ListProcessesResponse, type LogEvent, type MkdirResponse, type MoveFileResponse, type Process, ProcessAlreadyExistsError, ProcessNotFoundError, type ProcessOptions, type ProcessRecord, type ProcessStatus, type ReadFileResponse, type RenameFileResponse, SandboxError, type StartProcessRequest, type StartProcessResponse, type StreamOptions, type WriteFileResponse, isExecResult, isProcess, isProcessStatus };
398
+ export { type BaseExecOptions, type DeleteFileResponse, type ExecEvent, type ExecOptions, type ExecResult, type ExecuteResponse, type ExecutionSession, ExecutionTimeoutError, type GetProcessLogsResponse, type GetProcessResponse, type GitCheckoutResponse, type ISandbox, type ListFilesResponse, type ListProcessesResponse, type LogEvent, type MkdirResponse, type MoveFileResponse, type Process, ProcessAlreadyExistsError, ProcessNotFoundError, type ProcessOptions, type ProcessRecord, type ProcessStatus, type ReadFileResponse, type RenameFileResponse, SandboxError, type StartProcessRequest, type StartProcessResponse, type StreamOptions, type WriteFileResponse, isExecResult, isProcess, isProcessStatus };
package/dist/types.js CHANGED
@@ -1,12 +1,38 @@
1
- import {
2
- ExecutionTimeoutError,
3
- ProcessAlreadyExistsError,
4
- ProcessNotFoundError,
5
- SandboxError,
6
- isExecResult,
7
- isProcess,
8
- isProcessStatus
9
- } from "./chunk-6EWSYSO7.js";
1
+ // src/types.ts
2
+ var SandboxError = class extends Error {
3
+ constructor(message, code) {
4
+ super(message);
5
+ this.code = code;
6
+ this.name = "SandboxError";
7
+ }
8
+ };
9
+ var ProcessNotFoundError = class extends SandboxError {
10
+ constructor(processId) {
11
+ super(`Process not found: ${processId}`, "PROCESS_NOT_FOUND");
12
+ this.name = "ProcessNotFoundError";
13
+ }
14
+ };
15
+ var ProcessAlreadyExistsError = class extends SandboxError {
16
+ constructor(processId) {
17
+ super(`Process already exists: ${processId}`, "PROCESS_EXISTS");
18
+ this.name = "ProcessAlreadyExistsError";
19
+ }
20
+ };
21
+ var ExecutionTimeoutError = class extends SandboxError {
22
+ constructor(timeout) {
23
+ super(`Execution timed out after ${timeout}ms`, "EXECUTION_TIMEOUT");
24
+ this.name = "ExecutionTimeoutError";
25
+ }
26
+ };
27
+ function isExecResult(value) {
28
+ return value && typeof value.success === "boolean" && typeof value.exitCode === "number" && typeof value.stdout === "string" && typeof value.stderr === "string";
29
+ }
30
+ function isProcess(value) {
31
+ return value && typeof value.id === "string" && typeof value.command === "string" && typeof value.status === "string";
32
+ }
33
+ function isProcessStatus(value) {
34
+ return ["starting", "running", "completed", "failed", "killed", "error"].includes(value);
35
+ }
10
36
  export {
11
37
  ExecutionTimeoutError,
12
38
  ProcessAlreadyExistsError,
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["// Core Types\n\nexport interface BaseExecOptions {\n /**\n * Maximum execution time in milliseconds\n */\n timeout?: number;\n\n /**\n * Environment variables for the command\n */\n env?: Record<string, string>;\n\n /**\n * Working directory for command execution\n */\n cwd?: string;\n\n /**\n * Text encoding for output (default: 'utf8')\n */\n encoding?: string;\n}\n\nexport interface ExecOptions extends BaseExecOptions {\n /**\n * Enable real-time output streaming via callbacks\n */\n stream?: boolean;\n\n /**\n * Callback for real-time output data\n */\n onOutput?: (stream: 'stdout' | 'stderr', data: string) => void;\n\n /**\n * Callback when command completes (only when stream: true)\n */\n onComplete?: (result: ExecResult) => void;\n\n /**\n * Callback for execution errors\n */\n onError?: (error: Error) => void;\n\n /**\n * AbortSignal for cancelling execution\n */\n signal?: AbortSignal;\n}\n\nexport interface ExecResult {\n /**\n * Whether the command succeeded (exitCode === 0)\n */\n success: boolean;\n\n /**\n * Process exit code\n */\n exitCode: number;\n\n /**\n * Standard output content\n */\n stdout: string;\n\n /**\n * Standard error content\n */\n stderr: string;\n\n /**\n * Command that was executed\n */\n command: string;\n\n\n /**\n * Execution duration in milliseconds\n */\n duration: number;\n\n /**\n * ISO timestamp when command started\n */\n timestamp: string;\n}\n\n// Background Process Types\n\nexport interface ProcessOptions extends BaseExecOptions {\n /**\n * Custom process ID for later reference\n * If not provided, a UUID will be generated\n */\n processId?: string;\n\n /**\n * Automatically cleanup process record after exit (default: true)\n */\n autoCleanup?: boolean;\n\n /**\n * Callback when process exits\n */\n onExit?: (code: number | null) => void;\n\n /**\n * Callback for real-time output (background processes)\n */\n onOutput?: (stream: 'stdout' | 'stderr', data: string) => void;\n\n /**\n * Callback when process starts successfully\n */\n onStart?: (process: Process) => void;\n\n /**\n * Callback for process errors\n */\n onError?: (error: Error) => void;\n}\n\nexport type ProcessStatus =\n | 'starting' // Process is being initialized\n | 'running' // Process is actively running\n | 'completed' // Process exited successfully (code 0)\n | 'failed' // Process exited with non-zero code\n | 'killed' // Process was terminated by signal\n | 'error'; // Process failed to start or encountered error\n\nexport interface Process {\n /**\n * Unique process identifier\n */\n readonly id: string;\n\n /**\n * System process ID (if available and running)\n */\n readonly pid?: number;\n\n /**\n * Command that was executed\n */\n readonly command: string;\n\n\n /**\n * Current process status\n */\n readonly status: ProcessStatus;\n\n /**\n * When the process was started\n */\n readonly startTime: Date;\n\n /**\n * When the process ended (if completed)\n */\n readonly endTime?: Date;\n\n /**\n * Process exit code (if completed)\n */\n readonly exitCode?: number;\n\n /**\n * Kill the process\n */\n kill(signal?: string): Promise<void>;\n\n /**\n * Get current process status (refreshed)\n */\n getStatus(): Promise<ProcessStatus>;\n\n /**\n * Get accumulated logs\n */\n getLogs(): Promise<{ stdout: string; stderr: string }>;\n}\n\n// Streaming Types\n\nexport interface ExecEvent {\n type: 'start' | 'stdout' | 'stderr' | 'complete' | 'error';\n timestamp: string;\n data?: string;\n command?: string;\n exitCode?: number;\n result?: ExecResult;\n error?: string; // Changed to string for serialization\n}\n\nexport interface LogEvent {\n type: 'stdout' | 'stderr' | 'exit' | 'error';\n timestamp: string;\n data: string;\n processId: string;\n exitCode?: number; // For 'exit' events\n}\n\nexport interface StreamOptions extends BaseExecOptions {\n /**\n * Buffer size for streaming output\n */\n bufferSize?: number;\n\n /**\n * AbortSignal for cancelling stream\n */\n signal?: AbortSignal;\n}\n\n// Error Types\n\nexport class SandboxError extends Error {\n constructor(message: string, public code?: string) {\n super(message);\n this.name = 'SandboxError';\n }\n}\n\nexport class ProcessNotFoundError extends SandboxError {\n constructor(processId: string) {\n super(`Process not found: ${processId}`, 'PROCESS_NOT_FOUND');\n this.name = 'ProcessNotFoundError';\n }\n}\n\nexport class ProcessAlreadyExistsError extends SandboxError {\n constructor(processId: string) {\n super(`Process already exists: ${processId}`, 'PROCESS_EXISTS');\n this.name = 'ProcessAlreadyExistsError';\n }\n}\n\nexport class ExecutionTimeoutError extends SandboxError {\n constructor(timeout: number) {\n super(`Execution timed out after ${timeout}ms`, 'EXECUTION_TIMEOUT');\n this.name = 'ExecutionTimeoutError';\n }\n}\n\n// Internal Container Types\n\nexport interface ProcessRecord {\n id: string;\n pid?: number;\n command: string;\n status: ProcessStatus;\n startTime: Date;\n endTime?: Date;\n exitCode?: number;\n\n // Internal fields\n stdout: string; // Accumulated output (ephemeral)\n stderr: string; // Accumulated output (ephemeral)\n\n // Streaming\n outputListeners: Set<(stream: 'stdout' | 'stderr', data: string) => void>;\n statusListeners: Set<(status: ProcessStatus) => void>;\n}\n\n// Container Request/Response Types\n\nexport interface StartProcessRequest {\n command: string;\n options?: {\n processId?: string;\n timeout?: number;\n env?: Record<string, string>;\n cwd?: string;\n encoding?: string;\n autoCleanup?: boolean;\n };\n}\n\nexport interface StartProcessResponse {\n process: {\n id: string;\n pid?: number;\n command: string;\n status: ProcessStatus;\n startTime: string;\n endTime?: string | null;\n exitCode?: number | null;\n sessionId: string;\n };\n}\n\nexport interface ListProcessesResponse {\n processes: Array<{\n id: string;\n pid?: number;\n command: string;\n status: ProcessStatus;\n startTime: string;\n endTime?: string;\n exitCode?: number;\n }>;\n}\n\nexport interface GetProcessResponse {\n process: {\n id: string;\n pid?: number;\n command: string;\n status: ProcessStatus;\n startTime: string;\n endTime?: string;\n exitCode?: number;\n } | null;\n}\n\nexport interface GetProcessLogsResponse {\n stdout: string;\n stderr: string;\n processId: string;\n}\n\n// Import code interpreter types\nimport type {\n CodeContext,\n CreateContextOptions,\n ExecutionResult, \n RunCodeOptions\n} from './interpreter-types';\n\n// Main Sandbox Interface\n\nexport interface ISandbox {\n // Enhanced execution API\n exec(command: string, options?: ExecOptions): Promise<ExecResult>;\n\n // Background process management\n startProcess(command: string, options?: ProcessOptions): Promise<Process>;\n listProcesses(): Promise<Process[]>;\n getProcess(id: string): Promise<Process | null>;\n killProcess(id: string, signal?: string): Promise<void>;\n killAllProcesses(): Promise<number>;\n\n // Advanced streaming - returns ReadableStream that can be converted to AsyncIterable\n execStream(command: string, options?: StreamOptions): Promise<ReadableStream<Uint8Array>>;\n streamProcessLogs(processId: string, options?: { signal?: AbortSignal }): Promise<ReadableStream<Uint8Array>>;\n\n // Utility methods\n cleanupCompletedProcesses(): Promise<number>;\n getProcessLogs(id: string): Promise<{ stdout: string; stderr: string }>;\n\n // File operations\n gitCheckout(repoUrl: string, options: { branch?: string; targetDir?: string }): Promise<GitCheckoutResponse>;\n mkdir(path: string, options?: { recursive?: boolean }): Promise<MkdirResponse>;\n writeFile(path: string, content: string, options?: { encoding?: string }): Promise<WriteFileResponse>;\n deleteFile(path: string): Promise<DeleteFileResponse>;\n renameFile(oldPath: string, newPath: string): Promise<RenameFileResponse>;\n moveFile(sourcePath: string, destinationPath: string): Promise<MoveFileResponse>;\n readFile(path: string, options?: { encoding?: string }): Promise<ReadFileResponse>;\n listFiles(path: string, options?: { recursive?: boolean; includeHidden?: boolean }): Promise<ListFilesResponse>;\n\n // Port management\n exposePort(port: number, options: { name?: string; hostname: string }): Promise<{ url: string; port: number; name?: string }>;\n unexposePort(port: number): Promise<void>;\n getExposedPorts(hostname: string): Promise<Array<{ url: string; port: number; name?: string; exposedAt: string }>>;\n\n // Environment management\n setEnvVars(envVars: Record<string, string>): Promise<void>;\n setSandboxName(name: string): Promise<void>;\n\n // Code Interpreter API\n createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;\n runCode(code: string, options?: RunCodeOptions): Promise<ExecutionResult>;\n runCodeStream(code: string, options?: RunCodeOptions): Promise<ReadableStream>;\n listCodeContexts(): Promise<CodeContext[]>;\n deleteCodeContext(contextId: string): Promise<void>;\n}\n\n// Execution session returned by createSession()\n// Sessions are full-featured sandbox objects with scoped execution context\n// Inherits all ISandbox methods except createSession (sessions can't create sub-sessions),\n// and setSandboxName (sessions inherit sandbox name).\nexport interface ExecutionSession extends Omit<ISandbox, 'createSession' | 'setSandboxName'> {\n /**\n * Session ID\n */\n id: string;\n}\n\n// API Response Types\n\nexport interface ExecuteResponse {\n success: boolean;\n stdout: string;\n stderr: string;\n exitCode: number;\n command: string;\n timestamp: string;\n}\n\nexport interface GitCheckoutResponse {\n success: boolean;\n stdout: string;\n stderr: string;\n exitCode: number;\n repoUrl: string;\n branch: string;\n targetDir: string;\n timestamp: string;\n}\n\nexport interface MkdirResponse {\n success: boolean;\n stdout: string;\n stderr: string;\n exitCode: number;\n path: string;\n recursive: boolean;\n timestamp: string;\n}\n\nexport interface WriteFileResponse {\n success: boolean;\n exitCode: number;\n path: string;\n timestamp: string;\n}\n\nexport interface ReadFileResponse {\n success: boolean;\n exitCode: number;\n path: string;\n content: string;\n timestamp: string;\n}\n\nexport interface DeleteFileResponse {\n success: boolean;\n exitCode: number;\n path: string;\n timestamp: string;\n}\n\nexport interface RenameFileResponse {\n success: boolean;\n exitCode: number;\n oldPath: string;\n newPath: string;\n timestamp: string;\n}\n\nexport interface MoveFileResponse {\n success: boolean;\n exitCode: number;\n sourcePath: string;\n destinationPath: string;\n timestamp: string;\n}\n\nexport interface ListFilesResponse {\n success: boolean;\n exitCode: number;\n path: string;\n files: Array<{\n name: string;\n absolutePath: string;\n relativePath: string;\n type: 'file' | 'directory' | 'symlink' | 'other';\n size: number;\n modifiedAt: string;\n mode: string;\n permissions: {\n readable: boolean;\n writable: boolean;\n executable: boolean;\n };\n }>;\n timestamp: string;\n}\n\n// Type Guards\n\nexport function isExecResult(value: any): value is ExecResult {\n return value &&\n typeof value.success === 'boolean' &&\n typeof value.exitCode === 'number' &&\n typeof value.stdout === 'string' &&\n typeof value.stderr === 'string';\n}\n\nexport function isProcess(value: any): value is Process {\n return value &&\n typeof value.id === 'string' &&\n typeof value.command === 'string' &&\n typeof value.status === 'string';\n}\n\nexport function isProcessStatus(value: string): value is ProcessStatus {\n return ['starting', 'running', 'completed', 'failed', 'killed', 'error'].includes(value);\n}"],"mappings":";AA2NO,IAAM,eAAN,cAA2B,MAAM;AAAA,EACtC,YAAY,SAAwB,MAAe;AACjD,UAAM,OAAO;AADqB;AAElC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,uBAAN,cAAmC,aAAa;AAAA,EACrD,YAAY,WAAmB;AAC7B,UAAM,sBAAsB,SAAS,IAAI,mBAAmB;AAC5D,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,4BAAN,cAAwC,aAAa;AAAA,EAC1D,YAAY,WAAmB;AAC7B,UAAM,2BAA2B,SAAS,IAAI,gBAAgB;AAC9D,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,wBAAN,cAAoC,aAAa;AAAA,EACtD,YAAY,SAAiB;AAC3B,UAAM,6BAA6B,OAAO,MAAM,mBAAmB;AACnE,SAAK,OAAO;AAAA,EACd;AACF;AA+OO,SAAS,aAAa,OAAiC;AAC5D,SAAO,SACL,OAAO,MAAM,YAAY,aACzB,OAAO,MAAM,aAAa,YAC1B,OAAO,MAAM,WAAW,YACxB,OAAO,MAAM,WAAW;AAC5B;AAEO,SAAS,UAAU,OAA8B;AACtD,SAAO,SACL,OAAO,MAAM,OAAO,YACpB,OAAO,MAAM,YAAY,YACzB,OAAO,MAAM,WAAW;AAC5B;AAEO,SAAS,gBAAgB,OAAuC;AACrE,SAAO,CAAC,YAAY,WAAW,aAAa,UAAU,UAAU,OAAO,EAAE,SAAS,KAAK;AACzF;","names":[]}
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@cloudflare/sandbox",
3
- "version": "0.2.4",
3
+ "version": "0.3.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/cloudflare/sandbox-sdk"
7
7
  },
8
8
  "description": "A sandboxed environment for running commands",
9
9
  "dependencies": {
10
- "@cloudflare/containers": "^0.0.25"
10
+ "@cloudflare/containers": "^0.0.27"
11
11
  },
12
12
  "tags": [
13
13
  "sandbox",