Initial commit
This commit is contained in:
374
agents/meta.create/README.md
Normal file
374
agents/meta.create/README.md
Normal file
@@ -0,0 +1,374 @@
|
||||
# meta.create - Component Creation Orchestrator
|
||||
|
||||
The intelligent orchestrator for creating Betty skills, commands, and agents from natural language descriptions.
|
||||
|
||||
## Purpose
|
||||
|
||||
`meta.create` is the primary entry point for creating Betty components. It automatically:
|
||||
|
||||
- **Detects** what type of component you're describing (skill, command, agent, or combination)
|
||||
- **Checks** inventory to avoid duplicates
|
||||
- **Analyzes** complexity to determine the optimal creation pattern
|
||||
- **Creates** components in dependency order
|
||||
- **Validates** compatibility and identifies gaps
|
||||
- **Recommends** next steps for completion
|
||||
|
||||
## Why Use meta.create?
|
||||
|
||||
Instead of manually running multiple meta-agents (`meta.skill`, `meta.command`, `meta.agent`, `meta.compatibility`), `meta.create` orchestrates everything for you in the right order.
|
||||
|
||||
### Before meta.create:
|
||||
```bash
|
||||
# Manual workflow - you had to know the order and check everything
|
||||
python3 agents/meta.command/meta_command.py description.md
|
||||
# Check if it recommends creating a skill...
|
||||
python3 agents/meta.skill/meta_skill.py skill_description.md
|
||||
python3 agents/meta.agent/meta_agent.py agent_description.md
|
||||
python3 agents/meta.compatibility/meta_compatibility.py analyze my.agent
|
||||
# Check for gaps, create missing skills...
|
||||
```
|
||||
|
||||
### With meta.create:
|
||||
```bash
|
||||
# One command does it all
|
||||
python3 agents/meta.create/meta_create.py description.md
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
### Step 1: Analysis
|
||||
Parses your description to determine:
|
||||
- Is this a skill? command? agent?
|
||||
- What artifacts are involved?
|
||||
- What's the complexity level?
|
||||
|
||||
### Step 2: Duplicate Check
|
||||
Queries registries to find existing components:
|
||||
- Prevents recreating existing skills
|
||||
- Shows what you can reuse
|
||||
- Skips unnecessary work
|
||||
|
||||
### Step 3: Creation Planning
|
||||
Uses `meta.command` complexity analysis to determine pattern:
|
||||
- **COMMAND_ONLY**: Simple inline logic (1-3 steps)
|
||||
- **SKILL_ONLY**: Reusable utility without command
|
||||
- **SKILL_AND_COMMAND**: Complex logic in skill + command wrapper
|
||||
- **AGENT**: Multi-skill orchestration
|
||||
|
||||
### Step 4: Component Creation
|
||||
Creates components in dependency order:
|
||||
1. **Skills first** (using `meta.skill`)
|
||||
2. **Commands second** (using `meta.command`)
|
||||
3. **Agents last** (using `meta.agent` with skill composition)
|
||||
|
||||
### Step 5: Compatibility Validation
|
||||
For agents, runs `meta.compatibility` to:
|
||||
- Find compatible agent pipelines
|
||||
- Identify artifact gaps
|
||||
- Suggest workflows
|
||||
|
||||
### Step 6: Recommendations
|
||||
Provides actionable next steps:
|
||||
- Missing skills to create
|
||||
- Compatibility issues to fix
|
||||
- Integration opportunities
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```bash
|
||||
python3 agents/meta.create/meta_create.py <description.md>
|
||||
```
|
||||
|
||||
### Create Skill and Command
|
||||
|
||||
```bash
|
||||
python3 agents/meta.create/meta_create.py examples/api_validate.md
|
||||
```
|
||||
|
||||
If `api_validate.md` describes a complex command, meta.create will:
|
||||
1. Analyze complexity → detects SKILL_AND_COMMAND pattern
|
||||
2. Create the skill first
|
||||
3. Create the command that uses the skill
|
||||
4. Report what was created
|
||||
|
||||
### Create Agent with Dependencies
|
||||
|
||||
```bash
|
||||
python3 agents/meta.create/meta_create.py examples/api_agent.md
|
||||
```
|
||||
|
||||
meta.create will:
|
||||
1. Detect it's an agent description
|
||||
2. Check for required skills (reuse existing)
|
||||
3. Create missing skills if needed
|
||||
4. Create the agent with proper skill composition
|
||||
5. Validate compatibility with other agents
|
||||
6. Report gaps and recommendations
|
||||
|
||||
### Auto-Fill Gaps
|
||||
|
||||
```bash
|
||||
python3 agents/meta.create/meta_create.py description.md --auto-fill-gaps
|
||||
```
|
||||
|
||||
Automatically creates missing skills to fill compatibility gaps.
|
||||
|
||||
### Skip Duplicate Check
|
||||
|
||||
```bash
|
||||
python3 agents/meta.create/meta_create.py description.md --skip-duplicate-check
|
||||
```
|
||||
|
||||
Force creation even if components exist (useful for updates).
|
||||
|
||||
### Output Formats
|
||||
|
||||
```bash
|
||||
# Human-readable text (default)
|
||||
python3 agents/meta.create/meta_create.py description.md
|
||||
|
||||
# JSON output for automation
|
||||
python3 agents/meta.create/meta_create.py description.md --output-format json
|
||||
|
||||
# YAML output
|
||||
python3 agents/meta.create/meta_create.py description.md --output-format yaml
|
||||
```
|
||||
|
||||
### With Traceability
|
||||
|
||||
```bash
|
||||
python3 agents/meta.create/meta_create.py description.md \
|
||||
--requirement-id REQ-2025-042 \
|
||||
--requirement-description "Create API validation agent" \
|
||||
--issue-id JIRA-1234 \
|
||||
--requested-by "Product Team"
|
||||
```
|
||||
|
||||
## Description File Format
|
||||
|
||||
Your description file can be Markdown or JSON. meta.create detects the type automatically.
|
||||
|
||||
### Example: Skill Description
|
||||
|
||||
```markdown
|
||||
# Name: data.validate
|
||||
|
||||
# Type: skill
|
||||
|
||||
# Purpose:
|
||||
Validate data against JSON schemas with detailed error reporting
|
||||
|
||||
# Inputs:
|
||||
- data (JSON object to validate)
|
||||
- schema (JSON schema for validation)
|
||||
|
||||
# Outputs:
|
||||
- validation_result (validation report with errors)
|
||||
|
||||
# Produces Artifacts:
|
||||
- validation.report
|
||||
|
||||
# Consumes Artifacts:
|
||||
- data.json
|
||||
- schema.json
|
||||
```
|
||||
|
||||
### Example: Command Description
|
||||
|
||||
```markdown
|
||||
# Name: /validate-api
|
||||
|
||||
# Type: command
|
||||
|
||||
# Description:
|
||||
Validate API responses against OpenAPI schemas
|
||||
|
||||
# Execution Type: skill
|
||||
|
||||
# Target: api.validate
|
||||
|
||||
# Parameters:
|
||||
- endpoint: string (required) - API endpoint to validate
|
||||
- schema: string (required) - Path to OpenAPI schema
|
||||
```
|
||||
|
||||
### Example: Agent Description
|
||||
|
||||
```markdown
|
||||
# Name: api.validator
|
||||
|
||||
# Type: agent
|
||||
|
||||
# Purpose:
|
||||
Comprehensive API testing and validation agent
|
||||
|
||||
# Inputs:
|
||||
- api.spec
|
||||
|
||||
# Outputs:
|
||||
- validation.report
|
||||
- test.results
|
||||
|
||||
# Examples:
|
||||
- Validate all API endpoints against OpenAPI spec
|
||||
- Generate test cases from schema
|
||||
```
|
||||
|
||||
## What Gets Created
|
||||
|
||||
### For Skills
|
||||
- `skills/{name}/skill.yaml` - Skill configuration
|
||||
- `skills/{name}/{name}.py` - Python implementation stub
|
||||
- `skills/{name}/test_{name}.py` - pytest test template
|
||||
- `skills/{name}/README.md` - Documentation
|
||||
|
||||
### For Commands
|
||||
- `commands/{name}.yaml` - Command manifest
|
||||
- Recommendations for skill creation if needed
|
||||
|
||||
### For Agents
|
||||
- `agents/{name}/agent.yaml` - Agent configuration
|
||||
- `agents/{name}/README.md` - Documentation with usage examples
|
||||
- Compatibility analysis report
|
||||
|
||||
## Output Report
|
||||
|
||||
meta.create provides a comprehensive report:
|
||||
|
||||
```
|
||||
🎯 meta.create - Orchestrating component creation from description.md
|
||||
|
||||
📋 Step 1: Analyzing description...
|
||||
Detected types: Skill=True, Command=True, Agent=False
|
||||
|
||||
🔍 Step 2: Checking for existing components...
|
||||
✅ No duplicates found
|
||||
|
||||
🛠️ Step 3: Creating components...
|
||||
📊 Analyzing command complexity...
|
||||
Recommended pattern: SKILL_AND_COMMAND
|
||||
Should create skill: True
|
||||
|
||||
🔧 Creating skill...
|
||||
✅ Skill 'api.validate' created
|
||||
|
||||
📜 Creating command...
|
||||
✅ Command '/validate-api' created
|
||||
|
||||
================================================================================
|
||||
✨ CREATION SUMMARY
|
||||
================================================================================
|
||||
|
||||
✅ Created 2 component(s):
|
||||
• SKILL: api.validate
|
||||
• COMMAND: /validate-api
|
||||
|
||||
================================================================================
|
||||
```
|
||||
|
||||
## Integration with Other Meta-Agents
|
||||
|
||||
meta.create uses:
|
||||
- **meta.command** - Complexity analysis and command generation
|
||||
- **meta.skill** - Skill creation with full package
|
||||
- **meta.agent** - Agent creation with skill composition
|
||||
- **meta.compatibility** - Compatibility validation and gap detection
|
||||
- **registry.query** - Duplicate checking
|
||||
- **agent.compose** - Skill recommendation for agents
|
||||
|
||||
## Decision Tree
|
||||
|
||||
```
|
||||
Description Input
|
||||
↓
|
||||
Parse Type
|
||||
↓
|
||||
┌──┴──────────────────┐
|
||||
↓ ↓
|
||||
Command? Agent?
|
||||
↓ ↓
|
||||
Analyze Find Skills
|
||||
Complexity ↓
|
||||
↓ Create Missing
|
||||
SKILL_ONLY Skills
|
||||
COMMAND_ONLY ↓
|
||||
SKILL_AND_COMMAND Create Agent
|
||||
↓ ↓
|
||||
Create Skill Validate Compat
|
||||
↓ ↓
|
||||
Create Command Report Gaps
|
||||
↓ ↓
|
||||
Done Recommend
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: Simple Command
|
||||
|
||||
```bash
|
||||
# description.md specifies a simple 2-step command
|
||||
python3 agents/meta.create/meta_create.py description.md
|
||||
# Result: Creates COMMAND_ONLY (inline logic is sufficient)
|
||||
```
|
||||
|
||||
### Example 2: Complex Command
|
||||
|
||||
```bash
|
||||
# description.md specifies 10+ step validation logic
|
||||
python3 agents/meta.create/meta_create.py description.md
|
||||
# Result: Creates SKILL_AND_COMMAND (skill has logic, command delegates)
|
||||
```
|
||||
|
||||
### Example 3: Multi-Agent System
|
||||
|
||||
```bash
|
||||
# description.md describes an orchestration agent
|
||||
python3 agents/meta.create/meta_create.py description.md
|
||||
# Result:
|
||||
# - Creates agent with existing skills
|
||||
# - Validates compatibility
|
||||
# - Reports: "Can receive from api.architect, can feed to report.generator"
|
||||
# - Suggests pipeline workflows
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
✅ **Intelligent** - Automatically determines optimal creation pattern
|
||||
✅ **Safe** - Checks for duplicates, prevents overwrites
|
||||
✅ **Complete** - Creates all necessary components in order
|
||||
✅ **Validated** - Runs compatibility checks automatically
|
||||
✅ **Traceable** - Supports requirement tracking
|
||||
✅ **Informative** - Provides detailed reports and recommendations
|
||||
|
||||
## Next Steps
|
||||
|
||||
After using meta.create:
|
||||
|
||||
1. **Review** created files
|
||||
2. **Implement** TODO sections in generated code
|
||||
3. **Test** with pytest
|
||||
4. **Register** components (manual or use `skill.register`, etc.)
|
||||
5. **Use** in your Betty workflows
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Q: meta.create says component already exists**
|
||||
A: Use `--skip-duplicate-check` to override, or rename your component
|
||||
|
||||
**Q: Compatibility gaps reported**
|
||||
A: Use `--auto-fill-gaps` or manually create the missing skills
|
||||
|
||||
**Q: Wrong pattern detected**
|
||||
A: Add explicit `# Type: skill` or `# Type: command` to your description
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [META_AGENTS.md](../../docs/META_AGENTS.md) - Overview of all meta-agents
|
||||
- [SKILL_COMMAND_DECISION_TREE.md](../../docs/SKILL_COMMAND_DECISION_TREE.md) - Pattern decision logic
|
||||
- [ARTIFACTS.md](../../docs/ARTIFACTS.md) - Artifact metadata system
|
||||
|
||||
---
|
||||
|
||||
*Created by the Betty Framework Meta-Agent System*
|
||||
80
agents/meta.create/agent.yaml
Normal file
80
agents/meta.create/agent.yaml
Normal file
@@ -0,0 +1,80 @@
|
||||
name: meta.create
|
||||
version: 0.1.0
|
||||
description: |
|
||||
Orchestrator meta-agent that intelligently creates skills, commands, and agents.
|
||||
|
||||
Capabilities:
|
||||
- Detects component type from description
|
||||
- Checks inventory for duplicates
|
||||
- Analyzes complexity and determines creation pattern
|
||||
- Creates skills, commands, and agents in proper order
|
||||
- Validates compatibility using meta.compatibility
|
||||
- Identifies gaps and provides recommendations
|
||||
- Supports auto-filling missing dependencies
|
||||
|
||||
This is the primary entry point for creating Betty components from natural
|
||||
language descriptions.
|
||||
|
||||
status: draft
|
||||
reasoning_mode: iterative
|
||||
capabilities:
|
||||
- Diagnose component needs and recommend skills, commands, or agents to create
|
||||
- Generate scaffolding for new framework components with proper metadata
|
||||
- Coordinate validation steps to ensure compatibility before registration
|
||||
|
||||
skills_available:
|
||||
- registry.query
|
||||
- agent.compose
|
||||
|
||||
permissions:
|
||||
- filesystem:read
|
||||
- filesystem:write
|
||||
- registry:read
|
||||
- registry:write
|
||||
|
||||
artifact_metadata:
|
||||
consumes:
|
||||
- type: component.description
|
||||
description: Natural language description of component to create
|
||||
format: markdown or JSON
|
||||
required: true
|
||||
|
||||
produces:
|
||||
- type: skill.definition
|
||||
description: Complete skill package with YAML, implementation, tests
|
||||
optional: true
|
||||
|
||||
- type: command.manifest
|
||||
description: Command manifest in YAML format
|
||||
optional: true
|
||||
|
||||
- type: agent.definition
|
||||
description: Agent configuration with skill composition
|
||||
optional: true
|
||||
|
||||
- type: compatibility.report
|
||||
description: Compatibility analysis showing agent relationships and gaps
|
||||
optional: true
|
||||
|
||||
tags:
|
||||
- meta
|
||||
- orchestration
|
||||
- creation
|
||||
- automation
|
||||
|
||||
system_prompt: |
|
||||
You are meta.create, the intelligent orchestrator for creating Betty components.
|
||||
|
||||
Your responsibilities:
|
||||
1. Analyze component descriptions to determine type (skill/command/agent)
|
||||
2. Check registries to avoid creating duplicates
|
||||
3. Determine optimal creation pattern using complexity analysis
|
||||
4. Create components in dependency order (skills → commands → agents)
|
||||
5. Validate agent compatibility and identify gaps
|
||||
6. Provide actionable recommendations for completion
|
||||
|
||||
Always prioritize:
|
||||
- Reusing existing components over creating new ones
|
||||
- Creating building blocks (skills) before orchestrators (agents)
|
||||
- Validating compatibility to ensure smooth agent pipelines
|
||||
- Providing clear feedback about what was created and why
|
||||
555
agents/meta.create/meta_create.py
Normal file
555
agents/meta.create/meta_create.py
Normal file
@@ -0,0 +1,555 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
meta.create - Orchestrator Meta-Agent
|
||||
|
||||
Intelligently orchestrates the creation of skills, commands, and agents.
|
||||
Checks inventory, determines what needs to be created, validates compatibility,
|
||||
and fills gaps automatically.
|
||||
|
||||
This is the main entry point for creating Betty components from descriptions.
|
||||
"""
|
||||
|
||||
import json
|
||||
import yaml
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Any, Optional, Set, Tuple
|
||||
from datetime import datetime
|
||||
|
||||
# Add parent directory to path for imports
|
||||
parent_dir = str(Path(__file__).parent.parent.parent)
|
||||
sys.path.insert(0, parent_dir)
|
||||
|
||||
# Import other meta agents by adding their paths
|
||||
meta_command_path = Path(parent_dir) / "agents" / "meta.command"
|
||||
meta_skill_path = Path(parent_dir) / "agents" / "meta.skill"
|
||||
meta_agent_path = Path(parent_dir) / "agents" / "meta.agent"
|
||||
meta_compatibility_path = Path(parent_dir) / "agents" / "meta.compatibility"
|
||||
registry_query_path = Path(parent_dir) / "skills" / "registry.query"
|
||||
|
||||
sys.path.insert(0, str(meta_command_path))
|
||||
sys.path.insert(0, str(meta_skill_path))
|
||||
sys.path.insert(0, str(meta_agent_path))
|
||||
sys.path.insert(0, str(meta_compatibility_path))
|
||||
sys.path.insert(0, str(registry_query_path))
|
||||
|
||||
import meta_command
|
||||
import meta_skill
|
||||
import meta_agent
|
||||
import meta_compatibility
|
||||
import registry_query
|
||||
|
||||
from betty.config import BASE_DIR
|
||||
from betty.logging_utils import setup_logger
|
||||
from betty.traceability import get_tracer, RequirementInfo
|
||||
|
||||
logger = setup_logger(__name__)
|
||||
|
||||
|
||||
class ComponentCreator:
|
||||
"""Orchestrates the creation of skills, commands, and agents"""
|
||||
|
||||
def __init__(self, base_dir: str = BASE_DIR):
|
||||
"""Initialize orchestrator"""
|
||||
self.base_dir = Path(base_dir)
|
||||
self.created_components = []
|
||||
self.compatibility_analyzer = None
|
||||
|
||||
def check_duplicate(self, component_type: str, name: str) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Check if a component already exists in registry
|
||||
|
||||
Args:
|
||||
component_type: 'skills', 'commands', or 'agents'
|
||||
name: Component name to check
|
||||
|
||||
Returns:
|
||||
Existing component info if found, None otherwise
|
||||
"""
|
||||
try:
|
||||
result = registry_query.query_registry(
|
||||
registry=component_type,
|
||||
name=name,
|
||||
fuzzy=False
|
||||
)
|
||||
|
||||
if result.get("ok") and result.get("details", {}).get("matching_entries", 0) > 0:
|
||||
matches = result["details"]["results"]
|
||||
# Check for exact match
|
||||
for match in matches:
|
||||
if match["name"] == name:
|
||||
return match
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Error checking duplicate for {name}: {e}")
|
||||
return None
|
||||
|
||||
def parse_description_type(self, description_path: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Determine what type of component is being described
|
||||
|
||||
Args:
|
||||
description_path: Path to description file
|
||||
|
||||
Returns:
|
||||
Dict with component_type and parsed metadata
|
||||
"""
|
||||
path = Path(description_path)
|
||||
content = path.read_text()
|
||||
|
||||
# Try to determine type from content
|
||||
result = {
|
||||
"is_skill": False,
|
||||
"is_command": False,
|
||||
"is_agent": False,
|
||||
"path": str(path)
|
||||
}
|
||||
|
||||
content_lower = content.lower()
|
||||
|
||||
# Check for skill indicators
|
||||
if any(x in content_lower for x in ["# produces artifacts:", "# consumes artifacts:",
|
||||
"skill.yaml", "artifact_metadata"]):
|
||||
result["is_skill"] = True
|
||||
|
||||
# Check for command indicators
|
||||
if any(x in content_lower for x in ["# execution type:", "# parameters:",
|
||||
"command manifest"]):
|
||||
result["is_command"] = True
|
||||
|
||||
# Check for agent indicators
|
||||
if any(x in content_lower for x in ["# skills:", "skills_available",
|
||||
"agent purpose", "multi-step", "orchestrat"]):
|
||||
result["is_agent"] = True
|
||||
|
||||
# If ambiguous, look at explicit markers
|
||||
if "# type: skill" in content_lower:
|
||||
result["is_skill"] = True
|
||||
result["is_command"] = False
|
||||
result["is_agent"] = False
|
||||
elif "# type: command" in content_lower:
|
||||
result["is_command"] = True
|
||||
result["is_skill"] = False
|
||||
result["is_agent"] = False
|
||||
elif "# type: agent" in content_lower:
|
||||
result["is_agent"] = True
|
||||
result["is_skill"] = False
|
||||
result["is_command"] = False
|
||||
|
||||
return result
|
||||
|
||||
def create_skill(
|
||||
self,
|
||||
description_path: str,
|
||||
requirement: Optional[RequirementInfo] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Create a skill using meta.skill
|
||||
|
||||
Args:
|
||||
description_path: Path to skill description
|
||||
requirement: Optional requirement info
|
||||
|
||||
Returns:
|
||||
Creation result
|
||||
"""
|
||||
logger.info(f"Creating skill from {description_path}")
|
||||
|
||||
creator = meta_skill.SkillCreator(base_dir=str(self.base_dir))
|
||||
result = creator.create_skill(description_path, requirement=requirement)
|
||||
|
||||
self.created_components.append({
|
||||
"type": "skill",
|
||||
"name": result.get("skill_name"),
|
||||
"files": result.get("created_files", []),
|
||||
"trace_id": result.get("trace_id")
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
def create_command(
|
||||
self,
|
||||
description_path: str,
|
||||
requirement: Optional[RequirementInfo] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Create a command using meta.command
|
||||
|
||||
Args:
|
||||
description_path: Path to command description
|
||||
requirement: Optional requirement info
|
||||
|
||||
Returns:
|
||||
Creation result with complexity analysis
|
||||
"""
|
||||
logger.info(f"Creating command from {description_path}")
|
||||
|
||||
creator = meta_command.CommandCreator(base_dir=str(self.base_dir))
|
||||
result = creator.create_command(description_path, requirement=requirement)
|
||||
|
||||
self.created_components.append({
|
||||
"type": "command",
|
||||
"name": result.get("command_name"),
|
||||
"manifest": result.get("manifest_file"),
|
||||
"analysis": result.get("complexity_analysis"),
|
||||
"trace_id": result.get("trace_id")
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
def create_agent(
|
||||
self,
|
||||
description_path: str,
|
||||
requirement: Optional[RequirementInfo] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Create an agent using meta.agent
|
||||
|
||||
Args:
|
||||
description_path: Path to agent description
|
||||
requirement: Optional requirement info
|
||||
|
||||
Returns:
|
||||
Creation result
|
||||
"""
|
||||
logger.info(f"Creating agent from {description_path}")
|
||||
|
||||
creator = meta_agent.AgentCreator(
|
||||
registry_path=str(self.base_dir / "registry" / "skills.json")
|
||||
)
|
||||
result = creator.create_agent(description_path, requirement=requirement)
|
||||
|
||||
self.created_components.append({
|
||||
"type": "agent",
|
||||
"name": result.get("name"),
|
||||
"files": [result.get("agent_yaml"), result.get("readme")],
|
||||
"skills": result.get("skills", []),
|
||||
"trace_id": result.get("trace_id")
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
def validate_compatibility(self, agent_name: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Validate agent compatibility using meta.compatibility
|
||||
|
||||
Args:
|
||||
agent_name: Name of agent to validate
|
||||
|
||||
Returns:
|
||||
Compatibility analysis
|
||||
"""
|
||||
logger.info(f"Validating compatibility for {agent_name}")
|
||||
|
||||
if not self.compatibility_analyzer:
|
||||
self.compatibility_analyzer = meta_compatibility.CompatibilityAnalyzer(
|
||||
base_dir=str(self.base_dir)
|
||||
)
|
||||
self.compatibility_analyzer.scan_agents()
|
||||
self.compatibility_analyzer.build_compatibility_map()
|
||||
|
||||
return self.compatibility_analyzer.analyze_agent(agent_name)
|
||||
|
||||
def orchestrate_creation(
|
||||
self,
|
||||
description_path: str,
|
||||
auto_fill_gaps: bool = False,
|
||||
check_duplicates: bool = True,
|
||||
requirement: Optional[RequirementInfo] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Main orchestration method that intelligently creates components
|
||||
|
||||
Args:
|
||||
description_path: Path to description file
|
||||
auto_fill_gaps: Whether to automatically create missing dependencies
|
||||
check_duplicates: Whether to check for existing components
|
||||
requirement: Optional requirement info for traceability
|
||||
|
||||
Returns:
|
||||
Comprehensive creation report
|
||||
"""
|
||||
print(f"🎯 meta.create - Orchestrating component creation from {description_path}\n")
|
||||
|
||||
report = {
|
||||
"ok": True,
|
||||
"description_path": description_path,
|
||||
"component_type": None,
|
||||
"created_components": [],
|
||||
"skipped_components": [],
|
||||
"compatibility_analysis": None,
|
||||
"gaps": [],
|
||||
"recommendations": [],
|
||||
"errors": []
|
||||
}
|
||||
|
||||
try:
|
||||
# Step 1: Determine what's being described
|
||||
print("📋 Step 1: Analyzing description...")
|
||||
desc_type = self.parse_description_type(description_path)
|
||||
print(f" Detected types: Skill={desc_type['is_skill']}, "
|
||||
f"Command={desc_type['is_command']}, Agent={desc_type['is_agent']}\n")
|
||||
|
||||
# Step 2: Check for duplicates if requested
|
||||
if check_duplicates:
|
||||
print("🔍 Step 2: Checking for existing components...")
|
||||
|
||||
# Parse name from description
|
||||
content = Path(description_path).read_text()
|
||||
name_match = None
|
||||
for line in content.split('\n'):
|
||||
if line.strip().startswith('# Name:'):
|
||||
name_match = line.replace('# Name:', '').strip()
|
||||
break
|
||||
|
||||
if name_match:
|
||||
# Check all registries
|
||||
for comp_type in ['skills', 'commands', 'agents']:
|
||||
existing = self.check_duplicate(comp_type, name_match)
|
||||
if existing:
|
||||
print(f" ⚠️ Found existing {comp_type[:-1]}: {name_match}")
|
||||
report["skipped_components"].append({
|
||||
"type": comp_type[:-1],
|
||||
"name": name_match,
|
||||
"reason": "Already exists",
|
||||
"existing": existing
|
||||
})
|
||||
|
||||
if not report["skipped_components"]:
|
||||
print(" ✅ No duplicates found\n")
|
||||
else:
|
||||
print()
|
||||
|
||||
# Step 3: Create components based on type
|
||||
print("🛠️ Step 3: Creating components...\n")
|
||||
|
||||
# If it's a command, analyze complexity first
|
||||
if desc_type["is_command"]:
|
||||
print(" 📊 Analyzing command complexity...")
|
||||
creator = meta_command.CommandCreator(base_dir=str(self.base_dir))
|
||||
|
||||
# Read content for analysis
|
||||
with open(description_path) as f:
|
||||
full_content = f.read()
|
||||
|
||||
cmd_desc = creator.parse_description(description_path)
|
||||
analysis = creator.analyze_complexity(cmd_desc, full_content)
|
||||
|
||||
print(f" Recommended pattern: {analysis['recommended_pattern']}")
|
||||
print(f" Should create skill: {analysis['should_create_skill']}\n")
|
||||
|
||||
# Update desc_type based on analysis
|
||||
if analysis['should_create_skill']:
|
||||
desc_type['is_skill'] = True
|
||||
|
||||
# Create skill first if needed
|
||||
if desc_type["is_skill"]:
|
||||
print(" 🔧 Creating skill...")
|
||||
skill_result = self.create_skill(description_path, requirement)
|
||||
|
||||
if skill_result.get("errors"):
|
||||
report["errors"].extend(skill_result["errors"])
|
||||
print(f" ⚠️ Skill creation had warnings\n")
|
||||
else:
|
||||
print(f" ✅ Skill '{skill_result['skill_name']}' created\n")
|
||||
report["created_components"].append({
|
||||
"type": "skill",
|
||||
"name": skill_result["skill_name"],
|
||||
"files": skill_result.get("created_files", [])
|
||||
})
|
||||
|
||||
# Create command if needed
|
||||
if desc_type["is_command"]:
|
||||
print(" 📜 Creating command...")
|
||||
command_result = self.create_command(description_path, requirement)
|
||||
|
||||
if command_result.get("ok"):
|
||||
print(f" ✅ Command '{command_result['command_name']}' created\n")
|
||||
report["created_components"].append({
|
||||
"type": "command",
|
||||
"name": command_result["command_name"],
|
||||
"manifest": command_result.get("manifest_file"),
|
||||
"pattern": command_result.get("complexity_analysis", {}).get("recommended_pattern")
|
||||
})
|
||||
else:
|
||||
report["errors"].append(f"Command creation failed: {command_result.get('error')}")
|
||||
print(f" ❌ Command creation failed\n")
|
||||
|
||||
# Create agent if needed
|
||||
if desc_type["is_agent"]:
|
||||
print(" 🤖 Creating agent...")
|
||||
agent_result = self.create_agent(description_path, requirement)
|
||||
|
||||
print(f" ✅ Agent '{agent_result['name']}' created")
|
||||
print(f" Skills: {', '.join(agent_result.get('skills', []))}\n")
|
||||
|
||||
report["created_components"].append({
|
||||
"type": "agent",
|
||||
"name": agent_result["name"],
|
||||
"files": [agent_result.get("agent_yaml"), agent_result.get("readme")],
|
||||
"skills": agent_result.get("skills", [])
|
||||
})
|
||||
|
||||
# Step 4: Validate compatibility for agents
|
||||
print("🔬 Step 4: Validating compatibility...\n")
|
||||
compatibility = self.validate_compatibility(agent_result["name"])
|
||||
|
||||
if "error" not in compatibility:
|
||||
report["compatibility_analysis"] = compatibility
|
||||
|
||||
# Check for gaps
|
||||
gaps = compatibility.get("gaps", [])
|
||||
if gaps:
|
||||
print(f" ⚠️ Found {len(gaps)} gap(s):")
|
||||
for gap in gaps:
|
||||
print(f" • {gap['artifact']}: {gap['issue']}")
|
||||
report["gaps"].append(gap)
|
||||
print()
|
||||
|
||||
# Add recommendations
|
||||
for gap in gaps:
|
||||
report["recommendations"].append(
|
||||
f"Create skill to produce '{gap['artifact']}' artifact"
|
||||
)
|
||||
else:
|
||||
print(" ✅ No compatibility gaps found\n")
|
||||
|
||||
# Show compatible agents
|
||||
if compatibility.get("can_feed_to"):
|
||||
print(f" ➡️ Can feed to {len(compatibility['can_feed_to'])} agent(s)")
|
||||
if compatibility.get("can_receive_from"):
|
||||
print(f" ⬅️ Can receive from {len(compatibility['can_receive_from'])} agent(s)")
|
||||
print()
|
||||
|
||||
# Step 5: Auto-fill gaps if requested
|
||||
if auto_fill_gaps and report["gaps"]:
|
||||
print("🔧 Step 5: Auto-filling gaps...\n")
|
||||
for gap in report["gaps"]:
|
||||
print(f" TODO: Auto-create skill for '{gap['artifact']}'")
|
||||
# TODO: Implement auto-gap-filling
|
||||
print()
|
||||
|
||||
# Final summary
|
||||
print("=" * 80)
|
||||
print("✨ CREATION SUMMARY")
|
||||
print("=" * 80)
|
||||
|
||||
if report["created_components"]:
|
||||
print(f"\n✅ Created {len(report['created_components'])} component(s):")
|
||||
for comp in report["created_components"]:
|
||||
print(f" • {comp['type'].upper()}: {comp['name']}")
|
||||
|
||||
if report["skipped_components"]:
|
||||
print(f"\n⏭️ Skipped {len(report['skipped_components'])} component(s) (already exist):")
|
||||
for comp in report["skipped_components"]:
|
||||
print(f" • {comp['type'].upper()}: {comp['name']}")
|
||||
|
||||
if report["gaps"]:
|
||||
print(f"\n⚠️ Found {len(report['gaps'])} compatibility gap(s)")
|
||||
|
||||
if report["recommendations"]:
|
||||
print("\n💡 Recommendations:")
|
||||
for rec in report["recommendations"]:
|
||||
print(f" • {rec}")
|
||||
|
||||
print("\n" + "=" * 80 + "\n")
|
||||
|
||||
return report
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error during orchestration: {e}", exc_info=True)
|
||||
report["ok"] = False
|
||||
report["errors"].append(str(e))
|
||||
print(f"\n❌ Error: {e}\n")
|
||||
return report
|
||||
|
||||
|
||||
def main():
|
||||
"""CLI entry point"""
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="meta.create - Intelligent component creation orchestrator"
|
||||
)
|
||||
parser.add_argument(
|
||||
"description",
|
||||
help="Path to component description file (.md or .json)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--auto-fill-gaps",
|
||||
action="store_true",
|
||||
help="Automatically create missing dependencies"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--skip-duplicate-check",
|
||||
action="store_true",
|
||||
help="Skip checking for existing components"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output-format",
|
||||
choices=["json", "yaml", "text"],
|
||||
default="text",
|
||||
help="Output format for final report"
|
||||
)
|
||||
|
||||
# Traceability arguments
|
||||
parser.add_argument(
|
||||
"--requirement-id",
|
||||
help="Requirement identifier (e.g., REQ-2025-001)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--requirement-description",
|
||||
help="What this component accomplishes"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--requirement-source",
|
||||
help="Source document"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--issue-id",
|
||||
help="Issue tracking ID (e.g., JIRA-123)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--requested-by",
|
||||
help="Who requested this"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--rationale",
|
||||
help="Why this is needed"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Create requirement info if provided
|
||||
requirement = None
|
||||
if args.requirement_id and args.requirement_description:
|
||||
requirement = RequirementInfo(
|
||||
id=args.requirement_id,
|
||||
description=args.requirement_description,
|
||||
source=args.requirement_source,
|
||||
issue_id=args.issue_id,
|
||||
requested_by=args.requested_by,
|
||||
rationale=args.rationale
|
||||
)
|
||||
|
||||
orchestrator = ComponentCreator()
|
||||
result = orchestrator.orchestrate_creation(
|
||||
description_path=args.description,
|
||||
auto_fill_gaps=args.auto_fill_gaps,
|
||||
check_duplicates=not args.skip_duplicate_check,
|
||||
requirement=requirement
|
||||
)
|
||||
|
||||
# Output final report in requested format
|
||||
if args.output_format == "json":
|
||||
print(json.dumps(result, indent=2))
|
||||
elif args.output_format == "yaml":
|
||||
print(yaml.dump(result, default_flow_style=False))
|
||||
|
||||
sys.exit(0 if result.get("ok") else 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user