feat(app): reportAppDebug — Live-Debug-Logs an Bridge ohne ADB
Stefan-Anforderung: Background-Wake-Word-Pipeline klappt noch nicht, ADB nicht zur Hand → Debug via RVS-Log-Pipeline. Logger: - reportAppDebug(scope, message) analog zu reportAppError aber level=info, kein console.error, fuer Live-Diagnose Strategische Log-Punkte: - wakeword.ts: start() emits 'wake.start armed' - wakeword.ts: onWakeDetected emits 'wake.detect state=X' beim Native-Trigger-Empfang - ChatScreen.tsx wake-callback: 'wake.cb callback fired', 'wake.cb startRecording=X', 'wake.cb gong played' - backgroundAudio.ts: 'bg.start slot=X', 'bg.stop service stopped', 'bg.start.fail msg' wenn Service nicht hochkommt Abruf live via curl http://172.0.2.33:3001/api/app-log?lines=100 Damit kann Stefan nach APK-Build (mit allen Native-Fixes + Logger) im Background-Test exakt sehen wo es klemmt: - Kommt 'wake.detect' im Hintergrund an? (WakeLock-Frage) - Kommt 'wake.cb callback fired'? (JS-Bridge-Frage) - Geht 'bg.start slot=wake' durch? (Service-Start-Frage) APK neu bauen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1270,9 +1270,11 @@ const ChatScreen: React.FC = () => {
|
||||
useEffect(() => {
|
||||
const unsubWake = wakeWordService.onWakeWord(async () => {
|
||||
console.log('[Chat] Gespraechsmodus — starte Auto-Aufnahme');
|
||||
import('../services/logger').then(m => m.reportAppDebug('wake.cb', 'callback fired, calling startRecording')).catch(()=>{});
|
||||
// Conversation-Window: User hat X Sekunden um anzufangen, sonst Konversation aus
|
||||
const windowMs = await loadConvWindowMs();
|
||||
const started = await audioService.startRecording(true, windowMs);
|
||||
import('../services/logger').then(m => m.reportAppDebug('wake.cb', `startRecording returned ${started}`)).catch(()=>{});
|
||||
if (started) {
|
||||
// Erst JETZT signalisieren dass das Mikro wirklich offen ist —
|
||||
// vorher war's noch in der Init-Phase. So weiss der User exakt
|
||||
@@ -1280,6 +1282,7 @@ const ChatScreen: React.FC = () => {
|
||||
// ueber Settings → Wake-Word abschaltbar.
|
||||
ToastAndroid.show('🎤 Mikro offen — sprich jetzt', ToastAndroid.SHORT);
|
||||
playWakeReadySound().catch(() => {});
|
||||
import('../services/logger').then(m => m.reportAppDebug('wake.cb', 'gong played + recording started')).catch(()=>{});
|
||||
} else {
|
||||
// Mikrofon nicht verfuegbar, naechsten Versuch
|
||||
wakeWordService.resume();
|
||||
|
||||
@@ -48,6 +48,7 @@ async function applyState(): Promise<void> {
|
||||
if (slots.size === 0) {
|
||||
try { await BackgroundAudio.stop(); } catch {}
|
||||
console.log('[BackgroundAudio] Service gestoppt (keine Slots)');
|
||||
import('./logger').then(m => m.reportAppDebug('bg.stop', 'service stopped')).catch(()=>{});
|
||||
return;
|
||||
}
|
||||
const reason = topReason();
|
||||
@@ -55,8 +56,10 @@ async function applyState(): Promise<void> {
|
||||
await BackgroundAudio.start(reason);
|
||||
console.log('[BackgroundAudio] Service aktiv (slot=%s, slots=%s)',
|
||||
reason, [...slots].join('+'));
|
||||
import('./logger').then(m => m.reportAppDebug('bg.start', `slot=${reason} all=[${[...slots].join(',')}]`)).catch(()=>{});
|
||||
} catch (err: any) {
|
||||
console.warn('[BackgroundAudio] start fehlgeschlagen:', err?.message || err);
|
||||
import('./logger').then(m => m.reportAppDebug('bg.start.fail', err?.message || String(err))).catch(()=>{});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,22 @@ export function reportAppError(ev: AppErrorEvent): void {
|
||||
console.error(`[app-error scope=${ev.scope}]`, ev.message, '\n', ev.stack || '');
|
||||
}
|
||||
|
||||
/** Schickt eine Debug-/Info-Message via RVS an die Bridge. Landet ebenfalls
|
||||
* in /shared/logs/app.log — abrufbar via `curl /api/app-log?lines=N`.
|
||||
* Im Gegensatz zu reportAppError: keine Stacktrace, level=info, kein
|
||||
* console.error. Fuer Live-Diagnose im Hintergrund wenn ADB nicht da ist. */
|
||||
export function reportAppDebug(scope: string, message: string): void {
|
||||
try {
|
||||
rvs.send('app_log' as any, {
|
||||
ts: Date.now(),
|
||||
platform: Platform.OS,
|
||||
level: 'info',
|
||||
scope,
|
||||
message: String(message).slice(0, 2000),
|
||||
});
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** Installiert einen globalen JS-Error-Handler der ungefangene Errors via
|
||||
* RVS an die Bridge schickt. Beim App-Start aufrufen. */
|
||||
export function installGlobalCrashReporter(): void {
|
||||
|
||||
@@ -179,6 +179,8 @@ class WakeWordService {
|
||||
try {
|
||||
await OpenWakeWord.start();
|
||||
console.log('[WakeWord] armed — warte auf "%s"', this.keyword);
|
||||
// Debug-Log via RVS damit wir auch ohne ADB sehen wann es greift
|
||||
import('./logger').then(m => m.reportAppDebug('wake.start', `armed, keyword=${this.keyword}`)).catch(()=>{});
|
||||
ToastAndroid.show(`Lausche auf "${KEYWORD_LABELS[this.keyword]}"`, ToastAndroid.SHORT);
|
||||
this.setState('armed');
|
||||
return true;
|
||||
@@ -236,6 +238,8 @@ class WakeWordService {
|
||||
}
|
||||
console.log('[WakeWord] Wake-Word "%s" erkannt! (state=%s, barge=%s)',
|
||||
this.keyword, this.state, this.bargeListening);
|
||||
import('./logger').then(m => m.reportAppDebug('wake.detect',
|
||||
`keyword=${this.keyword} state=${this.state} barge=${this.bargeListening}`)).catch(()=>{});
|
||||
this.lastTriggerAt = now;
|
||||
if (this.nativeReady && OpenWakeWord) {
|
||||
try { await OpenWakeWord.stop(); } catch {}
|
||||
|
||||
Reference in New Issue
Block a user