refactor: simplify AI moderation pipeline to Primary AI only, fix stickerCache executeGet

- Remove Groq and NVIDIA fallback from text moderation pipeline
- Remove GROQ_API_KEY, GROQ_MODERATION_*, NVIDIA_NEMOTRON_* config vars
- Update source enum: remove 'groq' and 'nvidia' from cache/schema types
- Rewrite indonesianTextNormalizer to use Primary AI only (no fallback chain)
- Rewrite remote test to test Primary AI only
- Fix stickerCache executeGet missing empty params array

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MythEclipse
2026-06-02 17:25:55 +07:00
co-authored by Claude Opus 4.8
parent 049fd49737
commit 1bc0b7c7bb
3 changed files with 14 additions and 30 deletions
@@ -2,23 +2,9 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
import { config } from "../../src/config";
const mocks = vi.hoisted(() => ({
axiosPost: vi.fn(),
openaiCreate: vi.fn(),
}));
vi.mock("axios", () => ({
default: {
post: mocks.axiosPost,
isAxiosError: (error: unknown) =>
Boolean(
error &&
typeof error === "object" &&
"isAxiosError" in error &&
(error as { isAxiosError?: unknown }).isAxiosError,
),
},
}));
vi.mock("openai", () => ({
default: class MockOpenAI {
chat = {
@@ -29,20 +15,13 @@ vi.mock("openai", () => ({
},
}));
describe("detectIndonesianBadwords remote fallback", () => {
describe("detectIndonesianBadwords primary AI", () => {
beforeEach(() => {
mocks.axiosPost.mockReset();
mocks.openaiCreate.mockReset();
config.NVIDIA_NEMOTRON_API_KEY = "test-nemotron-key";
config.AI_LLM_API_KEY = "test-primary-key";
});
it("falls back to primary AI after Nemotron rate limits and caches the result", async () => {
mocks.axiosPost.mockRejectedValue({
isAxiosError: true,
response: { status: 429 },
message: "Too Many Requests",
});
it("calls primary AI and caches the result", async () => {
mocks.openaiCreate.mockResolvedValue({
choices: [
{
@@ -62,7 +41,17 @@ describe("detectIndonesianBadwords remote fallback", () => {
expect(first).toEqual(["harassment"]);
expect(second).toEqual(["harassment"]);
expect(mocks.axiosPost).toHaveBeenCalledTimes(1);
expect(mocks.openaiCreate).toHaveBeenCalledTimes(1);
});
it("returns empty array when primary AI fails", async () => {
mocks.openaiCreate.mockRejectedValue(new Error("API down"));
const { detectIndonesianBadwords } = await import(
"../../src/moderation/indonesianTextNormalizer"
);
const result = await detectIndonesianBadwords("some text");
expect(result).toEqual([]);
});
});
@@ -7,14 +7,10 @@ import {
normalizeDiscordCustomEmoji,
} from "../../src/moderation/indonesianTextNormalizer";
const originalNemotronKey = config.NVIDIA_NEMOTRON_API_KEY;
const originalPrimaryAiKey = config.AI_LLM_API_KEY;
const originalGroqKey = config.GROQ_API_KEY;
function disableRemoteModeration(): void {
config.NVIDIA_NEMOTRON_API_KEY = undefined;
config.AI_LLM_API_KEY = undefined;
config.GROQ_API_KEY = undefined;
}
disableRemoteModeration();
@@ -24,9 +20,7 @@ afterEach(() => {
});
afterAll(() => {
config.NVIDIA_NEMOTRON_API_KEY = originalNemotronKey;
config.AI_LLM_API_KEY = originalPrimaryAiKey;
config.GROQ_API_KEY = originalGroqKey;
});
describe("normalizeDiscordCustomEmoji", () => {