You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
292 lines
9.3 KiB
292 lines
9.3 KiB
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<string, unknown>;
|
|
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);
|
|
});
|
|
|