agentic-data-stack-community
Version:
AI Agentic Data Stack Framework - Community Edition. Open source data engineering framework with 4 core agents, essential templates, and 3-dimensional quality validation.
1,483 lines (1,246 loc) ⢠42.1 kB
JavaScript
/**
* Expansion Pack Manager - Modular Domain Extension System
*
* Implements sophisticated expansion pack architecture with:
* - Dynamic pack discovery and loading
* - Agent team composition and integration
* - Domain-specific resource management
* - Pack dependency resolution
* - Version compatibility checking
* - Interactive pack creation wizard
* - Pack validation and quality control
* - Marketplace integration readiness
*/
const chalk = require('chalk');
const inquirer = require('inquirer');
const fs = require('fs-extra');
const path = require('path');
const yaml = require('yaml');
class ExpansionPackManager {
constructor(options = {}) {
this.rootDir = options.rootDir || process.cwd();
this.dataCore = path.join(this.rootDir, 'data-core');
this.expansionPacksDir = path.join(this.rootDir, 'expansion-packs');
this.installedPacks = new Map();
this.packRegistry = new Map();
this.packDependencies = new Map();
this.agentOrchestrator = options.agentOrchestrator;
this.knowledgeBase = options.knowledgeBase;
this.templateEngine = options.templateEngine;
}
/**
* Initialize expansion pack system
*/
async initialize() {
console.log(chalk.blue('š¦ Initializing Expansion Pack System...'));
try {
// Ensure expansion packs directory exists
await fs.ensureDir(this.expansionPacksDir);
// Discover available packs
await this.discoverPacks();
// Load pack configurations
await this.loadPackConfigurations();
// Validate pack compatibility
await this.validateCompatibility();
console.log(chalk.green(`ā
Expansion Pack System initialized`));
console.log(chalk.dim(` Found ${this.packRegistry.size} available packs`));
console.log(chalk.dim(` ${this.installedPacks.size} packs installed`));
return {
success: true,
available: this.packRegistry.size,
installed: this.installedPacks.size
};
} catch (error) {
console.error(chalk.red(`ā Initialization failed: ${error.message}`));
return { success: false, error: error.message };
}
}
/**
* Discover available expansion packs
*/
async discoverPacks() {
if (!await fs.pathExists(this.expansionPacksDir)) {
return;
}
const entries = await fs.readdir(this.expansionPacksDir, { withFileTypes: true });
for (const entry of entries) {
if (entry.isDirectory() && !entry.name.startsWith('.')) {
const packPath = path.join(this.expansionPacksDir, entry.name);
const configPath = path.join(packPath, 'config.yaml');
if (await fs.pathExists(configPath)) {
try {
const config = await this.loadPackConfig(configPath);
this.packRegistry.set(entry.name, {
...config,
path: packPath,
installed: true
});
} catch (error) {
console.warn(chalk.yellow(`Warning: Invalid pack config in ${entry.name}`));
}
}
}
}
// Discover example packs from reference
await this.discoverReferencePacks();
}
/**
* Discover reference/example packs
*/
async discoverReferencePacks() {
const referencePacksDir = path.join(this.rootDir, 'reference', 'expansion-packs');
if (!await fs.pathExists(referencePacksDir)) {
return;
}
const entries = await fs.readdir(referencePacksDir, { withFileTypes: true });
for (const entry of entries) {
if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'README.md') {
const packPath = path.join(referencePacksDir, entry.name);
const configPath = path.join(packPath, 'config.yaml');
if (await fs.pathExists(configPath)) {
try {
const config = await this.loadPackConfig(configPath);
if (!this.packRegistry.has(entry.name)) {
this.packRegistry.set(entry.name, {
...config,
path: packPath,
installed: false,
reference: true
});
}
} catch (error) {
console.warn(chalk.yellow(`Warning: Invalid reference pack config in ${entry.name}`));
}
}
}
}
}
/**
* Load pack configuration
*/
async loadPackConfig(configPath) {
const content = await fs.readFile(configPath, 'utf8');
const config = yaml.parse(content);
return {
name: config.name,
version: config.version,
title: config['short-title'] || config.title || config.name,
description: config.description,
author: config.author || 'Unknown',
slashPrefix: config.slashPrefix,
dependencies: config.dependencies || [],
agents: config.agents || [],
category: config.category || 'general'
};
}
/**
* Load detailed pack configurations
*/
async loadPackConfigurations() {
for (const [packName, packInfo] of this.packRegistry.entries()) {
if (packInfo.installed) {
try {
const pack = await this.loadPackDetails(packInfo.path);
this.installedPacks.set(packName, pack);
} catch (error) {
console.warn(chalk.yellow(`Warning: Could not load pack ${packName}: ${error.message}`));
}
}
}
}
/**
* Load complete pack details
*/
async loadPackDetails(packPath) {
const pack = {
path: packPath,
agents: new Map(),
tasks: new Map(),
templates: new Map(),
workflows: new Map(),
checklists: new Map(),
data: new Map()
};
// Load agents
const agentsDir = path.join(packPath, 'agents');
if (await fs.pathExists(agentsDir)) {
const agentFiles = await fs.readdir(agentsDir);
for (const file of agentFiles) {
if (file.endsWith('.md')) {
const agentPath = path.join(agentsDir, file);
const content = await fs.readFile(agentPath, 'utf8');
const agentId = path.basename(file, '.md');
pack.agents.set(agentId, {
path: agentPath,
content,
id: agentId
});
}
}
}
// Load tasks
const tasksDir = path.join(packPath, 'tasks');
if (await fs.pathExists(tasksDir)) {
const taskFiles = await fs.readdir(tasksDir);
for (const file of taskFiles) {
if (file.endsWith('.md')) {
const taskPath = path.join(tasksDir, file);
const content = await fs.readFile(taskPath, 'utf8');
const taskId = path.basename(file, '.md');
pack.tasks.set(taskId, {
path: taskPath,
content,
id: taskId
});
}
}
}
// Load templates
const templatesDir = path.join(packPath, 'templates');
if (await fs.pathExists(templatesDir)) {
const templateFiles = await fs.readdir(templatesDir);
for (const file of templateFiles) {
if (file.endsWith('.yaml') || file.endsWith('.yml')) {
const templatePath = path.join(templatesDir, file);
const content = await fs.readFile(templatePath, 'utf8');
const templateId = path.basename(file).replace(/\.(yaml|yml)$/, '');
pack.templates.set(templateId, {
path: templatePath,
content,
id: templateId
});
}
}
}
// Load workflows
const workflowsDir = path.join(packPath, 'workflows');
if (await fs.pathExists(workflowsDir)) {
const workflowFiles = await fs.readdir(workflowsDir);
for (const file of workflowFiles) {
if (file.endsWith('.yaml') || file.endsWith('.yml')) {
const workflowPath = path.join(workflowsDir, file);
const content = await fs.readFile(workflowPath, 'utf8');
const workflowId = path.basename(file).replace(/\.(yaml|yml)$/, '');
pack.workflows.set(workflowId, {
path: workflowPath,
content,
id: workflowId
});
}
}
}
// Load data files
const dataDir = path.join(packPath, 'data');
if (await fs.pathExists(dataDir)) {
const dataFiles = await fs.readdir(dataDir);
for (const file of dataFiles) {
if (file.endsWith('.md')) {
const dataPath = path.join(dataDir, file);
const content = await fs.readFile(dataPath, 'utf8');
const dataId = path.basename(file, '.md');
pack.data.set(dataId, {
path: dataPath,
content,
id: dataId
});
}
}
}
return pack;
}
/**
* Validate pack compatibility
*/
async validateCompatibility() {
for (const [packName, packInfo] of this.packRegistry.entries()) {
if (packInfo.dependencies && packInfo.dependencies.length > 0) {
for (const dep of packInfo.dependencies) {
if (!this.packRegistry.has(dep)) {
console.warn(chalk.yellow(`Warning: Pack ${packName} requires missing dependency: ${dep}`));
}
}
}
}
}
/**
* Interactive pack management interface
*/
async managePacks() {
console.log(chalk.bold.blue('\nš¦ Expansion Pack Manager'));
const actions = [
'Browse available packs',
'Install expansion pack',
'Create new expansion pack',
'Manage installed packs',
'Validate pack integrity',
'Exit'
];
const { action } = await inquirer.prompt([{
type: 'list',
name: 'action',
message: 'What would you like to do?',
choices: actions
}]);
switch (action) {
case 'Browse available packs':
return await this.browseAvailablePacks();
case 'Install expansion pack':
return await this.installPack();
case 'Create new expansion pack':
return await this.createNewPack();
case 'Manage installed packs':
return await this.manageInstalledPacks();
case 'Validate pack integrity':
return await this.validatePacks();
default:
return { success: true, action: 'exit' };
}
}
/**
* Browse available expansion packs
*/
async browseAvailablePacks() {
console.log(chalk.bold.blue('\nš Available Expansion Packs\n'));
const categories = new Map();
// Group packs by category
this.packRegistry.forEach((pack, packName) => {
const category = pack.category || 'general';
if (!categories.has(category)) {
categories.set(category, []);
}
categories.get(category).push({ packName, ...pack });
});
// Display by category
categories.forEach((packs, category) => {
console.log(chalk.bold.yellow(`${category.charAt(0).toUpperCase() + category.slice(1)}:`));
packs.forEach(pack => {
const status = pack.installed ? chalk.green('ā Installed') :
pack.reference ? chalk.blue('⬠Available') :
chalk.gray('ā Not Installed');
console.log(` ${status} ${chalk.bold(pack.title || pack.name)} v${pack.version}`);
console.log(chalk.dim(` ${pack.description || 'No description'}`));
if (pack.author) {
console.log(chalk.dim(` Author: ${pack.author}`));
}
console.log('');
});
});
const { viewDetails } = await inquirer.prompt([{
type: 'confirm',
name: 'viewDetails',
message: 'Would you like to view details of a specific pack?',
default: true
}]);
if (viewDetails) {
const packChoices = Array.from(this.packRegistry.entries())
.map(([name, pack]) => ({
name: `${pack.title || name} (${pack.installed ? 'Installed' : 'Available'})`,
value: name
}));
const { selectedPack } = await inquirer.prompt([{
type: 'list',
name: 'selectedPack',
message: 'Select a pack to view details:',
choices: packChoices
}]);
await this.viewPackDetails(selectedPack);
}
return { success: true };
}
/**
* View detailed pack information
*/
async viewPackDetails(packName) {
const packInfo = this.packRegistry.get(packName);
if (!packInfo) {
console.log(chalk.red('Pack not found'));
return;
}
console.log(chalk.bold.blue(`\nš¦ ${packInfo.title || packName}`));
console.log(chalk.dim('ā'.repeat(50)));
console.log(chalk.bold('Version:'), packInfo.version);
console.log(chalk.bold('Author:'), packInfo.author || 'Unknown');
console.log(chalk.bold('Category:'), packInfo.category || 'general');
console.log(chalk.bold('Status:'), packInfo.installed ? 'Installed' : 'Not Installed');
if (packInfo.slashPrefix) {
console.log(chalk.bold('Command Prefix:'), `/${packInfo.slashPrefix}`);
}
console.log(chalk.bold('\nDescription:'));
console.log(chalk.dim(packInfo.description || 'No description available'));
if (packInfo.installed) {
const pack = this.installedPacks.get(packName);
if (pack) {
console.log(chalk.bold('\nContents:'));
console.log(chalk.green(` ⢠${pack.agents.size} Agents`));
console.log(chalk.green(` ⢠${pack.tasks.size} Tasks`));
console.log(chalk.green(` ⢠${pack.templates.size} Templates`));
console.log(chalk.green(` ⢠${pack.workflows.size} Workflows`));
console.log(chalk.green(` ⢠${pack.data.size} Data Files`));
if (pack.agents.size > 0) {
console.log(chalk.bold('\nAgents:'));
pack.agents.forEach((agent, agentId) => {
console.log(chalk.dim(` ⢠${agentId}`));
});
}
}
}
if (packInfo.dependencies && packInfo.dependencies.length > 0) {
console.log(chalk.bold('\nDependencies:'));
packInfo.dependencies.forEach(dep => {
const installed = this.packRegistry.has(dep) && this.packRegistry.get(dep).installed;
console.log(` ${installed ? chalk.green('ā') : chalk.red('ā')} ${dep}`);
});
}
}
/**
* Install an expansion pack
*/
async installPack() {
console.log(chalk.bold.blue('\nš„ Install Expansion Pack\n'));
// Filter available packs (not installed)
const availablePacks = Array.from(this.packRegistry.entries())
.filter(([_, pack]) => !pack.installed)
.map(([name, pack]) => ({
name: `${pack.title || name} - ${pack.description || 'No description'}`,
value: name
}));
if (availablePacks.length === 0) {
console.log(chalk.yellow('No available packs to install'));
console.log(chalk.dim('All discovered packs are already installed'));
return { success: false };
}
const { packToInstall } = await inquirer.prompt([{
type: 'list',
name: 'packToInstall',
message: 'Select pack to install:',
choices: availablePacks
}]);
const packInfo = this.packRegistry.get(packToInstall);
// Check dependencies
if (packInfo.dependencies && packInfo.dependencies.length > 0) {
console.log(chalk.yellow('\nChecking dependencies...'));
const missingDeps = packInfo.dependencies.filter(dep =>
!this.packRegistry.has(dep) || !this.packRegistry.get(dep).installed
);
if (missingDeps.length > 0) {
console.log(chalk.red('Missing dependencies:'), missingDeps.join(', '));
const { installDeps } = await inquirer.prompt([{
type: 'confirm',
name: 'installDeps',
message: 'Install missing dependencies?',
default: true
}]);
if (installDeps) {
for (const dep of missingDeps) {
await this.installPackByName(dep);
}
} else {
return { success: false, error: 'Missing dependencies' };
}
}
}
// Install the pack
return await this.installPackByName(packToInstall);
}
/**
* Install a pack by name
*/
async installPackByName(packName) {
const packInfo = this.packRegistry.get(packName);
if (!packInfo) {
console.log(chalk.red(`Pack not found: ${packName}`));
return { success: false, error: 'Pack not found' };
}
if (packInfo.installed) {
console.log(chalk.yellow(`Pack already installed: ${packName}`));
return { success: true, alreadyInstalled: true };
}
console.log(chalk.blue(`Installing ${packInfo.title || packName}...`));
try {
const targetPath = path.join(this.expansionPacksDir, packName);
// Copy from reference location
if (packInfo.reference && packInfo.path) {
await fs.copy(packInfo.path, targetPath);
// Update registry
packInfo.installed = true;
packInfo.path = targetPath;
// Load pack details
const pack = await this.loadPackDetails(targetPath);
this.installedPacks.set(packName, pack);
// Register with agent orchestrator if available
if (this.agentOrchestrator) {
await this.registerPackAgents(packName, pack);
}
// Add to knowledge base if available
if (this.knowledgeBase) {
await this.registerPackKnowledge(packName, pack);
}
console.log(chalk.green(`ā
Successfully installed ${packInfo.title || packName}`));
return { success: true, packName };
} else {
console.log(chalk.red('Pack source not found'));
return { success: false, error: 'Pack source not found' };
}
} catch (error) {
console.error(chalk.red(`Installation failed: ${error.message}`));
return { success: false, error: error.message };
}
}
/**
* Create a new expansion pack
*/
async createNewPack() {
console.log(chalk.bold.blue('\nšØ Create New Expansion Pack\n'));
console.log(chalk.dim('Let\'s create a custom expansion pack for your domain\n'));
// Gather basic information
const packInfo = await inquirer.prompt([
{
type: 'input',
name: 'name',
message: 'Pack name (lowercase, hyphens):',
validate: input => /^[a-z0-9-]+$/.test(input) || 'Use lowercase letters, numbers, and hyphens only',
filter: input => input.toLowerCase().replace(/\s+/g, '-')
},
{
type: 'input',
name: 'title',
message: 'Display title:',
validate: input => input.trim().length > 0 || 'Title is required'
},
{
type: 'input',
name: 'description',
message: 'Pack description:',
validate: input => input.trim().length > 0 || 'Description is required'
},
{
type: 'input',
name: 'author',
message: 'Author name:',
default: 'Unknown'
},
{
type: 'list',
name: 'category',
message: 'Pack category:',
choices: [
'technical',
'business',
'creative',
'health',
'education',
'gaming',
'productivity',
'general'
]
},
{
type: 'input',
name: 'slashPrefix',
message: 'Command prefix (optional, e.g., "game" for /game):',
filter: input => input.replace(/^\//, '').trim()
}
]);
// Domain-specific questions
const domainInfo = await inquirer.prompt([
{
type: 'input',
name: 'domain',
message: 'What domain/industry does this pack serve?',
validate: input => input.trim().length > 0 || 'Domain is required'
},
{
type: 'input',
name: 'problems',
message: 'What problems will this pack solve? (comma-separated):',
filter: input => input.split(',').map(s => s.trim()).filter(s => s)
},
{
type: 'input',
name: 'targetUsers',
message: 'Who are the target users?',
validate: input => input.trim().length > 0 || 'Target users required'
}
]);
// Agent design
console.log(chalk.bold('\nš¤ Let\'s design your agents:\n'));
const agents = await this.designPackAgents(packInfo.name);
// Create pack structure
console.log(chalk.blue('\nš Creating pack structure...'));
const packPath = path.join(this.expansionPacksDir, packInfo.name);
try {
// Create directories
await fs.ensureDir(packPath);
await fs.ensureDir(path.join(packPath, 'agents'));
await fs.ensureDir(path.join(packPath, 'tasks'));
await fs.ensureDir(path.join(packPath, 'templates'));
await fs.ensureDir(path.join(packPath, 'workflows'));
await fs.ensureDir(path.join(packPath, 'checklists'));
await fs.ensureDir(path.join(packPath, 'data'));
await fs.ensureDir(path.join(packPath, 'agent-teams'));
// Create config.yaml
const config = {
name: packInfo.name,
version: '1.0.0',
'short-title': packInfo.title,
description: packInfo.description,
author: packInfo.author,
category: packInfo.category,
slashPrefix: packInfo.slashPrefix || undefined,
domain: domainInfo.domain,
problems: domainInfo.problems,
targetUsers: domainInfo.targetUsers,
agents: agents.map(a => a.id),
dependencies: []
};
await fs.writeFile(
path.join(packPath, 'config.yaml'),
yaml.stringify(config),
'utf8'
);
// Create agent files
for (const agent of agents) {
await this.createAgentFile(packPath, agent);
}
// Create sample task
await this.createSampleTask(packPath, packInfo.name);
// Create sample template
await this.createSampleTemplate(packPath, packInfo.name);
// Create knowledge base file
await this.createPackKnowledgeBase(packPath, packInfo, domainInfo, agents);
// Create README
await this.createPackReadme(packPath, packInfo, domainInfo, agents);
console.log(chalk.green(`\nā
Expansion pack created successfully!`));
console.log(chalk.dim(`Location: ${packPath}`));
// Register the new pack
this.packRegistry.set(packInfo.name, {
...config,
path: packPath,
installed: true
});
// Load pack details
const pack = await this.loadPackDetails(packPath);
this.installedPacks.set(packInfo.name, pack);
console.log(chalk.bold('\nNext steps:'));
console.log('1. Add more agents to the agents/ directory');
console.log('2. Create tasks in the tasks/ directory');
console.log('3. Design templates in the templates/ directory');
console.log('4. Define workflows in the workflows/ directory');
console.log('5. Test with your target users');
return { success: true, packName: packInfo.name, path: packPath };
} catch (error) {
console.error(chalk.red(`Failed to create pack: ${error.message}`));
return { success: false, error: error.message };
}
}
/**
* Design agents for a new pack
*/
async designPackAgents(packName) {
const agents = [];
let addMore = true;
console.log(chalk.dim('Design specialized agents for your domain (minimum 2)\n'));
while (addMore || agents.length < 2) {
const agentNum = agents.length + 1;
console.log(chalk.bold(`\nAgent ${agentNum}:`));
const agentInfo = await inquirer.prompt([
{
type: 'input',
name: 'id',
message: 'Agent ID (lowercase, hyphens):',
validate: input => /^[a-z0-9-]+$/.test(input) || 'Use lowercase letters, numbers, and hyphens only',
filter: input => input.toLowerCase().replace(/\s+/g, '-')
},
{
type: 'input',
name: 'name',
message: 'Agent name:',
validate: input => input.trim().length > 0 || 'Name is required'
},
{
type: 'input',
name: 'title',
message: 'Agent title/role:',
validate: input => input.trim().length > 0 || 'Title is required'
},
{
type: 'input',
name: 'icon',
message: 'Agent icon (emoji):',
default: 'š¤'
},
{
type: 'input',
name: 'expertise',
message: 'Areas of expertise (comma-separated):',
filter: input => input.split(',').map(s => s.trim()).filter(s => s)
},
{
type: 'input',
name: 'personality',
message: 'Personality traits (comma-separated):',
filter: input => input.split(',').map(s => s.trim()).filter(s => s),
default: 'professional, helpful, knowledgeable'
}
]);
agents.push(agentInfo);
if (agents.length >= 2) {
const { continue: shouldContinue } = await inquirer.prompt([{
type: 'confirm',
name: 'continue',
message: 'Add another agent?',
default: false
}]);
addMore = shouldContinue;
}
}
return agents;
}
/**
* Create agent file
*/
async createAgentFile(packPath, agentInfo) {
const agentContent = `# ${agentInfo.name}
## Agent Configuration
\`\`\`yaml
agent:
id: ${agentInfo.id}
name: ${agentInfo.name}
title: ${agentInfo.title}
icon: ${agentInfo.icon}
persona:
role: ${agentInfo.title}
expertise: ${agentInfo.expertise.map(e => `\n - ${e}`).join('')}
personality: ${agentInfo.personality.map(p => `\n - ${p}`).join('')}
communication_style: Clear, professional, domain-specific
capabilities:
primary:
- ${agentInfo.expertise[0] || 'Domain expertise'}
- Task execution and guidance
- Knowledge synthesis
secondary:
- Cross-functional collaboration
- Best practice recommendations
- Quality assurance
commands:
- help: Show available commands and capabilities
- task: Execute a specific task
- analyze: Analyze current context
- recommend: Provide recommendations
- create-doc: Create documentation from templates
dependencies:
tasks:
- analyze-context.md
- provide-recommendations.md
templates:
- analysis-report-tmpl.yaml
- recommendation-tmpl.yaml
data:
- ${agentInfo.id}-kb.md
\`\`\`
## Operational Guidelines
### Primary Responsibilities
1. **${agentInfo.expertise[0] || 'Domain Expertise'}**
- Provide expert guidance and recommendations
- Ensure best practices are followed
- Validate approaches and solutions
2. **Task Execution**
- Guide users through complex tasks
- Break down problems into manageable steps
- Ensure quality outcomes
3. **Knowledge Management**
- Synthesize information effectively
- Provide context-aware insights
- Document decisions and rationale
### Interaction Patterns
- Always maintain professional demeanor
- Ask clarifying questions when needed
- Provide actionable recommendations
- Validate understanding before proceeding
### Quality Standards
- Ensure all outputs meet domain standards
- Validate recommendations against best practices
- Document assumptions and constraints
- Provide clear success criteria
`;
await fs.writeFile(
path.join(packPath, 'agents', `${agentInfo.id}.md`),
agentContent,
'utf8'
);
}
/**
* Create sample task
*/
async createSampleTask(packPath, packName) {
const taskContent = `# Analyze Context Task
## Purpose
Analyze the current context and provide domain-specific insights and recommendations.
## Task Steps
1. **Gather Context**
- Understand the current situation
- Identify key stakeholders
- Document constraints and requirements
2. **Analyze Domain Factors**
- Apply domain expertise
- Identify patterns and trends
- Assess risks and opportunities
3. **Generate Insights**
- Synthesize findings
- Identify key insights
- Prioritize by impact
4. **Provide Recommendations**
- Develop actionable recommendations
- Consider implementation feasibility
- Define success metrics
## Expected Outputs
- Context analysis document
- Key insights summary
- Prioritized recommendations
- Implementation roadmap
## Quality Criteria
- Comprehensive analysis
- Clear and actionable insights
- Evidence-based recommendations
- Practical implementation guidance
`;
await fs.writeFile(
path.join(packPath, 'tasks', 'analyze-context.md'),
taskContent,
'utf8'
);
}
/**
* Create sample template
*/
async createSampleTemplate(packPath, packName) {
const templateContent = {
template: {
name: 'Analysis Report Template',
version: '1.0',
description: 'Template for domain-specific analysis reports',
sections: [
{
id: 'executive-summary',
title: 'Executive Summary',
type: 'paragraph',
instruction: 'Provide a high-level summary of the analysis and key findings',
elicit: true
},
{
id: 'context',
title: 'Context and Background',
type: 'structured',
fields: [
{ field: 'Situation', description: 'Current situation overview' },
{ field: 'Stakeholders', description: 'Key stakeholders involved' },
{ field: 'Constraints', description: 'Known constraints and limitations' }
]
},
{
id: 'analysis',
title: 'Detailed Analysis',
type: 'paragraphs',
instruction: 'Provide comprehensive analysis of the domain-specific factors',
elicit: true
},
{
id: 'recommendations',
title: 'Recommendations',
type: 'numbered-list',
instruction: 'List prioritized recommendations with rationale',
elicit: true
},
{
id: 'next-steps',
title: 'Next Steps',
type: 'bullet-list',
instruction: 'Define clear next steps and action items'
}
]
}
};
await fs.writeFile(
path.join(packPath, 'templates', 'analysis-report-tmpl.yaml'),
yaml.stringify(templateContent),
'utf8'
);
}
/**
* Create pack knowledge base
*/
async createPackKnowledgeBase(packPath, packInfo, domainInfo, agents) {
const kbContent = `# ${packInfo.title} Knowledge Base
## Overview
${packInfo.description}
### Domain Focus
**Industry/Domain**: ${domainInfo.domain}
**Target Users**: ${domainInfo.targetUsers}
**Problems Solved**:
${domainInfo.problems.map(p => `- ${p}`).join('\n')}
## Agent Capabilities
${agents.map(agent => `### ${agent.name} (${agent.id})
**Role**: ${agent.title}
**Expertise Areas**:
${agent.expertise.map(e => `- ${e}`).join('\n')}
**Key Responsibilities**:
- Provide expert guidance in ${agent.expertise[0] || 'domain area'}
- Execute specialized tasks
- Collaborate with other agents
- Ensure quality outcomes
`).join('\n')}
## Best Practices
### Domain-Specific Guidelines
1. **Understand Context First**
- Always gather comprehensive context
- Identify stakeholder needs
- Document constraints clearly
2. **Apply Domain Expertise**
- Use established best practices
- Consider industry standards
- Validate against real-world scenarios
3. **Deliver Value**
- Focus on actionable outcomes
- Provide clear recommendations
- Enable implementation success
### Quality Standards
- All outputs must be practical and implementable
- Recommendations should be evidence-based
- Documentation must be clear and comprehensive
- Solutions should consider long-term sustainability
## Common Workflows
### Initial Analysis
1. Activate relevant agent
2. Execute context analysis task
3. Review findings
4. Generate recommendations
### Implementation Planning
1. Define objectives clearly
2. Break down into manageable tasks
3. Assign to appropriate agents
4. Track progress systematically
## Glossary
Define domain-specific terms here to ensure consistent understanding.
## Resources
List additional resources, references, and tools relevant to this domain.
`;
await fs.writeFile(
path.join(packPath, 'data', `${packInfo.name}-kb.md`),
kbContent,
'utf8'
);
}
/**
* Create pack README
*/
async createPackReadme(packPath, packInfo, domainInfo, agents) {
const readmeContent = `# ${packInfo.title}
${packInfo.description}
## Overview
This expansion pack provides specialized AI agents for ${domainInfo.domain}, designed to help ${domainInfo.targetUsers}.
### Problems Solved
${domainInfo.problems.map(p => `- ${p}`).join('\n')}
## Agents
${agents.map(agent => `### ${agent.icon} ${agent.name}
- **ID**: \`${agent.id}\`
- **Role**: ${agent.title}
- **Expertise**: ${agent.expertise.join(', ')}`).join('\n\n')}
## Quick Start
1. **Activate an agent**:
\`\`\`
@${agents[0].id}
\`\`\`
2. **View available commands**:
\`\`\`
*help
\`\`\`
3. **Execute a task**:
\`\`\`
*task analyze-context
\`\`\`
## Installation
This pack is installed in your expansion-packs directory. To use it:
1. Ensure the pack is loaded in your configuration
2. Activate agents using their IDs
3. Use the provided tasks and templates
## Structure
\`\`\`
${packInfo.name}/
āāā agents/ # Agent definitions
āāā tasks/ # Reusable task definitions
āāā templates/ # Document templates
āāā workflows/ # Multi-step workflows
āāā checklists/ # Quality checklists
āāā data/ # Knowledge base files
āāā config.yaml # Pack configuration
\`\`\`
## Customization
Feel free to:
- Add new agents to the agents/ directory
- Create domain-specific tasks
- Design custom templates
- Define workflows for common processes
## Version History
- v1.0.0 - Initial release
## Author
${packInfo.author}
## License
[Specify your license here]
`;
await fs.writeFile(
path.join(packPath, 'README.md'),
readmeContent,
'utf8'
);
}
/**
* Manage installed packs
*/
async manageInstalledPacks() {
console.log(chalk.bold.blue('\nš¦ Installed Expansion Packs\n'));
if (this.installedPacks.size === 0) {
console.log(chalk.yellow('No expansion packs installed'));
return { success: true };
}
const packChoices = Array.from(this.installedPacks.entries())
.map(([name, _]) => {
const info = this.packRegistry.get(name);
return {
name: `${info.title || name} v${info.version}`,
value: name
};
});
const { selectedPack } = await inquirer.prompt([{
type: 'list',
name: 'selectedPack',
message: 'Select a pack to manage:',
choices: [...packChoices, { name: 'Back', value: null }]
}]);
if (!selectedPack) {
return { success: true };
}
const { action } = await inquirer.prompt([{
type: 'list',
name: 'action',
message: `Manage ${selectedPack}:`,
choices: [
'View details',
'Update pack',
'Export pack',
'Uninstall pack',
'Back'
]
}]);
switch (action) {
case 'View details':
await this.viewPackDetails(selectedPack);
break;
case 'Update pack':
await this.updatePack(selectedPack);
break;
case 'Export pack':
await this.exportPack(selectedPack);
break;
case 'Uninstall pack':
await this.uninstallPack(selectedPack);
break;
}
return { success: true };
}
/**
* Validate pack integrity
*/
async validatePacks() {
console.log(chalk.bold.blue('\nš Validating Expansion Packs\n'));
const results = [];
for (const [packName, pack] of this.installedPacks.entries()) {
console.log(chalk.blue(`Validating ${packName}...`));
const issues = [];
// Check required directories
const requiredDirs = ['agents', 'tasks', 'templates'];
for (const dir of requiredDirs) {
const dirPath = path.join(pack.path, dir);
if (!await fs.pathExists(dirPath)) {
issues.push(`Missing required directory: ${dir}/`);
}
}
// Check config file
const configPath = path.join(pack.path, 'config.yaml');
if (!await fs.pathExists(configPath)) {
issues.push('Missing config.yaml');
}
// Check agent definitions
if (pack.agents.size === 0) {
issues.push('No agents defined');
}
// Validate agent files
for (const [agentId, agent] of pack.agents.entries()) {
const agentIssues = this.validateAgentDefinition(agent.content);
if (agentIssues.length > 0) {
issues.push(`Agent ${agentId}: ${agentIssues.join(', ')}`);
}
}
results.push({
packName,
valid: issues.length === 0,
issues
});
}
// Display results
console.log(chalk.bold('\nValidation Results:\n'));
results.forEach(result => {
if (result.valid) {
console.log(chalk.green(`ā
${result.packName}: Valid`));
} else {
console.log(chalk.red(`ā ${result.packName}: ${result.issues.length} issues found`));
result.issues.forEach(issue => {
console.log(chalk.dim(` - ${issue}`));
});
}
});
return { success: true, results };
}
/**
* Validate agent definition
*/
validateAgentDefinition(content) {
const issues = [];
// Check for required YAML block
if (!content.includes('```yaml')) {
issues.push('Missing YAML configuration block');
}
// Check for required sections
const requiredSections = ['agent:', 'persona:', 'commands:'];
requiredSections.forEach(section => {
if (!content.includes(section)) {
issues.push(`Missing required section: ${section}`);
}
});
return issues;
}
/**
* Register pack agents with orchestrator
*/
async registerPackAgents(packName, pack) {
if (!this.agentOrchestrator) return;
console.log(chalk.dim(`Registering agents from ${packName}...`));
for (const [agentId, agent] of pack.agents.entries()) {
try {
// Add pack prefix to avoid conflicts
const fullAgentId = `${packName}-${agentId}`;
await this.agentOrchestrator.loadAgent(agent.path);
console.log(chalk.dim(` ā Registered ${agentId}`));
} catch (error) {
console.warn(chalk.yellow(` Warning: Could not register ${agentId}`));
}
}
}
/**
* Register pack knowledge with KB
*/
async registerPackKnowledge(packName, pack) {
if (!this.knowledgeBase) return;
console.log(chalk.dim(`Adding knowledge from ${packName}...`));
for (const [dataId, data] of pack.data.entries()) {
try {
await this.knowledgeBase.updateKnowledge(
`${packName}-${dataId}.md`,
data.content,
{
source: 'expansion-pack',
pack: packName
}
);
console.log(chalk.dim(` ā Added ${dataId}`));
} catch (error) {
console.warn(chalk.yellow(` Warning: Could not add ${dataId}`));
}
}
}
/**
* Export pack for sharing
*/
async exportPack(packName) {
const pack = this.installedPacks.get(packName);
if (!pack) {
console.log(chalk.red('Pack not found'));
return { success: false };
}
console.log(chalk.blue(`\nš¤ Exporting ${packName}...`));
const exportPath = path.join(this.rootDir, 'exports', `${packName}-export.zip`);
// TODO: Implement zip export functionality
console.log(chalk.yellow('Export functionality coming soon!'));
console.log(chalk.dim(`Pack location: ${pack.path}`));
return { success: true };
}
/**
* Update pack (placeholder)
*/
async updatePack(packName) {
console.log(chalk.yellow('Update functionality coming soon!'));
console.log(chalk.dim('Check for updates manually or submit PRs to improve packs'));
return { success: true };
}
/**
* Uninstall pack
*/
async uninstallPack(packName) {
const pack = this.installedPacks.get(packName);
if (!pack) {
console.log(chalk.red('Pack not found'));
return { success: false };
}
const { confirm } = await inquirer.prompt([{
type: 'confirm',
name: 'confirm',
message: `Are you sure you want to uninstall ${packName}?`,
default: false
}]);
if (!confirm) {
return { success: false, cancelled: true };
}
try {
console.log(chalk.blue(`Uninstalling ${packName}...`));
// Remove from disk
await fs.remove(pack.path);
// Remove from registries
this.installedPacks.delete(packName);
const packInfo = this.packRegistry.get(packName);
if (packInfo) {
packInfo.installed = false;
}
console.log(chalk.green(`ā
Successfully uninstalled ${packName}`));
return { success: true };
} catch (error) {
console.error(chalk.red(`Failed to uninstall: ${error.message}`));
return { success: false, error: error.message };
}
}
/**
* Get pack by name
*/
getPack(packName) {
return this.installedPacks.get(packName);
}
/**
* List all installed packs
*/
listInstalledPacks() {
return Array.from(this.installedPacks.keys());
}
/**
* Get pack agents
*/
getPackAgents(packName) {
const pack = this.installedPacks.get(packName);
return pack ? Array.from(pack.agents.keys()) : [];
}
/**
* Get pack templates
*/
getPackTemplates(packName) {
const pack = this.installedPacks.get(packName);
return pack ? Array.from(pack.templates.keys()) : [];
}
}
module.exports = ExpansionPackManager;