jelisaveta-talbot
|
3c3e009a67
|
supplier: TTS capability scaffolding (audio.synthesize.piper.v1)
Path-A foundation: extend the supplier service so the same on-chain
escrow lifecycle can serve a PiperTTS supplier alongside the existing
Ollama-backed chat one. Capability dispatch is boot-time; one process
serves one capability via a single advert.
Receipt mapping for TTS is committed inline:
- prompt_hash = sha256(canonical({text, voice, format, speed}))
- result_hash = sha256(audio_bytes)
- prompt_tokens / completion_tokens = 0 (off-chain only; Piper has no
token semantics, on-chain validator never reads these fields)
New / changed files
- supplier/src/piper.ts (new): mirror of ollama.ts. callPiper(...)
POSTs OpenAI-shape /v1/audio/speech, returns {audio: Uint8Array,
contentType, wallclock_ms}. Typed errors: piper_failure | piper_
timeout | piper_malformed (with a 64-byte minimum to catch upstream
"200 OK, body length 0" cold-start)
- supplier/src/config.ts: + CapabilityKind = "chat" | "tts", + piperUrl
/ piperTimeoutMs. CAPABILITY_KIND env defaults to "chat" so existing
chat suppliers keep booting unchanged
- supplier/src/jobs.ts: JobResponsePayload becomes a discriminated
union (ChatJobResponsePayload | TtsJobResponsePayload). TTS variant
carries audio_b64 + content_type + byte_length so the in-memory
store stays JSON-clean and the GET poll route returns audio without
binary content-type negotiation
- supplier/src/jobRunner.ts: + runTtsJob (parallels runChatJob with
same 7-step shape: setRunning -> upstream -> receipt -> buildSubmit
-> awaitTx -> complete -> finally release)
- supplier/src/server.ts: + makeTtsHandler (POST /v1/audio/synthesize)
+ makeGetTtsJobHandler (poll). createApp dispatches by config.
capabilityKind: TTS supplier exposes the audio routes only, chat
supplier exposes the chat routes only. The on-chain capability_id
check on every request is belt-and-braces
Tests
- tests/unit/supplier-piper.test.ts: 9 tests (request shape, success,
network throw, AbortError -> piper_timeout, too-small body ->
piper_malformed, missing content-type fallback)
- tests/unit/supplier-routes-tts.test.ts: 9 tests (capability-routed
mounting, all 400 validation paths, sanity that the route is reachable)
- tests/fixtures/supplier-side/sample-config.ts: + buildSampleTtsConfig
243 supplier tests passing; chat path behaviourally untouched.
|
2026-05-06 19:01:35 +02:00 |
|