Repository navigation
feat: add BreezeBlue TTS extension - #2379
TiagoAgora wants to merge 3 commits into
Conversation
Add breezeblue_tts_python (AsyncTTS2HttpExtension) for BreezeBlue's HTTP
streaming API (POST /v1/text-to-speech/{voice_id}/stream).
- stream raw PCM16 24 kHz mono straight through, holding back a trailing odd
byte so a sample is never split across chunks
- send only whitelisted request fields: the API rejects unknown ones with a
422, e.g. the playground's generic sample_rate
- split text over the 1000 char per-request cap at sentence boundaries, since
the base class does not chunk
- retry 502/503/504 before any audio; map 401/403 and malformed-key 422 to an
invalid-key error; reject non-audio 200 responses
- cancel() closes the in-flight response and ends the stream with a flush
- extension-local tests for config, client and adapter events (audio-end
accounting, errors, cancellation, metrics, state machine)
- document BREEZE_API_KEY and BREEZE_TTS_VOICE_ID, add the extension to the
guarder fixed-sample-rate list, and record the gotchas in docs/ai
|
[P1] Redact authentication headers before logging the configuration ai_agents/agents/ten_packages/extension/breezeblue_tts_python/config.py:120–124 Header-based authentication is explicitly supported by [P1] Attach the required guarder evidence before merging the new extension ai_agents/agents/ten_packages/extension/breezeblue_tts_python/manifest.json:1–4 This extension is absent from the merge base, so the new-extension guarder evidence gate applies. The PR body reports 52 passed / 19 skipped at the current HEAD, but no owner/workflow evidence comment supplies the required result screenshot or a downloadable PCM output. This is a merge blocker under [P2] Make cancellation interrupt requests awaiting response headers ai_agents/agents/ten_packages/extension/breezeblue_tts_python/breezeblue_tts.py:135–138 If a flush arrives while connecting or waiting for response headers, [P2] Put the flush test credentials inside params ai_agents/agents/ten_packages/extension/breezeblue_tts_python/tests/test_basic.py:335–338
[P2] Cover request ownership and abnormal completion in the local suite ai_agents/agents/ten_packages/extension/breezeblue_tts_python/tests/test_audio_end.py:211–213 The controlled-clock assertion covers success only; partial-error and no-audio tests omit |
|
Guarder evidence for breezeblue_tts_python:
|
pylint reads the pydantic Field attributes (params, headers) as FieldInfo and reports E1101, which fails the lint step of the agents CI. Replace the inline pragmas, which black moves off the flagged line, with one scoped disable per config method. No behaviour change.
|
Note on the guarder evidence above The guarder run was done at
|
|
[P1] Redact authentication headers before logging configuration ai_agents/agents/ten_packages/extension/breezeblue_tts_python/config.py:115–119 Header authentication is explicitly accepted by [P1] Refresh the guarder evidence for the current HEAD ai_agents/agents/ten_packages/extension/breezeblue_tts_python/manifest.json:1–4 The attached screenshot and downloadable PCM are accessible, and the archive contains a non-empty PCM file. However, they document [P2] Interrupt cancellation while waiting for response headers ai_agents/agents/ten_packages/extension/breezeblue_tts_python/breezeblue_tts.py:135–137 When a flush arrives during connection establishment or response-header wait, [P2] Initialize the flush test with valid nested credentials ai_agents/agents/ten_packages/extension/breezeblue_tts_python/tests/test_basic.py:335–338 These top-level credentials are ignored by the config model, leaving [P2] Cover abnormal completion and request ownership in adapter tests ai_agents/agents/ten_packages/extension/breezeblue_tts_python/tests/test_audio_end.py:211–213 The sole |
|
[P1] Redact credentials in header-based auth before logging the config [P1] Guarder evidence does not match the current PR HEAD [P2] Flush cannot interrupt a request still waiting for response headers [P2] No independent TTFB hook is registered for this extension |
|
[P1] Redact authentication headers before logging configuration ai_agents/agents/ten_packages/extension/breezeblue_tts_python/config.py:115–119
[P1] Refresh the required guarder evidence at the current HEAD ai_agents/agents/ten_packages/extension/breezeblue_tts_python/manifest.json:1–4 The owner's screenshot and downloadable archive are accessible, and the archive contains a non-empty PCM file, but both document [P2] Interrupt cancellation while waiting for response headers ai_agents/agents/ten_packages/extension/breezeblue_tts_python/breezeblue_tts.py:135–137 If a flush arrives during connection establishment or response-header wait, [P2] Initialize the flush test with valid nested credentials ai_agents/agents/ten_packages/extension/breezeblue_tts_python/tests/test_basic.py:335–338 These top-level credentials are ignored by the config model, leaving [P2] Complete the mandatory lifecycle and termination assertions ai_agents/agents/ten_packages/extension/breezeblue_tts_python/tests/test_audio_end.py:211–213 Only success asserts [P2] Register an independent TTFB observer for the HTTP transport ai_agents/agents/ten_packages/extension/breezeblue_tts_python/extension.py:17 The adapter uses HTTP streaming, but the guarder's |

Summary
Adds
breezeblue_tts_python, a TTS extension for BreezeBlue built onAsyncTTS2HttpExtension. It uses the HTTP streaming endpoint (POST /v1/text-to-speech/{voice_id}/stream).sample_rate).max_text_lengthis configurable for accounts with a higher cap.cancel()closes the in-flight response and the stream ends with a flush.voice_id,model_id,language_code,instructions,speed,volume,guidance_scaleanduse_speaker_boost.Other changes:
.env.example:BREEZE_API_KEYandBREEZE_TTS_VOICE_ID.tests/bin/start: add the extension to the fixed-sample-rate list.docs/ai: gotchas for strict request schemas, unchunked text and PCM16 passthrough.Not in this PR
Test plan
Extension-local tests: 64 pass (config, client, and adapter-level events: audio-end accounting, errors, cancellation, metrics, state machine). A few deliberate client bugs were confirmed to fail the matching tests.
Real API: voice listing, English, Chinese, the multilingual model,
speed/volume, long text (split into two requests, onetts_audio_end).Full TTS guarder, default config, against the live API at commit
cc6fc4d4e:The skips are capability-based (connection status is WebSocket-only, no subtitle alignment, and checks for other vendors' hooks).
A guarder screenshot and the downloadable PCM output (24000 Hz, 16-bit signed little-endian, mono) will be attached in a comment on this PR.