🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

ComfyUI 绘图控制 xingxue-ux/dsh-comfyUI-control

DeepSeek Harnessv0.1.3
xingxue-ux26 天前有提交已提供中文文档扫描:含敏感能力

在绘图模式里调用本地 ComfyUI 出图与自检

30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/8 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查未通过:缺少 main/exports/bin 入口声明。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add xingxue-ux/dsh-comfyUI-control
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · vision
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 26 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/11/2) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装

缺少 main/exports/bin 入口声明

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-comfyui-control @ 0.1.3
✓Node 引擎要求 >=20.3 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/8 17:42:13

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 90 处,展示前 51 条)
  • 读取本地文件
    lib/comfyui.js:65
    if (!existsSync(path)) throw new Error(`pipeline not found: ${path}`)
  • 读取本地文件
    lib/comfyui.js:66
    const graph = JSON.parse(readFileSync(path, 'utf8'))
  • 读取本地文件
    lib/comfyui.js:198
    if (candidates.some((candidate) => existsSync(join(modelsDir(), folder, candidate)))) return
  • 读取本地文件
    lib/comfyui.js:658
    if (!existsSync(source)) return result
  • 写入本地文件
    lib/comfyui.js:662
    copyFileSync(source, generated)
  • 读取本地文件
    lib/comfyui.js:663
    if (referenceImage && existsSync(referenceImage)) {
  • 写入本地文件
    lib/comfyui.js:665
    copyFileSync(referenceImage, reference)
  • 写入本地文件
    lib/comfyui.js:667
    writeFileSync(page, compareHtml(basename(reference), basename(generated)), 'utf8')
  • 发起网络请求
    lib/comfyui.js:685
    const response = await fetch(`${VIEW_BASE}/`, { method: 'HEAD', signal: AbortSignal.timeout(timeoutMs) })
  • 读取本地文件
    lib/danbooru.js:76
    if (!existsSync(shim)) continue
  • 读取本地文件
    lib/danbooru.js:78
    if (existsSync(entry)) return entry
  • 执行外部命令来自配置/变量
    lib/danbooru.js:91
    const child = spawn(process.execPath, [entry], {
  • 发起网络请求
    lib/danbooru.js:126
    await fetch(`${CAMOFOX_URL}/tabs/${tabId}?userId=${encodeURIComponent(DANBOORU_CAMOFOX_USER)}`, {
  • 读取本地文件
    lib/danbooru.js:250
    if (!forceRefresh && existsSync(cacheFile)) {
  • 读取本地文件
    lib/danbooru.js:251
    if (Date.now() - statSync(cacheFile).mtimeMs < CACHE_TTL_DAYS * 86400000) {
  • 读取本地文件
    lib/danbooru.js:306
    if (!existsSync(CACHE_DIR)) return undefined
  • 读取本地文件
    lib/danbooru.js:307
    for (const file of readdirSync(CACHE_DIR).sort()) {
  • 读取本地文件
    lib/env.js:44
    return candidates.find((candidate) => existsSync(join(candidate, 'models'))) ?? candidates[0]
  • 读取本地文件
    lib/env.js:56
    return shipped.find((candidate) => existsSync(candidate)) ?? join(COMFYUI_ROOT, 'pipeline.json')
  • 读取密钥环境变量
    lib/env.js:65
    export const CIVITAI_TOKEN = process.env.CIVITAI_TOKEN || ''
  • 读取密钥环境变量
    lib/env.js:66
    export const CIVITAI_SEARCH_KEY = process.env.CIVITAI_SEARCH_KEY || ''
  • 写入本地文件
    lib/env.js:87
    mkdirSync(dir, { recursive: true })
  • 读取本地文件
    lib/env.js:94
    return JSON.parse(readFileSync(path, 'utf8'))
  • 写入本地文件
    lib/env.js:102
    writeFileSync(path, JSON.stringify(value, null, 2), 'utf8')
  • 读取本地文件
    lib/env.js:108
    return Date.now() - statSync(path).mtimeMs
  • 读取本地文件
    lib/env.js:116
    return readdirSync(dir)
  • 发起网络请求
    lib/http.js:46
    const response = await fetch(target, init)
  • 读取本地文件
    lib/lora-search.js:402
    total = statSync(source).size
  • 读取本地文件
    lib/repro.js:51
    if (existsSync(path)) {
  • 读取本地文件
    lib/repro.js:52
    const bytes = readFileSync(path)
  • 发起网络请求
    lib/repro.js:60
    const response = await fetch(sample.reference.url, { signal })
  • 写入本地文件
    lib/repro.js:68
    writeFileSync(path, bytes)
  • 读取本地文件
    preset/dsh-comfyui-control/lib/index.js:320
    return candidates.find((candidate) => existsSync(join(candidate, 'models'))) ?? candidates[0]
  • 读取本地文件
    preset/dsh-comfyui-control/lib/index.js:332
    return shipped.find((candidate) => existsSync(candidate)) ?? join(COMFYUI_ROOT, 'pipeline.json')
  • 读取密钥环境变量
    preset/dsh-comfyui-control/lib/index.js:341
    const CIVITAI_TOKEN = exports.CIVITAI_TOKEN = process.env.CIVITAI_TOKEN || ''
  • 读取密钥环境变量
    preset/dsh-comfyui-control/lib/index.js:342
    const CIVITAI_SEARCH_KEY = exports.CIVITAI_SEARCH_KEY = process.env.CIVITAI_SEARCH_KEY || ''
  • 写入本地文件
    preset/dsh-comfyui-control/lib/index.js:363
    mkdirSync(dir, { recursive: true })
  • 读取本地文件
    preset/dsh-comfyui-control/lib/index.js:370
    return JSON.parse(readFileSync(path, 'utf8'))
  • 写入本地文件
    preset/dsh-comfyui-control/lib/index.js:378
    writeFileSync(path, JSON.stringify(value, null, 2), 'utf8')
  • 读取本地文件
    preset/dsh-comfyui-control/lib/index.js:384
    return Date.now() - statSync(path).mtimeMs
  • 读取本地文件
    preset/dsh-comfyui-control/lib/index.js:392
    return readdirSync(dir)
  • 发起网络请求
    preset/dsh-comfyui-control/lib/index.js:449
    const response = await fetch(target, init)
  • 读取本地文件
    preset/dsh-comfyui-control/lib/index.js:571
    if (existsSync(path)) {
  • 发起网络请求
    preset/dsh-comfyui-control/lib/index.js:580
    const response = await fetch(sample.reference.url, { signal })
  • 写入本地文件
    preset/dsh-comfyui-control/lib/index.js:588
    writeFileSync(path, bytes)
  • 写入本地文件
    preset/dsh-comfyui-control/lib/index.js:1331
    mkdirSync(dirname(out), { recursive: true })
  • 写入本地文件
    preset/dsh-comfyui-control/lib/index.js:1335
    writeFileSync(out, encodePng(result, { textChunks }))
  • 写入本地文件
    preset/dsh-comfyui-control/lib/index.js:2054
    copyFileSync(source, generated)
  • 发起网络请求
    preset/dsh-comfyui-control/lib/index.js:2077
    const response = await fetch(`${VIEW_BASE}/`, { method: 'HEAD', signal: AbortSignal.timeout(timeoutMs) })
  • 执行外部命令来自配置/变量
    preset/dsh-comfyui-control/lib/index.js:3276
    const child = spawn(process.execPath, [entry], {
  • 发起网络请求
    preset/dsh-comfyui-control/lib/index.js:3311
    await fetch(`${CAMOFOX_URL}/tabs/${tabId}?userId=${encodeURIComponent(DANBOORU_CAMOFOX_USER)}`, {
扫描于 2026/11/3(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 本地ComfyUI出图
  • LoRA搜索
  • Danbooru标签查询

DeepSeek Harness 绘图模式预设插件:18 个 comfyui_* 工具,支持 Anima/Krea2 生成、LoRA 搜索、Danbooru 标签、PNG 元数据、Ollama 视觉、小番茄去混淆

README

由 DeepSeek 最新模型翻译生成
dsh-comfyUI-control DeepSeek Harness(DSH)0.2 bundle:把本地 ComfyUI 接进一个名为 绘图模式 的 Agent 预设里,完整复刻 xingxue-ux/good-comfyui-mcp 的 13 个工具,并补齐 ComfyUI 控制面与复刻自检,共 19 个 comfyui_ 工具。 安装:dsh plugin add --profile <profile> dsh-comfyui-control(见安装)。 只在「绘图模式」预设里生效:标准模式、极简模式、PTC 模式、创造模式等其他预设都不挂载这个插件,也就看不到任何 comfyui_ 工具。 零运行时依赖:只用 Node 内置模块 + 全局 fetch,不需要 pip、不需要常驻 Python MCP 进程。 0.2 与旧版预设机制的区别(重要) DSH 0.1 从 $DSH_HOME/.agent-presets/<id>/ 读取用户预设;0.2 已经不再读这个目录。 0.2 的预设是 bundle patch 里的 @deepseek-ai/dsh-agent-preset 声明,必须用 plugin_manager 安装 bundle 才能出现在预设选择器里。本包就是按 0.2 机制交付的。
展开完整文档(README 剩余 1 节)
dsh-comfyUI-control

DeepSeek Harness(DSH)0.2 bundle:把本地 ComfyUI 接进一个名为 绘图模式 的 Agent 预设里,完整复刻 xingxue-ux/good-comfyui-mcp 的 13 个工具,并补齐 ComfyUI 控制面与复刻自检,共 19 个 comfyui_ 工具。

安装:dsh plugin add --profile <profile> dsh-comfyui-control(见安装)。

只在「绘图模式」预设里生效:标准模式、极简模式、PTC 模式、创造模式等其他预设都不挂载这个插件,也就看不到任何 comfyui_ 工具。

零运行时依赖:只用 Node 内置模块 + 全局 fetch,不需要 pip、不需要常驻 Python MCP 进程。

0.2 与旧版预设机制的区别(重要) DSH 0.1 从 $DSH_HOME/.agent-presets/<id>/ 读取用户预设;0.2 已经不再读这个目录。
0.2 的预设是 bundle patch 里的 @deepseek-ai/dsh-agent-preset 声明,必须用 plugin_manager 安装 bundle 才能出现在预设选择器里。本包就是按 0.2 机制交付的。

功能(19 个工具)

| 工具 | 说明 | 对应上游 |
| comfyui_status | 依赖自检:ComfyUI / 管线模型 / 8899 对比页服务 / camofox / Civitai 凭据 / 视觉服务状态,返回 missing[] 与 on_demand[] | server_info |
| comfyui_setup_guide | 初始化清单(每步含操作 / 验证 / 是否必需) | setup_guide |
| comfyui_get_model_guide | Anima 官方用法:模型版本、采样参数、提示词规则、限制 | get_model_guide |
| comfyui_list_models | 列出 ComfyUI 各模型目录(loras / diffusion_models / text_encoders / vae / upscale_models …) | — |
| comfyui_generate | 出图:Anima 管线(默认)或 Krea2 引擎;可覆盖 steps/cfg/sampler/尺寸/seed;参考图自动生成对比页 | generate |
| comfyui_repro_check | 复刻自检:按上游样例元数据原样出图(1216 宽 × 30 步 / CFG 4 / euler_ancestral + 5 件套 LoRA),把结果与上游原图并排展示给你自己目视对比;不做自动评分 | run_example.py |
| comfyui_run_workflow | 提交任意 workflow JSON 并等待结果 | — |
| comfyui_history | 历史记录查询与 mcp/manual 来源标注 | — |
| comfyui_queue | 队列查看 / 中断 / 清空 | — |
| comfyui_node_info | 节点输入输出定义查询 | — |
| comfyui_extract_image_info | PNG 元数据解析:ComfyUI prompt/workflow、WebUI parameters、LoRA 配置 | extract_image_info |
| comfyui_describe_image | 识图,默认关闭(你通常已有多模态模型,直接读图);显式 enable_vision=true 后优先用宿主视觉模型 deepseek-v4.1-flash,Ollama 为可选的本地回退(qwen3-vl:8b → llava:7b,detail 11 问模式) | describe_image |
| comfyui_deconfuse_image | 小番茄(Gilbert 曲线)混淆图还原,可 enc/dec 多次 | deconfuse_image |
| comfyui_lookup_character_tags | Danbooru 角色规范 tag(camofox 反检测浏览器,30 天缓存) | lookup_character_tags |
| comfyui_lookup_character_appearance | 角色外貌 tag 统计(solo 图 tag 频率) | lookup_character_appearance |
| comfyui_list_cached_characters | 已缓存角色列表(离线) | list_cached_characters |
| comfyui_search_lora | Civitai LoRA 精确版搜索(网页搜索端点 models_v9,比 API 全) | search_lora |
| comfyui_download_lora | Civitai 下载 + safetensors 头校验 | download_lora |
| comfyui_lookup_lora_hash | 本地文件 SHA256 → by-hash 反查精确来源 | lookup_lora_hash |

安装

已发布到 npm:dsh-comfyui-control(dsh.bundle.patch 已声明,装进 profile 即自动成为一层 bundle)。

方式一:npm / dsh plugin add(推荐)

bash
dsh plugin add --profile <你的 profile> dsh-comfyui-control

它做三件事:pnpm 把包装进 <DSH_HOME>/profiles/<profile>/node_modules/、写完 package.json 依赖、并把 dsh-comfyui-control 追加到该 profile 的 dsh.profile.bundles。装完重启 DSH 即可。

也可以手动把包放进 profile:在 profile 目录跑 npm i dsh-comfyui-control(或 pnpm add),再在 package.json 的 dsh.profile.bundles 里加上 "dsh-comfyui-control"。

方式二:本地目录 bash
git clone https://github.com/xingxue-ux/dsh-comfyUI-control

对 Agent 说:

用 plugin_manager 安装 E:\AI\ComfyUI\dsh-comfyUI-control 这个 bundle(action: install_bundle)。

也可以在「设置 → 插件」里安装同一个目录。

选择预设

预设名 绘图模式(id drawing)。装完后 plugin_manager 的 list_bundles 会列出这个 bundle, list_plugins 里会出现 preset-drawing 行。在 Agent 预设选择器里选 绘图模式,或设为默认预设后新建会话。

预设只对新会话生效;已在运行的会话保持启动时的插件版本。

环境依赖

| 依赖 | 必需 | 说明 |
| ComfyUI(默认 http://127.0.0.1:8188) | ✅ | 出图与模型列表 |
| Anima 管线模型 | ✅ | anima-base-v1.0.safetensors(models/diffusion_models/)、qwen_3_06b_base.safetensors(models/text_encoders/)、qwen_image_vae.safetensors(models/vae/)、RealESRGAN_x2plus.pth(models/upscale_models/,开 upscale 时用) |
| 默认 5 件套 LoRA | ✅(默认挂载) | 见下节;缺了就用 comfyui_search_lora + comfyui_download_lora 拉 |
| 8899 对比页服务 | ✅ | 出图返回的 view_url 指向它。启动:npm run serve-compare(即 node tools/serve-compare.mjs,只读服务 <DSH_HOME>/storages/dsh-comfyui-control/compare/);没启动时 comfyui_status 会把它列进必需项并从 missing[] 报告,comfyui_generate 也会在结果里带 view_warning |
| camofox-browser(默认 http://127.0.0.1:9377) | 可选 | npm install -g @askjo/camofox-browser && camofox-browser;不装则角色 tag / 外貌统计不可用 |
| Civitai 凭据 | 可选 | CIVITAI_TOKEN(下载)、CIVITAI_SEARCH_KEY(搜索);不配时 by-hash 反查仍可用 |
| 视觉服务 | 可选(默认关闭) | comfyui_describe_image 默认不发请求 —— 你通常就是多模态模型,直接读图即可。需要时传 enable_vision=true,默认走宿主视觉模型 deepseek-v4.1-flash(opencode-go),用不到 Ollama;想走本地 Ollama 则传 model=qwen3-vl:8b 并先 ollama pull qwen3-vl:8b(+ llava:7b 作为 NSFW 回退) |

装好后在新会话里先调 comfyui_status,它会返回 missing[] 逐项告诉你缺什么。

默认 5 件套 LoRA(需要自己下载,插件不会自动拉)

comfyui_generate 不传 lora_text 时自动挂这 5 个;本包不包含任何模型文件,缺任何一个都会提交失败:

| LoRA | 权重 | 用途 |
| ushikani_kassen_lora-000013.safetensors | 0.3 | 画风 |
| anima-darklight-style-v1-000194.safetensors | 0.3 | 朦胧氛围 |
| anima-base-1-photo-background-v4.safetensors | 0.6 | 写实背景 |
| RealSkin SliderV2.safetensors | 0.8 | 写实皮肤 |
| surtr945_v1.safetensors | 0.8 | 画风 |

补齐方式(四选一):

1. 让 Agent 代下(推荐,需要 CIVITAI_TOKEN):
comfyui_search_lora(filename='surtr945_v1.safetensors') → comfyui_download_lora(version_id=3023314, filename='surtr945_v1.safetensors')
→ comfyui_lookup_lora_hash 核对来源。内置 KNOWN_EXACT 表让这 5 个都能离线命中精确版。
2. 自己下:从 Civitai 下到 <COMFYUI_ROOT>/models/loras/,文件名保持一致。
3. 不用默认套:显式传 lora_text="" 空载,或传 lora_text='<lora:你的LoRA:0.7>' 覆盖。
4. 补齐后复查:comfyui_status 的 default_loras.missing 应为 [],models_ok 才会是 true。

comfyui_status 会单独检查这 5 个文件(default_loras.present/missing):它们不在 pipeline.json 里,是生成时动态注入的,所以不检查的话新装环境会误报 ready: true。

复刻自检(comfyui_repro_check)

移植了上游 run_example.py 的目的,但不做 MAE 自动判定:用上游两个样例的元数据原样出图,然后把生成图与上游原图并排放在对比页里,由你目视判断本地环境是否与上游参考一致。

| 样例 | 尺寸 | seed | 说明 |
| repro_anima_00015 | 1216×912 | 8682388855765119 | 双人沙发月光夜 |
| repro_sofa_rose | 1216×832 | 2075224187 | 沙发玫瑰写实 |

两张都用 30 步、CFG 4、euler_ancestral/simple、同一套 5 件套 LoRA(含 darklight 0.4、RealSkin 0.8/0.7 的差异也与上游一致)。
元数据固定在 repro/samples.json,并有测试逐字段比对上游 examples/.json,防止漂移。

用法:

comfyui_repro_check # 两个样例都跑(需要参考图已缓存)
comfyui_repro_check(allow_download=true) # 首次:同意从上游仓库下载参考原图(约 5MB/张)
comfyui_repro_check(sample='repro_sofa_rose')# 只跑一个

- 上游参考图不随包发布(两张共约 10MB)。首次必须显式 allow_download=true,下载后按清单里的 sha256 校验并缓存在 <DSH_HOME>/storages/dsh-comfyui-control/repro/;校验不过就报错,不会拿错图对比。
- 生成的图与上游原图都写到 compare/repro/ 下,8899 服务在线时返回的 view_url 可直接打开并排对比。
- 前置:底模与 5 件套 LoRA 齐全、ComfyUI 运行中、8899 在跑。

配置

全部通过环境变量,都有可用默认值:

| 变量 | 默认 | 说明 |
| COMFYUI_ROOT | 从插件位置向上探测含 models/ 的那一级 | ComfyUI 安装根目录;models/、output/ 都在其下。兼容上游写法 MODELS_ROOT。强烈建议显式设置,例如 E:\AI\ComfyUI:插件装在 bundle store 里时,它离你的 ComfyUI 安装目录很远,自动探测不到 |
| COMFYUI_URL | http://127.0.0.1:8188 | ComfyUI 地址 |
| PIPELINE | bundle 内 pipeline.json | Anima 管线 workflow 路径 |
| COMFYUI_OUTPUT | <COMFYUI_ROOT>/output | 出图目录(对比页复制源文件用) |
| DSH_COMFYUI_STATE | <DSH_HOME>/storages/dsh-comfyui-control | 角色缓存 cache/ 与对比页 compare/ 的根目录 |
| OLLAMA_URL | http://127.0.0.1:11434 | Ollama 地址 |
| CAMOFOX_URL | http://127.0.0.1:9377 | camofox-browser 地址 |
| COMFYUI_VIEW_BASE | http://127.0.0.1:8899 | 对比页 URL 前缀 |
| CIVITAI_HOST | https://civitai.red | Civitai 镜像(civitai.com 会过滤内容) |
| CIVITAI_TOKEN | 空 | 下载 / 详情接口用 |
| CIVITAI_SEARCH_KEY | 空 | 网页搜索端点用 |

与上游 good-comfyui-mcp 的对应关系

- 工具语义一致:同样的参数名、同样的返回字段(prompt_id / outputs / view_url / character_info / canonical_tag / appearance_tags / exact / kind / model_id / version_id / sha256 / valid_safetensors …)。
- 行为一致:Anima 与 Krea2 两套引擎的参数、LoRA 动态注入、默认 5 件套、 30 天角色缓存与缓存键规则、Danbooru wiki 解析规则、Civitai 搜索匹配与打分、小番茄 Gilbert 曲线置换与 --preserve-meta、识图拒绝关键词与 fallback 逻辑。
- 实现方式不同:上游是 Python MCP 进程;本插件是 DSH 进程内的原生工具,用 fetch 直连各服务,不再需要 mcp / httpx / numpy / pillow。
PNG 编解码(含 tEXt/iTXt/zTXt 与 Gilbert 置换)用 Node 的 zlib 自己实现。
- 命名不同:所有工具加 comfyui_ 前缀,避免和宿主/其他插件撞名。

目录结构

package.json bundle 元数据:dsh.bundle.patch -> cordis.patch.yml cordis.patch.yml 【生成】preset-drawing 声明 + 插件列表 preset/ preset.yml 预设显示名「绘图模式」、描述、order agent.cordis.yml 预设的插件列表(唯一真源,build 时嵌入 patch) dsh-comfyui-control/ 预设加载的插件(随 bundle 一起安装) lib/entry.js 插件入口(人工维护) lib/index.js 【生成】自包含单文件插件(19 个工具) pipeline.json 【生成】Anima 管线 workflow LORA_GUIDE.md 【生成】LoRA 选用规范 lib/ 插件实现(打包进 lib/index.js) plugin.js 注册 19 个工具 + 释放 tool.js 工具定义与参数校验(对齐 harness schema DSL) env.js 路径与环境变量解析 http.js fetch 封装(超时 / 非 2xx 报错 / 只读探活) comfyui.js 管线、Krea2、提交轮询、历史/队列、对比页 danbooru.js camofox 会话 + Danbooru 角色查询与缓存 lora-search.js Civitai 搜索/反查/下载引擎(每个请求都有超时) png.js PNG 编解码与文本元数据 xfq.js 小番茄 Gilbert 曲线置换 tools/ 每个领域的工具定义(comfyui / danbooru / civitai / vision) docs/LORA_GUIDE.md LoRA 规范源文件 tools/ build-bundle.mjs 【构建】生成 cordis.patch.yml + 自包含插件 bundle.mjs ESM 自包含打包器 serve-compare.mjs 8899 对比页静态服务(必需依赖) verify.mjs bundle 结构与插件自检 verify-live.mjs 逐工具真实调用并打印结果 test/ node:test 套件

为什么插件是自包含的单文件

bundle store 里的预设行不保证能解析 harness 的 @deepseek-ai/ 包,所以 tools/bundle.mjs 把 lib/ 内联进 preset/dsh-comfyui-control/lib/index.js 这一个文件:只保留 Node 内置模块的外部 import,import.meta.url 指向打包产物自身(插件因此把 dsh-comfyui-control/ 当作自己的根目录)。
lib/tool.js 自带一份与 harness 等价的 schema 编译器与参数校验, test/harness-schema.test.js 对每个工具的编译结果和校验结果与 harness 真实实现逐一比对。

预设行为什么是相对路径(0.2 的一个坑)

预设里挂插件的那一行写成: yaml
- id: comfyui-control
name: './node_modules/dsh-comfyui-control/preset/dsh-comfyui-control/lib/index.js'

因为 0.2 的 Loader 对相对 specifier 做的是 new URL(name, ctx.baseUrl),而 profile 级 Loader 的 ctx.baseUrl 是 profile 目录,所以相对路径要相对 profile 目录来写(bundle 被 link 进 profile 的 node_modules,所以这正好命中)。

两个踩过的坑,写在这里省得再踩:

- 文档里说的"插入行的相对路径锚定在 patch 文件旁"在 0.2.0-rc.2 上不成立(至少在 bundle 被 install_bundle 装配之后):按包目录写的相对路径(如 ./preset/...)解析不到。
- 想在行里用 !!js new URL(..., import.meta.url) 也不行:!!js 表达式的求值方式是 new Function('ctx', ...),里面没有 import.meta,表达式会抛错。
同理可用的是 loader 上下文提供的 dshHomePath(...)(例如 !!js dshHomePath('sessions'))。

开发与验证 bash
npm run build # 生成 cordis.patch.yml 与自包含插件(改代码后必跑)
npm test # 102 用例:单元 + 契约 + bundle 结构 + 实时冒烟(服务不在时跳过)
node tools/verify.mjs # bundle 结构与插件自检
node tools/verify-live.mjs # 逐个真实调用需要服务的工具并打印结果

Node 25 把 node --test <目录> 当成模块入口,所以用 glob 形式(npm test 已是该命令)。

本机验证记录(2026-10-07):

- npm test → 108 用例 / 106 通过 / 1 跳过 / 0 失败
- node tools/verify.mjs → 15/15(bundle 声明、插件行可解析、构建产物与源码一致、19 工具注册)
- 真实出图:comfyui_generate(Anima,512x512,8 步,CFG 2)17 秒完成,输出 1024x1024;回读 PNG 元数据可见 KSampler 参数与注入的 5 个 LoraLoader
- 真实角色查询:comfyui_lookup_character_tags('hatsune miku') → hatsune_miku(147090 posts)
- 真实 by-hash 反查:surtr945_v1.safetensors → model 2692601 / version 3023314 / base Anima
- 小番茄解混淆:enc/dec 两次往返像素完全一致
- comfyui_status 实测:view_server=online(npm run serve-compare 起着时), comfyui_describe_image 默认返回「视觉服务默认关闭」且零网络请求

已知限制

- 视觉服务默认关闭,且默认走宿主模型:comfyui_describe_image 不传 enable_vision=true 时只回一句说明、不发任何请求。开启后优先用 opencode-go/deepseek-v4.1-flash(不存在或不支持图片时依次退到 deepseek-official/deepseek-flash、deepseek-account/deepseek-flash);只有显式传 Ollama 模型名(如 model=qwen3-vl:8b)才会走本地 Ollama,该路径沿用上游行为:qwen3-vl 会拒 NSFW,自动回退 llava:7b(无审查但多角色图容易幻觉)。
未安装模型时会明确提示 ollama pull <模型>。
- 8899 服务是必需依赖:view_url 只是 URL,服务没起就打不开。serve-compare 只读服务 compare 目录、不写盘、不联网;端口用 COMFYUI_VIEW_PORT 或 --port 改。
- Civitai:搜索端点需要 CIVITAI_SEARCH_KEY,下载需要 CIVITAI_TOKEN;by-hash 反查免凭据。
publishedAt 异常的条目 API 搜索搜不到(网页端点可以);个别模型两端都不收录。
- 解混淆:只支持小番茄(Gilbert 曲线)混淆;带密钥的像素混淆无密钥无法还原。
输入必须是 PNG(不引入 JPEG 解码器),times 上限 64(每次都是主机进程内的整幅像素遍历)。
- PNG 编解码:支持 8 位灰度 / RGB / 调色板 / RGBA;隔行 PNG 会明确报错而不是猜。
- 出图元数据处理:非 PNG(如 JPEG)只读取 JPEG COM 注释段的文本元数据并报告格式与尺寸; EXIF 标签数量与 WebUI parameters 的深度解析没有复刻。
- 磁盘增长:compare/ 与角色缓存只增不减,需要时自行清理 <DSH_HOME>/storages/dsh-comfyui-control/。

License

MIT
预览分享卡片长什么样 ↓xingxue-ux/dsh-comfyUI-control
分享 · DeepSeek Harness Hub
xingxue-ux/dsh-comfyUI-control

在绘图模式里调用本地 ComfyUI 出图与自检

这是你的仓库?认领条目

回到顶部