Let voice mode TTS use the model and voice an OpenAI-compatible server serves (#6060)

* fix(server): accept voice and model names from self-hosted speech servers

features.voiceMode.tts.voice and TTS_VOICE were validated against the
OpenAI voice catalog, so a server whose voices live under other names
could not be configured at all: config.json failed to parse and an env
var threw inside the speech config resolver, which config.ts calls
without a catch, so the daemon refused to start. TTS_MODEL had the same
problem for model ids the server serves itself. Both are free-form now,
with model ids keeping their case because rosters use values like
kokoro-v1:Q8_0. Regenerate the config JSON schema.

* fix(server): send TTS voice names as written and keep the config schema current

A self-hosted OpenAI-compatible server owns its voice ids and their case, so
lowercasing the configured voice could turn a valid id into one the server
does not know. Keep the published config schema in its existing form and
change only the voice field.

Co-authored-by: khimaros <me@khimaros.com>

* fix(server): drop the TTS baseUrl from the init log

The configured baseUrl can carry a token in its query string, and logging
it is not needed to accept self-hosted voice and model names.

* test(server): await bounded worktree fixture cleanup on Windows

---------

Co-authored-by: khimaros <me@khimaros.com>
Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
This commit is contained in:
paseo-bot[bot]
2026-10-14 05:10:35 +02:00
committed by GitHub
co-authored by khimaros
parent a4b15455b7
commit a4f1df3aed
8 changed files with 65 additions and 19 deletions
+3 -2
View File
@@ -10,6 +10,7 @@ import {
type WorktreeConfig,
} from "./worktree";
import { execFileSync } from "child_process";
import { rm } from "node:fs/promises";
import {
mkdtempSync,
mkdirSync,
@@ -89,8 +90,8 @@ describe("paseo worktree manager", () => {
});
});
afterEach(() => {
rmSync(tempDir, { recursive: true, force: true });
afterEach(async () => {
await rm(tempDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
});
it("treats a worktree as paseo-owned even when its .git admin is missing", async () => {