@boxlite-ai/boxlite 0.1.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/README.md +434 -0
- package/dist/browserbox.d.ts +145 -0
- package/dist/browserbox.d.ts.map +1 -0
- package/dist/browserbox.js +234 -0
- package/dist/browserbox.js.map +1 -0
- package/dist/codebox.d.ts +144 -0
- package/dist/codebox.d.ts.map +1 -0
- package/dist/codebox.js +202 -0
- package/dist/codebox.js.map +1 -0
- package/dist/computerbox.d.ts +271 -0
- package/dist/computerbox.d.ts.map +1 -0
- package/dist/computerbox.js +406 -0
- package/dist/computerbox.js.map +1 -0
- package/dist/constants.d.ts +24 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +32 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors.d.ts +82 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +114 -0
- package/dist/errors.js.map +1 -0
- package/dist/exec.d.ts +32 -0
- package/dist/exec.d.ts.map +1 -0
- package/dist/exec.js +3 -0
- package/dist/exec.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/interactivebox.d.ts +155 -0
- package/dist/interactivebox.d.ts.map +1 -0
- package/dist/interactivebox.js +299 -0
- package/dist/interactivebox.js.map +1 -0
- package/dist/native.d.ts +20 -0
- package/dist/native.d.ts.map +1 -0
- package/dist/native.js +41 -0
- package/dist/native.js.map +1 -0
- package/dist/simplebox.d.ts +175 -0
- package/dist/simplebox.d.ts.map +1 -0
- package/dist/simplebox.js +232 -0
- package/dist/simplebox.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* BrowserBox - Secure browser with remote debugging.
|
|
4
|
+
*
|
|
5
|
+
* Provides a minimal, elegant API for running isolated browsers that can be
|
|
6
|
+
* controlled from outside using standard tools like Puppeteer or Playwright.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.BrowserBox = void 0;
|
|
43
|
+
const simplebox_1 = require("./simplebox");
|
|
44
|
+
const errors_1 = require("./errors");
|
|
45
|
+
const constants = __importStar(require("./constants"));
|
|
46
|
+
/**
|
|
47
|
+
* Secure browser environment with remote debugging.
|
|
48
|
+
*
|
|
49
|
+
* Auto-starts a browser with Chrome DevTools Protocol enabled.
|
|
50
|
+
* Connect from outside using Puppeteer, Playwright, Selenium, or DevTools.
|
|
51
|
+
*
|
|
52
|
+
* ## Usage
|
|
53
|
+
*
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const browser = new BrowserBox();
|
|
56
|
+
* try {
|
|
57
|
+
* await browser.start(); // Manually start browser
|
|
58
|
+
* console.log(`Connect to: ${browser.endpoint()}`);
|
|
59
|
+
* // Use Puppeteer/Playwright from your host to connect
|
|
60
|
+
* await new Promise(resolve => setTimeout(resolve, 60000));
|
|
61
|
+
* } finally {
|
|
62
|
+
* await browser.stop();
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* ## Example with custom options
|
|
67
|
+
*
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const browser = new BrowserBox({
|
|
70
|
+
* browser: 'firefox',
|
|
71
|
+
* memoryMib: 4096,
|
|
72
|
+
* cpus: 4
|
|
73
|
+
* });
|
|
74
|
+
* try {
|
|
75
|
+
* await browser.start();
|
|
76
|
+
* const endpoint = browser.endpoint();
|
|
77
|
+
* // Connect using Playwright or Puppeteer
|
|
78
|
+
* } finally {
|
|
79
|
+
* await browser.stop();
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
class BrowserBox extends simplebox_1.SimpleBox {
|
|
84
|
+
/**
|
|
85
|
+
* Create a new BrowserBox.
|
|
86
|
+
*
|
|
87
|
+
* @param options - BrowserBox configuration options
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* const browser = new BrowserBox({
|
|
92
|
+
* browser: 'chromium',
|
|
93
|
+
* memoryMib: 2048,
|
|
94
|
+
* cpus: 2
|
|
95
|
+
* });
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
constructor(options = {}) {
|
|
99
|
+
const { browser = 'chromium', memoryMib = 2048, cpus = 2, ...restOptions } = options;
|
|
100
|
+
super({
|
|
101
|
+
...restOptions,
|
|
102
|
+
image: BrowserBox.DEFAULT_IMAGE,
|
|
103
|
+
memoryMib,
|
|
104
|
+
cpus,
|
|
105
|
+
});
|
|
106
|
+
this._browser = browser;
|
|
107
|
+
this._port = BrowserBox.PORTS[browser] || 9222;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Start the browser with remote debugging enabled.
|
|
111
|
+
*
|
|
112
|
+
* Call this method after creating the BrowserBox to start the browser process.
|
|
113
|
+
* Waits for the browser to be ready before returning.
|
|
114
|
+
*
|
|
115
|
+
* @param timeout - Maximum time to wait for browser to start in seconds (default: 30)
|
|
116
|
+
* @throws {TimeoutError} If browser doesn't start within timeout
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* const browser = new BrowserBox();
|
|
121
|
+
* try {
|
|
122
|
+
* await browser.start();
|
|
123
|
+
* console.log(`Connect to: ${browser.endpoint()}`);
|
|
124
|
+
* } finally {
|
|
125
|
+
* await browser.stop();
|
|
126
|
+
* }
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
async start(timeout = 30) {
|
|
130
|
+
let cmd;
|
|
131
|
+
let processPattern;
|
|
132
|
+
if (this._browser === 'chromium') {
|
|
133
|
+
const binary = '/ms-playwright/chromium-*/chrome-linux/chrome';
|
|
134
|
+
cmd =
|
|
135
|
+
`${binary} --headless --no-sandbox --disable-dev-shm-usage ` +
|
|
136
|
+
`--disable-gpu --remote-debugging-address=0.0.0.0 ` +
|
|
137
|
+
`--remote-debugging-port=${this._port} ` +
|
|
138
|
+
`> /tmp/browser.log 2>&1 &`;
|
|
139
|
+
processPattern = 'chrome';
|
|
140
|
+
}
|
|
141
|
+
else if (this._browser === 'firefox') {
|
|
142
|
+
const binary = '/ms-playwright/firefox-*/firefox/firefox';
|
|
143
|
+
cmd =
|
|
144
|
+
`${binary} --headless ` +
|
|
145
|
+
`--remote-debugging-port=${this._port} ` +
|
|
146
|
+
`> /tmp/browser.log 2>&1 &`;
|
|
147
|
+
processPattern = 'firefox';
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
// webkit
|
|
151
|
+
cmd =
|
|
152
|
+
`playwright run-server --browser webkit ` +
|
|
153
|
+
`--port ${this._port} > /tmp/browser.log 2>&1 &`;
|
|
154
|
+
processPattern = 'playwright';
|
|
155
|
+
}
|
|
156
|
+
// Start browser in background
|
|
157
|
+
await this.exec('sh', '-c', `nohup ${cmd}`);
|
|
158
|
+
// Wait for browser to be ready
|
|
159
|
+
await this.waitForBrowser(processPattern, timeout);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Wait for the browser process to be running.
|
|
163
|
+
*
|
|
164
|
+
* @param processPattern - Pattern to match browser process name
|
|
165
|
+
* @param timeout - Maximum wait time in seconds
|
|
166
|
+
* @throws {TimeoutError} If browser doesn't start within timeout
|
|
167
|
+
*/
|
|
168
|
+
async waitForBrowser(processPattern, timeout) {
|
|
169
|
+
const startTime = Date.now();
|
|
170
|
+
const pollInterval = 0.5;
|
|
171
|
+
while (true) {
|
|
172
|
+
const elapsed = (Date.now() - startTime) / 1000;
|
|
173
|
+
if (elapsed > timeout) {
|
|
174
|
+
throw new errors_1.TimeoutError(`Browser '${this._browser}' did not start within ${timeout} seconds`);
|
|
175
|
+
}
|
|
176
|
+
// Check if browser process is running
|
|
177
|
+
const result = await this.exec('pgrep', '-f', processPattern);
|
|
178
|
+
if (result.exitCode === 0 && result.stdout.trim()) {
|
|
179
|
+
// Browser process found, give it a moment to initialize
|
|
180
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
// Wait before retrying
|
|
184
|
+
await new Promise(resolve => setTimeout(resolve, pollInterval * 1000));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get the connection endpoint for remote debugging.
|
|
189
|
+
*
|
|
190
|
+
* Returns the HTTP endpoint URL for Chrome DevTools Protocol.
|
|
191
|
+
* Use this with Puppeteer, Playwright, or Selenium to connect to the browser.
|
|
192
|
+
*
|
|
193
|
+
* @returns HTTP endpoint URL (e.g., 'http://localhost:9222')
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* const browser = new BrowserBox();
|
|
198
|
+
* try {
|
|
199
|
+
* await browser.start();
|
|
200
|
+
* const url = browser.endpoint();
|
|
201
|
+
*
|
|
202
|
+
* // Use with Puppeteer:
|
|
203
|
+
* // const browserWSEndpoint = await fetch(`${url}/json/version`)
|
|
204
|
+
* // .then(r => r.json())
|
|
205
|
+
* // .then(d => d.webSocketDebuggerUrl);
|
|
206
|
+
* // const browser = await puppeteer.connect({ browserWSEndpoint });
|
|
207
|
+
*
|
|
208
|
+
* // Use with Playwright:
|
|
209
|
+
* // const browser = await chromium.connectOverCDP(url);
|
|
210
|
+
* } finally {
|
|
211
|
+
* await browser.stop();
|
|
212
|
+
* }
|
|
213
|
+
* ```
|
|
214
|
+
*/
|
|
215
|
+
endpoint() {
|
|
216
|
+
return `http://localhost:${this._port}`;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Override async disposal to start browser automatically.
|
|
220
|
+
*
|
|
221
|
+
* @internal
|
|
222
|
+
*/
|
|
223
|
+
async [Symbol.asyncDispose]() {
|
|
224
|
+
await super[Symbol.asyncDispose]();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
exports.BrowserBox = BrowserBox;
|
|
228
|
+
BrowserBox.DEFAULT_IMAGE = 'mcr.microsoft.com/playwright:v1.47.2-jammy';
|
|
229
|
+
BrowserBox.PORTS = {
|
|
230
|
+
chromium: constants.BROWSERBOX_PORT_CHROMIUM,
|
|
231
|
+
firefox: constants.BROWSERBOX_PORT_FIREFOX,
|
|
232
|
+
webkit: constants.BROWSERBOX_PORT_WEBKIT,
|
|
233
|
+
};
|
|
234
|
+
//# sourceMappingURL=browserbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browserbox.js","sourceRoot":"","sources":["../lib/browserbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeBox - Secure Python code execution container.
|
|
3
|
+
*
|
|
4
|
+
* Provides a simple, secure environment for running untrusted Python code.
|
|
5
|
+
*/
|
|
6
|
+
import { SimpleBox, type SimpleBoxOptions } from './simplebox';
|
|
7
|
+
/**
|
|
8
|
+
* Options for creating a CodeBox.
|
|
9
|
+
*/
|
|
10
|
+
export interface CodeBoxOptions extends Omit<SimpleBoxOptions, 'image'> {
|
|
11
|
+
/** Container image with Python (default: 'python:slim') */
|
|
12
|
+
image?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Secure container for executing Python code.
|
|
16
|
+
*
|
|
17
|
+
* CodeBox provides an isolated environment for running untrusted Python code
|
|
18
|
+
* with built-in safety and result formatting.
|
|
19
|
+
*
|
|
20
|
+
* ## Usage
|
|
21
|
+
*
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const codebox = new CodeBox();
|
|
24
|
+
* try {
|
|
25
|
+
* const result = await codebox.run("print('Hello, World!')");
|
|
26
|
+
* console.log(result); // Hello, World!
|
|
27
|
+
* } finally {
|
|
28
|
+
* await codebox.stop();
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* Or with async disposal (TypeScript 5.2+):
|
|
33
|
+
*
|
|
34
|
+
* ```typescript
|
|
35
|
+
* await using codebox = new CodeBox();
|
|
36
|
+
* const result = await codebox.run("print('Hello, World!')");
|
|
37
|
+
* // Automatically stopped when leaving scope
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare class CodeBox extends SimpleBox {
|
|
41
|
+
/**
|
|
42
|
+
* Create a new CodeBox.
|
|
43
|
+
*
|
|
44
|
+
* @param options - CodeBox configuration options
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const codebox = new CodeBox({
|
|
49
|
+
* image: 'python:slim',
|
|
50
|
+
* memoryMib: 512,
|
|
51
|
+
* cpus: 2
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
constructor(options?: CodeBoxOptions);
|
|
56
|
+
/**
|
|
57
|
+
* Execute Python code in the secure container.
|
|
58
|
+
*
|
|
59
|
+
* @param code - Python code to execute
|
|
60
|
+
*
|
|
61
|
+
* @returns Promise resolving to stdout output
|
|
62
|
+
* @throws {ExecError} If Python execution fails (non-zero exit code)
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const codebox = new CodeBox();
|
|
67
|
+
* try {
|
|
68
|
+
* const result = await codebox.run("print('Hello, World!')");
|
|
69
|
+
* console.log(result); // Hello, World!
|
|
70
|
+
* } finally {
|
|
71
|
+
* await codebox.stop();
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* @remarks
|
|
76
|
+
* Uses python3 from the container image.
|
|
77
|
+
* For custom Python paths, use exec() directly:
|
|
78
|
+
* ```typescript
|
|
79
|
+
* const result = await codebox.exec('/path/to/python', '-c', code);
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
run(code: string): Promise<string>;
|
|
83
|
+
/**
|
|
84
|
+
* Execute a Python script file in the container.
|
|
85
|
+
*
|
|
86
|
+
* @param scriptPath - Path to the Python script on the host
|
|
87
|
+
*
|
|
88
|
+
* @returns Promise resolving to execution output
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* const codebox = new CodeBox();
|
|
93
|
+
* try {
|
|
94
|
+
* const result = await codebox.runScript('./my_script.py');
|
|
95
|
+
* console.log(result);
|
|
96
|
+
* } finally {
|
|
97
|
+
* await codebox.stop();
|
|
98
|
+
* }
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
runScript(scriptPath: string): Promise<string>;
|
|
102
|
+
/**
|
|
103
|
+
* Install a Python package in the container using pip.
|
|
104
|
+
*
|
|
105
|
+
* @param packageName - Package name (e.g., 'requests', 'numpy==1.24.0')
|
|
106
|
+
*
|
|
107
|
+
* @returns Promise resolving to installation output
|
|
108
|
+
* @throws {ExecError} If pip installation fails
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* const codebox = new CodeBox();
|
|
113
|
+
* try {
|
|
114
|
+
* await codebox.installPackage('requests');
|
|
115
|
+
* const result = await codebox.run('import requests; print(requests.__version__)');
|
|
116
|
+
* console.log(result);
|
|
117
|
+
* } finally {
|
|
118
|
+
* await codebox.stop();
|
|
119
|
+
* }
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
installPackage(packageName: string): Promise<string>;
|
|
123
|
+
/**
|
|
124
|
+
* Install multiple Python packages.
|
|
125
|
+
*
|
|
126
|
+
* @param packages - Package names to install
|
|
127
|
+
*
|
|
128
|
+
* @returns Promise resolving to installation output
|
|
129
|
+
* @throws {ExecError} If pip installation fails
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* const codebox = new CodeBox();
|
|
134
|
+
* try {
|
|
135
|
+
* await codebox.installPackages('requests', 'numpy', 'pandas');
|
|
136
|
+
* const result = await codebox.run('import requests, numpy, pandas');
|
|
137
|
+
* } finally {
|
|
138
|
+
* await codebox.stop();
|
|
139
|
+
* }
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
installPackages(...packages: string[]): Promise<string>;
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=codebox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codebox.d.ts","sourceRoot":"","sources":["../lib/codebox.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/D;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACrE,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,OAAQ,SAAQ,SAAS;IACpC;;;;;;;;;;;;;OAaG;gBACS,OAAO,GAAE,cAAmB;IAOxC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQxC;;;;;;;;;;;;;;;;;OAiBG;IACG,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAMpD;;;;;;;;;;;;;;;;;;;OAmBG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ1D;;;;;;;;;;;;;;;;;;OAkBG;IACG,eAAe,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CAO9D"}
|
package/dist/codebox.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CodeBox - Secure Python code execution container.
|
|
4
|
+
*
|
|
5
|
+
* Provides a simple, secure environment for running untrusted Python code.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.CodeBox = void 0;
|
|
42
|
+
const simplebox_1 = require("./simplebox");
|
|
43
|
+
const errors_1 = require("./errors");
|
|
44
|
+
/**
|
|
45
|
+
* Secure container for executing Python code.
|
|
46
|
+
*
|
|
47
|
+
* CodeBox provides an isolated environment for running untrusted Python code
|
|
48
|
+
* with built-in safety and result formatting.
|
|
49
|
+
*
|
|
50
|
+
* ## Usage
|
|
51
|
+
*
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const codebox = new CodeBox();
|
|
54
|
+
* try {
|
|
55
|
+
* const result = await codebox.run("print('Hello, World!')");
|
|
56
|
+
* console.log(result); // Hello, World!
|
|
57
|
+
* } finally {
|
|
58
|
+
* await codebox.stop();
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* Or with async disposal (TypeScript 5.2+):
|
|
63
|
+
*
|
|
64
|
+
* ```typescript
|
|
65
|
+
* await using codebox = new CodeBox();
|
|
66
|
+
* const result = await codebox.run("print('Hello, World!')");
|
|
67
|
+
* // Automatically stopped when leaving scope
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
class CodeBox extends simplebox_1.SimpleBox {
|
|
71
|
+
/**
|
|
72
|
+
* Create a new CodeBox.
|
|
73
|
+
*
|
|
74
|
+
* @param options - CodeBox configuration options
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const codebox = new CodeBox({
|
|
79
|
+
* image: 'python:slim',
|
|
80
|
+
* memoryMib: 512,
|
|
81
|
+
* cpus: 2
|
|
82
|
+
* });
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
constructor(options = {}) {
|
|
86
|
+
super({
|
|
87
|
+
...options,
|
|
88
|
+
image: options.image ?? 'python:slim',
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Execute Python code in the secure container.
|
|
93
|
+
*
|
|
94
|
+
* @param code - Python code to execute
|
|
95
|
+
*
|
|
96
|
+
* @returns Promise resolving to stdout output
|
|
97
|
+
* @throws {ExecError} If Python execution fails (non-zero exit code)
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* const codebox = new CodeBox();
|
|
102
|
+
* try {
|
|
103
|
+
* const result = await codebox.run("print('Hello, World!')");
|
|
104
|
+
* console.log(result); // Hello, World!
|
|
105
|
+
* } finally {
|
|
106
|
+
* await codebox.stop();
|
|
107
|
+
* }
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* @remarks
|
|
111
|
+
* Uses python3 from the container image.
|
|
112
|
+
* For custom Python paths, use exec() directly:
|
|
113
|
+
* ```typescript
|
|
114
|
+
* const result = await codebox.exec('/path/to/python', '-c', code);
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
async run(code) {
|
|
118
|
+
const result = await this.exec('/usr/local/bin/python', '-c', code);
|
|
119
|
+
if (result.exitCode !== 0) {
|
|
120
|
+
throw new errors_1.ExecError('run()', result.exitCode, result.stderr);
|
|
121
|
+
}
|
|
122
|
+
return result.stdout;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Execute a Python script file in the container.
|
|
126
|
+
*
|
|
127
|
+
* @param scriptPath - Path to the Python script on the host
|
|
128
|
+
*
|
|
129
|
+
* @returns Promise resolving to execution output
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* const codebox = new CodeBox();
|
|
134
|
+
* try {
|
|
135
|
+
* const result = await codebox.runScript('./my_script.py');
|
|
136
|
+
* console.log(result);
|
|
137
|
+
* } finally {
|
|
138
|
+
* await codebox.stop();
|
|
139
|
+
* }
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
async runScript(scriptPath) {
|
|
143
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs/promises')));
|
|
144
|
+
const code = await fs.readFile(scriptPath, 'utf-8');
|
|
145
|
+
return this.run(code);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Install a Python package in the container using pip.
|
|
149
|
+
*
|
|
150
|
+
* @param packageName - Package name (e.g., 'requests', 'numpy==1.24.0')
|
|
151
|
+
*
|
|
152
|
+
* @returns Promise resolving to installation output
|
|
153
|
+
* @throws {ExecError} If pip installation fails
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* const codebox = new CodeBox();
|
|
158
|
+
* try {
|
|
159
|
+
* await codebox.installPackage('requests');
|
|
160
|
+
* const result = await codebox.run('import requests; print(requests.__version__)');
|
|
161
|
+
* console.log(result);
|
|
162
|
+
* } finally {
|
|
163
|
+
* await codebox.stop();
|
|
164
|
+
* }
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
async installPackage(packageName) {
|
|
168
|
+
const result = await this.exec('pip', 'install', packageName);
|
|
169
|
+
if (result.exitCode !== 0) {
|
|
170
|
+
throw new errors_1.ExecError(`installPackage('${packageName}')`, result.exitCode, result.stderr);
|
|
171
|
+
}
|
|
172
|
+
return result.stdout;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Install multiple Python packages.
|
|
176
|
+
*
|
|
177
|
+
* @param packages - Package names to install
|
|
178
|
+
*
|
|
179
|
+
* @returns Promise resolving to installation output
|
|
180
|
+
* @throws {ExecError} If pip installation fails
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* const codebox = new CodeBox();
|
|
185
|
+
* try {
|
|
186
|
+
* await codebox.installPackages('requests', 'numpy', 'pandas');
|
|
187
|
+
* const result = await codebox.run('import requests, numpy, pandas');
|
|
188
|
+
* } finally {
|
|
189
|
+
* await codebox.stop();
|
|
190
|
+
* }
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
async installPackages(...packages) {
|
|
194
|
+
const result = await this.exec('pip', 'install', ...packages);
|
|
195
|
+
if (result.exitCode !== 0) {
|
|
196
|
+
throw new errors_1.ExecError(`installPackages(${packages.join(', ')})`, result.exitCode, result.stderr);
|
|
197
|
+
}
|
|
198
|
+
return result.stdout;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
exports.CodeBox = CodeBox;
|
|
202
|
+
//# sourceMappingURL=codebox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codebox.js","sourceRoot":"","sources":["../lib/codebox.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,2CAA+D;AAC/D,qCAAqC;AAUrC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAa,OAAQ,SAAQ,qBAAS;IACpC;;;;;;;;;;;;;OAaG;IACH,YAAY,UAA0B,EAAE;QACtC,KAAK,CAAC;YACJ,GAAG,OAAO;YACV,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,aAAa;SACtC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,KAAK,CAAC,GAAG,CAAC,IAAY;QACpB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACpE,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,kBAAS,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,SAAS,CAAC,UAAkB;QAChC,MAAM,EAAE,GAAG,wDAAa,aAAa,GAAC,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,KAAK,CAAC,cAAc,CAAC,WAAmB;QACtC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,kBAAS,CAAC,mBAAmB,WAAW,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1F,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAK,CAAC,eAAe,CAAC,GAAG,QAAkB;QACzC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,kBAAS,CAAC,mBAAmB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACjG,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;CACF;AAtID,0BAsIC"}
|