在 dsh 网页中编辑 ComfyUI、实时预览并让 AI 操作工作流。
45.3/100
综合分
22
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/25 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查有告警:未发布到 npm registry,仅可从源码安装。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add mangfufu/dsh-comfyui-web该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · ui
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 11 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
⚠︎ 实装验证未通过(dependency_conflict · 2026/10/21) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意未发布到 npm registry,仅可从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包dsh-comfyui-web(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=22 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/2 17:40:39
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 72 处,展示前 60 条)
- 发起网络请求client.js:486
const response = await fetch('/dsh-comfyui/api', body ? { method: 'POST', signal, - 写入剪贴板client.js:631
try { await navigator.clipboard.writeText(JSON.stringify(connection.mcp.clientConfig, null, 2)); setCopied(true); } - 读取本地文件lib/host.js:25
const config = JSON.parse(await readFile(runtime.configFile, 'utf8').catch(() => '{}')); - 写入本地文件lib/host.js:32
await writeFile(runtime.configFile, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 }); - 读取本地文件lib/host.js:49
const config = JSON.parse(await readFile(runtime.configFile, 'utf8').catch(() => '{}')); - 发起网络请求lib/host.js:87
else if (body.op === 'check') { const stats = await runtime.request('/system_stats'); json(res, 200, { connected: true, system: stats.system }); } - 读取本地文件lib/runtime.js:139
try { const config = JSON.parse(await readFile(this.configFile, 'utf8')); this.url = normalizeUrl(config.url || this.url); this.mcpEnabled = config.mc - 读取本地文件lib/runtime.js:141
this.bridgeCode = await readFile(new URL('../bridge.js', import.meta.url), 'utf8'); - 读取本地文件lib/runtime.js:142
this.bridgeVersion = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8')).version; - 写入本地文件lib/runtime.js:158
await mkdir(dirname(this.configFile), { recursive: true }); - 写入本地文件lib/runtime.js:159
await writeFile(joinPath(dirname(this.configFile), 'connection.json'), JSON.stringify({ endpoint: this.frameOrigin + '/mcp', token: this.token }) + '\ - 写入本地文件lib/runtime.js:172
await mkdir(dirname(this.configFile), { recursive: true }); - 读取本地文件lib/runtime.js:173
const previous = JSON.parse(await readFile(this.configFile, 'utf8').catch(() => '{}')); - 写入本地文件lib/runtime.js:174
await writeFile(this.configFile, JSON.stringify({ ...previous, url: next }, null, 2) + '\n', { mode: 0o600 }); - 读取本地文件lib/runtime.js:185
const previous = JSON.parse(await readFile(this.configFile, 'utf8').catch(() => '{}')); - 写入本地文件lib/runtime.js:186
await writeFile(this.configFile, JSON.stringify({ ...previous, url: this.url, mcpEnabled: enabled }, null, 2) + '\n', { mode: 0o600 }); - 发起网络请求lib/runtime.js:239
const res = await fetch(this.url + path, { ...init, signal: signal ? AbortSignal.any([signal, timeout]) : timeout }); - 发起网络请求lib/runtime.js:417
const upstream = transport.request(target, { method: req.method, headers }, response => { - 发起网络请求lib/runtime.js:443
const upstream = transport.request(target, { headers }); - 发起网络请求lib/mcp.js:54
try { stats = await runtime.request('/system_stats', {}, signal); } catch(e) { connected = false; error = e.message; } - 发起网络请求lib/mcp.js:115
const stats = await runtime.request('/system_stats', {}, signal); - 发起网络请求lib/mcp.js:120
const queue = await runtime.request('/queue', {}, signal); - 发起网络请求lib/mcp.js:153
const raw = await runtime.request('/queue', {}, signal); - 发起网络请求lib/mcp.js:161
const raw = await runtime.request('/history' + (args.promptId ? '/' + encodeURIComponent(args.promptId) : '?max_items=5'), {}, signal); - 发起网络请求lib/mcp.js:169
const data = await runtime.request('/object_info' + (args.nodeType ? '/' + encodeURIComponent(args.nodeType) : ''), {}, signal); - 读取本地文件lib/extension-install.js:25
const source = await readFile(new URL('../comfy-extension.js', import.meta.url), 'utf8'); - 写入本地文件lib/extension-install.js:26
await mkdir(web, { recursive: true }); - 写入本地文件lib/extension-install.js:27
await writeFile(join(web, 'loader.js'), source.replaceAll('__DSH_DEFAULT_BRIDGE__', JSON.stringify(bridgeOrigin)), 'utf8'); - 写入本地文件lib/extension-install.js:28
if (custom) await writeFile(join(directory, '__init__.py'), - 发起网络请求lib/reference.js:55
const response = await fetch(runtime.url + '/upload/image', { method: 'POST', - 读取本地文件lib/launcher.js:8
const isFile = path => stat(path).then(value => value.isFile(), () => false); - 读取本地文件lib/launcher.js:9
const isDirectory = path => stat(path).then(value => value.isDirectory(), () => false); - 读取本地文件lib/launcher.js:34
const value = (await readFile(join(root, '.app_path'), 'utf8')).trim(); - 读取本地文件lib/launcher.js:62
const entries = await readdir(root, { withFileTypes: true }).catch(() => []); - 读取本地文件lib/launcher.js:92
const entries = await readdir(parent, { withFileTypes: true }).catch(() => []); - 发起网络请求lib/launcher.js:171
const response = await fetch(url + '/system_stats', { signal: AbortSignal.timeout(4000) }); - 读取本地文件lib/launcher.js:185
async readConfig() { return JSON.parse(await readFile(this.runtime.configFile, 'utf8').catch(() => '{}')); } - 写入本地文件lib/launcher.js:217
await mkdir(dirname(this.runtime.configFile), { recursive: true }); - 写入本地文件lib/launcher.js:219
await writeFile(this.runtime.configFile, JSON.stringify({ ...config, launcher: { path: selected.path, kind } }, null, 2) + '\n', { mode: 0o600 }); - 发起网络请求lib/generation.js:147
const data = await this.runtime.request('/history/' + encodeURIComponent(record.promptId)); - 发起网络请求lib/generation.js:157
const queue = await this.runtime.request('/queue'); - 发起网络请求lib/generation.js:166
const data = await this.runtime.request('/history/' + encodeURIComponent(record.promptId)); - 写入本地文件lib/media.js:51
await mkdir(dirname(keyFile), { recursive: true }); - 写入本地文件lib/media.js:52
try { await writeFile(keyFile, randomBytes(32), { flag: 'wx', mode: 0o600 }); } - 读取本地文件lib/media.js:54
this.key = await readFile(keyFile); - 发起网络请求lib/media.js:92
const upstream = await fetch(this.runtime.url + '/view?' + query, { method: req.method, - 读取本地文件lib/state.js:8
try { const data = JSON.parse(await readFile(this.file, 'utf8')); this.records = data.tasks || []; } - 写入本地文件lib/state.js:21
await mkdir(dirname(this.file), { recursive: true }); - 写入本地文件lib/state.js:23
await writeFile(temp, text, { mode: 0o600 }); await rename(temp, this.file); - 写入本地文件lib/state.js:23
await writeFile(temp, text, { mode: 0o600 }); await rename(temp, this.file); - 读取本地文件lib/notes.js:31
const data = JSON.parse(await readFile(this.file, 'utf8')); - 写入本地文件lib/notes.js:96
await mkdir(dirname(this.file), { recursive: true }); - 写入本地文件lib/notes.js:98
await writeFile(temp, text, { mode: 0o600 }); await rename(temp, this.file); - 写入本地文件lib/notes.js:98
await writeFile(temp, text, { mode: 0o600 }); await rename(temp, this.file); - 发起网络请求bridge.js:102
const r = await fetch(bridgeBase + '/__dsh_comfyui/' + path, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Dsh-Comfy-Token': tok - 发起网络请求bridge.js:104
const next = await (await fetch(bridgeBase + '/__dsh_comfyui/bootstrap')).json(); - 发起网络请求bridge.js:2187
const response = await fetch(bridgeBase + '/__dsh_comfyui/bootstrap'); - 发起网络请求comfy-extension.js:13
const response = await fetch(bridgeBase + '/__dsh_comfyui/bootstrap'); - 读取本地文件mcp-stdio.mjs:11
const connection = JSON.parse(await readFile(configPath, 'utf8')); - 发起网络请求mcp-stdio.mjs:12
const response = await fetch(connection.endpoint, { method: 'POST', headers: { Authorization: 'Bearer ' + connection.token, 'Content-Type': 'applicati
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-jobs-local@deepseek-ai/dsh-mcp-client@deepseek-ai/dsh-tool-jobs给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
界面预览
3 张 · 点击查看大图功能亮点
- 侧栏编辑工作流
- 实时预览
- AI操作工作流
README
由 DeepSeek 最新模型翻译生成dsh-comfyui-web
在 dsh 里直接使用 ComfyUI,让 AI 通过 MCP 操作当前工作流。改提示词、调参数、运行生图,节点变化和生成预览都在同一个页面里看得见。
安装
需要已安装的 dsh、pnpm 和本机 ComfyUI,Node.js 22 及以上。
| 插件版本 | 支持的 dsh 版本 |
| 0.5.13–0.5.18 | 0.2.0-rc.2、0.2.1-rc.2 |
| 0.5.12 | 0.2.0-rc.2 |
插件通过 engines.dsh 和 DSH peer dependencies 同时声明已验证的宿主版本,兼容新旧宿主的检查方式。其他 DSH 版本需要另行验证;升级后若提示版本不兼容,请先更新插件。
dsh plugin --profile web add github:mangfufu/dsh-comfyui-web
从 DSH 启动本机 ComfyUI(Windows)
只打开 DSH 时,ComfyUI 面板会显示本机启动入口。点击 自动检测,或用 选择文件夹 / 选择启动文件 打开 Windows 文件选择窗口;也可以手动填写绝对路径。
展开完整文档(README 剩余 1 节)
dsh-comfyui-web
在 dsh 里直接使用 ComfyUI,让 AI 通过 MCP 操作当前工作流。改提示词、调参数、运行生图,节点变化和生成预览都在同一个页面里看得见。
安装
需要已安装的 dsh、pnpm 和本机 ComfyUI,Node.js 22 及以上。
| 插件版本 | 支持的 dsh 版本 |
| 0.5.13–0.5.18 | 0.2.0-rc.2、0.2.1-rc.2 |
| 0.5.12 | 0.2.0-rc.2 |
插件通过 engines.dsh 和 DSH peer dependencies 同时声明已验证的宿主版本,兼容新旧宿主的检查方式。其他 DSH 版本需要另行验证;升级后若提示版本不兼容,请先更新插件。
dsh plugin --profile web add github:mangfufu/dsh-comfyui-web
从 DSH 启动本机 ComfyUI(Windows)
只打开 DSH 时,ComfyUI 面板会显示本机启动入口。点击 自动检测,或用 选择文件夹 / 选择启动文件 打开 Windows 文件选择窗口;也可以手动填写绝对路径。支持任意名称的 .exe 启动器、.bat / .cmd / .ps1 启动脚本、.lnk 快捷方式,以及 ComfyUI 目录 / main.py,不限制启动器品牌,也不要求启动器旁边存在 ComfyUI 源码。
- 直接启动 ComfyUI:使用安装目录里的 Python(支持 AKi、Windows 便携包和本地 .venv / venv),按面板配置的本机地址和端口启动。服务就绪后面板自动连接。
- 使用启动器或脚本:使用自己的启动器、脚本或快捷方式,保留原有启动流程;如果打开的是启动器界面,请在其中点击启动。快捷方式保留其目标参数和工作目录。服务地址和端口需与面板设置一致,服务就绪后 DSH 自动连接。
自动检测只检查已配置路径、常见安装位置和带启动特征的文件名;手动选择文件不限制名称,选择文件夹会列出其中的启动文件。检测不会运行程序。点击启动后会保存入口;仅在识别出 ComfyUI 安装目录时配置桥接扩展,独立启动器沿用已有桥接配置。已运行或正在启动时不会重复启动。启动日志位于 ~/.dsh/comfyui/launch.log,快捷方式目标程序的日志由目标程序管理。PowerShell 脚本遵循本机执行策略,失败时可查看日志。直接启动不会读取第三方启动器的自定义参数。远程 / Docker 地址仍需在对应环境中启动服务。
首次安装时,填写 ComfyUI 前端目录
创建或编辑 ~/.dsh/comfyui/config.json,将示例中的前端目录替换为本机实际路径。Windows 的 ~ 是用户目录;Linux 同样填写实际路径。
{
"url": "http://127.0.0.1:8188",
"frontendExtensionsDir": "D:/ComfyUI/python/Lib/site-packages/comfyui_frontend_package/static/extensions"
}
首次安装或更新后,先保存工作流,再刷新已打开的 ComfyUI 原网页和 dsh 内的面板。
目录未配置或写入失败时,面板的 连接设置和 dsh 启动日志会提示原因。能看到 ComfyUI 网页,还需等到 AI 已连接 才能让 AI 操作。
Docker / WSL 中的 ComfyUI
推荐使用已经持久化挂载的 custom_nodes 目录。编辑运行 dsh 的系统中的 ~/.dsh/comfyui/config.json:
{
"url": "http://127.0.0.1:8188",
"customNodesDir": "/mnt/data/ai/comfyui/storage-nodes/custom_nodes"
}
上面是 Linux 路径示例。dsh 在 Windows 运行时,应填写 Windows 能写入的路径,例如 D:/ComfyUI/custom_nodes,或实际 WSL 发行版的共享目录 //wsl.localhost/Ubuntu/mnt/data/ai/comfyui/storage-nodes/custom_nodes。
确认对应宿主目录已挂载到容器的 custom_nodes,例如:
volumes:
- /mnt/data/ai/comfyui/storage-nodes/custom_nodes:/root/ComfyUI/custom_nodes
启动 dsh 后会生成 dsh-comfyui-bridge 扩展。先保存工作流,再重启 ComfyUI、刷新 dsh 面板。扩展保存在挂载目录中,容器重建后仍保留。
customNodesDir 与 frontendExtensionsDir 二选一。如果沿用前端目录方式,目录同样必须是 dsh 可写、容器可见 的持久化挂载路径,不能直接填写容器内的 /usr/local/... 路径。
如果 Windows 无法直接访问挂载目录,也可在该目录手动创建 dsh-comfyui-bridge/__init__.py:
WEB_DIRECTORY = "./web"
NODE_CLASS_MAPPINGS = {}
再将插件中的 comfy-extension.js 复制为 dsh-comfyui-bridge/web/loader.js,重启 ComfyUI。从 dsh 面板打开时会自动取得桥接地址,无需编辑脚本。手动安装完成并连接后,可忽略宿主的“尚未配置”日志提示。
使用
1. 启动并打开
1. 先启动 ComfyUI。
2. 启动 dsh web,打开 http://127.0.0.1:3080。
3. 进入对话,点击右上角 ComfyUI。
ComfyUI 嵌入 dsh 右侧面板左边聊需求,右边改节点、看预览。手动编辑和 AI 操作都落在当前工作流上。
插件界面跟随 dsh 的语言设置,支持中文和 English。ComfyUI 自身的语言在 ComfyUI 设置中选择。
2. 确认连接地址
默认连接 http://127.0.0.1:8188。如果更换了端口,打开 连接设置,修改地址后点击 保存并连接。
连接地址与 MCP 开关
MCP 默认开启,dsh 已自动接入。这里也能关闭 MCP,或复制配置给其他本机 AI 客户端使用。
3. 让 AI 操作工作流
直接在当前对话里告诉 AI:
读取当前工作流,优化正向提示词,保留现有模型和节点连接,生成一张图并查看效果。
AI 修改提示词并生成图片
提示词直接写入当前节点,右侧查看生成预览,左侧查看出图结果。AI 做了哪些修改,画布上实时可见。
工作流较大时,AI 默认先读取结构摘要,再按需读取节点参数,减少对话上下文占用。
通过插件提交生成后,图片和视频会自动显示在发起任务的回复正文下方,不需要 AI 额外调用显示工具;收起工具过程后仍可查看。
多张图片同样按原比例显示,空间不够时自动换行,不会缩成小方块。
同一路图片同时接标准保存和 Preview 节点时,对话只展示保存版;不同分支的图片和只有 Preview 的结果仍正常展示。
已有历史结果也可以让 AI「用插件显示这个图片或视频」。
也可以直接说「列出工作流标签页,切换到 XXX」,或「复制当前工作流,另开一个叫测试的标签页」。已保存的工作流也能打开或复制,源工作流和未保存修改会保留。
更多操作直接在对话里说:
- 「用我刚上传的参考图做图生图,填入图片节点。」
- 「加一个放大节点,接到输出前面。」
- 「保存当前工作流」,或「另存为视频测试」。另存遇到同名文件会提示换名称。
- 「列出修改快照,恢复到这次修改之前。」撤销、重做和快照在同一浏览器刷新后仍可使用;最多保留 20 份,实际数量受浏览器存储空间限制。
- 「查看我的生成任务,取消还没开始的那一个。」排队任务可按任务取消;中断正在生成的任务会影响整个实例当前生成。
生成完成会自动通知原对话,正在进行的回复不会被强行中断。
在 ComfyUI 手动停止后,AI 会收到“主动中断”通知;同一对话收到你的新消息前,插件会拦截再次提交。想继续时,明确告诉 AI「继续生成」。
极简预设也支持完成通知:缺少后台任务控制器时,插件会在当前会话内自动启用,无需手改配置。
插件重启会恢复原任务跟踪和结果;原对话的 AI 恢复运行后,会重新接上尚未送达的完成通知,不会重复提交生成。
想撤销就说「撤销刚才的修改」。界面大小用顶部 − / + 调整,点击 刷新 可重新加载 ComfyUI。
顶部 图片对话中模糊 开关默认关闭,同时适用于视频。开启后,点击模糊图先显示清晰图片,再点可查看大图;视频先解除模糊,再用播放按钮播放。鼠标悬停时,左上角的灰色小眼睛可切换模糊/清晰。关闭开关后,不出现模糊提示和小眼睛。只影响本插件返回到对话中的图片和视频,开关会记住。
友情链接
LINUX DO
Star History预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
mangfufu/dsh-comfyui-web
在 dsh 网页中编辑 ComfyUI、实时预览并让 AI 操作工作流。
相关插件 · UI / 主题
破甲增强版JeffKeeping/dsh-purge-plus
dsh-purge 的非官方分支fork:适配 DeepSeek Harness 0.2.1-rc.2、破甲内核…
★ 387已汉化DeepSeek 客户端
71.9
无代码业务系统平台nocobase/nocobase
NocoBase 是什么
★ 24,804已汉化DSH
71.8
1Panel 服务器面板1Panel-dev/1Panel
全球 250 万+ 自托管用户共同喜爱。
★ 37,350已汉化DSH
71.5
工作状态行动态ccch1mneyyy/working-activity
作者:chimney@ccch1mneyyy。社区项目,非 DeepSeek 官方项目。
★ 664已汉化DSH
71.2
多模型配置管家farion1231/cc-switch
跨平台桌面一体化助手,支持 Claude Code、Codex、OpenCode、DeepSeek Harness 等工具,唯一官网 ccswitch.io
★ 151,506已汉化DSH
71.1
AI 矢量设计工具ZSeven-W/openpencil
全球首个 AI 原生开源矢量设计工具。
★ 7,027已汉化DSH
71.1
这是你的仓库?认领条目