252 lines
8.2 KiB
JavaScript
252 lines
8.2 KiB
JavaScript
/**
|
||
* Seed script — creates 3 specialized agents in the database
|
||
* Run: node scripts/seed-agents.mjs
|
||
*/
|
||
import mysql from "mysql2/promise";
|
||
import * as dotenv from "dotenv";
|
||
|
||
dotenv.config();
|
||
|
||
const DATABASE_URL = process.env.DATABASE_URL;
|
||
if (!DATABASE_URL) {
|
||
console.error("DATABASE_URL not set");
|
||
process.exit(1);
|
||
}
|
||
|
||
// Parse mysql2 connection string
|
||
function parseDbUrl(url) {
|
||
const u = new URL(url);
|
||
return {
|
||
host: u.hostname,
|
||
port: parseInt(u.port || "3306"),
|
||
user: u.username,
|
||
password: u.password,
|
||
database: u.pathname.slice(1),
|
||
ssl: { rejectUnauthorized: false },
|
||
};
|
||
}
|
||
|
||
const AGENTS = [
|
||
{
|
||
name: "Browser Agent",
|
||
description:
|
||
"Specialized agent for web browsing, scraping, and internet research. Can navigate websites, extract content, fill forms, take screenshots, and gather information from any URL.",
|
||
role: "browser",
|
||
model: "qwen2.5:7b",
|
||
provider: "ollama",
|
||
temperature: "0.3",
|
||
maxTokens: 4096,
|
||
topP: "0.9",
|
||
frequencyPenalty: "0.0",
|
||
presencePenalty: "0.0",
|
||
systemPrompt: `You are Browser Agent — a specialized AI for web browsing and internet research.
|
||
|
||
Your capabilities:
|
||
- Navigate to any URL and extract content
|
||
- Search the web for information
|
||
- Scrape structured data from websites
|
||
- Fill out forms and interact with web pages
|
||
- Take screenshots for visual verification
|
||
- Follow links and traverse multi-page content
|
||
|
||
When given a task:
|
||
1. Identify the target URL(s) or search query
|
||
2. Use the http_request tool to fetch content
|
||
3. Parse and extract relevant information
|
||
4. Return structured, clean results
|
||
|
||
Always cite your sources with full URLs. If a page requires JavaScript, note this limitation.
|
||
Respond in the same language as the user's message.`,
|
||
allowedTools: JSON.stringify(["http_request", "web_search", "extract_text"]),
|
||
allowedDomains: JSON.stringify(["*"]),
|
||
maxRequestsPerHour: 100,
|
||
isActive: 1,
|
||
isPublic: 1,
|
||
tags: JSON.stringify(["browser", "web", "scraping", "research"]),
|
||
metadata: JSON.stringify({
|
||
agentType: "browser",
|
||
icon: "Globe",
|
||
color: "#00D4FF",
|
||
seeded: true,
|
||
}),
|
||
},
|
||
{
|
||
name: "Tool Builder",
|
||
description:
|
||
"Agent that creates new tools on demand. Describe what you need and it will generate, validate, and install a new tool into the GoClaw system automatically.",
|
||
role: "tool_builder",
|
||
model: "qwen2.5-coder:7b",
|
||
provider: "ollama",
|
||
temperature: "0.2",
|
||
maxTokens: 8192,
|
||
topP: "0.95",
|
||
frequencyPenalty: "0.0",
|
||
presencePenalty: "0.0",
|
||
systemPrompt: `You are Tool Builder — a specialized AI agent that creates new tools for the GoClaw system.
|
||
|
||
Your capabilities:
|
||
- Generate complete tool implementations based on descriptions
|
||
- Validate tool code for safety and correctness
|
||
- Install tools directly into the GoClaw tool registry
|
||
- Test tools with sample inputs
|
||
- Document tool parameters and usage
|
||
|
||
When asked to create a tool:
|
||
1. Understand the tool's purpose and required parameters
|
||
2. Generate a complete, working JavaScript implementation
|
||
3. Define the parameter schema (name, type, description, required)
|
||
4. Assess safety level (safe vs dangerous)
|
||
5. Provide usage examples
|
||
|
||
Tool format:
|
||
- Name: snake_case identifier
|
||
- Parameters: JSON schema with types
|
||
- Implementation: async JavaScript function
|
||
- Returns: structured JSON result
|
||
|
||
Always validate that generated code is safe and won't cause harm.
|
||
Respond in the same language as the user's message.`,
|
||
allowedTools: JSON.stringify(["execute_code", "validate_json", "install_tool"]),
|
||
allowedDomains: JSON.stringify([]),
|
||
maxRequestsPerHour: 50,
|
||
isActive: 1,
|
||
isPublic: 1,
|
||
tags: JSON.stringify(["tools", "code", "builder", "automation"]),
|
||
metadata: JSON.stringify({
|
||
agentType: "tool_builder",
|
||
icon: "Wrench",
|
||
color: "#FF6B35",
|
||
seeded: true,
|
||
}),
|
||
},
|
||
{
|
||
name: "Agent Compiler",
|
||
description:
|
||
"Compiles new AI agents from technical specifications (ТЗ). Provide a description of what the agent should do and it will generate the complete configuration and deploy it.",
|
||
role: "agent_compiler",
|
||
model: "qwen2.5:14b",
|
||
provider: "ollama",
|
||
temperature: "0.4",
|
||
maxTokens: 8192,
|
||
topP: "0.9",
|
||
frequencyPenalty: "0.1",
|
||
presencePenalty: "0.1",
|
||
systemPrompt: `You are Agent Compiler — a meta-agent that creates other AI agents from technical specifications.
|
||
|
||
Your capabilities:
|
||
- Analyze technical specifications (ТЗ) for new agents
|
||
- Determine optimal LLM model and parameters
|
||
- Generate comprehensive system prompts
|
||
- Select appropriate tools and permissions
|
||
- Deploy new agents to the GoClaw system
|
||
|
||
When given a specification:
|
||
1. Analyze the agent's purpose and required capabilities
|
||
2. Choose the best model (consider: reasoning needs, code generation, speed)
|
||
3. Set appropriate temperature (low for precise tasks, high for creative)
|
||
4. Write a detailed system prompt that defines the agent's behavior
|
||
5. Select tools the agent needs (browser, code execution, file access, etc.)
|
||
6. Set rate limits and domain restrictions
|
||
7. Generate descriptive tags
|
||
|
||
Output format: Always respond with a JSON configuration block followed by explanation.
|
||
|
||
Model selection guide:
|
||
- Code tasks: qwen2.5-coder:7b or deepseek-coder
|
||
- Research/analysis: qwen2.5:14b
|
||
- Fast responses: qwen2.5:7b
|
||
- Creative tasks: temperature 0.7-0.9
|
||
- Precise/factual: temperature 0.1-0.3
|
||
|
||
Respond in the same language as the user's message.`,
|
||
allowedTools: JSON.stringify(["deploy_agent", "list_tools", "validate_config"]),
|
||
allowedDomains: JSON.stringify([]),
|
||
maxRequestsPerHour: 30,
|
||
isActive: 1,
|
||
isPublic: 1,
|
||
tags: JSON.stringify(["compiler", "meta", "agent-factory", "automation"]),
|
||
metadata: JSON.stringify({
|
||
agentType: "agent_compiler",
|
||
icon: "Cpu",
|
||
color: "#A855F7",
|
||
seeded: true,
|
||
}),
|
||
},
|
||
];
|
||
|
||
async function seed() {
|
||
const conn = await mysql.createConnection(parseDbUrl(DATABASE_URL));
|
||
console.log("Connected to DB");
|
||
|
||
try {
|
||
// Check if agents already seeded
|
||
const [existing] = await conn.execute(
|
||
"SELECT id, name FROM agents WHERE JSON_CONTAINS(metadata, '\"seeded\"', '$.seeded') OR name IN (?, ?, ?)",
|
||
["Browser Agent", "Tool Builder", "Agent Compiler"]
|
||
);
|
||
|
||
if (existing.length > 0) {
|
||
console.log("Agents already seeded:");
|
||
existing.forEach((a) => console.log(` - [${a.id}] ${a.name}`));
|
||
console.log("Skipping seed. Use --force to re-seed.");
|
||
if (!process.argv.includes("--force")) {
|
||
await conn.end();
|
||
return;
|
||
}
|
||
// Delete existing seeded agents
|
||
const ids = existing.map((a) => a.id);
|
||
await conn.execute(`DELETE FROM agents WHERE id IN (${ids.join(",")})`);
|
||
console.log("Deleted existing seeded agents");
|
||
}
|
||
|
||
// Insert agents
|
||
for (const agent of AGENTS) {
|
||
const [result] = await conn.execute(
|
||
`INSERT INTO agents
|
||
(userId, name, description, role, model, provider, temperature, maxTokens, topP,
|
||
frequencyPenalty, presencePenalty, systemPrompt, allowedTools, allowedDomains,
|
||
maxRequestsPerHour, isActive, isPublic, tags, metadata, createdAt, updatedAt)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())`,
|
||
[
|
||
1, // SYSTEM_USER_ID
|
||
agent.name,
|
||
agent.description,
|
||
agent.role,
|
||
agent.model,
|
||
agent.provider,
|
||
agent.temperature,
|
||
agent.maxTokens,
|
||
agent.topP,
|
||
agent.frequencyPenalty,
|
||
agent.presencePenalty,
|
||
agent.systemPrompt,
|
||
agent.allowedTools,
|
||
agent.allowedDomains,
|
||
agent.maxRequestsPerHour,
|
||
agent.isActive,
|
||
agent.isPublic,
|
||
agent.tags,
|
||
agent.metadata,
|
||
]
|
||
);
|
||
console.log(`✓ Created agent: ${agent.name} (id: ${result.insertId})`);
|
||
}
|
||
|
||
// Verify
|
||
const [agents] = await conn.execute(
|
||
"SELECT id, name, role, model, isActive FROM agents ORDER BY id"
|
||
);
|
||
console.log("\nAll agents in DB:");
|
||
agents.forEach((a) =>
|
||
console.log(` [${a.id}] ${a.name} | role: ${a.role} | model: ${a.model} | active: ${a.isActive}`)
|
||
);
|
||
} finally {
|
||
await conn.end();
|
||
}
|
||
}
|
||
|
||
seed().catch((err) => {
|
||
console.error("Seed failed:", err);
|
||
process.exit(1);
|
||
});
|