super-tts-daemon/src/daemon/http/v1/registry/list.rs
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-3.0-only |
2 | | use crate::daemon::http::state::AppState; |
3 | | use crate::daemon::http::wire::{ErrorEnvelope, ReasonEnvelope, RegistryError}; |
4 | | use axum::extract::{Query, State}; |
5 | | use axum::response::Response; |
6 | | use super_engine_daemon::registry::endpoints::{self, ListQuery}; |
7 | | use super_tts_shared::registry::RegistryListResponse; |
8 | | |
9 | | /// `GET /registry/backend/list` — list installable backends from the registry. |
10 | | #[utoipa::path( |
11 | | get, |
12 | | path = "/registry/backend/list", |
13 | | tag = "registry", |
14 | | summary = "Browse the published backend catalog", |
15 | | description = "\ |
16 | | Every backend published to the registry, with the models each serves and whether this \ |
17 | | machine can run it. `compatibility.compatible` is decided against the host's actual \ |
18 | | accelerators and this Super TTS's version, so the list reflects what is installable here \ |
19 | | rather than what exists in general; pass `include_incompatible=true` to see the rest, each \ |
20 | | with a `compatibility.reason` worth showing the user. |
21 | | |
22 | | `needs_client_update` separates the two ways a backend can be blocked: a host that lacks \ |
23 | | the right GPU will never run it, but a Super TTS one version behind is something the user \ |
24 | | can fix in a minute. Those are listed even without `include_incompatible`; surface them \ |
25 | | differently. |
26 | | |
27 | | `update_available` is the daemon's answer rather than the client's arithmetic: it \ |
28 | | compares the installed `backend.toml` on disk against what the index offers, by \ |
29 | | `source`, and refuses a downgrade. An entry with no `installed_version` is an install, \ |
30 | | not an update. |
31 | | |
32 | | This is what is *available*; `GET /backend/list` is what is installed. The index is \ |
33 | | cached and re-fetched on a schedule — `POST /registry/backend/refresh` forces that \ |
34 | | now.", |
35 | | params(ListQuery), |
36 | | security(("session_token" = ["settings"])), |
37 | | responses( |
38 | | (status = 200, description = "The catalog.", body = RegistryListResponse), |
39 | | (status = 401, description = "Token unknown, expired, or its binary changed.", body = ReasonEnvelope), |
40 | | (status = 403, description = "The token lacks the `settings` scope.", body = ErrorEnvelope), |
41 | | (status = 429, description = "Per-client rate limit hit; back off and retry.", body = ErrorEnvelope), |
42 | | (status = 503, description = "The catalog could not be fetched and nothing is cached (`registry_unavailable`). Retry, or force a fetch with `POST /registry/backend/refresh`.", body = RegistryError), |
43 | | ), |
44 | | )] |
45 | 0 | pub(crate) async fn list_registry_backends( |
46 | 0 | State(s): State<AppState>, |
47 | 0 | Query(q): Query<ListQuery>, |
48 | 0 | ) -> Response { |
49 | 0 | endpoints::list(&s.registry, &q).await |
50 | 0 | } |