diff options
Diffstat (limited to 'app/backends')
| -rw-r--r-- | app/backends/__init__.py | 9 | ||||
| -rwxr-xr-x | app/backends/audiocpp.py | 11 | ||||
| -rwxr-xr-x | app/backends/faster.py | 9 | ||||
| -rw-r--r-- | app/backends/qwen.py | 22 | ||||
| -rw-r--r-- | app/backends/servers.py | 16 |
5 files changed, 51 insertions, 16 deletions
diff --git a/app/backends/__init__.py b/app/backends/__init__.py index ed772d4..9facd13 100644 --- a/app/backends/__init__.py +++ b/app/backends/__init__.py @@ -55,6 +55,13 @@ class BackendStatus: start the server, derived from SERVERS by ``format_launch_hint``. SERVERS is the machine-usable list of server processes the hub can start/stop (empty when the backend is not yet configured). + + MANAGED says a running server was started by this tool: ``servers`` + contains a spec whose pid file still names a live process (see + ``servers.manages``); when RUNNING but not MANAGED the hub tags the + status "[remote]". RUNNING_MODELS names which of a multi-server + backend's models answered (qwen: "Base" and/or "CustomVoice"), shown + in parentheses in the hub's status table. """ key: str label: str @@ -64,6 +71,8 @@ class BackendStatus: details: List[str] = field(default_factory=list) launch_hint: str = "" servers: List[ServerSpec] = field(default_factory=list) + managed: bool = False + running_models: List[str] = field(default_factory=list) @property def ready(self) -> bool: diff --git a/app/backends/audiocpp.py b/app/backends/audiocpp.py index 2368ce7..673d344 100755 --- a/app/backends/audiocpp.py +++ b/app/backends/audiocpp.py @@ -47,6 +47,7 @@ from backends import ( ServerSpec, common, format_launch_hint, + servers, ) from backends.common import ( APP_DIR, @@ -1712,11 +1713,11 @@ def detect() -> BackendStatus: details.append("not built — run setup to build audiocpp_server") server_json = checkout / "server.json" configured = server_json.exists() - servers: List[ServerSpec] = [] + specs: List[ServerSpec] = [] if configured: details.append(f"config: {server_json}") if built: - servers = [ServerSpec( + specs = [ServerSpec( "audiocpp", config.AUDIOCPP_API_URL, [str(binary), "--config", str(server_json)])] else: @@ -1724,12 +1725,12 @@ def detect() -> BackendStatus: f"audiocpp_server --config {server_json}") else: details.append("no server.json — run setup to configure models") - if servers: - launch = format_launch_hint(servers) + if specs: + launch = format_launch_hint(specs) return BackendStatus("audiocpp", "audio.cpp", installed=built, configured=configured, running=running, details=details, launch_hint=launch, - servers=servers) + servers=specs, managed=servers.manages(specs)) configure_actions: List[ConfigureAction] = [ diff --git a/app/backends/faster.py b/app/backends/faster.py index 0d34a0f..77b9c8a 100755 --- a/app/backends/faster.py +++ b/app/backends/faster.py @@ -31,6 +31,7 @@ from backends import ( common, envs, format_launch_hint, + servers, ) from backends.common import ( APP_DIR, @@ -356,18 +357,18 @@ def detect() -> BackendStatus: details.append(f"voices: {voices_json}" if voices_json.exists() else "no voices.json — run setup to create one") launch = "" - servers: List[ServerSpec] = [] + specs: List[ServerSpec] = [] if cloned and voices_json.exists(): argv = [str(envs.env_python()), str(_checkout() / "examples" / "openai_server.py"), "--voices", str(voices_json), "--port", str(_config_port())] - servers = [ServerSpec("faster", config.FASTER_API_URL, argv)] - launch = format_launch_hint(servers) + specs = [ServerSpec("faster", config.FASTER_API_URL, argv)] + launch = format_launch_hint(specs) return BackendStatus("faster", "faster-qwen3-tts", installed=installed and cloned, configured=configured, running=running, details=details, launch_hint=launch, - servers=servers) + servers=specs, managed=servers.manages(specs)) def _run_voices_only_tui() -> int: diff --git a/app/backends/qwen.py b/app/backends/qwen.py index 21280a0..64f3996 100644 --- a/app/backends/qwen.py +++ b/app/backends/qwen.py @@ -27,6 +27,7 @@ from backends import ( common, envs, format_launch_hint, + servers, ) from converter import config from ui import tui @@ -215,10 +216,15 @@ def detect() -> BackendStatus: installed = _is_installed() custom_port = _config_port(config.QWEN_API_URL, DEFAULT_CUSTOM_PORT) clone_port = _config_port(config.CLONE_API_URL, DEFAULT_CLONE_PORT) - # Running when either server is up — CustomVoice (speaker mode) or Base - # (voice clone) each suffice for a conversion on their own. - running = (common.server_running(config.QWEN_API_URL) - or common.server_running(config.CLONE_API_URL)) + # Probe each port separately: whichever answers names the running + # model — CustomVoice (speaker mode) or Base (voice clone); either + # suffices for a conversion on its own. + custom_up = common.server_running(config.QWEN_API_URL) + clone_up = common.server_running(config.CLONE_API_URL) + running = custom_up or clone_up + running_models = [name for name, up in + (("Base", clone_up), ("CustomVoice", custom_up)) + if up] details: List[str] = [] details.append("pip: installed" if installed else "not installed — run setup to pip install qwen-tts") @@ -226,7 +232,7 @@ def detect() -> BackendStatus: details.append(f"Base (clone) port: {clone_port}") details.append(f"speaker: {config.SPEAKER}") demo = str(envs.env_script("qwen-tts-demo")) - servers = [ + specs = [ ServerSpec("qwen-custom", config.QWEN_API_URL, [demo, QWEN_CUSTOMVOICE_MODEL, "--ip", "127.0.0.1", "--port", str(custom_port)]), @@ -237,8 +243,10 @@ def detect() -> BackendStatus: return BackendStatus("qwen", "qwen-tts", installed=installed, configured=installed, running=running, details=details, - launch_hint=format_launch_hint(servers), - servers=servers) + launch_hint=format_launch_hint(specs), + servers=specs, + managed=servers.manages(specs), + running_models=running_models) configure_actions: List[ConfigureAction] = [ diff --git a/app/backends/servers.py b/app/backends/servers.py index a5a6829..63f37ce 100644 --- a/app/backends/servers.py +++ b/app/backends/servers.py @@ -233,6 +233,22 @@ def stop(name: str) -> bool: return killed +def manages(specs) -> bool: + """True when any SPEC in the list was started (and is kept alive) by us. + + A server counts as ours when ``start`` recorded a pid file for it and + that pid is still alive — the same ownership rule ``stop`` applies + before refusing ("not started by this tool"). Used by the backends' + ``detect()`` so the hub's status table can tag an up server as + "[remote]" when it was launched outside this tool. + """ + for spec in specs: + pid = pid_for(spec.name) + if pid is not None and _pid_alive(pid): + return True + return False + + def pid_for(name: str): """Return the recorded pid for NAME, or None when no pid file exists.""" pid_file = _pid_path(name) |
