Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🎙️ dsh-talk

Voice-first session loop for DeepSeek Harness: talk to it, hear it answer.

Press the mic, speak, and the reply is spoken back — with speak-to-interrupt.

License DSH plugin Node CI Version npm version npm downloads

English · 简体中文 · Español · Português · हिन्दी


Compatibility

Surface Status
Harness DeepSeek Harness 0.1.0-rc.6
Node ^22.19.0 || >=24.0.0
Browser Web Speech + MediaRecorder (Chrome/Edge best); host transcription/TTS engines for the rest

What you get

dsh-talk closes the voice loop in both directions:

  • speak tool — the agent speaks its replies aloud. TTS engines: the browser voice, edge-tts (network neural voices), or piper (local). Audio plays in the browser; the session log records the sanitized utterance.
  • Composer mic button — press it, speak, and the transcription lands in the input box (or submits directly). STT engines: the browser's Web Speech (interim results included), a FunASR HTTP server, or local whisper.cpp.
  • Speak-to-interrupt — starting to talk stops whatever is playing (client → host over the talk Remote namespace).
  • Event announcements — turn completion, pending approvals (waterfall-safe: never blocks the gate), and errors, with a mute switch and configurable phrases.
  • Settings tab — engine/language selects and announcement switches, saved as append-only profile-patch operations with backups.
browser                                host
  🎙 press ──▶ interrupt ─────────────────▶ talk/interrupt
  record (MediaRecorder / Web Speech)
  transcribe (browser) or talk/transcribe ─▶ FunASR / whisper.cpp
  setDraft(text) or submit()  ◀── talk:speech projection ── speak tool / announcements
  ▶ play audio (talk/audio or speechSynthesis)

Quick start

# 1. install the bundle into your profile
dsh plugin --profile web add "github:PerryLink/dsh-talk#main"

# or from npm (published releases)
dsh plugin --profile web add dsh-talk

# 2. restart and verify the row
dsh --profile web --dump-config | grep -A2 'id: talk'

Then press the microphone next to the composer and talk; ask the agent to speak its reply:

> Say "hello" with the speak tool.

Install & uninstall

  • git channel (latest main): dsh plugin --profile web add "github:PerryLink/dsh-talk#main" — the prepare script builds with production dependencies only.
  • npm channel (published releases): dsh plugin --profile web add dsh-talk.
  • tarball channel: pnpm pack in this repo, then dsh plugin --profile web add ./dsh-talk-<version>.tgz.
  • uninstall: dsh plugin --profile web remove dsh-talk (or remove the row from the profile patch).

If pnpm reports ERR_PNPM_IGNORED_BUILDS for this package (esbuild's harmless platform-binary validation), add allowBuilds: { esbuild: true } to your pnpm-workspace.yaml — the dsh CLI prints the exact snippet.

Configuration

All tunables are Schemastery Config fields (changeable from cordis.yml). cordis.patch.yml documents each key inline.

Key Default Meaning
record.enabled true Show the composer mic button
record.hotkey (none) Optional toggle hotkey, e.g. "alt+r"
record.maxSeconds 60 Recording cap in seconds (1..600)
record.autoSubmit false Submit the transcription as a user message (false = fill the draft)
stt.engine auto auto / web / funasr / whisper; auto prefers a configured local engine, then Web Speech
stt.language auto BCP-47 language or auto
stt.interim true Show interim transcriptions (Web Speech)
stt.funasr.url (none) FunASR inference endpoint; required when the engine is funasr
stt.whisper.modelPath (none) whisper.cpp model; required when the engine is whisper
tts.engine auto auto / browser / edge-tts / piper; auto prefers piper, then edge-tts, then the browser voice
tts.rate 0 Rate offset in percent (-50..50) for edge-tts/piper
tts.fallbackToBrowser true Fall back to the browser voice when a local engine fails
tts.piper.modelPath (none) piper voice model; required when the engine is piper
announce.enabled true Master switch for event announcements
announce.onTurnEnd / onApproval / onError true Which events are spoken
announce.messages.* "Turn complete." etc. Spoken phrases
interrupt true Talking stops current playback
maxSpeakChars 20000 Cap on the speak tool's text length (1..100000)
maxAudioCacheBytes 8388608 In-memory synthesized-audio cache cap (1 MiB..64 MiB)

Tools & surfaces

Surface Kind Notes
speak tool Speaks text aloud (browser/edge-tts/piper); per-call engine/voice overrides; canonical JSON outcome
mic button conversation.input.left slot Record → transcribe → fill draft (or submit); speak-to-interrupt on press
settings tab settings.plugins.tab (id talk) Engine/language/announcement switches; append-only save
talk:* Typert Remote status, audio, transcribe, applySettings, interrupt (host namespace)

Permissions & data

  • Permissions: the plugin stores nothing but an in-memory, byte-capped audio cache; microphone permission is browser-mediated. The settings tab only appends patch fragments to the profile with a timestamped backup — never rewrites the file.
  • Data: audio never enters the model context or the session log. The dsh-talk/speech event carries the utterance id, engine, reason, size, and sanitized text only. All display/log surfaces redact credentials, JWTs, bearer headers, and temp paths.
  • Network: only the engines you configure are contacted (edge-tts network synthesis, a FunASR endpoint); the browser voice and Web Speech stay on-device.

Security boundaries

  • Model-visible ⟺ logged — the model sees only the speak tool's canonical value; every utterance is reconstructable from the session log.
  • Approval announcements never block — the approval/request listener always calls next().
  • Sanitized output — credentials and temp audio paths never reach logs or displays.
  • Fail loud — invalid engines, out-of-range values, and engines configured without their required model/endpoint fail the mount.

Known limitations

  • Browser support: Web Speech and MediaRecorder are feature-detected; without them the mic button disables itself and host engines (FunASR/whisper.cpp) can still transcribe when configured.
  • Local engines are your install: edge-tts, piper, and whisper.cpp executables and models must be installed separately.
  • Recording format: the browser records with its native MediaRecorder codec; whisper.cpp may require a WAV-configured recorder or a server-side conversion for other formats.
  • Settings apply on reload: the settings tab appends to the profile patch; a profile reload (or web-app restart) activates the changes.

Development

pnpm install        # node ^22.19 || >=24
pnpm run typecheck  # tsc: src + tests against the local harness checkout
pnpm run typecheck:ci  # tsc against the published 0.1.0-rc.6 types (no paths)
pnpm test           # vitest: 45 tests, 7 suites
pnpm run build      # tsc declarations + tsdown bundles (lib/)
pnpm run verify:self-contained  # dependency specs resolve from the registry
pnpm run verify:artifacts       # built ESM faces + client ModuleLoader handshake
pnpm pack           # the published tarball

Topics

dsh, dsh-plugin, deepseek-harness, deepseek, cordis, voice, speech, tts, stt, speech-to-text, text-to-speech, microphone

Contributors

  • @PerryLink — creator and maintainer: speak pipeline, speech engines, mic recorder, event announcements, projection unit, and the five-language docs.

License

Apache License 2.0 © 2026 dsh-talk contributors

About

Voice-first session loop for DeepSeek Harness: a composer microphone button with browser/local speech-to-text (Web Speech, FunASR, whisper.cpp), a speak tool for text-to-speech replies (browser, edge-tts, piper), event announcements with mute, and speak-to-interrupt.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages