fix(app): Barge-In kontext-scoped — Hauptchat-Frage killt/blockiert Projekt-Arbeit nicht mehr
Bug: waehrend ARIA in einem Projekt arbeitet, im Hauptchat eine Frage stellen → sie wurde angezeigt aber nicht verarbeitet (erst wenn das Projekt fertig war). Proxy kann nachweislich parallel (2 claude-Subprozesse) — der Flaschenhals war die App: interruptAriaIfBusy wertete den GLOBALEN agentActivity aus und feuerte bei jedem Senden-waehrend-irgendein-Kontext-arbeitet einen kontext-uebergreifenden cancel_request. Fix: Busy-Status kontextgenau aus queueStatus (/projects/queue-status) statt global. Barge-In (Brain-Cancel) nur noch wenn GENAU der fokussierte Kontext arbeitet; TTS wird weiterhin immer gestoppt wenn ARIA spricht. cancel_request traegt jetzt die projectId (fuer spaeteres kontext-scoped Cancel in der Bridge). Damit laufen Hauptchat und Projekt(e) in der App parallel — passend zum Multi-Threading im Brain. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -295,6 +295,9 @@ const ChatScreen: React.FC = () => {
|
||||
const [projectNameById, setProjectNameById] = useState<Record<string, string>>({});
|
||||
// Queue-Status pro Kontext — polled alle 2s, fuer Status-Dots im Drawer
|
||||
const [queueStatus, setQueueStatus] = useState<Record<string, { busy: boolean; queue_size: number }>>({});
|
||||
// Ref-Spiegel fuer Callbacks (interruptAriaIfBusy liest den aktuellen
|
||||
// Busy-Status des fokussierten Kontexts ohne stale Closure).
|
||||
const queueStatusRef = useRef<Record<string, { busy: boolean; queue_size: number }>>({});
|
||||
const [searchIndex, setSearchIndex] = useState(0); // welcher Treffer aktiv ist
|
||||
const [pendingAttachments, setPendingAttachments] = useState<{file: any, isPhoto: boolean}[]>([]);
|
||||
const [agentActivity, setAgentActivity] = useState<{activity: string, tool: string}>({activity: 'idle', tool: ''});
|
||||
@@ -517,6 +520,7 @@ const ChatScreen: React.FC = () => {
|
||||
const s = await brainApi.getProjectQueueStatus();
|
||||
if (cancelled) return;
|
||||
setQueueStatus(s.contexts || {});
|
||||
queueStatusRef.current = s.contexts || {};
|
||||
} catch {}
|
||||
};
|
||||
poll();
|
||||
@@ -1939,18 +1943,27 @@ const ChatScreen: React.FC = () => {
|
||||
// mach lieber X" sagen wie in einem echten Gespraech.
|
||||
const interruptAriaIfBusy = useCallback(() => {
|
||||
const speaking = audioService.isPlayingAudio();
|
||||
const thinking = agentActivity.activity !== 'idle';
|
||||
if (!speaking && !thinking) return false;
|
||||
console.log('[Chat] Barge-In: speaking=%s thinking=%s — interrupting ARIA',
|
||||
speaking, thinking);
|
||||
// Multi-Threading: NUR den fokussierten Kontext als "busy" werten — nicht
|
||||
// global. Sonst bricht eine Nachricht im Hauptchat die parallele Arbeit in
|
||||
// einem Projekt ab (bzw. wird faelschlich als Barge-In behandelt und die
|
||||
// eigene Anfrage geht unter). Der Busy-Status kommt kontextgenau aus
|
||||
// /projects/queue-status (queueStatusRef). agentActivity ist global und
|
||||
// taugt dafuer nicht.
|
||||
const pid = focusedProjectIdRef.current || '';
|
||||
const focusKey = pid || '__main__';
|
||||
const focusBusy = !!queueStatusRef.current?.[focusKey]?.busy;
|
||||
if (!speaking && !focusBusy) return false;
|
||||
console.log('[Chat] Barge-In: speaking=%s focusBusy=%s (ctx=%s) — interrupting',
|
||||
speaking, focusBusy, focusKey);
|
||||
// TTS immer stoppen wenn ARIA gerade spricht — egal welcher Kontext.
|
||||
if (speaking) audioService.haltAllPlayback('user spricht (barge-in)');
|
||||
if (thinking) {
|
||||
setAgentActivity({ activity: 'idle', tool: '' });
|
||||
// Brain-Arbeit nur abbrechen wenn GENAU dieser Kontext arbeitet.
|
||||
if (focusBusy) {
|
||||
clearStuckWatchdog();
|
||||
rvs.send('cancel_request' as any, {});
|
||||
rvs.send('cancel_request' as any, { projectId: pid });
|
||||
}
|
||||
return true;
|
||||
}, [agentActivity]);
|
||||
}, []);
|
||||
|
||||
// Manueller Aufnahme-Knopf (VoiceButton) — Start.
|
||||
// Streaming-Variante: PcmStreamRecorder + Whisper-ML-Endpointer ersetzen
|
||||
|
||||
Reference in New Issue
Block a user