Skip to content

Commit 2c9c84b

Browse files
committed
fix(webui): one runtime warning per card, with the install instructions
Two takes on the same warning landed on this branch: an aside shown on every transcribe.cpp card, and a badge plus note driven by whether the runtime is actually resolvable on this host. Together a card said the same thing twice, and the aside kept saying it after transcribe-cli was installed. Keep the host-driven one, which clears itself once the binary resolves and covers every engine rather than transcribe.cpp alone, and give it what the aside had that it lacked: the deployment.md link and the reminder that the runtime lives where the gateway runs, inside the container under Docker. DependencyStatus carries the URL so the link is catalog data, not markup. The Settings page keeps the aside: the engine picker offers transcribe.cpp before any model exists, so there is no card there to carry the warning.
1 parent b2881c0 commit 2c9c84b

5 files changed

Lines changed: 29 additions & 9 deletions

File tree

app/admin_queries.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@
1818
# The GGUF models in the catalog need a transcribe-cli this project never ships;
1919
# the tile names the build and the override so a missing binary is actionable.
2020
TRANSCRIBE_INSTALL_HINT = (
21-
"Build https://github.com/handy-computer/transcribe.cpp, then set "
22-
"VOCAGATEWAY_TRANSCRIBE_BINARY to its transcribe-cli"
21+
"Install transcribe-cli where the gateway runs, inside the container under "
22+
"Docker, and set VOCAGATEWAY_TRANSCRIBE_BINARY if it is not on PATH"
23+
)
24+
TRANSCRIBE_DOCS_URL = (
25+
"https://github.com/VocaHQ/vocagateway/blob/main/docs/deployment.md#install-transcribecpp"
2326
)
2427
PYTHON_ENGINE_INSTALL_HINT = "Install vocagateway[engines] or use the Docker image"
2528
# One engine paired with the single runtime it needs.
@@ -75,7 +78,11 @@ def entry_fields(self, engine: str) -> dict[str, str | None]:
7578
unmet = self.missing(engine)
7679
if unmet is None:
7780
return {}
78-
return {"runtime_requirement": unmet.name, "runtime_hint": unmet.install_hint}
81+
return {
82+
"runtime_requirement": unmet.name,
83+
"runtime_hint": unmet.install_hint,
84+
"runtime_docs_url": unmet.docs_url,
85+
}
7986

8087
def _build(self) -> list[_EngineRuntime]:
8188
is_mac = self.system.os_name == "Darwin"
@@ -109,6 +116,7 @@ def _binary_tiles(self, is_mac: bool) -> list[_EngineRuntime]:
109116
available=self.system.transcribe_cli_path is not None,
110117
path=self.system.transcribe_cli_path,
111118
install_hint=TRANSCRIBE_INSTALL_HINT,
119+
docs_url=TRANSCRIBE_DOCS_URL,
112120
),
113121
),
114122
]

app/schemas.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ class DependencyStatus(BaseModel):
9191
available: bool
9292
path: str | None = None
9393
install_hint: str | None = None
94+
# Set when a hint alone cannot carry the setup, as for a tool the project
95+
# does not ship and the operator has to build.
96+
docs_url: str | None = None
9497

9598

9699
class SystemStatus(BaseModel):
@@ -224,6 +227,7 @@ class AdminModelEntry(BaseModel):
224227
# weights are still correct, so the card warns rather than hiding the button.
225228
runtime_requirement: str | None = None
226229
runtime_hint: str | None = None
230+
runtime_docs_url: str | None = None
227231

228232

229233
class CustomDownloadRequest(BaseModel):

app/templates/models/model_card.html

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{% from "macros/icons.html" import active_label, info as info_icon %}
2-
{% from "macros/native_requirements.html" import transcribe_requirement %}
32

43
{% macro language_chips(names) %}{% for name in names %}<span class="model-language-chip">{{ name }}</span>{% endfor %}{% endmacro %}
54

@@ -73,9 +72,6 @@ <h4 title="{{ entry.label }}">{{ card.display_label }}</h4>
7372
<p class="model-blurb" title="{{ entry.description }}">
7473
{{ entry.description }}
7574
</p>
76-
{% if entry.engine == "transcribe.cpp" %}
77-
{{ transcribe_requirement() }}
78-
{% endif %}
7975
{% if entry.retired %}
8076
<p class="model-retirement-note muted small">
8177
Retired{% if entry.replacement_id %}; use {{ entry.replacement_id }}{% endif %}{% if entry.retirement_reason %}. {{ entry.retirement_reason }}{% endif %}
@@ -85,7 +81,12 @@ <h4 title="{{ entry.label }}">{{ card.display_label }}</h4>
8581
missing before the operator spends the bandwidth on them. The badge above
8682
names the requirement, so this line carries only how to satisfy it. #}
8783
{% if entry.runtime_requirement and entry.runtime_hint %}
88-
<p class="model-runtime-note small">Not installed yet &mdash; {{ entry.runtime_hint }}.</p>
84+
<p class="model-runtime-note small">
85+
Not installed yet &mdash; {{ entry.runtime_hint }}.
86+
{%- if entry.runtime_docs_url %}
87+
<a href="{{ entry.runtime_docs_url }}" target="_blank" rel="noopener noreferrer">
88+
Installation instructions</a>{% endif %}
89+
</p>
8990
{% endif %}
9091
</div>
9192
<div class="model-toolbar">

app/webui/styles.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,6 +1659,7 @@ html[data-theme="dark"] .family-models-label {
16591659
}
16601660
/* A model whose engine has no runtime on this host. Warn-coloured rather than
16611661
error-coloured: the weights are fine, only the CLI or package is absent. */
1662+
.model-runtime-note a { color: inherit; font-weight: 500; }
16621663
.model-runtime-note {
16631664
margin: 6px 0 0;
16641665
padding-left: 8px;

tests/test_transcribe_cpp.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import pytest
1010

11-
from app.admin_queries import TRANSCRIBE_INSTALL_HINT, _EngineRuntimes
11+
from app.admin_queries import TRANSCRIBE_DOCS_URL, TRANSCRIBE_INSTALL_HINT, _EngineRuntimes
1212
from app.catalog import DEFAULT_CATALOG
1313
from app.config import Settings
1414
from app.errors import EngineUnavailableError, LanguageUnsupportedError, TranscriptionProcessError
@@ -291,6 +291,7 @@ def test_engine_runtimes_names_the_missing_binary_only_while_it_is_absent(tmp_pa
291291
assert absent.entry_fields("transcribe.cpp") == {
292292
"runtime_requirement": "transcribe.cpp CLI",
293293
"runtime_hint": TRANSCRIBE_INSTALL_HINT,
294+
"runtime_docs_url": TRANSCRIBE_DOCS_URL,
294295
}
295296

296297
present = _EngineRuntimes(_system(transcribe_cli="/opt/transcribe-cli"), _settings(tmp_path))
@@ -332,15 +333,20 @@ def card(**runtime) -> str:
332333
warned = card(
333334
runtime_requirement="transcribe.cpp CLI",
334335
runtime_hint=TRANSCRIBE_INSTALL_HINT,
336+
runtime_docs_url=TRANSCRIBE_DOCS_URL,
335337
)
336338
assert "needs transcribe.cpp CLI" in warned
337339
assert "Not installed yet" in warned
338340
assert "VOCAGATEWAY_TRANSCRIBE_BINARY" in warned
341+
assert TRANSCRIBE_DOCS_URL in warned
342+
assert "Installation instructions" in warned
339343
# The weights are still correct, so the card must not block the download.
340344
assert "Download" in warned
341345

342346
ready = card()
343347
assert "needs transcribe.cpp CLI" not in ready
348+
# The old always-on aside warned even once the runtime was installed.
349+
assert "Installation instructions" not in ready
344350
assert "Not installed yet" not in ready
345351
assert "Download" in ready
346352

0 commit comments

Comments
 (0)