asepharyana
9e8f4377af
fix(Dockerfile): use node:22-slim for backend (glibc), add linux-headers + nodedir for gateway
2026-07-02 02:22:09 +07:00
asepharyana
13bba60e3a
ci: remove docker tag — shared runners don't have it
2026-07-02 02:17:54 +07:00
asepharyana
90b317731b
ci: add Docker build + GitLab Container Registry push before deploy
2026-07-02 02:11:46 +07:00
asepharyana
0da9839b3a
ci: switch to debian:stable-slim for SSH compatibility
2026-07-02 01:55:21 +07:00
asepharyana
a62c23f1e8
ci: simplify GitLab CI — SSH → git pull → docker compose up -d --build
...
Remove Docker-in-Docker, registry push/pull, SCP complexity.
Pipeline now just SSHs into VPS and rebuilds from source.
Secrets configured:
VPS_HOST, VPS_USERNAME, VPS_SSH_KEY (file type)
2026-07-02 01:46:52 +07:00
asepharyana
c64dd7c2ee
ci: migrate from GitHub Actions to GitLab CI/CD
...
- Create .gitlab-ci.yml with Docker build + GitLab registry push + VPS deploy
- 4 build jobs (frontend, backend, discord-gateway, proxy) in parallel
- Uses Docker-in-Docker with BuildKit for cached multi-stage builds
- Deploy stage uses SCP for .env + docker-compose, then SSH for orchestration
- Images pushed to registry.gitlab.com/mytheclipse-group/gmw/
GitLab CI/CD secrets configured:
- VPS_HOST: 45.127.35.244
- VPS_USERNAME: root
- VPS_SSH_KEY: (file type - SSH private key)
- ENV_FILE: (env_var type - full .env content)
Remove old .github/workflows/deploy-docker.yml (GitHub Actions)
2026-07-02 01:46:18 +07:00
asepharyana
8ad888da28
feat: migrate frontend to Astro SSG with design system
...
- Replace monolithic React SPA (App.tsx) with 7 Astro pages (+ routing)
- Implement full design system from design/ (OKLCH tokens, Tailwind 4 @theme)
- Add 12 Astro components (Button, Badge, Card, Sidebar, Header, states)
- Add 11 React islands (AuthGuard, MessageFeed, VoiceControls, AudioVisualizer, etc.)
- Add 3 Zustand stores (UI, voice, message state)
- Add CSS architecture: dark/light themes, glassmorphism, fluid typography, animations
- Add 404, login, settings, recordings pages
- Remove 40+ legacy React SPA files
- Add Particles background and MascotChat deferred islands
- Wire WebSocket bridge for real-time messages and voice events
Build: 7 pages in ~900ms
Typecheck: clean (0 errors)
Lint: clean (0 errors)
2026-07-02 01:18:45 +07:00
asepharyana
5e40b1ad8c
docs: add Astro migration implementation plan
2026-07-02 00:41:17 +07:00
asepharyana
e8b1827638
docs: add Astro migration design spec
2026-07-02 00:36:30 +07:00
asepharyana
d59b59a7a7
feat: migrate frontend to Astro + expand AI moderation + backend admin/runtime config
...
Frontend:
- migrate from Vite to Astro (astro.config.mjs, pages/, layouts/)
- add admin panel, settings page, command palette, error boundary
- refactor App.tsx, MascotChatbot, Sidebar, Header, DashboardLayout
- update API client, WebSocket, auth, dashboard features
Backend:
- add admin module and config routes
- refactor middlewares, Redis connection, WebSocket server/bridge
- add runtime config loader
Discord Gateway:
- refactor AI moderation: circuit breaker, concurrency limiter, fallback processor
- add media analysis client, Seaxng search, user profile learner
- add new drizzle migration
Shared:
- extend database schema, add new config fields
2026-07-02 00:02:41 +07:00
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
MythEclipse and Claude
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
MythEclipse and Claude
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
MythEclipse and Claude
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
MythEclipse and Claude
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
MythEclipse and Claude
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
MythEclipse and Claude
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