Files
GoClaw/drizzle/schema.ts

204 lines
8.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<string[]>().default([]),
allowedDomains: json("allowedDomains").$type<string[]>().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<string[]>().default([]),
metadata: json("metadata").$type<Record<string, any>>().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<string[]>().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<string[]>().default([]),
blockedPatterns: json("blockedPatterns").$type<string[]>().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<Record<string, { type: string; description: string; required?: boolean }>>(),
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;