BoxLite 节点.js/ TypeScript SDK
可嵌入 VM 运行时间用于安全,孤立的代码执行环境.
进入 代理 API 结束 JsBox.agents
财务报告和审定财务报表 SimpleBox.agents 用于代理和转动方法、分组选项和错误处理.
想想"SQLite来沙盒" - 直接嵌入在应用程序中的轻量级库,而不需要守护进程或根权限.
特征
- 硬件级 VM 隔离 (KVM on Linux, Hypervisor. Framework on macOS) (韩语)
- OCI 集装箱支持 - 使用任何 Docker/OCI 图像
- Async 第一张API - 在土生土长的砂拉越上建造
- 多个专用盒数字 :
SimpleBox- 基本命令执行CodeBox- Python 密码沙盒BrowserBox- 浏览器自动化(Puppeteer/Playwright)ComputerBox- 桌面自动化(14个自动化功能)InteractiveBox- PTY终端会话
- 零守护进程 - 不需要背景过程
- 跨平台 - macOS ARM64, Linux x86 64/ARM64
安装
npm install @boxlite-ai/boxlite
所需经费:
- 节点.js 18或以后
- 有硬件虚拟化的平台 :
- macOS:苹果硅(macOS 12+)
- Linux: x86 64 或 ARM64 有 KVM ()
/dev/kvm可访问)
不支持 : macOS Intel, Windows(使用带有Linux要求的WSL2)
快速启动
Java 脚本
import { SimpleBox } from '@boxlite-ai/boxlite';
async function main() {
const box = new SimpleBox({ image: 'alpine:latest' });
try {
const result = await box.exec('echo', 'Hello from BoxLite!');
console.log(result.stdout); // Hello from BoxLite!
} finally {
await box.stop();
}
}
main();
类型脚本
import { SimpleBox } from 'boxlite';
async function main() {
const box = new SimpleBox({ image: 'alpine:latest' });
try {
const result = await box.exec('echo', 'Hello from BoxLite!');
console.log(result.stdout);
} finally {
await box.stop();
}
}
main();
TypeScript 5.2+ (同步处理)
import { SimpleBox } from 'boxlite';
async function main() {
await using box = new SimpleBox({ image: 'alpine:latest' });
const result = await box.exec('echo', 'Hello!');
console.log(result.stdout);
// Box automatically stopped when leaving scope
}
main();
API 参考
远程 BoxLite 服务器 (REST)
连接到远程 BoxLite 服务器而不是本地运行时间 .
构造一个 ApiKeyCredential 并呈递其位置:
Boxlite.rest(url, credential)。 。 。 .
import { JsBoxlite, ApiKeyCredential } from '@boxlite-ai/boxlite';
const rt = JsBoxlite.rest(
'http://localhost:8100',
new ApiKeyCredential('your-api-key'),
);
const boxes = await rt.listInfo();
// Env discovery — returns null when BOXLITE_API_KEY is unset:
const cred = ApiKeyCredential.fromEnv();
const rt2 = JsBoxlite.rest('http://localhost:8100', cred ?? undefined);
ApiKeyCredential 结构满足导出 Credential
界面; 函数可以按 Credential 财务报告和审定财务报表
接受任何未来的证书类型而无需更改签名.
运行前缀( 复仇- 不可知)
框范围请求 {url}/v1/{prefix}/…编辑
v1 段为硬码; path_prefix 是不透明的,部署 -
服务器告诉客户端通过
Principal.path_prefix 从 GET /v1/me。槽的语义
专供供应商使用:盒式云为组织使用
id; 另一种部署可能使用工作空间名称, 区域+团队
,或者任何其他多块值,例如 us-east/team-42。 。 。 .
import { JsBoxlite, BoxliteRestOptions, ApiKeyCredential } from '@boxlite-ai/boxlite';
const rt = JsBoxlite.rest(new BoxliteRestOptions({
url: 'https://api.boxlite.ai',
credential: new ApiKeyCredential('blk_live_…'),
pathPrefix: 'acme', // → requests hit /v1/acme/boxes
}));
何时 pathPrefix 未设置, 客户端将建立 URL 而不包含
部分( c)/v1/boxes/…)——单租户的犬形
部署人员,如当地 boxlite serve 参考服务器.
CLI 抓获 Principal.path_prefix 登录并缓存它
在活动剖面图下,因此 boxlite 命令路径
正确的没有额外的旗帜.
运行时登记选项
import { JsBoxlite } from 'boxlite';
const runtime = new JsBoxlite({
imageRegistries: [
{
host: 'registry.example.com',
auth: { username: 'user', password: 'password' },
},
{
host: 'registry.local:5000',
transport: 'http',
search: true,
},
],
});
简单框
命令执行的基本容器 .
import { SimpleBox } from 'boxlite';
const box = new SimpleBox({
image: 'python:slim',
memoryMib: 512, // Memory limit in MiB
cpus: 2, // Number of CPU cores
name: 'my-box', // Optional name
autoRemove: true, // Auto-remove on stop (default: true)
workingDir: '/app',
network: {
outbound: {
mode: 'enabled',
allowNet: ['api.openai.com'],
},
inbound: {
mode: 'disabled',
},
},
// The pre-split shape `network: { mode, allowNet }` still works and
// configures the outbound direction. Passing it together with `outbound`
// is rejected.
advanced: {
capabilities: {
add: ['NET_ADMIN'],
drop: ['NET_RAW'],
},
},
env: { FOO: 'bar' },
volumes: [
// A host bind (local runtimes only)...
{ hostPath: '/tmp/data', guestPath: '/data', readOnly: false },
// ...or a managed volume, by id or by name (REST runtimes).
{ managedVolume: 'my-data', guestPath: '/cache' }
],
ports: [
{ hostPort: 8080, guestPort: 80 }
],
secrets: [
{
name: 'openai',
value: process.env.OPENAI_API_KEY!,
hosts: ['api.openai.com'],
}
]
});
// Execute command
const result = await box.exec('ls', '-la', '/');
console.log(result.exitCode, result.stdout, result.stderr);
// Execute with options (cwd, user, timeout)
const pwdResult = await box.exec('pwd', [], undefined, {
cwd: '/tmp',
user: 'nobody',
timeoutSecs: 30,
});
console.log(pwdResult.stdout); // "/tmp\n"
// Get box info
console.log(box.id); // ULID
console.log(box.name); // Optional name
const info = await box.info(); // Metadata
// null means unknown to this handle; [] means no active publications.
console.log(info.network?.publishedPorts);
// Local info reads do not query the live network backend; REST info performs a GET.
const refreshed = await runtime.getInfo(box.id);
console.log(refreshed?.network?.publishedPorts);
// Cleanup
await box.stop();
info(), (中文(简体) ), getInfo(),以及 listInfo() 曝光 privileged,客机模式已保存
在创作。 地方元数据报告 true 或者说 false; 省略 REST 服务器
字段生成 undefined。 。 。 .
来宾 SSH 控制
JsBox 财务报告和审定财务报表 SimpleBox 曝光 box.ssh 配置、观察和禁用
嘉宾SSH听众.
import { readFile } from 'node:fs/promises';
const status = await box.ssh.configure({
listenAddress: '0.0.0.0:2222',
hostPrivateKey: await readFile('host_key', 'utf8'), // OpenSSH private key
accounts: [
{
login: 'alice',
authorizedKeys: [await readFile('alice.pub', 'utf8')],
// Certificate auth instead of authorizedKeys:
// ca: { publicKey: caPublicKey, principal: 'alice' },
},
],
});
// { enabled: true, generation: 1n, listenAddress, hostPublicKey,
// hostKeyFingerprint } — generation is a bigint (full u64).
await box.ssh.status();
await box.ssh.disable();
await box.ssh.enable(); // reuse saved configuration; requires a running box
见 节点.js SSH 参考 用于配置类型、返回值和出错.
运行时图像管理
runtime.images 保存运行时可启动的图像: 本地缓存
嵌入运行时间, 服务器的目录 JsBoxlite.rest(...)。同样的
代码对任意一种; pull 仅本地( REST 运行时间拉动当
框)和 usage, (中文(简体) ), createAlias 财务报告和审定财务报表 deleteAlias 仅是REST.
import { JsBoxlite } from "boxlite";
const runtime = JsBoxlite.withDefaultConfig();
const images = await runtime.images.list();
for (const image of images) {
console.log(image.repository, image.tag, image.id);
}
const detail = await runtime.images.get("docker.io/library/alpine");
console.log(detail.aliases, detail.versions.map((version) => version.digest));
await runtime.images.remove("docker.io/library/alpine");
pull 提前填补本地缓存。 REST 运行时间拒绝作为
不支持, 因为创建框会拉动图像 :
const pulled = await runtime.images.pull("alpine:latest");
console.log(pulled.reference, pulled.configDigest, pulled.layerCount);
见 节点参考 每个运行时间的每种方法.
私人登记登录
打开 JsBoxlite.rest(...), (中文(简体) ), runtime.images.registries 管理服务器的登录
绘制私人图像。 密码升起一次,再也没有回回.
本地运行时间抛出 unsupported: 通过 imageRegistries 备选案文
换句话说.
const login = await runtime.images.registries.create({
registryHost: "ghcr.io",
repositoryPrefix: "acme/", // omit for the whole registry
username: "acme-bot",
password: process.env.GHCR_TOKEN!,
});
const box = await runtime.create({ image: "ghcr.io/acme/private-app:1" });
// ...
await runtime.images.registries.remove(login.id); // refused while a box pulls through it
见 节点参考。 。 。 .
活期执行库存
await box.executions().list() 当地人提供 JsBox 财务报告和审定财务报表 SimpleBox。 。 。 .
它回来了 ExecutionInfo[] 从嘉宾的现场盘点,包括
主要进程: executionId (嘉宾身份), argv, (中文(简体) ), startedAt
(一分九秒), tty,以及 isMainSession。完成的进程消失;此
不是执行历史。 列表不附加或消耗输出, 永远不会
靴子一个停止的盒子。 停止/ 未启动的本地框返回空列表; a
暂停框返回无效状态错误。 未创建 SimpleBox (单位:千美元)
返回空列表而不创建其框.
使用 await box.executions().get(executionId) 仅限控制访问,而
另一个客户端拥有输出,或 await box.executions().attach(executionId, false)
以恢复溪流,而无需 stdin。 两者均可在本地 JsBox 财务报告和审定财务报表
SimpleBox,永远不要启动盒子,然后返回一个 JsExecution 支助 kill(), (中文(简体) ),
signal(),以及 wait()。只允许一个输出读取器.
for (const execution of await box.executions().list()) {
console.log(execution.executionId, execution.argv, execution.isMainSession);
}
代码框
Python代码执行沙盒.
import { CodeBox } from 'boxlite';
const codebox = new CodeBox({
image: 'python:slim', // default
memoryMib: 512,
cpus: 1
});
try {
// Run Python code
const result = await codebox.run(`
import math
print(f"Pi is approximately {math.pi}")
`);
console.log(result); // Pi is approximately 3.141592653589793
// Install packages
await codebox.installPackage('requests');
await codebox.installPackages('numpy', 'pandas');
// Use installed packages
const result2 = await codebox.run(`
import requests
response = requests.get('https://api.github.com/zen')
print(response.text)
`);
console.log(result2);
} finally {
await codebox.stop();
}
浏览器框
有远程调试的浏览器自动化 .
import { BrowserBox } from 'boxlite';
const browser = new BrowserBox({
browser: 'chromium', // 'chromium', 'firefox', or 'webkit'
memoryMib: 2048,
cpus: 2
});
try {
await browser.start();
// Get CDP endpoint
const endpoint = browser.endpoint();
console.log(endpoint); // http://localhost:9222
// Connect with Puppeteer
import puppeteer from 'puppeteer-core';
const browserInstance = await puppeteer.connect({ browserURL: endpoint });
const page = await browserInstance.newPage();
await page.goto('https://example.com');
const title = await page.title();
console.log(title);
await page.close();
} finally {
await browser.stop();
}
计算机盒
具有网页访问功能的桌面自动化.
import { ComputerBox } from 'boxlite';
const desktop = new ComputerBox({
cpus: 2,
memoryMib: 2048,
guiHttpPort: 3000, // default
guiHttpsPort: 3001 // default (self-signed cert)
});
try {
// Wait for desktop to be ready
await desktop.waitUntilReady(60);
// Mouse automation
await desktop.mouseMove(100, 200);
await desktop.leftClick();
await desktop.doubleClick();
await desktop.rightClick();
await desktop.leftClickDrag(100, 100, 200, 200);
const [x, y] = await desktop.cursorPosition();
console.log(`Cursor at: ${x}, ${y}`);
// Keyboard automation
await desktop.type('Hello, World!');
await desktop.key('Return');
await desktop.key('ctrl+c');
// Screenshot
const screenshot = await desktop.screenshot();
console.log(`${screenshot.width}x${screenshot.height} ${screenshot.format}`);
// screenshot.data contains base64-encoded PNG
// Scroll
await desktop.scroll(500, 300, 'down', 5);
// Get screen size
const [width, height] = await desktop.getScreenSize();
console.log(`Screen: ${width}x${height}`);
// Access desktop via browser:
// HTTP: http://localhost:3000
// HTTPS: https://localhost:3001 (self-signed certificate)
} finally {
await desktop.stop();
}
交互式框
与 PTY 交互终端会话.
import { InteractiveBox } from 'boxlite';
const box = new InteractiveBox({
image: 'alpine:latest',
shell: '/bin/sh',
tty: true, // Auto-detected if undefined
memoryMib: 512,
cpus: 1
});
try {
await box.start();
await box.wait(); // Blocks until shell exits
} finally {
await box.stop();
}
实例
见 ././实例/节点/ 完整示例目录 :
# If installed via npm
npm install @boxlite-ai/boxlite
node simplebox.js
# If working from source
cd ../../sdks/node
npm install && npm run build
npm link
cd ../../examples/node
npm link @boxlite-ai/boxlite
node simplebox.js
处理错误
import { SimpleBox, ExecError, TimeoutError, ParseError } from 'boxlite';
try {
const box = new SimpleBox({ image: 'alpine:latest' });
await box.exec('false'); // Exit code 1
} catch (err) {
if (err instanceof ExecError) {
console.error(`Command failed: ${err.command}`);
console.error(`Exit code: ${err.exitCode}`);
console.error(`Stderr: ${err.stderr}`);
}
}
运行时间本身的失败 包含一个代码 errorCode(err)
返回,例如 not_found 或者说 invalid_state这是 undefined 用于任何
其他错误。 见 节点参考。 。 。 .
来源建筑
# Clone repository
git clone https://github.com/boxlite-ai/boxlite.git
cd boxlite/sdks/node
# Initialize submodules (critical!)
git submodule update --init --recursive
# Install dependencies
npm install
# Build (Rust + TypeScript)
npm run build
# Link to examples
npm link
cd ../../examples/node
npm link @boxlite-ai/boxlite
# Run examples
node simplebox.js
类型脚本支持
全部类型脚本支持包括:
import {
SimpleBox, CodeBox, BrowserBox, ComputerBox, InteractiveBox,
type SimpleBoxOptions,
type CodeBoxOptions,
type BrowserBoxOptions,
type ComputerBoxOptions,
type InteractiveBoxOptions,
type Secret,
type ExecResult,
type Screenshot,
type BrowserType
} from 'boxlite';
平台要求
马科斯
- 苹果硅 (ARM64)
- macOS 12+(蒙特雷或以后)
- Hypervisor.framework (内建) (中文(简体) )
链接
- x86 64或ARM64 导弹
- KVM 已启用( O)
/dev/kvm可访问) - 用户在
kvm组 :sudo usermod -aG kvm $USER # Logout/login required
建筑
SDK使用双层架构:
-
第1层( Rust): 绑定本地 BoxLite 运行时的 supi- rs
- 直接映射到 Rust
boxlite条框 - 通过Async操作
env.spawn()(无阻塞) - 通过同步执行器进行流程处理
- 直接映射到 Rust
-
第2层( TypeScript): 方便包装
- 专用框类(CodeBox,浏览器Box等)
- 错误等级
- 输出收藏助手
- 类型脚本类型定义
业绩
- 启动时间: < 100ms
- 间接对 Python SDK: < 5%
- 并行框:受系统资源限制
- 内存足迹: ~50-100MB 每盒(取决于图像)
解决问题
找不到 BoxLite 本地扩展名
- 运行
npm run build来编译 Rust 绑定
"没有找到影像"
- 首次使用的 BoxLite 自动推出 OCI 图像
- 确保互联网连接
"拒绝"(Linux)
- 检查 KVM 访问 :
ls -l /dev/kvm - 添加用户到 kvm 组 :
sudo usermod -aG kvm $USER
"不支持的引擎"
- 只有苹果硅Macs支持(不是英特尔)
- 视窗用户:使用带有Linux要求的WSL2
捐款
见 ././ 捐款 发展准则.
代理绑定测试
从寄存器根运行
make test:integration:node FILTER='agent namespace'。本地的 Box 获取器测试
从回转的 REST 服务器获取一个手柄,并检查命名空间访问,而不包含
启动 VM 或发送代理请求。 单独测试拒绝纯对象和
在代理操作运行前只能使用原型方法接收器.
这些接收器测试练习了凝固汽油筒 调回未包装。 他们不锻炼
生成 FromNapiRef 财务报告和审定财务报表 FromNapiMutRef 由 CodeQL 标记的转换,
因此,通过它们并不能证明这些指针警告是虚假的阳性.
转换在锁定中生成
美洲狮后端。 。 。 .
许可证
Apache 2. 0 - 见 ././LICENSE
相关项目
- Python SDK 键盘 - Python绑定物(Python 3.10+)
- C SDK 软件 - CFFI捆绑(早期)
- 核心运行时间 - 粗略运行时间
支助
由 BoxLite 实验室制作
服务隧道
使用内置地址 node:net 准备服务隧道:
import { SocketAddress } from "node:net";
const tunnel = await box.network.tunnel(
new SocketAddress({ address: "127.0.0.1", port: 3000 }),
{ isPublic: false },
);
选项默认为公共;私人隧道需要云运行时间. IPv6目标
使用情况 new SocketAddress({ address: "::1", family: "ipv6", port: 3000 })。 。 。 .
目标必须有一个非零端口,一个回转或来宾IP,以及零流标签.
港口和旧的 { type: "tcp", ... } 目标被拒绝。 无效的参数
类型可以在本地网络控件上同步投放。 TCP/Unix 听器
形状仍然可用 tunnel.forward(listen)。 。 。 .
见 私人隧道。 。 。 .