@treesap/sandbox 0.2.0

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 (66) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/README.md +495 -0
  3. package/dist/api-server.d.ts +41 -0
  4. package/dist/api-server.d.ts.map +1 -0
  5. package/dist/api-server.js +536 -0
  6. package/dist/api-server.js.map +1 -0
  7. package/dist/auth-middleware.d.ts +31 -0
  8. package/dist/auth-middleware.d.ts.map +1 -0
  9. package/dist/auth-middleware.js +35 -0
  10. package/dist/auth-middleware.js.map +1 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +65 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/client.d.ts +137 -0
  16. package/dist/client.d.ts.map +1 -0
  17. package/dist/client.js +412 -0
  18. package/dist/client.js.map +1 -0
  19. package/dist/file-service.d.ts +94 -0
  20. package/dist/file-service.d.ts.map +1 -0
  21. package/dist/file-service.js +203 -0
  22. package/dist/file-service.js.map +1 -0
  23. package/dist/http-exposure-service.d.ts +71 -0
  24. package/dist/http-exposure-service.d.ts.map +1 -0
  25. package/dist/http-exposure-service.js +172 -0
  26. package/dist/http-exposure-service.js.map +1 -0
  27. package/dist/index.d.ts +59 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +66 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/sandbox-manager.d.ts +76 -0
  32. package/dist/sandbox-manager.d.ts.map +1 -0
  33. package/dist/sandbox-manager.js +161 -0
  34. package/dist/sandbox-manager.js.map +1 -0
  35. package/dist/sandbox.d.ts +118 -0
  36. package/dist/sandbox.d.ts.map +1 -0
  37. package/dist/sandbox.js +303 -0
  38. package/dist/sandbox.js.map +1 -0
  39. package/dist/server.d.ts +7 -0
  40. package/dist/server.d.ts.map +1 -0
  41. package/dist/server.js +240 -0
  42. package/dist/server.js.map +1 -0
  43. package/dist/stream-service.d.ts +35 -0
  44. package/dist/stream-service.d.ts.map +1 -0
  45. package/dist/stream-service.js +136 -0
  46. package/dist/stream-service.js.map +1 -0
  47. package/dist/terminal.d.ts +46 -0
  48. package/dist/terminal.d.ts.map +1 -0
  49. package/dist/terminal.js +264 -0
  50. package/dist/terminal.js.map +1 -0
  51. package/dist/websocket.d.ts +48 -0
  52. package/dist/websocket.d.ts.map +1 -0
  53. package/dist/websocket.js +332 -0
  54. package/dist/websocket.js.map +1 -0
  55. package/package.json +59 -0
  56. package/src/api-server.ts +658 -0
  57. package/src/auth-middleware.ts +65 -0
  58. package/src/cli.ts +71 -0
  59. package/src/client.ts +537 -0
  60. package/src/file-service.ts +273 -0
  61. package/src/http-exposure-service.ts +232 -0
  62. package/src/index.ts +101 -0
  63. package/src/sandbox-manager.ts +202 -0
  64. package/src/sandbox.ts +396 -0
  65. package/src/stream-service.ts +174 -0
  66. package/tsconfig.json +37 -0
@@ -0,0 +1,303 @@
1
+ import { spawn } from 'child_process';
2
+ import * as fs from 'fs/promises';
3
+ import * as path from 'path';
4
+ import { EventEmitter } from 'events';
5
+ import { v4 as uuidv4 } from 'uuid';
6
+ /**
7
+ * Represents a single isolated sandbox instance
8
+ * Each sandbox has its own working directory and process management
9
+ */
10
+ export class Sandbox extends EventEmitter {
11
+ id;
12
+ workDir;
13
+ createdAt;
14
+ processes = new Map();
15
+ runningProcesses = new Map();
16
+ config;
17
+ destroyed = false;
18
+ constructor(config = {}) {
19
+ super();
20
+ this.id = config.id || uuidv4();
21
+ this.workDir = config.workDir || path.join(process.cwd(), '.sandboxes', this.id);
22
+ this.config = { ...config, env: config.env || {} };
23
+ this.createdAt = Date.now();
24
+ }
25
+ /**
26
+ * Initialize the sandbox (create working directory)
27
+ */
28
+ async initialize() {
29
+ if (this.destroyed) {
30
+ throw new Error('Sandbox has been destroyed');
31
+ }
32
+ // Create working directory
33
+ await fs.mkdir(this.workDir, { recursive: true });
34
+ this.emit('initialized', { id: this.id, workDir: this.workDir });
35
+ }
36
+ /**
37
+ * Execute a command and return the complete result
38
+ */
39
+ async exec(command, options = {}) {
40
+ if (this.destroyed) {
41
+ throw new Error('Sandbox has been destroyed');
42
+ }
43
+ return new Promise((resolve) => {
44
+ let stdout = '';
45
+ let stderr = '';
46
+ let timedOut = false;
47
+ // Parse command and args
48
+ const [cmd, ...args] = this.parseCommand(command);
49
+ const childProcess = spawn(cmd, args, {
50
+ cwd: options.cwd || this.workDir,
51
+ env: { ...process.env, ...this.config.env, ...options.env },
52
+ shell: true,
53
+ });
54
+ // Handle timeout
55
+ let timeoutId;
56
+ const timeout = options.timeout || this.config.timeout;
57
+ if (timeout) {
58
+ timeoutId = setTimeout(() => {
59
+ timedOut = true;
60
+ childProcess.kill('SIGTERM');
61
+ // Force kill after 5 seconds
62
+ setTimeout(() => {
63
+ if (!childProcess.killed) {
64
+ childProcess.kill('SIGKILL');
65
+ }
66
+ }, 5000);
67
+ }, timeout);
68
+ }
69
+ // Capture stdout
70
+ childProcess.stdout?.on('data', (data) => {
71
+ const text = data.toString();
72
+ stdout += text;
73
+ if (options.stream && options.onOutput) {
74
+ options.onOutput('stdout', text);
75
+ }
76
+ this.emit('output', { stream: 'stdout', data: text });
77
+ });
78
+ // Capture stderr
79
+ childProcess.stderr?.on('data', (data) => {
80
+ const text = data.toString();
81
+ stderr += text;
82
+ if (options.stream && options.onOutput) {
83
+ options.onOutput('stderr', text);
84
+ }
85
+ this.emit('output', { stream: 'stderr', data: text });
86
+ });
87
+ // Handle process completion
88
+ childProcess.on('close', (exitCode) => {
89
+ if (timeoutId) {
90
+ clearTimeout(timeoutId);
91
+ }
92
+ const response = {
93
+ success: !timedOut && exitCode === 0,
94
+ stdout,
95
+ stderr,
96
+ exitCode: exitCode || 0,
97
+ timedOut,
98
+ };
99
+ this.emit('exec_complete', response);
100
+ resolve(response);
101
+ });
102
+ childProcess.on('error', (error) => {
103
+ if (timeoutId) {
104
+ clearTimeout(timeoutId);
105
+ }
106
+ const response = {
107
+ success: false,
108
+ stdout,
109
+ stderr: stderr + '\n' + error.message,
110
+ exitCode: 1,
111
+ };
112
+ this.emit('exec_error', error);
113
+ resolve(response);
114
+ });
115
+ });
116
+ }
117
+ /**
118
+ * Start a long-running background process
119
+ */
120
+ async startProcess(command, options = {}) {
121
+ if (this.destroyed) {
122
+ throw new Error('Sandbox has been destroyed');
123
+ }
124
+ // Check max processes limit
125
+ if (this.config.maxProcesses && this.runningProcesses.size >= this.config.maxProcesses) {
126
+ throw new Error(`Maximum process limit reached (${this.config.maxProcesses})`);
127
+ }
128
+ const processId = uuidv4();
129
+ const [cmd, ...args] = this.parseCommand(command);
130
+ const childProcess = spawn(cmd, args, {
131
+ cwd: options.cwd || this.workDir,
132
+ env: { ...process.env, ...this.config.env, ...options.env },
133
+ shell: true,
134
+ });
135
+ const processInfo = {
136
+ id: processId,
137
+ pid: childProcess.pid,
138
+ command,
139
+ status: 'running',
140
+ startTime: Date.now(),
141
+ };
142
+ this.processes.set(processId, processInfo);
143
+ this.runningProcesses.set(processId, childProcess);
144
+ // Listen for output
145
+ childProcess.stdout?.on('data', (data) => {
146
+ this.emit('process_output', {
147
+ processId,
148
+ stream: 'stdout',
149
+ data: data.toString(),
150
+ });
151
+ });
152
+ childProcess.stderr?.on('data', (data) => {
153
+ this.emit('process_output', {
154
+ processId,
155
+ stream: 'stderr',
156
+ data: data.toString(),
157
+ });
158
+ });
159
+ // Handle process exit
160
+ childProcess.on('close', (exitCode) => {
161
+ const info = this.processes.get(processId);
162
+ if (info) {
163
+ info.status = exitCode === 0 ? 'completed' : 'failed';
164
+ info.exitCode = exitCode || 0;
165
+ }
166
+ this.runningProcesses.delete(processId);
167
+ this.emit('process_exit', { processId, exitCode });
168
+ });
169
+ this.emit('process_started', processInfo);
170
+ return processInfo;
171
+ }
172
+ /**
173
+ * List all processes (running and completed)
174
+ */
175
+ listProcesses() {
176
+ return Array.from(this.processes.values());
177
+ }
178
+ /**
179
+ * Get information about a specific process
180
+ */
181
+ getProcess(processId) {
182
+ return this.processes.get(processId);
183
+ }
184
+ /**
185
+ * Kill a specific process
186
+ */
187
+ async killProcess(processId, signal = 'SIGTERM') {
188
+ const childProcess = this.runningProcesses.get(processId);
189
+ if (!childProcess) {
190
+ throw new Error(`Process ${processId} not found or already stopped`);
191
+ }
192
+ childProcess.kill(signal);
193
+ // Update process info
194
+ const info = this.processes.get(processId);
195
+ if (info) {
196
+ info.status = 'failed';
197
+ }
198
+ }
199
+ /**
200
+ * Kill all running processes
201
+ */
202
+ async killAllProcesses(signal = 'SIGTERM') {
203
+ const killPromises = Array.from(this.runningProcesses.keys()).map((processId) => this.killProcess(processId, signal).catch(() => {
204
+ // Ignore errors if process already stopped
205
+ }));
206
+ await Promise.all(killPromises);
207
+ }
208
+ /**
209
+ * Get sandbox status
210
+ */
211
+ getStatus() {
212
+ return {
213
+ id: this.id,
214
+ workDir: this.workDir,
215
+ createdAt: this.createdAt,
216
+ uptime: Date.now() - this.createdAt,
217
+ processCount: this.runningProcesses.size,
218
+ totalProcesses: this.processes.size,
219
+ destroyed: this.destroyed,
220
+ };
221
+ }
222
+ // ============================================================================
223
+ // Environment Variable Management
224
+ // ============================================================================
225
+ /**
226
+ * Set a single environment variable
227
+ */
228
+ setEnv(key, value) {
229
+ if (this.destroyed) {
230
+ throw new Error('Sandbox has been destroyed');
231
+ }
232
+ this.config.env[key] = value;
233
+ this.emit('env_changed', { key, value, action: 'set' });
234
+ }
235
+ /**
236
+ * Set multiple environment variables at once
237
+ */
238
+ setEnvBatch(variables) {
239
+ if (this.destroyed) {
240
+ throw new Error('Sandbox has been destroyed');
241
+ }
242
+ for (const [key, value] of Object.entries(variables)) {
243
+ this.config.env[key] = value;
244
+ }
245
+ this.emit('env_changed', { variables, action: 'batch_set' });
246
+ }
247
+ getEnv(key) {
248
+ if (key !== undefined) {
249
+ return this.config.env[key];
250
+ }
251
+ return { ...this.config.env };
252
+ }
253
+ /**
254
+ * Get list of environment variable names (for security, not exposing values)
255
+ */
256
+ getEnvKeys() {
257
+ return Object.keys(this.config.env);
258
+ }
259
+ /**
260
+ * Unset (remove) an environment variable
261
+ */
262
+ unsetEnv(key) {
263
+ if (this.destroyed) {
264
+ throw new Error('Sandbox has been destroyed');
265
+ }
266
+ if (key in this.config.env) {
267
+ delete this.config.env[key];
268
+ this.emit('env_changed', { key, action: 'unset' });
269
+ return true;
270
+ }
271
+ return false;
272
+ }
273
+ /**
274
+ * Destroy the sandbox (kill all processes, optionally clean up files)
275
+ */
276
+ async destroy(options = {}) {
277
+ if (this.destroyed) {
278
+ return;
279
+ }
280
+ // Kill all running processes
281
+ await this.killAllProcesses('SIGKILL');
282
+ // Clean up files if requested
283
+ if (options.cleanup) {
284
+ try {
285
+ await fs.rm(this.workDir, { recursive: true, force: true });
286
+ }
287
+ catch (error) {
288
+ // Ignore cleanup errors
289
+ }
290
+ }
291
+ this.destroyed = true;
292
+ this.emit('destroyed', { id: this.id });
293
+ this.removeAllListeners();
294
+ }
295
+ /**
296
+ * Parse a command string into command and arguments
297
+ */
298
+ parseCommand(command) {
299
+ // Simple parsing - for more complex commands, shell: true handles it
300
+ return command.split(' ').filter(Boolean);
301
+ }
302
+ }
303
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Server } from 'http';
2
+ export interface SandboxConfig {
3
+ port?: number;
4
+ projectRoot?: string;
5
+ }
6
+ export declare function startSandboxServer(config?: SandboxConfig): Promise<Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>>;
7
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAGnC,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,kBAAkB,CAAC,MAAM,GAAE,aAAkB,gGA4RlE"}
package/dist/server.js ADDED
@@ -0,0 +1,240 @@
1
+ import { Hono } from "hono";
2
+ import { TerminalService } from "./terminal.js";
3
+ import { WebSocketTerminalService } from "./websocket.js";
4
+ import process from "node:process";
5
+ export async function startSandboxServer(config = {}) {
6
+ const { port = 3000, projectRoot = process.cwd() } = config;
7
+ // Change the current working directory to the project root
8
+ process.chdir(projectRoot);
9
+ const app = new Hono();
10
+ // Health check endpoint
11
+ app.get("/", (c) => {
12
+ return c.json({
13
+ status: "ok",
14
+ message: "Treesap Sandbox Server",
15
+ version: "0.1.0",
16
+ endpoints: {
17
+ terminal_sessions: "/api/terminal/sessions",
18
+ websocket: "ws://localhost:" + port + "/terminal/ws"
19
+ }
20
+ });
21
+ });
22
+ // List active terminal sessions with WebSocket client info
23
+ app.get("/api/terminal/sessions", (c) => {
24
+ const sessions = TerminalService.getAllSessions();
25
+ const wsActiveSessions = WebSocketTerminalService.getActiveSessions();
26
+ return c.json({
27
+ sessions: sessions.map(session => {
28
+ const wsInfo = wsActiveSessions.find(ws => ws.sessionId === session.id);
29
+ return {
30
+ id: session.id,
31
+ createdAt: session.createdAt,
32
+ lastActivity: session.lastActivity,
33
+ connectedClients: wsInfo ? wsInfo.clientCount : 0
34
+ };
35
+ }),
36
+ totalConnectedClients: WebSocketTerminalService.getConnectedClients()
37
+ });
38
+ });
39
+ // Get specific terminal session status
40
+ app.get("/api/terminal/sessions/:sessionId/status", (c) => {
41
+ const sessionId = c.req.param('sessionId');
42
+ const session = TerminalService.getSession(sessionId);
43
+ if (!session) {
44
+ return c.json({ error: "Session not found" }, 404);
45
+ }
46
+ const clients = WebSocketTerminalService.getSessionClients(sessionId);
47
+ return c.json({
48
+ id: session.id,
49
+ createdAt: session.createdAt,
50
+ lastActivity: session.lastActivity,
51
+ connectedClients: clients.length,
52
+ clientIds: clients
53
+ });
54
+ });
55
+ // Send command to terminal via API
56
+ app.post("/api/terminal/sessions/:sessionId/command", async (c) => {
57
+ const sessionId = c.req.param('sessionId');
58
+ const body = await c.req.json();
59
+ const { command } = body;
60
+ if (!command) {
61
+ return c.json({ error: "Command is required" }, 400);
62
+ }
63
+ // Get or create terminal session
64
+ let session = TerminalService.getSession(sessionId);
65
+ if (!session) {
66
+ session = TerminalService.createSession(sessionId);
67
+ }
68
+ const success = WebSocketTerminalService.sendCommandToSession(sessionId, command);
69
+ if (success) {
70
+ return c.json({
71
+ success: true,
72
+ message: `Command sent to session ${sessionId}`,
73
+ connectedClients: WebSocketTerminalService.getSessionClients(sessionId).length
74
+ });
75
+ }
76
+ else {
77
+ return c.json({ error: "Failed to send command to terminal" }, 500);
78
+ }
79
+ });
80
+ // Get recent output from terminal session (for API clients)
81
+ app.get("/api/terminal/sessions/:sessionId/output", async (c) => {
82
+ const sessionId = c.req.param('sessionId');
83
+ const session = TerminalService.getSession(sessionId);
84
+ if (!session) {
85
+ return c.json({ error: "Session not found" }, 404);
86
+ }
87
+ // Note: This is a basic implementation. For production, you'd want to
88
+ // store recent output history in the TerminalService
89
+ return c.json({
90
+ sessionId,
91
+ message: "Output streaming available via WebSocket connection",
92
+ connectedClients: WebSocketTerminalService.getSessionClients(sessionId).length,
93
+ websocketUrl: `ws://${c.req.header('host')}/terminal/ws`
94
+ });
95
+ });
96
+ // Terminal endpoints
97
+ app.post("/terminal/execute/:sessionId", async (c) => {
98
+ const sessionId = c.req.param('sessionId');
99
+ const body = await c.req.json();
100
+ const { command } = body;
101
+ if (!command) {
102
+ return c.json({ error: "Command is required" }, 400);
103
+ }
104
+ // Get or create terminal session
105
+ let session = TerminalService.getSession(sessionId);
106
+ if (!session) {
107
+ session = TerminalService.createSession(sessionId);
108
+ }
109
+ const success = TerminalService.executeCommand(sessionId, command);
110
+ if (success) {
111
+ return c.json({ success: true });
112
+ }
113
+ else {
114
+ return c.json({ error: "Failed to execute command" }, 500);
115
+ }
116
+ });
117
+ app.post("/terminal/input/:sessionId", async (c) => {
118
+ const sessionId = c.req.param('sessionId');
119
+ const body = await c.req.json();
120
+ const { input } = body;
121
+ if (input === undefined) {
122
+ return c.json({ error: "Input is required" }, 400);
123
+ }
124
+ // Get or create terminal session
125
+ let session = TerminalService.getSession(sessionId);
126
+ if (!session) {
127
+ session = TerminalService.createSession(sessionId);
128
+ }
129
+ // Send input directly to PTY
130
+ try {
131
+ session.lastActivity = new Date();
132
+ session.process.write(input);
133
+ return c.json({ success: true });
134
+ }
135
+ catch (error) {
136
+ console.error(`Error sending input to session ${sessionId}:`, error);
137
+ return c.json({ error: "Failed to send input" }, 500);
138
+ }
139
+ });
140
+ app.get("/terminal/stream/:sessionId", async (c) => {
141
+ const sessionId = c.req.param('sessionId');
142
+ // Get or create terminal session
143
+ let session = TerminalService.getSession(sessionId);
144
+ if (!session) {
145
+ session = TerminalService.createSession(sessionId);
146
+ }
147
+ // Set SSE headers
148
+ c.header('Content-Type', 'text/event-stream');
149
+ c.header('Cache-Control', 'no-cache');
150
+ c.header('Connection', 'keep-alive');
151
+ c.header('Access-Control-Allow-Origin', '*');
152
+ const stream = new ReadableStream({
153
+ start(controller) {
154
+ const encoder = new TextEncoder();
155
+ // Send initial connection event
156
+ controller.enqueue(encoder.encode(`data: ${JSON.stringify({ type: 'connected' })}\n\n`));
157
+ // Set up output listener
158
+ const handleOutput = (data) => {
159
+ try {
160
+ controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`));
161
+ }
162
+ catch (error) {
163
+ console.error('Error sending terminal output:', error);
164
+ // Remove listener on error to prevent memory leaks
165
+ session.eventEmitter.removeListener('output', handleOutput);
166
+ }
167
+ };
168
+ session.eventEmitter.on('output', handleOutput);
169
+ // Handle client disconnect
170
+ const handleDisconnect = () => {
171
+ try {
172
+ session.eventEmitter.removeListener('output', handleOutput);
173
+ }
174
+ catch (error) {
175
+ console.error('Error removing output listener:', error);
176
+ }
177
+ };
178
+ // Clean up on stream close
179
+ return () => {
180
+ handleDisconnect();
181
+ };
182
+ }
183
+ });
184
+ return new Response(stream, {
185
+ headers: {
186
+ 'Content-Type': 'text/event-stream',
187
+ 'Cache-Control': 'no-cache',
188
+ 'Connection': 'keep-alive',
189
+ 'Access-Control-Allow-Origin': '*'
190
+ }
191
+ });
192
+ });
193
+ // Delete terminal session
194
+ app.delete("/terminal/session/:sessionId", async (c) => {
195
+ const sessionId = c.req.param('sessionId');
196
+ if (!sessionId) {
197
+ return c.json({ error: "Session ID is required" }, 400);
198
+ }
199
+ const success = TerminalService.destroySession(sessionId);
200
+ if (success) {
201
+ return c.json({ message: `Terminal session ${sessionId} destroyed successfully` });
202
+ }
203
+ else {
204
+ console.log(`Terminal session not found: ${sessionId}`);
205
+ return c.json({ error: `Terminal session ${sessionId} not found` }, 404);
206
+ }
207
+ });
208
+ const { serve } = await import('@hono/node-server');
209
+ // Start the server and initialize WebSocket
210
+ const server = serve({
211
+ fetch: app.fetch,
212
+ port,
213
+ });
214
+ // Initialize WebSocket service
215
+ WebSocketTerminalService.initialize(server);
216
+ // Setup global graceful shutdown
217
+ const setupGlobalShutdown = () => {
218
+ const cleanup = async () => {
219
+ console.log('\nšŸ›‘ Shutting down sandbox server and all terminal sessions...');
220
+ // Clean up WebSocket connections
221
+ WebSocketTerminalService.cleanup();
222
+ process.exit(0);
223
+ };
224
+ // Handle Ctrl+C (SIGINT)
225
+ process.on('SIGINT', () => {
226
+ cleanup().catch(() => process.exit(1));
227
+ });
228
+ // Handle termination signal
229
+ process.on('SIGTERM', () => {
230
+ cleanup().catch(() => process.exit(1));
231
+ });
232
+ };
233
+ setupGlobalShutdown();
234
+ // Initialize terminal service cleanup
235
+ TerminalService.setupGlobalCleanup();
236
+ console.log(`\n🌳 Treesap Sandbox Server running at http://localhost:${port}`);
237
+ console.log(`šŸ”Œ WebSocket terminal server available at ws://localhost:${port}/terminal/ws\n`);
238
+ return server;
239
+ }
240
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { Sandbox, ExecOptions } from './sandbox';
2
+ import { Readable } from 'stream';
3
+ export type ExecEventType = 'start' | 'stdout' | 'stderr' | 'complete' | 'error';
4
+ export interface ExecEvent {
5
+ type: ExecEventType;
6
+ data?: string;
7
+ exitCode?: number;
8
+ error?: string;
9
+ timestamp: number;
10
+ }
11
+ export interface LogEvent {
12
+ type: 'log';
13
+ data: string;
14
+ timestamp: number;
15
+ stream?: 'stdout' | 'stderr';
16
+ }
17
+ /**
18
+ * Service for creating Server-Sent Events (SSE) streams
19
+ */
20
+ export declare class StreamService {
21
+ /**
22
+ * Create an SSE stream for command execution
23
+ */
24
+ static createExecStream(sandbox: Sandbox, command: string, options?: ExecOptions): Readable;
25
+ /**
26
+ * Create an SSE stream for process logs
27
+ */
28
+ static createProcessLogStream(sandbox: Sandbox, processId: string): Readable;
29
+ /**
30
+ * Helper to parse SSE stream on client side
31
+ * This is exported for client library usage
32
+ */
33
+ static parseSSEStream<T = ExecEvent | LogEvent>(stream: ReadableStream): AsyncGenerator<T>;
34
+ }
35
+ //# sourceMappingURL=stream-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-service.d.ts","sourceRoot":"","sources":["../src/stream-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;AAEjF,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC9B;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,QAAQ;IAqD/F;;OAEG;IACH,MAAM,CAAC,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ;IA8C5E;;;OAGG;WACW,cAAc,CAAC,CAAC,GAAG,SAAS,GAAG,QAAQ,EACnD,MAAM,EAAE,cAAc,GACrB,cAAc,CAAC,CAAC,CAAC;CAsCrB"}