dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
tts tool that turns text into an audio file through any OpenAI-compatible TTS backend.
Text-to-speech plugin for dsh: one tts tool that turns text into an audio
file (wav / mp3 / flac / aac / opus / pcm) through any OpenAI-compatible TTS
backend, so agents can voice their output without per-backend glue. The same
tool lists voices and models, probes the routes, and calls the backend's dev
phonemize endpoint.
| verb | network | what it does |
|---|---|---|
synth | yes | Synthesizes the requested speech. The tool writes the audio file to disk and runs container checks on the returned bytes. |
voices | yes | Lists the backend voices, optionally filtered. When the backend returns 404 to GET {baseURL}/audio/voices, the tool serves the static OpenAI table and marks source: static. |
providers | no | Lists the configured routes with their fields, the originating layer of each field, and the credential state. The verb reads the local configuration and makes no network request. |
models | maybe | Reports the model list of each route. A route with declared models reports the declared list from the config layer, and a route without declared models reports the live GET {baseURL}/models probe. |
status | yes | Probes each route: the GET {baseURL}/models listing plus the optional server-root GET /health liveness probe. |
phonemize | yes | Calls the backend's POST /dev/phonemize endpoint at the server root. A 404 or 405 response reports the endpoint as unsupported. |
Key synth behaviors:
voice argument is required, and there is no default: the voice set is
provider-specific. The available ids are listed by the voices verb.model, the tool uses the route's single declared
model. When a route declares no models, the tool resolves the model by a
live /models probe. When the declared or probed model list contains
several models, the call fails and lists the candidates.response_format argument defaults to wav, and the tool sends the
value verbatim.wav, and magic checks for the other formats
(pcm carries no container check). When the payload is not the claimed
container, the call fails and the tool keeps the file on disk. When the
container carries a known defect, for example the placeholder RIFF chunk
sizes (0xFFFFFFFF or 0x7FFFFFFF) some backends emit, the successful
document reports it in warnings.out, the output path is that argument (a file path, or
a directory marked by a trailing separator or by existing on disk). When the
call omits out, the tool writes the file to
<process.cwd()>/tts/<unixts>_<voice>.<ext>. The file extension comes from
the response_format value.speed and language arguments are sent verbatim, and only when the
call sets them.The plugin ships a dsh-tts skill. The skill is the full tool reference for
agent contexts: it carries the parameter table, the env contract, and the
error shapes.
dsh-tts is an out-of-tree plugin for a dsh profile. Install it with the dsh plugin command:
dsh plugin --profile <name> add dsh-tts
Configuration is layered: built-in defaults, the TTS_* env contract, a
cordis patch file, a dsh-tts settings section (see below); the plugin
creates no config or state files.
Providers are configured in any of four layers, lowest to highest priority;
the providers verb reports the originating layer of every field, so a
shadowed value is never silent:
api: openai-compatible),TTS_* env contract (static per process boot),dsh-tts and a config
object, or profile-level patches),dsh-tts: section in the user settings document
($DSH_HOME/settings.yaml), which the plugin re-reads on every call, so
settings edits apply without a restart.dsh-tts:
defaultProvider: local
providers:
local:
baseURL: http://<host>:<port>/v1
hosted:
baseURL: https://api.example.com/v1
apiKeyEnv: TTS_HOSTED_KEY
models: [kokoro-v2]
displayName: Hosted Speech
The env contract mirrors the config fields 1:1: TTS_DEFAULT_PROVIDER,
and per route <NAME> the variables TTS_PROVIDER_<NAME>_BASEURL,
TTS_PROVIDER_<NAME>_API, TTS_PROVIDER_<NAME>_APIKEYENV,
TTS_PROVIDER_<NAME>_HEADERS, TTS_PROVIDER_<NAME>_MODELS,
TTS_PROVIDER_<NAME>_DISPLAYNAME. The <NAME> segment is the route name
uppercased with - written as _. The headers value is a JSON object
string, and the models value is a comma-separated list of model ids. The
baseURL value is the OpenAI-compatible base URL including the /v1 prefix
(the same shape as an LLM provider base URL); the plugin appends
/audio/speech, /audio/voices, and /models to it verbatim, and it
addresses /health and /dev/phonemize at the server root, which it derives
by stripping a trailing /v1 from the base URL. The apiKeyEnv value is a
reference to an environment variable name, never a secret in config; per
request the value resolves from the process environment, then from
$DSH_HOME/.credentials.yaml.
// Synthesize with the default route and its single declared model.
{ "verb": "synth", "input": "hello world", "voice": "zf_xiaoxiao" }
// Pick a route, format, speed, and output location explicitly.
{ "verb": "synth", "provider": "hosted", "input": "the quick brown fox",
"voice": "zf_xiaoxiao", "response_format": "mp3", "speed": 1.1, "out": "/tmp/hi.mp3" }
// Find the voices by an id prefix filter.
{ "verb": "voices", "filter": "zf_" }
// Or by a case-insensitive substring over the id and name.
{ "verb": "voices", "query": "zf" }
// List what is configured, and where each field comes from.
{ "verb": "providers" }
// Probe the backend health (the live /models probe).
{ "verb": "status" }
// Ask the backend dev phonemize endpoint (a 404/405 response reports it as unsupported).
{ "verb": "phonemize", "text": "hello world", "language": "zh" }
A failing call returns a JSON document with an error message field, and the
message text identifies the failure.
X in the environment or add it to $DSH_HOME/.credentials.yaml._ and - as the same separator; the error lists the configured
names.provider argument explicitly, or
set TTS_DEFAULT_PROVIDER, or set the settings defaultProvider.status reports reachable: false, the error field carries the
cause; the probe uses a 15 s budget against GET {baseURL}/models.voices reports source: static, the backend answered 404 to
GET {baseURL}/audio/voices, and the tool returned the static OpenAI
table. The listed voice ids may not exist on that backend.out; the backend may return an unsupported container for the requested
response_format.pnpm install
pnpm run build # tsc -> lib/
pnpm run lint # eslint src/ test/
pnpm run selftest # in-process: HTTP stub + config matrix + container checks