@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.
- package/CHANGELOG.md +107 -0
- package/README.md +495 -0
- package/dist/api-server.d.ts +41 -0
- package/dist/api-server.d.ts.map +1 -0
- package/dist/api-server.js +536 -0
- package/dist/api-server.js.map +1 -0
- package/dist/auth-middleware.d.ts +31 -0
- package/dist/auth-middleware.d.ts.map +1 -0
- package/dist/auth-middleware.js +35 -0
- package/dist/auth-middleware.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +65 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +137 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +412 -0
- package/dist/client.js.map +1 -0
- package/dist/file-service.d.ts +94 -0
- package/dist/file-service.d.ts.map +1 -0
- package/dist/file-service.js +203 -0
- package/dist/file-service.js.map +1 -0
- package/dist/http-exposure-service.d.ts +71 -0
- package/dist/http-exposure-service.d.ts.map +1 -0
- package/dist/http-exposure-service.js +172 -0
- package/dist/http-exposure-service.js.map +1 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +66 -0
- package/dist/index.js.map +1 -0
- package/dist/sandbox-manager.d.ts +76 -0
- package/dist/sandbox-manager.d.ts.map +1 -0
- package/dist/sandbox-manager.js +161 -0
- package/dist/sandbox-manager.js.map +1 -0
- package/dist/sandbox.d.ts +118 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +303 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +240 -0
- package/dist/server.js.map +1 -0
- package/dist/stream-service.d.ts +35 -0
- package/dist/stream-service.d.ts.map +1 -0
- package/dist/stream-service.js +136 -0
- package/dist/stream-service.js.map +1 -0
- package/dist/terminal.d.ts +46 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +264 -0
- package/dist/terminal.js.map +1 -0
- package/dist/websocket.d.ts +48 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +332 -0
- package/dist/websocket.js.map +1 -0
- package/package.json +59 -0
- package/src/api-server.ts +658 -0
- package/src/auth-middleware.ts +65 -0
- package/src/cli.ts +71 -0
- package/src/client.ts +537 -0
- package/src/file-service.ts +273 -0
- package/src/http-exposure-service.ts +232 -0
- package/src/index.ts +101 -0
- package/src/sandbox-manager.ts +202 -0
- package/src/sandbox.ts +396 -0
- package/src/stream-service.ts +174 -0
- package/tsconfig.json +37 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TreeSap Sandbox v1.0
|
|
3
|
+
*
|
|
4
|
+
* A self-hosted sandbox API for isolated code execution and file management.
|
|
5
|
+
* Provides a Cloudflare-style API for managing sandboxed environments.
|
|
6
|
+
*
|
|
7
|
+
* @example Server usage
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { startServer } from '@treesap/sandbox';
|
|
10
|
+
*
|
|
11
|
+
* // Start the sandbox server
|
|
12
|
+
* const { server, manager } = await startServer({
|
|
13
|
+
* port: 3000,
|
|
14
|
+
* basePath: './.sandboxes'
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example Client SDK usage
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { SandboxClient } from '@treesap/sandbox';
|
|
21
|
+
*
|
|
22
|
+
* // Create a new sandbox
|
|
23
|
+
* const sandbox = await SandboxClient.create('http://localhost:3000');
|
|
24
|
+
*
|
|
25
|
+
* // Execute commands
|
|
26
|
+
* const result = await sandbox.exec('npm install');
|
|
27
|
+
* console.log(result.stdout);
|
|
28
|
+
*
|
|
29
|
+
* // File operations
|
|
30
|
+
* await sandbox.writeFile('package.json', JSON.stringify(pkg, null, 2));
|
|
31
|
+
* const files = await sandbox.listFiles();
|
|
32
|
+
*
|
|
33
|
+
* // Process management
|
|
34
|
+
* const server = await sandbox.startProcess('node server.js');
|
|
35
|
+
* const logs = await sandbox.streamProcessLogs(server.id);
|
|
36
|
+
*
|
|
37
|
+
* // Cleanup
|
|
38
|
+
* await sandbox.destroy({ cleanup: true });
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* @packageDocumentation
|
|
42
|
+
*/
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// Server API
|
|
45
|
+
// ============================================================================
|
|
46
|
+
export { startServer, createServer } from './api-server';
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// Client SDK
|
|
49
|
+
// ============================================================================
|
|
50
|
+
export { SandboxClient, parseSSEStream } from './client';
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// Core Components
|
|
53
|
+
// ============================================================================
|
|
54
|
+
export { Sandbox } from './sandbox';
|
|
55
|
+
export { SandboxManager } from './sandbox-manager';
|
|
56
|
+
export { FileService } from './file-service';
|
|
57
|
+
export { StreamService } from './stream-service';
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// Auth & Middleware
|
|
60
|
+
// ============================================================================
|
|
61
|
+
export { createAuthMiddleware, parseApiKeysFromEnv } from './auth-middleware';
|
|
62
|
+
// ============================================================================
|
|
63
|
+
// HTTP Exposure
|
|
64
|
+
// ============================================================================
|
|
65
|
+
export { HttpExposureService } from './http-exposure-service';
|
|
66
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,+EAA+E;AAC/E,aAAa;AACb,+EAA+E;AAE/E,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGzD,+EAA+E;AAC/E,aAAa;AACb,+EAA+E;AAE/E,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAGzD,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAwBjD,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAG9E,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Sandbox, SandboxConfig } from './sandbox';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
export interface SandboxManagerConfig {
|
|
4
|
+
basePath?: string;
|
|
5
|
+
maxSandboxes?: number;
|
|
6
|
+
defaultTimeout?: number;
|
|
7
|
+
autoCleanup?: boolean;
|
|
8
|
+
cleanupInterval?: number;
|
|
9
|
+
maxIdleTime?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Manages multiple sandbox instances
|
|
13
|
+
*/
|
|
14
|
+
export declare class SandboxManager extends EventEmitter {
|
|
15
|
+
private sandboxes;
|
|
16
|
+
private lastActivity;
|
|
17
|
+
private config;
|
|
18
|
+
private cleanupIntervalId?;
|
|
19
|
+
constructor(config?: SandboxManagerConfig);
|
|
20
|
+
/**
|
|
21
|
+
* Create a new sandbox
|
|
22
|
+
*/
|
|
23
|
+
createSandbox(config?: SandboxConfig): Promise<Sandbox>;
|
|
24
|
+
/**
|
|
25
|
+
* Get a sandbox by ID
|
|
26
|
+
*/
|
|
27
|
+
getSandbox(id: string): Sandbox | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* List all sandboxes
|
|
30
|
+
*/
|
|
31
|
+
listSandboxes(): Array<{
|
|
32
|
+
id: string;
|
|
33
|
+
status: ReturnType<Sandbox['getStatus']>;
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* Destroy a sandbox
|
|
37
|
+
*/
|
|
38
|
+
destroySandbox(id: string, options?: {
|
|
39
|
+
cleanup?: boolean;
|
|
40
|
+
}): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Destroy all sandboxes
|
|
43
|
+
*/
|
|
44
|
+
destroyAll(options?: {
|
|
45
|
+
cleanup?: boolean;
|
|
46
|
+
}): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Get manager statistics
|
|
49
|
+
*/
|
|
50
|
+
getStats(): {
|
|
51
|
+
totalSandboxes: number;
|
|
52
|
+
maxSandboxes: number | undefined;
|
|
53
|
+
totalProcesses: number;
|
|
54
|
+
basePath: string | undefined;
|
|
55
|
+
autoCleanup: boolean | undefined;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Start periodic cleanup task
|
|
59
|
+
*/
|
|
60
|
+
private startCleanupTask;
|
|
61
|
+
/**
|
|
62
|
+
* Clean up idle sandboxes
|
|
63
|
+
*/
|
|
64
|
+
private cleanupIdleSandboxes;
|
|
65
|
+
/**
|
|
66
|
+
* Update last activity time for a sandbox
|
|
67
|
+
*/
|
|
68
|
+
private updateActivity;
|
|
69
|
+
/**
|
|
70
|
+
* Shutdown the manager (cleanup all sandboxes)
|
|
71
|
+
*/
|
|
72
|
+
shutdown(options?: {
|
|
73
|
+
cleanup?: boolean;
|
|
74
|
+
}): Promise<void>;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=sandbox-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-manager.d.ts","sourceRoot":"","sources":["../src/sandbox-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAItC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,iBAAiB,CAAC,CAAiB;gBAE/B,MAAM,GAAE,oBAAyB;IAqB7C;;OAEG;IACG,aAAa,CAAC,MAAM,GAAE,aAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IAkCjE;;OAEG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAQ3C;;OAEG;IACH,aAAa,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAA;KAAE,CAAC;IAOhF;;OAEG;IACG,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAapF;;OAEG;IACG,UAAU,CAAC,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAUpE;;OAEG;IACH,QAAQ;;;;;;;IAgBR;;OAEG;IACH,OAAO,CAAC,gBAAgB;IASxB;;OAEG;YACW,oBAAoB;IAkBlC;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACG,QAAQ,CAAC,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAQnE"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { Sandbox } from './sandbox';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
5
|
+
/**
|
|
6
|
+
* Manages multiple sandbox instances
|
|
7
|
+
*/
|
|
8
|
+
export class SandboxManager extends EventEmitter {
|
|
9
|
+
sandboxes = new Map();
|
|
10
|
+
lastActivity = new Map();
|
|
11
|
+
config;
|
|
12
|
+
cleanupIntervalId;
|
|
13
|
+
constructor(config = {}) {
|
|
14
|
+
super();
|
|
15
|
+
this.config = {
|
|
16
|
+
basePath: config.basePath || path.join(process.cwd(), '.sandboxes'),
|
|
17
|
+
maxSandboxes: config.maxSandboxes || 100,
|
|
18
|
+
defaultTimeout: config.defaultTimeout || 300000, // 5 minutes
|
|
19
|
+
autoCleanup: config.autoCleanup !== false, // Default true
|
|
20
|
+
cleanupInterval: config.cleanupInterval || 60000, // 1 minute
|
|
21
|
+
maxIdleTime: config.maxIdleTime || 1800000, // 30 minutes
|
|
22
|
+
};
|
|
23
|
+
// Ensure basePath is always set
|
|
24
|
+
if (!this.config.basePath) {
|
|
25
|
+
this.config.basePath = path.join(process.cwd(), '.sandboxes');
|
|
26
|
+
}
|
|
27
|
+
if (this.config.autoCleanup) {
|
|
28
|
+
this.startCleanupTask();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Create a new sandbox
|
|
33
|
+
*/
|
|
34
|
+
async createSandbox(config = {}) {
|
|
35
|
+
// Check sandbox limit
|
|
36
|
+
if (this.config.maxSandboxes && this.sandboxes.size >= this.config.maxSandboxes) {
|
|
37
|
+
throw new Error(`Maximum sandbox limit reached (${this.config.maxSandboxes})`);
|
|
38
|
+
}
|
|
39
|
+
// Generate ID first if not provided
|
|
40
|
+
const sandboxId = config.id || uuidv4();
|
|
41
|
+
// Create sandbox with base path
|
|
42
|
+
const sandboxConfig = {
|
|
43
|
+
...config,
|
|
44
|
+
id: sandboxId,
|
|
45
|
+
workDir: config.workDir || path.join(this.config.basePath, sandboxId),
|
|
46
|
+
timeout: config.timeout || this.config.defaultTimeout,
|
|
47
|
+
};
|
|
48
|
+
const sandbox = new Sandbox(sandboxConfig);
|
|
49
|
+
await sandbox.initialize();
|
|
50
|
+
// Track sandbox
|
|
51
|
+
this.sandboxes.set(sandbox.id, sandbox);
|
|
52
|
+
this.lastActivity.set(sandbox.id, Date.now());
|
|
53
|
+
// Listen for sandbox events to track activity
|
|
54
|
+
sandbox.on('output', () => this.updateActivity(sandbox.id));
|
|
55
|
+
sandbox.on('exec_complete', () => this.updateActivity(sandbox.id));
|
|
56
|
+
sandbox.on('process_started', () => this.updateActivity(sandbox.id));
|
|
57
|
+
this.emit('sandbox_created', { id: sandbox.id });
|
|
58
|
+
return sandbox;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get a sandbox by ID
|
|
62
|
+
*/
|
|
63
|
+
getSandbox(id) {
|
|
64
|
+
const sandbox = this.sandboxes.get(id);
|
|
65
|
+
if (sandbox) {
|
|
66
|
+
this.updateActivity(id);
|
|
67
|
+
}
|
|
68
|
+
return sandbox;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* List all sandboxes
|
|
72
|
+
*/
|
|
73
|
+
listSandboxes() {
|
|
74
|
+
return Array.from(this.sandboxes.entries()).map(([id, sandbox]) => ({
|
|
75
|
+
id,
|
|
76
|
+
status: sandbox.getStatus(),
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Destroy a sandbox
|
|
81
|
+
*/
|
|
82
|
+
async destroySandbox(id, options = {}) {
|
|
83
|
+
const sandbox = this.sandboxes.get(id);
|
|
84
|
+
if (!sandbox) {
|
|
85
|
+
throw new Error(`Sandbox ${id} not found`);
|
|
86
|
+
}
|
|
87
|
+
await sandbox.destroy(options);
|
|
88
|
+
this.sandboxes.delete(id);
|
|
89
|
+
this.lastActivity.delete(id);
|
|
90
|
+
this.emit('sandbox_destroyed', { id });
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Destroy all sandboxes
|
|
94
|
+
*/
|
|
95
|
+
async destroyAll(options = {}) {
|
|
96
|
+
const destroyPromises = Array.from(this.sandboxes.keys()).map((id) => this.destroySandbox(id, options).catch((err) => {
|
|
97
|
+
console.error(`Error destroying sandbox ${id}:`, err);
|
|
98
|
+
}));
|
|
99
|
+
await Promise.all(destroyPromises);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get manager statistics
|
|
103
|
+
*/
|
|
104
|
+
getStats() {
|
|
105
|
+
const sandboxList = this.listSandboxes();
|
|
106
|
+
const totalProcesses = sandboxList.reduce((sum, { status }) => sum + status.processCount, 0);
|
|
107
|
+
return {
|
|
108
|
+
totalSandboxes: this.sandboxes.size,
|
|
109
|
+
maxSandboxes: this.config.maxSandboxes,
|
|
110
|
+
totalProcesses,
|
|
111
|
+
basePath: this.config.basePath,
|
|
112
|
+
autoCleanup: this.config.autoCleanup,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Start periodic cleanup task
|
|
117
|
+
*/
|
|
118
|
+
startCleanupTask() {
|
|
119
|
+
this.cleanupIntervalId = setInterval(() => {
|
|
120
|
+
this.cleanupIdleSandboxes();
|
|
121
|
+
}, this.config.cleanupInterval);
|
|
122
|
+
// Don't keep process alive for cleanup
|
|
123
|
+
this.cleanupIntervalId.unref();
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Clean up idle sandboxes
|
|
127
|
+
*/
|
|
128
|
+
async cleanupIdleSandboxes() {
|
|
129
|
+
const now = Date.now();
|
|
130
|
+
const maxIdleTime = this.config.maxIdleTime;
|
|
131
|
+
const idleSandboxes = Array.from(this.lastActivity.entries())
|
|
132
|
+
.filter(([_, lastActive]) => now - lastActive > maxIdleTime)
|
|
133
|
+
.map(([id]) => id);
|
|
134
|
+
for (const id of idleSandboxes) {
|
|
135
|
+
try {
|
|
136
|
+
await this.destroySandbox(id, { cleanup: true });
|
|
137
|
+
this.emit('sandbox_cleaned_up', { id, reason: 'idle' });
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.error(`Error cleaning up sandbox ${id}:`, error);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Update last activity time for a sandbox
|
|
146
|
+
*/
|
|
147
|
+
updateActivity(id) {
|
|
148
|
+
this.lastActivity.set(id, Date.now());
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Shutdown the manager (cleanup all sandboxes)
|
|
152
|
+
*/
|
|
153
|
+
async shutdown(options = {}) {
|
|
154
|
+
if (this.cleanupIntervalId) {
|
|
155
|
+
clearInterval(this.cleanupIntervalId);
|
|
156
|
+
}
|
|
157
|
+
await this.destroyAll(options);
|
|
158
|
+
this.removeAllListeners();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=sandbox-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-manager.js","sourceRoot":"","sources":["../src/sandbox-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
export interface SandboxConfig {
|
|
3
|
+
id?: string;
|
|
4
|
+
workDir?: string;
|
|
5
|
+
env?: Record<string, string>;
|
|
6
|
+
timeout?: number;
|
|
7
|
+
maxProcesses?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface ProcessInfo {
|
|
10
|
+
id: string;
|
|
11
|
+
pid: number;
|
|
12
|
+
command: string;
|
|
13
|
+
status: 'running' | 'completed' | 'failed';
|
|
14
|
+
startTime: number;
|
|
15
|
+
exitCode?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface ExecOptions {
|
|
18
|
+
stream?: boolean;
|
|
19
|
+
onOutput?: (stream: 'stdout' | 'stderr', data: string) => void;
|
|
20
|
+
timeout?: number;
|
|
21
|
+
cwd?: string;
|
|
22
|
+
env?: Record<string, string>;
|
|
23
|
+
}
|
|
24
|
+
export interface ExecuteResponse {
|
|
25
|
+
success: boolean;
|
|
26
|
+
stdout: string;
|
|
27
|
+
stderr: string;
|
|
28
|
+
exitCode: number;
|
|
29
|
+
timedOut?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Represents a single isolated sandbox instance
|
|
33
|
+
* Each sandbox has its own working directory and process management
|
|
34
|
+
*/
|
|
35
|
+
export declare class Sandbox extends EventEmitter {
|
|
36
|
+
readonly id: string;
|
|
37
|
+
readonly workDir: string;
|
|
38
|
+
readonly createdAt: number;
|
|
39
|
+
private processes;
|
|
40
|
+
private runningProcesses;
|
|
41
|
+
private config;
|
|
42
|
+
private destroyed;
|
|
43
|
+
constructor(config?: SandboxConfig);
|
|
44
|
+
/**
|
|
45
|
+
* Initialize the sandbox (create working directory)
|
|
46
|
+
*/
|
|
47
|
+
initialize(): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Execute a command and return the complete result
|
|
50
|
+
*/
|
|
51
|
+
exec(command: string, options?: ExecOptions): Promise<ExecuteResponse>;
|
|
52
|
+
/**
|
|
53
|
+
* Start a long-running background process
|
|
54
|
+
*/
|
|
55
|
+
startProcess(command: string, options?: ExecOptions): Promise<ProcessInfo>;
|
|
56
|
+
/**
|
|
57
|
+
* List all processes (running and completed)
|
|
58
|
+
*/
|
|
59
|
+
listProcesses(): ProcessInfo[];
|
|
60
|
+
/**
|
|
61
|
+
* Get information about a specific process
|
|
62
|
+
*/
|
|
63
|
+
getProcess(processId: string): ProcessInfo | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Kill a specific process
|
|
66
|
+
*/
|
|
67
|
+
killProcess(processId: string, signal?: string): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Kill all running processes
|
|
70
|
+
*/
|
|
71
|
+
killAllProcesses(signal?: string): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Get sandbox status
|
|
74
|
+
*/
|
|
75
|
+
getStatus(): {
|
|
76
|
+
id: string;
|
|
77
|
+
workDir: string;
|
|
78
|
+
createdAt: number;
|
|
79
|
+
uptime: number;
|
|
80
|
+
processCount: number;
|
|
81
|
+
totalProcesses: number;
|
|
82
|
+
destroyed: boolean;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Set a single environment variable
|
|
86
|
+
*/
|
|
87
|
+
setEnv(key: string, value: string): void;
|
|
88
|
+
/**
|
|
89
|
+
* Set multiple environment variables at once
|
|
90
|
+
*/
|
|
91
|
+
setEnvBatch(variables: Record<string, string>): void;
|
|
92
|
+
/**
|
|
93
|
+
* Get environment variable(s)
|
|
94
|
+
* If key is provided, returns the value for that key
|
|
95
|
+
* Otherwise returns all environment variables
|
|
96
|
+
*/
|
|
97
|
+
getEnv(): Record<string, string>;
|
|
98
|
+
getEnv(key: string): string | undefined;
|
|
99
|
+
/**
|
|
100
|
+
* Get list of environment variable names (for security, not exposing values)
|
|
101
|
+
*/
|
|
102
|
+
getEnvKeys(): string[];
|
|
103
|
+
/**
|
|
104
|
+
* Unset (remove) an environment variable
|
|
105
|
+
*/
|
|
106
|
+
unsetEnv(key: string): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Destroy the sandbox (kill all processes, optionally clean up files)
|
|
109
|
+
*/
|
|
110
|
+
destroy(options?: {
|
|
111
|
+
cleanup?: boolean;
|
|
112
|
+
}): Promise<void>;
|
|
113
|
+
/**
|
|
114
|
+
* Parse a command string into command and arguments
|
|
115
|
+
*/
|
|
116
|
+
private parseCommand;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"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"}
|