@decocms/sandbox-controller

中文文档
0.19.0发布于 2026/11/11MITTypeScriptES Module构建来源已验证近 30 天下载 4935

运行工作室的代理沙盒 在Kubernetes, 并服务于远程工作室.

中文使用文档
文档目录11 节
  1. 概览
  2. 责任
  3. 使用量
  4. 建筑
  5. 租户暖水池
  6. 全权证书
  7. 存储
  8. 看着
  9. 发展
  10. 边界
  11. 相关文件

@ decocms/ sandbox- 控制器

运行工作室代理沙盒在Kubernetes上 服务于工作室外 服务于工作室 作为远程供应商.

属性数值
工作空间@decocms/sandbox-controller (单位:千美元)packages/sandbox-controller(中文(简体) )
仁爱公共图书馆,从 @decocms/sandbox
运行时间阿宝
分发公共 npm 软件包

概览

沙盒控制器是一个库,不是服务. 一个主机进程—— deco's 分组, decocms/control-plane - 依赖它,建立一个 AgentSandboxProvider 并服务于沙盒 API. 录音室的 RemoteSandboxProvider (单位:千美元)@decocms/sandbox/provider/remote(电话) 当API STUDIO_SANDBOX_CONTROL_PLANE_URL 已设定; 没有它, Studio 运行 同一供应商在进程中.

软件包再导出代码 @decocms/sandbox 财务报告和审定财务报表 @decocms/shared, (中文(简体) ), 秘密地把它捆入一个有申报的模块.

责任

  • 导出 AgentSandboxProvider,其选项和状态存储类型,以及 kubeConfigForServer,用于本地代理的无证书的 kubeconfig, 已建 和软件包的客户端.
  • 导出 migrateSandboxControllerSchema,用于创建和升级 图书馆自己的 sandbox_controller Postgres schema, 以及里面的商店: postgresRunnerStateStore页:1 RunnerStateStore (数量) scope 保留多个 在一个数据库中将主机或环境的行和锁分开),以及 postgresTenantPoolStore每个沙盒组的租户暖水池 tenantPoolReader,用于提供者的缓存列表 tenantPools。 。 。 .
  • 导出租户池模型 : TenantPool 财务报告和审定财务报表 TenantPoolRepo他们 校验符( e)tenantPoolSchema, (中文(简体) ), tenantPoolFieldsSchema, (中文(简体) ), tenantPoolRepoSchema, (中文(简体) ), normalizeRepoUrl,以及 renderTenantPoolWarmPools,它建立一个游泳池 SandboxWarmPool 对象供主机应用.
  • 导出 FreestyleSandboxProvider (散装箱作为 Freestyle VM)和 SandboxProviderRouter服务于库伯内兹和弗里斯泰特 提供者; 见 packages/sandbox。 。 。 .
  • 将电线合同导出 sandbox-api: 工具名称和计划,以及 监视路线.
  • 导出主机助手 : sandboxTools (无框架工具定义), sandboxWatchResponse (称为SSE阶段), PushedCredentials (单位:千美元) 证书工作室推倒的记忆存储)和 pushedCredentialOptions (提供商的薄荷钩 在商店.

使用量

import {
  AgentSandboxProvider,
  kubeConfigForServer,
  migrateSandboxControllerSchema,
  postgresRunnerStateStore,
  postgresTenantPoolStore,
  PushedCredentials,
  pushedCredentialOptions,
  renderTenantPoolWarmPools,
  sandboxTools,
  sandboxWatchResponse,
  tenantPoolReader,
} from "@decocms/sandbox-controller";

// At boot, before any store serves a call. Each store opens its own pool.
await migrateSandboxControllerSchema({ url: databaseUrl });
const stateStore = postgresRunnerStateStore({ url: databaseUrl });
const poolStore = postgresTenantPoolStore({ url: databaseUrl });
// The host's admin surface writes pools and their repo allocations.
await poolStore.upsertPool("sandbox-cluster-1", {
  name: "acme",
  tenant: orgId,
  size: 4,
});
const acme = await poolStore.setRepos("sandbox-cluster-1", "acme", [
  { repoUrl: "https://github.com/acme/site", replicas: 2 },
]);
// The host applies these; the provider only binds and warms their pods.
const warmPools = renderTenantPoolWarmPools(acme!, {
  templateName: "studio-sandbox-prod",
});
const pools = tenantPoolReader(poolStore, "sandbox-cluster-1");
await pools.start();

// Memory only: a restart forgets it until Studio's next push.
const credentials = new PushedCredentials();

const provider = new AgentSandboxProvider({
  // The host's local proxy to the cluster; it authenticates on its own.
  kubeConfig: kubeConfigForServer("http://127.0.0.1:7777"),
  // Reach daemons the host's way instead of an apiserver port-forward.
  forwardPort: (pod, port) => openDaemonForward(pod, port),
  stateStore,
  // Warm-pool mode; tenant pools need it.
  sentinelToken,
  // Read on every ensure, push and reconcile tick: a synchronous snapshot.
  tenantPools: pools.current,
  // Mint hooks that read the store, and `persistCredentials: false`.
  ...pushedCredentialOptions(credentials),
});

// Wrap each definition in the host's tool type, behind the host's auth.
const tools = sandboxTools(() => provider, credentials);

// GET /api/sandbox/watch?handle=… behind the same auth.
const watch = (req: Request, handle: string) =>
  sandboxWatchResponse(provider, handle, req.signal);

建筑

Studio ──MCP tools + SSE watch──▶ host (this library) ──▶ Kubernetes
Studio ──────── daemon and preview traffic ────────────▶ sandbox pod

主机回答沙盒守护进程在哪里, 哪个持卡人打开它; Studio 拨打守护进程本身( n)daemonAddress: "service" 解答分组 服务 URL. 控制平面没有集群证书:其库贝和 守护进程呼叫是沙盒操作 它的集群数据飞机代理运行 (单位:千美元)decocms/operator internal/agent/ops.go) (中文(简体) ).

租户暖水池

一个租户池是留给一个租户的温室容量: size 已建舱 从游泳池 image。租户是一个不透明的钥匙;供货商比较它 与索赔的租户密钥,即索赔用户的Org id. 重置为 顶部的可选分配 : { repoUrl, branch, workload, replicas } 带 replicas 并不断复制、安装和复制 运行 Repo 的 Dev 服务器 。 分配的复制品最多加到 size其余的都是空白的温室, 复制在捆绑上像通用的 游泳池的。 游泳池的吗. repoUrl 是一个无证书的 https 克隆 URL,已正常存储 : 小写主机, 没有用户信息, 没有线索 .git 或者说 /。 。 。 .

操作员绑定任何温室 SandboxWarmPool 索赔名称,以及 守护进程拒绝将一个被克隆的吊舱移动到另一个 repo, 因此每次分配 这是它自己的 SandboxWarmPool。 。 。 . renderTenantPoolWarmPools(pool, { templateName }) 返回每个分配符中的一个,命名 <pool>-<8 hex of repoUrl#branch>,和一个空白的,命名 <pool> 与 剩下的复制品,即使0点也做成 这样就应用了收缩器 他们都用 页:1 -medium 游泳池图像模板, 即一个有约束要求的模板 名称。 主机应用并删除这些对象; 库从来不写 他们.

一项索赔按其顺序对下列事项具有约束力: repo,在索赔的分行(如果有),其他的分行;其租户的空白 舱; 通用池. 只有一个池子,它的图像是要求的图像 合格,没有空白复制品的游泳池被跳过。 调和器暖和 仅分配吊舱,每波德刷新和故障后退;空白吊舱是 由约束它的权利要求所配置。 供应商把池子当作 tenantPools,列表或函数,并在每次使用时读取函数,所以 更改在下一个保证和对齐时生效,而不重新启动. 调和器会忘记一个被删除的分配器的吊舱,并且会使其深度计为零. markTenantPoolsDirty(repoUrl, ref) 刷新该 repo 上的配置 和树枝相接.

全权证书

主持人从不给工作室打电话. 只有工作室才能做薄荷(clone sorders, org-fs API 键) 到达它有两个方法: SANDBOX_ENSURE 带着他们 保持有效多久,每10分钟工作室打电话 SANDBOX_LIST (租户和回购户,以及每个游泳池的名称、租户、形象和回购分配, (没有全权证书),然后 SANDBOX_CREDENTIALS_PUSH工作室处理 列表为不信任 : 它只对租户使用薄荷, 而用户是其中的一员 ,并且仅用于连接或寄存器属于 那个鸟人 对于一个游泳池,它只从它自己的寄存器记录中取出薄荷 org 由该游泳池的租户命名,其克隆 URL 与所列 URL 相匹配 推一无相. 集合证书以下列方式送达: poolCloneUrls键入 租户和收回的URL,以及 pushedCredentialOptions 把他们交给 分配舱. STUDIO_SANDBOX_TENANT_POOLS 仅配置池 Studio的流程中供应商;带有控制平面,Studio忽略了它. 商店保存每个条目的过期, 从未替换一个寿命更长的条目 更短的,当一个入口的生命减少时, 以一无所有的方式回答再薄荷 离跑者要求的远 与 persistCredentials: false 坚持 状态不保留克隆令牌、子模块令牌或org-fs配置;恢复需要 他们从商店。 在主机重启后, 沙盒在下次启动前恢复 推力只有在10分钟后才能有证书.

存储

州立商店每个沙盒保留一行 sandbox_controller.runner_state, (中文(简体) ), 与 Studio 的同名语义库在进程商店. withLock 序列化 用交易范围为复制品提供一个沙盒 由用户和项目管理员键入的咨询锁定; 等待时间超过 90秒( 秒数 )lockWaitMs)获得可重试的"沙箱咨询锁"繁忙出错. 每个锁持有人都保持连接 整个供给,所以商店 打开自己的集合 maxConnections (违约4)而不是共享 东道方; close() 结束它。 主机运行 migrateSandboxControllerSchema 在靴子时; 店里从不独自迁移 迁移是天能的 并且持有 咨询锁,所以每个复制品可以同时运行. 应用版本为: 记录 sandbox_controller.migrations。 。 。 . state 嵌入短寿命 证书;永远不要登录.

游泳池店每游泳池一排 sandbox_controller.tenant_pools, (中文(简体) ), 单个的集群和名称,所以一个数据库可以服务于多个沙盒 组,每个分配单位一行 sandbox_controller.tenant_pool_repos, (中文(简体) ), 按池、 repo URL 和分支并与其池一起删除. upsertPool(cluster, pool) 用 tenantPoolFieldsSchema 创建 或更新该名称的池,保留其原样,但抛出 TenantPoolConflictError 当这个名字属于另一个租户时: 它的温暖的舱 保持租户的退房. setRepos(cluster, name, repos) 用 tenantPoolRepoSchema 并替换一个池的所有分配 ,当没有这样的池时,则无效回答。 都锁上泳池一行 掷出 TenantPoolCapacityError 而不是让分配额超过 尺寸. deletePool 回答是否删除了游泳池; list(cluster) 返回时 组群的池与它们的回放. tenantPoolReader(store, cluster) 装入集群的池 start()打开 refresh() 和每个 refreshMs (默认为30秒); current() 同步回答上次加载的列表。 保存失败的负载 最后的列表, 以及一个在更新的列表被丢弃后完成的负载。 写作 从另一个复制到读者的下个勾点; 作者自己的 进程可以调用 refresh() 马上.

看着

监视路由中每写一个 SSE 保留评论 SANDBOX_WATCH_KEEPALIVE_MS。工作室读取表作为主持人的标志 生活:它重新连接了一条流水, 放弃了只给养电话 在宿主沉默了4个守口如瓶后.

发展

bun run --cwd=packages/sandbox-controller build   # dist/index.js + index.d.ts
bun run --cwd=packages/sandbox-controller pack    # dist/sandbox-controller.tgz
bun test packages/sandbox/server/provider/remote.test.ts
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres \
  bun test packages/sandbox/server/provider/postgres-state-store.integration.test.ts

本地主机可以依赖包装的柏油球 bun add @decocms/sandbox-controller@file:<path>/dist/sandbox-controller.tgz。 。 。 .

边界

  • 主机拥有授权:工具没有自己的授权.
  • 默认 daemonAddress: "forward",守护进程地址是 主机本身 127.0.0.1 前进,只能从同一机器上到达.
  • 来源于 packages/sandbox换个位置 改为a 被捆绑的源头在发布时碰倒了这个软件包的版本,由它发布.
  • zod, (中文(简体) ), @opentelemetry/api 财务报告和审定财务报表 postgres 是同级依赖关系: 主办单位 zod 解析导出的计划, 提供者的测量选项是 @opentelemetry/api 类型,并运行在主机上 postgres。 。 。 .

版本与发布记录

@decocms/sandbox-controller 共发布 50 个版本,首次发布于 2026/09/29;过去 12 个月发布了 50 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.19.0latest2026/11/111 天前
0.18.12026/11/111 天前
0.18.02026/11/111 天前
0.17.02026/11/111 天前
0.16.82026/11/101 天前
0.16.62026/11/102 天前

关于 @decocms/sandbox-controller 的常见问题

@decocms/sandbox-controller 是什么?

运行工作室的代理沙盒 在Kubernetes, 并服务于远程工作室.

如何安装 @decocms/sandbox-controller?

在项目目录运行 npm install @decocms/sandbox-controller,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:zod(^4.3.6)、postgres(^3.4.5)、@opentelemetry/api(^1.9.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@decocms/sandbox-controller 支持 TypeScript 吗?

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

@decocms/sandbox-controller 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@decocms/sandbox-controller 可以商用吗?

@decocms/sandbox-controller 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@decocms/sandbox-controller 的下载量有多少?

根据 npm 官方下载统计,@decocms/sandbox-controller 在 2026/10/12 – 2026/11/10 这 30 天内被下载 4,935 次,日均约 165 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@decocms/sandbox-controller 还在维护吗?

最新版本 0.19.0 发布于 2026/11/11(1 天前);至今共发布 50 个版本,其中过去 12 个月发布了 50 个;首次发布于 2026/09/29。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。