@coda-console/host

中文文档
2.0.1发布于 2026/11/08MITES Module零依赖构建来源已验证近 30 天下载 2257

本机运行器与 Xcode、模拟器的排队名额

原始使用文档

宿主资源

运行器与执行环境

从 2.0.0 起,host 在清单里声明实现 coda/executor@1 与 coda/run@1,把自己这台机器的执行环境发布为一条 coda/executor@1 记录(ID host)。别的机器或 Coda 对这条记录调用 execute,输入照协议包 executor@1;host 在本机执行任务,并只写这次调用开出的 coda/run@1 运行:进行中是 working 带进展,结束写 completed、failed(带退出码、输出末尾、摘要与步骤输出)或 canceled。终态之后不再改。取消是对运行调用 cancel,交给 host 停下原 worker。

2.0.1:启动时先读上次运行留下的 coda/executor@1 记录,按它的 revision 接管;此前插件宿主重启后写这条记录会被 Coda 以 conflict 拒绝,host 模块载入失败。

配置意图、能力和名额在本机持有。host.enabled 控制是否接活,默认 true;host.capacity 配置名额数;host.labels 是逗号分隔的自定义标签。系统/CPU、Node、Xcode、可用模拟器 runtime 与图形会话由本机探测,每分钟刷新,不启动模拟器。容量和占用订阅 concurrency-groups,包括旧流程与 run-held,公布值不构成预留。停止接活不终止已接收的任务。

资源只接受 {slots:1} 或空对象;exclusiveResources: ['slots'] 表示独占。host 将 slots 映射到本机组 host,开跑前通过同一名额账本最终准入,账本返回稳定名额序号。其他资源量不能模拟为多次申请。

执行:execute 的输入照协议包 executor@1:source(git/snapshot@1,或 git/source@1 加完整 commit)、requirements.labels、resources、context、task、env、timeoutMs、cancelGraceMs。源码经 Coda 的引用解析取得鉴权到达,不拼机器 ID 或 /forward;快照的 source ID 在其持有者范围内解释。代理鉴权头只传给本次 Git 子进程,不进入对象、日志、持久记录或 .git/config。

固定目录为 <插件状态>/workspaces/<来源工作副本身份及 instance 的散列>/<账本名额序号>,不同来源工作副本、不同名额隔离;快照或提交改变不会丢掉同源缓存。fetch 后校验 commit,执行 reset --hard 和 clean -fd,保留被忽略缓存。cwd 必须在该工作根内,拒绝路径穿越和符号链接逃逸。没有源码的任务使用每次尝试的隔离目录。源码获取不改变发布/部署的准入政策。

三段 hook 与恢复:prepare_job / run_script_step / cleanup_job 使用原 JSON envelope,prepare 的 state 即使伴随失败也会收尾;命令退出码原样返回,cleanup 失败记日志。声明变量与执行器变量分开,取消先停止当前进程组、在收尾期限内 cleanup,确认完成后才释放名额。每次尝试在启动前持久记账;独立 worker 继续运行,不随插件宿主重启而重复启动。重启后跟随已有 worker;worker 不可达且无最终记录时在运行进展里写 result_unknown,保留名额,绝不把丢失响应当作安全重试。取消通过带随机 token 的 loopback 控制通道交给原 worker,不对可能已被复用的 PID 盲发信号。

运行本身是这次执行的持久结果引用,日志与结果留在插件状态的 attempts/<运行键>/ 下;结果保留有界 outputs、summary 和日志末尾。产物字节传输留给 artifacts 插件。

验证:纯规则、Git 目录、hook、取消竞态与重启记录在 test/plugins/host/;公共形状直接用 host 安装的协议包和同步的 provider 校验器测试。真实 Coda 存储/节点镜像/资源账本装配留 Coda 仓库验证。包含 host-sim 的完整插件测试经会话的 workflow_run → run-held 运行,不启动真实模拟器。

现有持锁执行与模拟器工具

这个后端实例的 Apple 模拟器、Xcode 构建和项目要求排队的命令共用一组名额,会话里的这类命令经这个插件排队与执行。名额是流程引擎的并发组 host, 每个后端实例各有一组,同一台 Mac 上的两个实例互不相干;插件只说它装的是什么、能同时进几个,Coda 内核不认识它。

从 Coda 的商店安装(npm 包 @coda-console/host,分类「机器与资源」),不随 Coda 默认装上;没装时流程步骤写 coda:group="host" 照样排队,容量按 1, 会话里也没有 host-sim。用法给 Agent 的部分在 Skill host-slots(skills/host-slots/SKILL.md)。

范围:插件的说明让会话的 Agent 把三类命令交给持锁执行:Xcode 构建、用 Apple 模拟器的命令、会调用 host-sim 的项目脚本。 别的命令(其他项目的构建、测试、静态检查)直接执行,不因为是构建就排队;项目要别的命令也排队,就在项目说明(如 AGENTS.md)里写明, 或让脚本经 host-sim 自己排队(见下文)。流程步骤占不占名额由流程自己用 coda:group="host" 声明。

入口:会话的 Agent 用 workflow_run 调用能力 run-held(持锁执行),inputs 给 command(要执行的命令,由 $SHELL -c 执行)、 cwd(在哪个目录执行,绝对路径),用模拟器时 what 为 模拟器(默认 构建)。能力写了 coda:inline 与 coda:subagents="false": 结束得快就随这次调用返回结果,否则结果之后送回会话(见 Agent 工具);原生子 Agent 发起时拒绝, 提示把这一步交回主 Agent 或用 spawn 派 Coda 子会话(见流程属性)。从命令行(coda-run)发起同样拒绝:命令行说不出是会话里谁在要。

host-sim 是这个插件放在会话 PATH 上的命令(scripts/host-sim.mjs),只在已占着的名额里用:持锁执行的命令里(HOST_SIM_LEASE), 或占着组 host 的流程步骤里(CODA_GROUPS)。在会话里不在名额中调用 host-sim run --kind build|simulator -- <命令> 时拒绝(退出码 2), 提示改由 Agent 用 workflow_run 调用 run-held 执行这条命令;所以经 host-sim 自己排队的项目脚本(scripts/check.sh 的编译范围、iOS 构建与测试入口) 在会话里整条交给 run-held 执行,脚本本身不必改写。别的 --kind(测试机的设备名)交给接在本插件扩展点 kinds 上的插件(测试机)。

总时限:what=模拟器 默认 60 分钟,其他 run-held 默认 30 分钟;从取得名额、进入执行步骤开始计时,不含排队。 长批次在 inputs 显式给 timeoutMinutes,如 { "command": "bash scripts/ios-ui-test.sh", "cwd": "/path/to/project", "what": "模拟器", "timeoutMinutes": 120 }。 timeoutMinutes=0(默认)按种类取值;显式值须大于 0、最多 1440 分钟。用引擎的中断计时器取消整组进程,保留 5 分钟清理宽限,之后才释放名额。

无输出上限:idleMinutes 默认 10 分钟,从命令启动起,stdout 或 stderr 每次有新输出就重新计时;连续到限无输出即失败,先向整组进程发送 TERM(连同命令另起进程组的子进程,如 swift build 的编译器),最多留 5 分钟收尾。可在 inputs 设 idleMinutes: 30 调高,或 idleMinutes: 0 关闭(总时限仍生效)。失败结果与会话通知区分「执行超过总时限」「N 分钟无输出」「命令非零退出(退出码 N)」;输出 failure_reason 记录原因。run-held 因无输出或总时限失败、执行器超时时,若 macOS 上检测到 SecurityAgent 进程,失败原因会追加钥匙串授权框提示,见 host-slots。

过程(.coda/capabilities/run-held.bpmn):

  1. 「等名额」:hold-group 为「占用名额」这一段排进 host,容量读设置 host.capacity;状态行写「排队等构建名额 · 排第 N 位」或「排队等模拟器名额 · 排第 N 位」, 队伍一动就改,会话底部显示这项等待。
  2. 「执行」:在 cwd 里、带项目的环境(同流程步骤,不含插件与执行器自己的变量)执行命令(scripts/run-held.mjs),附上 HOST_SIM_LEASE=coda-run:<种类>: 命令里的项目脚本再调用 host-sim run 时直接执行,host-sim check 通过,host-sim bind <udid> 把它启动的模拟器登记给这一步。 cwd 不是存在的目录的绝对路径时不执行,退出码记为 2。 命令结束(含被取消)时关机并删除登记的模拟器,命令的退出码记为输出 exit_code;命令失败这一步也失败,Agent 收到的结果带着输出的末尾。 被取消时整组进程收到 TERM,这一步的脚本以 exec 运行,执行器等它删完模拟器才结束;收尾超过取消时限被强杀而留下的模拟器,由下面的定时清点删除。
  3. 离开「占用名额」这一段才放开名额,排在后面的随即进入。

执行与中断:命令由 Coda 的步骤执行器运行,不随 Agent 的调用结束:调用先返回了,命令照常执行,结果送回会话; 要停下它用 workflow_cancel。命令不经过会话 Agent 自带的沙箱。

定时清点(.coda/workflows/clean-simulators.bpmn「清点模拟器」,scripts/clean-simulators.mjs):host-sim bind <udid> 除了登记给这一步, 还把 UDID 和登记运行 ID 写进本实例插件状态的 simulator-registrations/,每条登记独立保存,清理不会覆盖同时新增的登记。 持锁命令通过 HOST_SIM_RUN_ID 传递运行 ID;普通流程步骤读 GITHUB_RUN_ID。 按设置 host.cleanSchedule 的周期清点(整个实例只跑一次,coda:scope="machine"),不申请名额、不进入 host 队列。 清理脚本通过本插件模块的带进程令牌的本机只读通道查询;模块每次经公开 coda.api("workflow-runs/<id>") 读取运行终态,不缓存清理资格。 运行须为成功、失败或已取消才删除;运行与子运行是否收尾完成、何时发布终态,由 Coda 运行模块判断。插件不读取宿主数据库或复刻名额收尾逻辑。 运行中、取消收尾中、查不到运行、宿主接口不可用的都跳过。旧版 simulators 纯 UDID 登记没有归属,保留并记录原因,待人工确认闲置后处理。 删除直接交给 simctl delete,不强制关机;使用中或删不掉的跳过、记日志并保留登记,下次再试,已经不在的算删完。不为删除与其他进程使用的罕见交错加锁。 没经 host-sim bind 登记的模拟器不删:用户自己建的,同一用户另一个后端实例的。 只有这个实例自己的正式后端(CODA_ARBITER,插件进程的环境)真正删除,测试或开发起的后端跑这条流程什么也不删。

会话之外:终端里没有这个命令;从会话以外的地方调用插件的 host-sim 不排队,也不执行,提示只能在 Coda 的会话或流程步骤里用; 没有占着组的流程步骤里调用同样拒绝,提示写 coda:group="host"。

资源「构建名额」(类型 slots):从 CODA_GROUPS_STATE 读组 host,一行:读数「空闲」画空闲名额(空几个、共几个), 接着每个占着的写运行标题、所属会话和占了多久(借用中、正在收尾、占满另外注明),每个排着的写排第几、等了多久,合计至多 8 个读数。打开或刷新资源页时读,不在后台采集。 容量在「设置 › 插件」里改。

设置:host.capacity「名额数」,1–8,默认 1;host.cleanSchedule「清点模拟器的周期」,ISO 8601 重复间隔,默认 R/P1D(每天一次)。 插件以 contributes.groups 声明组 host 的容量就是 host.capacity,所以项目流程的步骤写 coda:group="host" 也按这个容量排;步骤里看到 CODA_GROUPS 含 host 时,host-sim 同样视作已占着名额(run 直接执行、check 通过,bind 只记进本实例的 simulator-registrations/,由定时清点删除)。run 直接执行的命令带上 HOST_SIM_LEASE=coda-group:host,所以只看有没有 HOST_SIM_LEASE 的项目脚本在步骤里多走一次就照常往下,不会反复调用自己。项目脚本判断自己在不在名额里应问 host-sim check(Skill host-slots):测试机上执行的命令也带 HOST_SIM_LEASE,占的却不是构建名额。已占着名额只说构建与模拟器,测试机的设备名另由测试机插件借用:在构建名额里用设备名调用,同样交给测试机插件,只借给正在做那台设备任务的会话。

扩展点 kinds:host-sim 遇到 build、simulator 之外的 --kind,把整条命令交给接在这里的第一个命令(按插件 ID 排),参数原样附在后面; 那条命令以接上它的插件的 CODA_PLUGIN_PATH、CODA_PLUGIN_STATE 运行,退出码就是 host-sim 的。没有插件接上时拒绝,提示装测试机插件。

  • 装上后对这台机器的所有项目生效(安装、停用与卸载),可按 Tag 限定或在项目里停用。

版本与发布记录

@coda-console/host 共发布 13 个版本,首次发布于 2026/10/27;过去 12 个月发布了 13 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
2.0.1latest2026/11/082 天前
2.0.02026/11/082 天前
1.4.02026/11/072 天前
1.3.02026/11/072 天前
1.2.62026/11/073 天前
1.2.52026/11/045 天前

其他发布通道:bootstrap → 0.0.0。

关于 @coda-console/host 的常见问题

@coda-console/host 是什么?

本机运行器与 Xcode、模拟器的排队名额

如何安装 @coda-console/host?

在项目目录运行 npm install @coda-console/host,或使用 pnpm add / yarn add / bun add。

@coda-console/host 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/coda-console__host 是否存在。

@coda-console/host 支持 ESM 还是 CommonJS?

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

@coda-console/host 可以商用吗?

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

@coda-console/host 的下载量有多少?

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

@coda-console/host 还在维护吗?

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