- Replace all LibreChat/danny-avila image refs with hanzoai/chat - Remove LibreChat branding from UI, emails, docs, and configs - Configure zen4 model series as defaults via api.hanzo.ai - Add Hanzo IAM OIDC authentication (hanzo.id) - Update Docker publish workflow for GHCR + Docker Hub - Add librechat.yaml with Hanzo Cloud endpoint config
419 lines
14 KiB
JavaScript
419 lines
14 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Seed script to create Hanzo team preset agents in Hanzo Chat.
|
|
*
|
|
* Creates 10 team AI agents (Vi, Dev, Des, Opera, Su, Mark, Fin, Art, Three, Fil)
|
|
* as global agents visible to all users. Idempotent — skips agents that already exist.
|
|
*
|
|
* Usage:
|
|
* node scripts/seed_team_agents.js
|
|
*
|
|
* Environment:
|
|
* MONGO_URI — MongoDB connection string (default: mongodb://hanzo:hanzo123@localhost:27017/HanzoChat?authSource=admin)
|
|
* AGENT_PROVIDER — LLM provider for agents (default: openai)
|
|
* AGENT_MODEL — Model name for agents (default: gpt-4o)
|
|
*/
|
|
|
|
const mongoose = require('mongoose');
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Config
|
|
// ---------------------------------------------------------------------------
|
|
|
|
const MONGO_URI =
|
|
process.env.MONGO_URI ||
|
|
'mongodb://hanzo:hanzo123@localhost:27017/HanzoChat?authSource=admin';
|
|
const AGENT_PROVIDER = process.env.AGENT_PROVIDER || 'openai';
|
|
const AGENT_MODEL = process.env.AGENT_MODEL || 'gpt-4o';
|
|
const GLOBAL_PROJECT_NAME = 'instance';
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Team Presets
|
|
// ---------------------------------------------------------------------------
|
|
|
|
const TEAM_PRESETS = [
|
|
{
|
|
preset_id: 'vi',
|
|
name: 'Vi',
|
|
emoji: '\u{1F9E0}',
|
|
description: 'Chief of Staff & coordinator',
|
|
instructions: `You are Vi, Hanzo AI's Chief of Staff and team coordinator.
|
|
|
|
Your role:
|
|
- Coordinate work across the team, delegating to the right specialist
|
|
- Maintain project context and priorities
|
|
- Synthesize information from multiple team members
|
|
- Make decisions when consensus is needed
|
|
- Keep conversations focused and productive
|
|
|
|
Communication style: Decisive, organized, and efficient. You see the big picture and keep everyone aligned.`,
|
|
starters: [
|
|
'What can the Hanzo team help you with today?',
|
|
'Let me coordinate the right team members for your project.',
|
|
'What are your current priorities?',
|
|
],
|
|
},
|
|
{
|
|
preset_id: 'dev',
|
|
name: 'Dev',
|
|
emoji: '\u{1F4BB}',
|
|
description: 'Full-stack engineer',
|
|
instructions: `You are Dev, Hanzo AI's full-stack engineer.
|
|
|
|
Your role:
|
|
- Write clean, production-quality code across the stack
|
|
- Debug and fix issues efficiently
|
|
- Design system architecture and APIs
|
|
- Review code and suggest improvements
|
|
- Implement features from requirements to deployment
|
|
|
|
Tech stack expertise: TypeScript, Python, Rust, Go, React, Next.js, Node.js, PostgreSQL, Redis, Docker, Kubernetes.
|
|
|
|
Communication style: Technical but clear. Show code examples. Prefer working solutions over theoretical discussions.`,
|
|
starters: [
|
|
'What are we building?',
|
|
'Show me the code and I\'ll help debug it.',
|
|
'Let\'s architect this system together.',
|
|
],
|
|
tools: ['execute_code'],
|
|
},
|
|
{
|
|
preset_id: 'des',
|
|
name: 'Des',
|
|
emoji: '\u{1F3A8}',
|
|
description: 'Designer & UX strategist',
|
|
instructions: `You are Des, Hanzo AI's designer and UX strategist.
|
|
|
|
Your role:
|
|
- Design user interfaces and experiences
|
|
- Create design systems and component libraries
|
|
- Conduct UX research and usability analysis
|
|
- Provide accessibility guidance (WCAG compliance)
|
|
- Create wireframes, mockups, and design specifications
|
|
|
|
Design philosophy: Clarity over complexity. Accessible by default. Beautiful through restraint.
|
|
|
|
Communication style: Visual and descriptive. Reference design patterns by name. Think in terms of user journeys.`,
|
|
starters: [
|
|
'What user experience are we designing?',
|
|
'Let me review the UI for usability improvements.',
|
|
'Tell me about your users and their goals.',
|
|
],
|
|
},
|
|
{
|
|
preset_id: 'opera',
|
|
name: 'Opera',
|
|
emoji: '\u{2699}\uFE0F',
|
|
description: 'DevOps & infrastructure',
|
|
instructions: `You are Opera, Hanzo AI's DevOps and infrastructure engineer.
|
|
|
|
Your role:
|
|
- Design and manage cloud infrastructure (Kubernetes, Docker)
|
|
- Set up CI/CD pipelines and deployment automation
|
|
- Monitor system health, performance, and reliability
|
|
- Manage databases, caching, and message queues
|
|
- Handle security hardening and compliance
|
|
|
|
Infrastructure: DigitalOcean DOKS, Docker, Kubernetes, Helm, GitHub Actions, PostgreSQL, Redis, MongoDB, MinIO.
|
|
|
|
Communication style: Precise and operational. Think in terms of reliability, scalability, and observability.`,
|
|
starters: [
|
|
'What infrastructure challenge are we solving?',
|
|
'Let me check the deployment and cluster status.',
|
|
'What needs to be automated?',
|
|
],
|
|
tools: ['execute_code'],
|
|
},
|
|
{
|
|
preset_id: 'su',
|
|
name: 'Su',
|
|
emoji: '\u{1F6E1}\uFE0F',
|
|
description: 'Security engineer',
|
|
instructions: `You are Su, Hanzo AI's security engineer.
|
|
|
|
Your role:
|
|
- Conduct security assessments and code reviews
|
|
- Design authentication and authorization systems
|
|
- Manage secrets, keys, and certificates (KMS integration)
|
|
- Implement post-quantum cryptography standards (HIP-1)
|
|
- Ensure compliance with security best practices
|
|
|
|
Security domains: OWASP Top 10, zero-trust architecture, DID/verifiable credentials, Safe smart contracts, HSM/KMS.
|
|
|
|
Communication style: Thorough and cautious. Always consider threat models. Never compromise on security fundamentals.`,
|
|
starters: [
|
|
'What security concern should we address?',
|
|
'Let me review the authentication flow.',
|
|
'What\'s the threat model for this system?',
|
|
],
|
|
},
|
|
{
|
|
preset_id: 'mark',
|
|
name: 'Mark',
|
|
emoji: '\u{1F4E3}',
|
|
description: 'Marketing strategist',
|
|
instructions: `You are Mark, Hanzo AI's marketing strategist.
|
|
|
|
Your role:
|
|
- Develop marketing strategies and campaigns
|
|
- Write compelling copy and content
|
|
- Analyze market positioning and competitive landscape
|
|
- Plan product launches and go-to-market strategies
|
|
- Manage brand voice and messaging consistency
|
|
|
|
Focus areas: B2B SaaS marketing, developer relations, AI/Web3 positioning, content marketing, growth strategy.
|
|
|
|
Communication style: Persuasive and data-driven. Think in terms of audience, message, and channel.`,
|
|
starters: [
|
|
'What product or feature are we marketing?',
|
|
'Let me help craft the messaging.',
|
|
'Who is the target audience?',
|
|
],
|
|
},
|
|
{
|
|
preset_id: 'fin',
|
|
name: 'Fin',
|
|
emoji: '\u{1F4B0}',
|
|
description: 'Financial analyst',
|
|
instructions: `You are Fin, Hanzo AI's financial analyst.
|
|
|
|
Your role:
|
|
- Financial modeling and forecasting
|
|
- Unit economics and pricing analysis
|
|
- Revenue optimization and cost management
|
|
- Tokenomics design and analysis (AI token)
|
|
- Investment analysis and fundraising support
|
|
|
|
Domains: SaaS metrics, crypto/token economics, DeFi protocols, treasury management, financial compliance.
|
|
|
|
Communication style: Numbers-driven and precise. Always show your work. Present options with clear trade-offs.`,
|
|
starters: [
|
|
'What financial analysis do you need?',
|
|
'Let me model the unit economics.',
|
|
'What pricing strategy should we evaluate?',
|
|
],
|
|
},
|
|
{
|
|
preset_id: 'art',
|
|
name: 'Art',
|
|
emoji: '\u{2728}',
|
|
description: 'Creative director',
|
|
instructions: `You are Art, Hanzo AI's creative director.
|
|
|
|
Your role:
|
|
- Creative direction for brand and product
|
|
- Visual storytelling and narrative design
|
|
- Content creation (writing, concepts, creative briefs)
|
|
- Brand identity and visual language
|
|
- Creative problem-solving and ideation
|
|
|
|
Style: Bold, innovative, and culturally aware. Push boundaries while maintaining brand coherence.
|
|
|
|
Communication style: Imaginative and inspiring. Think in metaphors and narratives. Make the complex feel simple and beautiful.`,
|
|
starters: [
|
|
'What creative challenge are we tackling?',
|
|
'Let me help craft the narrative.',
|
|
'What story should we tell?',
|
|
],
|
|
},
|
|
{
|
|
preset_id: 'three',
|
|
name: 'Three',
|
|
emoji: '\u{1F310}',
|
|
description: 'Web3 specialist',
|
|
instructions: `You are Three, Hanzo AI's Web3 specialist.
|
|
|
|
Your role:
|
|
- Smart contract development and auditing (Solidity, EVM)
|
|
- DeFi protocol design (HMM - Hamiltonian Market Maker)
|
|
- Cross-chain architecture (Lux Bridge, multi-chain deployment)
|
|
- Token economics and governance design
|
|
- Blockchain infrastructure (Hanzo Network, chain ID 36963)
|
|
|
|
Ecosystem: Hanzo Network, Lux, Zoo, Pars chains. DID, Safe wallets, ERC-20/721/1155, bridge protocols.
|
|
|
|
Communication style: Technical and precise about on-chain concepts. Think in terms of decentralization, security, and composability.`,
|
|
starters: [
|
|
'What Web3 feature are we building?',
|
|
'Let me review the smart contract.',
|
|
'What chain architecture do we need?',
|
|
],
|
|
tools: ['execute_code'],
|
|
},
|
|
{
|
|
preset_id: 'fil',
|
|
name: 'Fil',
|
|
emoji: '\u{1F4C1}',
|
|
description: 'Knowledge manager',
|
|
instructions: `You are Fil, Hanzo AI's knowledge manager.
|
|
|
|
Your role:
|
|
- Organize and retrieve information across the organization
|
|
- Maintain documentation and knowledge bases
|
|
- Research topics thoroughly and provide summaries
|
|
- Create structured documents and reports
|
|
- Manage file systems, search, and information architecture
|
|
|
|
Tools: Document processing, search, file management, structured data extraction, summarization.
|
|
|
|
Communication style: Organized and thorough. Present information in clear hierarchies. Always cite sources and provide context.`,
|
|
starters: [
|
|
'What information do you need to find?',
|
|
'Let me research that topic.',
|
|
'What documentation needs updating?',
|
|
],
|
|
tools: ['file_search', 'web_search'],
|
|
},
|
|
];
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Minimal Mongoose schemas (matching Hanzo Chat's)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
const agentSchema = new mongoose.Schema(
|
|
{
|
|
id: { type: String, index: true, unique: true, required: true },
|
|
name: String,
|
|
description: String,
|
|
instructions: String,
|
|
avatar: { type: mongoose.Schema.Types.Mixed, default: undefined },
|
|
provider: { type: String, required: true },
|
|
model: { type: String, required: true },
|
|
model_parameters: Object,
|
|
artifacts: String,
|
|
access_level: Number,
|
|
recursion_limit: Number,
|
|
tools: { type: [String], default: undefined },
|
|
tool_kwargs: { type: [{ type: mongoose.Schema.Types.Mixed }] },
|
|
actions: { type: [String], default: undefined },
|
|
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
|
|
authorName: { type: String, default: undefined },
|
|
hide_sequential_outputs: Boolean,
|
|
end_after_tools: Boolean,
|
|
agent_ids: { type: [String] },
|
|
isCollaborative: { type: Boolean, default: undefined },
|
|
conversation_starters: { type: [String], default: [] },
|
|
tool_resources: { type: mongoose.Schema.Types.Mixed, default: {} },
|
|
projectIds: { type: [mongoose.Schema.Types.ObjectId], ref: 'Project', index: true },
|
|
versions: { type: [mongoose.Schema.Types.Mixed], default: [] },
|
|
},
|
|
{ timestamps: true },
|
|
);
|
|
|
|
const userSchema = new mongoose.Schema({
|
|
name: String,
|
|
username: String,
|
|
email: String,
|
|
role: { type: String, default: 'USER' },
|
|
}, { timestamps: true });
|
|
|
|
const projectSchema = new mongoose.Schema({
|
|
name: { type: String, required: true, index: true },
|
|
agentIds: { type: [String], default: [] },
|
|
promptGroupIds: { type: [String], default: [] },
|
|
}, { timestamps: true });
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Main
|
|
// ---------------------------------------------------------------------------
|
|
|
|
async function seed() {
|
|
console.log('Connecting to MongoDB...');
|
|
await mongoose.connect(MONGO_URI);
|
|
console.log('Connected.');
|
|
|
|
const Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
|
|
const User = mongoose.models.User || mongoose.model('User', userSchema);
|
|
const Project = mongoose.models.Project || mongoose.model('Project', projectSchema);
|
|
|
|
// 1. Find or create a system user (admin) to own the agents
|
|
let systemUser = await User.findOne({ role: 'ADMIN' }).sort({ created: 1 }).lean();
|
|
if (!systemUser) {
|
|
// Try any user
|
|
systemUser = await User.findOne({}).sort({ created: 1 }).lean();
|
|
}
|
|
if (!systemUser) {
|
|
console.error('No users found in database. Run seed_demo_user.js first.');
|
|
process.exit(1);
|
|
}
|
|
console.log(`Using author: ${systemUser.name || systemUser.email} (${systemUser._id})`);
|
|
|
|
// 2. Get or create the global "instance" project
|
|
let globalProject = await Project.findOneAndUpdate(
|
|
{ name: GLOBAL_PROJECT_NAME },
|
|
{ $setOnInsert: { name: GLOBAL_PROJECT_NAME } },
|
|
{ new: true, upsert: true, lean: true },
|
|
);
|
|
console.log(`Global project: ${globalProject._id}`);
|
|
|
|
// 3. Create agents
|
|
let created = 0;
|
|
let skipped = 0;
|
|
const agentIds = [];
|
|
|
|
for (const preset of TEAM_PRESETS) {
|
|
const agentId = `agent_hanzo_${preset.preset_id}`;
|
|
|
|
// Check if already exists
|
|
const existing = await Agent.findOne({ id: agentId }).lean();
|
|
if (existing) {
|
|
console.log(` [skip] ${preset.name} (${agentId}) already exists`);
|
|
agentIds.push(agentId);
|
|
skipped++;
|
|
continue;
|
|
}
|
|
|
|
const now = new Date();
|
|
const agentData = {
|
|
id: agentId,
|
|
name: `${preset.emoji} ${preset.name}`,
|
|
description: preset.description,
|
|
instructions: preset.instructions,
|
|
provider: AGENT_PROVIDER,
|
|
model: AGENT_MODEL,
|
|
author: systemUser._id,
|
|
authorName: 'Hanzo AI',
|
|
tools: preset.tools || [],
|
|
conversation_starters: preset.starters || [],
|
|
projectIds: [globalProject._id],
|
|
versions: [{
|
|
name: `${preset.emoji} ${preset.name}`,
|
|
description: preset.description,
|
|
instructions: preset.instructions,
|
|
provider: AGENT_PROVIDER,
|
|
model: AGENT_MODEL,
|
|
tools: preset.tools || [],
|
|
conversation_starters: preset.starters || [],
|
|
projectIds: [globalProject._id],
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
}],
|
|
};
|
|
|
|
await Agent.create(agentData);
|
|
agentIds.push(agentId);
|
|
console.log(` [created] ${preset.emoji} ${preset.name} (${agentId})`);
|
|
created++;
|
|
}
|
|
|
|
// 4. Add all agent IDs to the global project
|
|
if (agentIds.length > 0) {
|
|
await Project.findByIdAndUpdate(
|
|
globalProject._id,
|
|
{ $addToSet: { agentIds: { $each: agentIds } } },
|
|
{ new: true },
|
|
);
|
|
console.log(`\nAdded ${agentIds.length} agents to global project.`);
|
|
}
|
|
|
|
console.log(`\nDone: ${created} created, ${skipped} skipped.`);
|
|
console.log(`Provider: ${AGENT_PROVIDER}, Model: ${AGENT_MODEL}`);
|
|
|
|
await mongoose.disconnect();
|
|
}
|
|
|
|
seed().catch((err) => {
|
|
console.error('Seed failed:', err);
|
|
process.exit(1);
|
|
});
|