Commit Graph
124 Commits
Author SHA1 Message Date
asepharyana 8166023f91 chore: remove React frontend, rename frontend-leptos to frontend 2026-07-03 23:11:00 +07:00
asepharyana 0926f235cb fix(auth): only reset activeTab on mount, don't block tab switching
Previous code continuously forced activeTab to 'messages' when not
authenticated, making dashboard and voice tabs unclickable.
Now uses useEffect once on mount to reset localStorage carryover,
then lets tab switching work normally.
2026-07-02 07:45:02 +07:00
asepharyana 948e41cec6 fix(ui): chat bubble max-w-xs broken by tailwind spacing override (4px not 320px)
tailwind.config.js overrides spacing.xs to 4px, which also overrides
max-w-xs to max-width: 4px instead of the default 20rem (320px).
Changed to explicit max-w-[280px] to bypass the corrupted token.
2026-07-02 07:08:58 +07:00
asepharyana 77812f9452 fix(auth): force activeTab to messages if not authenticated — prevent localStorage carryover
When a user visited the Live tab in a previous session, localStorage
stored activeTab: 'live'. On page reload, even with the new auth guard,
the app would try to render the Live tab and show the auth overlay.
Now if not authenticated, activeTab is always forced to 'messages'.
2026-07-02 07:06:33 +07:00
asepharyana 58de0df24b fix(ui): chat bubble text wrapping — replace break-words with overflow-wrap:anywhere
Fixes MascotChatbot messages wrapping 1 character per line.
overflow-wrap:anywhere handles long unbroken strings better
than break-words which only breaks at word boundaries.
2026-07-02 06:53:27 +07:00
asepharyana 0ae1ef1987 fix(auth): only guard Live tab, messages & dashboard are public
Auth overlay only shows when accessing Voice & Media without
authentication. Messages panel and Dashboard panel remain fully
accessible without login.
2026-07-02 06:40:39 +07:00
asepharyana 112b865a5b fix(infra): bypass Cloudflare Rocket Loader — breaks ES module scripts
Cloudflare Rocket Loader transforms <script type="module"> into
type="<hash>-module", which the browser cannot parse as ES module.
The React app never mounts — blank page on every route.

Fix: Vite plugin adds data-cfasync="false" attribute to the module
script tag, telling Rocket Loader to skip transformation.

Also: remove dist/ from the commit (build artifacts excluded).
2026-07-02 06:30:26 +07:00
asepharyana d53ec74d64 fix(build): resolve Tailwind 4 @apply breaking changes
- Replace @apply im-btn in im-btn-primary/secondary/ghost
  with inline Tailwind utilities + CSS properties
- Replace @apply im-status-dot in status dot variants
  with inline properties
- Tailwind 4 cannot @apply component-level classes from within
  @layer components — only standard utility classes are valid
2026-07-02 06:17:58 +07:00
asepharyana 81a004d250 feat(frontend): IMPHNEN design deep integration — full 5-layer redesign
Layer 0 — Foundation:
- Dark mode palette (30+ CSS var pairs in [data-theme='dark'])
- CSS-first theme engine in styles.css (@theme + CSS vars)
- UseTheme hook with light/dark/system support + localStorage persistence
- Fixed animation keyframes (shimmer 1.5s canonical, glowPulse moved to CSS)
- Smooth theme switch transitions via .theme-transitioning class

Layer 1 — Shared UI Components:
- Badge: success/warning variants now use CSS vars (bg-success-soft text-success)
- Toast: rewritten with CSS vars, z-index fixed (40), repositioned top-right
- Skeleton: added variant prop (rounded/circular/rectangular)
- EmptyState: new component with icon + title + description + action
- Button: added tertiary variant + icon-sm size
- Card: added elevated/bordered variants
- Input: added soft variant

Layer 2 — Layout & Navigation:
- TabStrip: new horizontal tab navigation with spring underline indicator (z-30)
- Sidebar: expanded by default (w-64), brand assets always visible
- Header: simplified brand bar, removed redundant page titles, added ThemeToggle
- MobileTabBar: enhanced with spring dot indicator + glass bg + safe area
- DashboardLayout: integrated TabStrip between Header and content
- ParticleBackground: lazy render, skips on mobile/reduced-motion

Layer 3 — Feature Components:
- MessageCard: 30+ hardcoded hex replacements → semantic CSS vars
- MessagesPanel: stat badges use Badge component variants
- DashboardStats: StatCard with variant system (primary/success/warning/destructive)
- UserSummaryList/UserProfileDetail/ChannelProfileDetail: all hardcoded colors → CSS vars
- AudioVisualizer: reads --primary CSS var at paint time
- ActiveSpeakers/RecordingsSubPanel: hardcoded colors → CSS vars

Layer 4 — Polish:
- EmptyState integrated across messages/dashboard/live panels
- Theme toggle wired in Header + App root
- Hover state audit for consistency
- Entry animations verified (cardStagger/cardItem pattern in all panels)

Resolves DESIGN_TOKENS.md §13.x issues: hardcoded colors, shimmer mismatch,
glow-pulse fragmentation, z-index collisions, toast positioning.
2026-07-02 05:58:36 +07:00
asepharyana 7efaf00c93 Revert "feat: migrate frontend to Astro + expand AI moderation + backend admin/runtime config"
This reverts commit d59b59a7a7.
2026-07-02 03:54:44 +07:00
asepharyana bf86fcda8e Revert "feat: migrate frontend to Astro SSG with design system"
This reverts commit 8ad888da28.
2026-07-02 03:54:44 +07:00
asepharyana 24c738dd19 Revert "fix: split LiveShell into Astro layout + individual islands"
This reverts commit 6e1757410a.
2026-07-02 03:54:44 +07:00
asepharyana 5a10bec67a Revert "fix: replace Astro.redirect with direct live content at /"
This reverts commit 34ac4be6c2.
2026-07-02 03:54:44 +07:00
asepharyana 34ac4be6c2 fix: replace Astro.redirect with direct live content at / 2026-07-02 03:47:23 +07:00
asepharyana 6e1757410a fix: split LiveShell into Astro layout + individual islands
- Rewrite live.astro to use Astro Sidebar/Header/Card components
- VoiceControls becomes self-contained (fetches guilds/channels internally)
- Remove LiveShell.tsx (no longer needed)
- Each React island uses appropriate client:load/idle directive
2026-07-02 03:13:54 +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 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 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 21b818a344 feat: add forwarding & reply detection with frontend indicators
- Enhanced messageMetadata to capture referenced message content
- Added reply indicator (↩️ Replying to @username + content snippet)
- Added forward badge (🔁 Forwarded) and crosspost badge (📢 Crossposted)
- Frontend auto-fetches referenced message content when metadata is empty
- Added getMessageById API helper
2026-06-21 18:22:27 +07:00
MythEclipseandClaude 752d144dc0 refactor(fe): overhaul — split types, type-safe WS, remove dead deps/code
- Remove unused deps: gsap, @tanstack/react-query, three, r3f, drei, autoprefixer
- Split types from shared/api/client.ts into entities/{guild,voice,media,ui,recording,dashboard}
- Type-safe WebSocket handlers using WsEventMap — 0 'as' casts in App.tsx
- Replace gsap with framer-motion in AuthOverlay
- Remove dead code: useMascotSummary, gsapCardHover, live/components/index barrel
- Fix bare console calls → use createLogger from @bete/shared/logger
- Clean up unused imports and variables (aiVariant, etc.)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-14 15:22:29 +07:00
MythEclipse 41e67423b8 chore(services): update components based on recent changes
Changes:
 services/frontend/src/features/dashboard/components/ChannelProfileDetail.tsx | 258 +++++++++++-----------------------------------------------------------------
 services/frontend/src/features/dashboard/components/ChannelSummaryList.tsx   | 171 ++++++++-------------------------------------------
 services/frontend/src/features/dashboard/components/DashboardStats.tsx       |   8 ++-
 services/frontend/src/features/dashboard/components/UserProfileDetail.tsx    | 297 +++++++++++++---------------------------------------------------------------------------
 services/frontend/src/features/dashboard/components/UserSummaryList.tsx      | 204 +++++++++++-------------------------------------------------
 services/frontend/src/features/dashboard/hooks/useDashboard.ts               | 203 +++++++++++++++---------------------------------------------
 services/frontend/src/features/messages/components/MessageCard.tsx           |  10 +--
 services/frontend/src/shared/api/client.ts                                   |  87 +++++++++++++++++++-------
 services/frontend/src/shared/hooks/useItemDetail.ts                          |  58 +++++++++++++++++
 services/frontend/src/shared/hooks/usePaginatedList.ts                       | 105 +++++++++++++++++++++++++++++++
2026-06-14 15:16:18 +07:00
MythEclipse f22201381f a 2026-06-13 23:58:29 +07:00
MythEclipse 9a896c7993 chore(services): update components based on recent changes
Changes:
 services/frontend/src/widgets/Sidebar.tsx | 51 +++++++++++++++++++++++++-------------------------
 1 file changed, 25 insertions(+), 26 deletions(-)
2026-06-13 19:47:06 +07:00
MythEclipse 23b45690ca chore(services): update components based on recent changes
Changes:
 services/backend/src/http/app.ts | 22 ++++++++--------
 services/frontend/src/App.tsx    | 81 ++++++++++++++++++++++++-----------------------------------
 2 files changed, 43 insertions(+), 60 deletions(-)
2026-06-13 19:46:56 +07:00
MythEclipse 82c1658bab chore(services): update components based on recent changes
Changes:
 services/frontend/src/features/messages/index.tsx | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
2026-06-13 19:43:32 +07:00
MythEclipse 28baeda5ad chore(services): update components based on recent changes
Changes:
 packages/shared/src/config/index.ts                                          |   7 +++
 packages/shared/src/moderation-types.ts                                      |   1 +
 services/backend/src/modules/recordings/recordings.service.ts                |   3 +-
 services/discord-gateway/drizzle/migrations/0011_add_voice_transcription.sql |   1 +
 services/discord-gateway/src/modules/voice-recording/recorder/segment.ts     |  10 ++++
 services/discord-gateway/src/modules/voice-recording/recorder/uploader.ts    |  15 ++++++
 services/discord-gateway/src/modules/voice-recording/voiceTranscriber.ts     |  51 ++++++++++++++++++
 services/discord-gateway/src/shared/database/schema.ts                       |   1 +
 services/discord-gateway/src/shared/database/voiceRecordingRepo.ts           |  17 ++++++
 services/frontend/src/features/live/components/RecordingsSubPanel.tsx        | 108 +++++++++++++++++++-------------------
2026-06-13 17:08:54 +07:00
MythEclipse 9bde518b71 chore(services): update components based on recent changes
Changes:
 services/backend/src/ws/redis-bridge.ts                | 31 ++++++++++++++++++++-
 services/backend/src/ws/server.ts                      | 36 +++++++++++++++++++++++-
 services/frontend/src/App.tsx                          | 12 ++++----
 services/frontend/src/shared/hooks/useAudioPlayback.ts | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 services/frontend/src/shared/hooks/useAudioTransmit.ts | 21 +++++---------
 5 files changed, 169 insertions(+), 22 deletions(-)
2026-06-13 17:00:02 +07:00
MythEclipse 1d06de5ce5 chore(services): update components based on recent changes
Changes:
 services/frontend/src/features/live/components/RecordingsSubPanel.tsx |  45 ++------
 services/frontend/src/features/live/components/WaveformPlayer.tsx     | 253 +++++++++++++++++++++++++++++++++++++++++++++
 services/frontend/src/features/live/components/index.ts               |   1 +
 3 files changed, 261 insertions(+), 38 deletions(-)
2026-06-13 16:56:17 +07:00
MythEclipse 5c8fa3d254 chore(services): update components based on recent changes
Changes:
 services/frontend/src/App.tsx                                          | 22 ++++++++++++++++++++++
 services/frontend/src/features/live/components/VoiceConnectionCard.tsx |  5 ++++-
 2 files changed, 26 insertions(+), 1 deletion(-)
2026-06-13 16:54:52 +07:00
MythEclipse 5459b13b03 chore(services): update components based on recent changes
Changes:
 services/frontend/src/App.tsx | 37 +++++++++++++++++++++++++++++++------
 1 file changed, 31 insertions(+), 6 deletions(-)
2026-06-13 16:54:29 +07:00
MythEclipse e76a874f11 chore(services): update components based on recent changes
Changes:
 services/frontend/src/shared/api/client.ts | 8 ++++++++
 1 file changed, 8 insertions(+)
2026-06-13 16:53:30 +07:00
MythEclipse fce24278f0 chore(auto): task completed - unknown 2026-06-13 14:49:47 +07:00
MythEclipse e6e34281ff chore(auto): task completed - unknown 2026-06-13 14:24:09 +07:00
MythEclipse 6822cb0bd3 chore(auto): task completed - unknown 2026-06-13 14:10:34 +07:00
MythEclipse 277d982c51 chore(auto): task completed - unknown 2026-06-13 14:05:17 +07:00
MythEclipseandClaude 14c0081f01 feat(discord-gateway): implement voice & push improvements
- Voice disconnect broadcast on stopRecording
- Multi-guild voice support (VoiceController Map<guildId>)
- Session finalization + auto-enqueue muxer job
- Recordings API: duration field, channelId/userId filters
- Transmitter Redis connection reuse (shared conn)
- FFmpeg stderr memory cap (4KB limit)
- 10 new Redis event channels + Redis bridge subscriptions
- New DB tables: message_reactions, message_edits
- Webhook notification module
- Gateway metrics / Prometheus endpoint
- Multi-guild message capture (MONITOR_GUILD_IDS array)
- Thread tracking, presence, channel topic, guild member events
- Edit history snapshot on message update
- Muxer audio post-processing worker

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 13:51:21 +07:00
MythEclipseandClaude 4fcab6b003 refactor(frontend): reorder sidebar — messages first, voice below
Default tab is now 'messages'; Voice & Media moved below
Messages in both desktop sidebar and mobile tab bar.
Updated Header titles/subtitles to match new order.

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

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

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

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

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

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

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

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 21:28:05 +07:00
MythEclipse 2557a07916 feat(core): implement data retention, metrics, and enhanced media handling
This commit introduces several significant improvements across the backend and gateway services:

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

- **Infrastructure**: Optimize Dockerfiles using build mounts for pnpm cache and reorder layers for better caching of dependencies and build tools.
- **Backend/Gateway**:
  - Refactor `broadcast` module to use a generic event-based system instead of hardcoded functions.
  - Simplify voice recording logic by merging metadata and segment management into a unified `segment.ts`.
  - Optimize audio downsampling in `streamSetup.ts` using `Int16Array` views for better performance.
  - Implement `withFallback` utility for more robust Redis/Database command execution.
- **Frontend**:
  - Optimize audio playback visualization using pre-computed level shapes and efficient RMS calculation.
  - Reduce latency in voice commands by prioritizing WebSocket communication over HTTP.
  - Improve base64 encoding efficiency in audio transmission.
- **General**:
  - Add default value for `ADMIN_PASSWORD` in shared config.
  - Fix Docker healthcheck to use `127.0.0.1` instead of `localhost`.
2026-06-09 22:04:05 +07:00
MythEclipseandClaude Opus 4.8 07032ab521 refactor: atomic, DRY, and logging improvements across codebase
- Split llmModerationClient.ts (2170 lines) into 5 focused sub-modules
- Split aiAnalyzer.ts (1282 lines) into 4 modular pipelines
- Split messages.db.ts (826 lines) into 5 domain-specific modules
- Moved shared schema to @bete/shared, eliminated backend duplication
- Added createChildLogger to all voice-recording and AI moderation modules
- Extracted tryCommandThenFallback, normalizeMediaState, DEFAULT_VOICE_STATUS
- Created shared pagination.ts utility, eliminated 5+ cursor-pagination duplications
- Created shared messageMapper.ts for row mapping
- Standardized backend error handling with asyncHandler
- Added frontend createLogger utility and useAsyncAction hook
- Added structured logging to frontend hooks, socket, and API client

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

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

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 16:36:23 +07:00