fix(automod): flow real LLM analysis + descriptive fallback
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 3m2s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 2m25s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 2m40s

Root cause: ai-analysis-worker read llmResult.explanation and
llmResult.toxicityScore — fields the LLM pipeline never produces
(canonical AnalysisResult uses analysis/score). Every message fell back
to the bare template "Tidak ada indikasi pelanggaran." and the stored
score was always 0.

- Map analysis/score correctly; fallback now quotes the message content
- Prompt: ban generic analysis phrasing, require reply context
- LLM context: include replied-to message content (metadata.reference)
  so the model can explain what the user is replying to
- Frontend: show thread/channel names from metadata instead of raw IDs
  (message card, detail views, search overlay); detail panel now
  displays the ai_analysis text
- Auto-delete log/DM include the descriptive analysis as the reason
This commit is contained in:
Developer
2026-07-31 19:11:13 +07:00
parent 0bd4369ae9
commit 60084b3cc3
11 changed files with 142 additions and 34 deletions
@@ -6,7 +6,7 @@ import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Progress } from "@/components/ui/progress";
import { safeParseJsonArray } from "@/lib/format";
import { safeParseJsonArray, getMessageChannelLabel } from "@/lib/format";
import type { MessageRecord } from "@/lib/types";
import { cn } from "@/lib/utils";
import { AiStatusBadge } from "./ai-status-badge";
@@ -52,9 +52,16 @@ export function MessageCard({
<span className="text-xs text-muted-foreground">
{new Date(msg.created_at).toLocaleString()}
</span>
<span className="text-xs text-muted-foreground">
<span
className="text-xs text-muted-foreground"
title={
msg.thread_id
? `Thread ${getMessageChannelLabel(msg)} (${msg.thread_id.slice(0, 8)})`
: undefined
}
>
<Hash className="size-3 inline mr-0.5" />
{msg.channel_id.slice(0, 8)}
{getMessageChannelLabel(msg)}
</span>
<AiStatusBadge status={msg.ai_status} />
{msg.ai_severity && msg.ai_severity !== "none" && (