- Replace direct better-sqlite3 imports with DatabaseAdapter pattern
- Make all muxer-queue functions async to support both SQLite and PostgreSQL
- Update database initialization to use adapter's getDatabase()
- Export DatabaseAdapter as SqliteDatabase for backward compatibility
- Update index.ts to handle async database initialization
- Update webserver.ts to await async database operations
- All functions now work with both SQLite and PostgreSQL backends
- Tests pass, no TypeScript errors
Reduce effective AI batch size so streaming requests finish before timeout. Keep token-based batching but cap each request to 80 messages or about 9k content tokens, and recursively split failed batches instead of marking the whole batch failed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Batch AI moderation by estimated token budget instead of fixed message count. Send as many messages as fit within an 80k token request budget while keeping one concurrent API request. Include message metadata and chronological conversation context so the model can judge provocation and replies from surrounding discussion.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Remove unclear-message and low-quality-message warning criteria because this is a casual group. Keep short, ambiguous, informal, and light profanity messages clean unless they target someone or provoke conflict.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Combine the right-side Warned and Flagged panels into a single Needs Review panel. Keep ordering by the existing newest-first message list.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Remove the channel topic/OOT rule from AI moderation criteria and renumber the remaining rules. WARN criteria no longer includes OOT.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Expand system prompt with complete community rules (9 sections)
- Add specific examples for each rule category
- Clarify WARN vs FLAGGED decision criteria
- Include all prohibited content types and behaviors
- Provide clear guidance for AI analyzer on rule enforcement
Community rules now cover:
1. Jaga Sikap dan Hormati Sesama
2. Hindari Konflik
3. Gunakan Channel Sesuai Topik
4. Konten Eksplisit Dilarang
5. Jaga Privasi
6. Profil yang Sopan
7. Dilarang Spam dan Penipuan
8. Langsung ke Inti Pertanyaan
9. Diskusi Berkualitas
This ensures AI analyzer makes consistent moderation decisions based on actual community rules.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add "warn" status between "clean" and "flagged" for minor violations
- Update AI analyzer system prompt with community rules and warn category
- Warn: profanity, OOT, tone issues - requires warning but not deletion
- Flagged: NSFW, illegal, hacking, scam, harassment, violence, SARA - requires review/deletion
- Update types to support warn status in MessageRecord and AIAnalysisUpdate
- Update client UI to show three panels: All Messages, Warned, Flagged
- Warned messages show in right-top panel for quick review
- Flagged messages show in right-bottom panel for moderation action
This resolves:
- Need to distinguish between minor and severe violations
- Moderators can now warn users before taking action
- Better moderation workflow with three-tier system
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Split text tab into two columns: All Messages (left) and Flagged (right)
- Left panel shows all captured messages
- Right panel shows only AI-flagged messages for quick review
- Flagged panel auto-populates when messages are analyzed
- Improves moderation workflow by separating flagged content
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Call POST /api/backlog-sync when user selects a text channel
- Backlog sync now runs automatically on channel selection
- Fetches messages from last 24 hours for selected channel only
- Prevents empty message list on first channel selection
This resolves:
- Empty message list when selecting channel
- Backlog sync not being triggered
- Messages not loading until manual refresh
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Change runLLMAnalysis to accept array of texts instead of single text
- Batch up to 5 messages per AI request instead of 1 message per request
- drainQueue now collects batch before sending to AI API
- Reduces API calls by 5x and speeds up analysis significantly
- System prompt updated to handle batch JSON array responses
This resolves:
- Slow AI analysis (3 messages every 15 seconds)
- Too many API calls (one per message)
- Long queue backlog
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Fix fetchJson to extract JSON from streaming response text
- API returns text/event-stream with complete JSON object embedded
- Extract JSON by finding first { and last } in response
- Prevents "Unexpected non-whitespace character after JSON" parse errors
- Streaming response now properly parsed and analyzed
This resolves:
- AI analysis stuck on "[Streaming in progress...]"
- JSON parse failures on streaming responses
- AI analysis now completes successfully
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add activeRequests counter to track in-flight AI requests
- Limit concurrent requests to 1 (MAX_CONCURRENT_REQUESTS)
- drainQueue now waits if at max concurrency before processing next message
- Prevents overwhelming streaming LLM API with multiple concurrent requests
This resolves:
- AI LLM API overload from concurrent requests
- Streaming response conflicts
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Sync channels in parallel with concurrency limit of 3 instead of sequentially
- Reduces backlog sync time from O(n) to O(n/3) for n channels
- Prevents overwhelming Discord API with too many concurrent requests
- Maintains per-channel message batching for memory efficiency
This resolves:
- Slow backlog sync performance
- Sequential channel processing bottleneck
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Skip attachment download/upload to Picser (was failing with 400 errors)
- Store Discord's original attachment URLs directly as uploaded_url
- Mark attachments as immediately uploaded with Discord URL
- Remove processAttachmentUpload call and unused attachmentUploader import
- Eliminates slow upload cycle and API failures
This resolves:
- Attachment upload 400 errors
- Performance slowdown from failed upload retries
- Unnecessary network overhead
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Fix client startup order: fetch/apply server UI state BEFORE loadGuilds() to prevent overwriting persisted state with default guild
- Remove auto-post of first guild in loadGuilds() — let server state drive selection
- Refactor collectWatchableChannels() to collect text channels fast first, then discover threads in parallel with 5s per-channel timeout and 30s overall timeout to prevent blocking message sync
- Ignore /favicon.ico 404 in error logging to reduce noise
Fixes:
- UI state now persists across restart (was being overwritten by client startup race)
- Backlog sync no longer hangs on thread discovery (was blocking before message sync)
- Cleaner logs without favicon 404 errors
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add CHANNELS constant (1 for mono)
- Use audioBuffer.length for loop instead of float32Array.length
- Use getChannelData(0) assignment pattern from aa85dd9
- Proper buffer frame calculation with CHANNELS divisor
- Use createScriptProcessor instead of Tone.UserMedia for transmit
- Use analyser.getByteFrequencyData() for proper visualizer
- Keep per-user timing with userTimelines Map for listen
- Remove Tone.js dependencies from transmit
- Restore proper AudioContext usage
- Add audioContextListen and userTimelines to state
- Create AudioContext on listen toggle
- Parse user ID hash from PCM packet header
- Track playback timing per user to prevent audio gaps
- Use proper AudioContext timing instead of Tone.now()
- Clear timelines when toggling listen off
- Remove ES module import statement from dashboard.js
- Use global Tone object loaded via CDN
- Remove type=module from script tag
- Fixes module resolution error
- Replace AudioWorkletNode with Tone.UserMedia for microphone capture
- Use Tone.Analyser for waveform analysis and Tone.Meter for level detection
- Implement proper stereo audio capture with real-time PCM transmission
- Use Tone.context for audio playback with proper buffer handling
- Add Tone.js CDN to HTML template
- Convert dashboard.js to ES module for Tone.js import
- Improve audio quality and reliability with battle-tested library
- Create audio-worklet.js with MicrophoneProcessor for audio capture
- Implement noise gate and RMS calculation in worklet
- Send PCM data via MessagePort to main thread
- Update startStreaming to use AudioWorkletNode instead of deprecated ScriptProcessorNode
- Remove WebCodecs decoder complexity from listen
- Keep simple PCM playback for listen feature
- Remove broadcastOpusToWeb from types and webserver
- Revert recorder to PCM-only broadcast path
- Remove WebCodecs AudioDecoder from dashboard.js
- Simplify WebSocket handler to just play PCM frames
- Remove Howler.js and Tone.js dependencies
- Keep simple AudioContext playback that works reliably
- Rename playAudioData to playAudioDataDirect for clarity
- Remove duplicate playAudioData function with debug logging
- Use direct copyTo into temp Float32Array per channel
- Check isListening state in output callback
- AudioData.copyTo requires destination Float32Array, not AudioBuffer channel
- Create temp Float32Array per channel, copyTo into it, then set into AudioBuffer
- Properly handle 48kHz stereo Opus output to AudioContext
- AudioData.copyTo requires planeIndex parameter per channel
- Check isListening state before decode to prevent closed decoder errors
- Properly close decoder when leaving listen mode
- Queue packets if decoder not ready yet
- Add broadcastOpusToWeb to PcmBroadcaster interface for raw Opus packets
- Server broadcasts Opus frames with mode byte (1) + user hash + packet data
- Browser detects packet mode: mode=1 for Opus, mode=0 for legacy PCM
- Implement WebCodecs AudioDecoder for Opus decoding in browser
- Keep existing PCM playback as fallback for compatibility
- Show error if WebCodecs unsupported
- Fixes listen feature under Bun where native Opus decode unavailable
- Added functions to retrieve message location, sticker metadata, and display content in messageCapture.ts.
- Updated captureMessage function to store thread information and sticker metadata in the database.
- Modified messageStore.ts to support querying messages and attachments by thread ID.
- Updated types.ts to include thread_id in AttachmentRecord.
- Altered database schema in muxer-queue.ts to add thread_id column to attachments.
- Introduced ChannelSummary interface and listWatchableChannels method in voiceController.ts to fetch watchable channels.
- Added API endpoint in webserver.ts to retrieve channels for a given guild.