microsandbox 0.1.1 → 0.3.7
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 +333 -84
- package/index.cjs +609 -0
- package/index.d.cts +751 -0
- package/index.mjs +21 -0
- package/package.json +31 -48
- package/postinstall.js +194 -0
- package/dist/base-sandbox.d.ts +0 -91
- package/dist/base-sandbox.js +0 -264
- package/dist/base-sandbox.js.map +0 -1
- package/dist/command-execution.d.ts +0 -59
- package/dist/command-execution.js +0 -102
- package/dist/command-execution.js.map +0 -1
- package/dist/command.d.ts +0 -24
- package/dist/command.js +0 -84
- package/dist/command.js.map +0 -1
- package/dist/execution.d.ts +0 -52
- package/dist/execution.js +0 -103
- package/dist/execution.js.map +0 -1
- package/dist/index.d.ts +0 -13
- package/dist/index.js +0 -25
- package/dist/index.js.map +0 -1
- package/dist/metrics.d.ts +0 -69
- package/dist/metrics.js +0 -142
- package/dist/metrics.js.map +0 -1
- package/dist/node-sandbox.d.ts +0 -32
- package/dist/node-sandbox.js +0 -92
- package/dist/node-sandbox.js.map +0 -1
- package/dist/python-sandbox.d.ts +0 -32
- package/dist/python-sandbox.js +0 -92
- package/dist/python-sandbox.js.map +0 -1
- package/dist/types.d.ts +0 -110
- package/dist/types.js +0 -88
- package/dist/types.js.map +0 -1
package/index.mjs
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Auto-generated ESM wrapper for NAPI-RS CJS module.
|
|
2
|
+
import binding from "./index.cjs";
|
|
3
|
+
|
|
4
|
+
export const {
|
|
5
|
+
ExecHandle,
|
|
6
|
+
ExecOutput,
|
|
7
|
+
ExecSink,
|
|
8
|
+
Mount,
|
|
9
|
+
NetworkPolicy,
|
|
10
|
+
Sandbox,
|
|
11
|
+
SandboxFs,
|
|
12
|
+
SandboxHandle,
|
|
13
|
+
Secret,
|
|
14
|
+
Volume,
|
|
15
|
+
VolumeHandle,
|
|
16
|
+
allSandboxMetrics,
|
|
17
|
+
install,
|
|
18
|
+
isInstalled,
|
|
19
|
+
} = binding;
|
|
20
|
+
|
|
21
|
+
export default binding;
|
package/package.json
CHANGED
|
@@ -1,57 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "microsandbox",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"types": "
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"test": "jest",
|
|
16
|
-
"lint": "eslint src --ext .ts",
|
|
17
|
-
"prepare": "npm run build",
|
|
18
|
-
"example:node": "ts-node examples/node.ts",
|
|
19
|
-
"example:python": "ts-node examples/python.ts",
|
|
20
|
-
"example:command": "ts-node examples/command.ts",
|
|
21
|
-
"example:metrics": "ts-node examples/metrics.ts"
|
|
3
|
+
"version": "0.3.7",
|
|
4
|
+
"main": "index.cjs",
|
|
5
|
+
"module": "index.mjs",
|
|
6
|
+
"types": "index.d.cts",
|
|
7
|
+
"napi": {
|
|
8
|
+
"binaryName": "microsandbox",
|
|
9
|
+
"packageName": "@superradcompany/microsandbox",
|
|
10
|
+
"targets": [
|
|
11
|
+
"aarch64-apple-darwin",
|
|
12
|
+
"x86_64-unknown-linux-gnu",
|
|
13
|
+
"aarch64-unknown-linux-gnu"
|
|
14
|
+
]
|
|
22
15
|
},
|
|
23
|
-
"keywords": [
|
|
24
|
-
"microsandbox",
|
|
25
|
-
"sdk",
|
|
26
|
-
"sandbox",
|
|
27
|
-
"security",
|
|
28
|
-
"code-execution",
|
|
29
|
-
"typescript"
|
|
30
|
-
],
|
|
31
|
-
"author": "Microsandbox Team <team@microsandbox.dev>",
|
|
32
16
|
"license": "Apache-2.0",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"url": "git+https://github.com/microsandbox/microsandbox.git"
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">= 18"
|
|
36
19
|
},
|
|
37
|
-
"
|
|
38
|
-
"
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "napi build --release --platform --js index.cjs --dts index.d.cts",
|
|
22
|
+
"build:debug": "napi build --platform --js index.cjs --dts index.d.cts",
|
|
23
|
+
"postinstall": "node postinstall.js"
|
|
39
24
|
},
|
|
40
|
-
"homepage": "https://github.com/microsandbox/microsandbox",
|
|
41
25
|
"devDependencies": {
|
|
42
|
-
"@
|
|
43
|
-
"@types/node": "^18.15.0",
|
|
44
|
-
"@types/node-fetch": "^2.6.4",
|
|
45
|
-
"@types/uuid": "^9.0.1",
|
|
46
|
-
"eslint": "^8.36.0",
|
|
47
|
-
"jest": "^29.5.0",
|
|
48
|
-
"ts-jest": "^29.1.0",
|
|
49
|
-
"ts-node": "^10.9.1",
|
|
50
|
-
"typescript": "^5.0.2"
|
|
26
|
+
"@napi-rs/cli": "^3"
|
|
51
27
|
},
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
}
|
|
28
|
+
"optionalDependencies": {
|
|
29
|
+
"@superradcompany/microsandbox-darwin-arm64": "0.3.7",
|
|
30
|
+
"@superradcompany/microsandbox-linux-x64-gnu": "0.3.7",
|
|
31
|
+
"@superradcompany/microsandbox-linux-arm64-gnu": "0.3.7"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"index.cjs",
|
|
35
|
+
"index.mjs",
|
|
36
|
+
"index.d.cts",
|
|
37
|
+
"postinstall.js",
|
|
38
|
+
"README.md"
|
|
39
|
+
]
|
|
57
40
|
}
|
package/postinstall.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Downloads msb + libkrunfw binaries to ~/.microsandbox/{bin,lib}/ during npm install.
|
|
4
|
+
|
|
5
|
+
const { execFileSync, execSync } = require("child_process");
|
|
6
|
+
const fs = require("fs");
|
|
7
|
+
const os = require("os");
|
|
8
|
+
const path = require("path");
|
|
9
|
+
const https = require("https");
|
|
10
|
+
const http = require("http");
|
|
11
|
+
|
|
12
|
+
const PREBUILT_VERSION = require("./package.json").version;
|
|
13
|
+
const LIBKRUNFW_ABI = "5";
|
|
14
|
+
const LIBKRUNFW_VERSION = "5.2.1";
|
|
15
|
+
const GITHUB_ORG = "superradcompany";
|
|
16
|
+
const REPO = "microsandbox";
|
|
17
|
+
const BASE_DIR = path.join(os.homedir(), ".microsandbox");
|
|
18
|
+
const BIN_DIR = path.join(BASE_DIR, "bin");
|
|
19
|
+
const LIB_DIR = path.join(BASE_DIR, "lib");
|
|
20
|
+
|
|
21
|
+
function getArch() {
|
|
22
|
+
const arch = process.arch;
|
|
23
|
+
if (arch === "arm64" || arch === "aarch64") return "aarch64";
|
|
24
|
+
if (arch === "x64" || arch === "x86_64") return "x86_64";
|
|
25
|
+
throw new Error(`Unsupported architecture: ${arch}`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getOS() {
|
|
29
|
+
const platform = process.platform;
|
|
30
|
+
if (platform === "darwin") return "darwin";
|
|
31
|
+
if (platform === "linux") return "linux";
|
|
32
|
+
throw new Error(`Unsupported platform: ${platform}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function libkrunfwFilename(targetOS) {
|
|
36
|
+
if (targetOS === "darwin") return `libkrunfw.${LIBKRUNFW_ABI}.dylib`;
|
|
37
|
+
return `libkrunfw.so.${LIBKRUNFW_VERSION}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function libkrunfwSymlinks(filename, targetOS) {
|
|
41
|
+
if (targetOS === "darwin") {
|
|
42
|
+
return [["libkrunfw.dylib", filename]];
|
|
43
|
+
}
|
|
44
|
+
const soname = `libkrunfw.so.${LIBKRUNFW_ABI}`;
|
|
45
|
+
return [
|
|
46
|
+
[soname, filename],
|
|
47
|
+
["libkrunfw.so", soname],
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function bundleUrl(version, arch, targetOS) {
|
|
52
|
+
return `https://github.com/${GITHUB_ORG}/${REPO}/releases/download/v${version}/${REPO}-${targetOS}-${arch}.tar.gz`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Follow redirects and return the response body as a Buffer. */
|
|
56
|
+
function download(url) {
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
const get = url.startsWith("https:") ? https.get : http.get;
|
|
59
|
+
get(url, (res) => {
|
|
60
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
61
|
+
return download(res.headers.location).then(resolve, reject);
|
|
62
|
+
}
|
|
63
|
+
if (res.statusCode !== 200) {
|
|
64
|
+
return reject(new Error(`HTTP ${res.statusCode} for ${url}`));
|
|
65
|
+
}
|
|
66
|
+
const chunks = [];
|
|
67
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
68
|
+
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
69
|
+
res.on("error", reject);
|
|
70
|
+
}).on("error", reject);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Extract a .tar.gz buffer, routing files to bin/ or lib/. */
|
|
75
|
+
function extractBundle(data) {
|
|
76
|
+
// Use tar CLI since Node doesn't have built-in tar support without dependencies.
|
|
77
|
+
const tmpFile = path.join(os.tmpdir(), `microsandbox-bundle-${Date.now()}.tar.gz`);
|
|
78
|
+
const tmpExtract = path.join(os.tmpdir(), `microsandbox-extract-${Date.now()}`);
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
fs.writeFileSync(tmpFile, data);
|
|
82
|
+
fs.mkdirSync(tmpExtract, { recursive: true });
|
|
83
|
+
execSync(`tar xzf "${tmpFile}" -C "${tmpExtract}"`, { stdio: "pipe" });
|
|
84
|
+
|
|
85
|
+
for (const name of fs.readdirSync(tmpExtract)) {
|
|
86
|
+
const src = path.join(tmpExtract, name);
|
|
87
|
+
const dest = name.startsWith("libkrunfw")
|
|
88
|
+
? path.join(LIB_DIR, name)
|
|
89
|
+
: path.join(BIN_DIR, name);
|
|
90
|
+
fs.copyFileSync(src, dest);
|
|
91
|
+
fs.chmodSync(dest, 0o755);
|
|
92
|
+
}
|
|
93
|
+
} finally {
|
|
94
|
+
try { fs.unlinkSync(tmpFile); } catch {}
|
|
95
|
+
try { fs.rmSync(tmpExtract, { recursive: true }); } catch {}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function main() {
|
|
100
|
+
const targetOS = getOS();
|
|
101
|
+
const arch = getArch();
|
|
102
|
+
const libkrunfw = libkrunfwFilename(targetOS);
|
|
103
|
+
|
|
104
|
+
// Skip if already installed and the bundled msb version matches the
|
|
105
|
+
// current package version.
|
|
106
|
+
if (
|
|
107
|
+
fs.existsSync(path.join(LIB_DIR, libkrunfw)) &&
|
|
108
|
+
installedMsbVersion(path.join(BIN_DIR, "msb")) === PREBUILT_VERSION
|
|
109
|
+
) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
114
|
+
fs.mkdirSync(LIB_DIR, { recursive: true });
|
|
115
|
+
|
|
116
|
+
if (installCiLocalBundle(libkrunfw)) {
|
|
117
|
+
console.log("microsandbox: installed runtime dependencies from local CI build/");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const url = bundleUrl(PREBUILT_VERSION, arch, targetOS);
|
|
122
|
+
console.log(`microsandbox: downloading runtime dependencies (v${PREBUILT_VERSION})...`);
|
|
123
|
+
const data = await download(url);
|
|
124
|
+
|
|
125
|
+
extractBundle(data);
|
|
126
|
+
|
|
127
|
+
// Create libkrunfw symlinks.
|
|
128
|
+
for (const [linkName, target] of libkrunfwSymlinks(libkrunfw, targetOS)) {
|
|
129
|
+
const linkPath = path.join(LIB_DIR, linkName);
|
|
130
|
+
try { fs.unlinkSync(linkPath); } catch {}
|
|
131
|
+
fs.symlinkSync(target, linkPath);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Verify.
|
|
135
|
+
if (!fs.existsSync(path.join(BIN_DIR, "msb"))) {
|
|
136
|
+
throw new Error("msb binary not found after extraction");
|
|
137
|
+
}
|
|
138
|
+
if (!fs.existsSync(path.join(LIB_DIR, libkrunfw))) {
|
|
139
|
+
throw new Error(`${libkrunfw} not found after extraction`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
console.log("microsandbox: runtime dependencies installed.");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function installedMsbVersion(msbPath) {
|
|
146
|
+
if (!fs.existsSync(msbPath)) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
const stdout = execFileSync(msbPath, ["--version"], { encoding: "utf8" }).trim();
|
|
152
|
+
return stdout.startsWith("msb ") ? stdout.slice(4) : null;
|
|
153
|
+
} catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function installCiLocalBundle(libkrunfw) {
|
|
159
|
+
if (!process.env.CI) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const repoRoot = path.resolve(__dirname, "..", "..");
|
|
164
|
+
const buildDir = path.join(repoRoot, "build");
|
|
165
|
+
if (!fs.existsSync(path.join(repoRoot, "Cargo.toml"))) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const msbSrc = path.join(buildDir, "msb");
|
|
170
|
+
const libSrc = path.join(buildDir, libkrunfw);
|
|
171
|
+
if (!fs.existsSync(msbSrc) || !fs.existsSync(libSrc)) {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
fs.copyFileSync(msbSrc, path.join(BIN_DIR, "msb"));
|
|
176
|
+
fs.copyFileSync(libSrc, path.join(LIB_DIR, libkrunfw));
|
|
177
|
+
fs.chmodSync(path.join(BIN_DIR, "msb"), 0o755);
|
|
178
|
+
fs.chmodSync(path.join(LIB_DIR, libkrunfw), 0o755);
|
|
179
|
+
|
|
180
|
+
for (const [linkName, target] of libkrunfwSymlinks(libkrunfw, getOS())) {
|
|
181
|
+
const linkPath = path.join(LIB_DIR, linkName);
|
|
182
|
+
try { fs.unlinkSync(linkPath); } catch {}
|
|
183
|
+
fs.symlinkSync(target, linkPath);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
main().catch((err) => {
|
|
190
|
+
console.error(`microsandbox: failed to install runtime dependencies: ${err.message}`);
|
|
191
|
+
console.error("You can install them manually: curl -fsSL https://get.microsandbox.dev | sh");
|
|
192
|
+
// Don't fail the npm install — the user can install manually.
|
|
193
|
+
process.exit(0);
|
|
194
|
+
});
|
package/dist/base-sandbox.d.ts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Base sandbox implementation for the Microsandbox TypeScript SDK.
|
|
3
|
-
*/
|
|
4
|
-
import { Command } from "./command";
|
|
5
|
-
import { Metrics } from "./metrics";
|
|
6
|
-
import { Execution } from "./execution";
|
|
7
|
-
import { SandboxOptions } from "./types";
|
|
8
|
-
export declare abstract class BaseSandbox {
|
|
9
|
-
protected _serverUrl: string;
|
|
10
|
-
protected _namespace: string;
|
|
11
|
-
protected _name: string;
|
|
12
|
-
protected _apiKey: string | undefined;
|
|
13
|
-
protected _isStarted: boolean;
|
|
14
|
-
/**
|
|
15
|
-
* Initialize a base sandbox instance.
|
|
16
|
-
*
|
|
17
|
-
* @param options - Configuration options for the sandbox
|
|
18
|
-
*/
|
|
19
|
-
constructor(options?: SandboxOptions);
|
|
20
|
-
/**
|
|
21
|
-
* Create and initialize a new sandbox instance.
|
|
22
|
-
*
|
|
23
|
-
* This is the base implementation that subclasses should call.
|
|
24
|
-
*
|
|
25
|
-
* @param ctor - The constructor function for the subclass
|
|
26
|
-
* @param options - Configuration options for the sandbox
|
|
27
|
-
* @returns A Promise resolving to a new sandbox instance
|
|
28
|
-
*/
|
|
29
|
-
protected static createBase<T extends BaseSandbox>(ctor: new (options?: SandboxOptions) => T, options?: SandboxOptions): Promise<T>;
|
|
30
|
-
static create(options?: SandboxOptions): Promise<BaseSandbox>;
|
|
31
|
-
/**
|
|
32
|
-
* Get the default Docker image for this sandbox type.
|
|
33
|
-
*
|
|
34
|
-
* @returns A string containing the Docker image name and tag
|
|
35
|
-
*/
|
|
36
|
-
abstract getDefaultImage(): Promise<string>;
|
|
37
|
-
/**
|
|
38
|
-
* Start the sandbox container.
|
|
39
|
-
*
|
|
40
|
-
* @param image - Docker image to use for the sandbox (defaults to language-specific image)
|
|
41
|
-
* @param memory - Memory limit in MB
|
|
42
|
-
* @param cpus - CPU limit (will be rounded to nearest integer)
|
|
43
|
-
* @param timeout - Maximum time in seconds to wait for the sandbox to start (default: 180 seconds)
|
|
44
|
-
*
|
|
45
|
-
* @throws Error if the sandbox fails to start
|
|
46
|
-
* @throws Error if the sandbox doesn't start within the specified timeout
|
|
47
|
-
*/
|
|
48
|
-
start(image?: string, memory?: number, cpus?: number, timeout?: number): Promise<void>;
|
|
49
|
-
/**
|
|
50
|
-
* Stop the sandbox container.
|
|
51
|
-
*
|
|
52
|
-
* @throws Error if the sandbox fails to stop
|
|
53
|
-
*/
|
|
54
|
-
stop(): Promise<void>;
|
|
55
|
-
/**
|
|
56
|
-
* Execute code in the sandbox.
|
|
57
|
-
*
|
|
58
|
-
* @param code - Code to execute
|
|
59
|
-
* @returns An Execution object representing the executed code
|
|
60
|
-
* @throws Error if execution fails
|
|
61
|
-
*/
|
|
62
|
-
abstract run(code: string): Promise<Execution>;
|
|
63
|
-
/**
|
|
64
|
-
* Access the command namespace for executing shell commands in the sandbox.
|
|
65
|
-
*/
|
|
66
|
-
get command(): Command;
|
|
67
|
-
/**
|
|
68
|
-
* Access the metrics namespace for retrieving sandbox metrics.
|
|
69
|
-
*/
|
|
70
|
-
get metrics(): Metrics;
|
|
71
|
-
/**
|
|
72
|
-
* Check if the sandbox is started.
|
|
73
|
-
*/
|
|
74
|
-
get isStarted(): boolean;
|
|
75
|
-
/**
|
|
76
|
-
* Get the server URL.
|
|
77
|
-
*/
|
|
78
|
-
get serverUrl(): string;
|
|
79
|
-
/**
|
|
80
|
-
* Get the namespace.
|
|
81
|
-
*/
|
|
82
|
-
get namespace(): string;
|
|
83
|
-
/**
|
|
84
|
-
* Get the sandbox name.
|
|
85
|
-
*/
|
|
86
|
-
get name(): string;
|
|
87
|
-
/**
|
|
88
|
-
* Get the API key.
|
|
89
|
-
*/
|
|
90
|
-
get apiKey(): string | undefined;
|
|
91
|
-
}
|
package/dist/base-sandbox.js
DELETED
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Base sandbox implementation for the Microsandbox TypeScript SDK.
|
|
4
|
-
*/
|
|
5
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
-
}
|
|
11
|
-
Object.defineProperty(o, k2, desc);
|
|
12
|
-
}) : (function(o, m, k, k2) {
|
|
13
|
-
if (k2 === undefined) k2 = k;
|
|
14
|
-
o[k2] = m[k];
|
|
15
|
-
}));
|
|
16
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
-
}) : function(o, v) {
|
|
19
|
-
o["default"] = v;
|
|
20
|
-
});
|
|
21
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
-
var ownKeys = function(o) {
|
|
23
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
-
var ar = [];
|
|
25
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
-
return ar;
|
|
27
|
-
};
|
|
28
|
-
return ownKeys(o);
|
|
29
|
-
};
|
|
30
|
-
return function (mod) {
|
|
31
|
-
if (mod && mod.__esModule) return mod;
|
|
32
|
-
var result = {};
|
|
33
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
-
__setModuleDefault(result, mod);
|
|
35
|
-
return result;
|
|
36
|
-
};
|
|
37
|
-
})();
|
|
38
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
-
};
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.BaseSandbox = void 0;
|
|
43
|
-
const uuid_1 = require("uuid");
|
|
44
|
-
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
45
|
-
const dotenv = __importStar(require("dotenv"));
|
|
46
|
-
const command_1 = require("./command");
|
|
47
|
-
const metrics_1 = require("./metrics");
|
|
48
|
-
class BaseSandbox {
|
|
49
|
-
/**
|
|
50
|
-
* Initialize a base sandbox instance.
|
|
51
|
-
*
|
|
52
|
-
* @param options - Configuration options for the sandbox
|
|
53
|
-
*/
|
|
54
|
-
constructor(options) {
|
|
55
|
-
this._isStarted = false;
|
|
56
|
-
// Try to load from .env if MSB_API_KEY is not already set
|
|
57
|
-
if (!process.env.MSB_API_KEY) {
|
|
58
|
-
try {
|
|
59
|
-
dotenv.config();
|
|
60
|
-
}
|
|
61
|
-
catch (error) {
|
|
62
|
-
// Ignore errors if .env file doesn't exist
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
this._serverUrl =
|
|
66
|
-
options?.serverUrl ||
|
|
67
|
-
process.env.MSB_SERVER_URL ||
|
|
68
|
-
"http://127.0.0.1:5555";
|
|
69
|
-
this._namespace = options?.namespace || "default";
|
|
70
|
-
this._name = options?.name || `sandbox-${(0, uuid_1.v4)().substring(0, 8)}`;
|
|
71
|
-
this._apiKey = options?.apiKey || process.env.MSB_API_KEY;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Create and initialize a new sandbox instance.
|
|
75
|
-
*
|
|
76
|
-
* This is the base implementation that subclasses should call.
|
|
77
|
-
*
|
|
78
|
-
* @param ctor - The constructor function for the subclass
|
|
79
|
-
* @param options - Configuration options for the sandbox
|
|
80
|
-
* @returns A Promise resolving to a new sandbox instance
|
|
81
|
-
*/
|
|
82
|
-
static async createBase(ctor, options) {
|
|
83
|
-
// Try to load from .env if MSB_API_KEY is not already set
|
|
84
|
-
if (!process.env.MSB_API_KEY) {
|
|
85
|
-
try {
|
|
86
|
-
dotenv.config();
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
// Ignore errors if .env file doesn't exist
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
const sandbox = new ctor(options);
|
|
93
|
-
// Start the sandbox
|
|
94
|
-
await sandbox.start(options?.image, options?.memory, options?.cpus, options?.timeout);
|
|
95
|
-
return sandbox;
|
|
96
|
-
}
|
|
97
|
-
// Abstract static method signature that subclasses must implement
|
|
98
|
-
static create(options) {
|
|
99
|
-
throw new Error("Static method 'create' must be implemented by subclass");
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Start the sandbox container.
|
|
103
|
-
*
|
|
104
|
-
* @param image - Docker image to use for the sandbox (defaults to language-specific image)
|
|
105
|
-
* @param memory - Memory limit in MB
|
|
106
|
-
* @param cpus - CPU limit (will be rounded to nearest integer)
|
|
107
|
-
* @param timeout - Maximum time in seconds to wait for the sandbox to start (default: 180 seconds)
|
|
108
|
-
*
|
|
109
|
-
* @throws Error if the sandbox fails to start
|
|
110
|
-
* @throws Error if the sandbox doesn't start within the specified timeout
|
|
111
|
-
*/
|
|
112
|
-
async start(image, memory = 512, cpus = 1.0, timeout = 180.0) {
|
|
113
|
-
if (this._isStarted) {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
const sandboxImage = image || (await this.getDefaultImage());
|
|
117
|
-
const requestData = {
|
|
118
|
-
jsonrpc: "2.0",
|
|
119
|
-
method: "sandbox.start",
|
|
120
|
-
params: {
|
|
121
|
-
namespace: this._namespace,
|
|
122
|
-
sandbox: this._name,
|
|
123
|
-
config: {
|
|
124
|
-
image: sandboxImage,
|
|
125
|
-
memory,
|
|
126
|
-
cpus: Math.round(cpus),
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
id: (0, uuid_1.v4)(),
|
|
130
|
-
};
|
|
131
|
-
const headers = {
|
|
132
|
-
"Content-Type": "application/json",
|
|
133
|
-
};
|
|
134
|
-
if (this._apiKey) {
|
|
135
|
-
headers["Authorization"] = `Bearer ${this._apiKey}`;
|
|
136
|
-
}
|
|
137
|
-
try {
|
|
138
|
-
// We don't have a client-side timeout like the Python SDK, but we can implement one if needed
|
|
139
|
-
const response = await (0, node_fetch_1.default)(`${this._serverUrl}/api/v1/rpc`, {
|
|
140
|
-
method: "POST",
|
|
141
|
-
headers,
|
|
142
|
-
body: JSON.stringify(requestData),
|
|
143
|
-
// We'd need to use a more sophisticated fetch library for proper timeout handling
|
|
144
|
-
// Node-fetch doesn't have a timeout option that works the same way as Python's aiohttp
|
|
145
|
-
});
|
|
146
|
-
if (!response.ok) {
|
|
147
|
-
const errorText = await response.text();
|
|
148
|
-
throw new Error(`Failed to start sandbox: ${errorText}`);
|
|
149
|
-
}
|
|
150
|
-
const responseData = await response.json();
|
|
151
|
-
if ("error" in responseData) {
|
|
152
|
-
throw new Error(`Failed to start sandbox: ${responseData.error.message}`);
|
|
153
|
-
}
|
|
154
|
-
// Check the result message - it might indicate the sandbox is still initializing
|
|
155
|
-
const result = responseData.result;
|
|
156
|
-
if (typeof result === "string" && result.includes("timed out waiting")) {
|
|
157
|
-
// Server timed out but still started the sandbox
|
|
158
|
-
// We'll log a warning but still consider it started
|
|
159
|
-
console.warn(`Sandbox start warning: ${result}`);
|
|
160
|
-
}
|
|
161
|
-
this._isStarted = true;
|
|
162
|
-
}
|
|
163
|
-
catch (e) {
|
|
164
|
-
if (e instanceof Error) {
|
|
165
|
-
if (e.message.includes("timeout")) {
|
|
166
|
-
throw new Error(`Timed out waiting for sandbox to start after ${timeout} seconds`);
|
|
167
|
-
}
|
|
168
|
-
throw new Error(`Failed to communicate with Microsandbox server: ${e.message}`);
|
|
169
|
-
}
|
|
170
|
-
throw new Error("Failed to communicate with Microsandbox server: Unknown error");
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Stop the sandbox container.
|
|
175
|
-
*
|
|
176
|
-
* @throws Error if the sandbox fails to stop
|
|
177
|
-
*/
|
|
178
|
-
async stop() {
|
|
179
|
-
if (!this._isStarted) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
const requestData = {
|
|
183
|
-
jsonrpc: "2.0",
|
|
184
|
-
method: "sandbox.stop",
|
|
185
|
-
params: {
|
|
186
|
-
namespace: this._namespace,
|
|
187
|
-
sandbox: this._name,
|
|
188
|
-
},
|
|
189
|
-
id: (0, uuid_1.v4)(),
|
|
190
|
-
};
|
|
191
|
-
const headers = {
|
|
192
|
-
"Content-Type": "application/json",
|
|
193
|
-
};
|
|
194
|
-
if (this._apiKey) {
|
|
195
|
-
headers["Authorization"] = `Bearer ${this._apiKey}`;
|
|
196
|
-
}
|
|
197
|
-
try {
|
|
198
|
-
const response = await (0, node_fetch_1.default)(`${this._serverUrl}/api/v1/rpc`, {
|
|
199
|
-
method: "POST",
|
|
200
|
-
headers,
|
|
201
|
-
body: JSON.stringify(requestData),
|
|
202
|
-
});
|
|
203
|
-
if (!response.ok) {
|
|
204
|
-
const errorText = await response.text();
|
|
205
|
-
throw new Error(`Failed to stop sandbox: ${errorText}`);
|
|
206
|
-
}
|
|
207
|
-
const responseData = await response.json();
|
|
208
|
-
if ("error" in responseData) {
|
|
209
|
-
throw new Error(`Failed to stop sandbox: ${responseData.error.message}`);
|
|
210
|
-
}
|
|
211
|
-
this._isStarted = false;
|
|
212
|
-
}
|
|
213
|
-
catch (e) {
|
|
214
|
-
if (e instanceof Error) {
|
|
215
|
-
throw new Error(`Failed to communicate with Microsandbox server: ${e.message}`);
|
|
216
|
-
}
|
|
217
|
-
throw new Error("Failed to communicate with Microsandbox server: Unknown error");
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Access the command namespace for executing shell commands in the sandbox.
|
|
222
|
-
*/
|
|
223
|
-
get command() {
|
|
224
|
-
return new command_1.Command(this);
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Access the metrics namespace for retrieving sandbox metrics.
|
|
228
|
-
*/
|
|
229
|
-
get metrics() {
|
|
230
|
-
return new metrics_1.Metrics(this);
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Check if the sandbox is started.
|
|
234
|
-
*/
|
|
235
|
-
get isStarted() {
|
|
236
|
-
return this._isStarted;
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Get the server URL.
|
|
240
|
-
*/
|
|
241
|
-
get serverUrl() {
|
|
242
|
-
return this._serverUrl;
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Get the namespace.
|
|
246
|
-
*/
|
|
247
|
-
get namespace() {
|
|
248
|
-
return this._namespace;
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Get the sandbox name.
|
|
252
|
-
*/
|
|
253
|
-
get name() {
|
|
254
|
-
return this._name;
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Get the API key.
|
|
258
|
-
*/
|
|
259
|
-
get apiKey() {
|
|
260
|
-
return this._apiKey;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
exports.BaseSandbox = BaseSandbox;
|
|
264
|
-
//# sourceMappingURL=base-sandbox.js.map
|
package/dist/base-sandbox.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"base-sandbox.js","sourceRoot":"","sources":["../src/base-sandbox.ts"],"names":[],"mappings":"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"}
|