Commit Graph
100 Commits
Author SHA1 Message Date
MythEclipse 0a71e76e62 fix(ai-moderation): enforce concurrency cap, prune stale counters, and prevent retry collisions 2026-06-02 22:12:03 +07:00
MythEclipse 9c352c94c9 chore: no staged changes 2026-06-02 22:05:47 +07:00
MythEclipse 862586a863 No staged changes found. 2026-06-02 22:04:46 +07:00
MythEclipse 1359dd4955 chore: no staged changes 2026-06-02 22:04:09 +07:00
MythEclipse a4e91822f6 chore: no staged changes 2026-06-02 22:03:53 +07:00
MythEclipse 55042ca9eb chore: no staged changes 2026-06-02 22:03:44 +07:00
MythEclipse 1e1fbb4583 fix(discord-gateway): require LLM API key only when AI analysis is enabled 2026-06-02 21:46:15 +07:00
MythEclipse 831bb692d9 chore: no staged changes 2026-06-02 21:44:42 +07:00
MythEclipseandClaude Opus 4.8 543be63503 chore: remove deprecated createLogger alias from @bete/shared/logger
Zero usages found across the codebase. Safe to delete.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 21:27:07 +07:00
MythEclipse 19028cf244 refactor: migrate discord-gateway from winston to @bete/shared/logger and utils
- Replace all local logger imports (../../shared/logger/logger.js) with @bete/shared/logger across 26 files
- Remove winston dependency, add pino to discord-gateway package.json
- Delete shared/logger/logger.ts (winston-based, 132 lines) and serialization.ts (109 lines)
- Replace local retryWithBackoff imports with @bete/shared/utils across 6 files
- Delete shared/utils/retry.ts (42 lines)
- Add CustomLogger type alias to @bete/shared/logger for backwards compatibility
- Remove logger param from all retryWithBackoff calls and uploadToTele interfaces
- Frontend: convert entity type files to re-exports from shared/api/client.ts
- Full monorepo typecheck clean (4/4 packages)

35 files changed, 42 insertions(+), 488 deletions(-)
2026-06-02 21:23:12 +07:00
MythEclipse 2d79d8aefd feat(shared): reorder AppError constructor to (message, code, status), add singleton logger, retry and TTL cache utilities 2026-06-02 21:06:42 +07:00
MythEclipse 9045e7e347 chore(backend): switch moduleResolution to bundler and remove baseUrl from tsconfig 2026-06-02 19:14:50 +07:00
MythEclipse 61b5a59ed3 chore: auto-commit task - 2026-06-02 19:08:06 +07:00
MythEclipse 0e61ad90e2 chore: auto-commit task - 2026-06-02 19:06:23 +07:00
MythEclipse 685a6b2ea9 chore: auto-commit task - 2026-06-02 19:04:49 +07:00
MythEclipse d1ad397be6 chore: session auto-commit 2026-06-02 18:57:38 +07:00
MythEclipse 924a6b8819 chore: session auto-commit 2026-06-02 18:57:13 +07:00
MythEclipse 0fa49b3613 chore: session auto-commit 2026-06-02 18:55:48 +07:00
MythEclipseandClaude Opus 4.7 de29f3d011 chore: update discord.js-selfbot-v13 submodule to formatted version
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 18:48:27 +07:00
MythEclipse 1a0090429e chore: auto-commit task - 2026-06-02 18:47:18 +07:00
MythEclipse d41c086253 chore: session auto-commit 2026-06-02 18:34:55 +07:00
MythEclipse 5520094725 chore: auto-commit task - 2026-06-02 18:31:32 +07:00
MythEclipseandClaude Opus 4.8 363676b608 fix: remove dead OpenAI client instance and fix ChatCompletion type imports
- Delete unused OpenAI WAF bypass client block (60+ lines) from both monolith
  and microservice llmModerationClient.ts
- Replace OpenAI.Chat.Completions.ChatCompletion with type-only ChatCompletion
  import from openai/resources/chat/completions
- All LLM chat calls already go through centralized llmClient.ts helper

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 18:22:42 +07:00
MythEclipse 71de941470 chore: session auto-commit 2026-06-02 18:09:00 +07:00
MythEclipseandClaude Opus 4.8 b405e0e9a6 refactor: centralize all LLM chat.completions.create calls into llmClient helper
- Create llmClient.ts (monolith + microservice) with llmChat(), llmVision(), llmDetectBadwords()
- Refactor llmModerationClient.ts: vision and moderation batch calls use llmClient
- Refactor indonesianTextNormalizer.ts: badword detection uses llmClient
- Remove unused withLlmConcurrency and direct openai.chat.completions.create imports
- All LLM config (model, tokens, concurrency, retry) now maintained in one place

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 18:05:20 +07:00
MythEclipse 292fcbf238 chore: session auto-commit 2026-06-02 17:55:42 +07:00
MythEclipse a2d4ba3f95 chore: auto-commit task - 2026-06-02 17:45:47 +07:00
MythEclipse e0d54b7770 chore: auto-commit task - 2026-06-02 17:33:19 +07:00
MythEclipseandClaude Opus 4.8 1bc0b7c7bb refactor: simplify AI moderation pipeline to Primary AI only, fix stickerCache executeGet
- Remove Groq and NVIDIA fallback from text moderation pipeline
- Remove GROQ_API_KEY, GROQ_MODERATION_*, NVIDIA_NEMOTRON_* config vars
- Update source enum: remove 'groq' and 'nvidia' from cache/schema types
- Rewrite indonesianTextNormalizer to use Primary AI only (no fallback chain)
- Rewrite remote test to test Primary AI only
- Fix stickerCache executeGet missing empty params array

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 17:25:55 +07:00
MythEclipse 049fd49737 chore: session auto-commit 2026-06-02 17:25:01 +07:00
MythEclipse b23ccf0837 chore: session auto-commit 2026-06-02 17:12:42 +07:00
MythEclipse 498ab73d62 chore: auto-commit task - 2026-06-02 17:08:42 +07:00
MythEclipse 406a6cbf79 refactor: migrate sticker cache to PostgreSQL, remove versioning
- Replace file-based sticker cache (.dat + index.json) with PostgreSQL sticker_cache table
- Remove model_version column and all versioning logic (git branch detection, GitHub API, CACHE_MODEL_VERSION)
- Strip VISION_MODEL_VERSION, logCacheEvent calls, and version filtering from SQL queries
- Remove STICKER_CACHE_DIR and STICKER_CACHE_MAX_SIZE_MB config variables
- Delete dead migration add_model_version_to_cache.sql

textCacheStore.ts reduced 482→204 lines (-57%)
stickerCache.ts reduced 210→144 lines (-31%)
Total: 11 files changed, 233 insertions, 591 deletions
2026-06-02 14:05:51 +07:00
MythEclipseandClaude Opus 4.8 e584a7941e fix(text-cache): apply model version migration on existing dbs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 13:05:05 +07:00
MythEclipseandClaude Opus 4.8 e5673c2bbd feat(text-cache): resolve cache version from real GitHub API, no static env or dummy
- Add fetchRemoteBranchFromGitHub() to query https://api.github.com/repos/MythEclipse/bete for actual default_branch
- Add resolveBranch() tiered resolver: git CLI → GitHub API → env → error
- Async post-startup branch resolution upgrades version from emergency fallback to real remote branch
- normalizeBranchName() for consistent version key formatting
- Emergency fallback 'v1' logged as ERROR with repo context — not a silent dummy
- Removed static env-first approach; env is now tier 3 override, not tier 1

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 12:52:56 +07:00
MythEclipseandClaude Opus 4.8 682fb31deb fix(text-cache): add missing model_version column to migration + strict git detection
- Create new migration 0001_add_model_version_to_cache.sql to add model_version column to text_analysis_cache table (default 'v1')
- Add composite index on source + model_version for efficient cache lookups
- Improve git branch detection in textCacheStore.ts:
  * Check CACHE_MODEL_VERSION env var first (required in Docker)
  * Suppress stderr with stdio pipes to eliminate spurious warnings
  * Log ERROR (not warning) when git unavailable AND no env var set
  * Only fall back to 'v1' as last resort, preventing silent dummy usage
- Remove unused imports (logModelVersionChange, logCacheInvalidation) and previousVersion variable
- Fixes repeated 'column model_version does not exist' errors on bot startup

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 12:46:37 +07:00
MythEclipse 505c30f124 chore(discord-gateway): remove unused imports from response logger
- aiAnalyzer.ts: removed unused logAnalysisSummary and logFalsePositiveDetected
- llmModerationClient.ts: removed unused logVisionAnalysis, logVisionError, logRetryAttempt

These functions are not called in the codebase.
2026-06-02 12:36:05 +07:00
MythEclipse 1acd452a2c fix(discord-gateway): resolve type errors in error logging - cast unknown error types to Error | string for logModerationError calls
- aiAnalyzer.ts: cast error to Error | string in individual fallback phase
- llmModerationClient.ts: cast parseError to Error | string in parse response phase

Fixes GitHub Actions build failure (exit code 2)
2026-06-02 12:30:59 +07:00
MythEclipse 385fc0bbbf feat: add response logger for moderation/vision audit trail + cache model versioning
- Add responseLogger.ts with comprehensive logging: vision analysis, moderation
  analysis batches, cache hit/miss events, errors, retries, false positives,
  model version changes, cache invalidation
- Integrate responseLogger calls into llmModerationClient.ts (cache events,
  moderation results, errors, retries)
- Add model_version column to text_analysis_cache schema with composite
  index for efficient filtering
- Add migration SQL for model_version column
- Document CACHE_MODEL_VERSION in .env.example
2026-06-02 12:23:52 +07:00
MythEclipseandClaude Opus 4.8 c5c667b147 feat: comprehensive UX improvements — messages, analysis, moderation
Fix #1 (CRITICAL): Wire message_analyzed through Redis EventBroadcaster
- DG aiAnalyzer.ts: Add broadcastAnalysisCompleted() helper that publishes
  to both in-memory WS broadcaster AND Redis EventBroadcaster
- DG bootstrap.ts: Pass eventBroadcaster to startPendingAIAnalysisWorker()
- Fixes broken real-time chain so analysis results appear instantly

Fix #2: Collapsible AI Analysis with Rich Formatting
- MessageCard: AI analysis now collapsible with color-coded severity border
  (red/yellow/blue), summary line showing categories + confidence + severity
- Default collapsed for clean, expanded for warn/flagged

Fix #3: Toast Notifications for Flagged Content
- Wrap app in ToastProvider; ModerationAlertListener component listens for
  moderation_alert custom events and shows toast with emoji + details

Fix #4: Discord-style Message Grouping
- MessageFeed: Group consecutive messages from same user within 5 min
- MessageCard: Compact variant hides avatar, reduces padding for non-first

Fix #5: Moderation Action Buttons in UI
- BE: POST /api/messages/:id/moderate endpoint + publishCommand() for Redis
- FE: Delete/Warn buttons on flagged/warned cards with confirmation dialog

Fix #6: Search Results Include Full Data
- BE analysis.service.ts: SELECT all 26 message columns instead of just 11
- Search results now render with full MessageCard including images/analysis

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 12:17:51 +07:00
MythEclipseandClaude Opus 4.8 74400376a0 fix: vision analysis retry + fallback jelas saat gagal
Vision API call sekarang pakai retryWithBackoff (2 retries instant).
Fallback message tegas: 'GAGAL DIANALISIS — JANGAN mengasumsikan aman'.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 11:41:18 +07:00
MythEclipseandClaude Opus 4.8 64643bb066 perf: hapus semua cooldown/backoff delay — retry tanpa bottleneck
Semua retry sekarang instant (retries=0, minTimeout=0, maxTimeout=0):
- retry.ts (kedua) — default minTimeout/maxTimeout 0, factor 1
- config.ts (kedua) — DECODER_COOLDOWN_MS=0, AI_ANALYSIS_ERROR_COOLDOWN_MS=0
- llmModerationClient.ts (kedua) — retries 0 tanpa delay
- aiAnalyzer.ts (kedua) — retries 0, AI_ANALYSIS_ERROR_COOLDOWN jadi 0
- indonesianTextNormalizer.ts (kedua) — semua rate limit cooldown 0
- recorder.ts (kedua), teleUpload (3 files), uploader (2 files) — retry instant
- attachmentUploader (kedua) — retries 0
- syncRoutes.ts — BACKLOG_SYNC_COOLDOWN 0

20 files changed. Semua cooldown bottleneck dihapus.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 11:29:52 +07:00
MythEclipseandClaude Opus 4.8 62d7d19b53 fix: analysis output wajib deskriptif — bukan generic placeholder
Sebelumnya: 'Pesan hanya berisi attachment tanpa teks yang melanggar'
Sekarang: harus deskriptif berdasarkan tipe konten:
- Text only: '[user] membahas tentang <topik>. <konteks>.'
- Image only: 'Gambar berupa <jenis>. Terlihat <isi>.'
- Text+Image: '[user] mengirim <gambar> sambil membahas <topik>.'

Tambahkan contoh baik vs buruk di OUTPUT_INSTRUCTIONS sebagai format wajib.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 11:24:21 +07:00
MythEclipseandClaude Opus 4.8 a69de85564 fix: prompt dua mode — gambar+teks vs gambar saja
Sebelumnya aturan 'percaya teks terlebih dahulu' membuat model abaikan
deskripsi gambar saat teks kosong. Semua image-only message di-clean.

Fix:
- SYSTEM_RULES: pisah Mode 1 (teks+gambar) dan Mode 2 (hanya gambar)
- Mode 2: deskripsi gambar jadi bukti utama, WAJIB dibaca
- Gambar terminal/chat/editor kode/casual → clean
- Gambar dengan elemen judi NYATA (chip, roulette, odds) → flag
- 2 contoh few-shot baru: terminal clean, situs judi flag

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 11:15:53 +07:00
MythEclipseandClaude Opus 4.8 55ee8ade16 fix: vision model hanya deskripsi, tidak memutuskan moderasi
Root cause: vision model diminta untuk 'flag' dan 'menilai' gambar,
sehingga screenshot terminal/chat biasa diklaim sebagai 'situs perjudian'.

Fix:
- vision prompt: HANYA deskripsi objektif (objek, teks, layout, jenis gambar)
- larang tegas kata 'gambling', 'judi', 'pelanggaran', 'harus dihapus'
- tambah buildGeneralImageVisionPrompt di discord-gateway stickerPrompt
- MEDIA_INSTRUCTIONS: tegaskan batch LLM adalah hakim, vision hanya saksi mata
- deskripsi netral (terminal, chat, editor kode) tidak boleh jadi dasar flag

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 11:08:41 +07:00
MythEclipseandClaude Opus 4.8 5f419a6f0f feat: real guild/channel names from Discord + remove selectors in Messages/Analytics
- discord-gateway: add redis command handlers for guilds:list, guilds:text-channels, voice:channels
- backend: replace postgres synthetic names with redis commands to gateway (with fallback)
- frontend: remove guild/channel dropdowns from messages and analytics tabs
- frontend: auto-load all channels from monitor guild via guildId query param
- frontend: show guild name in messages/analytics headers instead of selector
- live tab: keeps guild/channel selectors with real discord names

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 11:02:54 +07:00
MythEclipseandClaude Opus 4.8 f1ddca5eee fix: false positive gambling detection + route collision + WS events (#1)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 10:44:27 +07:00
MythEclipseandClaude Opus 4.8 34719d3366 fix(ci): force remove stale containers before up to avoid name conflict
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 10:09:04 +07:00
MythEclipseandClaude Opus 4.8 1a794f35fb fix(ci): write .env and recordings to infra/docker/ relative to compose
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 10:00:40 +07:00
MythEclipseandClaude Opus 4.8 5fdf951435 fix(ci): proper git clone/pull pattern like ZeaVis-Edu
- Check if origin mismatch → rm and re-clone fresh
- Public repo — no auth needed for clone
- docker-compose.yml from repo source of truth

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:54:57 +07:00
MythEclipseandClaude Opus 4.8 e142bd5ad2 fix(ci): drop git clone, generate docker-compose inline instead
GITHUB_TOKEN can't auth git over HTTPS on VPS, so revert to inline
compose generation. nginx.conf already baked into proxy image.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:50:28 +07:00
MythEclipseandClaude Opus 4.8 53d16dc9cd fix(ci): use x-access-token for git clone/pull on private repo
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:47:30 +07:00
MythEclipseandClaude Opus 4.8 3d62477a68 fix(ci): update git remote URL before fetch on VPS
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:45:10 +07:00
MythEclipseandClaude Opus 4.8 5ae6b73c1f fix(ci): update repo URL to new location MythEclipse/GMW
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:42:14 +07:00
MythEclipseandClaude Opus 4.8 73efc716a5 fix(ci): use git-pull pattern like ZeaVis-Edu, all images from GHCR
- Replace build: blocks with image: from ghcr.io
- Simplify deploy: git clone/pull on VPS, then docker compose pull/up
- Remove SCP step entirely — nginx.conf baked into proxy image
- Rename containers to imphenbot-* to match existing VPS setup
- Fix backend port to 3000 for production

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:41:38 +07:00
MythEclipseandClaude Opus 4.8 8c4b32f5e1 fix(ci): correct nginx conf path in Dockerfile.proxy
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:26:47 +07:00
MythEclipseandClaude Opus 4.8 6010319486 fix(ci): rename Dockerfile.nginx to Dockerfile.proxy to match workflow matrix
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:09:52 +07:00
MythEclipseandClaude Opus 4.8 bf0d0090c9 fix(ci): use SCP to copy docker-compose and nginx from repo instead of hardcoded cat
- Add proxy to build matrix
- Replace heredoc docker-compose generation with appleboy/scp-action
- Fix nginx upstream backend port to 3000 (matches prod WEBSERVER_PORT)
- Copy docker-compose.yml and nginx.conf from repo via SCP staging

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:03:13 +07:00
MythEclipseandClaude Opus 4.8 cbe63809dd fix(infra): use ^~ prefix location for /api and /ws to match without trailing slash
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 08:51:57 +07:00
MythEclipseandClaude Opus 4.8 2b8d1ac703 feat(infra): replace traefik path routing with nginx reverse proxy
- Add nginx service with /api, /ws, and / location routing
- Move traefik labels to proxy service only (port 80)
- Remove traefik labels from backend and frontend services
- Backend routes to :3001 via nginx upstream
- WebSocket upgrade enabled for /ws path

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 08:36:34 +07:00
MythEclipseandClaude Opus 4.8 3b2709455e feat: implement all real backend endpoints, Redis pub/sub bridge, and gateway command handler
Backend (real implementations, no more stubs):
- Redis pub/sub bridge: subscribes to discord-gateway events (message/attachment/voice) and broadcasts to WS clients
- Redis command channel: backend publishes voice/media commands, discord-gateway executes and replies
- Voice service: connectVoice/disconnectVoice/getVoiceStatus via Redis commands with graceful fallback
- Media service: queue/skip/stop/volume via Redis commands, reads status from Redis cache
- Messages repository: ALL 7 methods now use real PostgreSQL queries (findMany, findById, findByChannel, create, update, delete, getAttachmentsByChannel)
- Analytics: period returns {start,end} epoch millis, overview includes hourly/topics/top_users, worst_flags as string[]
- Health check: actually queries SELECT 1 against database
- VoiceStatus type fixed: {connected, activeGuildId, activeChannelId, activeChannelName}
- Guild type: includes icon: string | null
- asyncHandler: accepts Promise<unknown> instead of Promise<void>

Discord Gateway:
- CommandHandler: subscribes to 'backend:command' Redis channel, executes voice/media commands, publishes replies
- Publishes voice:status and media:status to Redis for backend caching
- Shutdown handler updated to close command handler

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 00:32:38 +07:00
MythEclipseandClaude Opus 4.8 9b41eb9c12 feat(backend): implement all missing endpoints, real analytics queries, and WebSocket server
- Replace stub analytics.repository.ts with real PostgreSQL queries using pg.Pool
- Add /api/guilds, /api/config, /api/auth/login, /api/ui-state (GET/POST)
- Add /api/review, /api/recordings, /api/analysis/search
- Add /api/messages/:id/reanalyze endpoint
- Add /api/analytics/heatmap and /api/analytics/topics
- Implement media routes (stub responses, backend has no Discord voice client)
- Add WebSocket server at /ws with heartbeat and broadcast functions
- Fix analytics route paths to match frontend contract (dual paths for backward compat)
- Export getPool() from database module for raw SQL queries
- Register all new routers in app.ts

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 00:11:29 +07:00
MythEclipseandClaude Opus 4.8 5a094c926a fix(frontend): pass VITE_BE_API_URL and VITE_BE_WS_URL as Docker build args
Vite embeds env vars at build time, not runtime. The frontend code uses
VITE_BE_API_URL/VITE_BE_WS_URL but the workflow was setting wrong names
(VITE_API_URL/VITE_WS_URL). Now Dockerfile accepts build args and
workflow passes production URLs during docker build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 23:31:20 +07:00
MythEclipseandClaude Opus 4.6 ccd3ccd556 fix(frontend): add vite preview allowedHosts and port config
Vite preview blocks unknown hosts by default. Added allowedHosts for
imphnen.asepharyana.my.id and set port/host in preview config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 23:22:14 +07:00
MythEclipseandClaude Opus 4.6 0f6cdff8ee fix(frontend): set preview port to 3000 to match traefik loadbalancer
Vite preview defaults to port 4173 but traefik routes to port 3000.
Added --port 3000 to the preview script in package.json.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 23:11:47 +07:00
MythEclipseandClaude Opus 4.6 58afa98132 fix(discord-gateway): skip migration if schema tables already exist
Instead of failing on CREATE TABLE when tables already exist, check
information_schema for all 10 schema tables. If all exist, skip
migration gracefully. This handles deployments where DB was created
by a previous deployment with different migration files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 23:09:04 +07:00
MythEclipseandClaude Opus 4.6 02564e1302 fix(ci): remove --force-recreate from docker compose up
'up --force-recreate' after 'down' causes 'No such container' race.
After down, up creates fresh containers automatically.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 23:00:10 +07:00
MythEclipseandClaude Opus 4.6 5e3c2dddb9 fix(discord-gateway): add missing dependencies (axios, ws, @types/pg, @types/ws)
After removing root package deps, discord-gateway service was missing:
- axios (used in indonesianTextNormalizer.ts)
- ws (used in broadcaster.ts)
- @types/pg (needed for TypeScript pg declarations)
- @types/ws (needed for ws types)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 22:55:30 +07:00
MythEclipseandClaude Opus 4.6 e2c1197caf fix(discord-gateway): generate Drizzle migrations and copy to Docker image
Container crashed with 'Can't find meta/_journal.json file' because
Drizzle ORM migration files were never generated. Generated migrations
for all 10 schema tables and updated Dockerfile to copy drizzle/ to
/app/drizzle/ where the migrator expects them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 22:52:03 +07:00
MythEclipse baa652ffeb chore: regenerate pnpm-lock.yaml after removing root package dependencies 2026-06-01 22:49:25 +07:00
MythEclipseandClaude Opus 4.6 3afa6298e3 refactor(monorepo): remove root package deps, simplify Dockerfiles
Root package.json no longer a workspace member — no src/, no 38 shared
dependencies. Root is now workspace config with dev tooling only (biome,
drizzle-kit, tsx, typescript).

This means Dockerfiles only need:
- pnpm-workspace.yaml + pnpm-lock.yaml + package.json (workspace config)
- The specific service being built
- Only vendor/ packages that service actually depends on (discord-gateway → discord.js-selfbot-v13)

Before: each Dockerfile copied src/, vendor/*, packages/*, all services/
After: each Dockerfile copies only its service + needed vendor deps

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 22:47:47 +07:00
MythEclipseandClaude Opus 4.6 a9fa22262e fix(docker): correct CMD paths for service builds
- backend: node services/backend/dist/index.js (not dist/index.js)
- discord-gateway: node services/discord-gateway/dist/index.js
- frontend: pnpm --filter preview instead of root dev:web (missing frontend/ dir)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 22:42:45 +07:00
MythEclipseandClaude Opus 4.6 bf5849f235 fix(ci): add docker compose down before up to resolve container name conflict
The VPS has orphan containers from previous deployments that conflict with
new compose up. Running compose down --remove-orphans first cleans them up.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 22:19:08 +07:00
MythEclipseandClaude Opus 4.8 31c4a077d2 fix(docker): remove non-existent frontend/ and public/ COPY from frontend Dockerfile
These directories don't exist at root level; frontend assets are in services/frontend/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 22:11:40 +07:00
MythEclipseandClaude Opus 4.6 30b03c68b1 fix(docker): copy all workspace packages and root src to Dockerfiles
pnpm install --frozen-lockfile at workspace root requires ALL workspace
members to be present. Previously vendor/ packages and root src/ were
missing, causing TS2307 'Cannot find module' errors during build.

- Copy vendor/ (discord.js-selfbot-v13, discord-video-stream, better-sqlite3, drizzle-orm)
- Copy root src/ and vite.backend.config.ts
- Copy all services/ to each Dockerfile
- Copy frontend/ and public/ assets to frontend Dockerfile

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 22:09:51 +07:00
MythEclipseandClaude Opus 4.6 e6668ffe51 fix(docker): use pnpm --filter to build each service in Dockerfiles
Root scripts point to old paths (src/, frontend/) that don't exist in the
services/ monorepo layout. Use pnpm --filter to invoke each service's
own build script (tsc) instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 22:05:00 +07:00
MythEclipseandClaude Opus 4.6 37ab92e7ea fix(docker): upgrade all Dockerfiles to node:22-alpine for pnpm v10 compatibility
pnpm v10+ requires the built-in `node:sqlite` module which is only available
in Node 22+. All services now use node:22-alpine.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 22:01:35 +07:00
MythEclipseandClaude Opus 4.6 ee540d11f6 fix(ci): lowercase GHCR owner name to fix 'repository name must be lowercase' error
`github.repository_owner` returns 'MythEclipse' (mixed case) which GHCR rejects.
Hardcode lowercase 'mytheclipse' to match GHCR requirements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 21:59:06 +07:00
MythEclipseandClaude Opus 4.6 f20c2389a4 refactor(backend): flatten module structure, move routes to .routes.ts files
- Remove empty controllers/, services/, repositories/ subdirectories
- Move routes/index.ts into module.routes.ts (flat naming convention)
- Update imports in http/app.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 21:53:08 +07:00
MythEclipseandClaude Opus 4.8 c48a0c5e3b refactor: split monolith into 3 microservices (frontend, backend, discord-gateway)
- Extract services into services/{frontend,backend,discord-gateway}
- Create packages/shared/ for shared logger, errors, utils, types
- Setup Modular MVC pattern in backend (controller→service→repository)
- Setup event-driven architecture in discord-gateway with Redis pub/sub
- Move Docker files to infra/docker/ with per-service Dockerfiles
- Update docker-compose.yml to use Traefik-only routing (no port exposes)
- Update GitHub Actions deploy workflow for multi-service matrix build
- Fix all import paths and resolve type errors across all services
- All 3 services pass tsc --noEmit clean

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 21:44:29 +07:00
MythEclipseandClaude Opus 4.8 bda8304bb9 fix(analytics): align flag counts and violation score math
- Count only flagged messages in the active users Flag column
- Coerce PostgreSQL count results to numbers before calculating violation_score
- Prevent string concatenation in flagged*3 + warned scoring

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 19:23:46 +07:00
MythEclipseandClaude Opus 4.8 80f1069e2f fix(moderation): remove unsupported chat_template_kwargs and reasoning_budget
API provider returns 400 error for these params. Removed from all LLM calls
in llmModerationClient.ts and indonesianTextNormalizer.ts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 19:05:06 +07:00
MythEclipseandClaude Opus 4.8 13efb576d6 fix(moderation): remove manual badword list and fix deferral regex false positives
- Remove LOCAL_BADWORDS array (25 hardcoded words) and FALSE_POSITIVE_WHITELISTS
- Remove detectLocalBadwords function — all detection now goes through API pipeline
- Fix DEFERRAL_ANALYSIS_PATTERN: remove overly broad patterns (admin perlu, bisa berpotensi, maaf/sorry, saya tidak yakin)
- Expand DEFERRAL_EXCEPTION_PATTERN to catch more decisive-deferral variations
- Update tests to reflect API-only detection (local fallback removed)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 19:00:16 +07:00
MythEclipseandClaude Opus 4.8 a643125c7b refactor(moderation): improve LLM moderation client - 10 recommendations
- Add XML delimiters to prevent prompt injection (R1)
- Use JSON Schema response format instead of json_object (R2)
- Add concurrency limiter via p-limit (R3)
- Add timeout per media analysis call (R4)
- Resize images with sharp before vision API (R5)
- Split text batches when exceeding batch size limit (R6)
- Add few-shot examples to system prompt (R7)
- Modularize system prompt builder (R8)
- Enhance deferral detection regex with exception patterns (R9)
- Sanitize error messages to avoid leaking internals (R10)

New files: concurrencyLimiter.ts, imageResizer.ts, moderationPrompt.ts
Updated: llmModerationClient.ts, config.ts, package.json, tests

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 18:50:05 +07:00
MythEclipseandClaude Opus 4.8 4117f83c1b fix(dashboard): infinite scroll, auto-refetch, analytics cache invalidation, remove topic row cap
Frontend:
- Cursor pagination (100/page) replacing hardcoded 80 message limit
- Removed .slice(0,200) cap on mergeMessages
- IntersectionObserver infinite scroll with skeleton loading
- 15s periodic refetch for message list sync

Backend:
- Removed LIMIT 2000 from topic trends SQL query
- Added invalidateAnalyticsCache on message capture (messageCreated)
- Added invalidateAnalyticsCache on batch analysis completion

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 18:14:32 +07:00
MythEclipse 5078b34ac2 fix: render custom emoji as images and feed to AI vision pipeline
- Extract custom emoji metadata with Discord CDN URLs
- Download and send emoji images to vision model for moderation analysis
- Render custom emoji as inline images in dashboard instead of raw <:name:id> text
- Add emoji vision cache with deterministic keying by emoji ID
- Add custom emoji vision prompt for context-aware moderation
2026-06-01 17:23:46 +07:00
MythEclipseandClaude Opus 4.8 f5507e01f6 refactor(frontend): major rebuild — feature-sliced architecture + bug fixes + glass-morphism UI
Architecture:
- Feature-sliced directory: entities/, shared/, features/, widgets/
- Consolidated API client (shared/api/client.ts) — all endpoints in one file
- Single WebSocket manager (shared/ws/socket.ts) with typed event bus
- Extracted hooks: useAudioPlayback, useAudioTransmit, useLocalStorage, useUIState
- UI primitives moved to shared/ui/ with barrel export
- Added Skeleton, Toast, MobileTabBar components

Bug fixes (8/8):
1. useMemo→useEffect in RecordingsSubPanel (async side-effect anti-pattern)
2. ArrayBuffer.slice() before WebSocket send (shared buffer bug)
3. Proper useEffect dependency arrays throughout
4. Stable React keys (no index fallbacks)
5. onReanalyze properly awaited (Promise<void> return)
6. monitorGuild memoized with useMemo
7. localStorage validation with shape checking
8. Deleted duplicate socket logic (ws/client.ts removed)

UI polish:
- Glass-morphism design tokens (backdrop-blur, translucent cards)
- Gradient mesh background with subtle radial overlays
- Expandable sidebar + mobile bottom tab bar
- Skeleton loading placeholders
- Audio visualizer with CSS pulse animation

Deleted: src/api/, src/components/, src/hooks/, src/types/, src/ws/, src/lib/
Added: 40 new files across feature-sliced structure

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 16:42:36 +07:00
MythEclipseandClaude Opus 4.8 1aab0d1df1 docs: frontend major refactor design document
Design for feature-sliced architecture, 8 bug fixes, and glass-morphism UI redesign.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 15:51:28 +07:00
MythEclipseandClaude Opus 4.6 23840e33a3 fix: install gnused and coreutils-full for native module scripts
The NixOS base image lacks sed and coreutils in PATH. Native Node.js
post-install scripts (node-pre-gyp, prebuild-install) require sed and
other core utilities. Installing gnused and coreutils-full provides the
necessary binaries for native module compilation.

Also switched back to single nix profile install call (instead of
sequential per-RUN) since all packages now reference the same pinned
nixpkgs commit, eliminating version drift conflicts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 12:52:26 +07:00
MythEclipseandClaude Opus 4.6 47bfbb278a fix: install coreutils for sed in NixOS container
The node-pre-gyp and prebuild-install wrapper scripts require sed, which
is not in PATH in the NixOS base container. Install coreutils first to
provide sed, dirname, basename, and other core utilities needed by
native module post-install scripts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 12:46:23 +07:00
MythEclipseandClaude Opus 4.6 c78a9618f8 fix: add .npmrc shamefully-hoist for native module compilation
pnpm's isolated store prevents native post-install scripts from finding
their dependency binaries (node-pre-gyp, prebuild-install). This causes
@discordjs/opus and @lng2004/node-datachannel to fail during pnpm install.

Enabling shamefully-hoist flattens node_modules so native scripts can
resolve their dependencies correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 12:42:33 +07:00
MythEclipseandClaude Opus 4.6 86853bbd4e fix: remove explicit cacert install to resolve version conflict
cacert 3.123 was installed first, but nodejs_22 pulls cacert 3.117 as a
transitive dependency, causing a file conflict on ca-bundle.crt.

Since all packages that need SSL certificates already pull cacert as a
dependency, installing it explicitly is redundant and causes conflicts.
Removing the explicit cacert install lets each package use its resolved
transitive cacert version.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 12:38:55 +07:00
MythEclipseandClaude Opus 4.6 20ff930bb3 fix: install nix packages sequentially with pinned nixpkgs commit
Two issues were causing Docker build failures:
1. Invalid nixpkgs commit hash (404 on GitHub archive)
2. Installing packages simultaneously caused version conflicts
   (cacert 3.123 vs 3.117, git vs git-minimal)

Fix:
- Pin to valid nixos-unstable HEAD commit
- Install each package with sequential 'nix profile add' calls
  so each package resolves dependencies before the next installs
- Remove explicit git (git-minimal pulled by yt-dlp is sufficient)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 12:36:43 +07:00
MythEclipseandClaude Opus 4.6 8883f2bf3a fix: pin nixpkgs to specific commit for reproducible Docker builds
The nixos-unstable channel changes rapidly and causes file conflicts
between packages (cacert 3.123 vs 3.117, git vs git-minimal) because
different packages are resolved from different nixpkgs snapshots during
the same profile install.

Pinning to a specific commit ensures all packages are resolved from the
same nixpkgs snapshot, eliminating version drift and file conflicts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 12:34:23 +07:00
MythEclipseandClaude Opus 4.6 65d5306764 fix: remove explicit git from nix profile install to resolve packinfo.pl conflict with git-minimal
yt-dlp already pulls git-minimal as a transitive dependency. Adding git
explicitly causes a file conflict on packinfo.pl. Removing git from the
install list resolves this since git-minimal provides all git functionality
needed for CI builds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 12:30:49 +07:00
MythEclipse 4e7be14efe migrate Dockerfile from Debian bookworm to NixOS base
Switch from node:22-bookworm-slim to nixos/nix:latest and install dependencies via Nix profile.
2026-06-01 12:12:37 +07:00
MythEclipse 685b97217d feat(docker): update Traefik router rule to remove redundant host entries 2026-06-01 11:28:54 +07:00
MythEclipse 1ab0fdf884 feat(deploy): update ssh-action version and remove container_name from docker-compose 2026-06-01 11:27:51 +07:00
MythEclipse 8310e58239 feat(config): add API route for app configuration and update related logic for monitor guild 2026-06-01 11:16:07 +07:00
MythEclipse 49e9197ce0 feat(deploy): update deployment workflow and remove obsolete Docker publish workflow 2026-06-01 11:07:25 +07:00