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>
This commit is contained in:
MythEclipse
2026-06-13 11:24:42 +07:00
co-authored by Claude
parent e3249edb6c
commit 30f8d7cce3
32 changed files with 1409 additions and 1219 deletions
+21 -11
View File
@@ -1,17 +1,21 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
// ─── Shared Error Classes ────────────────────────────────────────────────────
import {
AppError,
NotFoundError,
ValidationError,
UnauthorizedError,
DatabaseError,
ConfigError,
DatabaseError,
NotFoundError,
UnauthorizedError,
ValidationError,
} from "@bete/shared/errors";
// ─── Shared utilities ─────────────────────────────────────────────────────────
import { delay, retryWithBackoff, encodeCursor, decodeCursor, pageResult } from "@bete/shared/utils";
import {
decodeCursor,
delay,
encodeCursor,
pageResult,
retryWithBackoff,
} from "@bete/shared/utils";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
// ─── Backend middleware ──────────────────────────────────────────────────────
import { asyncHandler, requireParam } from "../src/shared/middlewares/index.js";
@@ -187,7 +191,9 @@ describe("pagination utilities", () => {
const notJson = Buffer.from("not-json").toString("base64");
expect(decodeCursor(notJson)).toBeNull();
// Valid JSON but wrong shape (missing created_at / id)
const wrongShape = Buffer.from(JSON.stringify({ foo: "bar" })).toString("base64");
const wrongShape = Buffer.from(JSON.stringify({ foo: "bar" })).toString(
"base64",
);
expect(decodeCursor(wrongShape)).toBeNull();
});
@@ -255,7 +261,9 @@ describe("requireParam", () => {
});
it("throws ValidationError for undefined", () => {
expect(() => requireParam(undefined, "query", "q")).toThrow(ValidationError);
expect(() => requireParam(undefined, "query", "q")).toThrow(
ValidationError,
);
});
it("throws ValidationError for empty string", () => {
@@ -263,6 +271,8 @@ describe("requireParam", () => {
});
it("throws with a descriptive message", () => {
expect(() => requireParam(null, "header", "X-Token")).toThrow("Missing header: X-Token");
expect(() => requireParam(null, "header", "X-Token")).toThrow(
"Missing header: X-Token",
);
});
});