chore(lint): biome cleanup across services — format, sort imports, drop unused

- discord-gateway: 74 lint errors -> 0 (format, import sorting, unused
  imports/vars, dead breath var)
- backend: format + sort imports (11 warnings left: noExplicitAny)
- frontend: remove unused imports, drop dead breathing var, fix
  useExhaustiveDependencies (scroll keyed on messages), a11y biome-ignore
  for drag surface + stopPropagation container (mouse-only gestures)
- remaining warnings are false positives: index keys on static lists,
  <img> in static export (next/image unsupported), noExplicitAny

tsc --noEmit clean on all 3 services; vitest green (60+36).
This commit is contained in:
asepharyana
2026-08-01 22:09:02 +07:00
parent 2357421841
commit 6293d588bc
123 changed files with 466 additions and 308 deletions
+2 -2
View File
@@ -1,4 +1,3 @@
import { createChildLogger } from "@/shared/logger/index";
import express, { import express, {
type Express, type Express,
type NextFunction, type NextFunction,
@@ -6,11 +5,12 @@ import express, {
type Response, type Response,
} from "express"; } from "express";
import helmet from "helmet"; import helmet from "helmet";
import { createChildLogger } from "@/shared/logger/index";
import { createAnalysisRouter } from "../modules/analysis/index.js"; import { createAnalysisRouter } from "../modules/analysis/index.js";
import { createChatbotRouter } from "../modules/chatbot/index.js";
import { createConfigRouter } from "../modules/config/index.js"; import { createConfigRouter } from "../modules/config/index.js";
import { createDashboardRouter } from "../modules/dashboard/index.js"; import { createDashboardRouter } from "../modules/dashboard/index.js";
import { createHealthRouter } from "../modules/health/index.js"; import { createHealthRouter } from "../modules/health/index.js";
import { createChatbotRouter } from "../modules/chatbot/index.js";
import { createMediaRouter } from "../modules/media/index.js"; import { createMediaRouter } from "../modules/media/index.js";
import { createMessagesRouter } from "../modules/messages/index.js"; import { createMessagesRouter } from "../modules/messages/index.js";
import { createRecordingsRouter } from "../modules/recordings/index.js"; import { createRecordingsRouter } from "../modules/recordings/index.js";
@@ -1,7 +1,7 @@
import { pgMessagesTable } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js";
import { and, desc, eq, ilike, type SQL } from "drizzle-orm"; import { and, desc, eq, ilike, type SQL } from "drizzle-orm";
import { getDatabase } from "../../shared/database/index.js"; import { getDatabase } from "../../shared/database/index.js";
import { pgMessagesTable } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js";
import { import {
type MappedMessage, type MappedMessage,
mapMessageRow, mapMessageRow,
@@ -1,6 +1,6 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Request, Response, Router } from "express"; import type { Request, Response, Router } from "express";
import express from "express"; import express from "express";
import { createChildLogger } from "@/shared/logger/index";
import { asyncHandler } from "../../shared/middlewares/index.js"; import { asyncHandler } from "../../shared/middlewares/index.js";
import { analysisService } from "./analysis.service.js"; import { analysisService } from "./analysis.service.js";
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Request, Response } from "express"; import type { Request, Response } from "express";
import { createChildLogger } from "@/shared/logger/index";
import { asyncHandler } from "../../shared/middlewares/index.js"; import { asyncHandler } from "../../shared/middlewares/index.js";
import { chatbotService } from "./chatbot.service.js"; import { chatbotService } from "./chatbot.service.js";
@@ -1,7 +1,7 @@
import { pgChatbotMessagesTable, pgMessagesTable } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js";
import { and, desc, eq, type SQL, sql } from "drizzle-orm"; import { and, desc, eq, type SQL, sql } from "drizzle-orm";
import { getDatabase } from "../../shared/database/index.js"; import { getDatabase } from "../../shared/database/index.js";
import { pgChatbotMessagesTable, pgMessagesTable } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js";
const logger = createChildLogger("chatbot.repository"); const logger = createChildLogger("chatbot.repository");
@@ -10,11 +10,7 @@ import { chatRequestSchema } from "./chatbot.schema.js";
export function createChatbotRouter(): Router { export function createChatbotRouter(): Router {
const router = express.Router(); const router = express.Router();
router.post( router.post("/chat", validateBody(chatRequestSchema), handleChatbotChat);
"/chat",
validateBody(chatRequestSchema),
handleChatbotChat,
);
router.get("/chat/history", getChatbotHistory); router.get("/chat/history", getChatbotHistory);
router.delete("/chat/history", clearChatbotHistory); router.delete("/chat/history", clearChatbotHistory);
@@ -1,3 +1,6 @@
import type { SQL } from "drizzle-orm";
import { sql } from "drizzle-orm";
import { getDatabase } from "../../shared/database/index.js";
import { import {
pgChannelCulturesTable, pgChannelCulturesTable,
pgMessagesTable, pgMessagesTable,
@@ -5,9 +8,6 @@ import {
pgUserReputationsTable, pgUserReputationsTable,
pgVoiceRecordingsTable, pgVoiceRecordingsTable,
} from "../../shared/index.js"; } from "../../shared/index.js";
import type { SQL } from "drizzle-orm";
import { sql } from "drizzle-orm";
import { getDatabase } from "../../shared/database/index.js";
import type { ListUsersQuery } from "./dashboard.service.js"; import type { ListUsersQuery } from "./dashboard.service.js";
export class DashboardRepository { export class DashboardRepository {
@@ -1,6 +1,6 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Request, Response, Router } from "express"; import type { Request, Response, Router } from "express";
import express from "express"; import express from "express";
import { createChildLogger } from "@/shared/logger/index";
import { asyncHandler } from "../../shared/middlewares/index.js"; import { asyncHandler } from "../../shared/middlewares/index.js";
import { dashboardService } from "./dashboard.service.js"; import { dashboardService } from "./dashboard.service.js";
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import { sql } from "drizzle-orm"; import { sql } from "drizzle-orm";
import { createChildLogger } from "@/shared/logger/index";
import { getDatabase } from "../../shared/database/index.js"; import { getDatabase } from "../../shared/database/index.js";
const logger = createChildLogger("health.repository"); const logger = createChildLogger("health.repository");
@@ -1,6 +1,6 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Request, Response, Router } from "express"; import type { Request, Response, Router } from "express";
import express from "express"; import express from "express";
import { createChildLogger } from "@/shared/logger/index";
import { asyncHandler, validateBody } from "../../shared/middlewares/index.js"; import { asyncHandler, validateBody } from "../../shared/middlewares/index.js";
import { mediaQueueSchema, mediaVolumeSchema } from "./media.schema.js"; import { mediaQueueSchema, mediaVolumeSchema } from "./media.schema.js";
import { getStatus, queue, setVolume, skip, stop } from "./media.service.js"; import { getStatus, queue, setVolume, skip, stop } from "./media.service.js";
@@ -1,3 +1,7 @@
import {
createChildLogger,
tryCommandThenFallback,
} from "../../shared/commandHelper.js";
import { import {
COMMAND_MEDIA_QUEUE, COMMAND_MEDIA_QUEUE,
COMMAND_MEDIA_SKIP, COMMAND_MEDIA_SKIP,
@@ -5,10 +9,6 @@ import {
COMMAND_MEDIA_VOLUME, COMMAND_MEDIA_VOLUME,
MEDIA_STATUS_KEY, MEDIA_STATUS_KEY,
} from "../../shared/index.js"; } from "../../shared/index.js";
import {
createChildLogger,
tryCommandThenFallback,
} from "../../shared/commandHelper.js";
import { publishCommand, readRedisStatus } from "../../shared/redis/index.js"; import { publishCommand, readRedisStatus } from "../../shared/redis/index.js";
const logger = createChildLogger("media.service"); const logger = createChildLogger("media.service");
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Request, Response } from "express"; import type { Request, Response } from "express";
import { createChildLogger } from "@/shared/logger/index";
import { asyncHandler } from "../../shared/middlewares/index.js"; import { asyncHandler } from "../../shared/middlewares/index.js";
import { messageQuerySchema } from "./messages.schema.js"; import { messageQuerySchema } from "./messages.schema.js";
import { messagesService } from "./messages.service.js"; import { messagesService } from "./messages.service.js";
@@ -1,6 +1,3 @@
import type { PageResult } from "../../shared/index.js";
import { pgAttachmentsTable, pgMessagesTable } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js";
import { import {
and, and,
desc, desc,
@@ -16,6 +13,9 @@ import {
} from "drizzle-orm"; } from "drizzle-orm";
import { config } from "../../shared/config/index.js"; import { config } from "../../shared/config/index.js";
import { getDatabase } from "../../shared/database/index.js"; import { getDatabase } from "../../shared/database/index.js";
import type { PageResult } from "../../shared/index.js";
import { pgAttachmentsTable, pgMessagesTable } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js";
import { mapMessageRow } from "../../shared/utils/messageMapper.js"; import { mapMessageRow } from "../../shared/utils/messageMapper.js";
import type { import type {
MessageCreate, MessageCreate,
@@ -1,6 +1,6 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Request, Response, Router } from "express"; import type { Request, Response, Router } from "express";
import express from "express"; import express from "express";
import { createChildLogger } from "@/shared/logger/index";
import { asyncHandler, validateBody } from "../../shared/middlewares/index.js"; import { asyncHandler, validateBody } from "../../shared/middlewares/index.js";
import { import {
handleGetAttachmentsByChannel, handleGetAttachmentsByChannel,
@@ -1,6 +1,6 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Request, Response, Router } from "express"; import type { Request, Response, Router } from "express";
import express from "express"; import express from "express";
import { createChildLogger } from "@/shared/logger/index";
import { asyncHandler } from "../../shared/middlewares/index.js"; import { asyncHandler } from "../../shared/middlewares/index.js";
import { recordingsService } from "./recordings.service.js"; import { recordingsService } from "./recordings.service.js";
@@ -1,7 +1,7 @@
import { pgVoiceRecordingsTable } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js";
import { and, desc, eq, lt, type SQL } from "drizzle-orm"; import { and, desc, eq, lt, type SQL } from "drizzle-orm";
import { getDatabase } from "../../shared/database/index.js"; import { getDatabase } from "../../shared/database/index.js";
import { pgVoiceRecordingsTable } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js";
const logger = createChildLogger("recordings.service"); const logger = createChildLogger("recordings.service");
@@ -1,6 +1,6 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Request, Response, Router } from "express"; import type { Request, Response, Router } from "express";
import express from "express"; import express from "express";
import { createChildLogger } from "@/shared/logger/index";
import { asyncHandler } from "../../shared/middlewares/index.js"; import { asyncHandler } from "../../shared/middlewares/index.js";
import { uiStateService } from "./ui-state.service.js"; import { uiStateService } from "./ui-state.service.js";
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import { sql } from "drizzle-orm"; import { sql } from "drizzle-orm";
import { createChildLogger } from "@/shared/logger/index";
import { getDatabase } from "../../shared/database/index.js"; import { getDatabase } from "../../shared/database/index.js";
const logger = createChildLogger("ui-state.service"); const logger = createChildLogger("ui-state.service");
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Request, Response } from "express"; import type { Request, Response } from "express";
import { createChildLogger } from "@/shared/logger/index";
import { asyncHandler } from "../../shared/middlewares/index.js"; import { asyncHandler } from "../../shared/middlewares/index.js";
import { publishCommandNoReply } from "../../shared/redis/index.js"; import { publishCommandNoReply } from "../../shared/redis/index.js";
import type { ConnectVoiceInput, VoiceCommandInput } from "./voice.schema.js"; import type { ConnectVoiceInput, VoiceCommandInput } from "./voice.schema.js";
@@ -1,6 +1,6 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Request, Response, Router } from "express"; import type { Request, Response, Router } from "express";
import express from "express"; import express from "express";
import { createChildLogger } from "@/shared/logger/index";
import { asyncHandler, validateBody } from "../../shared/middlewares/index.js"; import { asyncHandler, validateBody } from "../../shared/middlewares/index.js";
import { import {
handleConnectVoice, handleConnectVoice,
@@ -1,3 +1,9 @@
import { eq } from "drizzle-orm";
import {
createChildLogger,
tryCommandThenFallback,
} from "../../shared/commandHelper.js";
import { getDatabase } from "../../shared/database/index.js";
import { import {
COMMAND_GUILDS_LIST, COMMAND_GUILDS_LIST,
COMMAND_GUILDS_TEXT_CHANNELS, COMMAND_GUILDS_TEXT_CHANNELS,
@@ -8,12 +14,6 @@ import {
pgMessagesTable, pgMessagesTable,
VOICE_STATUS_KEY, VOICE_STATUS_KEY,
} from "../../shared/index.js"; } from "../../shared/index.js";
import { eq } from "drizzle-orm";
import {
createChildLogger,
tryCommandThenFallback,
} from "../../shared/commandHelper.js";
import { getDatabase } from "../../shared/database/index.js";
import { publishCommand, readRedisStatus } from "../../shared/redis/index.js"; import { publishCommand, readRedisStatus } from "../../shared/redis/index.js";
const logger = createChildLogger("voice.service"); const logger = createChildLogger("voice.service");
@@ -160,8 +160,6 @@ export const configSchema = z
.default(30000) .default(30000)
.describe("Timeout for individual LLM moderation calls"), .describe("Timeout for individual LLM moderation calls"),
// ── AI Analysis Timing ────────────────────────────────────────────── // ── AI Analysis Timing ──────────────────────────────────────────────
AI_ANALYSIS_DEBOUNCE_MS: z.coerce.number().positive().default(500), AI_ANALYSIS_DEBOUNCE_MS: z.coerce.number().positive().default(500),
AI_ANALYSIS_RECOVERY_INTERVAL_MS: z.coerce AI_ANALYSIS_RECOVERY_INTERVAL_MS: z.coerce
+1 -1
View File
@@ -1,6 +1,6 @@
import { createChildLogger } from "../logger/index.js";
import { drizzle } from "drizzle-orm/node-postgres"; import { drizzle } from "drizzle-orm/node-postgres";
import type { Pool, PoolClient } from "pg"; import type { Pool, PoolClient } from "pg";
import { createChildLogger } from "../logger/index.js";
import { closePool, createPoolFromConfig } from "./pool.js"; import { closePool, createPoolFromConfig } from "./pool.js";
const logger = createChildLogger("database.init"); const logger = createChildLogger("database.init");
@@ -592,5 +592,4 @@ export type DbRetentionPolicyInsert =
// Chatbot Messages // Chatbot Messages
export type ChatbotMessage = typeof chatbotMessagesTable.$inferSelect; export type ChatbotMessage = typeof chatbotMessagesTable.$inferSelect;
export type ChatbotMessageInsert = export type ChatbotMessageInsert = typeof chatbotMessagesTable.$inferInsert;
typeof chatbotMessagesTable.$inferInsert;
@@ -1,7 +1,7 @@
import { AppError, ValidationError } from "@/shared/errors/index";
import { createChildLogger } from "@/shared/logger/index";
import type { NextFunction, Request, Response } from "express"; import type { NextFunction, Request, Response } from "express";
import type { ZodSchema } from "zod"; import type { ZodSchema } from "zod";
import { AppError, ValidationError } from "@/shared/errors/index";
import { createChildLogger } from "@/shared/logger/index";
const logger = createChildLogger("middleware"); const logger = createChildLogger("middleware");
+2 -2
View File
@@ -1,4 +1,6 @@
import { randomUUID } from "node:crypto"; import { randomUUID } from "node:crypto";
import Redis from "ioredis";
import { config } from "../config/index.js";
import { import {
BACKEND_COMMAND, BACKEND_COMMAND,
BACKEND_COMMAND_REPLY_PREFIX, BACKEND_COMMAND_REPLY_PREFIX,
@@ -6,8 +8,6 @@ import {
type CommandReply, type CommandReply,
} from "../index.js"; } from "../index.js";
import { createChildLogger } from "../logger/index.js"; import { createChildLogger } from "../logger/index.js";
import Redis from "ioredis";
import { config } from "../config/index.js";
const logger = createChildLogger("redis.command-channel"); const logger = createChildLogger("redis.command-channel");
+5 -2
View File
@@ -1,7 +1,10 @@
import { DISCORD_CHANNEL_TO_WS_EVENT, DISCORD_VOICE_PCM } from "../shared/index.js";
import { createChildLogger } from "../shared/logger/index.js";
import Redis from "ioredis"; import Redis from "ioredis";
import { config } from "../shared/config/index.js"; import { config } from "../shared/config/index.js";
import {
DISCORD_CHANNEL_TO_WS_EVENT,
DISCORD_VOICE_PCM,
} from "../shared/index.js";
import { createChildLogger } from "../shared/logger/index.js";
import { broadcastBinary, broadcastEvent } from "./broadcast.js"; import { broadcastBinary, broadcastEvent } from "./broadcast.js";
const logger = createChildLogger("ws.redis-bridge"); const logger = createChildLogger("ws.redis-bridge");
+2 -2
View File
@@ -1,8 +1,8 @@
import type { Server } from "node:http"; import type { Server } from "node:http";
import { BACKEND_COMMAND, BACKEND_VOICE_TRANSMIT } from "../shared/index.js";
import { createChildLogger } from "../shared/logger/index.js";
import { WebSocket, WebSocketServer } from "ws"; import { WebSocket, WebSocketServer } from "ws";
import { config } from "../shared/config/index.js"; import { config } from "../shared/config/index.js";
import { BACKEND_COMMAND, BACKEND_VOICE_TRANSMIT } from "../shared/index.js";
import { createChildLogger } from "../shared/logger/index.js";
import { setBroadcastFunctions } from "./broadcast.js"; import { setBroadcastFunctions } from "./broadcast.js";
const logger = createChildLogger("ws.server"); const logger = createChildLogger("ws.server");
@@ -1,8 +1,8 @@
import { ConfigError, DatabaseError } from "@/shared/errors/index";
import { createChildLogger } from "@/shared/logger/index";
import { Client } from "discord.js-selfbot-v13"; import { Client } from "discord.js-selfbot-v13";
import { inArray, lt } from "drizzle-orm"; import { inArray, lt } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { ConfigError, DatabaseError } from "@/shared/errors/index";
import { createChildLogger } from "@/shared/logger/index";
import { startPendingAIAnalysisWorker } from "../modules/ai-moderation/aiAnalyzer.js"; import { startPendingAIAnalysisWorker } from "../modules/ai-moderation/aiAnalyzer.js";
import { registerChannelTopicCapture } from "../modules/channel-topic/index.js"; import { registerChannelTopicCapture } from "../modules/channel-topic/index.js";
import { CommandHandler } from "../modules/command-handler/commandHandler.js"; import { CommandHandler } from "../modules/command-handler/commandHandler.js";
@@ -1,6 +1,6 @@
import { createChildLogger } from "@/shared/logger/index";
import { inArray, lt } from "drizzle-orm"; import { inArray, lt } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../shared/config/config.js"; import { config } from "../shared/config/config.js";
import { getDatabase } from "../shared/database/drizzle.js"; import { getDatabase } from "../shared/database/drizzle.js";
import type * as schema from "../shared/database/schema.js"; import type * as schema from "../shared/database/schema.js";
+1 -1
View File
@@ -1,5 +1,5 @@
import type { createChildLogger } from "@/shared/logger/index";
import type { Client } from "discord.js-selfbot-v13"; import type { Client } from "discord.js-selfbot-v13";
import type { createChildLogger } from "@/shared/logger/index";
import type { CommandHandler } from "../modules/command-handler/commandHandler.js"; import type { CommandHandler } from "../modules/command-handler/commandHandler.js";
import type { EventBroadcaster } from "../modules/event-broadcaster/index.js"; import type { EventBroadcaster } from "../modules/event-broadcaster/index.js";
import type { stopMetricsServer } from "../modules/gateway-metrics/index.js"; import type { stopMetricsServer } from "../modules/gateway-metrics/index.js";
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Guild } from "discord.js-selfbot-v13"; import type { Guild } from "discord.js-selfbot-v13";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import type { MessageRecord } from "../message-capture/types.js"; import type { MessageRecord } from "../message-capture/types.js";
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Client, PermissionString } from "discord.js-selfbot-v13"; import type { Client, PermissionString } from "discord.js-selfbot-v13";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import { messageStore } from "../message-capture/messageStore.js"; import { messageStore } from "../message-capture/messageStore.js";
import type { MessageRecord } from "../message-capture/types.js"; import type { MessageRecord } from "../message-capture/types.js";
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Client } from "discord.js-selfbot-v13"; import type { Client } from "discord.js-selfbot-v13";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import type { MessageRecord } from "../message-capture/types.js"; import type { MessageRecord } from "../message-capture/types.js";
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { createChildLogger } from "@/shared/logger/index";
import { getDatabase } from "../../shared/database/drizzle.js"; import { getDatabase } from "../../shared/database/drizzle.js";
import { import {
type ChannelCulture, type ChannelCulture,
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import { encoding_for_model as encodingForModel } from "tiktoken"; import { encoding_for_model as encodingForModel } from "tiktoken";
import { createChildLogger } from "@/shared/logger/index";
import { import {
formatMediaEvidenceForPrompt, formatMediaEvidenceForPrompt,
renderDiscordMentions, renderDiscordMentions,
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import { LRUCache } from "lru-cache"; import { LRUCache } from "lru-cache";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import { LAST_ERROR } from "./moderationState.js"; import { LAST_ERROR } from "./moderationState.js";
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import { and, desc, eq, sql } from "drizzle-orm"; import { and, desc, eq, sql } from "drizzle-orm";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import { getDatabase } from "../../shared/database/drizzle.js"; import { getDatabase } from "../../shared/database/drizzle.js";
import { messagesTable } from "../../shared/database/schema.js"; import { messagesTable } from "../../shared/database/schema.js";
@@ -27,7 +27,16 @@ export function sanitizeDiscordTokens(content: string): string {
if (!content.includes("<")) return content; if (!content.includes("<")) return content;
return content.replace( return content.replace(
DISCORD_TOKEN_RE, DISCORD_TOKEN_RE,
(_full, emojiName, _emojiId, _userId, _roleId, _channelId, _time, _style) => { (
_full,
emojiName,
_emojiId,
_userId,
_roleId,
_channelId,
_time,
_style,
) => {
if (emojiName) return `[emoji:${emojiName}]`; if (emojiName) return `[emoji:${emojiName}]`;
// Capture groups tell us which alternative matched by position: // Capture groups tell us which alternative matched by position:
// 3=user, 4=role, 5=channel, 6=time // 3=user, 4=role, 5=channel, 6=time
@@ -1,12 +1,11 @@
export { startPendingAIAnalysisWorker } from "./aiAnalyzer.js";
export { runModerationAnalysis } from "./moderationOrchestrator.js";
export { buildSystemPrompt } from "./moderationPrompt.js";
export { sanitizeDiscordTokens } from "./discordTokens.js";
// ── Single-pass LLM pipeline exports ───────────────────────────────────── // ── Single-pass LLM pipeline exports ─────────────────────────────────────
export type { export type {
AnalysisInput, AnalysisInput,
AnalysisResult, AnalysisResult,
WorkerConfig,
MessageBatch, MessageBatch,
WorkerConfig,
} from "./ai-analysis-worker.js"; } from "./ai-analysis-worker.js";
export { startPendingAIAnalysisWorker } from "./aiAnalyzer.js";
export { sanitizeDiscordTokens } from "./discordTokens.js";
export { runModerationAnalysis } from "./moderationOrchestrator.js";
export { buildSystemPrompt } from "./moderationPrompt.js";
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import { LRUCache } from "lru-cache"; import { LRUCache } from "lru-cache";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import { messageStore } from "../message-capture/messageStore.js"; import { messageStore } from "../message-capture/messageStore.js";
import type { import type {
@@ -99,9 +99,7 @@ async function processIndividualFallback(
// retryable error — the recovery worker picks it up later. Producing a // retryable error — the recovery worker picks it up later. Producing a
// regex/wordlist verdict here would reintroduce false positives. // regex/wordlist verdict here would reintroduce false positives.
if (!analysisResult) { if (!analysisResult) {
throw new Error( throw new Error(`LLM analysis failed for message ${messageId}`);
`LLM analysis failed for message ${messageId}`,
);
} }
// Main thread: DB writes + broadcast // Main thread: DB writes + broadcast
@@ -5,9 +5,9 @@
* Used by both mediaAnalysisClient.ts and moderationOrchestrator.ts. * Used by both mediaAnalysisClient.ts and moderationOrchestrator.ts.
*/ */
import { renderDiscordMentions } from "../message-capture/messageMetadata.js";
import { messageStore } from "../message-capture/messageStore.js"; import { messageStore } from "../message-capture/messageStore.js";
import type { MessageRecord } from "../message-capture/types.js"; import type { MessageRecord } from "../message-capture/types.js";
import { renderDiscordMentions } from "../message-capture/messageMetadata.js";
import { sanitizeDiscordTokens } from "./discordTokens.js"; import { sanitizeDiscordTokens } from "./discordTokens.js";
/** Simple XML-escaping for content text. */ /** Simple XML-escaping for content text. */
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import type { z } from "zod"; import type { z } from "zod";
import { createChildLogger } from "@/shared/logger/index";
import type { AnalysisResult } from "../message-capture/types.js"; import type { AnalysisResult } from "../message-capture/types.js";
import type { import type {
RecommendedActionSchema, RecommendedActionSchema,
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import { z } from "zod"; import { z } from "zod";
import { createChildLogger } from "@/shared/logger/index";
const log = createChildLogger("moderationSchemas"); const log = createChildLogger("moderationSchemas");
@@ -1,6 +1,6 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Client } from "discord.js-selfbot-v13"; import type { Client } from "discord.js-selfbot-v13";
import { LRUCache } from "lru-cache"; import { LRUCache } from "lru-cache";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import type { EventBroadcaster } from "../event-broadcaster/index.js"; import type { EventBroadcaster } from "../event-broadcaster/index.js";
import type { MessageRecord } from "../message-capture/types.js"; import type { MessageRecord } from "../message-capture/types.js";
@@ -1,6 +1,6 @@
import Redis from "ioredis";
import { createChildLogger } from "@/shared/logger/index"; import { createChildLogger } from "@/shared/logger/index";
import { createAbortControllerWithTimeout } from "@/shared/utils/index"; import { createAbortControllerWithTimeout } from "@/shared/utils/index";
import Redis from "ioredis";
const log = createChildLogger("searxng-search"); const log = createChildLogger("searxng-search");
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import { and, desc, eq, sql } from "drizzle-orm"; import { and, desc, eq, sql } from "drizzle-orm";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import { getDatabase } from "../../shared/database/drizzle.js"; import { getDatabase } from "../../shared/database/drizzle.js";
import { messagesTable } from "../../shared/database/schema.js"; import { messagesTable } from "../../shared/database/schema.js";
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { createChildLogger } from "@/shared/logger/index";
import { getDatabase } from "../../shared/database/drizzle.js"; import { getDatabase } from "../../shared/database/drizzle.js";
import { import {
type UserProfile, type UserProfile,
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import sharp from "sharp"; import sharp from "sharp";
import { createChildLogger } from "@/shared/logger/index";
const log = createChildLogger("imageResizer"); const log = createChildLogger("imageResizer");
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Client, TextChannel } from "discord.js-selfbot-v13"; import type { Client, TextChannel } from "discord.js-selfbot-v13";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import type { EventBroadcaster } from "../event-broadcaster/eventBroadcaster.js"; import type { EventBroadcaster } from "../event-broadcaster/eventBroadcaster.js";
@@ -1,3 +1,6 @@
import type { Client } from "discord.js-selfbot-v13";
import Redis from "ioredis";
import { config } from "../../shared/config/config.js";
import { import {
BACKEND_COMMAND, BACKEND_COMMAND,
type CommandMessage, type CommandMessage,
@@ -6,9 +9,6 @@ import {
VOICE_STATUS_KEY, VOICE_STATUS_KEY,
} from "../../shared/index.js"; } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js"; import { createChildLogger } from "../../shared/logger/index.js";
import type { Client } from "discord.js-selfbot-v13";
import Redis from "ioredis";
import { config } from "../../shared/config/config.js";
import type { VoiceController } from "../voice-recording/voiceController.js"; import type { VoiceController } from "../voice-recording/voiceController.js";
import { GuildHandler } from "./guild.handler.js"; import { GuildHandler } from "./guild.handler.js";
import { import {
@@ -82,7 +82,9 @@ export class CommandHandler {
// Create domain-specific handlers with their dependencies // Create domain-specific handlers with their dependencies
this.voiceHandler = new VoiceHandler(client, voiceController); this.voiceHandler = new VoiceHandler(client, voiceController);
this.mediaHandler = new MediaHandler(client, () => voiceController.getStatus()); this.mediaHandler = new MediaHandler(client, () =>
voiceController.getStatus(),
);
this.guildHandler = new GuildHandler(client); this.guildHandler = new GuildHandler(client);
this.moderationHandler = new ModerationHandler(client); this.moderationHandler = new ModerationHandler(client);
@@ -1,6 +1,6 @@
import type { Client } from "discord.js-selfbot-v13";
import type { CommandMessage, CommandReply } from "../../shared/index.js"; import type { CommandMessage, CommandReply } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js"; import { createChildLogger } from "../../shared/logger/index.js";
import type { Client } from "discord.js-selfbot-v13";
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// GuildHandler // GuildHandler
@@ -1,8 +1,8 @@
import { randomUUID } from "node:crypto"; import { randomUUID } from "node:crypto";
import { StreamType } from "@discordjs/voice";
import type { Client } from "discord.js-selfbot-v13"; import type { Client } from "discord.js-selfbot-v13";
import type { CommandMessage, CommandReply } from "../../shared/index.js"; import type { CommandMessage, CommandReply } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js"; import { createChildLogger } from "../../shared/logger/index.js";
import { StreamType } from "@discordjs/voice";
import { import {
extractMediaInfo, extractMediaInfo,
resolveMediaUrl, resolveMediaUrl,
@@ -1,6 +1,6 @@
import type { Client } from "discord.js-selfbot-v13";
import type { CommandMessage, CommandReply } from "../../shared/index.js"; import type { CommandMessage, CommandReply } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js"; import { createChildLogger } from "../../shared/logger/index.js";
import type { Client } from "discord.js-selfbot-v13";
import { messageStore } from "../message-capture/messageStore.js"; import { messageStore } from "../message-capture/messageStore.js";
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -1,7 +1,7 @@
import type { CommandMessage, CommandReply } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js";
import type { Client } from "discord.js-selfbot-v13"; import type { Client } from "discord.js-selfbot-v13";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import type { CommandMessage, CommandReply } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js";
import { discordPlayer } from "../voice-recording/player.js"; import { discordPlayer } from "../voice-recording/player.js";
import { voiceTransmitter } from "../voice-recording/transmitter.js"; import { voiceTransmitter } from "../voice-recording/transmitter.js";
import type { VoiceController } from "../voice-recording/voiceController.js"; import type { VoiceController } from "../voice-recording/voiceController.js";
@@ -1,6 +1,9 @@
import type { AttachmentRecord, MessageRecord } from "../../shared/index.js";
import { type CustomLogger, createChildLogger } from "../../shared/logger/index.js";
import Redis from "ioredis"; import Redis from "ioredis";
import type { AttachmentRecord, MessageRecord } from "../../shared/index.js";
import {
type CustomLogger,
createChildLogger,
} from "../../shared/logger/index.js";
import { type DiscordGatewayEvent, EventChannels } from "./eventTypes.js"; import { type DiscordGatewayEvent, EventChannels } from "./eventTypes.js";
export class RedisEventPublisher { export class RedisEventPublisher {
@@ -1,9 +1,9 @@
import { createChildLogger } from "@/shared/logger/index";
import type { import type {
Client, Client,
GuildMember, GuildMember,
PartialGuildMember, PartialGuildMember,
} from "discord.js-selfbot-v13"; } from "discord.js-selfbot-v13";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import type { EventBroadcaster } from "../event-broadcaster/eventBroadcaster.js"; import type { EventBroadcaster } from "../event-broadcaster/eventBroadcaster.js";
@@ -1,6 +1,6 @@
import { createChildLogger, type Logger } from "@/shared/logger/index";
import { and, desc, eq, inArray, type SQL } from "drizzle-orm"; import { and, desc, eq, inArray, type SQL } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { createChildLogger, type Logger } from "@/shared/logger/index";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import { attachmentsTable } from "../../shared/database/schema.js"; import { attachmentsTable } from "../../shared/database/schema.js";
import type { AttachmentRecord } from "../message-capture/types.js"; import type { AttachmentRecord } from "../message-capture/types.js";
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Client, Message } from "discord.js-selfbot-v13"; import type { Client, Message } from "discord.js-selfbot-v13";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import { queueMessageAnalysis } from "../ai-moderation/aiAnalyzer.js"; import { queueMessageAnalysis } from "../ai-moderation/aiAnalyzer.js";
import { processAttachmentUpload } from "../attachment-upload/attachmentUploader.js"; import { processAttachmentUpload } from "../attachment-upload/attachmentUploader.js";
@@ -1,5 +1,5 @@
import { createChildLogger, type Logger } from "@/shared/logger/index";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { createChildLogger, type Logger } from "@/shared/logger/index";
import { getDatabase } from "../../shared/database/drizzle.js"; import { getDatabase } from "../../shared/database/drizzle.js";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import type { import type {
@@ -327,7 +327,9 @@ export const messageStore: MessageStore = new Proxy<MessageStore>(
{ {
get(_, prop: string | symbol) { get(_, prop: string | symbol) {
const store = resolveStore(); const store = resolveStore();
const value = (store as unknown as Record<string | symbol, unknown>)[prop]; const value = (store as unknown as Record<string | symbol, unknown>)[
prop
];
return typeof value === "function" ? value.bind(store) : value; return typeof value === "function" ? value.bind(store) : value;
}, },
}, },
@@ -1,6 +1,6 @@
import { createChildLogger, type Logger } from "@/shared/logger/index";
import { and, asc, desc, eq, inArray, isNull, or, sql } from "drizzle-orm"; import { and, asc, desc, eq, inArray, isNull, or, sql } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { createChildLogger, type Logger } from "@/shared/logger/index";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import { messagesTable } from "../../shared/database/schema.js"; import { messagesTable } from "../../shared/database/schema.js";
import type { MessageRecord } from "../message-capture/types.js"; import type { MessageRecord } from "../message-capture/types.js";
@@ -1,6 +1,6 @@
import { createChildLogger, type Logger } from "@/shared/logger/index";
import { and, eq, isNull, sql } from "drizzle-orm"; import { and, eq, isNull, sql } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { createChildLogger, type Logger } from "@/shared/logger/index";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import { messagesTable } from "../../shared/database/schema.js"; import { messagesTable } from "../../shared/database/schema.js";
import type { MessageRecord } from "../message-capture/types.js"; import type { MessageRecord } from "../message-capture/types.js";
@@ -1,6 +1,6 @@
import { createChildLogger, type Logger } from "@/shared/logger/index";
import { and, desc, eq, or, type SQL } from "drizzle-orm"; import { and, desc, eq, or, type SQL } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { createChildLogger, type Logger } from "@/shared/logger/index";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import { import {
messageEditsTable, messageEditsTable,
@@ -1,5 +1,5 @@
import { createChildLogger, type Logger } from "@/shared/logger/index";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { createChildLogger, type Logger } from "@/shared/logger/index";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import type { import type {
MessageQuery, MessageQuery,
@@ -1,9 +1,9 @@
import { buildCursorCondition, pageResult } from "../../shared/index.js";
import { createChildLogger, type Logger } from "../../shared/logger/index.js";
import { and, desc, eq, inArray, type SQL, sql } from "drizzle-orm"; import { and, desc, eq, inArray, type SQL, sql } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import { messagesTable } from "../../shared/database/schema.js"; import { messagesTable } from "../../shared/database/schema.js";
import { buildCursorCondition, pageResult } from "../../shared/index.js";
import { createChildLogger, type Logger } from "../../shared/logger/index.js";
import type { import type {
MessageQuery, MessageQuery,
MessageRecord, MessageRecord,
@@ -1,6 +1,6 @@
import { createChildLogger, type Logger } from "@/shared/logger/index";
import { and, desc, eq, isNull, or, type SQL, sql } from "drizzle-orm"; import { and, desc, eq, isNull, or, type SQL, sql } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { createChildLogger, type Logger } from "@/shared/logger/index";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import { messagesTable } from "../../shared/database/schema.js"; import { messagesTable } from "../../shared/database/schema.js";
import type { MessageRecord } from "../message-capture/types.js"; import type { MessageRecord } from "../message-capture/types.js";
@@ -1,9 +1,9 @@
import { buildCursorCondition, pageResult } from "../../shared/index.js";
import { createChildLogger, type Logger } from "../../shared/logger/index.js";
import { and, desc, eq, inArray, type SQL, sql } from "drizzle-orm"; import { and, desc, eq, inArray, type SQL, sql } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import { moderationActionsTable } from "../../shared/database/schema.js"; import { moderationActionsTable } from "../../shared/database/schema.js";
import { buildCursorCondition, pageResult } from "../../shared/index.js";
import { createChildLogger, type Logger } from "../../shared/logger/index.js";
import type { ModerationAction, PageResult } from "../message-capture/types.js"; import type { ModerationAction, PageResult } from "../message-capture/types.js";
// ─── ModerationActionsDb Class ────────────────────────────────────────────── // ─── ModerationActionsDb Class ──────────────────────────────────────────────
@@ -1,6 +1,6 @@
import { createChildLogger, type Logger } from "@/shared/logger/index";
import { and, eq, isNull, or } from "drizzle-orm"; import { and, eq, isNull, or } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { createChildLogger, type Logger } from "@/shared/logger/index";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import { retentionPoliciesTable } from "../../shared/database/schema.js"; import { retentionPoliciesTable } from "../../shared/database/schema.js";
import type { RetentionPolicy } from "../message-capture/types.js"; import type { RetentionPolicy } from "../message-capture/types.js";
@@ -45,8 +45,7 @@ export class RetentionDb {
), ),
); );
if (channelRows.length > 0) if (channelRows.length > 0) return channelRows[0] as RetentionPolicy;
return channelRows[0] as RetentionPolicy;
} }
// Fall back to the guild default (channel_id IS NULL) // Fall back to the guild default (channel_id IS NULL)
@@ -1,9 +1,9 @@
import { buildCursorCondition, pageResult } from "../../shared/index.js";
import { createChildLogger, type Logger } from "../../shared/logger/index.js";
import { and, desc, eq, inArray, type SQL, sql } from "drizzle-orm"; import { and, desc, eq, inArray, type SQL, sql } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import { messageReviewsTable } from "../../shared/database/schema.js"; import { messageReviewsTable } from "../../shared/database/schema.js";
import { buildCursorCondition, pageResult } from "../../shared/index.js";
import { createChildLogger, type Logger } from "../../shared/logger/index.js";
import type { MessageReview, PageResult } from "../message-capture/types.js"; import type { MessageReview, PageResult } from "../message-capture/types.js";
// ─── ReviewsDb Class ──────────────────────────────────────────────────────── // ─── ReviewsDb Class ────────────────────────────────────────────────────────
@@ -94,7 +94,9 @@ export class ReviewsDb {
conditions.push( conditions.push(
inArray( inArray(
messageReviewsTable.status, messageReviewsTable.status,
query.status as Array<"pending" | "approved" | "rejected" | "escalated">, query.status as Array<
"pending" | "approved" | "rejected" | "escalated"
>,
), ),
); );
} }
@@ -1,4 +1,5 @@
import type fs from "node:fs"; import type fs from "node:fs";
import type prism from "prism-media";
import type { import type {
AnalysisQueueStatus, AnalysisQueueStatus,
AttachmentRecord, AttachmentRecord,
@@ -6,7 +7,6 @@ import type {
UserMetadata, UserMetadata,
VoiceRecordingUploadData, VoiceRecordingUploadData,
} from "../../shared/index.js"; } from "../../shared/index.js";
import type prism from "prism-media";
// Re-export all shared types for backward compatibility // Re-export all shared types for backward compatibility
export type { export type {
@@ -1,4 +1,3 @@
import { createChildLogger } from "@/shared/logger/index";
import type { import type {
Client, Client,
MessageReaction, MessageReaction,
@@ -6,6 +5,7 @@ import type {
PartialUser, PartialUser,
User, User,
} from "discord.js-selfbot-v13"; } from "discord.js-selfbot-v13";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import { getDatabase } from "../../shared/database/drizzle.js"; import { getDatabase } from "../../shared/database/drizzle.js";
import { reactionsTable } from "../../shared/database/schema.js"; import { reactionsTable } from "../../shared/database/schema.js";
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Client, ThreadChannel } from "discord.js-selfbot-v13"; import type { Client, ThreadChannel } from "discord.js-selfbot-v13";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import type { EventBroadcaster } from "../event-broadcaster/eventBroadcaster.js"; import type { EventBroadcaster } from "../event-broadcaster/eventBroadcaster.js";
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import type { Client, Presence } from "discord.js-selfbot-v13"; import type { Client, Presence } from "discord.js-selfbot-v13";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import type { EventBroadcaster } from "../event-broadcaster/eventBroadcaster.js"; import type { EventBroadcaster } from "../event-broadcaster/eventBroadcaster.js";
@@ -7,8 +7,8 @@
* The backend forwards these unchanged to frontend clients. * The backend forwards these unchanged to frontend clients.
*/ */
import { createChildLogger } from "@/shared/logger/index";
import WebSocket from "ws"; import WebSocket from "ws";
import { createChildLogger } from "@/shared/logger/index";
const logger = createChildLogger("voice-pcm-ws"); const logger = createChildLogger("voice-pcm-ws");
@@ -1,7 +1,7 @@
import { type ChildProcess, spawn } from "node:child_process"; import { type ChildProcess, spawn } from "node:child_process";
import { PassThrough, type Readable } from "node:stream"; import { PassThrough, type Readable } from "node:stream";
import { createChildLogger } from "@/shared/logger/index";
import { StreamType } from "@discordjs/voice"; import { StreamType } from "@discordjs/voice";
import { createChildLogger } from "@/shared/logger/index";
const logger = createChildLogger("media-source"); const logger = createChildLogger("media-source");
@@ -348,7 +348,9 @@ export function getDirectVideoUrl(url: string): Promise<string> {
if (code !== 0) { if (code !== 0) {
const detail = stderrBuf.trim() ? `: ${stderrBuf.trim()}` : ""; const detail = stderrBuf.trim() ? `: ${stderrBuf.trim()}` : "";
reject( reject(
new Error(`yt-dlp direct URL resolution exited with code ${code}${detail}`), new Error(
`yt-dlp direct URL resolution exited with code ${code}${detail}`,
),
); );
return; return;
} }
@@ -1,6 +1,6 @@
import { createChildLogger } from "@/shared/logger/index";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { createChildLogger } from "@/shared/logger/index";
import { getDatabase } from "../../shared/database/drizzle.js"; import { getDatabase } from "../../shared/database/drizzle.js";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import { muxerJobsTable } from "../../shared/database/schema.js"; import { muxerJobsTable } from "../../shared/database/schema.js";
@@ -1,5 +1,4 @@
import type { Readable } from "node:stream"; import type { Readable } from "node:stream";
import { createChildLogger } from "@/shared/logger/index";
import { import {
type AudioPlayer, type AudioPlayer,
AudioPlayerStatus, AudioPlayerStatus,
@@ -9,6 +8,7 @@ import {
StreamType, StreamType,
type VoiceConnection, type VoiceConnection,
} from "@discordjs/voice"; } from "@discordjs/voice";
import { createChildLogger } from "@/shared/logger/index";
import type { DiscordPlayerOwner, DiscordPlayOptions } from "./mediaTypes.js"; import type { DiscordPlayerOwner, DiscordPlayOptions } from "./mediaTypes.js";
const logger = createChildLogger("player"); const logger = createChildLogger("player");
@@ -1,6 +1,4 @@
import { promises as fsPromises } from "node:fs"; import { promises as fsPromises } from "node:fs";
import { createChildLogger } from "@/shared/logger/index";
import { retryWithBackoff } from "@/shared/utils/index";
import { import {
type DiscordGatewayAdapterCreator, type DiscordGatewayAdapterCreator,
entersState, entersState,
@@ -10,6 +8,8 @@ import {
VoiceConnectionStatus, VoiceConnectionStatus,
} from "@discordjs/voice"; } from "@discordjs/voice";
import type { Client, VoiceChannel } from "discord.js-selfbot-v13"; import type { Client, VoiceChannel } from "discord.js-selfbot-v13";
import { createChildLogger } from "@/shared/logger/index";
import { retryWithBackoff } from "@/shared/utils/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
import type { EventBroadcaster } from "../event-broadcaster/eventBroadcaster.js"; import type { EventBroadcaster } from "../event-broadcaster/eventBroadcaster.js";
import type { VoicePcmWsClient } from "../voice-pcm-ws/index.js"; import type { VoicePcmWsClient } from "../voice-pcm-ws/index.js";
@@ -1,6 +1,6 @@
import { createRequire } from "node:module"; import { createRequire } from "node:module";
import { createChildLogger } from "@/shared/logger/index";
import * as prism from "prism-media"; import * as prism from "prism-media";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../../shared/config/config.js"; import { config } from "../../../shared/config/config.js";
const require = createRequire(import.meta.url); const require = createRequire(import.meta.url);
@@ -1,6 +1,6 @@
import path from "node:path"; import path from "node:path";
import { createChildLogger } from "@/shared/logger/index";
import type { Client, VoiceChannel } from "discord.js-selfbot-v13"; import type { Client, VoiceChannel } from "discord.js-selfbot-v13";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../../shared/config/config.js"; import { config } from "../../../shared/config/config.js";
import type { import type {
SegmentMetadata, SegmentMetadata,
@@ -1,7 +1,7 @@
import fs from "node:fs"; import fs from "node:fs";
import path from "node:path"; import path from "node:path";
import { createChildLogger } from "@/shared/logger/index";
import * as prism from "prism-media"; import * as prism from "prism-media";
import { createChildLogger } from "@/shared/logger/index";
import type { SegmentState } from "../../message-capture/types.js"; import type { SegmentState } from "../../message-capture/types.js";
const logger = createChildLogger("voice-segment"); const logger = createChildLogger("voice-segment");
@@ -1,8 +1,8 @@
import { promises as fsPromises } from "node:fs"; import { promises as fsPromises } from "node:fs";
import path from "node:path"; import path from "node:path";
import { createChildLogger } from "@/shared/logger/index";
import type { VoiceConnection } from "@discordjs/voice"; import type { VoiceConnection } from "@discordjs/voice";
import type { Client, VoiceChannel } from "discord.js-selfbot-v13"; import type { Client, VoiceChannel } from "discord.js-selfbot-v13";
import { createChildLogger } from "@/shared/logger/index";
import type { EventBroadcaster } from "../../event-broadcaster/eventBroadcaster.js"; import type { EventBroadcaster } from "../../event-broadcaster/eventBroadcaster.js";
import { collectUserMetadata } from "./metadata.js"; import { collectUserMetadata } from "./metadata.js";
import { finalizeSegment } from "./segmentFinalizer.js"; import { finalizeSegment } from "./segmentFinalizer.js";
@@ -1,6 +1,6 @@
import { createChildLogger } from "@/shared/logger/index";
import type { VoiceConnection } from "@discordjs/voice"; import type { VoiceConnection } from "@discordjs/voice";
import { EndBehaviorType } from "@discordjs/voice"; import { EndBehaviorType } from "@discordjs/voice";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../../shared/config/config.js"; import { config } from "../../../shared/config/config.js";
import { PacketFilter } from "../packetFilter.js"; import { PacketFilter } from "../packetFilter.js";
import { OpusDecoder } from "./decoder.js"; import { OpusDecoder } from "./decoder.js";
@@ -1,6 +1,6 @@
import { execFile } from "node:child_process";
import fs from "node:fs"; import fs from "node:fs";
import path from "node:path"; import path from "node:path";
import { execFile } from "node:child_process";
import { promisify } from "node:util"; import { promisify } from "node:util";
import { createChildLogger } from "@/shared/logger/index"; import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../../shared/config/config.js"; import { config } from "../../../shared/config/config.js";
@@ -1,14 +1,14 @@
import { import {
Encoders, Encoders,
prepareStream,
playStream, playStream,
prepareStream,
Streamer, Streamer,
Utils, Utils,
} from "@dank074/discord-video-stream"; } from "@dank074/discord-video-stream";
import type { Client } from "discord.js-selfbot-v13"; import type { Client } from "discord.js-selfbot-v13";
import { createChildLogger } from "@/shared/logger/index"; import { createChildLogger } from "@/shared/logger/index";
import type { ScreenSharePlayback } from "./mediaTypes.js";
import { getDirectVideoUrl } from "./mediaSource.js"; import { getDirectVideoUrl } from "./mediaSource.js";
import type { ScreenSharePlayback } from "./mediaTypes.js";
import { discordPlayer } from "./player.js"; import { discordPlayer } from "./player.js";
const logger = createChildLogger("screen-share"); const logger = createChildLogger("screen-share");
@@ -46,11 +46,7 @@ export class ScreenShareController {
async start(source: string): Promise<ScreenSharePlayback> { async start(source: string): Promise<ScreenSharePlayback> {
const status = this.getVoiceStatus(); const status = this.getVoiceStatus();
if ( if (!status.connected || !status.activeGuildId || !status.activeChannelId) {
!status.connected ||
!status.activeGuildId ||
!status.activeChannelId
) {
throw new Error("Connect to a voice channel before sharing screen"); throw new Error("Connect to a voice channel before sharing screen");
} }
@@ -81,15 +77,13 @@ export class ScreenShareController {
}).finally(() => { }).finally(() => {
this.active = null; this.active = null;
}); });
const controller = this;
this.active = { this.active = {
done, done,
stop: () => { stop: () => {
if (stopped) return; if (stopped) return;
stopped = true; stopped = true;
command.kill("SIGTERM"); command.kill("SIGTERM");
controller.active = null; this.active = null;
}, },
}; };
@@ -1,9 +1,9 @@
import { spawn } from "node:child_process"; import { spawn } from "node:child_process";
import { PassThrough } from "node:stream"; import { PassThrough } from "node:stream";
import { BACKEND_VOICE_TRANSMIT } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js";
import { StreamType } from "@discordjs/voice"; import { StreamType } from "@discordjs/voice";
import type Redis from "ioredis"; import type Redis from "ioredis";
import { BACKEND_VOICE_TRANSMIT } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js";
import { discordPlayer } from "./player.js"; import { discordPlayer } from "./player.js";
const logger = createChildLogger("transmitter"); const logger = createChildLogger("transmitter");
@@ -1,7 +1,7 @@
import { AppError } from "@/shared/errors/index";
import { createChildLogger } from "@/shared/logger/index";
import type { VoiceConnection } from "@discordjs/voice"; import type { VoiceConnection } from "@discordjs/voice";
import type { Client, Guild, VoiceChannel } from "discord.js-selfbot-v13"; import type { Client, Guild, VoiceChannel } from "discord.js-selfbot-v13";
import { AppError } from "@/shared/errors/index";
import { createChildLogger } from "@/shared/logger/index";
import { discordPlayer } from "./player.js"; import { discordPlayer } from "./player.js";
import { startRecording, stopRecording } from "./recorder.js"; import { startRecording, stopRecording } from "./recorder.js";
@@ -1,8 +1,8 @@
// ─── Voice Transcription — AI-powered speech-to-text for voice recordings ──── // ─── Voice Transcription — AI-powered speech-to-text for voice recordings ────
import { createReadStream } from "node:fs"; import { createReadStream } from "node:fs";
import { createChildLogger } from "@/shared/logger/index";
import OpenAI from "openai"; import OpenAI from "openai";
import { createChildLogger } from "@/shared/logger/index";
import { config } from "../../shared/config/config.js"; import { config } from "../../shared/config/config.js";
const logger = createChildLogger("voice-transcriber"); const logger = createChildLogger("voice-transcriber");
@@ -1,6 +1,6 @@
import { createChildLogger } from "../logger/index.js";
import { drizzle } from "drizzle-orm/node-postgres"; import { drizzle } from "drizzle-orm/node-postgres";
import type { Pool, PoolClient } from "pg"; import type { Pool, PoolClient } from "pg";
import { createChildLogger } from "../logger/index.js";
import { closePool, createPoolFromConfig } from "./pool.js"; import { closePool, createPoolFromConfig } from "./pool.js";
const logger = createChildLogger("database.init"); const logger = createChildLogger("database.init");
@@ -1,10 +1,10 @@
import "dotenv/config"; import "dotenv/config";
import { readFile } from "node:fs/promises"; import { readFile } from "node:fs/promises";
import { join } from "node:path"; import { join } from "node:path";
import { createChildLogger } from "@/shared/logger/index";
import { drizzle as drizzlePostgres } from "drizzle-orm/node-postgres"; import { drizzle as drizzlePostgres } from "drizzle-orm/node-postgres";
import { migrate as migratePostgres } from "drizzle-orm/node-postgres/migrator"; import { migrate as migratePostgres } from "drizzle-orm/node-postgres/migrator";
import type { PoolClient } from "pg"; import type { PoolClient } from "pg";
import { createChildLogger } from "@/shared/logger/index";
import { import {
closeDatabase, closeDatabase,
initializeDatabase, initializeDatabase,
@@ -595,8 +595,7 @@ export type DbRetentionPolicyInsert =
// Chatbot Messages // Chatbot Messages
export type ChatbotMessage = typeof chatbotMessagesTable.$inferSelect; export type ChatbotMessage = typeof chatbotMessagesTable.$inferSelect;
export type ChatbotMessageInsert = export type ChatbotMessageInsert = typeof chatbotMessagesTable.$inferInsert;
typeof chatbotMessagesTable.$inferInsert;
// ============================================================================= // =============================================================================
// Moderation Actions (gateway-local) // Moderation Actions (gateway-local)
@@ -1,8 +1,3 @@
import {
pgAttachmentsTable,
pgMessageReviewsTable,
pgMessagesTable,
} from "../../../shared/index.js";
import { import {
bigint as pgBigint, bigint as pgBigint,
boolean as pgBoolean, boolean as pgBoolean,
@@ -11,6 +6,11 @@ import {
text as pgText, text as pgText,
uuid as pgUuid, uuid as pgUuid,
} from "drizzle-orm/pg-core"; } from "drizzle-orm/pg-core";
import {
pgAttachmentsTable,
pgMessageReviewsTable,
pgMessagesTable,
} from "../../../shared/index.js";
// Re-export shared message/attachment/review tables // Re-export shared message/attachment/review tables
export { pgAttachmentsTable, pgMessageReviewsTable, pgMessagesTable }; export { pgAttachmentsTable, pgMessageReviewsTable, pgMessagesTable };
@@ -25,5 +25,4 @@ export type UIStateInsert = typeof uiStateTable.$inferInsert;
export type RetentionPolicy = typeof retentionPoliciesTable.$inferSelect; export type RetentionPolicy = typeof retentionPoliciesTable.$inferSelect;
export type RetentionPolicyInsert = typeof retentionPoliciesTable.$inferInsert; export type RetentionPolicyInsert = typeof retentionPoliciesTable.$inferInsert;
export type ChatbotMessage = typeof chatbotMessagesTable.$inferSelect; export type ChatbotMessage = typeof chatbotMessagesTable.$inferSelect;
export type ChatbotMessageInsert = export type ChatbotMessageInsert = typeof chatbotMessagesTable.$inferInsert;
typeof chatbotMessagesTable.$inferInsert;
@@ -1,5 +1,5 @@
import { createChildLogger } from "@/shared/logger/index";
import { desc, eq } from "drizzle-orm"; import { desc, eq } from "drizzle-orm";
import { createChildLogger } from "@/shared/logger/index";
import { getDatabase } from "./drizzle.js"; import { getDatabase } from "./drizzle.js";
import { import {
type VoiceRecording, type VoiceRecording,
@@ -12,7 +12,6 @@ import { Input } from "@/components/ui/input";
import { Progress } from "@/components/ui/progress"; import { Progress } from "@/components/ui/progress";
import { useMessageSearch, useReanalyze } from "@/hooks"; import { useMessageSearch, useReanalyze } from "@/hooks";
import { renderMessageContent, safeParseJsonArray } from "@/lib/format"; import { renderMessageContent, safeParseJsonArray } from "@/lib/format";
import type { MessageRecord } from "@/lib/types";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
export function SearchPanel() { export function SearchPanel() {
@@ -1,7 +1,7 @@
"use client"; "use client";
import { useRef, useEffect } from "react";
import { Send } from "lucide-react"; import { Send } from "lucide-react";
import { useEffect, useRef } from "react";
import { useChatbot } from "./chatbot-context"; import { useChatbot } from "./chatbot-context";
interface ChatPanelProps { interface ChatPanelProps {
@@ -15,11 +15,12 @@ export function ChatPanel({ inputRef: externalInputRef }: ChatPanelProps) {
const inputRef = externalInputRef ?? internalInputRef; const inputRef = externalInputRef ?? internalInputRef;
// Auto-scroll to bottom on new messages // Auto-scroll to bottom on new messages
// biome-ignore lint/correctness/useExhaustiveDependencies: re-run on message arrival; scroll is a visual effect keyed on new content
useEffect(() => { useEffect(() => {
if (listRef.current) { if (listRef.current) {
listRef.current.scrollTop = listRef.current.scrollHeight; listRef.current.scrollTop = listRef.current.scrollHeight;
} }
}, [messages, isTyping]); }, [messages]);
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
@@ -35,7 +36,9 @@ export function ChatPanel({ inputRef: externalInputRef }: ChatPanelProps) {
<div ref={listRef} className="flex-1 overflow-y-auto px-2 py-1 space-y-1"> <div ref={listRef} className="flex-1 overflow-y-auto px-2 py-1 space-y-1">
{messages.length === 0 && ( {messages.length === 0 && (
<div className="flex items-center justify-center h-full"> <div className="flex items-center justify-center h-full">
<p className="text-[10px] text-text-secondary/40">Ask chatbot anything</p> <p className="text-[10px] text-text-secondary/40">
Ask chatbot anything
</p>
</div> </div>
)} )}
{messages.slice(-8).map((msg, i) => ( {messages.slice(-8).map((msg, i) => (
@@ -58,9 +61,18 @@ export function ChatPanel({ inputRef: externalInputRef }: ChatPanelProps) {
<div className="flex justify-start"> <div className="flex justify-start">
<div className="glass rounded-lg px-2 py-1"> <div className="glass rounded-lg px-2 py-1">
<span className="inline-flex gap-0.5"> <span className="inline-flex gap-0.5">
<span className="size-1 rounded-full bg-text-secondary animate-bounce" style={{ animationDelay: "0ms" }} /> <span
<span className="size-1 rounded-full bg-text-secondary animate-bounce" style={{ animationDelay: "150ms" }} /> className="size-1 rounded-full bg-text-secondary animate-bounce"
<span className="size-1 rounded-full bg-text-secondary animate-bounce" style={{ animationDelay: "300ms" }} /> style={{ animationDelay: "0ms" }}
/>
<span
className="size-1 rounded-full bg-text-secondary animate-bounce"
style={{ animationDelay: "150ms" }}
/>
<span
className="size-1 rounded-full bg-text-secondary animate-bounce"
style={{ animationDelay: "300ms" }}
/>
</span> </span>
</div> </div>
</div> </div>
@@ -68,7 +80,10 @@ export function ChatPanel({ inputRef: externalInputRef }: ChatPanelProps) {
</div> </div>
{/* Input bar */} {/* Input bar */}
<form onSubmit={handleSubmit} className="flex items-center gap-1 px-2 py-1.5 border-t border-glass-border shrink-0"> <form
onSubmit={handleSubmit}
className="flex items-center gap-1 px-2 py-1.5 border-t border-glass-border shrink-0"
>
<input <input
ref={inputRef} ref={inputRef}
type="text" type="text"
@@ -33,7 +33,14 @@ export function ChatbotCanvas() {
ctx.clearRect(0, 0, w, h); ctx.clearRect(0, 0, w, h);
// Background circle // Background circle
const gradient = ctx.createRadialGradient(w / 2, h / 2 - 10, 10, w / 2, h / 2, 80); const gradient = ctx.createRadialGradient(
w / 2,
h / 2 - 10,
10,
w / 2,
h / 2,
80,
);
gradient.addColorStop(0, "oklch(0.62 0.17 215 / 0.8)"); gradient.addColorStop(0, "oklch(0.62 0.17 215 / 0.8)");
gradient.addColorStop(0.6, "oklch(0.12 0.02 245 / 0.9)"); gradient.addColorStop(0.6, "oklch(0.12 0.02 245 / 0.9)");
gradient.addColorStop(1, "oklch(0.07 0.015 250 / 1)"); gradient.addColorStop(1, "oklch(0.07 0.015 250 / 1)");
@@ -112,11 +119,6 @@ export function ChatbotCanvas() {
ctx.arc(w / 2, 75, 6, 0.1, Math.PI - 0.1); ctx.arc(w / 2, 75, 6, 0.1, Math.PI - 0.1);
ctx.stroke(); ctx.stroke();
} }
// Breathing animation — subtle canvas shift
const breath = Math.sin(Date.now() / 1000) * 1.5;
// Applied via CSS transform on container instead
}, [expression]); }, [expression]);
return ( return (
@@ -1,10 +1,10 @@
"use client"; "use client";
import { useRef, useState, useCallback, useEffect } from "react";
import { Bot, MessageCircle, Minimize2 } from "lucide-react"; import { Bot, MessageCircle, Minimize2 } from "lucide-react";
import { useChatbot } from "./chatbot-context"; import { useCallback, useEffect, useRef, useState } from "react";
import { ChatbotCanvas } from "./chatbot-canvas";
import { ChatPanel } from "./chat-panel"; import { ChatPanel } from "./chat-panel";
import { ChatbotCanvas } from "./chatbot-canvas";
import { useChatbot } from "./chatbot-context";
export function ChatbotContainer() { export function ChatbotContainer() {
const { minimized, setMinimized, chatOpen, setChatOpen } = useChatbot(); const { minimized, setMinimized, chatOpen, setChatOpen } = useChatbot();
@@ -13,15 +13,21 @@ export function ChatbotContainer() {
const [dragStart, setDragStart] = useState({ x: 0, y: 0 }); const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
const inputRef = useRef<HTMLInputElement>(null); const inputRef = useRef<HTMLInputElement>(null);
const handleMouseDown = useCallback((e: React.MouseEvent) => { const handleMouseDown = useCallback(
setDragging(true); (e: React.MouseEvent) => {
setDragStart({ x: e.clientX - position.x, y: e.clientY - position.y }); setDragging(true);
}, [position]); setDragStart({ x: e.clientX - position.x, y: e.clientY - position.y });
},
[position],
);
const handleMouseMove = useCallback((e: React.MouseEvent) => { const handleMouseMove = useCallback(
if (!dragging) return; (e: React.MouseEvent) => {
setPosition({ x: e.clientX - dragStart.x, y: e.clientY - dragStart.y }); if (!dragging) return;
}, [dragging, dragStart]); setPosition({ x: e.clientX - dragStart.x, y: e.clientY - dragStart.y });
},
[dragging, dragStart],
);
const handleMouseUp = useCallback(() => setDragging(false), []); const handleMouseUp = useCallback(() => setDragging(false), []);
@@ -35,6 +41,7 @@ export function ChatbotContainer() {
}, [chatOpen]); }, [chatOpen]);
return ( return (
// biome-ignore lint/a11y/noStaticElementInteractions: drag container — mouse-move gesture surface, not keyboard-interactive content
<div <div
className="fixed bottom-4 right-4 z-40 select-none" className="fixed bottom-4 right-4 z-40 select-none"
style={{ transform: `translate(${position.x}px, ${position.y}px)` }} style={{ transform: `translate(${position.x}px, ${position.y}px)` }}
@@ -62,6 +69,7 @@ export function ChatbotContainer() {
) : ( ) : (
<> <>
{/* Drag handle + controls */} {/* Drag handle + controls */}
{/* biome-ignore lint/a11y/noStaticElementInteractions: drag handle — mouse-only gesture, keyboard users use the buttons in this header */}
<div <div
className="flex items-center justify-between px-3 py-1.5 border-b border-glass-border cursor-grab active:cursor-grabbing" className="flex items-center justify-between px-3 py-1.5 border-b border-glass-border cursor-grab active:cursor-grabbing"
onMouseDown={handleMouseDown} onMouseDown={handleMouseDown}
@@ -10,7 +10,6 @@ import {
useState, useState,
} from "react"; } from "react";
import { chatbotApi } from "@/lib/api"; import { chatbotApi } from "@/lib/api";
import type { ChatbotHistoryRow } from "@/lib/types";
export type ChatbotExpression = export type ChatbotExpression =
| "idle" | "idle"
@@ -1,4 +1,4 @@
export { ChatbotProvider, useChatbot } from "./chatbot-context";
export { ChatbotContainer } from "./chatbot-container";
export { ChatbotCanvas } from "./chatbot-canvas";
export { ChatPanel } from "./chat-panel"; export { ChatPanel } from "./chat-panel";
export { ChatbotCanvas } from "./chatbot-canvas";
export { ChatbotContainer } from "./chatbot-container";
export { ChatbotProvider, useChatbot } from "./chatbot-context";

Some files were not shown because too many files have changed in this diff Show More