feat(flux): Modell-Wahl per Diagnostic + raw/switch-Keywords + Download-Hinweis
Diagnostic-Einstellungen fuer FLUX: - Default-Modell (dev | schnell) — wird via RVS gepusht, flux-bridge hot-swappt die Pipeline aus dem HF-Cache (~15-30s) - Raw-Keyword (Default 'flux') — Pipe-Modus, Brain leitet Stefans Text 1:1 als prompt durch, kein Rewriting/Beautify - Switch-Keyword (Default 'fix') — zwingt das ANDERE Modell als Default Brain-Tool flux_generate um model + raw erweitert, System-Prompt-Block mit den aktuellen Diagnostic-Settings + Whisper-Toleranz-Hinweis. Kein eager Bootstrap-Load: flux-bridge wartet auf config oder ersten Request. Bei erstem HF-Download zeigt Banner "laedt erstmalig runter" mit Pfeil-Icon, Toast in der App wenn fertig. FLUX_MODEL aus der .env entfernt (Steuerung jetzt komplett ueber Diagnostic). HF_TOKEN-Kommentar erklaert warum trotz lokaler Inference noetig (HF Gate-Mechanismus fuer FLUX.1-dev). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -290,7 +290,7 @@ const ChatScreen: React.FC = () => {
|
||||
// Stream zumuellen. Eigentlich seltener Fall, aber billig zu pruefen.
|
||||
const lastThoughtKeyRef = useRef<string>('');
|
||||
// Service-Status (Gamebox: F5-TTS / Whisper Lade-Status) + Banner-Sichtbarkeit
|
||||
const [serviceStatus, setServiceStatus] = useState<Record<string, {state: string, model?: string, loadSeconds?: number, error?: string}>>({});
|
||||
const [serviceStatus, setServiceStatus] = useState<Record<string, {state: string, model?: string, loadSeconds?: number, error?: string, downloading?: boolean, freshlyDownloaded?: boolean}>>({});
|
||||
const [serviceBannerDismissed, setServiceBannerDismissed] = useState(false);
|
||||
// Gerätelokale TTS-Config: globaler Toggle (aus Settings) + temporäres Muten (Mund-Button)
|
||||
const [ttsDeviceEnabled, setTtsDeviceEnabled] = useState(true);
|
||||
@@ -1171,22 +1171,39 @@ const ChatScreen: React.FC = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// Gamebox-Bridges (f5tts/whisper) melden Lade-Status — Banner oben
|
||||
// Gamebox-Bridges (f5tts/whisper/flux) melden Lade-Status — Banner oben.
|
||||
// Toast bei Download-Ende: erstmaliger HF-Download (mehrere GB) → User
|
||||
// soll wissen dass er Bilder/Stimmen jetzt nutzen kann ohne in den
|
||||
// Banner gucken zu muessen.
|
||||
if (message.type === ('service_status' as any)) {
|
||||
const p = message.payload as any;
|
||||
const svc = (p?.service as string) || '';
|
||||
if (!svc) return;
|
||||
const newState = (p?.state as string) || 'unknown';
|
||||
const freshlyDownloaded = p?.freshlyDownloaded === true;
|
||||
setServiceStatus(prev => ({
|
||||
...prev,
|
||||
[svc]: {
|
||||
state: (p?.state as string) || 'unknown',
|
||||
state: newState,
|
||||
model: p?.model as string | undefined,
|
||||
loadSeconds: p?.loadSeconds as number | undefined,
|
||||
error: p?.error as string | undefined,
|
||||
downloading: p?.downloading === true,
|
||||
freshlyDownloaded,
|
||||
},
|
||||
}));
|
||||
// Bei neuer Loading-Phase Banner wieder aktivieren
|
||||
if (p?.state === 'loading') setServiceBannerDismissed(false);
|
||||
if (newState === 'loading') setServiceBannerDismissed(false);
|
||||
// Download-Fertig-Toast: Bridge setzt freshlyDownloaded=true bei dem
|
||||
// 'ready'-Broadcast direkt nach einem Cache-Miss-Load. Ein einziger
|
||||
// Toast pro Modell-Download, kein State-Tracking auf App-Seite noetig.
|
||||
if (newState === 'ready' && freshlyDownloaded) {
|
||||
const niceName = svc === 'flux' ? 'FLUX' : svc === 'f5tts' ? 'F5-TTS' : svc === 'whisper' ? 'Whisper' : svc;
|
||||
const model = p?.model ? ` (${p.model})` : '';
|
||||
try {
|
||||
ToastAndroid.show(`${niceName}-Modell heruntergeladen${model} — jetzt einsatzbereit`, ToastAndroid.LONG);
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2196,7 +2213,7 @@ const ChatScreen: React.FC = () => {
|
||||
const allReady = !anyLoading && !anyError && entries.every(([, v]) => v.state === 'ready');
|
||||
const bg = anyError ? '#3A1F1F' : anyLoading ? '#3A331F' : '#1F3A2A';
|
||||
const border = anyError ? '#FF3B30' : anyLoading ? '#FFD60A' : '#34C759';
|
||||
const labels: Record<string, string> = { f5tts: 'F5-TTS', whisper: 'Whisper STT' };
|
||||
const labels: Record<string, string> = { f5tts: 'F5-TTS', whisper: 'Whisper STT', flux: 'FLUX Image-Gen' };
|
||||
return (
|
||||
<TouchableOpacity
|
||||
activeOpacity={allReady ? 0.6 : 1.0}
|
||||
@@ -2206,11 +2223,16 @@ const ChatScreen: React.FC = () => {
|
||||
{entries.map(([svc, info]) => {
|
||||
let icon = '\u23F3', text = '';
|
||||
if (info.state === 'loading') {
|
||||
text = `${labels[svc] || svc}: laedt${info.model ? ' ' + info.model : ''}...`;
|
||||
icon = info.downloading ? '\u2B07' : '\u23F3'; // \u2B07 vs \u23F3
|
||||
const action = info.downloading
|
||||
? 'laedt erstmalig runter (mehrere GB, kann dauern)'
|
||||
: 'laedt';
|
||||
text = `${labels[svc] || svc}: ${action}${info.model ? ' ' + info.model : ''}...`;
|
||||
} else if (info.state === 'ready') {
|
||||
icon = '\u2705';
|
||||
icon = info.freshlyDownloaded ? '\uD83C\uDF89' : '\u2705'; // \uD83C\uDF89 vs \u2705
|
||||
const sec = info.loadSeconds ? ` (${info.loadSeconds.toFixed(1)}s)` : '';
|
||||
text = `${labels[svc] || svc}: bereit${info.model ? ' ' + info.model : ''}${sec}`;
|
||||
const dl = info.freshlyDownloaded ? ' \u2014 Download fertig!' : '';
|
||||
text = `${labels[svc] || svc}: bereit${info.model ? ' ' + info.model : ''}${sec}${dl}`;
|
||||
} else if (info.state === 'error') {
|
||||
icon = '\u274C';
|
||||
text = `${labels[svc] || svc}: Fehler ${info.error || ''}`;
|
||||
|
||||
Reference in New Issue
Block a user