跳到正文
dsh-market 浏览插件 GitHub EN

BOWLUNA/dsh-zcode-farm

多实例 ComfyUI 编排:探测每个已配置 ComfyUI 端点的 GPU、空闲显存与队列深度,再把生成任务派给最空闲且满足条件的实例。提供三个工具(comfyui_farm_status、comfyui_farm_pick、comfyui_farm_run)。一个实例只有在可达、空闲显存不低于要求、且队列不深于上限时才算候选;候选按「空闲显存 - 队列深 × 权重」排序,因此空闲的浅队列胜过忙碌的大显存。零运行时依赖。探测失败可选重试——跨 SSH 隧道的一次超时不足以证明实例已下线。

Star 数 ★ 0 分类 工具与能力 收录于 2026-09-22

安装

在 DeepSeek Harness 里通过 dsh-market 安装

dsh plugin --profile web add dshmarket

或使用命令行

dsh plugin --profile web add github:BOWLUNA/dsh-zcode-farm

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络。请先审阅源码,并尽量锁定 commit(github:owner/repo#sha)。

README

English | 中文

test

让 DeepSeek Harness 的 Agent 看见整个 ComfyUI 农场,并把每个任务派给最空闲的那一台。

dsh plugin --profile web add dsh-zcode-farm

农场怎么挑实例

dsh-comfyui(77★) 本插件
能寻址的端点 一个 多个,并发探测
队列深度 会读 /queue,但只有一个实例时可比较的只有它自己 跨实例加权进排序
任务落在哪 就那一台 空闲显存最多且队列为空的那台
会不会写 ComfyUI 会 会(comfyui_farm_run),但只读也够用

零运行时依赖 · 适配 Node ≥ 22 · MIT


为什么需要它

ComfyUI 官方文档写得很清楚:一个 ComfyUI 进程一次只跑一个工作流,真正的并发只能靠 「每张卡一个进程,再把任务路由到最空闲的实例」。生态里也已经有 comfyui-orchestrator 这类 Node.js 池化库。

但把它们接到 AI Agent 上时,有一个缺口一直没人填:Agent 看不见农场。

实测(2026-09-21 某一刻的真实读数,来自本插件自己的探针):

实例 GPU 空闲显存 队列 判定
18100 ← dsh-comfyui 唯一能看见的那台 RTX 5090 0.8 / 33.7 GB 1 跑 / 0 等 装不下
18300 RTX 5090 0.8 / 33.7 GB 1 跑 / 0 等 装不下
18301 RTX 5090 0.9 / 33.7 GB 1 跑 / 0 等 装不下
18302 RTX 5090 0.5 / 33.7 GB 1 跑 / 0 等 装不下
18303 RTX PRO 6000 Blackwell 99.4 / 102.0 GB 0 / 0 ✅ 全空

dsh-comfyui(77★,市场里做这件事最成熟的插件)只能连一个端点, 于是 Agent 的每次出图请求都会撞上最忙的那台——而 102 GB 的算力从头到尾闲置。

本插件补的就是这一层:先让 Agent 看见,再让它派发。


它做什么

三个工具:

工具 作用
comfyui_farm_status 农场全景:每台的 GPU、空闲显存、队列深度、在跑什么,以及当前该派给谁
comfyui_farm_pick 只选择、不执行:按显存门槛 / 队列上限 / GPU 型号关键字 / 排除名单挑一台,并给出理由
comfyui_farm_run 负载感知派发:自动选实例(或指定某台),支持原始 API 工作流,也支持「提示词 + 模型」一键文生图

安装

dsh plugin --profile web add dsh-zcode-farm

装完重启应用,Agent 立刻获得上述三个工具。


配置

- id: comfyui-farm
  config:
    # 主端点,总是纳入探测(不在 instances 里也会被探测)
    primaryUrl: 'http://127.0.0.1:8188'
    # 农场成员。留空则退化为单实例模式。
    instances:
      - { id: gpu-18301, baseUrl: 'http://127.0.0.1:18301', label: '5090 分片' }
      - { id: gpu-18303, baseUrl: 'http://127.0.0.1:18303', label: 'Blackwell 102G' }
    # 派发策略
    needVramGb: 8          # 低于此空闲显存视为「装不下」
    maxQueueDepth: 3       # 队列深到此值就不再派发
    queueWeight: 1000      # 排序惩罚,见下
    # 探测
    probeTimeoutMs: 5000
    probeRetries: 1

选实例的规则(两段式)

  1. 过滤——不可达 / 空闲显存 < needVramGb / 队列深 > maxQueueDepth 的,一律出局。
  2. 排序——score = 空闲显存(GB) − 队列深 × queueWeight

默认 queueWeight = 1000 是刻意的:让队列主导排序,显存只在队列相同时做平局决胜。 直觉上是对的——一台空着的小卡,比一台正排队的大卡更快出结果。

只想用「显存最多者优先」?把 queueWeight 设成 0 即可。


与 dsh-comfyui 的关系:互补,可共存

dsh-comfyui(77★) dsh-zcode-farm dsh-comfyui 那一列怎么核
管的范围 一个端点 一整个农场 grep -n baseUrl package/lib/config.js → 一个 z.string()
强项 工作流库、技能包、画布、资产面板 状态感知、选实例、派发 ls package/lib
任务怎么落地 单端点在哪就发哪 按「空闲显存 − 队列深 × 权重」排序 grep -n "constructor(baseUrl" package/lib/comfyui.js
装配行 id comfyui comfyui-farm 两个都出现在本仓库的 cordis.patch.yml 里

两行 id 不同,可以同时装配:用 dsh-comfyui 管深度体验,用本插件决定"这活派给谁"。 也可以只用其中一个。本插件不依赖 dsh-comfyui,反之亦然。 dsh-comfyui 的单端点设计是从它已发布的源码核出来的,不是断言 —— 三条命令见下面「怎么自己复核这张表」。


与 ZCode 的关系

本仓库是自研的 —— 与 ZCode 没有代码血缘。 ZCode(zai-org/ZCode、zai-org/GLM-skills) 在这里的角色是工程约定的灵感来源,不是依赖:安装路径、运行时、验收检查里没有任何一处 需要它,本仓库也不涉及任何第三方厂商的 key。

因此下表多数格子是故意留白的,而不是填上编出来的东西。

ZCode 有什么 本插件取了什么 本插件多了什么(优于在哪) 证据(自己跑一遍)
多实例 ComfyUI 调度:无 —— 整个「探测 → 排序 → 派发」闭环 grep -rli comfyui <zcode 检出目录> | wc -l → 0
带两个跳过条件的记忆抽取子代理(apps/zcode-cli/packages/core/src/memory/extraction.ts:23) ——(不同领域) —— 不适用 —— 没取任何东西,所以没有主张要复核
双语配对文档 作为本工作区的约定沿用 扩展到了图文件(*.svg)—— 示意图与译文不会再各自漂移 node tools/verify-translation-pairing.mjs
守卫纪律 —— 提交前跑得动的检查 作为本工作区的约定沿用 扩展到六道,第六道是真启动检查 node test/run.mjs 与 node tools/boot-check.mjs --port 32041

写着 —— 的行是如实留白,不是漏填。


怎么自己复核这张表

上面每一条都不需要你相信 —— 下面就是它背后的命令:

git clone https://github.com/BOWLUNA/dsh-zcode-farm && cd dsh-zcode-farm
node test/run.mjs                        # 2 个套件、23 项检查
node tools/ordering-replay.mjs           # 图背后的排序对照表
node tools/boot-check.mjs --port 32041   # 真装一次、真启动一次(需要一个 harness)

关于 dsh-comfyui 的几条,是拿它已发布的包核的,不是拿本仓库:

npm view dsh-comfyui version                # 0.5.1
npm pack dsh-comfyui@0.5.1 && tar xzf dsh-comfyui-0.5.1.tgz
grep -n baseUrl package/lib/config.js       # 一个字符串,不是列表
grep -n "constructor(baseUrl" package/lib/comfyui.js
9:    baseUrl: z.string().default('http://127.0.0.1:8188'),
71:    constructor(baseUrl, apiKey, connectTimeoutMs, maxMediaBytes) {

以上命令在 2026-09-22 对 dsh-comfyui@0.5.1 实跑过。


设计取舍

  • 零运行时依赖。 只用 Node 内置的 fetch / AbortController。
  • 不做工作流编辑。 那是 dsh-comfyui 的地盘;这里只回答"派给谁"。
  • 不假设本地。 所有成员都是 URL——SSH 隧道、局域网、远端机器一视同仁。 本机的 5 条隧道就是 ssh -L 转发出来的。
  • 探测失败会重试。 跨隧道抖动很常见:实测同一台机器一次探测 >3s 超时、 紧接着 106ms 就返回。单次失败不当结论,重试后再判,并把 attempts 报出去, 让 Agent 能区分「真宕机」和「抖了一下」。
  • 失败原因不被覆盖。 例如按 GPU 型号筛选时,不可达的实例会保留"不可达"这个原因, 不会被改写成"型号不匹配"而把真正的问题藏起来。

开发

npm test                              # 单元测试(纯函数,不碰网络)
node probes/probe-farm.mjs            # 独立探针:只看农场状态
node probes/probe-tools.mjs           # 加载插件入口并真实执行工具(只读)
node probes/probe-tools.mjs --run     # 真的派发一次任务(默认最小负载:512² / 12 步)

开发期需要把宿主提供的 peer 依赖(@deepseek-ai/schemastery 及其依赖)放到本地 node_modules/,否则入口无法加载。装配到真实 profile 时不需要——宿主会提供。


已知限制

  • comfyui_farm_run 的内置模板只覆盖最简文生图(KSampler + CheckpointLoaderSimple + EmptyLatentImage + 两个 CLIPTextEncode + VAEDecode + SaveImage)。复杂需求请直接传 workflow。
  • 不检测"两个 URL 指向同一台机器"。如果你同时配了一个可切换的转发口(如把 127.0.0.1:8188 指向"当前聚焦实例")和它的真实目标,你会看到两行读数完全相同的成员。 这是如实反映,不是 bug——探测本身无法区分。
  • /prompt 返回的 number 是服务端累计接单序号,不是队列位置 (实测:队列为空时它照样返回 22)。真实队列深度以 comfyui_farm_status 的输出为准。

License

MIT


状态

  • 2 个套件、23 项检查 —— 跑 node test/run.mjs
  • 声明兼容范围:>=0.1.5-rc.2 <0.2.0-0 || >=0.1.6-alpha.1 <0.2.0-0 || >=0.1.7-alpha.1 <0.2.0-0(见 engines.dsh 与 peer 范围)
  • 钉住版本可绕过 pnpm 的发布冷却期:dsh plugin --profile web add dsh-zcode-farm@1.0.1
  • 已在 5 个 SSH 隧道实例 + 1 个可切换转发口上验证

内容来自项目 README(GitHub)↗

评论

评论存放在 GitHub Discussions。用 GitHub 账号登录后可发表评论或点表情。