dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Voice for the DeepSeek Harness: speak to the agent, hear it back, and see what it is doing from a floating window that stays on top of whatever you are running.
Voice for the DeepSeek Harness web interface — built Spanish-first, and usable without the browser in front of you.
Press a key, say what you want, and the agent answers out loud. A small companion window floats above whatever you are doing and shows what is happening.
Status: 1.0, in daily use. The spoken conversation, the companion window and the global keys are done and used daily. The interface speaks Spanish, English and Simplified Chinese. Local Whisper is not written; see What is missing.
There are already good voice plugins for the harness. Two things none of them do, and one of them is not a matter of effort:
dsh-kitt-voice uses Whisper, which is genuinely multilingual, and
Piper for speaking, which has good Spanish voices and runs locally.JSON=yeisón, setup=setáp, brake bias=breik báias — before the text reaches the voice. Piper only: the neural and
system voices say them correctly on their own.dsh plugin --profile web add dsh-kitt-voice
The command installs the package into the harness profile and appends the
plugin to the profile's bundle list by itself (a dependency that declares
dsh.bundle joins the layer stack automatically). Restart the harness — stop
it completely, do not just relaunch, or you keep talking to the old process. A
microphone and a speaker button appear in the composer tool row.
To undo it:
dsh plugin --profile web remove dsh-kitt-voice
The same command reconciles the bundle list, removing only this plugin. The
old advice to edit package.json by hand belongs to an earlier version of the
CLI that rewrote the whole bundle list; the current one reconciles by
installed state.
From a checkout instead of npm: point the profile at the clone.
dsh plugin --profile web add link:/absolute/path/to/dsh-kitt-voice
If your harness runs a different profile name, replace web with it.
Everything except the transcription key lives in Settings → Plugins → dsh-kitt-voice: recogniser, language, guidance vocabulary, voices folder, voice, microphone and sound output.
The transcription key comes from the harness's own credential store — the
same place the agent's own key lives. Nothing to create, nothing to restart:
store it under GROQ_API_KEY and the plugin finds it. Point apiKeyRef at a
different name if yours is stored under one.
If there is nothing in the store, DSH_KITT_API_KEY or GROQ_API_KEY in the
environment are used instead.
The key is never exposed in Settings and never reaches the browser. The page asks only whether one is configured, through a call that cannot return a value. It is resolved fresh on every request, so replacing a key takes effect immediately.
| Option | Account needed | Works inside a desktop shell | Notes |
|---|---|---|---|
| Browser (default) | no | no | Chrome and Edge only; audio passes through the browser vendor |
| Groq Whisper | yes | yes | Best accuracy and speed; needs a key in the credential store |
The browser recogniser is the default so a new user can talk within seconds. It does not work inside Electron — the object exists there but recognition fails every time — so when the harness is embedded in a desktop app the plugin switches to Groq and says so.
A Spanish speaker says setup, brake bias, understeer in the middle of
Spanish sentences. Told only "Spanish", Whisper writes them phonetically
(cetap, breik baias) and the agent receives nonsense. The guidance
vocabulary in Settings is sent to Whisper so those terms stay in English.
Edit it for your own field.
| Setting | What it does |
|---|---|
piperPronunciation | How English words are spelled out so a Piper voice says them properly, as term=spelling separated by commas. Piper reads phonemes for its voice's own language, so a Spanish voice says "jotason" where the text says JSON unless it is written the Spanish way. Piper only. |
speechRate | How fast the reply is read. 1 is the voice's own pace; 0.5 is half speed and 2 is double. It applies to all three engines, including the system voice, which is read by the page rather than the server. |
uiLang | Language of the plugin's own interface: Spanish, English or Simplified Chinese. Independent of the transcription language — you can dictate in Spanish with the interface in English. |
buttonColours | The controls each carry their own colour, or all of them in white. The colours say what each one does at a glance; the plain mode is for anyone who finds that noisy. |
overlayAuto | Open the floating window by itself the moment the voice is used, and close it with the harness. Off by default: a window that appears on its own is a window somebody did not ask for. |
micLabel | Which microphone, by name. Empty means the system default. By name and not by id on purpose: a browser hands every origin different ids for the same physical device, so an id chosen in the floating window would mean nothing in the page. |
outputLabel | Which speaker or headset the reply comes out of, by name. |
The hands-free conversation has to know when you have finished a sentence. That is a model — Silero v5 — plus its runtime, and together they are about sixteen megabytes.
They are not shipped in this package. Most people who install a voice plugin want to press a button and talk; making all of them carry sixteen megabytes for a mode they may never switch on is rude. So they arrive one of two ways, in this order:
vadDir in Settings — nothing is
downloaded;Either way the files are then served back to the page by the harness itself, so the browser never reaches the internet on its own, and only the six names on a fixed list can ever become a path.
Six files, not five: the detector's own bundle does not carry the inference runtime. It expects to find one already on the page, loaded first.
cd overlay
start.cmd Windows
./start.sh macOS and Linux
Electron is not bundled: the harness is a web application and most people will
never want a desktop window. The launcher uses one you already have — set
DSH_KITT_ELECTRON to point at it — or npm install here to fetch one.
A bar floats above everything, including a fullscreen game, and the bar is the controls — the same ones you get in the harness's own tool row: same drawing, same colour, same size, because they are the same control in two places.
The border carries the state, so it can be read out of the corner of an eye: nothing at rest, green while it listens — growing with the measured level of your voice — blue breathing while it thinks, and red while it speaks to you. If something fails, the word ERROR blinking, which needs no colour to interpret.
Drag it anywhere by holding it, and it remembers where you left it.
Keys (assign them in the menu): F8 speak and send, F9 start or end the
conversation, F7 mute the microphone, F10 hear the reply again, F11 be
quiet (in a conversation it also ends the wait for the reply), F6 open the
menu. To use a wheel button, map it to one of those keys
in your wheel's own software — no gamepad plumbing needed. Keys belonging to
the whole system (Ctrl+C, Alt+F4 and friends) are refused: a global shortcut
takes the key away from every application on the machine.
Set DSH_KITT_PORT if your harness is not on 3081. It takes a port, never
a URL: the window can only ever address loopback.
lib/ the plugin
index.js host half: settings, HTTP routes, capturing the last reply
client.js browser half: the controls, the recording, the settings card
guard.js who is allowed to call the routes
transcribe.js speech to text
speak.js text to speech with local Piper voices
neural.js the neural voices: their protocol, and what leaves the machine
overlay.js opening the companion window when the voice is used
vad.js the turn detector's files, and how they get here
lastfromlog.js recovering the last reply from the session's own log
apikey.js resolving the key, per call, never cached
log.js one startup line, and refusals — never the key
freshness.js detecting a server running an older copy of this plugin
paginas.js which page the keys belong to when more than one is open
pronunciacion.js how English words are spelled out for Piper
overlay/ the companion window (its own Electron app)
main.js the window, its shape and position
shortcuts.js system-wide keys
requests.js the closed list of what the window may ask the harness
textos.js every string the window shows, in the three languages
index.html what it draws
test/ the parts worth protecting
The two halves never share memory. They speak over thirteen loopback routes
under /dsh-kitt-voice: config, settings, devices, voices, transcribe,
speak, last, state, command, orders, and vad/status,
vad/download, vad/file. Every one of them checks its caller.
state flows page → host → companion; command flows the other way, and is
how a key pressed outside the browser reaches the page.
127.0.0.1. Requests must
arrive on loopback, and a request carrying an Origin must name this same
server — same loopback spelling, same port (Origin and Host are both written
by the caller, so they are never trusted to agree with each other). Refusals
say nothing about the machine.127.0.0.1 on a configurable port — never a URL it
was handed. Its page makes no network calls at all: the main process relays
them against a closed list of paths (overlay/requests.js), so the window
cannot be pointed at any other host even by its own code.npm test
115 tests, run with node --test, no build step. They cover the parts where a
mistake is expensive: who may call the routes, whether a voice name can escape
its folder, what the reply splitter promises, that the log fallback never
throws inside the route it exists to help, the window's request allowlist, the
read-aloud sentence splitter, the pieces handed to the voices, which page the
keys belong to when two are open, when the microphone is called out as the
problem, how English words are spelled out for Piper, what is sent to the neural voice
service, and the speed steps.
Twenty-seven bugs that each cost an afternoon, written down with their symptoms: Traps already paid for. Every one of them turned up by using the thing rather than by reading the code, and not one raised an error. Read the relevant one before touching the part it belongs to.
MIT — see LICENSE. Prior art and acknowledgements are in NOTICE. How to contribute: CONTRIBUTING.md. Changes: CHANGELOG.md.
Built by Kitt Cat · kittcat.com
Español: README.es.md · 中文: README.zh.md