@cloudflare/sandbox 0.3.7 → 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 -14
  3. package/Dockerfile +82 -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
@@ -1,568 +0,0 @@
1
- import type { Session, SessionManager } from "../isolation";
2
- import type { ProcessRecord, ProcessStatus, StartProcessRequest } from "../types";
3
-
4
- // Process management handlers - all processes are tracked per-session
5
-
6
- // Helper types for process responses
7
- interface ProcessInfo {
8
- id: string;
9
- pid?: number;
10
- command: string;
11
- status: ProcessStatus;
12
- startTime: string;
13
- endTime?: string | null;
14
- exitCode?: number | null;
15
- sessionId: string;
16
- }
17
-
18
- // Helper functions to reduce repetition
19
- function createErrorResponse(
20
- error: string,
21
- message?: string,
22
- status: number = 500,
23
- corsHeaders: Record<string, string> = {}
24
- ): Response {
25
- return new Response(
26
- JSON.stringify({
27
- error,
28
- ...(message && { message })
29
- }),
30
- {
31
- headers: {
32
- "Content-Type": "application/json",
33
- ...corsHeaders,
34
- },
35
- status,
36
- }
37
- );
38
- }
39
-
40
- function createSuccessResponse(
41
- data: Record<string, unknown>,
42
- corsHeaders: Record<string, string> = {}
43
- ): Response {
44
- return new Response(
45
- JSON.stringify(data),
46
- {
47
- headers: {
48
- "Content-Type": "application/json",
49
- ...corsHeaders,
50
- },
51
- }
52
- );
53
- }
54
-
55
- function processRecordToInfo(
56
- record: ProcessRecord,
57
- sessionId: string
58
- ): ProcessInfo {
59
- return {
60
- id: record.id,
61
- pid: record.pid,
62
- command: record.command,
63
- status: record.status,
64
- startTime: record.startTime.toISOString(),
65
- endTime: record.endTime ? record.endTime.toISOString() : null,
66
- exitCode: record.exitCode ?? null,
67
- sessionId
68
- };
69
- }
70
-
71
- async function findProcessAcrossSessions(
72
- processId: string,
73
- sessionManager: SessionManager
74
- ): Promise<{ process: ProcessRecord; sessionId: string } | null> {
75
- for (const sessionId of sessionManager.listSessions()) {
76
- const session = sessionManager.getSession(sessionId);
77
- if (session) {
78
- const process = await session.getProcess(processId);
79
- if (process) {
80
- return { process, sessionId };
81
- }
82
- }
83
- }
84
- return null;
85
- }
86
-
87
- export async function handleStartProcessRequest(
88
- req: Request,
89
- corsHeaders: Record<string, string>,
90
- sessionManager?: SessionManager
91
- ): Promise<Response> {
92
- try {
93
- const body = (await req.json()) as StartProcessRequest;
94
- const { command, sessionId, options = {} } = body;
95
-
96
- if (!command || typeof command !== "string") {
97
- return createErrorResponse(
98
- "Command is required and must be a string",
99
- undefined,
100
- 400,
101
- corsHeaders
102
- );
103
- }
104
-
105
- if (!sessionManager) {
106
- return createErrorResponse(
107
- "Session manager is required for process management",
108
- undefined,
109
- 500,
110
- corsHeaders
111
- );
112
- }
113
-
114
- console.log(`[Server] Starting process: ${command}${sessionId ? ` in session: ${sessionId}` : ' (default session)'}`);
115
-
116
- // Get the session (use default if not specified)
117
- let session: Session;
118
-
119
- if (sessionId) {
120
- const specificSession = sessionManager.getSession(sessionId);
121
- if (!specificSession) {
122
- return createErrorResponse(
123
- `Session '${sessionId}' not found`,
124
- undefined,
125
- 404,
126
- corsHeaders
127
- );
128
- }
129
- session = specificSession;
130
- } else {
131
- // Use the centralized method to get or create default session
132
- session = await sessionManager.getOrCreateDefaultSession();
133
- }
134
-
135
- const processRecord = await session.startProcess(command, options);
136
-
137
- return createSuccessResponse({
138
- process: processRecordToInfo(processRecord, sessionId || 'default')
139
- }, corsHeaders);
140
- } catch (error) {
141
- console.error("[Server] Error starting process:", error);
142
- return createErrorResponse(
143
- "Failed to start process",
144
- error instanceof Error ? error.message : "Unknown error",
145
- 500,
146
- corsHeaders
147
- );
148
- }
149
- }
150
-
151
- export async function handleListProcessesRequest(
152
- req: Request,
153
- corsHeaders: Record<string, string>,
154
- sessionManager?: SessionManager
155
- ): Promise<Response> {
156
- try {
157
- if (!sessionManager) {
158
- return createErrorResponse(
159
- "Session manager is required",
160
- undefined,
161
- 500,
162
- corsHeaders
163
- );
164
- }
165
-
166
- // Get the session name from query params if provided
167
- const url = new URL(req.url);
168
- const sessionId = url.searchParams.get('session');
169
-
170
- let allProcesses: ProcessInfo[] = [];
171
-
172
- if (sessionId) {
173
- // List processes from specific session
174
- const session = sessionManager.getSession(sessionId);
175
- if (!session) {
176
- return createErrorResponse(
177
- `Session '${sessionId}' not found`,
178
- undefined,
179
- 404,
180
- corsHeaders
181
- );
182
- }
183
- const processes = await session.listProcesses();
184
- allProcesses = processes.map(p => processRecordToInfo(p, sessionId));
185
- } else {
186
- // List processes from all sessions
187
- for (const name of sessionManager.listSessions()) {
188
- const session = sessionManager.getSession(name);
189
- if (session) {
190
- const processes = await session.listProcesses();
191
- allProcesses.push(...processes.map(p => processRecordToInfo(p, name)));
192
- }
193
- }
194
- }
195
-
196
- return createSuccessResponse({
197
- processes: allProcesses,
198
- count: allProcesses.length,
199
- timestamp: new Date().toISOString(),
200
- }, corsHeaders);
201
- } catch (error) {
202
- console.error("[Server] Error listing processes:", error);
203
- return createErrorResponse(
204
- "Failed to list processes",
205
- error instanceof Error ? error.message : "Unknown error",
206
- 500,
207
- corsHeaders
208
- );
209
- }
210
- }
211
-
212
- export async function handleGetProcessRequest(
213
- req: Request,
214
- corsHeaders: Record<string, string>,
215
- processId: string,
216
- sessionManager?: SessionManager
217
- ): Promise<Response> {
218
- try {
219
- if (!sessionManager) {
220
- return createErrorResponse(
221
- "Session manager is required",
222
- undefined,
223
- 500,
224
- corsHeaders
225
- );
226
- }
227
-
228
- const result = await findProcessAcrossSessions(processId, sessionManager);
229
- if (!result) {
230
- return createErrorResponse(
231
- "Process not found",
232
- processId,
233
- 404,
234
- corsHeaders
235
- );
236
- }
237
-
238
- return createSuccessResponse({
239
- process: processRecordToInfo(result.process, result.sessionId),
240
- timestamp: new Date().toISOString(),
241
- }, corsHeaders);
242
- } catch (error) {
243
- console.error("[Server] Error getting process:", error);
244
- return createErrorResponse(
245
- "Failed to get process",
246
- error instanceof Error ? error.message : "Unknown error",
247
- 500,
248
- corsHeaders
249
- );
250
- }
251
- }
252
-
253
- export async function handleKillProcessRequest(
254
- req: Request,
255
- corsHeaders: Record<string, string>,
256
- processId: string,
257
- sessionManager?: SessionManager
258
- ): Promise<Response> {
259
- try {
260
- if (!sessionManager) {
261
- return createErrorResponse(
262
- "Session manager is required",
263
- undefined,
264
- 500,
265
- corsHeaders
266
- );
267
- }
268
-
269
- // Search for and kill the process across all sessions
270
- for (const sessionId of sessionManager.listSessions()) {
271
- const session = sessionManager.getSession(sessionId);
272
- if (session) {
273
- const process = await session.getProcess(processId);
274
- if (process) {
275
- const killed = await session.killProcess(processId);
276
- return createSuccessResponse({
277
- success: killed,
278
- processId,
279
- sessionId,
280
- message: killed ? `Process ${processId} killed` : `Failed to kill process ${processId}`,
281
- timestamp: new Date().toISOString(),
282
- }, corsHeaders);
283
- }
284
- }
285
- }
286
-
287
- return createErrorResponse(
288
- "Process not found",
289
- processId,
290
- 404,
291
- corsHeaders
292
- );
293
- } catch (error) {
294
- console.error("[Server] Error killing process:", error);
295
- return createErrorResponse(
296
- "Failed to kill process",
297
- error instanceof Error ? error.message : "Unknown error",
298
- 500,
299
- corsHeaders
300
- );
301
- }
302
- }
303
-
304
- export async function handleKillAllProcessesRequest(
305
- req: Request,
306
- corsHeaders: Record<string, string>,
307
- sessionManager?: SessionManager
308
- ): Promise<Response> {
309
- try {
310
- if (!sessionManager) {
311
- return createErrorResponse(
312
- "Session manager is required",
313
- undefined,
314
- 500,
315
- corsHeaders
316
- );
317
- }
318
-
319
- // Get the session name from query params if provided
320
- const url = new URL(req.url);
321
- const sessionId = url.searchParams.get('session');
322
-
323
- let killedCount = 0;
324
-
325
- if (sessionId) {
326
- // Kill processes in specific session
327
- const session = sessionManager.getSession(sessionId);
328
- if (!session) {
329
- return createErrorResponse(
330
- `Session '${sessionId}' not found`,
331
- undefined,
332
- 404,
333
- corsHeaders
334
- );
335
- }
336
- killedCount = await session.killAllProcesses();
337
- } else {
338
- // Kill processes in all sessions
339
- for (const name of sessionManager.listSessions()) {
340
- const session = sessionManager.getSession(name);
341
- if (session) {
342
- killedCount += await session.killAllProcesses();
343
- }
344
- }
345
- }
346
-
347
- return createSuccessResponse({
348
- success: true,
349
- killedCount,
350
- message: `Killed ${killedCount} process${killedCount !== 1 ? 'es' : ''}`,
351
- timestamp: new Date().toISOString(),
352
- }, corsHeaders);
353
- } catch (error) {
354
- console.error("[Server] Error killing all processes:", error);
355
- return createErrorResponse(
356
- "Failed to kill all processes",
357
- error instanceof Error ? error.message : "Unknown error",
358
- 500,
359
- corsHeaders
360
- );
361
- }
362
- }
363
-
364
- export async function handleGetProcessLogsRequest(
365
- req: Request,
366
- corsHeaders: Record<string, string>,
367
- processId: string,
368
- sessionManager?: SessionManager
369
- ): Promise<Response> {
370
- try {
371
- if (!sessionManager) {
372
- return createErrorResponse(
373
- "Session manager is required",
374
- undefined,
375
- 500,
376
- corsHeaders
377
- );
378
- }
379
-
380
- const result = await findProcessAcrossSessions(processId, sessionManager);
381
- if (!result) {
382
- return createErrorResponse(
383
- "Process not found",
384
- processId,
385
- 404,
386
- corsHeaders
387
- );
388
- }
389
-
390
- // Get the session and use its getProcessLogs method to ensure logs are updated from files
391
- const session = sessionManager.getSession(result.sessionId);
392
- if (!session) {
393
- return createErrorResponse(
394
- "Session not found",
395
- result.sessionId,
396
- 500,
397
- corsHeaders
398
- );
399
- }
400
-
401
- // This will update logs from temp files before returning
402
- const logs = await session.getProcessLogs(processId);
403
-
404
- return createSuccessResponse({
405
- stdout: logs.stdout,
406
- stderr: logs.stderr,
407
- processId,
408
- sessionId: result.sessionId,
409
- timestamp: new Date().toISOString(),
410
- }, corsHeaders);
411
- } catch (error) {
412
- console.error("[Server] Error getting process logs:", error);
413
- return createErrorResponse(
414
- "Failed to get process logs",
415
- error instanceof Error ? error.message : "Unknown error",
416
- 500,
417
- corsHeaders
418
- );
419
- }
420
- }
421
-
422
- export async function handleStreamProcessLogsRequest(
423
- req: Request,
424
- corsHeaders: Record<string, string>,
425
- processId: string,
426
- sessionManager?: SessionManager
427
- ): Promise<Response> {
428
- try {
429
- if (!sessionManager) {
430
- return createErrorResponse(
431
- "Session manager is required",
432
- undefined,
433
- 500,
434
- corsHeaders
435
- );
436
- }
437
-
438
- const result = await findProcessAcrossSessions(processId, sessionManager);
439
- if (!result) {
440
- return createErrorResponse(
441
- "Process not found",
442
- processId,
443
- 404,
444
- corsHeaders
445
- );
446
- }
447
-
448
- const { process: targetProcess, sessionId } = result;
449
-
450
- // Get the session to start monitoring
451
- const session = sessionManager.getSession(sessionId);
452
- if (!session) {
453
- return createErrorResponse(
454
- "Session not found",
455
- sessionId,
456
- 404,
457
- corsHeaders
458
- );
459
- }
460
-
461
- // Store listeners outside the stream for proper cleanup
462
- let outputListener: ((stream: 'stdout' | 'stderr', data: string) => void) | null = null;
463
- let statusListener: ((status: ProcessStatus) => void) | null = null;
464
-
465
- // Create a stream that sends updates
466
- const stream = new ReadableStream({
467
- start(controller) {
468
- // Send initial logs
469
- if (targetProcess.stdout) {
470
- controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify({
471
- type: 'stdout',
472
- data: targetProcess.stdout,
473
- processId,
474
- sessionId,
475
- timestamp: new Date().toISOString()
476
- })}\n\n`));
477
- }
478
-
479
- if (targetProcess.stderr) {
480
- controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify({
481
- type: 'stderr',
482
- data: targetProcess.stderr,
483
- processId,
484
- sessionId,
485
- timestamp: new Date().toISOString()
486
- })}\n\n`));
487
- }
488
-
489
- // If process is complete, send completion and close
490
- if (targetProcess.status === 'completed' || targetProcess.status === 'failed' || targetProcess.status === 'killed') {
491
- controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify({
492
- type: 'complete',
493
- status: targetProcess.status,
494
- exitCode: targetProcess.exitCode,
495
- processId,
496
- sessionId,
497
- timestamp: new Date().toISOString()
498
- })}\n\n`));
499
- controller.close();
500
- return;
501
- }
502
-
503
- // Set up listeners for live updates
504
- outputListener = (stream: 'stdout' | 'stderr', data: string) => {
505
- controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify({
506
- type: stream,
507
- data,
508
- processId,
509
- sessionId,
510
- timestamp: new Date().toISOString()
511
- })}\n\n`));
512
- };
513
-
514
- statusListener = (status: ProcessStatus) => {
515
- if (status === 'completed' || status === 'failed' || status === 'killed') {
516
- controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify({
517
- type: 'complete',
518
- status,
519
- exitCode: targetProcess.exitCode,
520
- processId,
521
- sessionId,
522
- timestamp: new Date().toISOString()
523
- })}\n\n`));
524
- controller.close();
525
- }
526
- };
527
-
528
- targetProcess.outputListeners.add(outputListener);
529
- targetProcess.statusListeners.add(statusListener);
530
-
531
- // Start monitoring the process for output changes
532
- session.startProcessMonitoring(targetProcess);
533
- },
534
- cancel() {
535
- // Clean up when stream is closed (client disconnects)
536
- // Remove only this stream's listeners, not all listeners
537
- if (outputListener) {
538
- targetProcess.outputListeners.delete(outputListener);
539
- }
540
- if (statusListener) {
541
- targetProcess.statusListeners.delete(statusListener);
542
- }
543
-
544
- // Stop monitoring if no more listeners
545
- if (targetProcess.outputListeners.size === 0) {
546
- session.stopProcessMonitoring(targetProcess);
547
- }
548
- }
549
- });
550
-
551
- return new Response(stream, {
552
- headers: {
553
- "Content-Type": "text/event-stream",
554
- "Cache-Control": "no-cache",
555
- "Connection": "keep-alive",
556
- ...corsHeaders,
557
- },
558
- });
559
- } catch (error) {
560
- console.error("[Server] Error streaming process logs:", error);
561
- return createErrorResponse(
562
- "Failed to stream process logs",
563
- error instanceof Error ? error.message : "Unknown error",
564
- 500,
565
- corsHeaders
566
- );
567
- }
568
- }
@@ -1,92 +0,0 @@
1
- import type { SessionManager } from "../isolation";
2
- import type { CreateSessionRequest } from "../types";
3
-
4
- export async function handleCreateSession(
5
- req: Request,
6
- corsHeaders: Record<string, string>,
7
- sessionManager: SessionManager
8
- ) {
9
- try {
10
- const body = (await req.json()) as CreateSessionRequest;
11
- const { id, env, cwd, isolation } = body;
12
-
13
- if (!id) {
14
- return new Response(
15
- JSON.stringify({ error: "Session ID is required" }),
16
- {
17
- status: 400,
18
- headers: {
19
- "Content-Type": "application/json",
20
- ...corsHeaders,
21
- },
22
- }
23
- );
24
- }
25
-
26
- await sessionManager.createSession({
27
- id,
28
- env: env || {},
29
- cwd: cwd || "/workspace",
30
- isolation: isolation !== false,
31
- });
32
-
33
- console.log(`[Container] Session '${id}' created successfully`);
34
- console.log(
35
- `[Container] Available sessions now: ${sessionManager
36
- .listSessions()
37
- .join(", ")}`
38
- );
39
-
40
- return new Response(
41
- JSON.stringify({
42
- success: true,
43
- id,
44
- message: `Session '${id}' created with${
45
- isolation !== false ? "" : "out"
46
- } isolation`,
47
- }),
48
- {
49
- headers: {
50
- "Content-Type": "application/json",
51
- ...corsHeaders,
52
- },
53
- }
54
- );
55
- } catch (error) {
56
- console.error("[Container] Failed to create session:", error);
57
- return new Response(
58
- JSON.stringify({
59
- error: "Failed to create session",
60
- message:
61
- error instanceof Error ? error.message : String(error),
62
- }),
63
- {
64
- status: 500,
65
- headers: {
66
- "Content-Type": "application/json",
67
- ...corsHeaders,
68
- },
69
- }
70
- );
71
- }
72
- }
73
-
74
- export function handleListSessions(
75
- corsHeaders: Record<string, string>,
76
- sessionManager: SessionManager
77
- ) {
78
- const sessionList = sessionManager.listSessions();
79
- return new Response(
80
- JSON.stringify({
81
- count: sessionList.length,
82
- sessions: sessionList,
83
- timestamp: new Date().toISOString(),
84
- }),
85
- {
86
- headers: {
87
- "Content-Type": "application/json",
88
- ...corsHeaders,
89
- },
90
- }
91
- );
92
- }