Files
VoiceStudio/tests/test_worker_capabilities_downloaded.py
T
velixio aa1d739843 feat(workers): dubbing goes remote, and the protocol stops lying to old workers
The remote-GPU line, verified on hardware rather than asserted.

**Dubbing renders on the worker.** dub_generate.py dispatches the coarse
`dub_segments` operation through the gateway, following the audiobook
pattern: per-unit local fallback after consecutive remote failures, one
aggregated notice rather than one per segment. A 40-minute dub that loses
its worker at segment 200 degrades instead of producing 200 error rows.

**An out-of-date worker is now refused by name.** This was the worst
defect in the plan and it was silent: an un-upgraded worker registered
cleanly, then ignored `inputs` and rendered a clone with NO reference
audio — returned as success. A plausible wrong result with nothing
anywhere to surface it. Workers now declare features, and one missing
them is turned away with the features named and `no task was run`.
Verified live: a worker one commit behind was correctly refused.

**"Offline" and "cannot run this" are different facts.** Asking a live
worker for an engine it lacks answered "is offline or cannot be reached.
Wake the selected worker" — while that worker reported ready, one free
slot and 3.6 ms latency. The user was sent to wake a machine that was
already awake. The scheduler now distinguishes absent from present-but-
incapable, and names the engine rather than the operation, because the
engine is the thing a user can install.

**An engine with no catalog entry is no longer hidden.** A `repo_ids`
non-emptiness check had been implemented as a runtime filter, so a worker
silently refused to advertise any engine lacking a models.yaml entry —
which is four registered engines, including CosyVoice. Users with those
already installed would have lost remote support with only a log line.
Empty `repo_ids` now means "not downloadable here", never "not runnable".

**And a script so this stops being done by hand.**
scripts/verify-remote-worker.sh runs the per-phase acceptance checks
against a live worker, non-destructively. Its preconditions are the
mistakes that cost the most time: exactly one listener on the control
port (two instances silently shared it), and never detecting the worker
with a pgrep pattern that matches the ssh shell running it.

Its first real run found the dubbing picker claiming remote placement.
That turned out to be the CHECK being stale, not the picker — the port
had landed since it was written. It now asserts self-consistency instead:
the picker may claim remote only for an operation the control plane
actually advertises as remotely producible, which cannot rot the next
time an op is ported.

Backend 5291 passed, frontend 1812 passed. Acceptance script: no
automated failures across Phases 4-8 on an RTX 4090. Four checks remain
MANUAL by design — true airplane mode, concurrent downloads, killing a
worker mid-audiobook, and the model-list UI — and are reported as
unverified rather than passed.
2026-08-11 17:39:46 +05:30

84 lines
3.6 KiB
Python

from worker import capabilities
def test_downloaded_uses_shared_cache_helpers(monkeypatch):
monkeypatch.setattr(capabilities, "repo_ids_for", lambda _entry: ["org/model"])
monkeypatch.setattr(capabilities, "_resident_engine_ids", lambda: set())
monkeypatch.setattr("core.device_caps.detect_host_caps", lambda: None)
monkeypatch.setattr("services.tts_backend.list_backends", lambda: [{
"id": "omnivoice", "available": True, "routing_status": "accelerated"
}])
monkeypatch.setattr("api.routers.setup.models.is_cached", lambda _repo: False)
row = capabilities.discover(include_unavailable=True)[0]
assert row["downloaded"] is False
assert row["repo_ids"] == ["org/model"]
def test_engine_without_a_catalog_repo_is_advertised_and_schedulable(monkeypatch):
"""Missing download metadata must not hide an already-working engine."""
monkeypatch.setattr(capabilities, "repo_ids_for", lambda _entry: [])
monkeypatch.setattr(capabilities, "_resident_engine_ids", lambda: set())
monkeypatch.setattr("core.device_caps.detect_host_caps", lambda: None)
monkeypatch.setattr("services.tts_backend.list_backends", lambda: [{
"id": "omnivoice", "available": True, "routing_status": "accelerated"
}])
discovered = capabilities.discover()
assert [row["engine"] for row in discovered] == ["omnivoice"]
assert discovered[0]["repo_ids"] == []
from worker.pool import ConnectedWorker
from worker.registry import RemoteWorker
worker = ConnectedWorker(
record=RemoteWorker(
id="worker-1",
name="worker",
key_id="key-1",
public_key=b"key",
capabilities=discovered,
consent_granted_at=1.0,
),
session=None,
epoch=1,
capacity=None,
connected_at=1.0,
last_heartbeat_at=1.0,
)
assert worker.record.schedulable is True
assert worker.supports("omnivoice", "omnivoice:default", "tts") is True
def test_hf_downloadable_engine_always_names_a_repository(monkeypatch):
"""A positive missing-weights answer must carry an HF download target."""
monkeypatch.setattr(capabilities, "repo_ids_for", lambda _entry: ["org/model"])
monkeypatch.setattr(capabilities, "_resident_engine_ids", lambda: set())
monkeypatch.setattr("core.device_caps.detect_host_caps", lambda: None)
monkeypatch.setattr("services.tts_backend.list_backends", lambda: [{
"id": "omnivoice", "available": True, "routing_status": "accelerated"
}])
monkeypatch.setattr("api.routers.setup.models.is_cached", lambda _repo: False)
for row in capabilities.discover():
if row["downloaded"] is False:
assert row["repo_ids"], "HF-downloadable capabilities need a repository"
def test_download_probe_fails_open_when_cache_is_inconclusive(monkeypatch):
monkeypatch.setattr("api.routers.setup.models.is_cached", lambda _repo: (_ for _ in ()).throw(OSError()))
assert capabilities._downloaded(["user/managed-model"]) is True
def test_unavailable_engine_is_reported_when_requested(monkeypatch):
monkeypatch.setattr(capabilities, "repo_ids_for", lambda _entry: [])
monkeypatch.setattr(capabilities, "_resident_engine_ids", lambda: set())
monkeypatch.setattr("core.device_caps.detect_host_caps", lambda: None)
monkeypatch.setattr("services.tts_backend.list_backends", lambda: [{
"id": "indextts2", "available": False, "routing_status": "unavailable"
}])
assert capabilities.discover() == []
assert capabilities.discover(include_unavailable=True)[0]["engine"] == "indextts2"