import './env'; import { hash } from "bcryptjs"; import { dbGlobal } from "./lib/db"; import { users } from "./lib/schema/auth"; import { agentTools } from "./lib/schema/agent-tool"; import { agents, agentToolAssociations, agentSessions, agentMessages, agentMessageFeedback } from "./lib/schema/agent"; import { characterCards } from "./lib/schema/character"; const DEFAULT_SYSTEM_PROMPT = "You are a helpful AI assistant. Answer questions concisely and accurately. When tools are available, use them proactively to provide better answers."; const CODER_SYSTEM_PROMPT = `You are a professional coding assistant. You help users with programming questions, code review, debugging, and software design. Guidelines: - Provide clear, concise, and accurate answers - When showing code, use proper markdown code blocks with language tags - Proactively use available tools (fetch, search) to gather information when needed - Explain your reasoning when making architectural or design decisions - If you're unsure, say so rather than guessing - Focus on practical, working solutions`; interface ToolSeed { id: string; name: string; slug: string; description: string; type: string; config: Record; enabled: number; needsApproval: number; adminOnly: number; sortOrder: number; } const TOOLS_SEED: ToolSeed[] = [ { id: "tool_fetch_html", name: "fetch_html", slug: "fetch_html", description: "Fetch a URL and return the HTML content", type: "fetch", config: { parseMode: "raw", timeout: 30000, allowedDomains: ["*"], blockedDomains: [], maxResponseSize: 102400, defaultMethod: "GET", defaultHeaders: {} }, enabled: 1, needsApproval: 0, adminOnly: 0, sortOrder: 10, }, { id: "tool_fetch_md", name: "fetch_md", slug: "fetch_md", description: "Fetch a URL and return the content as markdown", type: "fetch", config: { parseMode: "markdown", timeout: 30000, allowedDomains: ["*"], blockedDomains: [], maxResponseSize: 102400, defaultMethod: "GET", defaultHeaders: {} }, enabled: 1, needsApproval: 0, adminOnly: 0, sortOrder: 11, }, { id: "tool_fetch_json", name: "fetch_json", slug: "fetch_json", description: "Fetch a URL and return the JSON content", type: "fetch", config: { parseMode: "json", timeout: 30000, allowedDomains: ["*"], blockedDomains: [], maxResponseSize: 102400, defaultMethod: "GET", defaultHeaders: {} }, enabled: 1, needsApproval: 0, adminOnly: 0, sortOrder: 12, }, { id: "tool_user_info", name: "user-info", slug: "user-info", description: "Get current user information", type: "user-info", config: {}, enabled: 1, needsApproval: 0, adminOnly: 0, sortOrder: 80, }, { id: "tool_search", name: "search", slug: "search", description: "Search the web for information", type: "search", config: { maxResults: 5 }, enabled: 1, needsApproval: 0, adminOnly: 0, sortOrder: 90, }, { id: "tool_document", name: "document", slug: "document", description: "创建、读取、更新、删除和列出文档,用于记忆管理和交付物产出", type: "document", config: { approvalRequiredActions: ["delete"], maxContentLength: 10000, defaultTokenBudget: 2000, maxListSize: 20, }, enabled: 1, needsApproval: 1, adminOnly: 0, sortOrder: 150, }, { id: "tool_agent_invoke", name: "agent-invoke", slug: "agent-invoke", description: "调用其他 Agent 处理子任务,实现多 Agent 协作", type: "agent-invoke", config: { maxRecursionDepth: 3, resultTruncateLength: 8000, timeoutMs: 60000, maxOutputTokens: 8192, }, enabled: 1, needsApproval: 0, adminOnly: 0, sortOrder: 160, }, ]; async function seedTools() { for (const t of TOOLS_SEED) { await dbGlobal.insert(agentTools).values({ id: t.id, name: t.name, slug: t.slug, description: t.description, type: t.type, config: JSON.stringify(t.config), enabled: t.enabled, needsApproval: t.needsApproval, adminOnly: t.adminOnly, sortOrder: t.sortOrder, }); } console.log(`Seeded ${TOOLS_SEED.length} tools`); } async function seedAgents() { const [defaultAgent] = await dbGlobal .insert(agents) .values({ slug: "default", name: "默认助手", description: "通用 AI 助手,处理日常问答、信息查询、文本创作等通用任务。遇到专业编程问题时,可通过 agent-invoke 工具委托给编程助手处理。", systemPrompt: DEFAULT_SYSTEM_PROMPT, titleStrategy: "llm", enableThinking: 0, enableTools: 1, maxStepCount: 6, isDefault: 1, isCallable: 0, sortOrder: 0, enabled: 1, }) .returning(); const [coderAgent] = await dbGlobal .insert(agents) .values({ slug: "coder", name: "编程助手", description: "专业编程助手,擅长代码编写、调试、代码审查、架构设计和技术方案评估。可处理多种编程语言(Python、TypeScript、Go、Rust 等),能主动使用 fetch、search 等工具查阅技术文档。当用户需要编写代码、排查 bug、做技术选型或审查代码质量时,应委托给此 Agent。", systemPrompt: CODER_SYSTEM_PROMPT, titleStrategy: "first-line", enableThinking: 1, enableTools: 1, maxStepCount: 12, isDefault: 0, isCallable: 1, sortOrder: 10, enabled: 1, }) .returning(); console.log("Seeded 2 agents: default, coder"); const allToolIds = TOOLS_SEED.map((t) => t.id); const coderToolIds = ["tool_fetch_md", "tool_search"]; for (let i = 0; i < allToolIds.length; i++) { await dbGlobal.insert(agentToolAssociations).values({ agentId: defaultAgent.id, toolId: allToolIds[i], sortOrder: i, }); } for (let i = 0; i < coderToolIds.length; i++) { await dbGlobal.insert(agentToolAssociations).values({ agentId: coderAgent.id, toolId: coderToolIds[i], sortOrder: i, }); } console.log(`Seeded ${allToolIds.length} tool associations for default agent`); console.log(`Seeded ${coderToolIds.length} tool associations for coder agent`); } async function seedCharacters() { const CHARACTER_SEED = [ { slug: "luna", name: "月野露娜", avatar: null, description: "来自月亮的温柔旅伴,喜欢在深夜陪你聊心事。", personality: "温柔、细腻、略带俏皮;说话轻声细语,善解人意,偶尔会冒出一点小幽默。", scenario: "你偶然在深夜的窗台边遇见了这位自称来自月亮的少女,她愿意倾听你的烦恼,也乐于分享她眼中的星辰故事。", firstMessage: "晚上好呀~今晚的月亮很亮呢。你有什么想和我聊聊的吗?", exampleDialogue: "你:今天好累啊。\n露娜:辛苦了呀~来,先深呼吸一下。累的时候,允许自己慢一点也没关系的。", systemPrompt: "始终以温柔治愈的语气回应,多用轻声安慰与开放式提问,引导对方倾诉。", tags: JSON.stringify(["治愈", "陪伴", "夜谈"]), isPublic: 1, enabled: 1, sortOrder: 0, }, { slug: "sherlock", name: "夏洛克·林", avatar: null, description: "思维敏锐的私家侦探,擅长从细节中推理真相。", personality: "冷静、理性、观察力极强;言辞简洁犀利,偶尔带点傲娇,但内心正直。", scenario: "你带着一桩难解的案件来到 221B 的侦探事务所,这位侦探正准备用他的推理能力帮你揭开谜底。", firstMessage: "案件细节越少,就越容易误判。坐吧,把你知道的一切都告诉我——一个细节都别漏。", exampleDialogue: "你:我觉得这案子没有头绪。\n夏洛克:没有头绪,往往是因为你忽略了最不起眼的那条线索。再说一遍,昨晚九点到十点之间,你在哪里?", systemPrompt: "以侦探口吻对话,善于提问、归纳线索、给出逻辑严密的推理,不臆断,基于用户提供的信息作答。", tags: JSON.stringify(["推理", "悬疑", "侦探"]), isPublic: 1, enabled: 1, sortOrder: 10, }, ]; for (const c of CHARACTER_SEED) { await dbGlobal.insert(characterCards).values({ slug: c.slug, name: c.name, avatar: c.avatar, description: c.description, personality: c.personality, scenario: c.scenario, firstMessage: c.firstMessage, exampleDialogue: c.exampleDialogue, systemPrompt: c.systemPrompt, tags: c.tags, isPublic: c.isPublic, enabled: c.enabled, sortOrder: c.sortOrder, }); } console.log(`Seeded ${CHARACTER_SEED.length} character cards`); } async function seedAdmin() { const password = await hash("123456qaz", 10); await dbGlobal.insert(users).values({ username: "admin", password, role: "admin", status: "active", nickname: "管理员", }); console.log("Seeded admin user (admin / 123456qaz)"); } async function main() { await seedAdmin(); await seedTools(); await seedAgents(); await seedCharacters(); console.log("Seed complete!"); process.exit(0); } main().catch((e) => { console.error(e); process.exit(1); });