DeepSeek Harness 插件

vamyane/dsh-local-studio

分类 视觉与多模态 收录于 2026-11-10

本地创作工具箱:连接本机 ComfyUI 出图、连接本地 GPT-SoVITS 配音,检查服务是否在线,并把生成的文件保存到工作区。

安装

# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)

dsh plugin --profile web add github:vamyane/dsh-local-studio

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。

README

DeepSeek Harness 的本地创作面板:把 ComfyUI 变成侧栏里的「出图」按钮,把 GPT-SoVITS 变成「配音」按钮,生成的文件都留在本机目录。

插件不上传提示词/图片/音频,也不调用任何云端付费 API。

English

功能

  • 侧栏入口 + 全屏面板:React 直接渲染(没有 iframe),跟随 DSH 主题深浅色,Esc 关闭。
  • 健康状态点:ComfyUI 与 GPT-SoVITS 各 3 秒超时探活;鼠标悬停能看到具体原因 (连接被拒绝 / 超时 / …)和修复建议。
  • 出图:提示词 / 宽 / 高 / 步数 → ComfyUI /prompt → 轮询 /history/{id} → 下载 /view → 存到 outputs/local-studio/image-<时间戳>.png,面板里直接预览。
  • 配音:文本(可选参考音频)→ GPT-SoVITS /tts(先 GET,失败自动回退 POST)→ 存 voice-<时间戳>.wav,面板里直接试听。
  • 最近输出:输出目录里最新的 30 个图片/音频,带缩略图 / 试听和「复制路径」。
  • 错误一定友好:所有路由失败都返回 { "error": "...", "hint": "..." } + 4xx/5xx; ComfyUI 没启动、模型名写错都不会把宿主搞崩。

环境要求

组件 版本 说明
DeepSeek Harness >= 0.2.2-rc.1 < 0.3.0-0 用到 connection 的 Fetch 路由服务
Node.js >= 20 DSH 运行时已经满足
ComfyUI 可选 默认 http://127.0.0.1:8188
GPT-SoVITS 可选 它的 api.py 服务,默认 http://127.0.0.1:9880

两个服务都可以不装:面板照样能打开,只是顶部状态点会告诉你该启动什么。 内置工作流用的是 Animagine XL 3.1(animagine-xl-3.1.safetensors);换 comfyCheckpoint 或提供自己的 comfyWorkflow 就能用别的 SDXL 模型。

安装

npm pack
dsh plugin --profile desktop add ./dsh-local-studio-0.1.0.tgz

本地开发也可以用 link 方式(参考 ai-brain/dsh-plugin/install.mjs):把本目录复制到 <profile>/local-plugins/dsh-local-studio,在 profile 的 dependencies 里加 link:./local-plugins/dsh-local-studio,把 dsh-local-studio 追加到 dsh.profile.bundles, 跑一次 pnpm install,然后重启 DSH。

重启后左侧栏底部出现 🎨 本地创作,点开就是面板。

配置

~/.dsh/local-studio.config.json 是可选的:不存在时直接用默认值,插件不会主动创建文件。

{
  "comfyUrl": "http://127.0.0.1:8188",
  "comfyCheckpoint": "animagine-xl-3.1.safetensors",
  "comfyWorkflow": "",
  "ttsUrl": "http://127.0.0.1:9880",
  "ttsRefAudio": "",
  "ttsPromptText": "",
  "ttsPromptLang": "zh",
  "outputDir": ""
}
字段 说明
comfyUrl ComfyUI 地址;填 "" 表示禁用(出图路由返回 501)。
comfyCheckpoint CheckpointLoaderSimple 的 ckpt_name,必须和 ComfyUI/models/checkpoints 里的文件名一致。
comfyWorkflow 可选:自定义 ComfyUI API 格式工作流 JSON 的绝对路径,支持下面的占位符。
ttsUrl GPT-SoVITS 地址;填 "" 表示禁用(配音路由返回 501)。
ttsRefAudio 可选:默认参考音频(本机绝对路径)。
ttsPromptText / ttsPromptLang 可选:参考音频的 prompt_text / prompt_lang。
outputDir 输出目录;留空 = <workspace>/outputs/local-studio。

环境变量覆盖(测试用,排查问题时也方便):

  • DSH_LOCAL_STUDIO_CONFIG:配置文件路径
  • DSH_LOCAL_STUDIO_OUTPUT:覆盖 outputDir
  • DSH_WORKSPACE:覆盖工作区解析

内置工作流(也随包提供 app/workflow.json)支持这些占位符: {{PROMPT}} {{NEGATIVE}} {{WIDTH}} {{HEIGHT}} {{STEPS}} {{SEED}} {{CHECKPOINT}}。 自定义工作流可以用它们,也可以把参数全部写死。

HTTP 接口

所有路由都挂在 DSH 带登录态的共享 /api 通道上(connection.fetch.register), Host/Origin 栅栏与登录态在进入 handler 之前就已经校验。除 /file 外响应都是 JSON; 失败统一是 { "error": "...", "hint": "..." } + 4xx/5xx。

GET /api/dsh-local-studio/health

{
  "ok": false,
  "comfy": { "ok": false, "detail": "/system_stats → 连接被拒绝(服务可能没启动);/queue → …", "hint": "…", "url": "http://127.0.0.1:8188" },
  "tts":   { "ok": true,  "detail": "HTTP 200 · 根路径可达", "url": "http://127.0.0.1:9880" },
  "config": { "comfyUrl": "…", "ttsUrl": "…", "comfyCheckpoint": "…", "outputDir": "…", "configFile": "…", "configExists": false },
  "warnings": [],
  "version": "0.1.0"
}

两个探活各自 3 秒超时。

POST /api/dsh-local-studio/image

请求:{ "prompt": "1girl, cherry blossoms", "width": 1024, "height": 1024, "steps": 28 } (宽高必须是 8 的倍数、256–2048;步数 1–80;seed 可选)。

响应:{ "file": "C:\\…\\image-20261108-135732.png", "name": "…", "width": 1024, "height": 1024, "bytes": 123456, "promptId": "…", "elapsedMs": 8123, "seed": 123456 }

流程:POST /prompt → 每 1 秒轮询 GET /history/{prompt_id}(最多 90 秒)→ GET /view 下载 → 存 PNG 到 outputDir。

POST /api/dsh-local-studio/tts

请求:{ "text": "你好,世界", "refAudio": "D:\\voices\\ref.wav" }(refAudio 可选; 文本最多 2000 字)。

响应:{ "file": "…/voice-20261108-135800.wav", "name": "…", "bytes": 123456, "mediaType": "audio/wav", "chars": 6, "ms": 1830, "mode": "GET" }

调用 GET {ttsUrl}/tts?text=…&text_language=zh&text_lang=zh&media_type=wav…;如果这个端点 不被接受(404/405/422),自动改用 POST {ttsUrl}/tts + JSON body 重试一次。 ttsUrl 显式留空时返回 501 并给配置提示。

GET /api/dsh-local-studio/outputs

{ "dir": "…\\outputs\\local-studio", "count": 3, "limit": 30, "files": [ { "name": "image-…png", "path": "…", "size": 123, "mtimeMs": 1762…, "kind": "image", "ext": "png" } ] }

只列 .png/.jpg/.jpeg/.webp/.wav/.mp3/.ogg/.flac,按 mtime 倒序,最多 30 个。

GET /api/dsh-local-studio/file?name=image-…png

按正确 content-type 返回原始字节。只接受 outputDir 里的裸文件名 (..、路径分隔符、控制字符一律 400)。

面板

Tab 内容
🖼️ 出图 提示词 + 宽/高/步数、生成、实时计时、预览、复制路径
🔊 配音 文本 + 可选参考音频、生成、内嵌 <audio> 试听、复制路径
🗂️ 最近输出 最新 30 个文件列表,点一下就能预览图片/试听语音、复制路径

顶部是两个健康状态点(ComfyUI / TTS)和刷新按钮;底部显示解析后的输出目录。

构建与测试

node build.mjs          # app/workflow.json 经 gzip 内嵌成 lib/workflow.data.js,
                        # app/panel.css 内嵌进 lib/client.js,并校验包名一致性
npm test                # smoke + unit + mock
npm run pack:check      # npm pack --dry-run
  • test/smoke.mjs:离线结构测试——用桩件加载构建产物 lib/client.js,验证 __ModuleLoader__.load 的 id、两个槽位注册与可渲染、宿主半边能导入且注册五条路由、 内嵌的 gzip 工作流能解回合法 JSON,以及 package.json/cordis.patch.yml/图标/README/LICENSE 的一致性。
  • test/unit.mjs:不依赖网络的单测——服务没启动时 /health 返回友好的 {ok:false, detail}、/outputs 的排序与上限、参数校验、TTS 禁用时的 501、 路径穿越防护、占位符替换、PNG 头解析。
  • test/mock.mjs:在本机起一个假 ComfyUI + 假 GPT-SoVITS(127.0.0.1,离线),跑完整链路: 探活 → 提交工作流 → 轮询 history → 下载并落盘 PNG → TTS 的 GET 与 POST 回退 → 落盘 WAV → outputs 列表 → /file 读回;另外验证 node_errors 和 status_str=error 两条错误分支。

本仓库没有在真实 ComfyUI / GPT-SoVITS 上实测:mock 覆盖了协议和错误分支,但模型名、 生成耗时、显存行为需要真机确认。出问题先看面板健康点的悬停提示——它会指出 URL 和底层 socket 错误。

已知限制

  • 一次一张图;批量/队列管理交给 ComfyUI。
  • 内置工作流只有一条 SDXL 文生图链路;LoRA、ControlNet、放大、视频请用 comfyWorkflow。
  • 提示词最多 2000 字,配音文本最多 2000 字。
  • 出图请求最多同步等 90 秒;面板上有实时计时。
  • 主要在 Windows 上开发(路径按宿主返回原样显示)。

许可证

MIT,见 LICENSE。

内容来自项目 README(GitHub)↗

链接

同类插件

查看整个分类 →

社区评论

评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。