Commit Graph
100 Commits
Author SHA1 Message Date
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
MythEclipse 942b446ff5 feat(deploy): add GitHub Actions workflow for deploying GMW to VPS 2026-06-01 10:56:23 +07:00
MythEclipse a7b3692982 feat(docker): update Docker configuration and add build workflow 2026-06-01 10:53:20 +07:00
MythEclipse c2d5bde633 feat(database): update migration command to use migrateCli and separate migration logic 2026-05-31 23:10:28 +07:00
MythEclipse 7607282db2 feat(database): add automatic migration on startup and enhance text analysis cache source 2026-05-31 23:01:38 +07:00
MythEclipse 96cd0cfc62 refactor(moderation): clean up code formatting for improved readability 2026-05-31 22:05:50 +07:00
MythEclipse 331076a540 feat(moderation): enhance media analysis with separate handling for images and text 2026-05-31 22:01:42 +07:00
MythEclipse 47e7e8e549 feat(moderation): implement media analysis caching with deterministic keys and database integration 2026-05-31 20:57:01 +07:00
MythEclipse d63e34d259 feat(moderation): refactor word analysis caching to text analysis caching with improved context handling 2026-05-31 20:33:27 +07:00
MythEclipse 7e58741b5c feat(moderation): implement per-word analysis caching for improved performance 2026-05-31 20:27:19 +07:00
MythEclipse 34c4e3e017 feat(moderation): add support for vision model in moderation analysis 2026-05-31 20:12:16 +07:00
MythEclipse 47bac6ff8f feat: add Groq Llama Prompt Guard moderation integration
- Updated .env.example to include Groq API configuration.
- Enhanced config schema in config.ts to support Groq API keys and settings.
- Implemented Groq moderation API call in indonesianTextNormalizer.ts as a fallback for badword detection.
- Removed the Indonesian slang normalization function and related tests to streamline moderation logic.
- Updated tests to reflect changes in moderation strategy, focusing on emoji normalization and badword detection.
2026-05-31 19:42:39 +07:00
MythEclipse c30785a978 feat(moderation): add additional channel to skip in message capture logic 2026-05-31 19:04:03 +07:00
MythEclipse f386e6deba chore: remove Dockerfile as part of project restructuring 2026-05-31 18:25:33 +07:00
MythEclipse 4bb90153b0 feat(analytics): add support for selected analytics guild and channel in App component
fix(redis): enhance Redis connection handling with fallback to in-memory storage
chore(sql): create missing messages and attachments tables with necessary constraints and indexes
2026-05-31 17:19:24 +07:00
MythEclipse 30ce607d88 style: format code for improved readability and consistency across multiple files 2026-05-31 16:54:15 +07:00
MythEclipse f224be2a66 Refactor test database setup and add migrations
- Updated test files to use a separate test database configuration.
- Introduced a new helper module for managing test database operations.
- Added a setup file to configure the environment for tests.
- Created new database migration scripts to optimize message indexing.
- Added a sample environment file for test database configuration.
2026-05-31 16:32:38 +07:00
MythEclipse 8a712cff9b Refactor database handling to exclusively support PostgreSQL
- Removed SQLite support from the configuration and database initialization logic.
- Updated database migration scripts to focus solely on PostgreSQL migrations.
- Simplified logging messages to reflect PostgreSQL usage.
- Adjusted database schema definitions to remove SQLite-specific types and structures.
- Modified tests to ensure compatibility with PostgreSQL, including changes to table creation and data types.
- Cleaned up unused imports and code related to SQLite.
2026-05-31 15:46:18 +07:00
MythEclipse d1ef036358 feat(redis): integrate Redis for job queue management and persistent storage 2026-05-31 14:21:43 +07:00
MythEclipse ce945c8af0 fix(analytics): simplify GROUP BY and ORDER BY clauses in getDailyTrend function 2026-05-31 01:34:35 +07:00
MythEclipse 48b4123f58 chore: remove recharts dependency and clean up pnpm-lock.yaml
- Removed "recharts" from package.json and its associated entries from pnpm-lock.yaml.
- Cleaned up unnecessary dependencies and peer dependencies related to recharts and other unused packages.
2026-05-31 01:04:26 +07:00
MythEclipse 39e4e0ddc5 feat(analytics): refactor ActivityChart and TrendChart to use custom rendering and improve data visualization 2026-05-31 01:00:08 +07:00
MythEclipse 38ae6b03dd feat(analytics): add error boundary for AnalyticsPanel and improve loading state handling 2026-05-31 00:52:23 +07:00
MythEclipse 71e240c1e7 feat(analytics): add daily trend and activity heatmap endpoints, and implement corresponding frontend components
- Added new API endpoints for daily trend data and activity heatmap in analyticsRoutes.ts.
- Created new frontend components: ActivityChart, ControlBar, Heatmap, SummaryCards, TopicList, TrendChart, UserTable, and ViolatorTable for displaying analytics data.
- Implemented loading and empty states in the new components.
- Enhanced the existing moderation tests with remote fallback handling for Indonesian text normalization.
2026-05-31 00:41:34 +07:00
MythEclipse 4e9e370eb1 feat: enhance getTopViolators query to use conditional counts for improved accuracy in moderation stats 2026-05-30 21:29:16 +07:00
MythEclipse 10f44138bc feat: implement age restriction handling in message analysis and metadata 2026-05-30 21:12:25 +07:00
MythEclipse c9e79c8c7c feat: refactor database access in analyticsStore to use executeAll and executeGet for improved query handling 2026-05-30 20:40:33 +07:00
MythEclipse b19529f135 feat: enhance logging and moderation response handling with improved serialization and error management 2026-05-30 20:13:44 +07:00
MythEclipse b105f9748a refactor: optimize database queries and enhance caching for analytics 2026-05-30 17:28:27 +07:00
MythEclipseandClaude Opus 4.8 9a7b8f569d feat: make analytics real-time via WebSocket-triggered refresh
- Analytics panel now refreshes immediately when messages are created, updated, deleted, or analyzed
- WebSocket events (message_created, message_updated, message_deleted, message_analyzed) trigger custom event 'analytics_refresh'
- Analytics hook listens to 'analytics_refresh' event for instant updates
- Auto-refresh interval lowered from 60s to 5s as fallback
- Two-tier refresh: real-time push + 5s polling safety net

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 16:58:25 +07:00
MythEclipseandClaude Opus 4.8 fed9f39bd9 feat: rebrand to GMW — Discord Moderation Watcher
- New custom SVG logo: shield with eye + GMW text
- Page title: 'GMW — Discord Moderation Watcher'
- Header: shows logo + 'GMW · {tab title}'
- Sidebar: shows logo + 'GMW v1.0' + 'Discord Moderation Watcher'
- Favicon set to logo.svg
- Removed old 'Bete Watcher' branding

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 16:34:18 +07:00
MythEclipseandClaude Opus 4.8 c7abe39728 refactor: remove Review tab, make UI state client-side, fix Jakarta time in analytics
- Remove Review tab completely (was redundant with Messages flagged view)
- UI state now client-side only (localStorage) — no server API calls for tab/channel/guild selection
- Fixes dashboard crash when server is down — now loads fully client-side
- Live panel still uses server API for voice/media operations (only what needs it)
- Analytics hourly chart labels now show Jakarta time (WIB/UTC+7) instead of UTC
- Analytics formatTimeAgo uses Jakarta time reference
- Reduced tabs to 3: Live, Messages, Analytics
- Removed unused uiState API imports and server-side state fetching

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 16:31:27 +07:00
MythEclipseandClaude Opus 4.8 9019e24263 feat: merge Voice, Media, and Recordings into unified Live panel
- New LivePanel component combines voice bridge, media player, screen share, and recordings
- Single page layout: voice controls → audio visualizer + active speakers → now playing → music/screen/recordings tabs
- Reduced tabs from 6 to 4: Live, Messages, Analytics, Review
- Sidebar updated with new tab structure
- Default tab changed from 'voice' to 'live'
- Cleaner compact layout with icon buttons and inline controls
- Recordings sub-panel with user avatars, status badges, and download buttons

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 16:20:41 +07:00
MythEclipseandClaude Opus 4.8 c213300800 feat: redesign dashboard messages UI with better sticker/image display and AI filtering
MessageCard:
- Add sticker image preview (renders actual sticker from URL, not just text name)
- Show attachment thumbnails inline (up to 4 with overflow counter)
- Remove dead columns (ai_policy_version, ai_evidence) from UI
- Add severity color coding (critical=red, high=orange, medium=yellow, low=blue)
- Add relative time display ('2h ago' instead of full datetime)
- Better hover effects and visual hierarchy

MessagesPanel:
- Add stats bar showing total/clean/warn/flagged/error/pending/deleted/edited counts
- Add AI status filter buttons (all, clean, warn, flagged, error, pending)
- Improve search UX with inline search icon and clear button
- Show filtered count in tab labels

ImageGrid:
- Include sticker images (was only attachments + embeds before)
- Add kind badge overlay (sticker/attachment/embed)
- Show user avatar next to image caption
- Better sticker rendering (object-contain with padding)

Header:
- Add shield icon per tab
- Improve tab titles and add descriptive subtitles

API client:
- Remove dead fields from MessageRecord (ai_moderation_raw, ai_policy_version, ai_evidence)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 16:13:09 +07:00
MythEclipseandClaude Opus 4.8 a00a5a508f refactor: remove unused AI columns from messages table
Drop 3 columns that were written but never read:
- ai_moderation_raw: raw LLM JSON response (~KB per message, never consumed)
- ai_policy_version: hardcoded 'default-2026-05-30', never used for decisions
- ai_evidence: JSON evidence array, never read after write

Changes:
- schema.ts: remove columns from both Postgres and SQLite table definitions
- messageStore.ts: remove from AIAnalysisUpdate interface and SET clauses
- aiAnalyzer.ts: remove from individual fallback update calls
- aiAnalysisWorker.ts: remove raw write, add missing fields (categories, severity, etc.)
- types.ts: remove from MessageRecord interface
- analysisRoutes.ts: remove from reset analysis call
- New migration: src/database/migrations/001_drop_unused_ai_columns.sql
- Migration applied to live DB: 27 columns → 24 columns

Kept ai_error (useful for future debugging, currently 0 non-null)
Kept metadata (1.9MB total, used for AI sticker/embed evidence analysis)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 16:06:37 +07:00