generated from Labyricorn/labyricorn-project-template
rebrand: rename VoiceBox to TalkBox throughout codebase
CI / frontend-quality (push) Canceled after 0s
CI / frontend-quality (push) Canceled after 0s
- All 'voicebox'/'Voicebox'/'VOICEBOX' strings replaced with 'talkbox'/'TalkBox'/'TALKBOX' - Port changed from 17493 to 17494 (avoids conflict with upstream VoiceBox) - MCP tool namespace: voicebox.* -> talkbox.* - App bundle ID: sh.voicebox.app -> com.talkbox.app - Binary names: voicebox-server -> talkbox-server, voicebox-mcp -> talkbox-mcp - Docker user/group: voicebox -> talkbox - Database: voicebox.db -> talkbox.db - Env vars: VOICEBOX_* -> TALKBOX_* - Asset files renamed: voicebox-logo.* -> talkbox-logo.*, etc. - External binaries in tauri.conf.json updated to talkbox-server/talkbox-mcp
This commit is contained in:
@@ -48,10 +48,10 @@ Search order — **first hit wins**:
|
||||
|
||||
| Platform | Path | Build type |
|
||||
|----------|------|------------|
|
||||
| macOS | `backend/dist/voicebox-server-cuda/voicebox-server-cuda` | onedir (CUDA, rarely on Mac) |
|
||||
| macOS | `backend/dist/voicebox-server` | onefile (CPU) |
|
||||
| Windows | `backend\dist\voicebox-server-cuda\voicebox-server-cuda.exe` | onedir (CUDA) |
|
||||
| Windows | `backend\dist\voicebox-server.exe` | onefile (CPU) |
|
||||
| macOS | `backend/dist/talkbox-server-cuda/talkbox-server-cuda` | onedir (CUDA, rarely on Mac) |
|
||||
| macOS | `backend/dist/talkbox-server` | onefile (CPU) |
|
||||
| Windows | `backend\dist\talkbox-server-cuda\talkbox-server-cuda.exe` | onedir (CUDA) |
|
||||
| Windows | `backend\dist\talkbox-server.exe` | onefile (CPU) |
|
||||
|
||||
If none exist, run `python backend/build_binary.py` and wait for it to finish (can take 5-20 min). Fail with a clear error if the build itself fails. `--skip-build` flag forces "error out if no binary" instead of building.
|
||||
|
||||
@@ -64,7 +64,7 @@ Mirrors Tauri's launch in `tauri/src-tauri/src/main.rs:369-388`:
|
||||
```
|
||||
|
||||
- **Port**: bind to `0` first in Python to grab a free port, then pass that number.
|
||||
- **Data dir**: `tempfile.mkdtemp(prefix="voicebox-e2e-")`. Deleted after the run unless `--keep-data-dir`. Profiles and generated WAVs land here.
|
||||
- **Data dir**: `tempfile.mkdtemp(prefix="talkbox-e2e-")`. Deleted after the run unless `--keep-data-dir`. Profiles and generated WAVs land here.
|
||||
- **Parent PID**: current Python PID — ensures the backend dies if the test crashes (watchdog in `server.py:102-224`).
|
||||
- **stdout/stderr**: tee to both a log file in `./results/server-<timestamp>.log` and a rolling in-memory buffer. On model failure, last 100 lines of the buffer are attached to that model's error record.
|
||||
|
||||
@@ -136,7 +136,7 @@ On timeout: cancel the SSE stream, mark the row `timeout`, and continue to the n
|
||||
```json
|
||||
{
|
||||
"platform": "darwin-arm64",
|
||||
"binary": "/abs/path/voicebox-server",
|
||||
"binary": "/abs/path/talkbox-server",
|
||||
"binary_size_mb": 612,
|
||||
"started_at": "2026-04-16T12:34:56Z",
|
||||
"finished_at": "...",
|
||||
@@ -160,7 +160,7 @@ On timeout: cancel the SSE stream, mark the row `timeout`, and continue to the n
|
||||
Companion `./results/e2e-<...>.md`:
|
||||
|
||||
```
|
||||
# Voicebox E2E — darwin-arm64 — 2026-04-16 12:34
|
||||
# TalkBox E2E — darwin-arm64 — 2026-04-16 12:34
|
||||
|
||||
| Engine | Size | Status | Elapsed | Error |
|
||||
|---------------------|------|--------|---------|-------|
|
||||
@@ -208,7 +208,7 @@ The script uses only stdlib + `httpx` (or `requests`) + `sseclient-py` — all a
|
||||
|
||||
- Always kill the spawned binary in a `try/finally`. On Windows, `taskkill /F /T` the whole tree (Tauri does the same).
|
||||
- Verify the port is free on shutdown (Tauri port-reuse check in `main.rs:114-186` could otherwise pick up a ghost).
|
||||
- Don't touch the user's HF cache by default — let the server use `HF_HUB_CACHE` / `VOICEBOX_MODELS_DIR`. Passing `--isolated-cache` would point both env vars at the tempdir for a true cold-start run (opt-in only; would re-download every time).
|
||||
- Don't touch the user's HF cache by default — let the server use `HF_HUB_CACHE` / `TALKBOX_MODELS_DIR`. Passing `--isolated-cache` would point both env vars at the tempdir for a true cold-start run (opt-in only; would re-download every time).
|
||||
|
||||
## Non-goals
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Test suite for Voicebox backend.
|
||||
Test suite for TalkBox backend.
|
||||
|
||||
This directory contains manual test scripts for debugging and validating
|
||||
progress tracking, model downloads, and generation functionality.
|
||||
|
||||
@@ -96,8 +96,8 @@ def find_binary() -> Optional[Path]:
|
||||
is_win = platform.system() == "Windows"
|
||||
exe = ".exe" if is_win else ""
|
||||
candidates = [
|
||||
DIST_DIR / "voicebox-server-cuda" / f"voicebox-server-cuda{exe}",
|
||||
DIST_DIR / f"voicebox-server{exe}",
|
||||
DIST_DIR / "talkbox-server-cuda" / f"talkbox-server-cuda{exe}",
|
||||
DIST_DIR / f"talkbox-server{exe}",
|
||||
]
|
||||
for c in candidates:
|
||||
if c.exists() and c.is_file():
|
||||
@@ -381,7 +381,7 @@ def write_reports(
|
||||
json_path.write_text(json.dumps(doc, indent=2))
|
||||
|
||||
lines = [
|
||||
f"# Voicebox E2E — {plat} — {started_at.strftime('%Y-%m-%d %H:%M UTC')}",
|
||||
f"# TalkBox E2E — {plat} — {started_at.strftime('%Y-%m-%d %H:%M UTC')}",
|
||||
"",
|
||||
f"Binary: `{binary}` ",
|
||||
f"Elapsed: {doc['elapsed_seconds']:.1f}s",
|
||||
@@ -424,8 +424,8 @@ def write_reports(
|
||||
# ── Main ─────────────────────────────────────────────────────────────
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
p = argparse.ArgumentParser(description="Voicebox E2E model generation test")
|
||||
p.add_argument("--binary", type=Path, help="Path to voicebox-server binary (overrides auto-detect)")
|
||||
p = argparse.ArgumentParser(description="TalkBox E2E model generation test")
|
||||
p.add_argument("--binary", type=Path, help="Path to talkbox-server binary (overrides auto-detect)")
|
||||
p.add_argument("--skip-build", action="store_true", help="Error if binary missing instead of building")
|
||||
p.add_argument(
|
||||
"--reference-wav",
|
||||
@@ -516,7 +516,7 @@ def main() -> int:
|
||||
print(f"[fixture] reference text: {ref_text!r}", flush=True)
|
||||
|
||||
# Tempdir + log path
|
||||
data_dir = Path(tempfile.mkdtemp(prefix="voicebox-e2e-"))
|
||||
data_dir = Path(tempfile.mkdtemp(prefix="talkbox-e2e-"))
|
||||
args.output_dir.mkdir(parents=True, exist_ok=True)
|
||||
ts = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
|
||||
log_path = args.output_dir / f"server-{ts}.log"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Tests for CORS origin restrictions.
|
||||
|
||||
Validates that the CORS middleware only allows known local origins
|
||||
and respects the VOICEBOX_CORS_ORIGINS environment variable.
|
||||
and respects the TALKBOX_CORS_ORIGINS environment variable.
|
||||
|
||||
Uses a minimal FastAPI app that mirrors the exact CORS configuration
|
||||
from backend/main.py, so tests run without heavy ML dependencies.
|
||||
@@ -32,8 +32,8 @@ def _build_app(env_origins: str = "") -> FastAPI:
|
||||
_default_origins = [
|
||||
"http://localhost:5173",
|
||||
"http://127.0.0.1:5173",
|
||||
"http://localhost:17493",
|
||||
"http://127.0.0.1:17493",
|
||||
"http://localhost:17494",
|
||||
"http://127.0.0.1:17494",
|
||||
"tauri://localhost",
|
||||
"https://tauri.localhost",
|
||||
]
|
||||
@@ -88,8 +88,8 @@ class TestCORSDefaultOrigins:
|
||||
@pytest.mark.parametrize("origin", [
|
||||
"http://localhost:5173",
|
||||
"http://127.0.0.1:5173",
|
||||
"http://localhost:17493",
|
||||
"http://127.0.0.1:17493",
|
||||
"http://localhost:17494",
|
||||
"http://127.0.0.1:17494",
|
||||
"tauri://localhost",
|
||||
"https://tauri.localhost",
|
||||
])
|
||||
@@ -121,7 +121,7 @@ class TestCORSDefaultOrigins:
|
||||
|
||||
|
||||
class TestCORSCustomOrigins:
|
||||
"""VOICEBOX_CORS_ORIGINS env var should extend the allowlist."""
|
||||
"""TALKBOX_CORS_ORIGINS env var should extend the allowlist."""
|
||||
|
||||
def test_custom_origin_allowed(self, client_with_custom_origins):
|
||||
headers = _get_with_origin(client_with_custom_origins, "https://custom.example.com")
|
||||
@@ -141,7 +141,7 @@ class TestCORSCustomOrigins:
|
||||
|
||||
|
||||
class TestCORSEnvVarParsing:
|
||||
"""Edge cases for VOICEBOX_CORS_ORIGINS parsing."""
|
||||
"""Edge cases for TALKBOX_CORS_ORIGINS parsing."""
|
||||
|
||||
def test_empty_env_var(self):
|
||||
app = _build_app("")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Tests for the voicebox.speak MCP tool's ``model_size`` plumbing (issue #884).
|
||||
"""Tests for the talkbox.speak MCP tool's ``model_size`` plumbing (issue #884).
|
||||
|
||||
The MCP speak path used to build its ``GenerationRequest`` without a
|
||||
``model_size``, so every agent-triggered generation silently fell back to the
|
||||
|
||||
@@ -45,7 +45,7 @@ class TestIsRocmFile:
|
||||
@pytest.mark.parametrize(
|
||||
"rel_path",
|
||||
[
|
||||
"voicebox-server-rocm.exe",
|
||||
"talkbox-server-rocm.exe",
|
||||
"_internal/python312.dll",
|
||||
"_internal/torch/lib/torch_cpu.dll",
|
||||
"_internal/torch/lib/c10.dll",
|
||||
@@ -68,8 +68,8 @@ class TestPackage:
|
||||
"""End-to-end split of a synthetic onedir into the two archives."""
|
||||
|
||||
def test_split_and_manifest(self, tmp_path):
|
||||
onedir = tmp_path / "voicebox-server-rocm"
|
||||
_write(onedir / "voicebox-server-rocm.exe")
|
||||
onedir = tmp_path / "talkbox-server-rocm"
|
||||
_write(onedir / "talkbox-server-rocm.exe")
|
||||
_write(onedir / "_internal" / "python312.dll")
|
||||
_write(onedir / "_internal" / "rocm_sdk" / "__init__.py")
|
||||
_write(onedir / "_internal" / "torch" / "lib" / "torch_cpu.dll")
|
||||
@@ -88,11 +88,11 @@ class TestPackage:
|
||||
out = tmp_path / "release-assets"
|
||||
package_rocm.package(onedir, out, "rocm7.2-v1", ">=2.9.0,<2.10.0")
|
||||
|
||||
server = out / "voicebox-server-rocm.tar.gz"
|
||||
server = out / "talkbox-server-rocm.tar.gz"
|
||||
libs = out / "rocm-libs-rocm7.2-v1.tar.gz"
|
||||
assert server.exists()
|
||||
assert libs.exists()
|
||||
assert (out / "voicebox-server-rocm.tar.gz.sha256").exists()
|
||||
assert (out / "talkbox-server-rocm.tar.gz.sha256").exists()
|
||||
assert (out / "rocm-libs-rocm7.2-v1.tar.gz.sha256").exists()
|
||||
|
||||
with tarfile.open(libs) as tar:
|
||||
@@ -106,15 +106,15 @@ class TestPackage:
|
||||
"_internal/_rocm_sdk_libraries_custom/lib/rocblas/library/TensileLibrary.dat"
|
||||
in lib_names
|
||||
)
|
||||
assert "voicebox-server-rocm.exe" in core_names
|
||||
assert "talkbox-server-rocm.exe" in core_names
|
||||
assert "_internal/torch/lib/torch_cpu.dll" in core_names
|
||||
assert "_internal/rocm_sdk/__init__.py" in core_names
|
||||
# Archives must be disjoint.
|
||||
assert lib_names.isdisjoint(core_names)
|
||||
|
||||
def test_empty_rocm_set_exits(self, tmp_path):
|
||||
onedir = tmp_path / "voicebox-server-rocm"
|
||||
_write(onedir / "voicebox-server-rocm.exe")
|
||||
onedir = tmp_path / "talkbox-server-rocm"
|
||||
_write(onedir / "talkbox-server-rocm.exe")
|
||||
_write(onedir / "_internal" / "torch" / "lib" / "torch_cpu.dll")
|
||||
|
||||
with pytest.raises(SystemExit):
|
||||
|
||||
@@ -177,7 +177,7 @@ def score(
|
||||
# ── Runner ────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
DEFAULT_PORTS = (8000, 8765, 8899, 17493)
|
||||
DEFAULT_PORTS = (8000, 8765, 8899, 17494)
|
||||
THROWAWAY_PROFILE_PREFIX = "personality-harness-"
|
||||
KOKORO_PROBE_VOICE = "af_heart"
|
||||
"""Any valid kokoro voice id works — compose never calls into TTS, it
|
||||
@@ -204,7 +204,7 @@ def detect_backend_port(hint: Optional[int]) -> int:
|
||||
except Exception:
|
||||
continue
|
||||
raise SystemExit(
|
||||
"No running Voicebox backend found. Start it (`python backend/main.py`) "
|
||||
"No running TalkBox backend found. Start it (`python backend/main.py`) "
|
||||
f"or pass --port. Tried: {candidates}"
|
||||
)
|
||||
|
||||
|
||||
@@ -252,7 +252,7 @@ async def test_full_integration():
|
||||
async def main():
|
||||
"""Run all tests."""
|
||||
print("\n" + "=" * 60)
|
||||
print("Voicebox Progress Tracking Test Suite")
|
||||
print("TalkBox Progress Tracking Test Suite")
|
||||
print("=" * 60)
|
||||
|
||||
results = []
|
||||
|
||||
@@ -15,7 +15,7 @@ Usage:
|
||||
python backend/tests/test_refinement_samples.py
|
||||
|
||||
# Hit a non-default port (auto-detected via /health probe when omitted):
|
||||
python backend/tests/test_refinement_samples.py --port 17493
|
||||
python backend/tests/test_refinement_samples.py --port 17494
|
||||
|
||||
# Only test one model size:
|
||||
python backend/tests/test_refinement_samples.py --model 4B
|
||||
@@ -316,7 +316,7 @@ def score(sample: Sample, model: str, refined: str, latency_ms: int) -> Scorecar
|
||||
# ── Runner ────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
DEFAULT_PORTS = (8000, 8765, 8899, 17493)
|
||||
DEFAULT_PORTS = (8000, 8765, 8899, 17494)
|
||||
|
||||
|
||||
def detect_backend_port(hint: Optional[int]) -> int:
|
||||
@@ -339,7 +339,7 @@ def detect_backend_port(hint: Optional[int]) -> int:
|
||||
except Exception:
|
||||
continue
|
||||
raise SystemExit(
|
||||
"No running Voicebox backend found. Start it (`python backend/main.py`) "
|
||||
"No running TalkBox backend found. Start it (`python backend/main.py`) "
|
||||
f"or pass --port. Tried: {candidates}"
|
||||
)
|
||||
|
||||
@@ -407,7 +407,7 @@ def format_report(cards: list[Scorecard]) -> str:
|
||||
def main() -> int:
|
||||
ap = argparse.ArgumentParser(description=__doc__)
|
||||
ap.add_argument("--port", type=int, default=None,
|
||||
help="Voicebox backend port (auto-detected if omitted)")
|
||||
help="TalkBox backend port (auto-detected if omitted)")
|
||||
ap.add_argument("--model", choices=("0.6B", "1.7B", "4B"), action="append",
|
||||
help="Refinement model size(s) to test (repeat to run several)")
|
||||
ap.add_argument("--json", type=Path, default=None,
|
||||
|
||||
@@ -35,7 +35,7 @@ class TestRocmBuildArgs:
|
||||
|
||||
def test_binary_name(self, captured_args):
|
||||
idx = captured_args.index("--name")
|
||||
assert captured_args[idx + 1] == "voicebox-server-rocm"
|
||||
assert captured_args[idx + 1] == "talkbox-server-rocm"
|
||||
|
||||
def test_pack_mode_is_onedir(self, captured_args):
|
||||
assert "--onedir" in captured_args
|
||||
@@ -91,8 +91,8 @@ class TestRocmBuildE2E:
|
||||
backend_dir = Path(__file__).parent.parent
|
||||
build_script = backend_dir / "build_binary.py"
|
||||
dist_dir = backend_dir / "dist"
|
||||
binary_dir = dist_dir / "voicebox-server-rocm"
|
||||
binary_exe = binary_dir / "voicebox-server-rocm.exe"
|
||||
binary_dir = dist_dir / "talkbox-server-rocm"
|
||||
binary_exe = binary_dir / "talkbox-server-rocm.exe"
|
||||
|
||||
# Clean previous dist if it exists to ensure a fresh build
|
||||
if binary_dir.exists():
|
||||
|
||||
@@ -40,7 +40,7 @@ def fake_tar_gz():
|
||||
buf = BytesIO()
|
||||
with tarfile.open(fileobj=buf, mode="w:gz") as tar:
|
||||
data = b"fake binary content"
|
||||
info = tarfile.TarInfo(name="voicebox-server-rocm.exe")
|
||||
info = tarfile.TarInfo(name="talkbox-server-rocm.exe")
|
||||
info.size = len(data)
|
||||
tar.addfile(info, BytesIO(data))
|
||||
buf.seek(0)
|
||||
@@ -137,18 +137,18 @@ async def test_download_rocm_binary_progress_reporting(mock_backends_dir, fake_t
|
||||
libs_sha = hashlib.sha256(fake_tar_gz).hexdigest()
|
||||
|
||||
responses = {
|
||||
"https://github.com/jamiepine/voicebox/releases/download/v0.2.3/voicebox-server-rocm.tar.gz": FakeResponse(
|
||||
"https://github.com/jamiepine/talkbox/releases/download/v0.2.3/talkbox-server-rocm.tar.gz": FakeResponse(
|
||||
content=fake_tar_gz,
|
||||
headers={"content-length": str(len(fake_tar_gz))},
|
||||
),
|
||||
"https://github.com/jamiepine/voicebox/releases/download/v0.2.3/voicebox-server-rocm.tar.gz.sha256": FakeResponse(
|
||||
content=f"{server_sha} voicebox-server-rocm.tar.gz\n".encode(),
|
||||
"https://github.com/jamiepine/talkbox/releases/download/v0.2.3/talkbox-server-rocm.tar.gz.sha256": FakeResponse(
|
||||
content=f"{server_sha} talkbox-server-rocm.tar.gz\n".encode(),
|
||||
),
|
||||
f"https://github.com/jamiepine/voicebox/releases/download/v0.2.3/rocm-libs-{rocm.ROCM_LIBS_VERSION}.tar.gz": FakeResponse(
|
||||
f"https://github.com/jamiepine/talkbox/releases/download/v0.2.3/rocm-libs-{rocm.ROCM_LIBS_VERSION}.tar.gz": FakeResponse(
|
||||
content=fake_tar_gz,
|
||||
headers={"content-length": str(len(fake_tar_gz))},
|
||||
),
|
||||
f"https://github.com/jamiepine/voicebox/releases/download/v0.2.3/rocm-libs-{rocm.ROCM_LIBS_VERSION}.tar.gz.sha256": FakeResponse(
|
||||
f"https://github.com/jamiepine/talkbox/releases/download/v0.2.3/rocm-libs-{rocm.ROCM_LIBS_VERSION}.tar.gz.sha256": FakeResponse(
|
||||
content=f"{libs_sha} rocm-libs.tar.gz\n".encode(),
|
||||
),
|
||||
}
|
||||
@@ -160,7 +160,7 @@ async def test_download_rocm_binary_progress_reporting(mock_backends_dir, fake_t
|
||||
|
||||
# Verify extraction
|
||||
rocm_dir = rocm.get_rocm_dir()
|
||||
assert (rocm_dir / "voicebox-server-rocm.exe").exists()
|
||||
assert (rocm_dir / "talkbox-server-rocm.exe").exists()
|
||||
|
||||
# Verify manifest written
|
||||
manifest_path = rocm.get_rocm_libs_manifest_path()
|
||||
@@ -177,13 +177,13 @@ async def test_download_rocm_binary_progress_reporting(mock_backends_dir, fake_t
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_is_rocm_active(mock_backends_dir, monkeypatch):
|
||||
monkeypatch.setenv("VOICEBOX_BACKEND_VARIANT", "rocm")
|
||||
monkeypatch.setenv("TALKBOX_BACKEND_VARIANT", "rocm")
|
||||
assert rocm.is_rocm_active() is True
|
||||
|
||||
monkeypatch.setenv("VOICEBOX_BACKEND_VARIANT", "cpu")
|
||||
monkeypatch.setenv("TALKBOX_BACKEND_VARIANT", "cpu")
|
||||
assert rocm.is_rocm_active() is False
|
||||
|
||||
monkeypatch.delenv("VOICEBOX_BACKEND_VARIANT", raising=False)
|
||||
monkeypatch.delenv("TALKBOX_BACKEND_VARIANT", raising=False)
|
||||
assert rocm.is_rocm_active() is False
|
||||
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@ class TestRocmRequirements:
|
||||
|
||||
@pytest.mark.timeout(900)
|
||||
@pytest.mark.skipif(
|
||||
not os.environ.get("VOICEBOX_TEST_ROCM_INSTALL"),
|
||||
reason="Set VOICEBOX_TEST_ROCM_INSTALL=1 to run the heavy install test",
|
||||
not os.environ.get("TALKBOX_TEST_ROCM_INSTALL"),
|
||||
reason="Set TALKBOX_TEST_ROCM_INSTALL=1 to run the heavy install test",
|
||||
)
|
||||
def test_rocm_torch_installs_and_detects_amd(self, backend_dir):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user