Files
GMW/.hermes/plans/2026-08-30_nsfw-capture-skip-ai-spec.md
T
asepharyana 441b5282ef feat(gateway): capture NSFW/age-restricted messages but skip AI analysis + exclude from public archive
Previously isAgeRestrictedMessage() early-returned in messageCreate/messageUpdate,
so NSFW-channel messages were never stored at all. Now they are captured like
any message (visible in dashboard), while the existing age-restricted skip path
(queueMessageAnalysis -> buildAgeRestrictedSkipResult) marks them clean with flag
age_restricted WITHOUT calling the LLM.

NSFW content is also deliberately kept OUT of the Qdrant public semantic-search
archive (archiveMessageEmbedded skips when isAgeRestricted), so it can't be found
via public web search. No schema change needed (metadata already carries channel.nsfw).
2026-08-30 20:19:34 +07:00

2.8 KiB

Spec: Simpan pesan NSFW tanpa analisis AI (Request 1)

Date: 2026-08-30

Goal

Saat ini GMW skip capture untuk pesan di channel age-restricted/NSFW (messageCapture.ts baris 291 & 310 memanggil isAgeRestrictedMessage lalu return). User ingin pesan NSFW tetap disimpan ke database (jadi terlihat di dashboard), tetapi tidak dianalisis AI (tidak dipanggil LLM).

Behavior target

  1. Pesan NSFW/age-restricted di messageCreate → DISIMPAN (capture normal).
  2. Pesan NSFW di messageUpdate/messageDelete → tetap diproses seperti pesan biasa (edit/deleted state tercatat).
  3. AI analysis TIDAK berjalan untuk pesan NSFW. Sudah ada jalur yang benar: queueMessageAnalysis → isAgeRestrictedMessage(message) → buildAgeRestrictedSkipResult() yang menulis status=clean + flag age_restricted + action=none TANPA memanggil LLM. Jalur ini sudah ada dan dipakai di aiAnalyzer.queueMessageAnalysis (baris 72-84) dan batchProcessor.skipAgeRestrictedMessages. Jadi tinggal membuka capture.
  4. Konten NSFW TIDAK masuk ke Qdrant public archive (semantic search publik). archiveMessageEmbedded harus di-guard untuk pesan age-restricted.

Files touched

  • services/discord-gateway/src/modules/message-capture/messageCapture.ts
    • Hapus guard isAgeRestrictedMessage di messageCreate (baris 291) dan messageUpdate (baris 310). Jangan hapus guard isExcludedThread, isBotExcludedChannel, shouldCaptureForAnyTarget.
  • services/discord-gateway/src/modules/message-capture/archiveEmbedder.ts
    • archiveMessageEmbedded terima flag/cek metadata age-restricted → skip embed untuk NSFW.
    • Call-site di messageCapture.ts captureMessage (baris 218) pass isNSFW atau cek dulu.

Schema/type changes

  • TIDAK ada perubahan DB schema. Metadata pesan sudah membawa channel.nsfw (getMessageLocation). Tidak perlu kolom baru — flag age_restricted sudah ditulis ke ai_moderation_flags lewat skip-result.

Verification

  • pnpm typecheck, pnpm lint (biome), pnpm build di services/discord-gateway.
  • Unit test: pastikan ada test untuk age-restricted skip (sudah ada tests/conversationContext.test.ts ref nsfw; cek apakah ada test sesuai).
  • Deploy via GHA push; verify pesan NSFW muncul di DB dan ai_status = clean dengan flag age_restricted, dan TIDAK ada panggilan LLM (log llm-caller tidak menampilkan id pesan NSFW).

Status

  • Request 1: DONE & DEPLOYED (commit 50967f64, CI green, gateway restart 20:17 WIB).
  • Request 2 (video): dicatat, belum dikerjakan — lihat section di bawah.

Request 2 (video) — NOT in this change

Fitur record video kamera/screenshare orang lain. @discordjs/voice hanya mendukung audio receive. Video orang lain butuh WebRTC viewer baru (SDP answer, decrypt H264/VP8, decode frame, mux MP4/WebM). Diluar scope changeset ini; dicatat untuk desain lanjutan.