From b21ff3e6c96c795df3cc08ad991b75f5ff82b600 Mon Sep 17 00:00:00 2001 From: Myka Date: Tue, 17 Feb 2026 13:03:56 +0300 Subject: [PATCH] fix(voice/tts): use /health endpoint for Chatterbox availability check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /v1/models returns 404 on Chatterbox — use /health instead. All other backends keep using /v1/models. --- pkg/voice/kokoro.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pkg/voice/kokoro.go b/pkg/voice/kokoro.go index e42269567..b58fd393e 100644 --- a/pkg/voice/kokoro.go +++ b/pkg/voice/kokoro.go @@ -201,19 +201,25 @@ func (s *KokoroSynthesizer) Synthesize(ctx context.Context, text string) (string return tmpFile.Name(), nil } -// IsAvailable checks if the Kokoro TTS server is reachable. +// IsAvailable checks if the TTS server is reachable. +// Chatterbox uses /health; all others use /v1/models. func (s *KokoroSynthesizer) IsAvailable() bool { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - req, err := http.NewRequestWithContext(ctx, "GET", s.apiBase+"/v1/models", nil) + endpoint := "/v1/models" + if s.isChatterbox() { + endpoint = "/health" + } + + req, err := http.NewRequestWithContext(ctx, "GET", s.apiBase+endpoint, nil) if err != nil { return false } resp, err := s.httpClient.Do(req) if err != nil { - logger.DebugCF("voice", "Kokoro TTS health check failed", map[string]interface{}{ + logger.DebugCF("voice", "TTS health check failed", map[string]interface{}{ "error": err.Error(), }) return false @@ -221,9 +227,10 @@ func (s *KokoroSynthesizer) IsAvailable() bool { defer resp.Body.Close() available := resp.StatusCode == http.StatusOK - logger.DebugCF("voice", "Kokoro TTS availability", map[string]interface{}{ + logger.DebugCF("voice", "TTS availability", map[string]interface{}{ "available": available, "status_code": resp.StatusCode, + "endpoint": endpoint, }) return available }