claude-mpm 4.1.0__py3-none-any.whl → 4.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/BUILD_NUMBER +1 -1
- claude_mpm/VERSION +1 -1
- claude_mpm/__main__.py +1 -1
- claude_mpm/agents/BASE_PM.md +74 -46
- claude_mpm/agents/INSTRUCTIONS.md +11 -153
- claude_mpm/agents/WORKFLOW.md +61 -321
- claude_mpm/agents/__init__.py +11 -11
- claude_mpm/agents/agent_loader.py +23 -20
- claude_mpm/agents/agent_loader_integration.py +1 -1
- claude_mpm/agents/agents_metadata.py +27 -0
- claude_mpm/agents/async_agent_loader.py +5 -8
- claude_mpm/agents/base_agent_loader.py +36 -25
- claude_mpm/agents/frontmatter_validator.py +6 -6
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +9 -9
- claude_mpm/agents/templates/api_qa.json +47 -2
- claude_mpm/agents/templates/imagemagick.json +256 -0
- claude_mpm/agents/templates/qa.json +41 -2
- claude_mpm/agents/templates/ticketing.json +5 -5
- claude_mpm/agents/templates/web_qa.json +133 -58
- claude_mpm/agents/templates/web_ui.json +3 -3
- claude_mpm/cli/__init__.py +51 -46
- claude_mpm/cli/__main__.py +1 -1
- claude_mpm/cli/commands/__init__.py +10 -12
- claude_mpm/cli/commands/agent_manager.py +186 -181
- claude_mpm/cli/commands/agents.py +271 -268
- claude_mpm/cli/commands/aggregate.py +30 -29
- claude_mpm/cli/commands/cleanup.py +50 -44
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
- claude_mpm/cli/commands/config.py +162 -127
- claude_mpm/cli/commands/doctor.py +52 -62
- claude_mpm/cli/commands/info.py +37 -25
- claude_mpm/cli/commands/mcp.py +3 -7
- claude_mpm/cli/commands/mcp_command_router.py +14 -18
- claude_mpm/cli/commands/mcp_install_commands.py +28 -23
- claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
- claude_mpm/cli/commands/mcp_server_commands.py +23 -17
- claude_mpm/cli/commands/memory.py +192 -141
- claude_mpm/cli/commands/monitor.py +117 -88
- claude_mpm/cli/commands/run.py +120 -84
- claude_mpm/cli/commands/run_config_checker.py +4 -5
- claude_mpm/cli/commands/socketio_monitor.py +17 -19
- claude_mpm/cli/commands/tickets.py +92 -92
- claude_mpm/cli/parser.py +1 -5
- claude_mpm/cli/parsers/__init__.py +1 -1
- claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
- claude_mpm/cli/parsers/agents_parser.py +2 -3
- claude_mpm/cli/parsers/base_parser.py +7 -5
- claude_mpm/cli/parsers/mcp_parser.py +4 -2
- claude_mpm/cli/parsers/monitor_parser.py +26 -18
- claude_mpm/cli/shared/__init__.py +10 -10
- claude_mpm/cli/shared/argument_patterns.py +57 -71
- claude_mpm/cli/shared/base_command.py +61 -53
- claude_mpm/cli/shared/error_handling.py +62 -58
- claude_mpm/cli/shared/output_formatters.py +78 -77
- claude_mpm/cli/startup_logging.py +204 -172
- claude_mpm/cli/utils.py +10 -11
- claude_mpm/cli_module/__init__.py +1 -1
- claude_mpm/cli_module/args.py +1 -1
- claude_mpm/cli_module/migration_example.py +5 -5
- claude_mpm/config/__init__.py +9 -9
- claude_mpm/config/agent_config.py +15 -14
- claude_mpm/config/experimental_features.py +4 -4
- claude_mpm/config/paths.py +0 -1
- claude_mpm/config/socketio_config.py +5 -6
- claude_mpm/constants.py +1 -2
- claude_mpm/core/__init__.py +8 -8
- claude_mpm/core/agent_name_normalizer.py +1 -1
- claude_mpm/core/agent_registry.py +20 -23
- claude_mpm/core/agent_session_manager.py +3 -3
- claude_mpm/core/base_service.py +7 -15
- claude_mpm/core/cache.py +4 -6
- claude_mpm/core/claude_runner.py +85 -113
- claude_mpm/core/config.py +43 -28
- claude_mpm/core/config_aliases.py +0 -9
- claude_mpm/core/config_constants.py +52 -30
- claude_mpm/core/constants.py +0 -1
- claude_mpm/core/container.py +18 -27
- claude_mpm/core/exceptions.py +2 -2
- claude_mpm/core/factories.py +10 -12
- claude_mpm/core/framework_loader.py +581 -280
- claude_mpm/core/hook_manager.py +26 -22
- claude_mpm/core/hook_performance_config.py +58 -47
- claude_mpm/core/injectable_service.py +1 -1
- claude_mpm/core/interactive_session.py +61 -152
- claude_mpm/core/interfaces.py +1 -100
- claude_mpm/core/lazy.py +5 -5
- claude_mpm/core/log_manager.py +587 -0
- claude_mpm/core/logger.py +125 -8
- claude_mpm/core/logging_config.py +15 -15
- claude_mpm/core/minimal_framework_loader.py +5 -8
- claude_mpm/core/oneshot_session.py +15 -33
- claude_mpm/core/optimized_agent_loader.py +4 -6
- claude_mpm/core/optimized_startup.py +2 -1
- claude_mpm/core/output_style_manager.py +147 -106
- claude_mpm/core/pm_hook_interceptor.py +0 -1
- claude_mpm/core/service_registry.py +11 -8
- claude_mpm/core/session_manager.py +1 -2
- claude_mpm/core/shared/__init__.py +1 -1
- claude_mpm/core/shared/config_loader.py +101 -97
- claude_mpm/core/shared/path_resolver.py +72 -68
- claude_mpm/core/shared/singleton_manager.py +56 -50
- claude_mpm/core/socketio_pool.py +26 -6
- claude_mpm/core/tool_access_control.py +4 -5
- claude_mpm/core/typing_utils.py +50 -59
- claude_mpm/core/unified_agent_registry.py +14 -19
- claude_mpm/core/unified_config.py +4 -6
- claude_mpm/core/unified_paths.py +197 -109
- claude_mpm/dashboard/open_dashboard.py +2 -4
- claude_mpm/experimental/cli_enhancements.py +51 -36
- claude_mpm/generators/agent_profile_generator.py +2 -4
- claude_mpm/hooks/base_hook.py +1 -2
- claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
- claude_mpm/hooks/claude_hooks/event_handlers.py +93 -38
- claude_mpm/hooks/claude_hooks/hook_handler.py +130 -76
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
- claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
- claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
- claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
- claude_mpm/hooks/memory_integration_hook.py +5 -5
- claude_mpm/hooks/tool_call_interceptor.py +1 -1
- claude_mpm/hooks/validation_hooks.py +4 -4
- claude_mpm/init.py +4 -9
- claude_mpm/models/__init__.py +2 -2
- claude_mpm/models/agent_session.py +11 -14
- claude_mpm/scripts/mcp_server.py +20 -11
- claude_mpm/scripts/mcp_wrapper.py +5 -5
- claude_mpm/scripts/mpm_doctor.py +321 -0
- claude_mpm/scripts/socketio_daemon.py +28 -25
- claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
- claude_mpm/scripts/socketio_server_manager.py +116 -95
- claude_mpm/services/__init__.py +49 -49
- claude_mpm/services/agent_capabilities_service.py +12 -18
- claude_mpm/services/agents/__init__.py +22 -22
- claude_mpm/services/agents/agent_builder.py +140 -119
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
- claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
- claude_mpm/services/agents/deployment/agent_deployment.py +136 -106
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
- claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
- claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
- claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
- claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
- claude_mpm/services/agents/deployment/agent_validator.py +0 -1
- claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
- claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
- claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
- claude_mpm/services/agents/deployment/config/__init__.py +1 -1
- claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
- claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
- claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
- claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
- claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
- claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
- claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
- claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
- claude_mpm/services/agents/deployment/results/__init__.py +1 -1
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
- claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
- claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
- claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
- claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
- claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
- claude_mpm/services/agents/loading/__init__.py +1 -1
- claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
- claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
- claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
- claude_mpm/services/agents/management/__init__.py +1 -1
- claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
- claude_mpm/services/agents/management/agent_management_service.py +5 -9
- claude_mpm/services/agents/memory/__init__.py +4 -4
- claude_mpm/services/agents/memory/agent_memory_manager.py +280 -160
- claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
- claude_mpm/services/agents/memory/content_manager.py +44 -38
- claude_mpm/services/agents/memory/template_generator.py +4 -6
- claude_mpm/services/agents/registry/__init__.py +10 -6
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
- claude_mpm/services/agents/registry/modification_tracker.py +3 -6
- claude_mpm/services/async_session_logger.py +1 -2
- claude_mpm/services/claude_session_logger.py +1 -2
- claude_mpm/services/command_deployment_service.py +173 -0
- claude_mpm/services/command_handler_service.py +20 -22
- claude_mpm/services/core/__init__.py +25 -25
- claude_mpm/services/core/base.py +0 -5
- claude_mpm/services/core/interfaces/__init__.py +32 -32
- claude_mpm/services/core/interfaces/agent.py +0 -21
- claude_mpm/services/core/interfaces/communication.py +0 -27
- claude_mpm/services/core/interfaces/infrastructure.py +0 -56
- claude_mpm/services/core/interfaces/service.py +0 -29
- claude_mpm/services/diagnostics/__init__.py +1 -1
- claude_mpm/services/diagnostics/checks/__init__.py +6 -6
- claude_mpm/services/diagnostics/checks/agent_check.py +89 -80
- claude_mpm/services/diagnostics/checks/base_check.py +12 -16
- claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
- claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
- claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
- claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
- claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
- claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
- claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
- claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
- claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
- claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
- claude_mpm/services/diagnostics/models.py +21 -19
- claude_mpm/services/event_aggregator.py +10 -17
- claude_mpm/services/event_bus/__init__.py +1 -1
- claude_mpm/services/event_bus/config.py +54 -35
- claude_mpm/services/event_bus/event_bus.py +76 -71
- claude_mpm/services/event_bus/relay.py +74 -64
- claude_mpm/services/events/__init__.py +11 -11
- claude_mpm/services/events/consumers/__init__.py +3 -3
- claude_mpm/services/events/consumers/dead_letter.py +71 -63
- claude_mpm/services/events/consumers/logging.py +39 -37
- claude_mpm/services/events/consumers/metrics.py +56 -57
- claude_mpm/services/events/consumers/socketio.py +82 -81
- claude_mpm/services/events/core.py +110 -99
- claude_mpm/services/events/interfaces.py +56 -72
- claude_mpm/services/events/producers/__init__.py +1 -1
- claude_mpm/services/events/producers/hook.py +38 -38
- claude_mpm/services/events/producers/system.py +46 -44
- claude_mpm/services/exceptions.py +81 -80
- claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
- claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
- claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
- claude_mpm/services/hook_service.py +6 -9
- claude_mpm/services/infrastructure/__init__.py +1 -1
- claude_mpm/services/infrastructure/context_preservation.py +8 -12
- claude_mpm/services/infrastructure/monitoring.py +21 -23
- claude_mpm/services/mcp_gateway/__init__.py +37 -37
- claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
- claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
- claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
- claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
- claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
- claude_mpm/services/mcp_gateway/core/base.py +0 -3
- claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
- claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
- claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
- claude_mpm/services/mcp_gateway/main.py +2 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
- claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
- claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
- claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
- claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
- claude_mpm/services/memory/__init__.py +3 -3
- claude_mpm/services/memory/builder.py +3 -6
- claude_mpm/services/memory/cache/__init__.py +1 -1
- claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
- claude_mpm/services/memory/cache/simple_cache.py +1 -1
- claude_mpm/services/memory/indexed_memory.py +5 -7
- claude_mpm/services/memory/optimizer.py +7 -10
- claude_mpm/services/memory/router.py +8 -9
- claude_mpm/services/memory_hook_service.py +48 -34
- claude_mpm/services/monitor_build_service.py +77 -73
- claude_mpm/services/port_manager.py +130 -108
- claude_mpm/services/project/analyzer.py +12 -10
- claude_mpm/services/project/registry.py +11 -11
- claude_mpm/services/recovery_manager.py +10 -19
- claude_mpm/services/response_tracker.py +0 -1
- claude_mpm/services/runner_configuration_service.py +19 -20
- claude_mpm/services/session_management_service.py +7 -11
- claude_mpm/services/shared/__init__.py +1 -1
- claude_mpm/services/shared/async_service_base.py +58 -50
- claude_mpm/services/shared/config_service_base.py +73 -67
- claude_mpm/services/shared/lifecycle_service_base.py +82 -78
- claude_mpm/services/shared/manager_base.py +94 -82
- claude_mpm/services/shared/service_factory.py +96 -98
- claude_mpm/services/socketio/__init__.py +3 -3
- claude_mpm/services/socketio/client_proxy.py +5 -5
- claude_mpm/services/socketio/event_normalizer.py +199 -181
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +5 -4
- claude_mpm/services/socketio/handlers/connection.py +163 -136
- claude_mpm/services/socketio/handlers/file.py +13 -14
- claude_mpm/services/socketio/handlers/git.py +12 -7
- claude_mpm/services/socketio/handlers/hook.py +49 -44
- claude_mpm/services/socketio/handlers/memory.py +0 -1
- claude_mpm/services/socketio/handlers/project.py +0 -1
- claude_mpm/services/socketio/handlers/registry.py +37 -19
- claude_mpm/services/socketio/migration_utils.py +98 -84
- claude_mpm/services/socketio/server/__init__.py +1 -1
- claude_mpm/services/socketio/server/broadcaster.py +81 -87
- claude_mpm/services/socketio/server/core.py +65 -54
- claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
- claude_mpm/services/socketio/server/main.py +64 -38
- claude_mpm/services/socketio_client_manager.py +10 -12
- claude_mpm/services/subprocess_launcher_service.py +4 -7
- claude_mpm/services/system_instructions_service.py +13 -14
- claude_mpm/services/ticket_manager.py +2 -2
- claude_mpm/services/utility_service.py +5 -13
- claude_mpm/services/version_control/__init__.py +16 -16
- claude_mpm/services/version_control/branch_strategy.py +5 -8
- claude_mpm/services/version_control/conflict_resolution.py +9 -23
- claude_mpm/services/version_control/git_operations.py +5 -7
- claude_mpm/services/version_control/semantic_versioning.py +16 -17
- claude_mpm/services/version_control/version_parser.py +13 -18
- claude_mpm/services/version_service.py +10 -11
- claude_mpm/storage/__init__.py +1 -1
- claude_mpm/storage/state_storage.py +22 -28
- claude_mpm/utils/__init__.py +6 -6
- claude_mpm/utils/agent_dependency_loader.py +47 -33
- claude_mpm/utils/config_manager.py +11 -14
- claude_mpm/utils/dependency_cache.py +1 -1
- claude_mpm/utils/dependency_manager.py +13 -17
- claude_mpm/utils/dependency_strategies.py +8 -10
- claude_mpm/utils/environment_context.py +3 -9
- claude_mpm/utils/error_handler.py +3 -13
- claude_mpm/utils/file_utils.py +1 -1
- claude_mpm/utils/path_operations.py +8 -12
- claude_mpm/utils/robust_installer.py +110 -33
- claude_mpm/utils/subprocess_utils.py +5 -6
- claude_mpm/validation/agent_validator.py +3 -6
- claude_mpm/validation/frontmatter_validator.py +1 -1
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/METADATA +1 -1
- claude_mpm-4.1.2.dist-info/RECORD +498 -0
- claude_mpm-4.1.0.dist-info/RECORD +0 -494
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
|
@@ -9,84 +9,79 @@ This module provides CLI interface for:
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
import json
|
|
12
|
-
import os
|
|
13
12
|
import shutil
|
|
14
13
|
import sys
|
|
15
14
|
from pathlib import Path
|
|
16
15
|
from typing import Any, Dict, List, Optional
|
|
17
16
|
|
|
18
|
-
from ...core.config import Config
|
|
19
17
|
from ...core.logging_config import get_logger
|
|
20
18
|
from ...services.agents.agent_builder import AgentBuilderService
|
|
21
19
|
from ...services.agents.deployment.agent_deployment import AgentDeploymentService
|
|
22
|
-
from ..shared import AgentCommand, CommandResult
|
|
20
|
+
from ..shared import AgentCommand, CommandResult
|
|
23
21
|
|
|
24
22
|
|
|
25
23
|
class AgentManagerCommand(AgentCommand):
|
|
26
24
|
"""Agent Manager command for comprehensive agent management."""
|
|
27
|
-
|
|
25
|
+
|
|
28
26
|
def __init__(self):
|
|
29
27
|
super().__init__("agent-manager")
|
|
30
28
|
self.builder_service = AgentBuilderService()
|
|
31
29
|
self.deployment_service = None
|
|
32
30
|
self.logger = get_logger(__name__)
|
|
33
|
-
|
|
31
|
+
|
|
34
32
|
@property
|
|
35
33
|
def deployment(self):
|
|
36
34
|
"""Lazy load deployment service."""
|
|
37
35
|
if self.deployment_service is None:
|
|
38
36
|
self.deployment_service = AgentDeploymentService()
|
|
39
37
|
return self.deployment_service
|
|
40
|
-
|
|
38
|
+
|
|
41
39
|
def run(self, args) -> CommandResult:
|
|
42
40
|
"""Execute agent manager command.
|
|
43
|
-
|
|
41
|
+
|
|
44
42
|
Args:
|
|
45
43
|
args: Command arguments
|
|
46
|
-
|
|
44
|
+
|
|
47
45
|
Returns:
|
|
48
46
|
CommandResult with operation status
|
|
49
47
|
"""
|
|
50
|
-
if not hasattr(args,
|
|
48
|
+
if not hasattr(args, "agent_manager_command"):
|
|
51
49
|
return self._show_help()
|
|
52
|
-
|
|
50
|
+
|
|
53
51
|
command_map = {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
"list": self._list_agents,
|
|
53
|
+
"create": self._create_agent,
|
|
54
|
+
"variant": self._create_variant,
|
|
55
|
+
"deploy": self._deploy_agent,
|
|
56
|
+
"customize-pm": self._customize_pm,
|
|
57
|
+
"show": self._show_agent,
|
|
58
|
+
"test": self._test_agent,
|
|
59
|
+
"templates": self._list_templates,
|
|
62
60
|
}
|
|
63
|
-
|
|
61
|
+
|
|
64
62
|
command = args.agent_manager_command
|
|
65
63
|
if command in command_map:
|
|
66
64
|
return command_map[command](args)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
return CommandResult.error_result(f"Unknown command: {command}")
|
|
66
|
+
|
|
70
67
|
def _list_agents(self, args) -> CommandResult:
|
|
71
68
|
"""List all agents across tiers with hierarchy.
|
|
72
|
-
|
|
69
|
+
|
|
73
70
|
Shows agents from:
|
|
74
71
|
1. Project level (.claude/agents/)
|
|
75
72
|
2. User level (~/.claude/agents/)
|
|
76
73
|
3. System level (framework)
|
|
77
74
|
"""
|
|
78
|
-
agents = {
|
|
79
|
-
|
|
80
|
-
"user": [],
|
|
81
|
-
"system": []
|
|
82
|
-
}
|
|
83
|
-
|
|
75
|
+
agents = {"project": [], "user": [], "system": []}
|
|
76
|
+
|
|
84
77
|
# Check project level
|
|
85
78
|
project_dir = Path.cwd() / ".claude" / "agents"
|
|
86
79
|
if project_dir.exists():
|
|
87
80
|
for agent_file in project_dir.glob("*.yaml"):
|
|
88
|
-
agents["project"].append(
|
|
89
|
-
|
|
81
|
+
agents["project"].append(
|
|
82
|
+
self._read_agent_summary(agent_file, "project")
|
|
83
|
+
)
|
|
84
|
+
|
|
90
85
|
# Check user level
|
|
91
86
|
user_dir = Path.home() / ".claude" / "agents"
|
|
92
87
|
if user_dir.exists():
|
|
@@ -95,263 +90,271 @@ class AgentManagerCommand(AgentCommand):
|
|
|
95
90
|
# Skip if overridden by project
|
|
96
91
|
if not any(a["id"] == agent_id for a in agents["project"]):
|
|
97
92
|
agents["user"].append(self._read_agent_summary(agent_file, "user"))
|
|
98
|
-
|
|
93
|
+
|
|
99
94
|
# Get system agents
|
|
100
95
|
templates = self.builder_service.list_available_templates()
|
|
101
96
|
for template in templates:
|
|
102
97
|
agent_id = template["id"]
|
|
103
98
|
# Skip if overridden by project or user
|
|
104
99
|
if not any(a["id"] == agent_id for a in agents["project"] + agents["user"]):
|
|
105
|
-
agents["system"].append(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
100
|
+
agents["system"].append(
|
|
101
|
+
{
|
|
102
|
+
"id": agent_id,
|
|
103
|
+
"name": template["name"],
|
|
104
|
+
"tier": "system",
|
|
105
|
+
"description": template["description"],
|
|
106
|
+
"category": template.get("category", "custom"),
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
|
|
113
110
|
# Format output
|
|
114
|
-
output_format = getattr(args,
|
|
111
|
+
output_format = getattr(args, "format", "text")
|
|
115
112
|
if output_format == "json":
|
|
116
113
|
return CommandResult.success_result("Agents listed", data=agents)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
114
|
+
output = self._format_agent_list(agents)
|
|
115
|
+
return CommandResult.success_result(output)
|
|
116
|
+
|
|
121
117
|
def _create_agent(self, args) -> CommandResult:
|
|
122
118
|
"""Create a new agent interactively or from arguments."""
|
|
123
119
|
try:
|
|
124
120
|
# Interactive mode if no arguments
|
|
125
|
-
if not hasattr(args,
|
|
121
|
+
if not hasattr(args, "agent_id"):
|
|
126
122
|
return self._interactive_create()
|
|
127
|
-
|
|
123
|
+
|
|
128
124
|
# Create from arguments
|
|
129
125
|
config, instructions = self.builder_service.create_agent(
|
|
130
126
|
agent_id=args.agent_id,
|
|
131
|
-
name=getattr(args,
|
|
132
|
-
description=getattr(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
127
|
+
name=getattr(args, "name", args.agent_id),
|
|
128
|
+
description=getattr(
|
|
129
|
+
args, "description", f"Custom agent {args.agent_id}"
|
|
130
|
+
),
|
|
131
|
+
model=getattr(args, "model", "sonnet"),
|
|
132
|
+
tool_choice=getattr(args, "tool_choice", "auto"),
|
|
133
|
+
base_template=getattr(args, "template", None),
|
|
136
134
|
)
|
|
137
|
-
|
|
135
|
+
|
|
138
136
|
# Save agent files
|
|
139
137
|
result = self._save_agent(config, instructions, args.agent_id)
|
|
140
|
-
|
|
138
|
+
|
|
141
139
|
if result:
|
|
142
|
-
return CommandResult.success_result(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
140
|
+
return CommandResult.success_result(
|
|
141
|
+
f"Agent '{args.agent_id}' created successfully"
|
|
142
|
+
)
|
|
143
|
+
return CommandResult.error_result("Failed to save agent files")
|
|
144
|
+
|
|
146
145
|
except Exception as e:
|
|
147
146
|
return CommandResult.error_result(f"Failed to create agent: {e}")
|
|
148
|
-
|
|
147
|
+
|
|
149
148
|
def _create_variant(self, args) -> CommandResult:
|
|
150
149
|
"""Create an agent variant."""
|
|
151
150
|
try:
|
|
152
|
-
if not hasattr(args,
|
|
153
|
-
return CommandResult.error_result(
|
|
154
|
-
|
|
151
|
+
if not hasattr(args, "base_agent"):
|
|
152
|
+
return CommandResult.error_result(
|
|
153
|
+
"Base agent ID required for variant creation"
|
|
154
|
+
)
|
|
155
|
+
|
|
155
156
|
modifications = {}
|
|
156
|
-
if hasattr(args,
|
|
157
|
-
modifications[
|
|
158
|
-
if hasattr(args,
|
|
159
|
-
modifications[
|
|
160
|
-
|
|
157
|
+
if hasattr(args, "model"):
|
|
158
|
+
modifications["model"] = args.model
|
|
159
|
+
if hasattr(args, "tool_choice"):
|
|
160
|
+
modifications["tool_choice"] = args.tool_choice
|
|
161
|
+
|
|
161
162
|
config, instructions = self.builder_service.create_variant(
|
|
162
163
|
base_agent_id=args.base_agent,
|
|
163
164
|
variant_id=args.variant_id,
|
|
164
|
-
variant_name=getattr(args,
|
|
165
|
+
variant_name=getattr(args, "name", f"{args.base_agent}-variant"),
|
|
165
166
|
modifications=modifications,
|
|
166
|
-
instructions_append=getattr(args,
|
|
167
|
+
instructions_append=getattr(args, "instructions", None),
|
|
167
168
|
)
|
|
168
|
-
|
|
169
|
+
|
|
169
170
|
# Save variant
|
|
170
171
|
result = self._save_agent(config, instructions, args.variant_id)
|
|
171
|
-
|
|
172
|
+
|
|
172
173
|
if result:
|
|
173
|
-
return CommandResult.success_result(
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
return CommandResult.success_result(
|
|
175
|
+
f"Variant '{args.variant_id}' created successfully"
|
|
176
|
+
)
|
|
177
|
+
return CommandResult.error_result("Failed to save variant files")
|
|
178
|
+
|
|
177
179
|
except Exception as e:
|
|
178
180
|
return CommandResult.error_result(f"Failed to create variant: {e}")
|
|
179
|
-
|
|
181
|
+
|
|
180
182
|
def _deploy_agent(self, args) -> CommandResult:
|
|
181
183
|
"""Deploy an agent to specified tier."""
|
|
182
184
|
try:
|
|
183
185
|
agent_id = args.agent_id
|
|
184
|
-
tier = getattr(
|
|
185
|
-
|
|
186
|
+
tier = getattr(
|
|
187
|
+
args, "tier", "project"
|
|
188
|
+
) # Default to project (changed from 'user')
|
|
189
|
+
|
|
186
190
|
# Always deploy to project directory
|
|
187
191
|
# Regardless of tier, all agents go to project .claude/agents
|
|
188
192
|
deploy_path = Path.cwd() / ".claude" / "agents"
|
|
189
|
-
|
|
193
|
+
|
|
190
194
|
# Note: We're keeping the tier parameter for backward compatibility
|
|
191
195
|
# but it no longer affects the deployment location
|
|
192
|
-
if tier not in [
|
|
193
|
-
return CommandResult.error_result(
|
|
194
|
-
|
|
196
|
+
if tier not in ["project", "user"]:
|
|
197
|
+
return CommandResult.error_result(
|
|
198
|
+
"Invalid tier. Use 'project' or 'user'"
|
|
199
|
+
)
|
|
200
|
+
|
|
195
201
|
# Create directory if needed
|
|
196
202
|
deploy_path.mkdir(parents=True, exist_ok=True)
|
|
197
|
-
|
|
203
|
+
|
|
198
204
|
# Find agent files
|
|
199
205
|
template_dir = Path(__file__).parent.parent.parent / "agents" / "templates"
|
|
200
206
|
json_file = template_dir / f"{agent_id}.json"
|
|
201
|
-
|
|
202
|
-
|
|
207
|
+
template_dir / f"{agent_id}.md"
|
|
208
|
+
|
|
203
209
|
if not json_file.exists():
|
|
204
210
|
return CommandResult.error_result(f"Agent '{agent_id}' not found")
|
|
205
|
-
|
|
211
|
+
|
|
206
212
|
# Deploy using deployment service
|
|
207
213
|
# Pass Path object, not string
|
|
208
214
|
self.deployment.deploy_agent(agent_id, deploy_path)
|
|
209
|
-
|
|
215
|
+
|
|
210
216
|
return CommandResult.success_result(
|
|
211
217
|
f"Agent '{agent_id}' deployed to {tier} level"
|
|
212
218
|
)
|
|
213
|
-
|
|
219
|
+
|
|
214
220
|
except Exception as e:
|
|
215
221
|
return CommandResult.error_result(f"Deployment failed: {e}")
|
|
216
|
-
|
|
222
|
+
|
|
217
223
|
def _customize_pm(self, args) -> CommandResult:
|
|
218
224
|
"""Customize PM instructions via .claude-mpm/INSTRUCTIONS.md."""
|
|
219
225
|
try:
|
|
220
|
-
level = getattr(args,
|
|
221
|
-
|
|
226
|
+
level = getattr(args, "level", "user")
|
|
227
|
+
|
|
222
228
|
# Use .claude-mpm/INSTRUCTIONS.md for customization
|
|
223
|
-
if level ==
|
|
229
|
+
if level == "user":
|
|
224
230
|
pm_file = Path.home() / ".claude-mpm" / "INSTRUCTIONS.md"
|
|
225
|
-
elif level ==
|
|
231
|
+
elif level == "project":
|
|
226
232
|
pm_file = Path.cwd() / ".claude-mpm" / "INSTRUCTIONS.md"
|
|
227
233
|
else:
|
|
228
|
-
return CommandResult.error_result(
|
|
229
|
-
|
|
234
|
+
return CommandResult.error_result(
|
|
235
|
+
"Invalid level. Use 'user' or 'project'"
|
|
236
|
+
)
|
|
237
|
+
|
|
230
238
|
# Create backup if file exists
|
|
231
239
|
if pm_file.exists():
|
|
232
|
-
backup_file = pm_file.with_suffix(
|
|
240
|
+
backup_file = pm_file.with_suffix(".md.backup")
|
|
233
241
|
shutil.copy(pm_file, backup_file)
|
|
234
242
|
self.logger.info(f"Backup created: {backup_file}")
|
|
235
|
-
|
|
243
|
+
|
|
236
244
|
# Generate or load instructions
|
|
237
|
-
if hasattr(args,
|
|
245
|
+
if hasattr(args, "template"):
|
|
238
246
|
instructions = self._load_pm_template(args.template)
|
|
239
247
|
else:
|
|
240
248
|
instructions = self.builder_service.generate_pm_instructions(
|
|
241
|
-
delegation_patterns=getattr(args,
|
|
242
|
-
workflow_overrides=getattr(args,
|
|
243
|
-
custom_rules=getattr(args,
|
|
249
|
+
delegation_patterns=getattr(args, "patterns", None),
|
|
250
|
+
workflow_overrides=getattr(args, "workflows", None),
|
|
251
|
+
custom_rules=getattr(args, "rules", None),
|
|
244
252
|
)
|
|
245
|
-
|
|
253
|
+
|
|
246
254
|
# Save instructions to .claude-mpm directory
|
|
247
255
|
pm_file.parent.mkdir(parents=True, exist_ok=True)
|
|
248
256
|
pm_file.write_text(instructions)
|
|
249
|
-
|
|
257
|
+
|
|
250
258
|
return CommandResult.success_result(
|
|
251
259
|
f"PM instructions customized at {level} level: {pm_file}\n"
|
|
252
260
|
f"Note: These instructions will be loaded by the framework loader."
|
|
253
261
|
)
|
|
254
|
-
|
|
262
|
+
|
|
255
263
|
except Exception as e:
|
|
256
264
|
return CommandResult.error_result(f"Failed to customize PM: {e}")
|
|
257
|
-
|
|
265
|
+
|
|
258
266
|
def _show_agent(self, args) -> CommandResult:
|
|
259
267
|
"""Show detailed agent information."""
|
|
260
268
|
try:
|
|
261
269
|
agent_id = args.agent_id
|
|
262
|
-
|
|
270
|
+
|
|
263
271
|
# Find agent across tiers
|
|
264
272
|
agent_info = self._find_agent(agent_id)
|
|
265
|
-
|
|
273
|
+
|
|
266
274
|
if not agent_info:
|
|
267
275
|
return CommandResult.error_result(f"Agent '{agent_id}' not found")
|
|
268
|
-
|
|
269
|
-
output_format = getattr(args,
|
|
276
|
+
|
|
277
|
+
output_format = getattr(args, "format", "text")
|
|
270
278
|
if output_format == "json":
|
|
271
279
|
return CommandResult.success_result("Agent details", data=agent_info)
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
280
|
+
output = self._format_agent_details(agent_info)
|
|
281
|
+
return CommandResult.success_result(output)
|
|
282
|
+
|
|
276
283
|
except Exception as e:
|
|
277
284
|
return CommandResult.error_result(f"Failed to show agent: {e}")
|
|
278
|
-
|
|
285
|
+
|
|
279
286
|
def _test_agent(self, args) -> CommandResult:
|
|
280
287
|
"""Test agent configuration."""
|
|
281
288
|
try:
|
|
282
289
|
agent_id = args.agent_id
|
|
283
|
-
|
|
290
|
+
|
|
284
291
|
# Find agent configuration
|
|
285
292
|
config = self._load_agent_config(agent_id)
|
|
286
|
-
|
|
293
|
+
|
|
287
294
|
if not config:
|
|
288
295
|
return CommandResult.error_result(f"Agent '{agent_id}' not found")
|
|
289
|
-
|
|
296
|
+
|
|
290
297
|
# Validate configuration
|
|
291
298
|
errors = self.builder_service.validate_configuration(config)
|
|
292
|
-
|
|
299
|
+
|
|
293
300
|
if errors:
|
|
294
301
|
return CommandResult.error_result(
|
|
295
|
-
|
|
302
|
+
"Validation failed:\n" + "\n".join(f" - {e}" for e in errors)
|
|
296
303
|
)
|
|
297
|
-
|
|
304
|
+
|
|
298
305
|
# Check for conflicts
|
|
299
306
|
conflicts = self._check_conflicts(agent_id)
|
|
300
|
-
|
|
301
|
-
if conflicts
|
|
302
|
-
|
|
303
|
-
else:
|
|
304
|
-
warning = ""
|
|
305
|
-
|
|
307
|
+
|
|
308
|
+
warning = f"Warning: Agent overrides {conflicts}" if conflicts else ""
|
|
309
|
+
|
|
306
310
|
return CommandResult.success_result(
|
|
307
311
|
f"Agent '{agent_id}' configuration is valid. {warning}"
|
|
308
312
|
)
|
|
309
|
-
|
|
313
|
+
|
|
310
314
|
except Exception as e:
|
|
311
315
|
return CommandResult.error_result(f"Test failed: {e}")
|
|
312
|
-
|
|
316
|
+
|
|
313
317
|
def _list_templates(self, args) -> CommandResult:
|
|
314
318
|
"""List available agent templates."""
|
|
315
319
|
templates = self.builder_service.list_available_templates()
|
|
316
|
-
|
|
317
|
-
output_format = getattr(args,
|
|
320
|
+
|
|
321
|
+
output_format = getattr(args, "format", "text")
|
|
318
322
|
if output_format == "json":
|
|
319
323
|
return CommandResult.success_result("Templates listed", data=templates)
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
324
|
+
output = "Available Agent Templates:\n\n"
|
|
325
|
+
for template in templates:
|
|
326
|
+
template_id = template.get("id", "unknown")
|
|
327
|
+
template_name = template.get("name", "Unnamed")
|
|
328
|
+
output += f" {template_id:<20} - {template_name}\n"
|
|
329
|
+
if template.get("description"):
|
|
330
|
+
output += f" {template['description']}\n"
|
|
331
|
+
return CommandResult.success_result(output)
|
|
332
|
+
|
|
330
333
|
def _interactive_create(self) -> CommandResult:
|
|
331
334
|
"""Interactive agent creation wizard."""
|
|
332
335
|
print("\n=== Agent Creation Wizard ===\n")
|
|
333
|
-
|
|
336
|
+
|
|
334
337
|
# Get agent ID
|
|
335
338
|
agent_id = input("Agent ID (lowercase, hyphens only): ").strip()
|
|
336
339
|
if not agent_id:
|
|
337
340
|
return CommandResult.error_result("Agent ID is required")
|
|
338
|
-
|
|
341
|
+
|
|
339
342
|
# Get name
|
|
340
343
|
name = input(f"Display name [{agent_id}]: ").strip() or agent_id
|
|
341
|
-
|
|
344
|
+
|
|
342
345
|
# Get description
|
|
343
346
|
description = input("Description: ").strip()
|
|
344
347
|
if not description:
|
|
345
348
|
return CommandResult.error_result("Description is required")
|
|
346
|
-
|
|
349
|
+
|
|
347
350
|
# Get model
|
|
348
351
|
print("\nAvailable models: sonnet, opus, haiku")
|
|
349
352
|
model = input("Model [sonnet]: ").strip() or "sonnet"
|
|
350
|
-
|
|
353
|
+
|
|
351
354
|
# Get tool choice
|
|
352
355
|
print("\nTool choices: auto, required, any, none")
|
|
353
356
|
tool_choice = input("Tool choice [auto]: ").strip() or "auto"
|
|
354
|
-
|
|
357
|
+
|
|
355
358
|
# Create agent
|
|
356
359
|
try:
|
|
357
360
|
config, instructions = self.builder_service.create_agent(
|
|
@@ -359,49 +362,52 @@ class AgentManagerCommand(AgentCommand):
|
|
|
359
362
|
name=name,
|
|
360
363
|
description=description,
|
|
361
364
|
model=model,
|
|
362
|
-
tool_choice=tool_choice
|
|
365
|
+
tool_choice=tool_choice,
|
|
363
366
|
)
|
|
364
|
-
|
|
367
|
+
|
|
365
368
|
# Save agent
|
|
366
369
|
if self._save_agent(config, instructions, agent_id):
|
|
367
|
-
return CommandResult.success_result(
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
370
|
+
return CommandResult.success_result(
|
|
371
|
+
f"\nAgent '{agent_id}' created successfully!"
|
|
372
|
+
)
|
|
373
|
+
return CommandResult.error_result("Failed to save agent files")
|
|
374
|
+
|
|
371
375
|
except Exception as e:
|
|
372
376
|
return CommandResult.error_result(f"Creation failed: {e}")
|
|
373
|
-
|
|
374
|
-
def _save_agent(
|
|
377
|
+
|
|
378
|
+
def _save_agent(
|
|
379
|
+
self, config: Dict[str, Any], instructions: str, agent_id: str
|
|
380
|
+
) -> bool:
|
|
375
381
|
"""Save agent configuration and instructions.
|
|
376
|
-
|
|
382
|
+
|
|
377
383
|
Args:
|
|
378
384
|
config: Agent configuration dictionary
|
|
379
385
|
instructions: Agent instructions markdown
|
|
380
386
|
agent_id: Agent identifier
|
|
381
|
-
|
|
387
|
+
|
|
382
388
|
Returns:
|
|
383
389
|
True if saved successfully
|
|
384
390
|
"""
|
|
385
391
|
try:
|
|
386
392
|
template_dir = Path(__file__).parent.parent.parent / "agents" / "templates"
|
|
387
393
|
template_dir.mkdir(parents=True, exist_ok=True)
|
|
388
|
-
|
|
394
|
+
|
|
389
395
|
# Save JSON configuration
|
|
390
396
|
json_file = template_dir / f"{agent_id}.json"
|
|
391
|
-
with open(json_file,
|
|
397
|
+
with open(json_file, "w") as f:
|
|
392
398
|
json.dump(config, f, indent=2)
|
|
393
|
-
|
|
399
|
+
|
|
394
400
|
# Save instructions
|
|
395
401
|
md_file = template_dir / f"{agent_id}.md"
|
|
396
402
|
md_file.write_text(instructions)
|
|
397
|
-
|
|
403
|
+
|
|
398
404
|
self.logger.info(f"Agent saved: {json_file} and {md_file}")
|
|
399
405
|
return True
|
|
400
|
-
|
|
406
|
+
|
|
401
407
|
except Exception as e:
|
|
402
408
|
self.logger.error(f"Failed to save agent: {e}")
|
|
403
409
|
return False
|
|
404
|
-
|
|
410
|
+
|
|
405
411
|
def _read_agent_summary(self, agent_file: Path, tier: str) -> Dict[str, Any]:
|
|
406
412
|
"""Read agent summary from file."""
|
|
407
413
|
try:
|
|
@@ -411,68 +417,68 @@ class AgentManagerCommand(AgentCommand):
|
|
|
411
417
|
"id": agent_id,
|
|
412
418
|
"name": agent_id.replace("-", " ").title(),
|
|
413
419
|
"tier": tier,
|
|
414
|
-
"file": str(agent_file)
|
|
420
|
+
"file": str(agent_file),
|
|
415
421
|
}
|
|
416
422
|
except Exception:
|
|
417
423
|
return {}
|
|
418
|
-
|
|
424
|
+
|
|
419
425
|
def _format_agent_list(self, agents: Dict[str, List]) -> str:
|
|
420
426
|
"""Format agent list for display."""
|
|
421
427
|
output = "=== Agent Hierarchy ===\n\n"
|
|
422
|
-
|
|
428
|
+
|
|
423
429
|
# Project agents
|
|
424
430
|
if agents["project"]:
|
|
425
431
|
output += "[P] PROJECT LEVEL (Highest Priority)\n"
|
|
426
432
|
for agent in agents["project"]:
|
|
427
433
|
output += f" {agent['id']:<20} - {agent.get('name', agent['id'])}\n"
|
|
428
434
|
output += "\n"
|
|
429
|
-
|
|
435
|
+
|
|
430
436
|
# User agents
|
|
431
437
|
if agents["user"]:
|
|
432
438
|
output += "[U] USER LEVEL\n"
|
|
433
439
|
for agent in agents["user"]:
|
|
434
440
|
output += f" {agent['id']:<20} - {agent.get('name', agent['id'])}\n"
|
|
435
441
|
output += "\n"
|
|
436
|
-
|
|
442
|
+
|
|
437
443
|
# System agents
|
|
438
444
|
if agents["system"]:
|
|
439
445
|
output += "[S] SYSTEM LEVEL (Framework Defaults)\n"
|
|
440
446
|
for agent in agents["system"]:
|
|
441
447
|
output += f" {agent['id']:<20} - {agent.get('name', agent['id'])}\n"
|
|
442
|
-
|
|
448
|
+
|
|
443
449
|
return output
|
|
444
|
-
|
|
450
|
+
|
|
445
451
|
def _find_agent(self, agent_id: str) -> Optional[Dict[str, Any]]:
|
|
446
452
|
"""Find agent across all tiers."""
|
|
447
453
|
# Implementation would search across tiers
|
|
448
454
|
# This is a simplified version
|
|
449
455
|
return {"id": agent_id, "tier": "system"}
|
|
450
|
-
|
|
456
|
+
|
|
451
457
|
def _load_agent_config(self, agent_id: str) -> Optional[Dict[str, Any]]:
|
|
452
458
|
"""Load agent configuration."""
|
|
453
459
|
try:
|
|
454
460
|
return self.builder_service._load_template(agent_id)
|
|
455
461
|
except:
|
|
456
462
|
return None
|
|
457
|
-
|
|
463
|
+
|
|
458
464
|
def _check_conflicts(self, agent_id: str) -> Optional[str]:
|
|
459
465
|
"""Check for agent conflicts across tiers."""
|
|
460
466
|
# Check if agent exists in multiple tiers
|
|
461
467
|
# Return tier information if conflicts exist
|
|
462
468
|
return None
|
|
463
|
-
|
|
469
|
+
|
|
464
470
|
def _format_agent_details(self, agent_info: Dict[str, Any]) -> str:
|
|
465
471
|
"""Format agent details for display."""
|
|
466
472
|
output = f"=== Agent: {agent_info['id']} ===\n\n"
|
|
467
473
|
for key, value in agent_info.items():
|
|
468
474
|
output += f"{key}: {value}\n"
|
|
469
475
|
return output
|
|
470
|
-
|
|
476
|
+
|
|
471
477
|
def _load_pm_template(self, template_name: str) -> str:
|
|
472
478
|
"""Load PM instruction template."""
|
|
473
479
|
# Load predefined PM templates
|
|
474
480
|
return "# PM Instructions Template\n"
|
|
475
|
-
|
|
481
|
+
|
|
476
482
|
def _show_help(self) -> CommandResult:
|
|
477
483
|
"""Show help for agent manager."""
|
|
478
484
|
help_text = """
|
|
@@ -503,21 +509,20 @@ Note: PM customization writes to .claude-mpm/INSTRUCTIONS.md, not CLAUDE.md
|
|
|
503
509
|
# Module-level function for CLI integration
|
|
504
510
|
def manage_agent_manager(args) -> int:
|
|
505
511
|
"""Entry point for agent-manager command from CLI.
|
|
506
|
-
|
|
512
|
+
|
|
507
513
|
Args:
|
|
508
514
|
args: Parsed command line arguments
|
|
509
|
-
|
|
515
|
+
|
|
510
516
|
Returns:
|
|
511
517
|
Exit code (0 for success, non-zero for failure)
|
|
512
518
|
"""
|
|
513
519
|
command = AgentManagerCommand()
|
|
514
520
|
result = command.run(args)
|
|
515
|
-
|
|
521
|
+
|
|
516
522
|
if result.success:
|
|
517
523
|
if result.message:
|
|
518
524
|
print(result.message)
|
|
519
525
|
return 0
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
return 1
|
|
526
|
+
if result.message:
|
|
527
|
+
print(f"Error: {result.message}", file=sys.stderr)
|
|
528
|
+
return 1
|