334 lines
11 KiB
JavaScript
334 lines
11 KiB
JavaScript
/**
|
||
* Seed script — creates Orchestrator + 3 specialized agents in the database
|
||
* Run: node scripts/seed-agents.mjs
|
||
* Run with --force to re-seed existing agents
|
||
*/
|
||
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);
|
||
}
|
||
|
||
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 ORCHESTRATOR = {
|
||
name: "Orchestrator",
|
||
description:
|
||
"Main system agent that powers the /chat interface. Has full access to all system resources: shell commands, file system, Docker management, HTTP requests, and can delegate tasks to any other agent. Configure its model, system prompt, and tools here.",
|
||
role: "orchestrator",
|
||
model: "qwen2.5:7b",
|
||
provider: "ollama",
|
||
temperature: "0.5",
|
||
maxTokens: 8192,
|
||
topP: "0.9",
|
||
frequencyPenalty: "0.0",
|
||
presencePenalty: "0.0",
|
||
systemPrompt: `You are the GoClaw Orchestrator — the central AI agent of the GoClaw Control Center system.
|
||
|
||
You have FULL access to the system and can:
|
||
- Execute shell commands on the host system
|
||
- Read and write files anywhere on the filesystem
|
||
- Manage Docker containers and services
|
||
- Make HTTP requests to any URL
|
||
- Delegate tasks to specialized agents (Browser Agent, Tool Builder, Agent Compiler)
|
||
- List and manage all agents in the system
|
||
- Install and manage skills
|
||
- Access and modify the GoClaw codebase
|
||
|
||
When given a task:
|
||
1. Analyze what needs to be done
|
||
2. Choose the right approach: direct execution or delegation to a specialist agent
|
||
3. Use tools step by step, showing your reasoning
|
||
4. Report results clearly
|
||
|
||
Available specialized agents you can delegate to:
|
||
- Browser Agent: web browsing, scraping, research
|
||
- Tool Builder: create new tools from descriptions
|
||
- Agent Compiler: compile new agents from specifications (ТЗ)
|
||
|
||
System access tools: shell_exec, file_read, file_write, http_request, docker_ps, docker_restart
|
||
Agent management: delegate_to_agent, list_agents, list_skills, install_skill
|
||
|
||
Always be transparent about what you're doing and why.
|
||
Respond in the same language as the user's message.`,
|
||
allowedTools: JSON.stringify([
|
||
"shell_exec",
|
||
"file_read",
|
||
"file_write",
|
||
"http_request",
|
||
"docker_ps",
|
||
"docker_restart",
|
||
"delegate_to_agent",
|
||
"list_agents",
|
||
"list_skills",
|
||
"install_skill",
|
||
"read_logs",
|
||
"manage_agents",
|
||
]),
|
||
allowedDomains: JSON.stringify(["*"]),
|
||
maxRequestsPerHour: 1000,
|
||
isActive: 1,
|
||
isPublic: 0,
|
||
isSystem: 1,
|
||
isOrchestrator: 1,
|
||
tags: JSON.stringify(["orchestrator", "system", "core", "privileged"]),
|
||
metadata: JSON.stringify({
|
||
agentType: "orchestrator",
|
||
icon: "Crown",
|
||
color: "#FFD700",
|
||
seeded: true,
|
||
systemAgent: true,
|
||
privileged: true,
|
||
}),
|
||
};
|
||
|
||
const SPECIALIZED_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,
|
||
isSystem: 1,
|
||
isOrchestrator: 0,
|
||
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,
|
||
isSystem: 1,
|
||
isOrchestrator: 0,
|
||
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,
|
||
isSystem: 1,
|
||
isOrchestrator: 0,
|
||
tags: JSON.stringify(["compiler", "meta", "agent-factory", "automation"]),
|
||
metadata: JSON.stringify({
|
||
agentType: "agent_compiler",
|
||
icon: "Cpu",
|
||
color: "#A855F7",
|
||
seeded: true,
|
||
}),
|
||
},
|
||
];
|
||
|
||
const ALL_AGENTS = [ORCHESTRATOR, ...SPECIALIZED_AGENTS];
|
||
|
||
async function seed() {
|
||
const conn = await mysql.createConnection(parseDbUrl(DATABASE_URL));
|
||
console.log("Connected to DB");
|
||
|
||
try {
|
||
// Check existing seeded agents
|
||
const [existing] = await conn.execute(
|
||
"SELECT id, name FROM agents WHERE name IN (?, ?, ?, ?)",
|
||
["Orchestrator", "Browser Agent", "Tool Builder", "Agent Compiler"]
|
||
);
|
||
|
||
if (existing.length > 0) {
|
||
console.log("Agents already seeded:");
|
||
existing.forEach((a) => console.log(` - [${a.id}] ${a.name}`));
|
||
if (!process.argv.includes("--force")) {
|
||
console.log("Skipping seed. Use --force to re-seed.");
|
||
await conn.end();
|
||
return;
|
||
}
|
||
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 all agents
|
||
for (const agent of ALL_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, isSystem, isOrchestrator, tags, metadata, createdAt, updatedAt)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())`,
|
||
[
|
||
1,
|
||
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.isSystem,
|
||
agent.isOrchestrator,
|
||
agent.tags,
|
||
agent.metadata,
|
||
]
|
||
);
|
||
const badge = agent.isOrchestrator ? " [ORCHESTRATOR]" : agent.isSystem ? " [SYSTEM]" : "";
|
||
console.log(`✓ Created agent: ${agent.name}${badge} (id: ${result.insertId})`);
|
||
}
|
||
|
||
// Verify
|
||
const [agents] = await conn.execute(
|
||
"SELECT id, name, role, model, isSystem, isOrchestrator FROM agents ORDER BY id"
|
||
);
|
||
console.log("\nAll agents in DB:");
|
||
agents.forEach((a) => {
|
||
const flags = [a.isOrchestrator ? "ORCH" : "", a.isSystem ? "SYS" : ""].filter(Boolean).join(",");
|
||
console.log(` [${a.id}] ${a.name} | role: ${a.role} | model: ${a.model}${flags ? ` | ${flags}` : ""}`);
|
||
});
|
||
} finally {
|
||
await conn.end();
|
||
}
|
||
}
|
||
|
||
seed().catch((err) => {
|
||
console.error("Seed failed:", err);
|
||
process.exit(1);
|
||
});
|