@cloudflare/sandbox 0.2.2 → 0.2.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/Dockerfile +10 -6
  3. package/README.md +1 -1
  4. package/container_src/handler/file.ts +222 -2
  5. package/container_src/index.ts +7 -0
  6. package/container_src/jupyter-service.ts +15 -2
  7. package/container_src/jupyter_config.py +48 -0
  8. package/container_src/startup.sh +33 -32
  9. package/container_src/types.ts +9 -0
  10. package/dist/{chunk-CUHYLCMT.js → chunk-3CQ6THKA.js} +31 -1
  11. package/dist/chunk-3CQ6THKA.js.map +1 -0
  12. package/dist/{chunk-S5FFBU4Y.js → chunk-6EWSYSO7.js} +1 -1
  13. package/dist/{chunk-S5FFBU4Y.js.map → chunk-6EWSYSO7.js.map} +1 -1
  14. package/dist/{chunk-ZMPO44U4.js → chunk-CKIGERRS.js} +9 -8
  15. package/dist/chunk-CKIGERRS.js.map +1 -0
  16. package/dist/{chunk-VTKZL632.js → chunk-HHUDRGPY.js} +2 -2
  17. package/dist/{client-bzEV222a.d.ts → client-Ce40ujDF.d.ts} +10 -62
  18. package/dist/client.d.ts +1 -1
  19. package/dist/client.js +1 -1
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.js +4 -4
  22. package/dist/interpreter.d.ts +2 -2
  23. package/dist/jupyter-client.d.ts +2 -2
  24. package/dist/jupyter-client.js +2 -2
  25. package/dist/request-handler.d.ts +3 -3
  26. package/dist/request-handler.js +4 -4
  27. package/dist/sandbox.d.ts +2 -2
  28. package/dist/sandbox.js +4 -4
  29. package/dist/types.d.ts +118 -1
  30. package/dist/types.js +1 -1
  31. package/package.json +1 -1
  32. package/src/client.ts +62 -59
  33. package/src/index.ts +15 -13
  34. package/src/sandbox.ts +15 -5
  35. package/src/types.ts +110 -0
  36. package/dist/chunk-CUHYLCMT.js.map +0 -1
  37. package/dist/chunk-ZMPO44U4.js.map +0 -1
  38. /package/dist/{chunk-VTKZL632.js.map → chunk-HHUDRGPY.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @cloudflare/sandbox
2
2
 
3
+ ## 0.2.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#57](https://github.com/cloudflare/sandbox-sdk/pull/57) [`12bbd12`](https://github.com/cloudflare/sandbox-sdk/commit/12bbd1229c07ef8c1c0bf58a4235a27938155b08) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Add listFiles method
8
+
9
+ ## 0.2.3
10
+
11
+ ### Patch Changes
12
+
13
+ - [#53](https://github.com/cloudflare/sandbox-sdk/pull/53) [`c87db11`](https://github.com/cloudflare/sandbox-sdk/commit/c87db117693a86cfb667bf09fb7720d6a6e0524d) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Improve jupyterlab config to speed up startup
14
+
3
15
  ## 0.2.2
4
16
 
5
17
  ### Patch Changes
package/Dockerfile CHANGED
@@ -37,6 +37,7 @@ RUN apt-get update && apt-get install -y \
37
37
  ca-certificates \
38
38
  gnupg \
39
39
  lsb-release \
40
+ strace \
40
41
  && rm -rf /var/lib/apt/lists/*
41
42
 
42
43
  # Set Python 3.11 as default python3
@@ -56,17 +57,20 @@ RUN apt-get update && apt-get install -y ca-certificates curl gnupg \
56
57
  COPY --from=bun-source /usr/local/bin/bun /usr/local/bin/bun
57
58
  COPY --from=bun-source /usr/local/bin/bunx /usr/local/bin/bunx
58
59
 
59
- # Install Jupyter and kernels
60
+ # Install minimal Jupyter components
60
61
  RUN pip3 install --no-cache-dir \
61
- jupyter \
62
- jupyterlab \
62
+ jupyter-server \
63
+ jupyter-client \
63
64
  ipykernel \
64
- notebook \
65
+ orjson \
66
+ && python3 -m ipykernel install --user --name python3
67
+
68
+ # Install scientific packages
69
+ RUN pip3 install --no-cache-dir \
65
70
  matplotlib \
66
71
  numpy \
67
72
  pandas \
68
- seaborn \
69
- && python3 -m ipykernel install --user --name python3
73
+ seaborn
70
74
 
71
75
  # Install JavaScript kernel (ijavascript) - using E2B's fork
72
76
  RUN npm install -g --unsafe-perm git+https://github.com/e2b-dev/ijavascript.git \
package/README.md CHANGED
@@ -72,7 +72,7 @@ npm install @cloudflare/sandbox
72
72
  1. **Create a Dockerfile** (temporary requirement, will be removed in future releases):
73
73
 
74
74
  ```dockerfile
75
- FROM docker.io/cloudflare/sandbox:0.2.2
75
+ FROM docker.io/cloudflare/sandbox:0.2.4
76
76
 
77
77
  # Expose the ports you want to expose
78
78
  EXPOSE 3000
@@ -1,8 +1,9 @@
1
1
  import { spawn } from "node:child_process";
2
- import { mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
3
- import { dirname } from "node:path";
2
+ import { mkdir, readdir, readFile, rename, stat, unlink, writeFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
4
  import type {
5
5
  DeleteFileRequest,
6
+ ListFilesRequest,
6
7
  MkdirRequest,
7
8
  MoveFileRequest,
8
9
  ReadFileRequest,
@@ -842,3 +843,222 @@ export async function handleMoveFileRequest(
842
843
  }
843
844
  }
844
845
 
846
+
847
+ async function executeListFiles(
848
+ path: string,
849
+ options?: {
850
+ recursive?: boolean;
851
+ includeHidden?: boolean;
852
+ }
853
+ ): Promise<{
854
+ success: boolean;
855
+ exitCode: number;
856
+ files: Array<{
857
+ name: string;
858
+ absolutePath: string;
859
+ relativePath: string;
860
+ type: 'file' | 'directory' | 'symlink' | 'other';
861
+ size: number;
862
+ modifiedAt: string;
863
+ mode: string;
864
+ permissions: {
865
+ readable: boolean;
866
+ writable: boolean;
867
+ executable: boolean;
868
+ };
869
+ }>;
870
+ }> {
871
+ try {
872
+ const basePath = path.endsWith('/') ? path.slice(0, -1) : path;
873
+ const files: Array<{
874
+ name: string;
875
+ absolutePath: string;
876
+ relativePath: string;
877
+ type: 'file' | 'directory' | 'symlink' | 'other';
878
+ size: number;
879
+ modifiedAt: string;
880
+ mode: string;
881
+ permissions: {
882
+ readable: boolean;
883
+ writable: boolean;
884
+ executable: boolean;
885
+ };
886
+ }> = [];
887
+
888
+ // Helper function to convert numeric mode to string like "rwxr-xr-x"
889
+ function modeToString(mode: number): string {
890
+ const perms = ['---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx'];
891
+ const user = (mode >> 6) & 7;
892
+ const group = (mode >> 3) & 7;
893
+ const other = mode & 7;
894
+ return perms[user] + perms[group] + perms[other];
895
+ }
896
+
897
+ // Helper function to extract permission booleans for current user
898
+ function getPermissions(mode: number): { readable: boolean; writable: boolean; executable: boolean } {
899
+ // Extract user permissions (owner permissions)
900
+ const userPerms = (mode >> 6) & 7;
901
+ return {
902
+ readable: (userPerms & 4) !== 0,
903
+ writable: (userPerms & 2) !== 0,
904
+ executable: (userPerms & 1) !== 0
905
+ };
906
+ }
907
+
908
+ async function scanDirectory(dirPath: string): Promise<void> {
909
+ const entries = await readdir(dirPath);
910
+
911
+ for (const entry of entries) {
912
+ // Skip hidden files unless includeHidden is true
913
+ if (!options?.includeHidden && entry.startsWith('.')) {
914
+ continue;
915
+ }
916
+
917
+ const fullPath = join(dirPath, entry);
918
+ const stats = await stat(fullPath);
919
+
920
+ let type: 'file' | 'directory' | 'symlink' | 'other';
921
+ if (stats.isDirectory()) {
922
+ type = 'directory';
923
+ } else if (stats.isFile()) {
924
+ type = 'file';
925
+ } else if (stats.isSymbolicLink()) {
926
+ type = 'symlink';
927
+ } else {
928
+ type = 'other';
929
+ }
930
+
931
+ // Extract mode (permissions) - stats.mode is a number
932
+ const mode = stats.mode & 0o777; // Get only permission bits
933
+
934
+ // Calculate relative path from base directory
935
+ const relativePath = fullPath.startsWith(`${basePath}/`)
936
+ ? fullPath.substring(basePath.length + 1)
937
+ : fullPath === basePath
938
+ ? '.'
939
+ : entry;
940
+
941
+ const fileInfo = {
942
+ name: entry,
943
+ absolutePath: fullPath,
944
+ relativePath,
945
+ type,
946
+ size: stats.size,
947
+ modifiedAt: stats.mtime.toISOString(),
948
+ mode: modeToString(mode),
949
+ permissions: getPermissions(mode)
950
+ };
951
+
952
+ files.push(fileInfo);
953
+
954
+ // Recursively scan subdirectories if requested
955
+ if (options?.recursive && type === 'directory') {
956
+ await scanDirectory(fullPath);
957
+ }
958
+ }
959
+ }
960
+
961
+ await scanDirectory(path);
962
+
963
+ console.log(`[Server] Listed ${files.length} files in: ${path}`);
964
+ return {
965
+ exitCode: 0,
966
+ files,
967
+ success: true,
968
+ };
969
+ } catch (error) {
970
+ console.error(`[Server] Error listing files in: ${path}`, error);
971
+ throw error;
972
+ }
973
+ }
974
+
975
+ export async function handleListFilesRequest(
976
+ req: Request,
977
+ corsHeaders: Record<string, string>
978
+ ): Promise<Response> {
979
+ try {
980
+ const body = (await req.json()) as ListFilesRequest;
981
+ const { path, options } = body;
982
+
983
+ if (!path || typeof path !== "string") {
984
+ return new Response(
985
+ JSON.stringify({
986
+ error: "Path is required and must be a string",
987
+ }),
988
+ {
989
+ headers: {
990
+ "Content-Type": "application/json",
991
+ ...corsHeaders,
992
+ },
993
+ status: 400,
994
+ }
995
+ );
996
+ }
997
+
998
+ // Basic safety check - prevent dangerous paths
999
+ const dangerousPatterns = [
1000
+ /^\/etc/, // System directories
1001
+ /^\/var/, // System directories
1002
+ /^\/usr/, // System directories
1003
+ /^\/bin/, // System directories
1004
+ /^\/sbin/, // System directories
1005
+ /^\/boot/, // System directories
1006
+ /^\/dev/, // System directories
1007
+ /^\/proc/, // System directories
1008
+ /^\/sys/, // System directories
1009
+ /^\/tmp\/\.\./, // Path traversal attempts
1010
+ /\.\./, // Path traversal attempts
1011
+ ];
1012
+
1013
+ if (dangerousPatterns.some((pattern) => pattern.test(path))) {
1014
+ return new Response(
1015
+ JSON.stringify({
1016
+ error: "Dangerous path not allowed",
1017
+ }),
1018
+ {
1019
+ headers: {
1020
+ "Content-Type": "application/json",
1021
+ ...corsHeaders,
1022
+ },
1023
+ status: 400,
1024
+ }
1025
+ );
1026
+ }
1027
+
1028
+ console.log(`[Server] Listing files in: ${path}`);
1029
+
1030
+ const result = await executeListFiles(path, options);
1031
+
1032
+ return new Response(
1033
+ JSON.stringify({
1034
+ exitCode: result.exitCode,
1035
+ files: result.files,
1036
+ path,
1037
+ success: result.success,
1038
+ timestamp: new Date().toISOString(),
1039
+ }),
1040
+ {
1041
+ headers: {
1042
+ "Content-Type": "application/json",
1043
+ ...corsHeaders,
1044
+ },
1045
+ }
1046
+ );
1047
+ } catch (error) {
1048
+ console.error("[Server] Error in handleListFilesRequest:", error);
1049
+ return new Response(
1050
+ JSON.stringify({
1051
+ error: "Failed to list files",
1052
+ message: error instanceof Error ? error.message : "Unknown error",
1053
+ }),
1054
+ {
1055
+ headers: {
1056
+ "Content-Type": "application/json",
1057
+ ...corsHeaders,
1058
+ },
1059
+ status: 500,
1060
+ }
1061
+ );
1062
+ }
1063
+ }
1064
+
@@ -6,6 +6,7 @@ import {
6
6
  } from "./handler/exec";
7
7
  import {
8
8
  handleDeleteFileRequest,
9
+ handleListFilesRequest,
9
10
  handleMkdirRequest,
10
11
  handleMoveFileRequest,
11
12
  handleReadFileRequest,
@@ -279,6 +280,12 @@ const server = serve({
279
280
  }
280
281
  break;
281
282
 
283
+ case "/api/list-files":
284
+ if (req.method === "POST") {
285
+ return handleListFilesRequest(req, corsHeaders);
286
+ }
287
+ break;
288
+
282
289
  case "/api/expose-port":
283
290
  if (req.method === "POST") {
284
291
  return handleExposePortRequest(exposedPorts, req, corsHeaders);
@@ -133,16 +133,29 @@ export class JupyterService {
133
133
  * Pre-warm context pools for better performance
134
134
  */
135
135
  private async warmContextPools() {
136
+ // Delay pre-warming to avoid startup rush that triggers Bun WebSocket bug
137
+ await new Promise((resolve) => setTimeout(resolve, 2000));
138
+
136
139
  try {
137
140
  console.log(
138
141
  "[JupyterService] Pre-warming context pools for better performance"
139
142
  );
140
143
 
141
- // Enable pool warming with min sizes
144
+ // Only pre-warm Python contexts to avoid Bun WebSocket validation errors
145
+ // JavaScript contexts will be created on-demand
142
146
  await this.jupyterServer.enablePoolWarming("python", 1);
143
- await this.jupyterServer.enablePoolWarming("javascript", 1);
147
+
148
+ // Commenting out JavaScript pre-warming due to kernel message validation errors
149
+ // The errors appear to be related to Bun's handling of WebSocket messages
150
+ // JavaScript contexts still work fine when created on-demand
151
+ //
152
+ // await new Promise((resolve) => setTimeout(resolve, 1000));
153
+ // await this.jupyterServer.enablePoolWarming("javascript", 1);
144
154
  } catch (error) {
145
155
  console.error("[JupyterService] Error pre-warming context pools:", error);
156
+ console.error(
157
+ "[JupyterService] Pre-warming failed but service continues"
158
+ );
146
159
  }
147
160
  }
148
161
 
@@ -0,0 +1,48 @@
1
+ """
2
+ Minimal Jupyter configuration focused on kernel-only usage
3
+ """
4
+
5
+ c = get_config() # noqa
6
+
7
+ # Disable all authentication - we handle security at container level
8
+ c.ServerApp.token = ''
9
+ c.ServerApp.password = ''
10
+ c.IdentityProvider.token = ''
11
+ c.ServerApp.allow_origin = '*'
12
+ c.ServerApp.allow_remote_access = True
13
+ c.ServerApp.disable_check_xsrf = True
14
+ c.ServerApp.allow_root = True
15
+ c.ServerApp.allow_credentials = True
16
+
17
+ # Also set NotebookApp settings for compatibility
18
+ c.NotebookApp.token = ''
19
+ c.NotebookApp.password = ''
20
+ c.NotebookApp.allow_origin = '*'
21
+ c.NotebookApp.allow_remote_access = True
22
+ c.NotebookApp.disable_check_xsrf = True
23
+ c.NotebookApp.allow_credentials = True
24
+
25
+ # Performance settings
26
+ c.ServerApp.iopub_data_rate_limit = 1000000000 # E2B uses 1GB/s
27
+
28
+ # Minimal logging
29
+ c.Application.log_level = 'ERROR'
30
+
31
+ # Disable browser
32
+ c.ServerApp.open_browser = False
33
+
34
+ # Optimize for container environment
35
+ c.ServerApp.ip = '0.0.0.0'
36
+ c.ServerApp.port = 8888
37
+
38
+ # Kernel optimizations
39
+ c.KernelManager.shutdown_wait_time = 0.0
40
+ c.MappingKernelManager.cull_idle_timeout = 0
41
+ c.MappingKernelManager.cull_interval = 0
42
+
43
+ # Disable terminals
44
+ c.ServerApp.terminals_enabled = False
45
+
46
+ # Disable all extensions to speed up startup
47
+ c.ServerApp.jpserver_extensions = {}
48
+ c.ServerApp.nbserver_extensions = {}
@@ -2,7 +2,8 @@
2
2
 
3
3
  # Function to check if Jupyter is ready
4
4
  check_jupyter_ready() {
5
- curl -s http://localhost:8888/api > /dev/null 2>&1
5
+ # Check if API is responsive and kernelspecs are available
6
+ curl -s http://localhost:8888/api/kernelspecs > /dev/null 2>&1
6
7
  }
7
8
 
8
9
  # Function to notify Bun server that Jupyter is ready
@@ -12,19 +13,10 @@ notify_jupyter_ready() {
12
13
  echo "[Startup] Jupyter is ready, notified Bun server"
13
14
  }
14
15
 
15
- # Start Jupyter notebook server in background
16
+ # Start Jupyter server in background
16
17
  echo "[Startup] Starting Jupyter server..."
17
- jupyter notebook \
18
- --ip=0.0.0.0 \
19
- --port=8888 \
20
- --no-browser \
21
- --allow-root \
22
- --NotebookApp.token='' \
23
- --NotebookApp.password='' \
24
- --NotebookApp.allow_origin='*' \
25
- --NotebookApp.disable_check_xsrf=True \
26
- --NotebookApp.allow_remote_access=True \
27
- --NotebookApp.allow_credentials=True \
18
+ jupyter server \
19
+ --config=/container-server/jupyter_config.py \
28
20
  > /tmp/jupyter.log 2>&1 &
29
21
 
30
22
  JUPYTER_PID=$!
@@ -37,18 +29,21 @@ BUN_PID=$!
37
29
  # Monitor Jupyter readiness in background
38
30
  (
39
31
  echo "[Startup] Monitoring Jupyter readiness in background..."
40
- MAX_ATTEMPTS=30
32
+ MAX_ATTEMPTS=60
41
33
  ATTEMPT=0
42
- DELAY=0.5
43
- MAX_DELAY=5
44
-
34
+
35
+ # Track start time for reporting
36
+ START_TIME=$(date +%s.%N)
37
+
45
38
  while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
46
39
  if check_jupyter_ready; then
47
40
  notify_jupyter_ready
48
- echo "[Startup] Jupyter server is ready after $ATTEMPT attempts"
41
+ END_TIME=$(date +%s.%N)
42
+ ELAPSED=$(awk "BEGIN {printf \"%.2f\", $END_TIME - $START_TIME}")
43
+ echo "[Startup] Jupyter server is ready after $ELAPSED seconds ($ATTEMPT attempts)"
49
44
  break
50
45
  fi
51
-
46
+
52
47
  # Check if Jupyter process is still running
53
48
  if ! kill -0 $JUPYTER_PID 2>/dev/null; then
54
49
  echo "[Startup] WARNING: Jupyter process died. Check /tmp/jupyter.log for details"
@@ -56,21 +51,27 @@ BUN_PID=$!
56
51
  # Don't exit - let Bun server continue running in degraded mode
57
52
  break
58
53
  fi
59
-
54
+
60
55
  ATTEMPT=$((ATTEMPT + 1))
61
- echo "[Startup] Jupyter not ready yet (attempt $ATTEMPT/$MAX_ATTEMPTS, delay ${DELAY}s)"
62
-
63
- # Sleep with exponential backoff
64
- sleep $DELAY
65
-
66
- # Increase delay exponentially with jitter, cap at MAX_DELAY
67
- DELAY=$(awk "BEGIN {printf \"%.2f\", $DELAY * 1.5 + (rand() * 0.5)}")
68
- # Use awk for comparison since bc might not be available
69
- if [ $(awk "BEGIN {print ($DELAY > $MAX_DELAY)}") -eq 1 ]; then
70
- DELAY=$MAX_DELAY
56
+
57
+ # Start with faster checks
58
+ if [ $ATTEMPT -eq 1 ]; then
59
+ DELAY=0.5 # Start at 0.5s
60
+ else
61
+ # Exponential backoff with 1.3x multiplier (less aggressive than 1.5x)
62
+ DELAY=$(awk "BEGIN {printf \"%.2f\", $DELAY * 1.3}")
63
+ # Cap at 2s max (instead of 5s)
64
+ if [ $(awk "BEGIN {print ($DELAY > 2)}") -eq 1 ]; then
65
+ DELAY=2
66
+ fi
71
67
  fi
68
+
69
+ # Log with current delay for transparency
70
+ echo "[Startup] Jupyter not ready yet (attempt $ATTEMPT/$MAX_ATTEMPTS, next check in ${DELAY}s)"
71
+
72
+ sleep $DELAY
72
73
  done
73
-
74
+
74
75
  if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
75
76
  echo "[Startup] WARNING: Jupyter failed to become ready within attempts"
76
77
  echo "[Startup] Jupyter logs:"
@@ -80,4 +81,4 @@ BUN_PID=$!
80
81
  ) &
81
82
 
82
83
  # Wait for Bun server (main process)
83
- wait $BUN_PID
84
+ wait $BUN_PID
@@ -92,6 +92,15 @@ export interface MoveFileRequest {
92
92
  sessionId?: string;
93
93
  }
94
94
 
95
+ export interface ListFilesRequest {
96
+ path: string;
97
+ options?: {
98
+ recursive?: boolean;
99
+ includeHidden?: boolean;
100
+ };
101
+ sessionId?: string;
102
+ }
103
+
95
104
  export interface ExposePortRequest {
96
105
  port: number;
97
106
  name?: string;
@@ -322,6 +322,36 @@ var HttpClient = class {
322
322
  throw error;
323
323
  }
324
324
  }
325
+ async listFiles(path, options, sessionId) {
326
+ try {
327
+ const targetSessionId = sessionId || this.sessionId;
328
+ const response = await this.doFetch(`/api/list-files`, {
329
+ body: JSON.stringify({
330
+ path,
331
+ options,
332
+ sessionId: targetSessionId
333
+ }),
334
+ headers: {
335
+ "Content-Type": "application/json"
336
+ },
337
+ method: "POST"
338
+ });
339
+ if (!response.ok) {
340
+ const errorData = await response.json().catch(() => ({}));
341
+ throw new Error(
342
+ errorData.error || `HTTP error! status: ${response.status}`
343
+ );
344
+ }
345
+ const data = await response.json();
346
+ console.log(
347
+ `[HTTP Client] Listed ${data.files.length} files in: ${path}, Success: ${data.success}`
348
+ );
349
+ return data;
350
+ } catch (error) {
351
+ console.error("[HTTP Client] Error listing files:", error);
352
+ throw error;
353
+ }
354
+ }
325
355
  async exposePort(port, name) {
326
356
  try {
327
357
  const response = await this.doFetch(`/api/expose-port`, {
@@ -626,4 +656,4 @@ var HttpClient = class {
626
656
  export {
627
657
  HttpClient
628
658
  };
629
- //# sourceMappingURL=chunk-CUHYLCMT.js.map
659
+ //# sourceMappingURL=chunk-3CQ6THKA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import type { ExecuteRequest } from \"../container_src/types\";\nimport type { Sandbox } from \"./index\";\nimport type {\n BaseExecOptions,\n DeleteFileResponse,\n ExecuteResponse,\n GetProcessLogsResponse,\n GetProcessResponse,\n GitCheckoutResponse,\n ListFilesResponse,\n ListProcessesResponse,\n MkdirResponse,\n MoveFileResponse,\n ReadFileResponse,\n RenameFileResponse,\n StartProcessRequest,\n StartProcessResponse,\n WriteFileResponse,\n} from \"./types\";\n\n\ninterface CommandsResponse {\n availableCommands: string[];\n timestamp: string;\n}\n\ninterface GitCheckoutRequest {\n repoUrl: string;\n branch?: string;\n targetDir?: string;\n sessionId?: string;\n}\n\n\ninterface MkdirRequest {\n path: string;\n recursive?: boolean;\n sessionId?: string;\n}\n\n\ninterface WriteFileRequest {\n path: string;\n content: string;\n encoding?: string;\n sessionId?: string;\n}\n\n\ninterface ReadFileRequest {\n path: string;\n encoding?: string;\n sessionId?: string;\n}\n\n\ninterface DeleteFileRequest {\n path: string;\n sessionId?: string;\n}\n\n\ninterface RenameFileRequest {\n oldPath: string;\n newPath: string;\n sessionId?: string;\n}\n\n\ninterface MoveFileRequest {\n sourcePath: string;\n destinationPath: string;\n sessionId?: string;\n}\n\n\ninterface ListFilesRequest {\n path: string;\n options?: {\n recursive?: boolean;\n includeHidden?: boolean;\n };\n sessionId?: string;\n}\n\n\ninterface PreviewInfo {\n url: string;\n port: number;\n name?: string;\n}\n\ninterface ExposedPort extends PreviewInfo {\n exposedAt: string;\n timestamp: string;\n}\n\ninterface ExposePortResponse {\n success: boolean;\n port: number;\n name?: string;\n exposedAt: string;\n timestamp: string;\n}\n\ninterface UnexposePortResponse {\n success: boolean;\n port: number;\n timestamp: string;\n}\n\ninterface GetExposedPortsResponse {\n ports: ExposedPort[];\n count: number;\n timestamp: string;\n}\n\ninterface PingResponse {\n message: string;\n timestamp: string;\n}\n\ninterface HttpClientOptions {\n stub?: Sandbox;\n baseUrl?: string;\n port?: number;\n onCommandStart?: (command: string) => void;\n onOutput?: (\n stream: \"stdout\" | \"stderr\",\n data: string,\n command: string\n ) => void;\n onCommandComplete?: (\n success: boolean,\n exitCode: number,\n stdout: string,\n stderr: string,\n command: string\n ) => void;\n onError?: (error: string, command?: string) => void;\n}\n\nexport class HttpClient {\n private baseUrl: string;\n private options: HttpClientOptions;\n private sessionId: string | null = null;\n\n constructor(options: HttpClientOptions = {}) {\n this.options = {\n ...options,\n };\n this.baseUrl = this.options.baseUrl!;\n }\n\n protected async doFetch(\n path: string,\n options?: RequestInit\n ): Promise<Response> {\n const url = this.options.stub\n ? `http://localhost:${this.options.port}${path}`\n : `${this.baseUrl}${path}`;\n const method = options?.method || \"GET\";\n\n console.log(`[HTTP Client] Making ${method} request to ${url}`);\n\n try {\n let response: Response;\n\n if (this.options.stub) {\n response = await this.options.stub.containerFetch(\n url,\n options,\n this.options.port\n );\n } else {\n response = await fetch(url, options);\n }\n\n console.log(\n `[HTTP Client] Response: ${response.status} ${response.statusText}`\n );\n\n if (!response.ok) {\n console.error(\n `[HTTP Client] Request failed: ${method} ${url} - ${response.status} ${response.statusText}`\n );\n }\n\n return response;\n } catch (error) {\n console.error(`[HTTP Client] Request error: ${method} ${url}`, error);\n throw error;\n }\n }\n\n async execute(\n command: string,\n options: Pick<BaseExecOptions, \"sessionId\" | \"cwd\" | \"env\">\n ): Promise<ExecuteResponse> {\n try {\n const targetSessionId = options.sessionId || this.sessionId;\n const executeRequest = {\n command,\n sessionId: targetSessionId,\n cwd: options.cwd,\n env: options.env,\n } satisfies ExecuteRequest;\n\n const response = await this.doFetch(`/api/execute`, {\n body: JSON.stringify(executeRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: ExecuteResponse = await response.json();\n console.log(\n `[HTTP Client] Command executed: ${command}, Success: ${data.success}`\n );\n\n // Call the callback if provided\n this.options.onCommandComplete?.(\n data.success,\n data.exitCode,\n data.stdout,\n data.stderr,\n data.command\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error executing command:\", error);\n this.options.onError?.(\n error instanceof Error ? error.message : \"Unknown error\",\n command\n );\n throw error;\n }\n }\n\n async executeCommandStream(\n command: string,\n sessionId?: string\n ): Promise<ReadableStream<Uint8Array>> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/execute/stream`, {\n body: JSON.stringify({\n command,\n sessionId: targetSessionId,\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n if (!response.body) {\n throw new Error(\"No response body for streaming request\");\n }\n\n console.log(`[HTTP Client] Started command stream: ${command}`);\n\n return response.body;\n } catch (error) {\n console.error(\"[HTTP Client] Error in command stream:\", error);\n throw error;\n }\n }\n\n async gitCheckout(\n repoUrl: string,\n branch: string = \"main\",\n targetDir?: string,\n sessionId?: string\n ): Promise<GitCheckoutResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/git/checkout`, {\n body: JSON.stringify({\n branch,\n repoUrl,\n sessionId: targetSessionId,\n targetDir,\n } as GitCheckoutRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: GitCheckoutResponse = await response.json();\n console.log(\n `[HTTP Client] Git checkout completed: ${repoUrl}, Success: ${data.success}, Target: ${data.targetDir}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error in git checkout:\", error);\n throw error;\n }\n }\n\n async mkdir(\n path: string,\n recursive: boolean = false,\n sessionId?: string\n ): Promise<MkdirResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/mkdir`, {\n body: JSON.stringify({\n path,\n recursive,\n sessionId: targetSessionId,\n } as MkdirRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: MkdirResponse = await response.json();\n console.log(\n `[HTTP Client] Directory created: ${path}, Success: ${data.success}, Recursive: ${data.recursive}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error creating directory:\", error);\n throw error;\n }\n }\n\n async writeFile(\n path: string,\n content: string,\n encoding: string = \"utf-8\",\n sessionId?: string\n ): Promise<WriteFileResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/write`, {\n body: JSON.stringify({\n content,\n encoding,\n path,\n sessionId: targetSessionId,\n } as WriteFileRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: WriteFileResponse = await response.json();\n console.log(\n `[HTTP Client] File written: ${path}, Success: ${data.success}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error writing file:\", error);\n throw error;\n }\n }\n\n async readFile(\n path: string,\n encoding: string = \"utf-8\",\n sessionId?: string\n ): Promise<ReadFileResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/read`, {\n body: JSON.stringify({\n encoding,\n path,\n sessionId: targetSessionId,\n } as ReadFileRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: ReadFileResponse = await response.json();\n console.log(\n `[HTTP Client] File read: ${path}, Success: ${data.success}, Content length: ${data.content.length}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error reading file:\", error);\n throw error;\n }\n }\n\n async deleteFile(\n path: string,\n sessionId?: string\n ): Promise<DeleteFileResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/delete`, {\n body: JSON.stringify({\n path,\n sessionId: targetSessionId,\n } as DeleteFileRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: DeleteFileResponse = await response.json();\n console.log(\n `[HTTP Client] File deleted: ${path}, Success: ${data.success}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error deleting file:\", error);\n throw error;\n }\n }\n\n async renameFile(\n oldPath: string,\n newPath: string,\n sessionId?: string\n ): Promise<RenameFileResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/rename`, {\n body: JSON.stringify({\n newPath,\n oldPath,\n sessionId: targetSessionId,\n } as RenameFileRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: RenameFileResponse = await response.json();\n console.log(\n `[HTTP Client] File renamed: ${oldPath} -> ${newPath}, Success: ${data.success}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error renaming file:\", error);\n throw error;\n }\n }\n\n async moveFile(\n sourcePath: string,\n destinationPath: string,\n sessionId?: string\n ): Promise<MoveFileResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/move`, {\n body: JSON.stringify({\n destinationPath,\n sessionId: targetSessionId,\n sourcePath,\n } as MoveFileRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: MoveFileResponse = await response.json();\n console.log(\n `[HTTP Client] File moved: ${sourcePath} -> ${destinationPath}, Success: ${data.success}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error moving file:\", error);\n throw error;\n }\n }\n\n async listFiles(\n path: string,\n options?: {\n recursive?: boolean;\n includeHidden?: boolean;\n },\n sessionId?: string\n ): Promise<ListFilesResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/list-files`, {\n body: JSON.stringify({\n path,\n options,\n sessionId: targetSessionId,\n } as ListFilesRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: ListFilesResponse = await response.json();\n console.log(\n `[HTTP Client] Listed ${data.files.length} files in: ${path}, Success: ${data.success}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error listing files:\", error);\n throw error;\n }\n }\n\n async exposePort(port: number, name?: string): Promise<ExposePortResponse> {\n try {\n const response = await this.doFetch(`/api/expose-port`, {\n body: JSON.stringify({\n port,\n name,\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n console.log(errorData);\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: ExposePortResponse = await response.json();\n console.log(\n `[HTTP Client] Port exposed: ${port}${\n name ? ` (${name})` : \"\"\n }, Success: ${data.success}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error exposing port:\", error);\n throw error;\n }\n }\n\n async unexposePort(port: number): Promise<UnexposePortResponse> {\n try {\n const response = await this.doFetch(`/api/unexpose-port`, {\n body: JSON.stringify({\n port,\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"DELETE\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: UnexposePortResponse = await response.json();\n console.log(\n `[HTTP Client] Port unexposed: ${port}, Success: ${data.success}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error unexposing port:\", error);\n throw error;\n }\n }\n\n async getExposedPorts(): Promise<GetExposedPortsResponse> {\n try {\n const response = await this.doFetch(`/api/exposed-ports`, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: GetExposedPortsResponse = await response.json();\n console.log(`[HTTP Client] Got ${data.count} exposed ports`);\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error getting exposed ports:\", error);\n throw error;\n }\n }\n\n async ping(): Promise<string> {\n try {\n const response = await this.doFetch(`/api/ping`, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const data: PingResponse = await response.json();\n console.log(`[HTTP Client] Ping response: ${data.message}`);\n return data.timestamp;\n } catch (error) {\n console.error(\"[HTTP Client] Error pinging server:\", error);\n throw error;\n }\n }\n\n async getCommands(): Promise<string[]> {\n try {\n const response = await fetch(`${this.baseUrl}/api/commands`, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const data: CommandsResponse = await response.json();\n console.log(\n `[HTTP Client] Available commands: ${data.availableCommands.length}`\n );\n return data.availableCommands;\n } catch (error) {\n console.error(\"[HTTP Client] Error getting commands:\", error);\n throw error;\n }\n }\n\n getSessionId(): string | null {\n return this.sessionId;\n }\n\n setSessionId(sessionId: string): void {\n this.sessionId = sessionId;\n }\n\n clearSession(): void {\n this.sessionId = null;\n }\n\n // Process management methods\n async startProcess(\n command: string,\n options?: {\n processId?: string;\n sessionId?: string;\n timeout?: number;\n env?: Record<string, string>;\n cwd?: string;\n encoding?: string;\n autoCleanup?: boolean;\n }\n ): Promise<StartProcessResponse> {\n try {\n const targetSessionId = options?.sessionId || this.sessionId;\n\n const response = await this.doFetch(\"/api/process/start\", {\n body: JSON.stringify({\n command,\n options: {\n ...options,\n sessionId: targetSessionId,\n },\n } as StartProcessRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: StartProcessResponse = await response.json();\n console.log(\n `[HTTP Client] Process started: ${command}, ID: ${data.process.id}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error starting process:\", error);\n throw error;\n }\n }\n\n async listProcesses(): Promise<ListProcessesResponse> {\n try {\n const response = await this.doFetch(\"/api/process/list\", {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: ListProcessesResponse = await response.json();\n console.log(`[HTTP Client] Listed ${data.processes.length} processes`);\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error listing processes:\", error);\n throw error;\n }\n }\n\n async getProcess(processId: string): Promise<GetProcessResponse> {\n try {\n const response = await this.doFetch(`/api/process/${processId}`, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: GetProcessResponse = await response.json();\n console.log(\n `[HTTP Client] Got process ${processId}: ${\n data.process?.status || \"not found\"\n }`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error getting process:\", error);\n throw error;\n }\n }\n\n async killProcess(\n processId: string\n ): Promise<{ success: boolean; message: string }> {\n try {\n const response = await this.doFetch(`/api/process/${processId}`, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"DELETE\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data = (await response.json()) as {\n success: boolean;\n message: string;\n };\n console.log(`[HTTP Client] Killed process ${processId}`);\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error killing process:\", error);\n throw error;\n }\n }\n\n async killAllProcesses(): Promise<{\n success: boolean;\n killedCount: number;\n message: string;\n }> {\n try {\n const response = await this.doFetch(\"/api/process/kill-all\", {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"DELETE\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data = (await response.json()) as {\n success: boolean;\n killedCount: number;\n message: string;\n };\n console.log(`[HTTP Client] Killed ${data.killedCount} processes`);\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error killing all processes:\", error);\n throw error;\n }\n }\n\n async getProcessLogs(processId: string): Promise<GetProcessLogsResponse> {\n try {\n const response = await this.doFetch(`/api/process/${processId}/logs`, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: GetProcessLogsResponse = await response.json();\n console.log(`[HTTP Client] Got logs for process ${processId}`);\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error getting process logs:\", error);\n throw error;\n }\n }\n\n async streamProcessLogs(\n processId: string\n ): Promise<ReadableStream<Uint8Array>> {\n try {\n const response = await this.doFetch(`/api/process/${processId}/stream`, {\n headers: {\n Accept: \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n if (!response.body) {\n throw new Error(\"No response body for streaming request\");\n }\n\n console.log(\n `[HTTP Client] Started streaming logs for process ${processId}`\n );\n\n return response.body;\n } catch (error) {\n console.error(\"[HTTP Client] Error streaming process logs:\", error);\n throw error;\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -43,4 +43,4 @@ export {
43
43
  isProcess,
44
44
  isProcessStatus
45
45
  };
46
- //# sourceMappingURL=chunk-S5FFBU4Y.js.map
46
+ //# sourceMappingURL=chunk-6EWSYSO7.js.map