fix: resolve architecture disconnects and codebase weaknesses

- fix(backend): replace raw .parse() with proper loadConfig() + ConfigError
- fix(gateway): connect voice recording uploader to EventBroadcaster
- fix(gateway): remove dead globalThis.moderationBroadcaster path in AI analyzer
- fix(gateway): eliminate audioStream race condition by attaching handlers before pipe
- fix(gateway): enable inlineVolume by default for setMusicVolume to work
- fix(gateway): reuse persistent redisPub for command replies (no new connection per cmd)
- fix(frontend): add missing voice_active_user/voice_pcm_data to WsEventMap
- fix(frontend): correct onAttachmentUploaded handler signature to accept data
- chore: move @types/pg from dependencies to devDependencies
- chore: translate remaining Indonesian comments to English
- chore: remove stale P3 TODO comment
This commit is contained in:
MythEclipse
2026-06-09 11:06:14 +07:00
parent 4becf0d6f1
commit f84b380f4f
13 changed files with 104 additions and 93 deletions
@@ -22,7 +22,6 @@ import type {
AnalysisQueueStatus,
AnalysisResult,
MessageRecord,
ModerationBroadcaster,
} from "../message-capture/types.js";
import { attemptAutoDeleteFlaggedMessage } from "./autoDeleteManager.js";
import { estimateTokens } from "./conversationContext.js";
@@ -30,22 +29,12 @@ import { logModerationError } from "./responseLogger.js";
const logger = createChildLogger("ai-analyzer");
type ModerationGlobal = typeof globalThis & {
moderationBroadcaster?: ModerationBroadcaster;
};
function getModerationBroadcaster(): ModerationBroadcaster | undefined {
return (globalThis as ModerationGlobal).moderationBroadcaster;
}
// Redis EventBroadcaster — set by startPendingAIAnalysisWorker.
// Used to publish analysis completion events so the backend
// redis-bridge can forward them to frontend WebSocket clients.
let _redisEventBroadcaster: EventBroadcaster | undefined;
function broadcastAnalysisCompleted(row: MessageRecord): void {
// In-memory WS broadcast (direct-connected DG clients)
getModerationBroadcaster()?.messageAnalyzed(row);
// Redis pub/sub broadcast → backend → frontend WebSocket
if (_redisEventBroadcaster) {
_redisEventBroadcaster.messageAnalyzed(row).catch((err: unknown) =>