Files
kaizen-agentic/src/kaizen_agentic/cli.py
tegwick da6eee7d47 Fix all flake8 violations across the codebase
CODE STYLE FIXES:
- Fixed line length violations by breaking long lines appropriately
- Removed unused imports (os from installer.py and registry.py)
- Removed unused variables (package_name in _create_pyproject_toml)
- Fixed f-string usage (removed f-strings without placeholders)
- Fixed import organization and removed redundant imports
- Added missing newlines at end of files

SPECIFIC FIXES:
- cli.py: Split long option line, fixed f-string usage, added newline
- installer.py: Removed unused imports/variables, fixed line breaks, improved validation logic
- registry.py: Removed unused import/variable, broke long condition line
- test files: Removed unused imports, fixed long assertion lines, added newlines

All 24 tests still pass and flake8 now reports no violations.
Code is now compliant with PEP 8 style guidelines.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-19 08:15:42 +02:00

357 lines
12 KiB
Python

"""Command-line interface for Kaizen Agentic agent management."""
import sys
import click
from pathlib import Path
from typing import List, Optional
from .registry import AgentRegistry, AgentCategory
from .installer import AgentInstaller, ProjectInitializer, InstallationConfig
@click.group()
@click.version_option()
def cli():
"""Kaizen Agentic - AI agent development framework."""
pass
@cli.command()
@click.option('--category',
type=click.Choice([c.value for c in AgentCategory]),
help='Filter by category')
@click.option('--verbose', '-v', is_flag=True, help='Show detailed information')
def list(category: Optional[str], verbose: bool):
"""List available agents."""
registry = _get_registry()
if category:
cat_enum = AgentCategory(category)
agents = registry.list_agents(cat_enum)
click.echo(f"\n{category.replace('-', ' ').title()} Agents:")
click.echo("=" * 40)
else:
if verbose:
categories = registry.get_categories()
for cat, agents in categories.items():
click.echo(f"\n{cat.value.replace('-', ' ').title()} ({len(agents)} agents):")
click.echo("=" * 50)
for agent in agents:
click.echo(f"{agent.name}: {agent.description}")
return
else:
agents = registry.list_agents()
click.echo(f"\nAvailable Agents ({len(agents)} total):")
click.echo("=" * 40)
for agent in agents:
if verbose:
click.echo(f"\n{agent.name}")
click.echo(f" Description: {agent.description}")
click.echo(f" Category: {agent.category.value}")
if agent.dependencies:
click.echo(f" Dependencies: {', '.join(agent.dependencies)}")
else:
click.echo(f"{agent.name}: {agent.description}")
@cli.command()
@click.argument('agents', nargs=-1, required=True)
@click.option('--target', '-t', default='.', help='Target directory (default: current)')
@click.option('--no-backup', is_flag=True, help='Skip creating backup')
@click.option('--no-docs', is_flag=True, help='Skip updating documentation')
def install(agents: List[str], target: str, no_backup: bool, no_docs: bool):
"""Install agents into a project."""
registry = _get_registry()
installer = AgentInstaller(registry)
target_path = Path(target).resolve()
config = InstallationConfig(
target_dir=target_path,
claude_config_path=target_path / "CLAUDE.md",
makefile_path=target_path / "Makefile",
update_docs=not no_docs,
create_backup=not no_backup
)
click.echo(f"Installing agents to: {target_path}")
# Resolve and show dependencies
resolved = registry.resolve_dependencies(list(agents))
if len(resolved) > len(agents):
additional = [a for a in resolved if a not in agents]
click.echo(f"Including dependencies: {', '.join(additional)}")
results = installer.install_agents(resolved, config)
# Display results
success_count = 0
for agent_name, status in results.items():
if status == "INSTALLED":
click.echo(f"{agent_name}")
success_count += 1
else:
click.echo(f"{agent_name}: {status}")
click.echo(f"\nInstalled {success_count}/{len(results)} agents successfully")
@cli.command()
@click.option('--target', '-t', default='.', help='Target directory (default: current)')
@click.argument('agents', nargs=-1)
def update(target: str, agents: List[str]):
"""Update installed agents."""
registry = _get_registry()
installer = AgentInstaller(registry)
target_path = Path(target).resolve()
if not agents:
agents = installer.list_installed_agents(target_path)
if not agents:
click.echo("No agents installed in this project")
return
click.echo(f"Updating all installed agents: {', '.join(agents)}")
else:
click.echo(f"Updating specific agents: {', '.join(agents)}")
results = installer.update_agents(target_path, list(agents))
# Display results
success_count = 0
for agent_name, status in results.items():
if status == "INSTALLED":
click.echo(f"{agent_name}")
success_count += 1
else:
click.echo(f"{agent_name}: {status}")
click.echo(f"\nUpdated {success_count}/{len(results)} agents successfully")
@cli.command()
@click.argument('agents', nargs=-1, required=True)
@click.option('--target', '-t', default='.', help='Target directory (default: current)')
def remove(agents: List[str], target: str):
"""Remove agents from a project."""
registry = _get_registry()
installer = AgentInstaller(registry)
target_path = Path(target).resolve()
click.echo(f"Removing agents from: {target_path}")
results = installer.remove_agents(list(agents), target_path)
# Display results
for agent_name, status in results.items():
if status == "REMOVED":
click.echo(f"{agent_name}")
elif status == "NOT_FOUND":
click.echo(f" ⚠️ {agent_name}: Not installed")
else:
click.echo(f"{agent_name}: {status}")
@cli.command()
@click.argument('project_name')
@click.option('--template', '-t', default='python-basic',
help='Project template (python-basic, python-web, python-cli, python-data)')
@click.option('--agents', '-a', help='Comma-separated list of agents to install')
@click.option('--parent-dir', default='.', help='Parent directory for project (default: current)')
def init(project_name: str, template: str, agents: Optional[str], parent_dir: str):
"""Initialize a new project with agents."""
registry = _get_registry()
initializer = ProjectInitializer(registry)
project_path = Path(parent_dir) / project_name
if project_path.exists():
click.echo(f"Error: Directory {project_path} already exists")
sys.exit(1)
# Parse agent list
agent_list = None
if agents:
agent_list = [a.strip() for a in agents.split(',')]
click.echo(f"Initializing project: {project_name}")
click.echo(f"Template: {template}")
# Show available templates
templates = registry.get_agent_templates()
if template not in templates:
click.echo(f"Error: Unknown template '{template}'")
click.echo(f"Available templates: {', '.join(templates.keys())}")
sys.exit(1)
if not agent_list:
agent_list = templates[template]
click.echo(f"Using template agents: {', '.join(agent_list)}")
else:
click.echo(f"Using custom agents: {', '.join(agent_list)}")
results = initializer.init_project(project_path, template, agent_list, project_name)
# Display results
success_count = sum(1 for status in results.values() if status == "INSTALLED")
click.echo(f"\nProject initialized with {success_count}/{len(results)} agents")
click.echo("\nNext steps:")
click.echo(f" cd {project_name}")
click.echo(" make setup-complete # Set up development environment")
click.echo(" make test # Run tests")
@cli.command()
@click.option('--target', '-t', default='.', help='Target directory (default: current)')
def validate(target: str):
"""Validate agents in a project."""
registry = _get_registry()
installer = AgentInstaller(registry)
target_path = Path(target).resolve()
# Validate registry agents
click.echo("Validating agent registry...")
registry_errors = registry.validate_agents()
if registry_errors:
click.echo("Registry validation errors:")
for agent, errors in registry_errors.items():
click.echo(f" {agent}:")
for error in errors:
click.echo(f"{error}")
else:
click.echo(" ✅ Registry validation passed")
# Validate installed agents
click.echo(f"\nValidating installed agents in: {target_path}")
install_errors = installer.validate_installation(target_path)
if install_errors:
click.echo("Installation validation errors:")
for agent, errors in install_errors.items():
click.echo(f" {agent}:")
for error in errors:
click.echo(f"{error}")
else:
click.echo(" ✅ Installation validation passed")
# Show installed agents
installed = installer.list_installed_agents(target_path)
if installed:
click.echo(f"\nInstalled agents ({len(installed)}):")
for agent in installed:
click.echo(f"{agent}")
else:
click.echo("\nNo agents installed in this project")
@cli.command()
def templates():
"""List available project templates."""
registry = _get_registry()
templates = registry.get_agent_templates()
click.echo("Available Project Templates:")
click.echo("=" * 40)
for template_name, agent_list in templates.items():
click.echo(f"\n{template_name}:")
click.echo(f" Agents ({len(agent_list)}): {', '.join(agent_list)}")
@cli.command()
@click.option('--target', '-t', default='.', help='Target directory (default: current)')
def status(target: str):
"""Show status of agents in a project."""
registry = _get_registry()
installer = AgentInstaller(registry)
target_path = Path(target).resolve()
click.echo(f"Project: {target_path.name}")
click.echo(f"Path: {target_path}")
click.echo("=" * 50)
# Check if agents directory exists
agents_dir = target_path / "agents"
if not agents_dir.exists():
click.echo("❌ No agents directory found")
click.echo("\nRun 'kaizen-agentic init' to initialize a new project")
click.echo("or 'kaizen-agentic install <agents>' to add agents")
return
# List installed agents
installed = installer.list_installed_agents(target_path)
if installed:
click.echo(f"✅ Agents installed ({len(installed)}):")
# Group by category
categories = {}
for agent_name in installed:
agent = registry.get_agent(agent_name)
if agent:
cat = agent.category.value
if cat not in categories:
categories[cat] = []
categories[cat].append(agent_name)
else:
if "unknown" not in categories:
categories["unknown"] = []
categories["unknown"].append(agent_name)
for category, agents in categories.items():
click.echo(f"\n {category.replace('-', ' ').title()}:")
for agent in agents:
click.echo(f"{agent}")
else:
click.echo("❌ No agents installed")
# Check for configuration files
click.echo("\nConfiguration files:")
config_files = ["CLAUDE.md", "Makefile", "pyproject.toml", ".gitignore"]
for config_file in config_files:
file_path = target_path / config_file
if file_path.exists():
click.echo(f"{config_file}")
else:
click.echo(f"{config_file}")
def _get_registry() -> AgentRegistry:
"""Get the agent registry."""
# Try to find agents directory
current_dir = Path.cwd()
# Check if we're in a kaizen-agentic project
if (current_dir / "agents").exists():
agents_dir = current_dir / "agents"
elif (current_dir / "src" / "kaizen_agentic").exists():
# We're in the kaizen-agentic repo itself
agents_dir = current_dir / "agents"
else:
# Try to find installed package
try:
import kaizen_agentic
package_dir = Path(kaizen_agentic.__file__).parent.parent.parent
agents_dir = package_dir / "agents"
if not agents_dir.exists():
# Try relative to package
agents_dir = Path(kaizen_agentic.__file__).parent / "data" / "agents"
except ImportError:
click.echo("Error: Could not find agents directory")
click.echo("Make sure you're in a kaizen-agentic project or have the package installed")
sys.exit(1)
if not agents_dir.exists():
click.echo(f"Error: Agents directory not found: {agents_dir}")
sys.exit(1)
return AgentRegistry(agents_dir)
if __name__ == '__main__':
cli()