DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

vamyane /

vamyane/dsh-local-studio

Verified

Local AI creation toolbox for DeepSeek Harness: ComfyUI image generation, local GPT-SoVITS voice, and health checks, all on localhost.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@51a6d42c

dsh-local-studio

Local creation studio for DeepSeek Harness: a sidebar panel that turns ComfyUI into a text-to-image button and GPT-SoVITS into a text-to-speech button, and keeps every generated file in a local folder.

Everything runs on your machine. The plugin never uploads prompts, images or audio, and it never calls a cloud API.

中文说明

Features

  • Sidebar entry + full-screen panel — React rendered directly (no iframe), dark/light aware (uses DSH theme tokens), Esc closes it.
  • Health dots — ComfyUI and GPT-SoVITS are probed with a 3 s timeout; hover a dot to see the exact failure (connection refused, timeout, …) and the fix.
  • Image tab — prompt / width / height / steps → ComfyUI /prompt → poll /history/{id} → download /view → save outputs/local-studio/image-<timestamp>.png, preview in the panel.
  • Speech tab — text (+ optional reference audio) → GPT-SoVITS /tts (GET, then POST as a fallback) → save voice-<timestamp>.wav, listen directly in the panel.
  • Recent outputs tab — the 30 newest images/audio files in the output directory, with thumbnail / audio preview and copy-path.
  • Friendly errors everywhere — every route returns { "error": "...", "hint": "..." } with a 4xx/5xx status; a stopped ComfyUI or a bad checkpoint name never crashes the host.

Requirements

Component Version Notes
DeepSeek Harness >= 0.2.2-rc.1 < 0.3.0-0 uses the connection Fetch-route service
Node.js >= 20 DSH runtime already satisfies this
ComfyUI optional default http://127.0.0.1:8188
GPT-SoVITS optional its api.py server, default http://127.0.0.1:9880

Both services are optional: without them the panel still opens and tells you what to start. The default ComfyUI workflow uses Animagine XL 3.1 (animagine-xl-3.1.safetensors); any SDXL checkpoint works if you set comfyCheckpoint or supply your own workflow.

Install

# from the plugin market (once published), or from a packed tarball:
npm pack
dsh plugin --profile desktop add ./dsh-local-studio-0.1.0.tgz

For local development you can link the directory instead (see ai-brain/dsh-plugin/install.mjs for the link-based recipe): copy this folder into <profile>/local-plugins/dsh-local-studio, add link:./local-plugins/dsh-local-studio to the profile dependencies, append dsh-local-studio to dsh.profile.bundles, run pnpm install, then restart DSH.

After a restart the sidebar footer shows 🎨 Local Studio; open it from there.

Configuration

~/.dsh/local-studio.config.json is optional — when it is missing, these defaults are used and no file is created:

{
  "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": ""
}
Key Meaning
comfyUrl ComfyUI root URL. Set to "" to disable the image route (it answers 501).
comfyCheckpoint ckpt_name for CheckpointLoaderSimple — must match a file under ComfyUI/models/checkpoints.
comfyWorkflow Optional absolute path to a ComfyUI API-format workflow JSON. Supports the placeholders below.
ttsUrl GPT-SoVITS root URL. Set to "" to disable the speech route (it answers 501).
ttsRefAudio Optional default reference audio path for GPT-SoVITS.
ttsPromptText / ttsPromptLang Optional prompt_text / prompt_lang for the reference audio.
outputDir Output folder. Empty = <workspace>/outputs/local-studio.

Environment overrides (used by the tests and handy for debugging):

  • DSH_LOCAL_STUDIO_CONFIG — path to the config file
  • DSH_LOCAL_STUDIO_OUTPUT — override outputDir
  • DSH_WORKSPACE — override workspace detection

The built-in workflow (also shipped as app/workflow.json) supports these placeholders: {{PROMPT}}, {{NEGATIVE}}, {{WIDTH}}, {{HEIGHT}}, {{STEPS}}, {{SEED}}, {{CHECKPOINT}}. A custom workflow may use them or hard-code everything.

HTTP API

All routes live on the authenticated shared /api channel of DSH (connection.fetch.register), so the Host/Origin fence and login state are enforced before the handler runs. Every response is JSON except /file; failures are { "error": "...", "hint": "..." } plus a 4xx/5xx status.

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"
}

Both probes time out after 3 s.

POST /api/dsh-local-studio/image

Request: { "prompt": "1girl, cherry blossoms", "width": 1024, "height": 1024, "steps": 28 } (width/height must be multiples of 8, 256–2048; steps 1–80; seed optional).

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

Flow: POST /prompt → poll GET /history/{prompt_id} every 1 s for up to 90 s → download GET /view → save the PNG into outputDir.

POST /api/dsh-local-studio/tts

Request: { "text": "你好,世界", "refAudio": "D:\\voices\\ref.wav" } (refAudio optional; text ≤ 2000 chars).

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

Calls GET {ttsUrl}/tts?text=…&text_language=zh&text_lang=zh&media_type=wav…; if that endpoint is not accepted (404/405/422) it retries with POST {ttsUrl}/tts and a JSON body. When ttsUrl is explicitly empty the route answers 501 with a configuration hint.

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" } ] }

Only .png/.jpg/.jpeg/.webp/.wav/.mp3/.ogg/.flac files are listed, newest first, capped at 30.

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

Returns the raw bytes with the right content-type. Only bare file names inside outputDir are accepted (.., path separators and control characters are rejected with 400).

Panel

Tab What it does
🖼️ Image prompt + width/height/steps, Generate, live elapsed timer, preview, copy path
🔊 Speech text + optional reference audio, Generate, inline <audio> player, copy path
🗂️ Recent outputs list of the 30 newest files, click to preview image/audio, copy path

The header shows two health dots (ComfyUI / TTS) and a refresh button; the footer shows the resolved output directory.

Build & test

node build.mjs          # gzip-embeds app/workflow.json -> lib/workflow.data.js,
                        # inlines app/panel.css -> lib/client.js, checks name consistency
npm test                # smoke + unit + mock
npm run pack:check      # npm pack --dry-run
  • test/smoke.mjs — offline structural test: the built client loads with a stubbed __ModuleLoader__, both slots register and render, the host module imports and registers five routes, the embedded gzip workflow decompresses, package.json / cordis.patch.yml / icon / README / LICENSE are consistent.
  • test/unit.mjs — no-network unit test: /health returns friendly {ok:false,detail} when the services are down, /outputs ordering/limits, parameter validation, 501 for a disabled TTS, path-traversal protection, placeholder substitution, PNG header parsing.
  • test/mock.mjs — boots a loopback mock of ComfyUI + GPT-SoVITS and exercises the whole chain: health probe, workflow submission, history polling, image download and save, TTS GET and POST fallback, node_errors and status_str=error friendly errors, outputs listing and /file.

Not verified against a real ComfyUI / GPT-SoVITS in this repository: the mock covers the wire protocol and the error branches, but model names, generation times and GPU behaviour need a real box. If something fails, open the panel health dot tooltip first — it names the URL and the underlying socket error.

Known limitations

  • One image per request; batch/queue management is left to ComfyUI.
  • The built-in workflow is a single SDXL text-to-image graph; use comfyWorkflow for anything else (LoRA, ControlNet, upscale, video…).
  • Prompt length capped at 2000 characters, speech text at 2000 characters.
  • The image route waits synchronously for up to 90 s; the panel shows a live timer.
  • Windows-first development (output paths are shown as returned by the host).

License

MIT — see LICENSE.

—/ 5

No ratings yet

Verified DSH bundle

Commit 51a6d42cd132

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout