# @easybits\.cloud/sdk 中文文档

规范地址：https://npmcn.com/package/%40easybits.cloud/sdk/

版本：0\.44\.0
npm 元数据更新时间：2026-10-22T23:37:28.402Z
中文译文更新时间：2026-11-13T05:18:32.314Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40easybits.cloud/sdk
原文对照：https://npmcn.com/package/%40easybits.cloud/sdk/?lang=original
项目主页：https://github.com/blissito/easybits#readme
源码仓库：https://github.com/blissito/easybits

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：555 kB，20 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：0 个
- 首次发布：2026-02-25T18:24:15.172Z
- 最新版本发布：2026-10-22T23:37:28.180Z
- 近 30 天下载量：2217（2026-10-13 至 2026-11-11，npm 官方下载统计）
- 已发布版本数：59（近 12 个月 59 个）

## 中文简介

为 AI 代理机-沙盒、网络、文件、 SQL 数据库、文档和应用程序托管的 EasyBits 云输入了 HTTP 客户端

## 安装

```sh
npm install @easybits.cloud/sdk
```

也可以使用：`pnpm add @easybits.cloud/sdk`、`yarn add @easybits.cloud/sdk`、`bun add @easybits.cloud/sdk`

## README

# @ easybits. cloud/ sdk

用于AI代理的EasyBits云的被打入HTTP客户端——沙盒,网络,文件,SQL数据库,文档和应用程序托管.

EasyBits是云AI代理已经知道如何使用:在被隔离的"鞭炮"微VM中运行代码,搜索并读取网络,存储并服务文件,查询一个SQL数据库,生成文档并部署应用——通过SDK,MCP和REST API. 价格为MXN.

## 安装

```bash
npm install @easybits.cloud/sdk
```

## 快速启动

```ts
import { EasybitsClient } from "@easybits.cloud/sdk";

const eb = new EasybitsClient({ apiKey: "eb_sk_live_..." });

// Upload a file
const { file, putUrl } = await eb.uploadFile({
  fileName: "photo.jpg",
  contentType: "image/jpeg",
  size: 1024000,
});

// Upload bytes to the presigned URL
await fetch(putUrl, { method: "PUT", body: fileBuffer });

// Confirm upload
await eb.updateFile(file.id, { status: "DONE" });
```

## 认证

从中获取您的 API 密钥 [开发者 Dashboard](https://www.easybits.cloud/dash/developer)。 。 。 .

```ts
const eb = new EasybitsClient({ apiKey: process.env.EASYBITS_API_KEY! });
```

或使用自动分辨率从 `~/.easybitsrc` 或 env vars : (中文(简体) )

```ts
import { createClientFromEnv } from "@easybits.cloud/sdk";
const eb = await createClientFromEnv();
```

## 方法

### 文件

| 方法 | 说明 |
| --- | --- |
| `listFiles(params?)` | 列出您的文件( 已插入) |
| `getFile(fileId)` | 获取文件细节 + 下载 URL |
| `uploadFile(params)` | 创建文件记录 + 获得上传 URL |
| `updateFile(fileId, params)` | 更新名称、访问、元数据或状态 |
| `deleteFile(fileId)` | 软删除文件( 保留了 7天) |
| `restoreFile(fileId)` | 恢复软删除文件 |
| `listDeletedFiles(params?)` | 列出删除的文件, 日期为清除日期 |
| `searchFiles(query)` | AI 驱动的自然语言文件搜索 |
| `bulkUploadFiles(items)` | 创建最多 20 个文件记录 + 上传 URL |
| `bulkDeleteFiles(fileIds)` | 软删除最多100个文件 |
| `duplicateFile(fileId, name?)` | 复制已存在的文件( 新存储对象) |
| `listPermissions(fileId)` | 列出文件共享权限 |

### 图像

| 方法 | 说明 |
| --- | --- |
| `optimizeImage(params)` | 转换为 WebP/ AVIF( 创建新文件) |
| `transformImage(params)` | 调整大小、裁剪、旋转、翻转、灰度 |

### 共享

| 方法 | 说明 |
| --- | --- |
| `shareFile(params)` | 通过电子邮件与另一个用户共享文件 |
| `generateShareToken(fileId, expiresIn?)` | 生成临时下载 URL |
| `listShareTokens(params?)` | 列出共享令牌( 已贴上) |

### 网络呼号

| 方法 | 说明 |
| --- | --- |
| `listWebhooks()` | 列出您已配置的网点 |
| `createWebhook(params)` | 创建 Webhook( 返回秘密, 一次显示) |
| `getWebhook(webhookId)` | 获取网络浏览细节 |
| `updateWebhook(webhookId, params)` | 更新 URL、事件或状态 |
| `deleteWebhook(webhookId)` | 永久删除网签 |

### 克鲁斯

您账户中已排定的任务: 调用一个公开的 https URL( 选择以一个金库密钥作为标题) 或发送一个转机给您的车队代理 。 最多5分钟; IANA 时区( 默认) `America/Mexico_City`);每个计划的限制(Byte 3,Mega 20,Tera 100).

| 方法 | 说明 |
| --- | --- |
| `listCrons({ includeAgents? })` | 你的膝盖`includeAgents` 增加你的特工作为转弯目标) |
| `createCron(params)` | `{ name, cron, timezone?, enabled?, action }` |
| `getCron(id)` 编号 : `updateCron(id, params)` 编号 : `deleteCron(id)` | `updateCron(id, { enabled: false })` 暂停 |
| `runCron(id)` | 现在在背景中运行 |
| `listCronRuns(id, { limit? })` | 最新跑道,最新第一 |

```ts
await eb.createCron({
  name: "Study reminder",
  cron: "30 8 * * *",
  action: { type: "http", url: "https://www.ghosty.studio/api/v2/me/push", method: "POST", body: { title: "Study time" }, secretName: "GHOSTY_PUSH_TOKEN" },
});
```

### 秘密(账户金库)

| 方法 | 说明 |
| --- | --- |
| `listSecrets()` | 在您的金库中的名字( C)`{ items:[{id,name,createdAt,lastUsedAt}] }`; 从未返回值 |
| `setSecret(name, value)` | 存储或替换一个秘密( E)`[A-Z_][A-Z0-9_]*`; 名称为 `$secret:NAME` |
| `deleteSecret(name)` | 删除它;无论它停止解决任何引用 |

### 网站

| 方法 | 说明 |
| --- | --- |
| `listSites()` | 列出您的站点建设站点(/dash/sitios):静态和网络应用程序,并带有引擎和URL |
| `listWebsites()` | 列出您的静态网站 |
| `createWebsite(name, { slug? })` | 创建新网站( 可选自定义 swit) |
| `getWebsite(websiteId)` | 获取网站细节 |
| `updateWebsite(websiteId, params)` | 更新网站名称, swit或状态(旧 swit 301s to the new switter) |
| `deleteWebsite(websiteId)` | 删除网站及其文件 |

### 工作空间

指定位置, 限定配额的文件容器 。 每个租户创建一个, 薄荷一个工作空间范围密钥, 而该密钥只能触摸它自己的工作空间的文件.

| 方法 | 说明 |
| --- | --- |
| `listWorkspaces(params?)` | 列出工作空间( cursor pagized) |
| `createWorkspace({ name, slug?, quotaBytes? })` | 创建工作空间 |
| `getWorkspace(workspaceId)` | 获取工作空间细节 |
| `updateWorkspace(workspaceId, params)` | 更新名称/状态/配额 |
| `deleteWorkspace(workspaceId)` | 删除工作空间及其文件 |
| `getWorkspaceUsage(workspaceId)` | 获取 `{ usedBytes, quotaBytes, fileCount }` |
| `createWorkspaceKey(workspaceId, params?)` | Mint 工作空间扫描 API 密钥( 画回一次) |

### 文档

| 方法 | 说明 |
| --- | --- |
| `listDocuments()` | 列出文档 |
| `getDocument(id)` | 获取所有页面的文档 |
| `createDocument(params)` | 创建文档 |
| `updateDocument(id, params)` | 更新文档元数据( 名称、 主题、 颜色) |
| `deleteDocument(id)` | 删除文档 |
| `deployDocument(id)` | 作为现场网站发布 |
| `unpublishDocument(id)` | 撤消文档 |
| `generateDocument(id, params)` | AI-遗传页面(并行,流出) |
| `refineDocument(id, params)` | 外科AI编辑到一页 |
| `regenerateDocumentPage(id, params)` | 重新设计保存内容的页面 |
| `enhanceDocumentPrompt(name, prompt?)` | 自动描述或增强提示 |
| `getDocumentDirections(prompt, opts?)` | 获得4个设计方向(指针、颜色、心情) |

### 账户

| 方法 | 说明 |
| --- | --- |
| `getUsageStats()` | 已使用的存储/限制、文件清点、计划信息 |
| `listProviders()` | 列表存储提供者 |
| `listKeys()` | 列出您的 API 密钥 |

## 网络呼号

轻点 当事件发生时,比特将 POST 请求发送到您的 URL 。 有效载荷由HMAC SHA-256签署.

```ts
// Create a webhook
const webhook = await eb.createWebhook({
  url: "https://your-server.com/webhooks/easybits",
  events: ["file.created", "file.deleted"],
});

// Save the secret — it's only shown once
console.log(webhook.secret); // whsec_...
```

### 活动

| 活动 | 触发 |
| --- | --- |
| `file.created` | 文件已上传或复制 |
| `file.updated` | 文件名称、访问或元数据已更改 |
| `file.deleted` | 文件被软删除 |
| `file.restored` | 从回收站恢复文件 |
| `website.created` | 创建网站 |
| `website.updated` | 网站名称或弹片已更改 |
| `website.deleted` | 网站已删除 |
| `workspace.created` | 创建工作空间 |
| `workspace.deleted` | 工作空间已删除 |

### 验证签名

```ts
import { createHmac } from "crypto";

function verifyWebhook(body: string, signature: string, secret: string): boolean {
  const expected = `sha256=${createHmac("sha256", secret).update(body).digest("hex")}`;
  return signature === expected;
}

// In your webhook handler:
const signature = req.headers["x-easybits-signature"];
const event = req.headers["x-easybits-event"];
const isValid = verifyWebhook(rawBody, signature, webhook.secret);
```

### 有效载荷格式

```json
{
  "event": "file.created",
  "timestamp": "2026-02-26T12:00:00.000Z",
  "data": {
    "id": "abc123",
    "name": "photo.jpg",
    "size": 1024000,
    "contentType": "image/jpeg",
    "access": "private"
  }
}
```

### 自动暂停

Webhooks在连续5次发送失败后自动被暂停. 以 :

```ts
await eb.updateWebhook(webhookId, { status: "ACTIVE" });
```

## 实例

### 批量上传文件

```ts
const { items } = await eb.bulkUploadFiles([
  { fileName: "a.pdf", contentType: "application/pdf", size: 50000 },
  { fileName: "b.png", contentType: "image/png", size: 120000 },
]);

for (const { file, putUrl } of items) {
  await fetch(putUrl, { method: "PUT", body: buffers[file.name] });
  await eb.updateFile(file.id, { status: "DONE" });
}
```

### 检查账户使用情况

```ts
const stats = await eb.getUsageStats();
console.log(`${stats.storage.usedGB}/${stats.storage.maxGB} GB used`);
console.log(`${stats.counts.files} files, ${stats.counts.webhooks} webhooks`);
```

### 复制文件

```ts
const copy = await eb.duplicateFile("abc123", "photo-backup.jpg");
```

## 倾斜

每个被标注的列表返回一个信封: `{ items, nextCursor, hasMore }` (部分) 还包括: `total`) (中文(简体) ). 何时 `hasMore` 实值 `true`,通过 `nextCursor` 恢复为 `cursor` 获取下一页 :

```ts
let cursor: string | undefined;
do {
  const { items, nextCursor, hasMore } = await eb.listFiles({ limit: 50, cursor });
  process(items);
  cursor = nextCursor ?? undefined;
  if (!hasMore) break;
} while (cursor);
```

## 处理错误

所有出错都有一个形状: JSON 躯体 `{ "error": "message" }`,有时与 额外字段类 `code` 或者说 `status`。 。 。 .

```ts
import { EasybitsError } from "@easybits.cloud/sdk";

try {
  await eb.getFile("nonexistent");
} catch (err) {
  if (err instanceof EasybitsError) {
    console.log(err.status); // 404
    console.log(err.body);   // '{"error":"File not found"}'
  }
}
```

## 沙盒

在孤立的鞭炮微VMs中运行代码——用持久执行代码 Jupyter 内核,管理文件,运行背景进程,并曝光端口为 公共 HTTPS URLs. (原始内容存档于2018-09-29).

```ts
import { EasybitsClient } from "@easybits.cloud/sdk";

const eb = new EasybitsClient({ apiKey: process.env.EASYBITS_API_KEY });

// Create a sandbox (waits until it's running)
const sbx = await eb.sandboxes.create({ template: "code-interpreter" });

// Persistent Python kernel — state survives between calls
await sbx.runCell("import pandas as pd; df = pd.read_csv('sales.csv')");
const out = await sbx.runCell("df.groupby('month').total.sum()");
console.log(out.stdout);

// matplotlib charts come back as image/png in results[]
const chart = await sbx.runCell("df.plot(); plt.show()");
const png = chart.results.find((r) => r.type === "image/png")?.data; // base64

// Run a server and get a public URL. Write the command as `exec <program>`:
// the shell is REPLACED by your process instead of staying as its parent, so
// signals and logs go straight to it. (Do NOT try to background something with
// nohup or & inside exec(): that call is synchronous and its shell dies with
// the response, taking the child with it. That is what execBackground is for.)
const { execId } = await sbx.execBackground("exec python3 -m http.server 3000");
const { url } = await sbx.exposePort(3000);
console.log(url); // https://sb-...-3000.sandboxes.easybits.cloud

// Poll it, list them, kill it. bgStatus returns the ACCUMULATED stdout, so
// live logs are just `st.stdout.slice(seen)` — no websockets needed.
const st = await sbx.bgStatus(execId); // { status, exitCode?, stdout, stderr }
const { processes } = await sbx.bgList(); // lost the execId? it is in here
await sbx.bgKill(execId, { graceSeconds: 2 });
// bgKill signals the whole process GROUP (SIGTERM, then SIGKILL after the
// grace), so a dev server's forked children die too instead of surviving and
// holding the port. Killing an already-finished process succeeds and reports
// alreadyExited.

// exposePort is HTTP-only (22/23/25/445/3389 are rejected). For a raw L4 port:
const fwd = await sbx.exposeRawPort(22, "tcp");
console.log(fwd.endpoint); // cname.sandboxes.easybits.cloud:49123 — dial this
// hostPort comes from a pool, differs per box and is released on destroy:
// read it back, never hardcode it. Close it with unexposeRawPort(22, "tcp").
// Only templates that declare the port work; a 403 is permanent, not transient.

// SSH: injects the key, restarts the box sshd and opens 22, in one call.
// The box sshd is fail-closed, so the key has to go in before the port opens.
const ssh = await sbx.enableSsh(["ssh-ed25519 AAAA... me@laptop"]);
console.log(ssh.command); // ssh -p 49002 root@<host of THAT box>
// Key-only, as root. disableSsh() closes the port but does NOT revoke the key.

// PREFER THE TUNNEL over that command. A high port does not survive office
// networks or corporate VPNs, and that failure reaches you as an
// unreproducible "it won't connect". The tunnel rides the same 443 as the web:
//
//   npm i -g @easybits.cloud/cli && easybits login   # or: easybits login - < key.txt
//   easybits ssh-key      # your public key; created once, never leaves the box
//
//   # ~/.ssh/config
//   Host *.ghosty
//     ProxyCommand easybits ssh-proxy %h
//     User root
//
//   ssh my-box.ghosty     # the `name` you gave it at create time
//   ssh sb_abc123.ghosty  # the id works too
//   ssh my-box.ghosty "cd /data/work && ghosty serve --acp"   # remote ACP
//
// enableSsh() is still needed once, to inject the key (the box sshd is
// fail-closed). The tunnel moves opaque bytes and does NOT authenticate: the
// SSH session authenticates end-to-end against the box's sshd, so a bug in the
// tunnel cannot let anyone in. sshTicket() mints the short-lived signed ticket
// the proxy uses — you rarely call it yourself.

// Files
await sbx.files.write("/tmp/data.json", JSON.stringify({ ok: true }));
const { content } = await sbx.files.read("/tmp/data.json");

// Lifecycle
await sbx.extend(600);   // add 10 min to the TTL
await sbx.destroy();
```

### 快照叉( 复制- 写入克隆) (F)

别动a **运行** 框,然后启动 **无子女** 从它 - 每个独立沙盒都有自己的IP。 一次准备环境( 选项 ) 安装、项目设置、快照和叉子并列尝试 N 变体 不重复设置.

```ts
// Base box: install deps once
const base = await eb.sandboxes.create({ template: "node" });
await base.exec("npm i -g cowsay");

// Snapshot the ready state — the box keeps running
const snap = await base.snapshot("deps-ready");

// Fork into 3 children that run in parallel (each inherits the disk)
const kids = await base.fork({ count: 3 });
for (const k of kids) {
  await k.waitUntilReady();
  console.log(k.sandboxId, (await k.exec("cowsay hi")).stdout);
}

// Reuse the snapshot later, without the base box
const more = await eb.sandboxes.forkFromSnapshot(snap.snapshotId, { count: 2 });

// Catalog + cleanup
await eb.sandboxes.snapshots.list();
await eb.sandboxes.snapshots.delete(snap.snapshotId);
```

### 衍生模板( 模板- snapshot)

准备 **一个** 框内(`npm ci`种子,技能,在内容下捕捉一次 键 `(key, hash)`,每个框 创建与该对 **与生俱来 靴子绑好了** ——没有分叉,没有每个孩子的复制;主机只保留磁盘三角洲 (12-22 MB) (中文(简体) ). 测量:捕捉~0.5-1 s,取自衍生模板~0.6 s

-   ~2个靴子. 这就是 `@easybits.cloud/eve-sandbox` 用于夜之夜 `prewarm`。 。 。 .

```ts
const base = await eb.sandboxes.create({ template: "node" });
await base.exec("cd /workspace && npm ci");

// Idempotent per (key, hash): a second call returns reused: true
const dt = await base.templateSnapshot({ key: "agent", hash: "3f9c" }); // { derivedId, reused, sizeBytes }

// Children never inherit the source env (secrets are scrubbed): pass their own
const child = await eb.sandboxes.create({ templateKey: "agent", templateHash: "3f9c", env: { FOO: "bar" } });

await eb.sandboxes.templateSnapshots.get({ key: "agent", hash: "3f9c" }); // 404 DerivedTemplateNotProvisioned → capture first
await eb.sandboxes.templateSnapshots.list();
await eb.sandboxes.templateSnapshots.delete(dt.derivedId);            // 409 DerivedTemplateInUse while children live
```

未使用30天,一个衍生模板会自删除. 如果基准模板是 重温, `create` 答题 `409 DerivedTemplateStale`:又捉来.

### 网络政策(每箱 Egress)

```ts
await sbx.setNetworkPolicy("deny-all");
await sbx.setNetworkPolicy({ allow: { "api.github.com": [], "registry.npmjs.org": [] } }); // no wildcards
await sbx.setNetworkPolicy("allow-all");
```

由主机决定IP( DNS 刷新), 坚持使用框并重新应用 简历. `transform` (头部注射)不支持.

### 睡觉/醒来(静眠)

无 `suspendOnIdle`,这个盒子是 **已销毁** 何时 `timeoutSeconds` (默认) 300 s)发作. 以后要谈的,你先睡吧 挂起的框是一个鞭炮快照,在~1 s 中恢复并保存磁盘和内存.

```ts
// At creation
const sbx = await eb.sandboxes.create({ template: "node", timeoutSeconds: 600, suspendOnIdle: true });

// Or on an existing box (e.g. one you created without it)
await sbx.setIdlePolicy({ suspendOnIdle: true, idleTtlSeconds: 600, hardTtlSeconds: 7 * 24 * 3600 });

await sbx.suspend();   // sleep now; TTL is paused
await sbx.resume();    // wake; the remaining lifetime is restored
```

### 模板

使用 `eb.listTemplates()` 用于有需要的内存的活目录。 类型 : `base` (运行代码), `agent` (已准备好的代理人), `service` (平台框开始于 `service_start`, (中文(简体) ), `internal` (平台创建的员工).

| 模板 | 仁爱 | 说明 |
| --- | --- | --- |
| `ubuntu` | 基础 | 满地取出. 安装软件包,编译,运行服务器. |
| `python` | 基础 | Python 运行时间;每个运行代码是一个新鲜的过程. |
| `node` | 基础 | 节点24+打字,tsx,pnpm,git和python3;每个跑码是一个新鲜的过程. |
| `bun` | 基础 | Bun 运行时间. |
| `dev-box` | 基础 | 清洁工作箱(基特、卷曲、基本建设、节点22);为SSH推荐的工作箱. |
| `code-interpreter` | 基础 | Python + 持久性 Jupyter 内核(sandbox run cell):在细胞间存活的变量和图表. |
| `eve-nitro` | 基础 | 自发托管的夜(Vercel)服务器:节点24,pnpm,前夕CLI 0.65;持久/数据,端口3000. |
| `node-agent` | 代理人 | 节点 + Claude Agent SDK 预烤(代理运行). |
| `claude-code` | 代理人 | Claude探员SDK回路,每笔账单. |
| `goose` | 代理人 | 鹅 (AAIF),与本地非加太公司的编码代理. |
| `ghostyclaw` | 代理人 | 常上"鬼"守护进程(WhatsApp,Slack,Telegram)与多克和admin-api. |
| `ghosty-lite` | 代理人 | 轻量级 Rust ACP 代理, 多供应商; 您的 Easy 位键可以是它的大脑. |
| `open-ghosty` | 代理人 | 开放式模型上的"鬼",SSE网络聊天. |
| `lang-ghosty` | 代理人 | (原始内容存档于2012-10-12). Ghosty on LangChain, SSE web talk. |
| `rust-ghosty` | 代理人 | DeepSeek-First Ghosty (CodeWhale/Rust) 有SSE网络聊天和WhatsApp. |
| `ghosty-gc` | 代理人 | Ghosty for teams (GTeams):线条,文物,合作编辑. |
| `ghosty-chat` | 代理人 | 持续幽灵聊天(Express + SSE). |
| `cagent-ghosty` | 代理人 | Cagent上的幽灵 (Docker),SSE网络聊天. |
| `openclaw` | 代理人 | OpenClaw,总是个人AI. |
| `chat-openai` | 代理人 | 在 OpenAI 上持续快递+SSE 聊天; 使用代理创建 create. |
| `chat-anthropic` | 代理人 | 在 Anthropic 上持续快递+ SSE 聊天; 用代理 创建它 . |
| `ghosty-studio` | 代理人 | Ghosty Studio:一个盒子里面的特工控制平面. |
| `desktop-ghosty` | 代理人 | Linux 有 Ghosty (noVNC) 的桌面. |
| `computer-ghosty` | 代理人 | 用XFCE桌面+公用NoVNC的计算机使用. |
| `computer-ghosty-gemini` | 代理人 | 电脑对双子座的使用. |
| `livekit-svc` | 服务 | 视频呼叫室+HD录音 (Studio). |
| `whisper-svc` | 服务 | 低声STT; 语音框的一部分. |
| `kokoro-svc` | 服务 | kokoro TTS; 语音盒的一部分. |
| `voice-svc` | 服务 | 为舰队配音(STT + TTS; service start ('voice')). |
| `render-svc` | 服务 | PDF/PNG/审计的铬; service start('nder'). |
| `collab-svc` | 服务 | GTeams 协作编辑器 (Yjs). |
| `hyperframes-svc` | 服务 | HyperFrames 视频渲染. |
| `claude-worker` | 内部 | 舰队工人 (克洛德). 由平台创建. |
| `codex-worker` | 内部 | 舰队工人 (Codex). 由平台创建. |
| `gemini-worker` | 内部 | 舰队工人 (格米尼). 由平台创建. |
|  |  |  |

对于没有持续状态的一次性片段,使用 `sbx.runCode(code, { lang })`。 。 。 . 建筑代理人 [夜 间](https://eve.dev/)? 吗? `@easybits.cloud/eve-sandbox` 转弯 这些盒子进入了夜之夜 `SandboxBackend`。 。 。 .

## 舰队特工

弹性舰队特工与麻风工人的对话(WhatsApp, WABA, 页:1 用客户端证书创建/列表/删除认证( 用户 OAuth JWT) 与 `WRITE` 范围); **每一个配置和信件的调用都使用每个代理 `token` 返回时间 `create()`** ——坚持不懈 `{ id, token }` 并重用符号作为 第二次辩论 一个客户端实例可以配置许多代理.

```ts
// Lifecycle — auth = client credential (pass the user JWT as apiKey)
const eb = new EasybitsClient({ apiKey: userJwt });
const { fleetAgent } = await eb.fleet.create({ name: "Tania", systemPrompt: "...", model: "claude-sonnet-5" });
const { id, token } = fleetAgent;              // persist BOTH

// Pick a non-default engine (DeepSeek/Codex/…). Some engines need a provider
// secret — set it right after with setSecret (e.g. DEEPSEEK_API_KEY).
const ds = await eb.fleet.create({ engine: "deepseek", name: "Vendedor", systemPrompt: "..." });
await eb.fleet.setSecret(ds.fleetAgent.id, ds.fleetAgent.token, { name: "DEEPSEEK_API_KEY", value: "sk-..." });
await eb.fleet.list();                          // { pools: [...] }
await eb.fleet.delete(id);

// Read config — auth = per-agent token
const caps = await eb.fleet.getCapabilities(id, token);
caps.agent.model;      // "claude-sonnet-5"
caps.agent.effort;     // "medium"
caps.skills;           // [{ id, name, enabled, ... }]

// Agent-level config
await eb.fleet.setName(id, token, "Tania");
await eb.fleet.setAgentPrompt(id, token, "New base instructions...");
await eb.fleet.setModel(id, token, "claude-opus-4-8");
await eb.fleet.setEffort(id, token, "high");           // low|medium|high|xhigh|max
await eb.fleet.toggleOwnNumber(id, token, true);
await eb.fleet.addMcp(id, token, { name: "stripe", pkg: "@stripe/mcp", requiredSecret: "STRIPE_KEY" });
await eb.fleet.toggleSkill(id, token, { skillId: "abc", on: true });

// Per-channel config (groupId; "*" = the agent's default)
await eb.fleet.setGroupPrompt(id, token, "*", "Extra per-channel instructions");
await eb.fleet.setToolGroup(id, token, "*", { buckets: ["documentos", "db", "db-write"] });
await eb.fleet.setCapLevel(id, token, "*", { cap: "denik", level: "write" });

// Messaging
const { reply } = await eb.fleet.message(id, token, { groupId: "web-123", text: "Hola" });

// WhatsApp (Baileys) connection — auth = client credential (owner), NOT the per-agent token.
// Link a PERSONAL number (never a Business/WABA number). Omit pairingPhone → QR; pass it → code.
await eb.fleet.connect(id);                          // then poll:
const { baileys } = await eb.fleet.connectionState(id);  // { status, qr?, pairingCode?, pairBlockedUntil? }
// status: qr_pending | pairing | connecting | connected | failed | disconnected. Poll ~2.5s.
const { groups } = await eb.fleet.listGroups(id);    // [{ groupId, subject, enabled, isMain }] (on-demand)
await eb.fleet.toggleGroup(id, groups[0].groupId, true);  // answer here
await eb.fleet.setMain(id, groups[0].groupId);       // admin/main channel
await eb.fleet.disconnect(id);
```

`getCapabilities` 返回完整目录 + 当前状态(已建构,容量, 桶头, `bucketTools`,模型,技能,每组配置. 见类型 `FleetCapabilities` 为了形状.

## MCP 一体化

对于 **AI探员**,同样的沙盒作为MCP工具可用(代理调用) 它们本身——不需要代码:

```bash
npx -y @easybits.cloud/mcp
```

## 许可证

麻省理工学院

## 常见问题

### @easybits\.cloud/sdk 是什么？

为 AI 代理机-沙盒、网络、文件、 SQL 数据库、文档和应用程序托管的 EasyBits 云输入了 HTTP 客户端

### 如何安装 @easybits\.cloud/sdk？

在项目目录运行 npm install @easybits\.cloud/sdk，或使用 pnpm add / yarn add / bun add。

### @easybits\.cloud/sdk 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @easybits\.cloud/sdk 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @easybits\.cloud/sdk 可以商用吗？

@easybits\.cloud/sdk 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @easybits\.cloud/sdk 的下载量有多少？

根据 npm 官方下载统计，@easybits\.cloud/sdk 在 2026/10/13 – 2026/11/11 这 30 天内被下载 2,217 次，日均约 74 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @easybits\.cloud/sdk 还在维护吗？

最新版本 0\.44\.0 发布于 2026/10/23（21 天前）；至今共发布 59 个版本，其中过去 12 个月发布了 59 个；首次发布于 2026/02/26。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

