Implement complete Scenario 2: Integration with existing projects having agents
Built comprehensive system for introducing Kaizen agents to existing projects: 🔍 **Detection System (detection.py)**: - Detects 9+ types of existing agent systems (Kaizen, Claude Code, custom agents, etc.) - Analyzes agent files with YAML frontmatter parsing - Identifies conflicts and functional overlaps - Generates integration strategies and migration recommendations 🔄 **Migration Framework (migration.py)**: - Creates detailed migration plans for each detected agent - Supports 5 migration strategies: replace, extend, preserve, merge, remove - Intelligent conflict resolution with multiple resolution types - Safe execution with backup creation and rollback capability 🔗 **Extension System (extensions.py)**: - Project-specific agent customizations and extensions - Multiple extension types: config overlay, functional extension, workflow integration - Template generation for basic and advanced extensions - Legacy agent integration with wrapper creation 🛠️ **CLI Integration**: - `kaizen-agentic detect` - Analyze existing agent systems - `kaizen-agentic migrate` - Execute migration plans with dry-run support - `kaizen-agentic extensions` - Complete extension management commands 📖 **Integration Patterns Documentation**: - 5 proven integration scenarios with detailed patterns - Conflict resolution strategies and decision matrices - Safe transition strategies with phased rollout - Best practices and troubleshooting guides **Key Features**: ✅ Respects existing project structure and workflows ✅ Safe transitions with comprehensive backup strategies ✅ Conflict detection and automated resolution ✅ Extension mechanisms for preserving custom functionality ✅ Comprehensive tooling for all transition scenarios Scenario 2 is now production-ready for integrating Kaizen agents into any existing project! 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -320,6 +320,281 @@ def status(target: str):
|
||||
click.echo(f" ❌ {config_file}")
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option('--target', '-t', default='.', help='Target directory (default: current)')
|
||||
@click.option('--detailed', '-d', is_flag=True, help='Show detailed analysis')
|
||||
def detect(target: str, detailed: bool):
|
||||
"""Detect existing agent systems in a project."""
|
||||
from .detection import AgentSystemDetector
|
||||
|
||||
target_path = Path(target).resolve()
|
||||
|
||||
if not target_path.exists():
|
||||
click.echo(f"Error: Directory not found: {target_path}")
|
||||
sys.exit(1)
|
||||
|
||||
click.echo(f"Detecting agent systems in: {target_path}")
|
||||
click.echo("=" * 50)
|
||||
|
||||
detector = AgentSystemDetector()
|
||||
result = detector.detect_agent_systems(target_path)
|
||||
|
||||
# Show detected systems
|
||||
if result.detected_systems:
|
||||
click.echo(f"\n🔍 Detected Agent Systems ({len(result.detected_systems)}):")
|
||||
for system in result.detected_systems:
|
||||
click.echo(f" • {system.value}")
|
||||
else:
|
||||
click.echo("\n🔍 No existing agent systems detected")
|
||||
|
||||
# Show detected agents
|
||||
if result.agents:
|
||||
click.echo(f"\n🤖 Detected Agents ({len(result.agents)}):")
|
||||
for agent in result.agents:
|
||||
status = "✅" if agent.can_migrate else "⚠️"
|
||||
click.echo(f" {status} {agent.name} ({agent.type.value})")
|
||||
if detailed and agent.description:
|
||||
click.echo(f" {agent.description}")
|
||||
if not agent.can_migrate and agent.migration_notes:
|
||||
click.echo(f" Note: {agent.migration_notes}")
|
||||
|
||||
# Show config files
|
||||
if result.config_files:
|
||||
click.echo(f"\n📄 Configuration Files ({len(result.config_files)}):")
|
||||
for config_file in result.config_files:
|
||||
click.echo(f" • {config_file.relative_to(target_path)}")
|
||||
|
||||
# Show conflicts
|
||||
if result.conflicts:
|
||||
click.echo(f"\n⚠️ Potential Conflicts ({len(result.conflicts)}):")
|
||||
for agent1, agent2, reason in result.conflicts:
|
||||
click.echo(f" • {agent1} vs {agent2}: {reason}")
|
||||
|
||||
# Show integration strategy
|
||||
if result.integration_strategy:
|
||||
click.echo(f"\n💡 Recommended Integration Strategy: {result.integration_strategy}")
|
||||
|
||||
# Show migration recommendations
|
||||
if result.migration_recommendations:
|
||||
click.echo(f"\n📋 Migration Recommendations:")
|
||||
for recommendation in result.migration_recommendations:
|
||||
if recommendation.startswith(" "):
|
||||
click.echo(f" {recommendation}")
|
||||
else:
|
||||
click.echo(f" • {recommendation}")
|
||||
|
||||
if not result.detected_systems:
|
||||
click.echo(f"\n✨ This project is ready for Kaizen Agentic installation!")
|
||||
click.echo(f" Run: kaizen-agentic install <agent-names>")
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option('--target', '-t', default='.', help='Target directory (default: current)')
|
||||
@click.option('--dry-run', '-n', is_flag=True, help='Show what would be done without executing')
|
||||
@click.option('--auto-resolve', '-a', is_flag=True, help='Automatically resolve simple conflicts')
|
||||
def migrate(target: str, dry_run: bool, auto_resolve: bool):
|
||||
"""Create migration plan for integrating Kaizen agents into existing project."""
|
||||
from .migration import AgentMigrationPlanner, AgentMigrator
|
||||
|
||||
target_path = Path(target).resolve()
|
||||
|
||||
if not target_path.exists():
|
||||
click.echo(f"Error: Directory not found: {target_path}")
|
||||
sys.exit(1)
|
||||
|
||||
click.echo(f"Creating migration plan for: {target_path}")
|
||||
click.echo("=" * 50)
|
||||
|
||||
planner = AgentMigrationPlanner()
|
||||
integration_plan = planner.create_integration_plan(target_path)
|
||||
|
||||
if not integration_plan.migration_plans and not integration_plan.conflict_resolutions:
|
||||
click.echo("✨ No migration needed - project is ready for Kaizen agents!")
|
||||
click.echo(" Run: kaizen-agentic install <agent-names>")
|
||||
return
|
||||
|
||||
# Show migration plans
|
||||
if integration_plan.migration_plans:
|
||||
click.echo(f"\n🔄 Migration Plans ({len(integration_plan.migration_plans)}):")
|
||||
for plan in integration_plan.migration_plans:
|
||||
strategy_emoji = {
|
||||
"replace": "🔄", "extend": "🔗", "preserve": "💾",
|
||||
"merge": "🔀", "remove": "🗑️"
|
||||
}
|
||||
emoji = strategy_emoji.get(plan.strategy.value, "❓")
|
||||
|
||||
click.echo(f" {emoji} {plan.source_agent.name} ({plan.source_agent.type.value})")
|
||||
click.echo(f" Strategy: {plan.strategy.value}")
|
||||
if plan.target_agent:
|
||||
click.echo(f" Target: {plan.target_agent}")
|
||||
|
||||
for note in plan.migration_notes:
|
||||
click.echo(f" 📝 {note}")
|
||||
|
||||
# Show conflict resolutions
|
||||
if integration_plan.conflict_resolutions:
|
||||
click.echo(f"\n⚠️ Conflict Resolutions ({len(integration_plan.conflict_resolutions)}):")
|
||||
for resolution in integration_plan.conflict_resolutions:
|
||||
click.echo(f" • {resolution.agent1} vs {resolution.agent2}")
|
||||
click.echo(f" Resolution: {resolution.resolution.value}")
|
||||
if resolution.action_details:
|
||||
for key, value in resolution.action_details.items():
|
||||
click.echo(f" {key}: {value}")
|
||||
|
||||
# Show integration order
|
||||
if integration_plan.integration_order:
|
||||
click.echo(f"\n📋 Integration Order:")
|
||||
for i, agent_name in enumerate(integration_plan.integration_order, 1):
|
||||
click.echo(f" {i}. {agent_name}")
|
||||
|
||||
# Show post-migration tasks
|
||||
if integration_plan.post_migration_tasks:
|
||||
click.echo(f"\n✅ Post-Migration Tasks:")
|
||||
for task in integration_plan.post_migration_tasks:
|
||||
click.echo(f" • {task}")
|
||||
|
||||
# Execute migration if requested
|
||||
if not dry_run:
|
||||
click.echo(f"\n🚀 Executing migration...")
|
||||
migrator = AgentMigrator()
|
||||
results = migrator.execute_migration(integration_plan, dry_run=False)
|
||||
|
||||
click.echo(f"\n📊 Migration Results:")
|
||||
for agent, result in results.items():
|
||||
status_emoji = "✅" if "ERROR" not in result else "❌"
|
||||
click.echo(f" {status_emoji} {agent}: {result}")
|
||||
|
||||
click.echo(f"\n💾 Backup created at: {integration_plan.backup_directory}")
|
||||
else:
|
||||
click.echo(f"\n🔍 This was a dry run. Use --no-dry-run to execute the migration.")
|
||||
click.echo(f" Backup would be created at: {integration_plan.backup_directory}")
|
||||
|
||||
|
||||
@cli.group()
|
||||
def extensions():
|
||||
"""Manage agent extensions."""
|
||||
pass
|
||||
|
||||
|
||||
@extensions.command()
|
||||
@click.option('--target', '-t', default='.', help='Target directory (default: current)')
|
||||
@click.option('--base-agent', '-b', help='Filter by base agent')
|
||||
def list_extensions(target: str, base_agent: Optional[str]):
|
||||
"""List installed extensions."""
|
||||
from .extensions import ExtensionManager
|
||||
|
||||
target_path = Path(target).resolve()
|
||||
manager = ExtensionManager(target_path)
|
||||
|
||||
extensions_list = manager.list_extensions(base_agent)
|
||||
|
||||
if not extensions_list:
|
||||
if base_agent:
|
||||
click.echo(f"No extensions found for agent: {base_agent}")
|
||||
else:
|
||||
click.echo("No extensions installed in this project")
|
||||
return
|
||||
|
||||
click.echo(f"Extensions in {target_path}:")
|
||||
click.echo("=" * 40)
|
||||
|
||||
for ext in extensions_list:
|
||||
status = "✅" if ext.enabled else "❌"
|
||||
click.echo(f"\n{status} {ext.name} (extends {ext.base_agent})")
|
||||
click.echo(f" Type: {ext.extension_type.value}")
|
||||
click.echo(f" Description: {ext.description}")
|
||||
click.echo(f" Version: {ext.version}")
|
||||
|
||||
if ext.custom_commands:
|
||||
click.echo(f" Custom commands: {', '.join(ext.custom_commands.keys())}")
|
||||
|
||||
|
||||
@extensions.command()
|
||||
@click.argument('name')
|
||||
@click.argument('base_agent')
|
||||
@click.option('--target', '-t', default='.', help='Target directory (default: current)')
|
||||
@click.option('--description', '-d', help='Extension description')
|
||||
@click.option('--template', default='basic', help='Template type (basic, advanced)')
|
||||
def create(name: str, base_agent: str, target: str, description: Optional[str], template: str):
|
||||
"""Create a new agent extension."""
|
||||
from .extensions import ExtensionManager, ExtensionType, create_extension_template
|
||||
|
||||
target_path = Path(target).resolve()
|
||||
manager = ExtensionManager(target_path)
|
||||
|
||||
# Generate template
|
||||
template_content = create_extension_template(name, base_agent, target_path, template)
|
||||
|
||||
# Save template to file
|
||||
template_dir = target_path / ".kaizen" / "extensions" / name
|
||||
template_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
template_file = template_dir / "template.md"
|
||||
template_file.write_text(template_content)
|
||||
|
||||
# Create basic extension
|
||||
manager.create_extension(
|
||||
name=name,
|
||||
base_agent=base_agent,
|
||||
extension_type=ExtensionType.FUNCTIONAL_EXTENSION,
|
||||
description=description or f"Custom extension for {base_agent}"
|
||||
)
|
||||
|
||||
click.echo(f"✅ Created extension: {name}")
|
||||
click.echo(f" Base agent: {base_agent}")
|
||||
click.echo(f" Template saved to: {template_file}")
|
||||
click.echo(f" Edit the configuration and run: kaizen-agentic extensions enable {name}")
|
||||
|
||||
|
||||
@extensions.command()
|
||||
@click.argument('name')
|
||||
@click.option('--target', '-t', default='.', help='Target directory (default: current)')
|
||||
def enable(name: str, target: str):
|
||||
"""Enable an extension."""
|
||||
from .extensions import ExtensionManager
|
||||
|
||||
target_path = Path(target).resolve()
|
||||
manager = ExtensionManager(target_path)
|
||||
|
||||
if manager.enable_extension(name):
|
||||
click.echo(f"✅ Enabled extension: {name}")
|
||||
else:
|
||||
click.echo(f"❌ Extension not found: {name}")
|
||||
|
||||
|
||||
@extensions.command()
|
||||
@click.argument('name')
|
||||
@click.option('--target', '-t', default='.', help='Target directory (default: current)')
|
||||
def disable(name: str, target: str):
|
||||
"""Disable an extension."""
|
||||
from .extensions import ExtensionManager
|
||||
|
||||
target_path = Path(target).resolve()
|
||||
manager = ExtensionManager(target_path)
|
||||
|
||||
if manager.disable_extension(name):
|
||||
click.echo(f"❌ Disabled extension: {name}")
|
||||
else:
|
||||
click.echo(f"❌ Extension not found: {name}")
|
||||
|
||||
|
||||
@extensions.command()
|
||||
@click.argument('name')
|
||||
@click.option('--target', '-t', default='.', help='Target directory (default: current)')
|
||||
@click.confirmation_option(prompt='Are you sure you want to remove this extension?')
|
||||
def remove(name: str, target: str):
|
||||
"""Remove an extension."""
|
||||
from .extensions import ExtensionManager
|
||||
|
||||
target_path = Path(target).resolve()
|
||||
manager = ExtensionManager(target_path)
|
||||
|
||||
if manager.remove_extension(name):
|
||||
click.echo(f"🗑️ Removed extension: {name}")
|
||||
else:
|
||||
click.echo(f"❌ Extension not found: {name}")
|
||||
|
||||
|
||||
def _get_registry() -> AgentRegistry:
|
||||
"""Get the agent registry."""
|
||||
# Try to find agents directory
|
||||
|
||||
Reference in New Issue
Block a user