Merge branch 'fix/catalogue-install-capability' into fix/community-integration
# Conflicts: # CHANGELOG.md # docs/install/troubleshooting.md
This commit is contained in:
@@ -18,6 +18,7 @@ export function EngineInstall({ id }: { id: string }) {
|
||||
queryFn: () =>
|
||||
apiJson<{
|
||||
installed: boolean;
|
||||
install_allowed?: boolean;
|
||||
job: null | {
|
||||
state: string;
|
||||
steps: { name?: string; state: string }[];
|
||||
@@ -36,8 +37,15 @@ export function EngineInstall({ id }: { id: string }) {
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
disabled={running || status.data?.installed}
|
||||
disabled={
|
||||
running ||
|
||||
status.isPending ||
|
||||
status.isError ||
|
||||
status.data?.installed ||
|
||||
status.data?.install_allowed === false
|
||||
}
|
||||
onClick={async () => {
|
||||
if (status.data?.install_allowed === false) return;
|
||||
setStarting(true);
|
||||
setFailed(null);
|
||||
setDismissedFailure(false);
|
||||
@@ -54,6 +62,11 @@ export function EngineInstall({ id }: { id: string }) {
|
||||
<DownloadIcon />
|
||||
{t(running ? 'modelMaintenance.installing' : 'modelMaintenance.install')}
|
||||
</Button>
|
||||
{status.data?.install_allowed === false && (
|
||||
<p className="max-w-sm text-xs text-muted-foreground">
|
||||
{t('engines.localInstallRequired')}
|
||||
</p>
|
||||
)}
|
||||
{!dismissedFailure && (failed || status.isError || status.data?.job?.state === 'failed') && (
|
||||
<SettingsActionError
|
||||
className="max-w-sm text-left"
|
||||
|
||||
@@ -107,7 +107,41 @@ it('confirms a diarisation engine selection after the backend accepts it', async
|
||||
);
|
||||
|
||||
fireEvent.click(await screen.findByRole('button', { name: 'modelSettings.select' }));
|
||||
await waitFor(() =>
|
||||
expect(mock.toast.success).toHaveBeenCalledWith('settings.engine_switched'),
|
||||
await waitFor(() => expect(mock.toast.success).toHaveBeenCalledWith('settings.engine_switched'));
|
||||
});
|
||||
|
||||
it('explains remote native installation restrictions before a POST', async () => {
|
||||
mock.api.mockImplementation((path: string) =>
|
||||
Promise.resolve(
|
||||
path === '/engines/diarisation'
|
||||
? {
|
||||
active: 'pyannote',
|
||||
options: [
|
||||
{
|
||||
id: 'audiocpp-sortformer',
|
||||
label: 'Sortformer',
|
||||
model_installed: true,
|
||||
runtime_installed: false,
|
||||
installed: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
: {
|
||||
installed: false,
|
||||
supported: true,
|
||||
install_allowed: false,
|
||||
job: { state: 'idle', progress: 0 },
|
||||
},
|
||||
),
|
||||
);
|
||||
render(
|
||||
<QueryClientProvider client={new QueryClient()}>
|
||||
<DiarisationSettings />
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
expect(await screen.findByText('engines.localInstallRequired')).toBeInTheDocument();
|
||||
const button = screen.getByRole('button', { name: 'modelMaintenance.install' });
|
||||
expect(button).toBeDisabled();
|
||||
fireEvent.click(button);
|
||||
expect(mock.api.mock.calls.some(([, init]) => init?.method === 'POST')).toBe(false);
|
||||
});
|
||||
|
||||
@@ -61,6 +61,7 @@ export function DiarisationSettings() {
|
||||
apiJson<{
|
||||
installed: boolean;
|
||||
supported: boolean;
|
||||
install_allowed?: boolean;
|
||||
job: { state: string; progress: number; error?: string | null };
|
||||
}>('/engines/audiocpp/runtime/install/status'),
|
||||
refetchInterval: (state) => (state.state.data?.job.state === 'running' ? 1_500 : 10_000),
|
||||
@@ -75,6 +76,7 @@ export function DiarisationSettings() {
|
||||
}, [client, runtime.data?.installed]);
|
||||
const runtimeRunning = busy || runtime.data?.job.state === 'running';
|
||||
const installRuntime = async () => {
|
||||
if (runtime.data?.install_allowed === false) return;
|
||||
setBusy(true);
|
||||
setFailed(null);
|
||||
try {
|
||||
@@ -152,7 +154,12 @@ export function DiarisationSettings() {
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
disabled={runtimeRunning}
|
||||
disabled={runtimeRunning || runtime.data?.install_allowed === false}
|
||||
title={
|
||||
runtime.data?.install_allowed === false
|
||||
? t('engines.localInstallRequired')
|
||||
: undefined
|
||||
}
|
||||
onClick={() => void installRuntime()}
|
||||
>
|
||||
<DownloadIcon />
|
||||
@@ -163,6 +170,13 @@ export function DiarisationSettings() {
|
||||
: t('modelMaintenance.install')}
|
||||
</Button>
|
||||
)}
|
||||
{option.id === 'audiocpp-sortformer' &&
|
||||
!option.runtime_installed &&
|
||||
runtime.data?.install_allowed === false && (
|
||||
<p className="max-w-sm text-xs text-muted-foreground">
|
||||
{t('engines.localInstallRequired')}
|
||||
</p>
|
||||
)}
|
||||
{option.installed && (
|
||||
<Button
|
||||
size="sm"
|
||||
@@ -380,11 +394,13 @@ export function ModelSettings({
|
||||
name: engine.display_name,
|
||||
available: engine.available,
|
||||
detail:
|
||||
engine.id === selected
|
||||
? engineState.active_model
|
||||
: !engine.available
|
||||
? engine.install_hint || engine.reason || engine.hint || undefined
|
||||
: undefined,
|
||||
engine.local_install_required && !engine.available
|
||||
? t('engines.localInstallRequired')
|
||||
: engine.id === selected
|
||||
? engineState.active_model
|
||||
: !engine.available
|
||||
? engine.install_hint || engine.reason || engine.hint || undefined
|
||||
: undefined,
|
||||
models: engine.curated_models,
|
||||
installable: engine.one_click_install,
|
||||
setupSnippet: !engine.available ? engine.setup_snippet || undefined : undefined,
|
||||
|
||||
@@ -2492,7 +2492,8 @@
|
||||
"none_ready_title": "تحويل النص إلى كلام غير جاهز",
|
||||
"none_ready_body": "يمكن لـ VoiceStudio إعداد أفضل خيار متوافق مع هذا الجهاز تلقائيًا.",
|
||||
"active": "المحرك: {{name}}",
|
||||
"none": "لا يوجد محرك نشط"
|
||||
"none": "لا يوجد محرك نشط",
|
||||
"localInstallRequired": "ثبّت هذا المحرك على جهاز الخادم باستخدام localhost أو دليل الإعداد. التثبيت عن بُعد معطّل."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "ثبّت {{engine}} وحدده لضبط السرعة والجودة.",
|
||||
|
||||
@@ -2484,7 +2484,8 @@
|
||||
"none_ready_title": "Sprachausgabe ist nicht bereit",
|
||||
"none_ready_body": "VoiceStudio kann automatisch die beste kompatible Option für dieses Gerät einrichten.",
|
||||
"active": "Engine: {{name}}",
|
||||
"none": "Keine Engine aktiv"
|
||||
"none": "Keine Engine aktiv",
|
||||
"localInstallRequired": "Installiere diese Engine auf dem Backend-Rechner über localhost oder die Einrichtungsanleitung. Die Ferninstallation ist deaktiviert."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "Installiere und wähle {{engine}}, um Geschwindigkeit und Qualität anzupassen.",
|
||||
|
||||
@@ -114,7 +114,8 @@
|
||||
"recheck": "Re-check",
|
||||
"rechecking": "Re-checking…",
|
||||
"failed": "failed",
|
||||
"latencyMs": "{{ms}} ms"
|
||||
"latencyMs": "{{ms}} ms",
|
||||
"localInstallRequired": "Install this engine on the backend computer using localhost or its setup guide. Remote installation is disabled."
|
||||
},
|
||||
"clone": {
|
||||
"title": "Voice cloning",
|
||||
|
||||
@@ -2486,7 +2486,8 @@
|
||||
"none_ready_title": "La síntesis de voz no está lista",
|
||||
"none_ready_body": "VoiceStudio puede configurar automáticamente la mejor opción compatible con este dispositivo.",
|
||||
"active": "Motor: {{name}}",
|
||||
"none": "Ningún motor activo"
|
||||
"none": "Ningún motor activo",
|
||||
"localInstallRequired": "Instala este motor en el equipo del servidor mediante localhost o su guía de configuración. La instalación remota está desactivada."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "Instala y selecciona {{engine}} para ajustar la velocidad y la calidad.",
|
||||
|
||||
@@ -2486,7 +2486,8 @@
|
||||
"none_ready_title": "La synthèse vocale n’est pas prête",
|
||||
"none_ready_body": "VoiceStudio peut configurer automatiquement la meilleure option compatible avec cet appareil.",
|
||||
"active": "Moteur : {{name}}",
|
||||
"none": "Aucun moteur actif"
|
||||
"none": "Aucun moteur actif",
|
||||
"localInstallRequired": "Installez ce moteur sur l’ordinateur du serveur via localhost ou son guide de configuration. L’installation à distance est désactivée."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "Installez et sélectionnez {{engine}} pour régler la vitesse et la qualité.",
|
||||
|
||||
@@ -2484,7 +2484,8 @@
|
||||
"none_ready_title": "वाक् संश्लेषण तैयार नहीं है",
|
||||
"none_ready_body": "VoiceStudio इस डिवाइस के लिए सबसे अच्छा संगत विकल्प अपने आप सेट कर सकता है।",
|
||||
"active": "इंजन: {{name}}",
|
||||
"none": "कोई इंजन सक्रिय नहीं है"
|
||||
"none": "कोई इंजन सक्रिय नहीं है",
|
||||
"localInstallRequired": "इस इंजन को बैकएंड कंप्यूटर पर localhost या सेटअप गाइड से इंस्टॉल करें। रिमोट इंस्टॉलेशन बंद है।"
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "गति और गुणवत्ता समायोजित करने के लिए {{engine}} इंस्टॉल करके चुनें।",
|
||||
|
||||
@@ -2484,7 +2484,8 @@
|
||||
"none_ready_title": "Sintesis ucapan belum siap",
|
||||
"none_ready_body": "VoiceStudio dapat menyiapkan opsi kompatibel terbaik untuk perangkat ini secara otomatis.",
|
||||
"active": "Mesin: {{name}}",
|
||||
"none": "Tidak ada mesin aktif"
|
||||
"none": "Tidak ada mesin aktif",
|
||||
"localInstallRequired": "Instal mesin ini di komputer backend melalui localhost atau panduan penyiapannya. Instalasi jarak jauh dinonaktifkan."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "Instal dan pilih {{engine}} untuk menyesuaikan kecepatan dan kualitas.",
|
||||
|
||||
@@ -2486,7 +2486,8 @@
|
||||
"none_ready_title": "La sintesi vocale non è pronta",
|
||||
"none_ready_body": "VoiceStudio può configurare automaticamente l’opzione compatibile migliore per questo dispositivo.",
|
||||
"active": "Motore: {{name}}",
|
||||
"none": "Nessun motore attivo"
|
||||
"none": "Nessun motore attivo",
|
||||
"localInstallRequired": "Installa questo motore sul computer del backend tramite localhost o la guida alla configurazione. L’installazione remota è disabilitata."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "Installa e seleziona {{engine}} per regolare velocità e qualità.",
|
||||
|
||||
@@ -2484,7 +2484,8 @@
|
||||
"none_ready_title": "音声合成の準備ができていません",
|
||||
"none_ready_body": "VoiceStudio がこのデバイスに最適な互換オプションを自動で設定できます。",
|
||||
"active": "エンジン:{{name}}",
|
||||
"none": "有効なエンジンがありません"
|
||||
"none": "有効なエンジンがありません",
|
||||
"localInstallRequired": "バックエンドのコンピューターで localhost またはセットアップガイドを使ってこのエンジンをインストールしてください。リモートインストールは無効です。"
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "速度と品質を調整するには、{{engine}} をインストールして選択してください。",
|
||||
|
||||
@@ -2484,7 +2484,8 @@
|
||||
"none_ready_title": "음성 합성이 준비되지 않았습니다",
|
||||
"none_ready_body": "VoiceStudio가 이 기기에 가장 적합한 호환 옵션을 자동으로 설정할 수 있습니다.",
|
||||
"active": "엔진: {{name}}",
|
||||
"none": "활성 엔진 없음"
|
||||
"none": "활성 엔진 없음",
|
||||
"localInstallRequired": "백엔드 컴퓨터에서 localhost 또는 설정 가이드를 사용하여 이 엔진을 설치하세요. 원격 설치는 비활성화되어 있습니다."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "속도와 품질을 조절하려면 {{engine}}을 설치하고 선택하세요.",
|
||||
|
||||
@@ -2484,7 +2484,8 @@
|
||||
"none_ready_title": "Spraaksynthese is niet gereed",
|
||||
"none_ready_body": "VoiceStudio kan automatisch de beste compatibele optie voor dit apparaat instellen.",
|
||||
"active": "Engine: {{name}}",
|
||||
"none": "Geen engine actief"
|
||||
"none": "Geen engine actief",
|
||||
"localInstallRequired": "Installeer deze engine op de backendcomputer via localhost of de installatiehandleiding. Installatie op afstand is uitgeschakeld."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "Installeer en selecteer {{engine}} om snelheid en kwaliteit af te stellen.",
|
||||
|
||||
@@ -2488,7 +2488,8 @@
|
||||
"none_ready_title": "Synteza mowy nie jest gotowa",
|
||||
"none_ready_body": "VoiceStudio może automatycznie skonfigurować najlepszą zgodną opcję dla tego urządzenia.",
|
||||
"active": "Silnik: {{name}}",
|
||||
"none": "Brak aktywnego silnika"
|
||||
"none": "Brak aktywnego silnika",
|
||||
"localInstallRequired": "Zainstaluj ten silnik na komputerze zaplecza przez localhost lub zgodnie z instrukcją konfiguracji. Instalacja zdalna jest wyłączona."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "Zainstaluj i wybierz {{engine}}, aby dostosować szybkość i jakość.",
|
||||
|
||||
@@ -2486,7 +2486,8 @@
|
||||
"none_ready_title": "A síntese de voz não está pronta",
|
||||
"none_ready_body": "O VoiceStudio pode configurar automaticamente a melhor opção compatível com este dispositivo.",
|
||||
"active": "Motor: {{name}}",
|
||||
"none": "Nenhum motor ativo"
|
||||
"none": "Nenhum motor ativo",
|
||||
"localInstallRequired": "Instale este motor no computador do backend pelo localhost ou pelo guia de configuração. A instalação remota está desativada."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "Instale e selecione {{engine}} para ajustar a velocidade e a qualidade.",
|
||||
|
||||
@@ -2488,7 +2488,8 @@
|
||||
"none_ready_title": "Синтез речи не готов",
|
||||
"none_ready_body": "VoiceStudio может автоматически настроить лучший совместимый вариант для этого устройства.",
|
||||
"active": "Движок: {{name}}",
|
||||
"none": "Нет активного движка"
|
||||
"none": "Нет активного движка",
|
||||
"localInstallRequired": "Установите этот движок на компьютере сервера через localhost или по инструкции. Удалённая установка отключена."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "Установите и выберите {{engine}}, чтобы настроить скорость и качество.",
|
||||
|
||||
@@ -2484,7 +2484,8 @@
|
||||
"none_ready_title": "Talsyntesen är inte redo",
|
||||
"none_ready_body": "VoiceStudio kan automatiskt konfigurera det bästa kompatibla alternativet för den här enheten.",
|
||||
"active": "Motor: {{name}}",
|
||||
"none": "Ingen motor aktiv"
|
||||
"none": "Ingen motor aktiv",
|
||||
"localInstallRequired": "Installera motorn på backenddatorn via localhost eller installationsguiden. Fjärrinstallation är avstängd."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "Installera och välj {{engine}} för att justera hastighet och kvalitet.",
|
||||
|
||||
@@ -2484,7 +2484,8 @@
|
||||
"none_ready_title": "การสังเคราะห์เสียงยังไม่พร้อม",
|
||||
"none_ready_body": "VoiceStudio สามารถตั้งค่าตัวเลือกที่เข้ากันได้ดีที่สุดสำหรับอุปกรณ์นี้โดยอัตโนมัติ",
|
||||
"active": "เอนจิน: {{name}}",
|
||||
"none": "ไม่มีเอนจินที่ใช้งานอยู่"
|
||||
"none": "ไม่มีเอนจินที่ใช้งานอยู่",
|
||||
"localInstallRequired": "ติดตั้งเอนจินนี้บนคอมพิวเตอร์แบ็กเอนด์ผ่าน localhost หรือคู่มือการตั้งค่า การติดตั้งจากระยะไกลถูกปิดใช้งาน"
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "ติดตั้งและเลือก {{engine}} เพื่อปรับความเร็วและคุณภาพ",
|
||||
|
||||
@@ -2484,7 +2484,8 @@
|
||||
"none_ready_title": "Konuşma sentezi hazır değil",
|
||||
"none_ready_body": "VoiceStudio bu cihaz için en iyi uyumlu seçeneği otomatik olarak ayarlayabilir.",
|
||||
"active": "Motor: {{name}}",
|
||||
"none": "Etkin motor yok"
|
||||
"none": "Etkin motor yok",
|
||||
"localInstallRequired": "Bu motoru arka uç bilgisayarında localhost veya kurulum kılavuzu üzerinden yükleyin. Uzaktan kurulum devre dışıdır."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "Hız ve kaliteyi ayarlamak için {{engine}} yükleyip seçin.",
|
||||
|
||||
@@ -2488,7 +2488,8 @@
|
||||
"none_ready_title": "Синтез мовлення не готовий",
|
||||
"none_ready_body": "VoiceStudio може автоматично налаштувати найкращий сумісний варіант для цього пристрою.",
|
||||
"active": "Рушій: {{name}}",
|
||||
"none": "Немає активного рушія"
|
||||
"none": "Немає активного рушія",
|
||||
"localInstallRequired": "Установіть цей рушій на комп’ютері сервера через localhost або за інструкцією. Віддалене встановлення вимкнено."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "Установіть і виберіть {{engine}}, щоб налаштувати швидкість і якість.",
|
||||
|
||||
@@ -2484,7 +2484,8 @@
|
||||
"none_ready_title": "Tổng hợp giọng nói chưa sẵn sàng",
|
||||
"none_ready_body": "VoiceStudio có thể tự động thiết lập tùy chọn tương thích tốt nhất cho thiết bị này.",
|
||||
"active": "Bộ máy: {{name}}",
|
||||
"none": "Không có bộ máy đang hoạt động"
|
||||
"none": "Không có bộ máy đang hoạt động",
|
||||
"localInstallRequired": "Cài đặt công cụ này trên máy chủ qua localhost hoặc hướng dẫn thiết lập. Cài đặt từ xa đã bị tắt."
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "Cài đặt và chọn {{engine}} để điều chỉnh tốc độ và chất lượng.",
|
||||
|
||||
@@ -2488,7 +2488,8 @@
|
||||
"none_ready_title": "语音合成尚未就绪",
|
||||
"none_ready_body": "VoiceStudio 可以自动为此设备设置最佳兼容选项。",
|
||||
"active": "引擎:{{name}}",
|
||||
"none": "没有启用的引擎"
|
||||
"none": "没有启用的引擎",
|
||||
"localInstallRequired": "请在后端计算机上通过 localhost 或安装指南安装此引擎。远程安装已禁用。"
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "安装并选择 {{engine}} 以调整速度和质量。",
|
||||
|
||||
@@ -2484,7 +2484,8 @@
|
||||
"none_ready_title": "語音合成尚未就緒",
|
||||
"none_ready_body": "VoiceStudio 可以自動為此裝置設定最佳相容選項。",
|
||||
"active": "引擎:{{name}}",
|
||||
"none": "沒有啟用的引擎"
|
||||
"none": "沒有啟用的引擎",
|
||||
"localInstallRequired": "請在後端電腦上透過 localhost 或安裝指南安裝此引擎。遠端安裝已停用。"
|
||||
},
|
||||
"performanceProfile": {
|
||||
"requiresEngine": "安裝並選取 {{engine}} 以調整速度與品質。",
|
||||
|
||||
@@ -66,6 +66,7 @@ export interface EngineBackend {
|
||||
setup_snippet?: string | null;
|
||||
docs_url?: string | null;
|
||||
one_click_install?: boolean;
|
||||
local_install_required?: boolean;
|
||||
license_required?: boolean;
|
||||
license_accepted?: boolean;
|
||||
effective_device?: string;
|
||||
|
||||
Reference in New Issue
Block a user