@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/cli.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { startServer } from './api-server';
|
|
3
|
+
/**
|
|
4
|
+
* CLI entry point for TreeSap Sandbox
|
|
5
|
+
*/
|
|
6
|
+
// Parse command line arguments
|
|
7
|
+
const args = process.argv.slice(2);
|
|
8
|
+
const config = {};
|
|
9
|
+
for (let i = 0; i < args.length; i++) {
|
|
10
|
+
const arg = args[i];
|
|
11
|
+
switch (arg) {
|
|
12
|
+
case '--port':
|
|
13
|
+
case '-p':
|
|
14
|
+
config.port = parseInt(args[++i]);
|
|
15
|
+
break;
|
|
16
|
+
case '--host':
|
|
17
|
+
case '-h':
|
|
18
|
+
config.host = args[++i];
|
|
19
|
+
break;
|
|
20
|
+
case '--base-path':
|
|
21
|
+
case '-b':
|
|
22
|
+
config.basePath = args[++i];
|
|
23
|
+
break;
|
|
24
|
+
case '--max-sandboxes':
|
|
25
|
+
case '-m':
|
|
26
|
+
config.maxSandboxes = parseInt(args[++i]);
|
|
27
|
+
break;
|
|
28
|
+
case '--cors':
|
|
29
|
+
config.cors = true;
|
|
30
|
+
break;
|
|
31
|
+
case '--help':
|
|
32
|
+
printHelp();
|
|
33
|
+
process.exit(0);
|
|
34
|
+
default:
|
|
35
|
+
console.error(`Unknown argument: ${arg}`);
|
|
36
|
+
printHelp();
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function printHelp() {
|
|
41
|
+
console.log(`
|
|
42
|
+
TreeSap Sandbox Server
|
|
43
|
+
|
|
44
|
+
Usage: treesap-sandbox [options]
|
|
45
|
+
|
|
46
|
+
Options:
|
|
47
|
+
-p, --port <port> Port to listen on (default: 3000)
|
|
48
|
+
-h, --host <host> Host to bind to (default: 0.0.0.0)
|
|
49
|
+
-b, --base-path <path> Base path for sandbox folders (default: ./.sandboxes)
|
|
50
|
+
-m, --max-sandboxes <num> Maximum number of sandboxes (default: 100)
|
|
51
|
+
--cors Enable CORS (default: false)
|
|
52
|
+
--help Show this help message
|
|
53
|
+
|
|
54
|
+
Examples:
|
|
55
|
+
treesap-sandbox --port 8080
|
|
56
|
+
treesap-sandbox --base-path /tmp/sandboxes --cors
|
|
57
|
+
treesap-sandbox -p 3000 -m 50
|
|
58
|
+
`);
|
|
59
|
+
}
|
|
60
|
+
// Start the server
|
|
61
|
+
startServer(config).catch((error) => {
|
|
62
|
+
console.error('Failed to start server:', error);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C;;GAEG;AAEH,+BAA+B;AAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,MAAM,GAAQ,EAAE,CAAC;AAEvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAEpB,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,QAAQ,CAAC;QACd,KAAK,IAAI;YACP,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAClC,MAAM;QACR,KAAK,QAAQ,CAAC;QACd,KAAK,IAAI;YACP,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACxB,MAAM;QACR,KAAK,aAAa,CAAC;QACnB,KAAK,IAAI;YACP,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC5B,MAAM;QACR,KAAK,iBAAiB,CAAC;QACvB,KAAK,IAAI;YACP,MAAM,CAAC,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC1C,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;YACnB,MAAM;QACR,KAAK,QAAQ;YACX,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB;YACE,OAAO,CAAC,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;YAC1C,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;GAiBX,CAAC,CAAC;AACL,CAAC;AAED,mBAAmB;AACnB,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAClC,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;IAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { ExecuteResponse, ProcessInfo, ExecOptions } from './sandbox';
|
|
2
|
+
import { FileInfo, ListFilesOptions } from './file-service';
|
|
3
|
+
import { ExecEvent, LogEvent } from './stream-service';
|
|
4
|
+
export interface SandboxClientConfig {
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
sandboxId?: string;
|
|
7
|
+
apiKey?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface CreateSandboxOptions {
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
env?: Record<string, string>;
|
|
12
|
+
timeout?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface CreateSandboxResponse {
|
|
15
|
+
id: string;
|
|
16
|
+
workDir: string;
|
|
17
|
+
createdAt: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Client library for interacting with TreeSap Sandbox API
|
|
21
|
+
*/
|
|
22
|
+
export declare class SandboxClient {
|
|
23
|
+
private baseUrl;
|
|
24
|
+
private apiKey?;
|
|
25
|
+
readonly id: string;
|
|
26
|
+
constructor(config: SandboxClientConfig);
|
|
27
|
+
/**
|
|
28
|
+
* Get headers for API requests (includes API key if configured)
|
|
29
|
+
*/
|
|
30
|
+
private getHeaders;
|
|
31
|
+
/**
|
|
32
|
+
* Create a new sandbox instance
|
|
33
|
+
*/
|
|
34
|
+
static create(baseUrl: string, options?: CreateSandboxOptions): Promise<SandboxClient>;
|
|
35
|
+
/**
|
|
36
|
+
* Get existing sandbox by ID
|
|
37
|
+
*/
|
|
38
|
+
static fromId(baseUrl: string, sandboxId: string, apiKey?: string): SandboxClient;
|
|
39
|
+
/**
|
|
40
|
+
* Execute a command and return the complete result
|
|
41
|
+
*/
|
|
42
|
+
exec(command: string, options?: ExecOptions): Promise<ExecuteResponse>;
|
|
43
|
+
/**
|
|
44
|
+
* Execute a command and return a streaming response
|
|
45
|
+
*/
|
|
46
|
+
execStream(command: string, options?: ExecOptions): Promise<ReadableStream>;
|
|
47
|
+
/**
|
|
48
|
+
* Start a long-running background process
|
|
49
|
+
*/
|
|
50
|
+
startProcess(command: string, options?: ExecOptions): Promise<ProcessInfo>;
|
|
51
|
+
/**
|
|
52
|
+
* List all processes
|
|
53
|
+
*/
|
|
54
|
+
listProcesses(): Promise<ProcessInfo[]>;
|
|
55
|
+
/**
|
|
56
|
+
* Get process information
|
|
57
|
+
*/
|
|
58
|
+
getProcess(processId: string): Promise<ProcessInfo>;
|
|
59
|
+
/**
|
|
60
|
+
* Kill a process
|
|
61
|
+
*/
|
|
62
|
+
killProcess(processId: string, signal?: string): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Kill all processes
|
|
65
|
+
*/
|
|
66
|
+
killAllProcesses(): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Stream process logs
|
|
69
|
+
*/
|
|
70
|
+
streamProcessLogs(processId: string): Promise<ReadableStream>;
|
|
71
|
+
/**
|
|
72
|
+
* Get accumulated process logs (utility method)
|
|
73
|
+
*/
|
|
74
|
+
getProcessLogs(processId: string): Promise<string>;
|
|
75
|
+
/**
|
|
76
|
+
* List files in a directory
|
|
77
|
+
*/
|
|
78
|
+
listFiles(path?: string, options?: ListFilesOptions): Promise<FileInfo[]>;
|
|
79
|
+
/**
|
|
80
|
+
* Read a file's contents
|
|
81
|
+
*/
|
|
82
|
+
readFile(path: string): Promise<string>;
|
|
83
|
+
/**
|
|
84
|
+
* Write content to a file
|
|
85
|
+
*/
|
|
86
|
+
writeFile(path: string, content: string): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Delete a file or directory
|
|
89
|
+
*/
|
|
90
|
+
deleteFile(path: string, options?: {
|
|
91
|
+
recursive?: boolean;
|
|
92
|
+
}): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Set environment variables in the sandbox
|
|
95
|
+
*/
|
|
96
|
+
setEnv(variables: Record<string, string>): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Get list of environment variable names (not values for security)
|
|
99
|
+
*/
|
|
100
|
+
listEnv(): Promise<string[]>;
|
|
101
|
+
/**
|
|
102
|
+
* Unset (remove) an environment variable
|
|
103
|
+
*/
|
|
104
|
+
unsetEnv(key: string): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Expose a sandbox port via HTTP and return the public URL
|
|
107
|
+
*/
|
|
108
|
+
exposeHttp(port: number): Promise<string>;
|
|
109
|
+
/**
|
|
110
|
+
* Get list of exposed HTTP endpoints
|
|
111
|
+
*/
|
|
112
|
+
listExposures(): Promise<Array<{
|
|
113
|
+
sandboxId: string;
|
|
114
|
+
port: number;
|
|
115
|
+
publicUrl: string;
|
|
116
|
+
}>>;
|
|
117
|
+
/**
|
|
118
|
+
* Remove HTTP exposure for a specific port (or all if port is undefined)
|
|
119
|
+
*/
|
|
120
|
+
unexposeHttp(port?: number): Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Get sandbox status
|
|
123
|
+
*/
|
|
124
|
+
getStatus(): Promise<any>;
|
|
125
|
+
/**
|
|
126
|
+
* Destroy the sandbox
|
|
127
|
+
*/
|
|
128
|
+
destroy(options?: {
|
|
129
|
+
cleanup?: boolean;
|
|
130
|
+
}): Promise<void>;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Parse Server-Sent Events stream
|
|
134
|
+
* Utility function for consuming SSE streams from exec and logs
|
|
135
|
+
*/
|
|
136
|
+
export declare function parseSSEStream<T = ExecEvent | LogEvent>(stream: ReadableStream): AsyncGenerator<T>;
|
|
137
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client library for interacting with TreeSap Sandbox API
|
|
3
|
+
*/
|
|
4
|
+
export class SandboxClient {
|
|
5
|
+
baseUrl;
|
|
6
|
+
apiKey;
|
|
7
|
+
id;
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
10
|
+
this.id = config.sandboxId || '';
|
|
11
|
+
this.apiKey = config.apiKey;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Get headers for API requests (includes API key if configured)
|
|
15
|
+
*/
|
|
16
|
+
getHeaders(contentType) {
|
|
17
|
+
const headers = {};
|
|
18
|
+
if (contentType) {
|
|
19
|
+
headers['Content-Type'] = contentType;
|
|
20
|
+
}
|
|
21
|
+
if (this.apiKey) {
|
|
22
|
+
headers['X-API-Key'] = this.apiKey;
|
|
23
|
+
}
|
|
24
|
+
return headers;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Create a new sandbox instance
|
|
28
|
+
*/
|
|
29
|
+
static async create(baseUrl, options = {}) {
|
|
30
|
+
const url = `${baseUrl.replace(/\/$/, '')}/sandbox`;
|
|
31
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
32
|
+
if (options.apiKey) {
|
|
33
|
+
headers['X-API-Key'] = options.apiKey;
|
|
34
|
+
}
|
|
35
|
+
const response = await fetch(url, {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers,
|
|
38
|
+
body: JSON.stringify({ env: options.env, timeout: options.timeout }),
|
|
39
|
+
});
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
const error = await response.json();
|
|
42
|
+
throw new Error(error.error || 'Failed to create sandbox');
|
|
43
|
+
}
|
|
44
|
+
const data = await response.json();
|
|
45
|
+
return new SandboxClient({
|
|
46
|
+
baseUrl,
|
|
47
|
+
sandboxId: data.id,
|
|
48
|
+
apiKey: options.apiKey,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get existing sandbox by ID
|
|
53
|
+
*/
|
|
54
|
+
static fromId(baseUrl, sandboxId, apiKey) {
|
|
55
|
+
return new SandboxClient({ baseUrl, sandboxId, apiKey });
|
|
56
|
+
}
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// Command Execution
|
|
59
|
+
// ============================================================================
|
|
60
|
+
/**
|
|
61
|
+
* Execute a command and return the complete result
|
|
62
|
+
*/
|
|
63
|
+
async exec(command, options = {}) {
|
|
64
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/exec`;
|
|
65
|
+
const response = await fetch(url, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: this.getHeaders('application/json'),
|
|
68
|
+
body: JSON.stringify({ command, ...options }),
|
|
69
|
+
});
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
const error = await response.json();
|
|
72
|
+
throw new Error(error.error || 'Failed to execute command');
|
|
73
|
+
}
|
|
74
|
+
return await response.json();
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Execute a command and return a streaming response
|
|
78
|
+
*/
|
|
79
|
+
async execStream(command, options = {}) {
|
|
80
|
+
const params = new URLSearchParams({ command });
|
|
81
|
+
if (options.timeout) {
|
|
82
|
+
params.append('timeout', options.timeout.toString());
|
|
83
|
+
}
|
|
84
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/exec-stream?${params}`;
|
|
85
|
+
const response = await fetch(url, { headers: this.getHeaders() });
|
|
86
|
+
if (!response.ok) {
|
|
87
|
+
const error = await response.json();
|
|
88
|
+
throw new Error(error.error || 'Failed to execute command');
|
|
89
|
+
}
|
|
90
|
+
if (!response.body) {
|
|
91
|
+
throw new Error('No response body');
|
|
92
|
+
}
|
|
93
|
+
return response.body;
|
|
94
|
+
}
|
|
95
|
+
// ============================================================================
|
|
96
|
+
// Process Management
|
|
97
|
+
// ============================================================================
|
|
98
|
+
/**
|
|
99
|
+
* Start a long-running background process
|
|
100
|
+
*/
|
|
101
|
+
async startProcess(command, options = {}) {
|
|
102
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/process`;
|
|
103
|
+
const response = await fetch(url, {
|
|
104
|
+
method: 'POST',
|
|
105
|
+
headers: this.getHeaders('application/json'),
|
|
106
|
+
body: JSON.stringify({ command, ...options }),
|
|
107
|
+
});
|
|
108
|
+
if (!response.ok) {
|
|
109
|
+
const error = await response.json();
|
|
110
|
+
throw new Error(error.error || 'Failed to start process');
|
|
111
|
+
}
|
|
112
|
+
return await response.json();
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* List all processes
|
|
116
|
+
*/
|
|
117
|
+
async listProcesses() {
|
|
118
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/process`;
|
|
119
|
+
const response = await fetch(url, { headers: this.getHeaders() });
|
|
120
|
+
if (!response.ok) {
|
|
121
|
+
const error = await response.json();
|
|
122
|
+
throw new Error(error.error || 'Failed to list processes');
|
|
123
|
+
}
|
|
124
|
+
const data = await response.json();
|
|
125
|
+
return data.processes;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get process information
|
|
129
|
+
*/
|
|
130
|
+
async getProcess(processId) {
|
|
131
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/process/${processId}`;
|
|
132
|
+
const response = await fetch(url, { headers: this.getHeaders() });
|
|
133
|
+
if (!response.ok) {
|
|
134
|
+
const error = await response.json();
|
|
135
|
+
throw new Error(error.error || 'Failed to get process');
|
|
136
|
+
}
|
|
137
|
+
return await response.json();
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Kill a process
|
|
141
|
+
*/
|
|
142
|
+
async killProcess(processId, signal = 'SIGTERM') {
|
|
143
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/process/${processId}?signal=${signal}`;
|
|
144
|
+
const response = await fetch(url, { method: 'DELETE', headers: this.getHeaders() });
|
|
145
|
+
if (!response.ok) {
|
|
146
|
+
const error = await response.json();
|
|
147
|
+
throw new Error(error.error || 'Failed to kill process');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Kill all processes
|
|
152
|
+
*/
|
|
153
|
+
async killAllProcesses() {
|
|
154
|
+
const processes = await this.listProcesses();
|
|
155
|
+
const runningProcesses = processes.filter((p) => p.status === 'running');
|
|
156
|
+
await Promise.all(runningProcesses.map((p) => this.killProcess(p.id).catch(() => { })));
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Stream process logs
|
|
160
|
+
*/
|
|
161
|
+
async streamProcessLogs(processId) {
|
|
162
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/process/${processId}/logs`;
|
|
163
|
+
const response = await fetch(url, { headers: this.getHeaders() });
|
|
164
|
+
if (!response.ok) {
|
|
165
|
+
const error = await response.json();
|
|
166
|
+
throw new Error(error.error || 'Failed to stream logs');
|
|
167
|
+
}
|
|
168
|
+
if (!response.body) {
|
|
169
|
+
throw new Error('No response body');
|
|
170
|
+
}
|
|
171
|
+
return response.body;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get accumulated process logs (utility method)
|
|
175
|
+
*/
|
|
176
|
+
async getProcessLogs(processId) {
|
|
177
|
+
const stream = await this.streamProcessLogs(processId);
|
|
178
|
+
const logs = [];
|
|
179
|
+
for await (const event of parseSSEStream(stream)) {
|
|
180
|
+
if (event.data) {
|
|
181
|
+
logs.push(event.data);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return logs.join('');
|
|
185
|
+
}
|
|
186
|
+
// ============================================================================
|
|
187
|
+
// File Operations
|
|
188
|
+
// ============================================================================
|
|
189
|
+
/**
|
|
190
|
+
* List files in a directory
|
|
191
|
+
*/
|
|
192
|
+
async listFiles(path = '.', options = {}) {
|
|
193
|
+
const params = new URLSearchParams({ path });
|
|
194
|
+
if (options.recursive) {
|
|
195
|
+
params.append('recursive', 'true');
|
|
196
|
+
}
|
|
197
|
+
if (options.pattern) {
|
|
198
|
+
params.append('pattern', options.pattern);
|
|
199
|
+
}
|
|
200
|
+
if (options.includeHidden) {
|
|
201
|
+
params.append('hidden', 'true');
|
|
202
|
+
}
|
|
203
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/files?${params}`;
|
|
204
|
+
const response = await fetch(url, { headers: this.getHeaders() });
|
|
205
|
+
if (!response.ok) {
|
|
206
|
+
const error = await response.json();
|
|
207
|
+
throw new Error(error.error || 'Failed to list files');
|
|
208
|
+
}
|
|
209
|
+
const data = await response.json();
|
|
210
|
+
return data.files;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Read a file's contents
|
|
214
|
+
*/
|
|
215
|
+
async readFile(path) {
|
|
216
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/files/${path}`;
|
|
217
|
+
const response = await fetch(url, { headers: this.getHeaders() });
|
|
218
|
+
if (!response.ok) {
|
|
219
|
+
const error = await response.json();
|
|
220
|
+
throw new Error(error.error || 'Failed to read file');
|
|
221
|
+
}
|
|
222
|
+
const data = await response.json();
|
|
223
|
+
return data.content;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Write content to a file
|
|
227
|
+
*/
|
|
228
|
+
async writeFile(path, content) {
|
|
229
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/files/${path}`;
|
|
230
|
+
const response = await fetch(url, {
|
|
231
|
+
method: 'POST',
|
|
232
|
+
headers: this.getHeaders('application/json'),
|
|
233
|
+
body: JSON.stringify({ content }),
|
|
234
|
+
});
|
|
235
|
+
if (!response.ok) {
|
|
236
|
+
const error = await response.json();
|
|
237
|
+
throw new Error(error.error || 'Failed to write file');
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Delete a file or directory
|
|
242
|
+
*/
|
|
243
|
+
async deleteFile(path, options = {}) {
|
|
244
|
+
const params = new URLSearchParams();
|
|
245
|
+
if (options.recursive) {
|
|
246
|
+
params.append('recursive', 'true');
|
|
247
|
+
}
|
|
248
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/files/${path}?${params}`;
|
|
249
|
+
const response = await fetch(url, { method: 'DELETE', headers: this.getHeaders() });
|
|
250
|
+
if (!response.ok) {
|
|
251
|
+
const error = await response.json();
|
|
252
|
+
throw new Error(error.error || 'Failed to delete file');
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// ============================================================================
|
|
256
|
+
// Environment Variable Management
|
|
257
|
+
// ============================================================================
|
|
258
|
+
/**
|
|
259
|
+
* Set environment variables in the sandbox
|
|
260
|
+
*/
|
|
261
|
+
async setEnv(variables) {
|
|
262
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/env`;
|
|
263
|
+
const response = await fetch(url, {
|
|
264
|
+
method: 'POST',
|
|
265
|
+
headers: this.getHeaders('application/json'),
|
|
266
|
+
body: JSON.stringify({ variables }),
|
|
267
|
+
});
|
|
268
|
+
if (!response.ok) {
|
|
269
|
+
const error = await response.json();
|
|
270
|
+
throw new Error(error.error || 'Failed to set environment variables');
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Get list of environment variable names (not values for security)
|
|
275
|
+
*/
|
|
276
|
+
async listEnv() {
|
|
277
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/env`;
|
|
278
|
+
const response = await fetch(url, { headers: this.getHeaders() });
|
|
279
|
+
if (!response.ok) {
|
|
280
|
+
const error = await response.json();
|
|
281
|
+
throw new Error(error.error || 'Failed to list environment variables');
|
|
282
|
+
}
|
|
283
|
+
const data = await response.json();
|
|
284
|
+
return data.variables;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Unset (remove) an environment variable
|
|
288
|
+
*/
|
|
289
|
+
async unsetEnv(key) {
|
|
290
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/env/${encodeURIComponent(key)}`;
|
|
291
|
+
const response = await fetch(url, { method: 'DELETE', headers: this.getHeaders() });
|
|
292
|
+
if (!response.ok) {
|
|
293
|
+
const error = await response.json();
|
|
294
|
+
throw new Error(error.error || 'Failed to unset environment variable');
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// ============================================================================
|
|
298
|
+
// HTTP Exposure
|
|
299
|
+
// ============================================================================
|
|
300
|
+
/**
|
|
301
|
+
* Expose a sandbox port via HTTP and return the public URL
|
|
302
|
+
*/
|
|
303
|
+
async exposeHttp(port) {
|
|
304
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/expose`;
|
|
305
|
+
const response = await fetch(url, {
|
|
306
|
+
method: 'POST',
|
|
307
|
+
headers: this.getHeaders('application/json'),
|
|
308
|
+
body: JSON.stringify({ port }),
|
|
309
|
+
});
|
|
310
|
+
if (!response.ok) {
|
|
311
|
+
const error = await response.json();
|
|
312
|
+
throw new Error(error.error || 'Failed to expose HTTP port');
|
|
313
|
+
}
|
|
314
|
+
const data = await response.json();
|
|
315
|
+
return data.url;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Get list of exposed HTTP endpoints
|
|
319
|
+
*/
|
|
320
|
+
async listExposures() {
|
|
321
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/expose`;
|
|
322
|
+
const response = await fetch(url, { headers: this.getHeaders() });
|
|
323
|
+
if (!response.ok) {
|
|
324
|
+
const error = await response.json();
|
|
325
|
+
throw new Error(error.error || 'Failed to list exposures');
|
|
326
|
+
}
|
|
327
|
+
const data = await response.json();
|
|
328
|
+
return data.exposures || [];
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Remove HTTP exposure for a specific port (or all if port is undefined)
|
|
332
|
+
*/
|
|
333
|
+
async unexposeHttp(port) {
|
|
334
|
+
const params = port ? `?port=${port}` : '';
|
|
335
|
+
const url = `${this.baseUrl}/sandbox/${this.id}/expose${params}`;
|
|
336
|
+
const response = await fetch(url, { method: 'DELETE', headers: this.getHeaders() });
|
|
337
|
+
if (!response.ok) {
|
|
338
|
+
const error = await response.json();
|
|
339
|
+
throw new Error(error.error || 'Failed to unexpose HTTP');
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
// ============================================================================
|
|
343
|
+
// Sandbox Management
|
|
344
|
+
// ============================================================================
|
|
345
|
+
/**
|
|
346
|
+
* Get sandbox status
|
|
347
|
+
*/
|
|
348
|
+
async getStatus() {
|
|
349
|
+
const url = `${this.baseUrl}/sandbox/${this.id}`;
|
|
350
|
+
const response = await fetch(url, { headers: this.getHeaders() });
|
|
351
|
+
if (!response.ok) {
|
|
352
|
+
const error = await response.json();
|
|
353
|
+
throw new Error(error.error || 'Failed to get status');
|
|
354
|
+
}
|
|
355
|
+
return await response.json();
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Destroy the sandbox
|
|
359
|
+
*/
|
|
360
|
+
async destroy(options = {}) {
|
|
361
|
+
const params = new URLSearchParams();
|
|
362
|
+
if (options.cleanup) {
|
|
363
|
+
params.append('cleanup', 'true');
|
|
364
|
+
}
|
|
365
|
+
const url = `${this.baseUrl}/sandbox/${this.id}?${params}`;
|
|
366
|
+
const response = await fetch(url, { method: 'DELETE', headers: this.getHeaders() });
|
|
367
|
+
if (!response.ok) {
|
|
368
|
+
const error = await response.json();
|
|
369
|
+
throw new Error(error.error || 'Failed to destroy sandbox');
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Parse Server-Sent Events stream
|
|
375
|
+
* Utility function for consuming SSE streams from exec and logs
|
|
376
|
+
*/
|
|
377
|
+
export async function* parseSSEStream(stream) {
|
|
378
|
+
const reader = stream.getReader();
|
|
379
|
+
const decoder = new TextDecoder();
|
|
380
|
+
let buffer = '';
|
|
381
|
+
try {
|
|
382
|
+
while (true) {
|
|
383
|
+
const { done, value } = await reader.read();
|
|
384
|
+
if (done) {
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
buffer += decoder.decode(value, { stream: true });
|
|
388
|
+
// Split by double newline (SSE event delimiter)
|
|
389
|
+
const events = buffer.split('\n\n');
|
|
390
|
+
buffer = events.pop() || '';
|
|
391
|
+
for (const event of events) {
|
|
392
|
+
if (event.trim()) {
|
|
393
|
+
// Parse SSE format (data: {json})
|
|
394
|
+
const match = event.match(/^data: (.+)$/m);
|
|
395
|
+
if (match) {
|
|
396
|
+
try {
|
|
397
|
+
const data = JSON.parse(match[1]);
|
|
398
|
+
yield data;
|
|
399
|
+
}
|
|
400
|
+
catch {
|
|
401
|
+
// Ignore parse errors
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
finally {
|
|
409
|
+
reader.releaseLock();
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|