import { int, mysqlEnum, mysqlTable, text, timestamp, varchar, decimal, json, boolean, index } from "drizzle-orm/mysql-core"; /** * Core user table backing auth flow. * Extend this file with additional tables as your product grows. * Columns use camelCase to match both database fields and generated types. */ export const users = mysqlTable("users", { /** * Surrogate primary key. Auto-incremented numeric value managed by the database. * Use this for relations between tables. */ id: int("id").autoincrement().primaryKey(), /** Manus OAuth identifier (openId) returned from the OAuth callback. Unique per user. */ openId: varchar("openId", { length: 64 }).notNull().unique(), name: text("name"), email: varchar("email", { length: 320 }), loginMethod: varchar("loginMethod", { length: 64 }), role: mysqlEnum("role", ["user", "admin"]).default("user").notNull(), createdAt: timestamp("createdAt").defaultNow().notNull(), updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(), lastSignedIn: timestamp("lastSignedIn").defaultNow().notNull(), }); export type User = typeof users.$inferSelect; export type InsertUser = typeof users.$inferInsert; /** * Agents — конфигурация и управление AI-агентами */ export const agents = mysqlTable("agents", { id: int("id").autoincrement().primaryKey(), userId: int("userId").notNull(), // Владелец агента name: varchar("name", { length: 255 }).notNull(), description: text("description"), role: varchar("role", { length: 100 }).notNull(), // "developer", "researcher", "executor" // Модель LLM model: varchar("model", { length: 100 }).notNull(), provider: varchar("provider", { length: 50 }).notNull(), // Параметры LLM temperature: decimal("temperature", { precision: 3, scale: 2 }).default("0.7"), maxTokens: int("maxTokens").default(2048), topP: decimal("topP", { precision: 3, scale: 2 }).default("1.0"), frequencyPenalty: decimal("frequencyPenalty", { precision: 3, scale: 2 }).default("0.0"), presencePenalty: decimal("presencePenalty", { precision: 3, scale: 2 }).default("0.0"), // System Prompt systemPrompt: text("systemPrompt"), // Доступы и разрешения allowedTools: json("allowedTools").$type().default([]), allowedDomains: json("allowedDomains").$type().default([]), maxRequestsPerHour: int("maxRequestsPerHour").default(100), // Статус isActive: boolean("isActive").default(true), isPublic: boolean("isPublic").default(false), isSystem: boolean("isSystem").default(false), // Системный агент (нельзя удалить) isOrchestrator: boolean("isOrchestrator").default(false), // Главный оркестратор чата // Метаданные tags: json("tags").$type().default([]), metadata: json("metadata").$type>().default({}), createdAt: timestamp("createdAt").defaultNow().notNull(), updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(), }, (table) => ({ userIdIdx: index("agents_userId_idx").on(table.userId), modelIdx: index("agents_model_idx").on(table.model), })); export type Agent = typeof agents.$inferSelect; export type InsertAgent = typeof agents.$inferInsert; /** * Agent Metrics — метрики производительности агентов */ export const agentMetrics = mysqlTable("agentMetrics", { id: int("id").autoincrement().primaryKey(), agentId: int("agentId").notNull(), // Информация о запросе requestId: varchar("requestId", { length: 64 }).notNull().unique(), userMessage: text("userMessage"), agentResponse: text("agentResponse"), // Токены inputTokens: int("inputTokens").default(0), outputTokens: int("outputTokens").default(0), totalTokens: int("totalTokens").default(0), // Время обработки processingTimeMs: int("processingTimeMs").notNull(), // Статус status: mysqlEnum("status", ["success", "error", "timeout", "rate_limited"]).notNull(), errorMessage: text("errorMessage"), // Инструменты toolsCalled: json("toolsCalled").$type().default([]), // Модель model: varchar("model", { length: 100 }), temperature: decimal("temperature", { precision: 3, scale: 2 }), createdAt: timestamp("createdAt").defaultNow().notNull(), }, (table) => ({ agentIdIdx: index("agentMetrics_agentId_idx").on(table.agentId), createdAtIdx: index("agentMetrics_createdAt_idx").on(table.createdAt), })); export type AgentMetric = typeof agentMetrics.$inferSelect; export type InsertAgentMetric = typeof agentMetrics.$inferInsert; /** * Agent History — полная история запросов */ export const agentHistory = mysqlTable("agentHistory", { id: int("id").autoincrement().primaryKey(), agentId: int("agentId").notNull(), userMessage: text("userMessage").notNull(), agentResponse: text("agentResponse"), conversationId: varchar("conversationId", { length: 64 }), messageIndex: int("messageIndex"), status: mysqlEnum("status", ["pending", "success", "error"]).default("pending"), createdAt: timestamp("createdAt").defaultNow().notNull(), }, (table) => ({ agentIdIdx: index("agentHistory_agentId_idx").on(table.agentId), })); export type AgentHistory = typeof agentHistory.$inferSelect; export type InsertAgentHistory = typeof agentHistory.$inferInsert; /** * Agent Access Control — управление доступами */ export const agentAccessControl = mysqlTable("agentAccessControl", { id: int("id").autoincrement().primaryKey(), agentId: int("agentId").notNull(), tool: varchar("tool", { length: 50 }).notNull(), isAllowed: boolean("isAllowed").default(true), maxExecutionsPerHour: int("maxExecutionsPerHour").default(100), timeoutSeconds: int("timeoutSeconds").default(30), allowedPatterns: json("allowedPatterns").$type().default([]), blockedPatterns: json("blockedPatterns").$type().default([]), createdAt: timestamp("createdAt").defaultNow().notNull(), updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(), }, (table) => ({ agentIdToolIdx: index("agentAccessControl_agentId_tool_idx").on(table.agentId, table.tool), })); export type AgentAccessControl = typeof agentAccessControl.$inferSelect; export type InsertAgentAccessControl = typeof agentAccessControl.$inferInsert; /** * Tool Definitions — пользовательские инструменты, созданные Tool Builder Agent */ export const toolDefinitions = mysqlTable("toolDefinitions", { id: int("id").autoincrement().primaryKey(), toolId: varchar("toolId", { length: 100 }).notNull().unique(), name: varchar("name", { length: 255 }).notNull(), description: text("description").notNull(), category: varchar("category", { length: 50 }).notNull().default("custom"), dangerous: boolean("dangerous").default(false), parameters: json("parameters").$type>(), implementation: text("implementation").notNull(), // JS код функции isActive: boolean("isActive").default(true), createdBy: int("createdBy"), // agentId или null createdAt: timestamp("createdAt").defaultNow().notNull(), updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(), }); export type ToolDefinition = typeof toolDefinitions.$inferSelect; export type InsertToolDefinition = typeof toolDefinitions.$inferInsert; /** * Browser Sessions — активные сессии браузера для Browser Agent */ export const browserSessions = mysqlTable("browserSessions", { id: int("id").autoincrement().primaryKey(), sessionId: varchar("sessionId", { length: 64 }).notNull().unique(), agentId: int("agentId").notNull(), currentUrl: text("currentUrl"), title: text("title"), status: mysqlEnum("status", ["active", "idle", "closed", "error"]).default("idle"), screenshotUrl: text("screenshotUrl"), // S3 URL последнего скриншота lastActionAt: timestamp("lastActionAt").defaultNow(), createdAt: timestamp("createdAt").defaultNow().notNull(), closedAt: timestamp("closedAt"), }); export type BrowserSession = typeof browserSessions.$inferSelect; export type InsertBrowserSession = typeof browserSessions.$inferInsert;