Commit Graph
100 Commits
Author SHA1 Message Date
MythEclipse d5c22a3959 fix(discord-gateway): handle forwarded message content via messageSnapshots
Two-layer fix for forwarded messages showing as empty/clean:

Layer 1 (messageMetadata.ts): getReferencedMessageContent() now falls
back to message.messageSnapshots Collection when channel.messages.cache
lookup fails. Discord stores forward content in message_snapshots API
field, not in message.content.

Layer 2 (moderationBuilders.ts): buildReferenceXml() now parses msg.
metadata JSON to extract reference.content when DB getMessageById()
fails (cross-server forwards not in local DB).

Previously: forward messages captured with empty parentContent →
LLM saw no reference text → '99% confidence, pesan kosong'.
Now: forward content flows through capture → metadata → analysis.
2026-06-23 23:27:23 +07:00
MythEclipse ed4a506ca7 refactor: split llmModerationClient.ts + add tests + metrics
## Split llmModerationClient.ts (2103 → 3 files)
- **moderationBuilders.ts** (67 lines) — shared: escapeXml, getAnalysisContent, buildReferenceXml
- **mediaAnalysisClient.ts** (656 lines) — vision analysis with multi-layer LRU/DB/phash caching, image/video download, ffmpeg frame extraction, prepareMediaMessage
- **moderationOrchestrator.ts** (998 lines) — callModerationLLM, runTextOnlyBatch, runMediaBatch, runModerationAnalysis, runSimpleTextFallback
- **llmModerationClient.ts** (30 lines) — re-export bridge (backward compat)

No import changes needed — aiAnalysisWorker.ts still imports from llmModerationClient.js.

## Unit tests (backend)
- vitest.config.ts + e2e.test.ts with 9 tests against production:
  - health, metrics, dashboard/stats, recordings, config, auth, guilds, negative (404/400)

## Monitoring metrics
- moderationMetrics.ts in backend health module:
  - LLM call count/duration/tokens
  - Cache hit/miss per layer
  - Media analysis count/download duration
  - Batch size distribution, errors, SearXNG, auto-delete
2026-06-22 20:38:34 +07:00
MythEclipse c00b1625fa chore: add E2E test script for production stack
- Tests: health, dashboard/stats, recordings, messages, config, auth, voice guilds, frontend, 404
- Validates JSON fields + HTTP status codes
- Runs against real production (imphnen.asepharyana.my.id)
- Usage: bash scripts/e2e-test.sh [url]
2026-06-22 18:45:45 +07:00
MythEclipse a3c99a08c3 fix: recordings endpoint 500 — column 'transcription' doesn't exist
- SELECT transcription FROM voice_recordings fails because table has no such column
- Removed non-existent transcription from SELECT and interface
- Previous sql.raw() parameter binding also broken — fixed with proper drizzle sql``
2026-06-22 18:22:46 +07:00
MythEclipse 3a282d8467 fix: recordings endpoint 500 — broken SQL parameter binding
- Hand-rolled ,  params with sql.raw() didn't actually bind values
- Drizzle's sql.raw() just inserts literal text — no parameter binding
- Replaced with proper sql`` tagged templates + sql.join() for conditions
- Each filter now correctly binds via drizzle's parameterized query
2026-06-22 17:54:09 +07:00
MythEclipse ad84d0a1bb fix: messages with text+media also go into text batch immediately
- Previously: text+media message went ONLY to media array → text waited for vision
- Now: text part goes to text batch (immediate LLM analysis), media parallel
- DB update is idempotent — second write to same message_id overwrites
- User sees text moderation results instantly, media follows when ready
2026-06-22 17:45:32 +07:00
MythEclipse e8286247d6 fix: parallelize text + media LLM analysis instead of sequential
- text-only and media analysis now run concurrently via Promise.all
- text no longer blocks on media download + vision analysis
- each path independently saves to DB when its own results are ready
- same batch still uses single context fetch + attachment lookup
2026-06-22 17:42:46 +07:00
MythEclipse dfabdc85cd feat: search ALL messages via SearXNG + Redis cache dedup
- Remove shouldSearchContent() trigger gate — search runs on all messages
- extractSearchQueries() now extracts from ANY message, not just trigger-matched
- Redis cache (24h TTL) prevents redundant searches for same query
- initSearxngCache() lazy-connects via config.REDIS_URL
- Cache miss→API, hit→skip — fire-and-forget writes
- Both text batch + media path simplified
2026-06-22 12:41:48 +07:00
MythEclipse 84f87104e7 refactor: remove hardcoded lists from prompt, use SearXNG as single source of truth
- Remove hardcoded hentai title lists (Boku no Pico, Euphoria, etc.) from prompt
- Remove hardcoded SARA examples from prompt (Kitabonia, etc.)
- Prompt now tells LLM to use <web_searches> as evidence instead of hardcoded knowledge
- Evidence priority: searxng > web_content > media_analysis > internal model
- Code-side triggers in searxngSearch.ts still filter which messages to search
- LLM makes final decision based on search results, not static lists
2026-06-22 12:01:55 +07:00
MythEclipse 18ee8a35d2 feat: SearXNG search enrichment for moderation
- extractSearchQueries(): extract specific terms from trigger patterns
  instead of searching entire message (e.g. 'bokuno pico' from 'nonton bokuno pico anime')
- Add hentai studio/publisher triggers (Pink Pineapple, Maryjane, etc.)
- Fix media path SearXNG: use extractSearchQueries instead of quoted-only
- Prompt: add <web_searches> usage instructions so LLM actually uses search data
- Priority: searxng evidence > web_content > internal model knowledge
2026-06-22 10:58:52 +07:00
MythEclipse 641fb47d10 fix: hentai reference detection + severity high auto-delete
- Add explicit hentai title detection rule (Boku no Pico, Euphoria, Bible Black,
  Kuroinu, loli/shota) -> sexual_deviation severity high, recommended_action delete
- LLM flagged correctly but severity 'medium' caused auto-delete skip in fallback path
2026-06-22 10:28:16 +07:00
MythEclipse f502918b27 feat: multimodal video detection + reply/forward/crosspost + batch optimization
- Video frame extraction via ffmpeg (4 key frames per video → vision LLM)
- Video display in FE MessageCard with HTML5 <video> player
- Reply/forward/crosspost indicator in FE + pipeline in DG/BE
- Fix: missing sanitizeAiContent + escapeXml in media path (prompt injection)
- Optimize: text-only batch results saved to DB immediately, no longer wait for media analysis
- BE mapper/schema/repo: add reference fields (is_reply, is_forward, etc.)
2026-06-22 09:46:06 +07:00
MythEclipse dc62b283c0 refactor(ai-moderation): fix all 8 issues per review
- #2: Duplikasi contoh → single-source ALL_EXAMPLES array + formatExamples()
- #3: Hierarki evasion → Level 1 (Wajib Flag) vs Level 2 (Pilih Clean)
- #4: Dead code → remove duplicate PromptMode, cleanup
- #5: Sanitasi AI content → sanitizeAiContent() + CDATA wrapping for
      channel culture & user profile (prevents prompt injection)
- #6: Contoh personality → match actual XML format (<message>,
      <user_profile>, <content> tags instead of plain text)
- #7: Contoh invite link → example #29 added
- #8: 'Deskripsi selesai.' removed from stickerPrompt.ts
- Image analysis balance: teks = gambar (equal weight), no more bias
- Removed LGBT exclusion from SYSTEM_RULES
- Removed all template fallback language, enforce specific descriptions
2026-06-21 22:14:59 +07:00
MythEclipse 04f2862abc feat(ai-moderation): profile learner ai_status filter + channel-aware + simple fallback memory
- userProfileLearner.ts: filter query to only clean messages (eq ai_status='clean')
  to prevent profile contamination from flagged content. Also select channel_id
  to group messages by channel in prompt, enabling channel-aware personality
  summarization (user may behave differently across channels).
- llmModerationClient.ts (runSimpleTextFallback): inject user profile into
  both the classify prompt and the reason prompt, so even the last-resort
  fallback path has personality/memory context instead of being blind.
2026-06-21 20:07:51 +07:00
MythEclipse e5fa2b3f30 feat(ai-moderation): personality-rich user/channel profiling & memory-aware analysis
- moderationPrompt.ts: Add PERSONALITY & MEMORY section instructing LLM to
  use user_profile and channel_culture in analysis, with 3 new few-shot
  examples (normal profile use, deviation detection, don't overfit)
- userProfileLearner.ts: Richer personality summary prompt — asks for
  communication style, passion topics, unique habits/signature traits,
  social dynamics, and writes in warm observer prose
- cultureLearner.ts: Richer channel culture summary — asks for 'vibe',
  inside jokes, social norms, dynamics. Writes in anthropologist style
2026-06-21 19:11:11 +07:00
MythEclipse 21b818a344 feat: add forwarding & reply detection with frontend indicators
- Enhanced messageMetadata to capture referenced message content
- Added reply indicator (↩️ Replying to @username + content snippet)
- Added forward badge (🔁 Forwarded) and crosspost badge (📢 Crossposted)
- Frontend auto-fetches referenced message content when metadata is empty
- Added getMessageById API helper
2026-06-21 18:22:27 +07:00
MythEclipseandClaude 752d144dc0 refactor(fe): overhaul — split types, type-safe WS, remove dead deps/code
- Remove unused deps: gsap, @tanstack/react-query, three, r3f, drei, autoprefixer
- Split types from shared/api/client.ts into entities/{guild,voice,media,ui,recording,dashboard}
- Type-safe WebSocket handlers using WsEventMap — 0 'as' casts in App.tsx
- Replace gsap with framer-motion in AuthOverlay
- Remove dead code: useMascotSummary, gsapCardHover, live/components/index barrel
- Fix bare console calls → use createLogger from @bete/shared/logger
- Clean up unused imports and variables (aiVariant, etc.)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 22:44:28 +07:00
MythEclipseandClaude 9af2d7d4dd refactor(fe): DRY components, hooks, a11y fixes, and WS/client improvements
- Extract StatusBadge, SummaryList, ProfileDetail shared components (~300 lines deduplicated)
- Extract usePaginatedList<T>, useItemDetail<T> generic hooks (~170 lines deduplicated)
- Fix a11y: Badge (role=status, dark variants), Button (aria-disabled, motion-safe), Input (aria-invalid, errorId), Select (error variant), Skeleton (aria-hidden), MobileTabBar (full tab ARIA), Toast (timer leak fix, role=alert, keyboard dismiss), Card (role=region)
- Fix API client: buildSearchParams helper, request timeout, password caching, named types
- Fix WS: typed 24 event payloads (was all unknown), exponential backoff reconnect, max 20 attempts, msg.data guard
- Fix bug: listDashboardChannels cursor pagination was silently dropped
- Remove duplicate shimmer keyframes from tailwind.config.js
- Fix WaveformPlayer non-null assertion

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-14 15:22:29 +07:00
MythEclipse 41e67423b8 chore(services): update components based on recent changes
Changes:
 services/frontend/src/features/dashboard/components/ChannelProfileDetail.tsx | 258 +++++++++++-----------------------------------------------------------------
 services/frontend/src/features/dashboard/components/ChannelSummaryList.tsx   | 171 ++++++++-------------------------------------------
 services/frontend/src/features/dashboard/components/DashboardStats.tsx       |   8 ++-
 services/frontend/src/features/dashboard/components/UserProfileDetail.tsx    | 297 +++++++++++++---------------------------------------------------------------------------
 services/frontend/src/features/dashboard/components/UserSummaryList.tsx      | 204 +++++++++++-------------------------------------------------
 services/frontend/src/features/dashboard/hooks/useDashboard.ts               | 203 +++++++++++++++---------------------------------------------
 services/frontend/src/features/messages/components/MessageCard.tsx           |  10 +--
 services/frontend/src/shared/api/client.ts                                   |  87 +++++++++++++++++++-------
 services/frontend/src/shared/hooks/useItemDetail.ts                          |  58 +++++++++++++++++
 services/frontend/src/shared/hooks/usePaginatedList.ts                       | 105 +++++++++++++++++++++++++++++++
2026-06-14 15:16:18 +07:00
MythEclipse 2b084b326f a 2026-06-14 05:10:58 +07:00
MythEclipseandClaude 6733ea8f01 fix(db): add 0011_add_voice_transcription to drizzle journal
Migration SQL file existed but was never registered in _journal.json,
so Drizzle skipped it. Every voice recording insert failed with:
  PG code 42703: column "transcription" does not exist

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-14 04:59:44 +07:00
MythEclipseandClaude a2beda77c4 fix(db): surface PG error code/detail/cause in voice recording insert failures
Drizzle wraps PG errors — the previous log only showed the formatted query
text. Now extracts code, detail, schema, table, constraint, severity from
the error envelope and from .cause to make the actual Postgres error visible.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-14 04:40:22 +07:00
MythEclipseandClaude dbc2879e16 fix(voice): resolve Redis subscriber corruption, transmitter races, and DB error logging
Redis root cause: VoiceHandler passed redisPub to transmitter.start(),
which called .subscribe() on it — permanently converting the publish
connection to subscriber mode. Every subsequent command reply and status
update failed.

Fixes:
1. Transmitter now creates its own Redis client via new IORedis()
2. Mutual exclusion gate serialises start/stop to prevent null-deref races
3. PassThrough drain listeners cleaned up to stop MaxListenersExceeded
4. FFmpeg SIGTERM flagged as expected exit (no more false level-50 errors)
5. Voice recording repo captures PG error code/detail for diagnostics

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-14 04:23:04 +07:00
MythEclipse 32b0b20ca7 chore(services): update components based on recent changes
Changes:
 services/discord-gateway/src/shared/database/voiceRecordingRepo.ts | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)
2026-06-14 03:31:40 +07:00
MythEclipse 93634d129a chore(services): update components based on recent changes
Changes:
 services/discord-gateway/src/modules/command-handler/voice.handler.ts | 10 ++++----
 services/discord-gateway/src/modules/voice-recording/transmitter.ts   | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
 2 files changed, 72 insertions(+), 29 deletions(-)
2026-06-14 03:28:24 +07:00
MythEclipseandClaude c317cfb420 fix(ci): resolve TS build errors across all services
- recordings.routes.ts: cast req.params.id to string (express 5 typed params)
- recordings.service.ts: cast Record<string,unknown>[] via unknown first
- guilds.routes.ts: cast req.params.guildId to string (2 sites)
- transmitter.ts: capture pcmStream ref locally + re-acquire in drain callback

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-14 01:17:18 +07:00
MythEclipse 92d73fe12d chore(services): update components based on recent changes
Changes:
 .env.example                                                     | 5 +++++
 services/discord-gateway/src/modules/voice-recording/recorder.ts | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)
2026-06-14 00:57:08 +07:00
MythEclipse b0422777ec chore(services): update components based on recent changes
Changes:
 services/backend/src/ws/server.ts | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 72 insertions(+), 16 deletions(-)
2026-06-14 00:52:04 +07:00
MythEclipse 7789aca620 chore(services): update components based on recent changes
Changes:
 services/discord-gateway/src/app/shutdown.ts | 8 ++++++++
 1 file changed, 8 insertions(+)
2026-06-14 00:45:59 +07:00
MythEclipse ac661b64f4 chore(services): update components based on recent changes
Changes:
 services/discord-gateway/src/app/bootstrap.ts                                    | 24 ++++++++++++++++++++++++
 services/discord-gateway/src/modules/voice-recording/recorder.ts                 | 10 ++++++++++
 services/discord-gateway/src/modules/voice-recording/recorder/speakingHandler.ts |  9 ++++++++-
 3 files changed, 42 insertions(+), 1 deletion(-)
2026-06-14 00:45:31 +07:00
MythEclipse c886dfb184 chore(services): update components based on recent changes
Changes:
 services/discord-gateway/src/modules/voice-pcm-ws/index.ts            |   1 +
 services/discord-gateway/src/modules/voice-pcm-ws/voicePcmWsClient.ts | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 152 insertions(+)
2026-06-14 00:43:50 +07:00
MythEclipse 5d1d53a305 chore(packages): update components based on recent changes
Changes:
 packages/shared/src/config/index.ts | 8 ++++++++
 1 file changed, 8 insertions(+)
2026-06-14 00:43:12 +07:00
MythEclipse f22201381f a 2026-06-13 23:58:29 +07:00
MythEclipse 9a896c7993 chore(services): update components based on recent changes
Changes:
 services/frontend/src/widgets/Sidebar.tsx | 51 +++++++++++++++++++++++++-------------------------
 1 file changed, 25 insertions(+), 26 deletions(-)
2026-06-13 19:47:06 +07:00
MythEclipse 23b45690ca chore(services): update components based on recent changes
Changes:
 services/backend/src/http/app.ts | 22 ++++++++--------
 services/frontend/src/App.tsx    | 81 ++++++++++++++++++++++++-----------------------------------
 2 files changed, 43 insertions(+), 60 deletions(-)
2026-06-13 19:46:56 +07:00
MythEclipse 82c1658bab chore(services): update components based on recent changes
Changes:
 services/frontend/src/features/messages/index.tsx | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
2026-06-13 19:43:32 +07:00
MythEclipse 28baeda5ad chore(services): update components based on recent changes
Changes:
 packages/shared/src/config/index.ts                                          |   7 +++
 packages/shared/src/moderation-types.ts                                      |   1 +
 services/backend/src/modules/recordings/recordings.service.ts                |   3 +-
 services/discord-gateway/drizzle/migrations/0011_add_voice_transcription.sql |   1 +
 services/discord-gateway/src/modules/voice-recording/recorder/segment.ts     |  10 ++++
 services/discord-gateway/src/modules/voice-recording/recorder/uploader.ts    |  15 ++++++
 services/discord-gateway/src/modules/voice-recording/voiceTranscriber.ts     |  51 ++++++++++++++++++
 services/discord-gateway/src/shared/database/schema.ts                       |   1 +
 services/discord-gateway/src/shared/database/voiceRecordingRepo.ts           |  17 ++++++
 services/frontend/src/features/live/components/RecordingsSubPanel.tsx        | 108 +++++++++++++++++++-------------------
2026-06-13 17:08:54 +07:00
MythEclipse 9bde518b71 chore(services): update components based on recent changes
Changes:
 services/backend/src/ws/redis-bridge.ts                | 31 ++++++++++++++++++++-
 services/backend/src/ws/server.ts                      | 36 +++++++++++++++++++++++-
 services/frontend/src/App.tsx                          | 12 ++++----
 services/frontend/src/shared/hooks/useAudioPlayback.ts | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 services/frontend/src/shared/hooks/useAudioTransmit.ts | 21 +++++---------
 5 files changed, 169 insertions(+), 22 deletions(-)
2026-06-13 17:00:02 +07:00
MythEclipse 1d06de5ce5 chore(services): update components based on recent changes
Changes:
 services/frontend/src/features/live/components/RecordingsSubPanel.tsx |  45 ++------
 services/frontend/src/features/live/components/WaveformPlayer.tsx     | 253 +++++++++++++++++++++++++++++++++++++++++++++
 services/frontend/src/features/live/components/index.ts               |   1 +
 3 files changed, 261 insertions(+), 38 deletions(-)
2026-06-13 16:56:17 +07:00
MythEclipse 5c8fa3d254 chore(services): update components based on recent changes
Changes:
 services/frontend/src/App.tsx                                          | 22 ++++++++++++++++++++++
 services/frontend/src/features/live/components/VoiceConnectionCard.tsx |  5 ++++-
 2 files changed, 26 insertions(+), 1 deletion(-)
2026-06-13 16:54:52 +07:00
MythEclipse 5459b13b03 chore(services): update components based on recent changes
Changes:
 services/frontend/src/App.tsx | 37 +++++++++++++++++++++++++++++++------
 1 file changed, 31 insertions(+), 6 deletions(-)
2026-06-13 16:54:29 +07:00
MythEclipse e76a874f11 chore(services): update components based on recent changes
Changes:
 services/frontend/src/shared/api/client.ts | 8 ++++++++
 1 file changed, 8 insertions(+)
2026-06-13 16:53:30 +07:00
MythEclipse d0d2c316cf chore(auto): task completed - unknown 2026-06-13 15:11:06 +07:00
MythEclipse 265251233a chore(auto): task completed - unknown 2026-06-13 15:03:21 +07:00
MythEclipse 9e9ce463cb chore(auto): task completed - unknown 2026-06-13 14:59:00 +07:00
MythEclipse fce24278f0 chore(auto): task completed - unknown 2026-06-13 14:49:47 +07:00
MythEclipseandClaude 3965ea79bc fix(gateway): voice speaking handler, metadata cache, transmitter backpressure
- speakingHandler: check subscriptions.has() BEFORE voiceActiveUser broadcast
- segment.ts: add LRU metadata cache (200 entries, avoids Discord API in hotpath)
- transmitter.ts: add backpressure handling with drain queue/flush
  (PassThrough.write() return value was ignored — potential OOM under load)
- cleanup backpressure queue on transmitter stop

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 14:38:06 +07:00
MythEclipseandClaude 29d4cb87b6 fix(gateway): voice module critical bugs
- shutdown ordering: DB pool closed AFTER voice disconnect (was before)
- muxer: amix (mix) -> concat (sequential) filter for OGG segments
- upload retries: 0->3 with proper backoff 1-10s
- teleUpload retry backoff: minTimeout 0->1000, maxTimeout 0->10000
- mediaSource: 64KB buffer bound on readFirstTwoLines, 1MB on extractMediaInfo
- ffmpegProcess: pipe stderr to structured logger instead of inherit

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 14:35:35 +07:00
MythEclipse e6e34281ff chore(auto): task completed - unknown 2026-06-13 14:24:09 +07:00
MythEclipse 1a195b737e chore(auto): task completed - unknown 2026-06-13 14:12:09 +07:00
MythEclipse 6822cb0bd3 chore(auto): task completed - unknown 2026-06-13 14:10:34 +07:00
MythEclipse 277d982c51 chore(auto): task completed - unknown 2026-06-13 14:05:17 +07:00
MythEclipseandClaude 14c0081f01 feat(discord-gateway): implement voice & push improvements
- Voice disconnect broadcast on stopRecording
- Multi-guild voice support (VoiceController Map<guildId>)
- Session finalization + auto-enqueue muxer job
- Recordings API: duration field, channelId/userId filters
- Transmitter Redis connection reuse (shared conn)
- FFmpeg stderr memory cap (4KB limit)
- 10 new Redis event channels + Redis bridge subscriptions
- New DB tables: message_reactions, message_edits
- Webhook notification module
- Gateway metrics / Prometheus endpoint
- Multi-guild message capture (MONITOR_GUILD_IDS array)
- Thread tracking, presence, channel topic, guild member events
- Edit history snapshot on message update
- Muxer audio post-processing worker

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 13:51:21 +07:00
MythEclipse fd3b5c5ca5 chore(auto): task completed - unknown 2026-06-13 13:39:02 +07:00
MythEclipse 111ba0a139 chore(auto): task completed - unknown 2026-06-13 13:36:13 +07:00
MythEclipse 942c33db7e chore(auto): task completed - unknown 2026-06-13 13:35:56 +07:00
MythEclipse eab8505889 chore(auto): task completed - unknown 2026-06-13 13:35:41 +07:00
MythEclipse 2e14b5e4ed chore(auto): task completed - unknown 2026-06-13 13:35:11 +07:00
MythEclipse d569ffa2db chore(auto): task completed - unknown 2026-06-13 13:12:49 +07:00
MythEclipse 4097b23dc3 chore(auto): task completed - unknown 2026-06-13 13:12:41 +07:00
MythEclipse e413cf9fca chore(auto): task completed - unknown 2026-06-13 13:12:29 +07:00
MythEclipse ff006980f8 chore(auto): task completed - unknown 2026-06-13 13:12:01 +07:00
MythEclipse 140a0ba46a chore(auto): task completed - unknown 2026-06-13 13:11:49 +07:00
MythEclipseandClaude 4fcab6b003 refactor(frontend): reorder sidebar — messages first, voice below
Default tab is now 'messages'; Voice & Media moved below
Messages in both desktop sidebar and mobile tab bar.
Updated Header titles/subtitles to match new order.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 12:50:13 +07:00
MythEclipse 615c23f061 chore(auto): task completed - unknown 2026-06-13 12:24:32 +07:00
MythEclipse dcede1d676 chore(auto): task completed - unknown 2026-06-13 12:11:37 +07:00
MythEclipse 5b04a4637c docs(frontend): add design tokens documentation 2026-06-13 11:54:20 +07:00
MythEclipse 1406ce3585 chore(auto): task completed - unknown 2026-06-13 11:46:15 +07:00
MythEclipseandClaude 30f8d7cce3 feat: replace corrections/tuner with dashboard module
Replace the corrections/adaptive-prompt-tuner feature with a new
dashboard module providing server stats and user profile overview.

Backend:
- Add dashboard module (routes, service, repository) with stats + user list + user detail endpoints
- Remove corrections module entirely
- Wire dashboard router in app.ts

Frontend:
- Add dashboard feature (DashboardStats, UserSummaryList, UserProfileDetail components + useDashboard hook)
- Remove tuner feature (CorrectionStats, CorrectionHistory, SubmitCorrection, useCorrections)
- Update API client from corrections → dashboard types/fns
- Rename tab 'tuner' → 'dashboard'
- Update MobileTabBar, Header, Sidebar links

Tests:
- Expand backend placeholder test with dashboard assertions
- Expand discord-gateway placeholder test with config/channel assertions

AI moderation:
- llmModerationClient: improve status/reply detection, expand safety categories, fix timer reset
- userProfileLearner: fix isReply refinement
- userProfileStore: add pending cache check
- messageMetadata: add crosspost type mapping
- migrate.ts: improve partial-index safety in schema push

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 11:24:42 +07:00
MythEclipseandClaude e3249edb6c feat: detect reply/forward/crosspost in message capture + inject into AI moderation
- Add is_reply, is_forward, is_crosspost, reference_message_id,
  reference_channel_id, reference_guild_id columns to messages table
- Update MessageRecord type with reference fields
- Extract reply/forward/crosspost from Discord message type/flags
- Track reference.type (DEFAULT=reply, FORWARD) and CROSSPOSTED flag
- Inject <reference> XML with parent content into LLM moderation prompt
- Add reply/forward/crosspost rules to moderation prompt rules
- Format context messages with [reply_to], [forward_from], [crosspost]
- Add migration 0009

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 00:55:42 +07:00
MythEclipseandClaude 0ac056dc8a fix(ai-moderation): audit prompts to reduce false positives
- ENTROPY rule: replace 'PILIH WARN' default with 'PILIH CLEAN'
- Add safe-list for code/log/stack traces/project names
- Narrow sexual_deviation: only flag explicit sexual solicitation
- Remove overbroad ontological graph (kostum hewan → furry) detection
- Add clean few-shot examples: error logs, project names, orientation disclosure
- Update simple fallback prompt with FP prevention rules
- Remove LGBT/furry from offensive username criteria

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 00:01:09 +07:00
MythEclipseandClaude 12f9b55000 fix(ai-moderation): implement prompt analysis recommendations
- Expand IMPHNEN domain rule to cover wildcard (*.imphnen.*)
- Trim redundant SARA examples from TEXT_ONLY_MODE (save ~950 tokens)
- Add debugging logs for channel culture injection into prompt
- Sync flag validation set with missing flags: potential_evasion, unclear_context

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 23:40:25 +07:00
MythEclipseandClaude b508a39ff7 fix(ai-moderation): prevent false positive SARA flag for IMPHNEN project name
- Add explicit system rule that IMPHNEN is the project's own name, not religion
- Rename 'Imphnemia 11:17' example to 'Kitabonia 11:17' to avoid name collision
- Ensures mentioning/promoting the project URL is not flagged as SARA

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 23:28:09 +07:00
MythEclipseandClaude 5c00c9f60b feat(ui): overhaul frontend with IMPHNEN visual identity
- Update CSS foundation: HSL→oklch color tokens, Poppins font, new utilities
- Replace Three.js sakura particles with CSS glow orbs
- Rebrand Header with IMPHNEN logo and gradient text
- Update all UI components (Button, Card, Badge, Input, Select, Tabs, Toast)
- Apply IMPHNEN design patterns (glass, gradient, grid) to layout
- Remove all hardcoded #7EC8E3/#FFB7C5/#FCA5A5 references
- Standardize rounded-xl across all components
- Replace emoji toasts with Lucide icons

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 23:00:52 +07:00
MythEclipseandClaude 7f3eb7b9ac feat(ui): add Adaptive Prompt Tuner tab with correction submission UI
- Add pgCorrectedModerationsTable to shared schema
- Create backend corrections module (stats, list, create endpoints)
- Add TunerPanel with Stats, History, and Submit sub-tabs
- Add AuthOverlay gate for Tuner (admin-only, same as Live)
- Set messages as default tab
- Wire Tuner into sidebar, header, and mobile tab bar

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 21:28:05 +07:00
MythEclipseandClaude fbc2184c6e feat(ai-moderation): add user profile self-learning system
Add user_profiles table, store, and background learner worker
that summarizes user communication style, topics, and personality.

- New user_profiles table (user_id PK, guild_id, profile_summary, last_analyzed_at)
- userProfileStore.ts — CRUD (get/update) following channelCultureStore pattern
- userProfileLearner.ts — background worker: queries 100 recent msgs per user,
  calls LLM for personality summary, updates every 12h
- Inject <user_profile> XML tag per-message in moderation prompt
- Start worker alongside cultureLearner in aiAnalyzer.ts
- Migration 0008 for user_profiles table

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 20:11:34 +07:00
MythEclipseandClaude 6effb51b5d fix(ai-moderation): don't cache text-only results for messages with media
- hasMediaContent now also checks evidence.attachments from metadata
  (not just DB attachment records), catching the race where attachment
  DB rows aren't inserted yet when analysis runs.
- Cache-hit guard: treat cached entries as miss when the message has
  media evidence in metadata, so stale 24h-freezes are avoided.
- Cache-write guard: skip storing text-only analysis results for
  messages whose metadata shows attachments/stickers/embeds. This
  prevents a text-only 'clean' result (from failed vision) being
  frozen for 24h, blocking future re-analysis with full media context.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 18:45:33 +07:00
MythEclipseandClaude 33b787dbd6 fix(migration): make all DDL idempotent with IF NOT EXISTS
- 0000: CREATE TABLE IF NOT EXISTS, CREATE INDEX IF NOT EXISTS,
  FK constraint wrapped in DO 539994 EXCEPTION WHEN duplicate_object
- 0001: ALTER ADD COLUMN wrapped in DO 539994 EXCEPTION WHEN duplicate_column
- 0002: CREATE TABLE IF NOT EXISTS, CREATE INDEX IF NOT EXISTS
- 0003: CREATE TABLE IF NOT EXISTS, CREATE INDEX IF NOT EXISTS
- 0006: ALTER ADD COLUMN wrapped in DO 539994 EXCEPTION,
  DROP COLUMN IF EXISTS

Allows migrations to run cleanly regardless of DB state —
handles fresh DB, partial migration, or wiped __drizzle_migrations.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 18:05:09 +07:00
MythEclipseandClaude fcb199a6ae fix(capture): exclude threads inside excluded channels
- Resolve parent channel ID for threads before checking
  EXCLUDED_CHANNEL_IDS set
- Thread messages now blocked if their parent channel is excluded

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 17:07:34 +07:00
MythEclipseandClaude c91f9f18cc refactor(capture): DRY age-restricted check, use Set for excluded IDs
- Move isAgeRestrictedMessage to messageMetadata.ts alongside
  isAgeRestrictedMetadata — single source of truth for NSFW logic
- Replace || chain of channel IDs with a Set for O(1) lookup
- Import isAgeRestrictedMessage in capture layer instead of inline

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 17:03:01 +07:00
MythEclipseandClaude ebfe942db9 fix(capture): skip age-restricted/NSFW channels entirely
Auto-filter all age-restricted and NSFW channels at capture layer
so messages never enter the database or reach frontend.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 17:00:02 +07:00
MythEclipseandClaude 1efa7b6505 feat(ignore): exclude channel 1323365288447574128 from capture
Add hardcoded channel ID to shouldCaptureMessageLocation so messages
from this channel are not stored, analyzed by AI, or sent to frontend.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 16:49:14 +07:00
MythEclipseandClaude Fable 5 906aef1807 fix(database): handle PG15+ public schema CREATE privilege error in seedDrizzleHistory
In PG15+, the CREATE privilege on the public schema is revoked from
non-owner roles by default. The seedDrizzleHistory function's
CREATE TABLE IF NOT EXISTS for __drizzle_migrations fails with 42501,
causing the gateway to crash-loop on startup.

Wrap the CREATE in a try/catch for 42501 — if the table already exists
(created by a prior run), we continue gracefully; otherwise re-throw.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 04:06:11 +07:00
MythEclipseandClaude Fable 5 490aad7704 fix(ci): add build tools to backend Dockerfile for native deps
@discordjs/opus requires Python and C++ build tools for native
compilation. The discord-gateway Dockerfile already had these but
the backend Dockerfile was missing them, causing CI build failure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 03:58:47 +07:00
MythEclipse 2e5371f3ee fix(discord-gateway): bypass Drizzle PG15 schema creation restrictions 2026-06-11 03:53:48 +07:00
MythEclipseandClaude Fable 5 378f1b6bdc fix(database): use public schema for drizzle migrations to avoid permission error
PostgreSQL error 42501 when Drizzle tries CREATE SCHEMA IF NOT EXISTS
"drizzle" — the DB user lacks schema creation privileges. Configuring
migrationsSchema: "public" keeps __drizzle_migrations in the existing
public schema, matching what seedDrizzleHistory already expects.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 03:34:16 +07:00
MythEclipse 8b114ca278 refactor(ai-moderation): expand SARA and religious blasphemy detection rules
Update the moderation prompt to include high-priority detection categories for:
- Fake scripture/verse parodies
- Claims of divinity or false religious movements
- Misuse of theological terms as internet slang/memes
- Mockery of religious figures and rituals

This change ensures stricter enforcement of SARA (Suku, Agama, Ras, Antargolongan) policies by explicitly defining religious blasphemy and parody as high-severity violations.
2026-06-11 02:40:11 +07:00
MythEclipse 2557a07916 feat(core): implement data retention, metrics, and enhanced media handling
This commit introduces several significant improvements across the backend and gateway services:

- **Data Retention**: Added an automated cleanup scheduler in `discord-gateway` to prune expired messages, attachments, and voice recordings based on configurable retention policies.
- **Observability**: Integrated `prom-client` in the `backend` service to expose Prometheus metrics via `/api/metrics` and added default Node.js runtime metrics.
- **Media Handling**: Enhanced `MediaHandler` in `discord-gateway` to support media URL resolution and improved playback status tracking.
- **API & Config**: Expanded the configuration endpoint to expose more system settings and reorganized `.env.example` for better readability.
- **Refactoring & Cleanup**:
    - Removed unused `better-sqlite3` dependency.
    - Refactored voice channel routing.
    - Improved error handling and testing coverage with comprehensive unit tests for shared utilities and error classes.
- **Documentation**: Added `MEMORY.md` for project context.
2026-06-10 20:56:16 +07:00
MythEclipse f04b0f0b42 refactor(voice): optimize recording pipeline and improve performance
Refactor the voice recording and playback systems to improve efficiency, reduce latency, and enhance Docker build performance.

- **Infrastructure**: Optimize Dockerfiles using build mounts for pnpm cache and reorder layers for better caching of dependencies and build tools.
- **Backend/Gateway**:
  - Refactor `broadcast` module to use a generic event-based system instead of hardcoded functions.
  - Simplify voice recording logic by merging metadata and segment management into a unified `segment.ts`.
  - Optimize audio downsampling in `streamSetup.ts` using `Int16Array` views for better performance.
  - Implement `withFallback` utility for more robust Redis/Database command execution.
- **Frontend**:
  - Optimize audio playback visualization using pre-computed level shapes and efficient RMS calculation.
  - Reduce latency in voice commands by prioritizing WebSocket communication over HTTP.
  - Improve base64 encoding efficiency in audio transmission.
- **General**:
  - Add default value for `ADMIN_PASSWORD` in shared config.
  - Fix Docker healthcheck to use `127.0.0.1` instead of `localhost`.
2026-06-09 22:04:05 +07:00
MythEclipseandClaude Opus 4.8 823b342c2c fix: remove --wait flag from docker compose up
The --wait flag causes the deploy to abort when a container exits
immediately (e.g., due to transient DB connection issue on startup).
With restart: unless-stopped, containers will auto-recover without
blocking the deployment pipeline.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 20:48:39 +07:00
MythEclipseandClaude Opus 4.8 c371317755 fix: add retry logic for docker compose pull transient errors
GitHub Container Registry pulls occasionally fail with 'connection reset
by peer'. Adding a 3-attempt retry loop with 5s backoff between pulls
to handle transient network errors gracefully.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 20:39:32 +07:00
MythEclipseandClaude Opus 4.8 655380dd8d fix: build @bete/shared before frontend in Dockerfile
TypeScript compilation in the frontend Docker build fails with TS2307:
Cannot find module '@bete/shared' because the shared package's .d.ts
files in dist/ were never generated. The backend and discord-gateway
Dockerfiles already have this build step — frontend was missing it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 20:35:35 +07:00
MythEclipseandClaude Opus 4.8 07032ab521 refactor: atomic, DRY, and logging improvements across codebase
- Split llmModerationClient.ts (2170 lines) into 5 focused sub-modules
- Split aiAnalyzer.ts (1282 lines) into 4 modular pipelines
- Split messages.db.ts (826 lines) into 5 domain-specific modules
- Moved shared schema to @bete/shared, eliminated backend duplication
- Added createChildLogger to all voice-recording and AI moderation modules
- Extracted tryCommandThenFallback, normalizeMediaState, DEFAULT_VOICE_STATUS
- Created shared pagination.ts utility, eliminated 5+ cursor-pagination duplications
- Created shared messageMapper.ts for row mapping
- Standardized backend error handling with asyncHandler
- Added frontend createLogger utility and useAsyncAction hook
- Added structured logging to frontend hooks, socket, and API client

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 19:46:08 +07:00
MythEclipseandClaude Opus 4.8 b68789fffc refactor: atomic, DRY, and logging improvements
- Shared Redis channel constants as single source of truth (redis-channels.ts)
- commandHandler.ts split into VoiceHandler, MediaHandler, GuildHandler,
  ModerationHandler with handler-registry.ts dispatch
- messageStore.ts (1322 lines) split into domain-specific DB files:
  messages.db.ts, attachments.db.ts, reviews.db.ts,
  moderation-actions.db.ts, retention.db.ts
- recorder.ts startSpeaking callback extracted into speakingHandler.ts,
  streamSetup.ts, segmentFinalizer.ts
- autoDeleteManager.ts split into autoDeleteEligibility.ts,
  autoDeleteNotify.ts, autoDeleteLogger.ts
- Added createChildLogger() logging across 8 service files
- Backend messages.repository.ts migrated from raw SQL to Drizzle ORM
- Fixed biome.json to exclude packages/**/dist/* from lint
- Fixed config.ts GUILD_ID pre-existing type error

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 17:34:18 +07:00
MythEclipse 7108f6bb47 feat(system): implement graceful shutdown and expand websocket events
Improve system reliability and real-time capabilities by implementing a robust lifecycle management system and adding new broadcast events for attachments and voice recordings.

- Implement asynchronous graceful shutdown in backend to close HTTP, WebSocket, Redis, and database connections.
- Add new WebSocket broadcast events: `attachment_created`, `voice_recording_started`, `voice_recording_stopped`, `voice_recording_uploaded`, and `analysis_queue_status`.
- Refactor media status handling to use boolean `playing` state instead of string-based status.
- Centralize `PageResult` and `VoiceRecording` types to improve consistency between frontend and backend.
- Update frontend API client to include `listRecordings` and handle new WebSocket event types.
- Fix type mismatches in voice command handling and media status reporting.
2026-06-09 16:56:44 +07:00
MythEclipseandClaude Opus 4.8 3a7b005d95 fix: resolve architecture disconnects and codebase weaknesses
- Add TEXT_CHANNEL_ID and TEXT_GUILD_ID to config schema (fix silent channel monitoring)
- Remove dead files: message-capture/broadcaster.ts, voice-recording/index.ts
- Fix WebSocket voice_command payload to forward from frontend
- Implement moderation:action handler in commandHandler
- Fix useMascotChat to use canonical request() wrapper
- Fix useAudioPlayback userId hash collision (use string not parseInt)
- Add catch blocks to useMediaControl.skip/stop
- Add typed broadcast functions (messageAnalyzed, voicePcmData, voiceActiveUser)
- Apply Biome formatting and lint fixes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 16:36:23 +07:00
MythEclipseandClaude Opus 4.8 30c9e86edc test: add placeholder test files for vitest
Prevents vitest from exiting with code 1 when no test files exist.
Adds minimal test files to backend and discord-gateway services.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 15:40:40 +07:00
MythEclipseandClaude Opus 4.8 7d6612bb2d refactor: resolve architecture disconnects and codebase weaknesses
- Consolidate eventTypes.ts as single source of truth for Redis channels:
  - Remove duplicate DiscordGatewayEvent interface from eventBroadcaster.ts
  - Replace all hardcoded channel strings with EventChannels constants
  - eventTypes.ts is no longer an orphan file

- Remove dangerous moderation action feature (selfbot safety):
  - Remove /messages/:id/moderate endpoint from backend
  - Remove moderation:action handler from commandHandler.ts
  - Remove publishFireAndForgetCommand (wrong envelope format)
  - Verified no remaining references to moderation:action in code

- Remove unused getCommandPublisher import from redis-bridge.ts

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 13:22:09 +07:00
MythEclipseandClaude Opus 4.8 3614d32701 fix: resolve architecture disconnects and codebase weaknesses
- Standardize MessageRecord types — single source of truth from @bete/shared
- Clean up config: remove unused GUILD_ID/TEXT_GUILD_ID/TEXT_CHANNEL_ID, fix WEBSERVER_PORT default (3001), remove default admin password
- Move mascot_chat_messages table to Drizzle schema with proper migration
- Remove runtime DDL (CREATE TABLE IF NOT EXISTS) from mascot-chat repository
- Remove phantom analytics/ module from documentation
- Add better-sqlite3 dependency to root devDependencies
- Replace 'as any' casts with proper type assertions across AI moderation
- Add error logging to silent catch blocks in LLM client
- Apply Biome formatting and import organization

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 13:07:01 +07:00
MythEclipse 67d66bb5dd refactor(shared): centralize configuration and types
Migrate configuration validation and core moderation types from individual services to the `@bete/shared` package to ensure consistency across the monorepo.

- Move `AppConfig` and moderation-related interfaces to `packages/shared`.
- Replace service-specific Zod schemas with the centralized shared configuration.
- Refactor `services/backend` and `services/discord-gateway` to consume shared config and types.
- Remove redundant type definitions and local configuration logic in services.
- Update `packages/shared` exports to include new `config` and `moderation-types` modules.
- Clean up unused files and deprecated utility functions in `packages/shared`.
2026-06-09 11:56:03 +07:00