Files
GMW/services/discord-gateway/src/modules/ai-moderation/verdictToActionFields.ts
T

49 lines
1.7 KiB
TypeScript
Raw Normal View History

import type { MessageRecord } from "../message-capture/types.js";
/**
* Map a captured message's persisted AI verdict (the `ai_*` columns on
* MessageRecord) into the explainability columns of a moderation action.
*
* This is READ-ONLY structured data — it never changes any enforcement
* decision. It exists so the public web view can show *why* a message was
* moderated, making GMW's automod transparent instead of a black box.
*
* All fields are null-safe: manual actions (e.g. command-handler bans) carry
* no AI verdict, so they simply store nulls and the UI falls back to the
* free-text `reason`.
*/
export function verdictToActionFields(message?: MessageRecord | null): {
flags: string | null;
categories: string | null;
severity: string | null;
confidence: number | null;
score: number | null;
evidence: string | null;
policy_version: string | null;
} {
if (!message) {
return {
flags: null,
categories: null,
severity: null,
confidence: null,
score: null,
evidence: null,
policy_version: null,
};
}
// ai_moderation_flags / ai_categories are stored as JSON-stringified TEXT
// (see messagesAnalysis.buildAIAnalysisSet → stringifyAIList). Pass them
// through verbatim so the backend can JSON.parse them back into arrays.
return {
flags: message.ai_moderation_flags ?? null,
categories: message.ai_categories ?? null,
severity: message.ai_severity ?? null,
confidence: message.ai_confidence ?? null,
score: message.ai_moderation_score ?? null,
evidence: null, // not persisted on MessageRecord; reserved for future use
policy_version: null, // set by caller if a policy version is available
};
}