@cloudflare/sandbox 0.3.6 → 0.4.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 (120) hide show
  1. package/.turbo/turbo-build.log +44 -0
  2. package/CHANGELOG.md +6 -8
  3. package/Dockerfile +88 -18
  4. package/README.md +89 -824
  5. package/dist/{chunk-JTKON2SH.js → chunk-BCJ7SF3Q.js} +9 -5
  6. package/dist/chunk-BCJ7SF3Q.js.map +1 -0
  7. package/dist/chunk-BFVUNTP4.js +104 -0
  8. package/dist/chunk-BFVUNTP4.js.map +1 -0
  9. package/dist/{chunk-NNGBXDMY.js → chunk-EKSWCBCA.js} +3 -6
  10. package/dist/chunk-EKSWCBCA.js.map +1 -0
  11. package/dist/chunk-HGF554LH.js +2236 -0
  12. package/dist/chunk-HGF554LH.js.map +1 -0
  13. package/dist/{chunk-6UAWTJ5S.js → chunk-Z532A7QC.js} +13 -20
  14. package/dist/{chunk-6UAWTJ5S.js.map → chunk-Z532A7QC.js.map} +1 -1
  15. package/dist/file-stream.d.ts +16 -38
  16. package/dist/file-stream.js +1 -2
  17. package/dist/index.d.ts +6 -5
  18. package/dist/index.js +35 -39
  19. package/dist/index.js.map +1 -1
  20. package/dist/interpreter.d.ts +3 -3
  21. package/dist/interpreter.js +2 -2
  22. package/dist/request-handler.d.ts +4 -3
  23. package/dist/request-handler.js +4 -7
  24. package/dist/sandbox-D9K2ypln.d.ts +583 -0
  25. package/dist/sandbox.d.ts +3 -3
  26. package/dist/sandbox.js +4 -7
  27. package/dist/security.d.ts +4 -3
  28. package/dist/security.js +3 -3
  29. package/dist/sse-parser.js +1 -1
  30. package/package.json +11 -5
  31. package/src/clients/base-client.ts +280 -0
  32. package/src/clients/command-client.ts +115 -0
  33. package/src/clients/file-client.ts +269 -0
  34. package/src/clients/git-client.ts +92 -0
  35. package/src/clients/index.ts +63 -0
  36. package/src/{interpreter-client.ts → clients/interpreter-client.ts} +148 -171
  37. package/src/clients/port-client.ts +105 -0
  38. package/src/clients/process-client.ts +177 -0
  39. package/src/clients/sandbox-client.ts +41 -0
  40. package/src/clients/types.ts +84 -0
  41. package/src/clients/utility-client.ts +94 -0
  42. package/src/errors/adapter.ts +180 -0
  43. package/src/errors/classes.ts +469 -0
  44. package/src/errors/index.ts +105 -0
  45. package/src/file-stream.ts +119 -117
  46. package/src/index.ts +81 -69
  47. package/src/interpreter.ts +17 -8
  48. package/src/request-handler.ts +69 -43
  49. package/src/sandbox.ts +694 -533
  50. package/src/security.ts +14 -23
  51. package/src/sse-parser.ts +4 -8
  52. package/startup.sh +3 -0
  53. package/tests/base-client.test.ts +328 -0
  54. package/tests/command-client.test.ts +407 -0
  55. package/tests/file-client.test.ts +643 -0
  56. package/tests/file-stream.test.ts +306 -0
  57. package/tests/git-client.test.ts +328 -0
  58. package/tests/port-client.test.ts +301 -0
  59. package/tests/process-client.test.ts +658 -0
  60. package/tests/sandbox.test.ts +465 -0
  61. package/tests/sse-parser.test.ts +290 -0
  62. package/tests/utility-client.test.ts +266 -0
  63. package/tests/wrangler.jsonc +35 -0
  64. package/tsconfig.json +9 -1
  65. package/vitest.config.ts +31 -0
  66. package/container_src/bun.lock +0 -76
  67. package/container_src/circuit-breaker.ts +0 -121
  68. package/container_src/control-process.ts +0 -784
  69. package/container_src/handler/exec.ts +0 -185
  70. package/container_src/handler/file.ts +0 -457
  71. package/container_src/handler/git.ts +0 -130
  72. package/container_src/handler/ports.ts +0 -314
  73. package/container_src/handler/process.ts +0 -568
  74. package/container_src/handler/session.ts +0 -92
  75. package/container_src/index.ts +0 -601
  76. package/container_src/interpreter-service.ts +0 -276
  77. package/container_src/isolation.ts +0 -1213
  78. package/container_src/mime-processor.ts +0 -255
  79. package/container_src/package.json +0 -18
  80. package/container_src/runtime/executors/javascript/node_executor.ts +0 -123
  81. package/container_src/runtime/executors/python/ipython_executor.py +0 -338
  82. package/container_src/runtime/executors/typescript/ts_executor.ts +0 -138
  83. package/container_src/runtime/process-pool.ts +0 -464
  84. package/container_src/shell-escape.ts +0 -42
  85. package/container_src/startup.sh +0 -11
  86. package/container_src/types.ts +0 -131
  87. package/dist/chunk-32UDXUPC.js +0 -671
  88. package/dist/chunk-32UDXUPC.js.map +0 -1
  89. package/dist/chunk-5DILEXGY.js +0 -85
  90. package/dist/chunk-5DILEXGY.js.map +0 -1
  91. package/dist/chunk-D3U63BZP.js +0 -240
  92. package/dist/chunk-D3U63BZP.js.map +0 -1
  93. package/dist/chunk-FXYPFGOZ.js +0 -129
  94. package/dist/chunk-FXYPFGOZ.js.map +0 -1
  95. package/dist/chunk-JTKON2SH.js.map +0 -1
  96. package/dist/chunk-NNGBXDMY.js.map +0 -1
  97. package/dist/chunk-SQLJNZ3K.js +0 -674
  98. package/dist/chunk-SQLJNZ3K.js.map +0 -1
  99. package/dist/chunk-W7TVRPBG.js +0 -108
  100. package/dist/chunk-W7TVRPBG.js.map +0 -1
  101. package/dist/client-B3RUab0s.d.ts +0 -225
  102. package/dist/client.d.ts +0 -4
  103. package/dist/client.js +0 -7
  104. package/dist/client.js.map +0 -1
  105. package/dist/errors.d.ts +0 -95
  106. package/dist/errors.js +0 -27
  107. package/dist/errors.js.map +0 -1
  108. package/dist/interpreter-client.d.ts +0 -4
  109. package/dist/interpreter-client.js +0 -9
  110. package/dist/interpreter-client.js.map +0 -1
  111. package/dist/interpreter-types.d.ts +0 -259
  112. package/dist/interpreter-types.js +0 -9
  113. package/dist/interpreter-types.js.map +0 -1
  114. package/dist/types.d.ts +0 -453
  115. package/dist/types.js +0 -45
  116. package/dist/types.js.map +0 -1
  117. package/src/client.ts +0 -1048
  118. package/src/errors.ts +0 -219
  119. package/src/interpreter-types.ts +0 -390
  120. package/src/types.ts +0 -571
@@ -0,0 +1,177 @@
1
+ import type {
2
+ ProcessCleanupResult,
3
+ ProcessInfoResult,
4
+ ProcessKillResult,
5
+ ProcessListResult,
6
+ ProcessLogsResult,
7
+ ProcessStartResult,
8
+ StartProcessRequest,
9
+ } from '@repo/shared';
10
+ import { BaseHttpClient } from './base-client';
11
+ import type { HttpClientOptions } from './types';
12
+
13
+ // Re-export for convenience
14
+ export type {
15
+ StartProcessRequest,
16
+ ProcessStartResult,
17
+ ProcessListResult,
18
+ ProcessInfoResult,
19
+ ProcessKillResult,
20
+ ProcessLogsResult,
21
+ ProcessCleanupResult,
22
+ };
23
+
24
+
25
+ /**
26
+ * Client for background process management
27
+ */
28
+ export class ProcessClient extends BaseHttpClient {
29
+
30
+ /**
31
+ * Start a background process
32
+ * @param command - Command to execute as a background process
33
+ * @param sessionId - The session ID for this operation
34
+ * @param options - Optional settings (processId)
35
+ */
36
+ async startProcess(
37
+ command: string,
38
+ sessionId: string,
39
+ options?: { processId?: string }
40
+ ): Promise<ProcessStartResult> {
41
+ try {
42
+ const data: StartProcessRequest = {
43
+ command,
44
+ sessionId,
45
+ processId: options?.processId,
46
+ };
47
+
48
+ const response = await this.post<ProcessStartResult>(
49
+ '/api/process/start',
50
+ data
51
+ );
52
+
53
+ this.logSuccess(
54
+ 'Process started',
55
+ `${command} (ID: ${response.processId})`
56
+ );
57
+
58
+ return response;
59
+ } catch (error) {
60
+ this.logError('startProcess', error);
61
+ throw error;
62
+ }
63
+ }
64
+
65
+ /**
66
+ * List all processes (sandbox-scoped, not session-scoped)
67
+ */
68
+ async listProcesses(): Promise<ProcessListResult> {
69
+ try {
70
+ const url = `/api/process/list`;
71
+ const response = await this.get<ProcessListResult>(url);
72
+
73
+ this.logSuccess('Processes listed', `${response.processes.length} processes`);
74
+ return response;
75
+ } catch (error) {
76
+ this.logError('listProcesses', error);
77
+ throw error;
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Get information about a specific process (sandbox-scoped, not session-scoped)
83
+ * @param processId - ID of the process to retrieve
84
+ */
85
+ async getProcess(processId: string): Promise<ProcessInfoResult> {
86
+ try {
87
+ const url = `/api/process/${processId}`;
88
+ const response = await this.get<ProcessInfoResult>(url);
89
+
90
+ this.logSuccess('Process retrieved', `ID: ${processId}`);
91
+ return response;
92
+ } catch (error) {
93
+ this.logError('getProcess', error);
94
+ throw error;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Kill a specific process (sandbox-scoped, not session-scoped)
100
+ * @param processId - ID of the process to kill
101
+ */
102
+ async killProcess(processId: string): Promise<ProcessKillResult> {
103
+ try {
104
+ const url = `/api/process/${processId}`;
105
+ const response = await this.delete<ProcessKillResult>(url);
106
+
107
+ this.logSuccess('Process killed', `ID: ${processId}`);
108
+ return response;
109
+ } catch (error) {
110
+ this.logError('killProcess', error);
111
+ throw error;
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Kill all running processes (sandbox-scoped, not session-scoped)
117
+ */
118
+ async killAllProcesses(): Promise<ProcessCleanupResult> {
119
+ try {
120
+ const url = `/api/process/kill-all`;
121
+ const response = await this.delete<ProcessCleanupResult>(url);
122
+
123
+ this.logSuccess(
124
+ 'All processes killed',
125
+ `${response.cleanedCount} processes terminated`
126
+ );
127
+
128
+ return response;
129
+ } catch (error) {
130
+ this.logError('killAllProcesses', error);
131
+ throw error;
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Get logs from a specific process (sandbox-scoped, not session-scoped)
137
+ * @param processId - ID of the process to get logs from
138
+ */
139
+ async getProcessLogs(processId: string): Promise<ProcessLogsResult> {
140
+ try {
141
+ const url = `/api/process/${processId}/logs`;
142
+ const response = await this.get<ProcessLogsResult>(url);
143
+
144
+ this.logSuccess(
145
+ 'Process logs retrieved',
146
+ `ID: ${processId}, stdout: ${response.stdout.length} chars, stderr: ${response.stderr.length} chars`
147
+ );
148
+
149
+ return response;
150
+ } catch (error) {
151
+ this.logError('getProcessLogs', error);
152
+ throw error;
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Stream logs from a specific process (sandbox-scoped, not session-scoped)
158
+ * @param processId - ID of the process to stream logs from
159
+ */
160
+ async streamProcessLogs(processId: string): Promise<ReadableStream<Uint8Array>> {
161
+ try {
162
+ const url = `/api/process/${processId}/stream`;
163
+ const response = await this.doFetch(url, {
164
+ method: 'GET',
165
+ });
166
+
167
+ const stream = await this.handleStreamResponse(response);
168
+
169
+ this.logSuccess('Process log stream started', `ID: ${processId}`);
170
+
171
+ return stream;
172
+ } catch (error) {
173
+ this.logError('streamProcessLogs', error);
174
+ throw error;
175
+ }
176
+ }
177
+ }
@@ -0,0 +1,41 @@
1
+ import { CommandClient } from './command-client';
2
+ import { FileClient } from './file-client';
3
+ import { GitClient } from './git-client';
4
+ import { InterpreterClient } from './interpreter-client';
5
+ import { PortClient } from './port-client';
6
+ import { ProcessClient } from './process-client';
7
+ import type { HttpClientOptions } from './types';
8
+ import { UtilityClient } from './utility-client';
9
+
10
+ /**
11
+ * Main sandbox client that composes all domain-specific clients
12
+ * Provides organized access to all sandbox functionality
13
+ */
14
+ export class SandboxClient {
15
+ public readonly commands: CommandClient;
16
+ public readonly files: FileClient;
17
+ public readonly processes: ProcessClient;
18
+ public readonly ports: PortClient;
19
+ public readonly git: GitClient;
20
+ public readonly interpreter: InterpreterClient;
21
+ public readonly utils: UtilityClient;
22
+
23
+ constructor(options: HttpClientOptions) {
24
+ // Ensure baseUrl is provided for all clients
25
+ const clientOptions: HttpClientOptions = {
26
+ baseUrl: 'http://localhost:3000',
27
+ ...options,
28
+ };
29
+
30
+ // Initialize all domain clients with shared options
31
+ this.commands = new CommandClient(clientOptions);
32
+ this.files = new FileClient(clientOptions);
33
+ this.processes = new ProcessClient(clientOptions);
34
+ this.ports = new PortClient(clientOptions);
35
+ this.git = new GitClient(clientOptions);
36
+ this.interpreter = new InterpreterClient(clientOptions);
37
+ this.utils = new UtilityClient(clientOptions);
38
+ }
39
+
40
+
41
+ }
@@ -0,0 +1,84 @@
1
+ import type { Logger } from '@repo/shared';
2
+
3
+ /**
4
+ * Minimal interface for container fetch functionality
5
+ */
6
+ export interface ContainerStub {
7
+ containerFetch(url: string, options: RequestInit, port?: number): Promise<Response>;
8
+ }
9
+
10
+ /**
11
+ * Shared HTTP client configuration options
12
+ */
13
+ export interface HttpClientOptions {
14
+ logger?: Logger;
15
+ baseUrl?: string;
16
+ port?: number;
17
+ stub?: ContainerStub;
18
+ onCommandComplete?: (
19
+ success: boolean,
20
+ exitCode: number,
21
+ stdout: string,
22
+ stderr: string,
23
+ command: string
24
+ ) => void;
25
+ onError?: (error: string, command?: string) => void;
26
+ }
27
+
28
+ /**
29
+ * Base response interface for all API responses
30
+ */
31
+ export interface BaseApiResponse {
32
+ success: boolean;
33
+ timestamp: string;
34
+ }
35
+
36
+ /**
37
+ * Standard error response structure - matches BaseHandler.createErrorResponse()
38
+ */
39
+ export interface ApiErrorResponse {
40
+ success: false;
41
+ error: string;
42
+ code: string;
43
+ details?: any;
44
+ timestamp: string;
45
+ }
46
+
47
+ /**
48
+ * Validation error response structure - matches ValidationMiddleware
49
+ */
50
+ export interface ValidationErrorResponse {
51
+ error: string;
52
+ message: string;
53
+ details?: any[];
54
+ timestamp: string;
55
+ }
56
+
57
+ /**
58
+ * Legacy error response interface - deprecated, use ApiErrorResponse
59
+ */
60
+ export interface ErrorResponse {
61
+ error: string;
62
+ details?: string;
63
+ code?: string;
64
+ }
65
+
66
+ /**
67
+ * HTTP request configuration
68
+ */
69
+ export interface RequestConfig extends RequestInit {
70
+ endpoint: string;
71
+ data?: Record<string, any>;
72
+ }
73
+
74
+ /**
75
+ * Typed response handler
76
+ */
77
+ export type ResponseHandler<T> = (response: Response) => Promise<T>;
78
+
79
+ /**
80
+ * Common session-aware request interface
81
+ */
82
+ export interface SessionRequest {
83
+ sessionId?: string;
84
+ }
@@ -0,0 +1,94 @@
1
+ import { BaseHttpClient } from './base-client';
2
+ import type { BaseApiResponse, HttpClientOptions } from './types';
3
+
4
+ /**
5
+ * Response interface for ping operations
6
+ */
7
+ export interface PingResponse extends BaseApiResponse {
8
+ message: string;
9
+ uptime?: number;
10
+ }
11
+
12
+ /**
13
+ * Response interface for getting available commands
14
+ */
15
+ export interface CommandsResponse extends BaseApiResponse {
16
+ availableCommands: string[];
17
+ count: number;
18
+ }
19
+
20
+ /**
21
+ * Request interface for creating sessions
22
+ */
23
+ export interface CreateSessionRequest {
24
+ id: string;
25
+ env?: Record<string, string>;
26
+ cwd?: string;
27
+ }
28
+
29
+ /**
30
+ * Response interface for creating sessions
31
+ */
32
+ export interface CreateSessionResponse extends BaseApiResponse {
33
+ id: string;
34
+ message: string;
35
+ }
36
+
37
+ /**
38
+ * Client for health checks and utility operations
39
+ */
40
+ export class UtilityClient extends BaseHttpClient {
41
+
42
+ /**
43
+ * Ping the sandbox to check if it's responsive
44
+ */
45
+ async ping(): Promise<string> {
46
+ try {
47
+ const response = await this.get<PingResponse>('/api/ping');
48
+
49
+ this.logSuccess('Ping successful', response.message);
50
+ return response.message;
51
+ } catch (error) {
52
+ this.logError('ping', error);
53
+ throw error;
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Get list of available commands in the sandbox environment
59
+ */
60
+ async getCommands(): Promise<string[]> {
61
+ try {
62
+ const response = await this.get<CommandsResponse>('/api/commands');
63
+
64
+ this.logSuccess(
65
+ 'Commands retrieved',
66
+ `${response.count} commands available`
67
+ );
68
+
69
+ return response.availableCommands;
70
+ } catch (error) {
71
+ this.logError('getCommands', error);
72
+ throw error;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Create a new execution session
78
+ * @param options - Session configuration (id, env, cwd)
79
+ */
80
+ async createSession(options: CreateSessionRequest): Promise<CreateSessionResponse> {
81
+ try {
82
+ const response = await this.post<CreateSessionResponse>(
83
+ '/api/session/create',
84
+ options
85
+ );
86
+
87
+ this.logSuccess('Session created', `ID: ${options.id}`);
88
+ return response;
89
+ } catch (error) {
90
+ this.logError('createSession', error);
91
+ throw error;
92
+ }
93
+ }
94
+ }
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Error adapter that converts ErrorResponse to appropriate Error class
3
+ *
4
+ * Simple switch statement - we trust the container sends correct context
5
+ * No validation overhead since we control both sides
6
+ */
7
+
8
+ import type {
9
+ CodeExecutionContext,
10
+ CommandErrorContext,
11
+ CommandNotFoundContext,
12
+ ContextNotFoundContext,ErrorResponse,
13
+ FileExistsContext,
14
+ FileNotFoundContext,
15
+ FileSystemContext,
16
+ GitAuthFailedContext,
17
+ GitBranchNotFoundContext,
18
+ GitErrorContext,
19
+ GitRepositoryNotFoundContext,
20
+ InternalErrorContext,
21
+ InterpreterNotReadyContext,
22
+ InvalidPortContext,
23
+ PortAlreadyExposedContext,
24
+ PortErrorContext,
25
+ PortNotExposedContext,
26
+ ProcessErrorContext,
27
+ ProcessNotFoundContext,
28
+ ValidationFailedContext,} from '@repo/shared/errors';
29
+ import { ErrorCode } from '@repo/shared/errors';
30
+
31
+ import {
32
+ CodeExecutionError,
33
+ CommandError,
34
+ CommandNotFoundError,
35
+ ContextNotFoundError,
36
+ CustomDomainRequiredError,
37
+ FileExistsError,
38
+ FileNotFoundError,
39
+ FileSystemError,
40
+ GitAuthenticationError,
41
+ GitBranchNotFoundError,
42
+ GitCheckoutError,
43
+ GitCloneError,
44
+ GitError,
45
+ GitNetworkError,
46
+ GitRepositoryNotFoundError,
47
+ InterpreterNotReadyError,
48
+ InvalidGitUrlError,
49
+ InvalidPortError,
50
+ PermissionDeniedError,
51
+ PortAlreadyExposedError,
52
+ PortError,
53
+ PortInUseError,
54
+ PortNotExposedError,
55
+ ProcessError,
56
+ ProcessNotFoundError,
57
+ SandboxError,
58
+ ServiceNotRespondingError,
59
+ ValidationFailedError,
60
+ } from './classes';
61
+
62
+ /**
63
+ * Convert ErrorResponse to appropriate Error class
64
+ * Simple switch statement - we trust the container sends correct context
65
+ */
66
+ export function createErrorFromResponse(errorResponse: ErrorResponse): Error {
67
+ // We trust the container sends correct context, use type assertions
68
+ switch (errorResponse.code) {
69
+ // File System Errors
70
+ case ErrorCode.FILE_NOT_FOUND:
71
+ return new FileNotFoundError(errorResponse as unknown as ErrorResponse<FileNotFoundContext>);
72
+
73
+ case ErrorCode.FILE_EXISTS:
74
+ return new FileExistsError(errorResponse as unknown as ErrorResponse<FileExistsContext>);
75
+
76
+ case ErrorCode.PERMISSION_DENIED:
77
+ return new PermissionDeniedError(errorResponse as unknown as ErrorResponse<FileSystemContext>);
78
+
79
+ case ErrorCode.IS_DIRECTORY:
80
+ case ErrorCode.NOT_DIRECTORY:
81
+ case ErrorCode.NO_SPACE:
82
+ case ErrorCode.TOO_MANY_FILES:
83
+ case ErrorCode.RESOURCE_BUSY:
84
+ case ErrorCode.READ_ONLY:
85
+ case ErrorCode.NAME_TOO_LONG:
86
+ case ErrorCode.TOO_MANY_LINKS:
87
+ case ErrorCode.FILESYSTEM_ERROR:
88
+ return new FileSystemError(errorResponse as unknown as ErrorResponse<FileSystemContext>);
89
+
90
+ // Command Errors
91
+ case ErrorCode.COMMAND_NOT_FOUND:
92
+ return new CommandNotFoundError(errorResponse as unknown as ErrorResponse<CommandNotFoundContext>);
93
+
94
+ case ErrorCode.COMMAND_PERMISSION_DENIED:
95
+ case ErrorCode.COMMAND_EXECUTION_ERROR:
96
+ case ErrorCode.INVALID_COMMAND:
97
+ case ErrorCode.STREAM_START_ERROR:
98
+ return new CommandError(errorResponse as unknown as ErrorResponse<CommandErrorContext>);
99
+
100
+ // Process Errors
101
+ case ErrorCode.PROCESS_NOT_FOUND:
102
+ return new ProcessNotFoundError(errorResponse as unknown as ErrorResponse<ProcessNotFoundContext>);
103
+
104
+ case ErrorCode.PROCESS_PERMISSION_DENIED:
105
+ case ErrorCode.PROCESS_ERROR:
106
+ return new ProcessError(errorResponse as unknown as ErrorResponse<ProcessErrorContext>);
107
+
108
+ // Port Errors
109
+ case ErrorCode.PORT_ALREADY_EXPOSED:
110
+ return new PortAlreadyExposedError(errorResponse as unknown as ErrorResponse<PortAlreadyExposedContext>);
111
+
112
+ case ErrorCode.PORT_NOT_EXPOSED:
113
+ return new PortNotExposedError(errorResponse as unknown as ErrorResponse<PortNotExposedContext>);
114
+
115
+ case ErrorCode.INVALID_PORT_NUMBER:
116
+ case ErrorCode.INVALID_PORT:
117
+ return new InvalidPortError(errorResponse as unknown as ErrorResponse<InvalidPortContext>);
118
+
119
+ case ErrorCode.SERVICE_NOT_RESPONDING:
120
+ return new ServiceNotRespondingError(errorResponse as unknown as ErrorResponse<PortErrorContext>);
121
+
122
+ case ErrorCode.PORT_IN_USE:
123
+ return new PortInUseError(errorResponse as unknown as ErrorResponse<PortErrorContext>);
124
+
125
+ case ErrorCode.PORT_OPERATION_ERROR:
126
+ return new PortError(errorResponse as unknown as ErrorResponse<PortErrorContext>);
127
+
128
+ case ErrorCode.CUSTOM_DOMAIN_REQUIRED:
129
+ return new CustomDomainRequiredError(errorResponse as unknown as ErrorResponse<InternalErrorContext>);
130
+
131
+ // Git Errors
132
+ case ErrorCode.GIT_REPOSITORY_NOT_FOUND:
133
+ return new GitRepositoryNotFoundError(errorResponse as unknown as ErrorResponse<GitRepositoryNotFoundContext>);
134
+
135
+ case ErrorCode.GIT_AUTH_FAILED:
136
+ return new GitAuthenticationError(errorResponse as unknown as ErrorResponse<GitAuthFailedContext>);
137
+
138
+ case ErrorCode.GIT_BRANCH_NOT_FOUND:
139
+ return new GitBranchNotFoundError(errorResponse as unknown as ErrorResponse<GitBranchNotFoundContext>);
140
+
141
+ case ErrorCode.GIT_NETWORK_ERROR:
142
+ return new GitNetworkError(errorResponse as unknown as ErrorResponse<GitErrorContext>);
143
+
144
+ case ErrorCode.GIT_CLONE_FAILED:
145
+ return new GitCloneError(errorResponse as unknown as ErrorResponse<GitErrorContext>);
146
+
147
+ case ErrorCode.GIT_CHECKOUT_FAILED:
148
+ return new GitCheckoutError(errorResponse as unknown as ErrorResponse<GitErrorContext>);
149
+
150
+ case ErrorCode.INVALID_GIT_URL:
151
+ return new InvalidGitUrlError(errorResponse as unknown as ErrorResponse<ValidationFailedContext>);
152
+
153
+ case ErrorCode.GIT_OPERATION_FAILED:
154
+ return new GitError(errorResponse as unknown as ErrorResponse<GitErrorContext>);
155
+
156
+ // Code Interpreter Errors
157
+ case ErrorCode.INTERPRETER_NOT_READY:
158
+ return new InterpreterNotReadyError(errorResponse as unknown as ErrorResponse<InterpreterNotReadyContext>);
159
+
160
+ case ErrorCode.CONTEXT_NOT_FOUND:
161
+ return new ContextNotFoundError(errorResponse as unknown as ErrorResponse<ContextNotFoundContext>);
162
+
163
+ case ErrorCode.CODE_EXECUTION_ERROR:
164
+ return new CodeExecutionError(errorResponse as unknown as ErrorResponse<CodeExecutionContext>);
165
+
166
+ // Validation Errors
167
+ case ErrorCode.VALIDATION_FAILED:
168
+ return new ValidationFailedError(errorResponse as unknown as ErrorResponse<ValidationFailedContext>);
169
+
170
+ // Generic Errors
171
+ case ErrorCode.INVALID_JSON_RESPONSE:
172
+ case ErrorCode.UNKNOWN_ERROR:
173
+ case ErrorCode.INTERNAL_ERROR:
174
+ return new SandboxError(errorResponse as unknown as ErrorResponse<InternalErrorContext>);
175
+
176
+ default:
177
+ // Fallback for unknown error codes
178
+ return new SandboxError(errorResponse);
179
+ }
180
+ }