claude-mpm 4.1.1__py3-none-any.whl → 4.1.3__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/engineer.json +33 -11
- 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 +50 -2
- 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 +648 -1098
- 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 +339 -967
- claude_mpm/cli/commands/monitor.py +117 -88
- claude_mpm/cli/commands/run.py +233 -542
- 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 +280 -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 +22 -29
- 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 +500 -680
- 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 -17
- 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 +99 -154
- claude_mpm/hooks/claude_hooks/hook_handler.py +110 -720
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
- 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/services/__init__.py +13 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
- claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
- 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 +129 -511
- 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/base_agent_locator.py +132 -0
- 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_results_manager.py +185 -0
- 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/single_agent_deployer.py +315 -0
- 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 +157 -503
- 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/memory_categorization_service.py +165 -0
- claude_mpm/services/agents/memory/memory_file_service.py +103 -0
- claude_mpm/services/agents/memory/memory_format_service.py +201 -0
- claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
- claude_mpm/services/agents/memory/template_generator.py +4 -6
- claude_mpm/services/agents/registry/__init__.py +11 -7
- 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/cli/__init__.py +18 -0
- claude_mpm/services/cli/agent_cleanup_service.py +407 -0
- claude_mpm/services/cli/agent_dependency_service.py +395 -0
- claude_mpm/services/cli/agent_listing_service.py +463 -0
- claude_mpm/services/cli/agent_output_formatter.py +605 -0
- claude_mpm/services/cli/agent_validation_service.py +589 -0
- claude_mpm/services/cli/dashboard_launcher.py +424 -0
- claude_mpm/services/cli/memory_crud_service.py +617 -0
- claude_mpm/services/cli/memory_output_formatter.py +604 -0
- claude_mpm/services/cli/session_manager.py +513 -0
- claude_mpm/services/cli/socketio_manager.py +498 -0
- claude_mpm/services/cli/startup_checker.py +370 -0
- 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/cache_manager.py +311 -0
- 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/core/memory_manager.py +637 -0
- claude_mpm/services/core/path_resolver.py +498 -0
- claude_mpm/services/core/service_container.py +520 -0
- claude_mpm/services/core/service_interfaces.py +436 -0
- 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 +152 -97
- 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.1.dist-info → claude_mpm-4.1.3.dist-info}/METADATA +1 -1
- claude_mpm-4.1.3.dist-info/RECORD +528 -0
- claude_mpm/cli/commands/run_config_checker.py +0 -160
- claude_mpm-4.1.1.dist-info/RECORD +0 -494
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/top_level.txt +0 -0
|
@@ -13,18 +13,14 @@ DESIGN DECISIONS:
|
|
|
13
13
|
|
|
14
14
|
import json
|
|
15
15
|
import os
|
|
16
|
-
from datetime import datetime
|
|
17
16
|
from pathlib import Path
|
|
18
|
-
from typing import
|
|
17
|
+
from typing import Any, Dict
|
|
19
18
|
|
|
20
|
-
import click
|
|
21
|
-
|
|
22
|
-
from ...core.config import Config
|
|
23
|
-
from ...core.logger import get_logger
|
|
24
19
|
from ...core.shared.config_loader import ConfigLoader
|
|
25
20
|
from ...services.agents.memory import AgentMemoryManager
|
|
26
|
-
from
|
|
27
|
-
from
|
|
21
|
+
from ...services.cli.memory_crud_service import MemoryCRUDService
|
|
22
|
+
from ...services.cli.memory_output_formatter import MemoryOutputFormatter
|
|
23
|
+
from ..shared.base_command import CommandResult, MemoryCommand
|
|
28
24
|
|
|
29
25
|
|
|
30
26
|
class MemoryManagementCommand(MemoryCommand):
|
|
@@ -33,6 +29,8 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
33
29
|
def __init__(self):
|
|
34
30
|
super().__init__("memory")
|
|
35
31
|
self._memory_manager = None
|
|
32
|
+
self._formatter = None
|
|
33
|
+
self._crud_service = None
|
|
36
34
|
|
|
37
35
|
@property
|
|
38
36
|
def memory_manager(self):
|
|
@@ -46,11 +44,36 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
46
44
|
self._memory_manager = AgentMemoryManager(config, current_dir)
|
|
47
45
|
return self._memory_manager
|
|
48
46
|
|
|
47
|
+
@property
|
|
48
|
+
def formatter(self):
|
|
49
|
+
"""Get formatter instance (lazy loaded)."""
|
|
50
|
+
if self._formatter is None:
|
|
51
|
+
# Check if quiet mode is requested
|
|
52
|
+
quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
|
|
53
|
+
self._formatter = MemoryOutputFormatter(quiet=quiet)
|
|
54
|
+
return self._formatter
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def crud_service(self):
|
|
58
|
+
"""Get CRUD service instance (lazy loaded)."""
|
|
59
|
+
if self._crud_service is None:
|
|
60
|
+
self._crud_service = MemoryCRUDService(memory_manager=self.memory_manager)
|
|
61
|
+
return self._crud_service
|
|
62
|
+
|
|
49
63
|
def validate_args(self, args) -> str:
|
|
50
64
|
"""Validate command arguments."""
|
|
51
65
|
# Check if memory command is valid
|
|
52
|
-
if hasattr(args,
|
|
53
|
-
valid_commands = [
|
|
66
|
+
if hasattr(args, "memory_command") and args.memory_command:
|
|
67
|
+
valid_commands = [
|
|
68
|
+
"init",
|
|
69
|
+
"view",
|
|
70
|
+
"add",
|
|
71
|
+
"clean",
|
|
72
|
+
"optimize",
|
|
73
|
+
"build",
|
|
74
|
+
"cross-ref",
|
|
75
|
+
"route",
|
|
76
|
+
]
|
|
54
77
|
if args.memory_command not in valid_commands:
|
|
55
78
|
return f"Unknown memory command: {args.memory_command}. Valid commands: {', '.join(valid_commands)}"
|
|
56
79
|
return None
|
|
@@ -59,7 +82,7 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
59
82
|
"""Execute the memory command."""
|
|
60
83
|
try:
|
|
61
84
|
# Handle default case (no subcommand)
|
|
62
|
-
if not hasattr(args,
|
|
85
|
+
if not hasattr(args, "memory_command") or not args.memory_command:
|
|
63
86
|
return self._show_status(args)
|
|
64
87
|
|
|
65
88
|
# Route to specific subcommand handlers
|
|
@@ -78,20 +101,17 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
78
101
|
|
|
79
102
|
if args.memory_command in command_map:
|
|
80
103
|
return command_map[args.memory_command](args)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
error_msg = f"Unknown memory command: {args.memory_command}"
|
|
104
|
+
available_commands = list(command_map.keys())
|
|
105
|
+
error_msg = f"Unknown memory command: {args.memory_command}"
|
|
84
106
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
print(f"Available commands: {', '.join(available_commands)}")
|
|
94
|
-
return CommandResult.error_result(error_msg)
|
|
107
|
+
output_format = getattr(args, "format", "text")
|
|
108
|
+
if output_format in ["json", "yaml"]:
|
|
109
|
+
return CommandResult.error_result(
|
|
110
|
+
error_msg, data={"available_commands": available_commands}
|
|
111
|
+
)
|
|
112
|
+
print(f"❌ {error_msg}")
|
|
113
|
+
print(f"Available commands: {', '.join(available_commands)}")
|
|
114
|
+
return CommandResult.error_result(error_msg)
|
|
95
115
|
|
|
96
116
|
except Exception as e:
|
|
97
117
|
self.logger.error(f"Error managing memory: {e}", exc_info=True)
|
|
@@ -100,16 +120,19 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
100
120
|
def _show_status(self, args) -> CommandResult:
|
|
101
121
|
"""Show memory system status."""
|
|
102
122
|
try:
|
|
103
|
-
output_format = getattr(args,
|
|
123
|
+
output_format = getattr(args, "format", "text")
|
|
104
124
|
|
|
105
|
-
if output_format in [
|
|
125
|
+
if output_format in ["json", "yaml"]:
|
|
106
126
|
# Structured output
|
|
107
127
|
status_data = self._get_status_data()
|
|
108
|
-
return CommandResult.success_result(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
128
|
+
return CommandResult.success_result(
|
|
129
|
+
"Memory status retrieved", data=status_data
|
|
130
|
+
)
|
|
131
|
+
# Text output using formatter
|
|
132
|
+
status = self.memory_manager.get_memory_status()
|
|
133
|
+
output = self.formatter.format_status(status)
|
|
134
|
+
print(output)
|
|
135
|
+
return CommandResult.success_result("Memory status displayed")
|
|
113
136
|
|
|
114
137
|
except Exception as e:
|
|
115
138
|
self.logger.error(f"Error showing memory status: {e}", exc_info=True)
|
|
@@ -117,110 +140,151 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
117
140
|
|
|
118
141
|
def _get_status_data(self) -> Dict[str, Any]:
|
|
119
142
|
"""Get memory status as structured data."""
|
|
120
|
-
|
|
143
|
+
# Use CRUD service to list memories with stats
|
|
144
|
+
result = self.crud_service.list_memories(include_stats=True)
|
|
121
145
|
|
|
122
|
-
if not
|
|
146
|
+
if not result.get("success"):
|
|
123
147
|
return {
|
|
124
|
-
"
|
|
148
|
+
"error": result.get("error", "Failed to get status"),
|
|
125
149
|
"exists": False,
|
|
126
150
|
"agents": [],
|
|
127
151
|
"total_size_kb": 0,
|
|
128
|
-
"total_files": 0
|
|
152
|
+
"total_files": 0,
|
|
129
153
|
}
|
|
130
154
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
"size_kb": size / 1024,
|
|
143
|
-
"path": str(memory_file)
|
|
144
|
-
})
|
|
155
|
+
# Transform CRUD service result to expected format
|
|
156
|
+
memories = result.get("memories", [])
|
|
157
|
+
agents = [
|
|
158
|
+
{
|
|
159
|
+
"agent_id": mem["agent_id"],
|
|
160
|
+
"file": mem["file"],
|
|
161
|
+
"size_kb": mem.get("size_kb", 0),
|
|
162
|
+
"path": mem["path"],
|
|
163
|
+
}
|
|
164
|
+
for mem in memories
|
|
165
|
+
]
|
|
145
166
|
|
|
146
167
|
return {
|
|
147
|
-
"memory_directory":
|
|
148
|
-
"exists":
|
|
168
|
+
"memory_directory": result.get("memory_directory", ""),
|
|
169
|
+
"exists": result.get("exists", False),
|
|
149
170
|
"agents": agents,
|
|
150
|
-
"total_size_kb":
|
|
151
|
-
"total_files":
|
|
171
|
+
"total_size_kb": result.get("total_size_kb", 0),
|
|
172
|
+
"total_files": result.get("total_files", 0),
|
|
152
173
|
}
|
|
153
174
|
|
|
154
175
|
def _show_memories(self, args) -> CommandResult:
|
|
155
176
|
"""Show agent memories."""
|
|
156
177
|
try:
|
|
157
|
-
output_format = getattr(args,
|
|
178
|
+
output_format = getattr(args, "format", "text")
|
|
179
|
+
agent_id = getattr(args, "agent_id", None)
|
|
180
|
+
raw_output = getattr(args, "raw", False)
|
|
158
181
|
|
|
159
|
-
if output_format in [
|
|
160
|
-
#
|
|
161
|
-
|
|
162
|
-
|
|
182
|
+
if output_format in ["json", "yaml"] or raw_output:
|
|
183
|
+
# Use CRUD service for structured output
|
|
184
|
+
result = self.crud_service.read_memory(agent_id)
|
|
185
|
+
|
|
186
|
+
if not result.get("success"):
|
|
187
|
+
return CommandResult.error_result(
|
|
188
|
+
result.get("error", "Failed to read memories")
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
if raw_output:
|
|
192
|
+
# Output raw JSON for external tools
|
|
193
|
+
print(json.dumps(result, indent=2, ensure_ascii=False))
|
|
194
|
+
return CommandResult.success_result("Raw memory data output")
|
|
195
|
+
|
|
196
|
+
return CommandResult.success_result("Memories retrieved", data=result)
|
|
197
|
+
|
|
198
|
+
# Text output
|
|
199
|
+
result = self.crud_service.read_memory(agent_id)
|
|
200
|
+
|
|
201
|
+
if not result.get("success"):
|
|
202
|
+
print(f"❌ {result.get('error', 'Failed to read memories')}")
|
|
203
|
+
return CommandResult.error_result(result.get("error"))
|
|
204
|
+
|
|
205
|
+
print("🧠 Agent Memories Display")
|
|
206
|
+
print("-" * 80)
|
|
207
|
+
|
|
208
|
+
if agent_id:
|
|
209
|
+
# Single agent memory
|
|
210
|
+
content = result.get("content", "")
|
|
211
|
+
if content:
|
|
212
|
+
output = self.formatter.format_memory_view(
|
|
213
|
+
agent_id, content, getattr(args, "format", "detailed")
|
|
214
|
+
)
|
|
215
|
+
print(output)
|
|
216
|
+
else:
|
|
217
|
+
print(f"📭 No memory found for agent: {agent_id}")
|
|
163
218
|
else:
|
|
164
|
-
#
|
|
165
|
-
|
|
166
|
-
|
|
219
|
+
# All agent memories
|
|
220
|
+
agents = result.get("agents", {})
|
|
221
|
+
if agents:
|
|
222
|
+
# Parse and format all memories
|
|
223
|
+
agent_memories = {}
|
|
224
|
+
for aid, data in agents.items():
|
|
225
|
+
sections = self.formatter._parse_memory_content(
|
|
226
|
+
data.get("content", "")
|
|
227
|
+
)
|
|
228
|
+
agent_memories[aid] = sections
|
|
229
|
+
|
|
230
|
+
output = self.formatter.format_agent_memories_summary(
|
|
231
|
+
agent_memories, getattr(args, "format", "detailed")
|
|
232
|
+
)
|
|
233
|
+
print(output)
|
|
234
|
+
else:
|
|
235
|
+
print("📭 No agent memories found")
|
|
236
|
+
|
|
237
|
+
return CommandResult.success_result("Memories displayed")
|
|
167
238
|
|
|
168
239
|
except Exception as e:
|
|
169
240
|
self.logger.error(f"Error showing memories: {e}", exc_info=True)
|
|
170
241
|
return CommandResult.error_result(f"Error showing memories: {e}")
|
|
171
242
|
|
|
172
|
-
|
|
173
|
-
"""Get memories as structured data."""
|
|
174
|
-
agent_id = getattr(args, 'agent', None)
|
|
175
|
-
|
|
176
|
-
if agent_id:
|
|
177
|
-
# Single agent memory
|
|
178
|
-
memory_content = self.memory_manager.load_agent_memory(agent_id)
|
|
179
|
-
return {
|
|
180
|
-
"agent_id": agent_id,
|
|
181
|
-
"memory_content": memory_content,
|
|
182
|
-
"has_memory": bool(memory_content)
|
|
183
|
-
}
|
|
184
|
-
else:
|
|
185
|
-
# All agent memories
|
|
186
|
-
memory_dir = self.memory_manager.memories_dir
|
|
187
|
-
if not memory_dir.exists():
|
|
188
|
-
return {"agents": [], "memory_directory": str(memory_dir), "exists": False}
|
|
189
|
-
|
|
190
|
-
agents = {}
|
|
191
|
-
for memory_file in memory_dir.glob("*.md"):
|
|
192
|
-
if memory_file.is_file():
|
|
193
|
-
agent_id = memory_file.stem
|
|
194
|
-
memory_content = self.memory_manager.load_agent_memory(agent_id)
|
|
195
|
-
agents[agent_id] = {
|
|
196
|
-
"memory_content": memory_content,
|
|
197
|
-
"file_path": str(memory_file)
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
return {
|
|
201
|
-
"agents": agents,
|
|
202
|
-
"memory_directory": str(memory_dir),
|
|
203
|
-
"exists": True,
|
|
204
|
-
"agent_count": len(agents)
|
|
205
|
-
}
|
|
243
|
+
# Removed _get_memories_data - now handled inline with CRUD service
|
|
206
244
|
|
|
207
245
|
def _init_memory(self, args) -> CommandResult:
|
|
208
246
|
"""Initialize project-specific memories."""
|
|
209
247
|
try:
|
|
210
|
-
output_format = getattr(args,
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
"
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
#
|
|
222
|
-
|
|
223
|
-
|
|
248
|
+
output_format = getattr(args, "format", "text")
|
|
249
|
+
|
|
250
|
+
# Use CRUD service for initialization task
|
|
251
|
+
result = self.crud_service.init_project_memories()
|
|
252
|
+
|
|
253
|
+
if not result.get("success"):
|
|
254
|
+
return CommandResult.error_result(
|
|
255
|
+
result.get("error", "Failed to create initialization task")
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
if output_format in ["json", "yaml"]:
|
|
259
|
+
# Return structured task data
|
|
260
|
+
return CommandResult.success_result(
|
|
261
|
+
"Memory initialization task created", data=result.get("task_data")
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
# Text output - display the task
|
|
265
|
+
task = result.get("task_data", {})
|
|
266
|
+
print("🚀 Initializing project-specific memories...")
|
|
267
|
+
print("=" * 80)
|
|
268
|
+
print()
|
|
269
|
+
print("This will analyze the project to:")
|
|
270
|
+
for idx, instruction in enumerate(task.get("instructions", []), 1):
|
|
271
|
+
print(f" {idx}. {instruction}")
|
|
272
|
+
print()
|
|
273
|
+
print("The analysis will cover:")
|
|
274
|
+
for area in task.get("focus_areas", []):
|
|
275
|
+
print(f" • {area}")
|
|
276
|
+
print()
|
|
277
|
+
print("Example commands to use:")
|
|
278
|
+
for cmd in task.get("example_commands", []):
|
|
279
|
+
print(f" {cmd}")
|
|
280
|
+
print()
|
|
281
|
+
print("=" * 80)
|
|
282
|
+
print()
|
|
283
|
+
print(
|
|
284
|
+
"📝 Note: Copy the task above to execute the memory initialization process."
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
return CommandResult.success_result("Memory initialization task displayed")
|
|
224
288
|
|
|
225
289
|
except Exception as e:
|
|
226
290
|
self.logger.error(f"Error initializing memory: {e}", exc_info=True)
|
|
@@ -229,17 +293,38 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
229
293
|
def _add_learning(self, args) -> CommandResult:
|
|
230
294
|
"""Add learning to agent memory."""
|
|
231
295
|
try:
|
|
232
|
-
output_format = getattr(args,
|
|
296
|
+
output_format = getattr(args, "format", "text")
|
|
233
297
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
298
|
+
# Extract arguments
|
|
299
|
+
agent_id = getattr(args, "agent_id", None)
|
|
300
|
+
learning_type = getattr(args, "learning_type", "context")
|
|
301
|
+
content = getattr(args, "content", "")
|
|
302
|
+
|
|
303
|
+
if not agent_id or not content:
|
|
304
|
+
return CommandResult.error_result(
|
|
305
|
+
"Agent ID and content are required for adding learning"
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
# Use CRUD service to add learning
|
|
309
|
+
result = self.crud_service.update_memory(agent_id, learning_type, content)
|
|
310
|
+
|
|
311
|
+
if not result.get("success"):
|
|
312
|
+
return CommandResult.error_result(
|
|
313
|
+
result.get("error", "Failed to add learning")
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
if output_format in ["json", "yaml"]:
|
|
317
|
+
# Return structured result
|
|
318
|
+
return CommandResult.success_result(
|
|
319
|
+
"Learning added to agent memory", data=result
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
# Text output
|
|
323
|
+
print(f"✅ Added {learning_type} to {agent_id} memory")
|
|
324
|
+
print(f" Section: {result.get('section', 'Unknown')}")
|
|
325
|
+
print(f" Content: {result.get('content_preview', content[:100])}")
|
|
326
|
+
|
|
327
|
+
return CommandResult.success_result("Learning added")
|
|
243
328
|
|
|
244
329
|
except Exception as e:
|
|
245
330
|
self.logger.error(f"Error adding learning: {e}", exc_info=True)
|
|
@@ -248,16 +333,49 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
248
333
|
def _clean_memory(self, args) -> CommandResult:
|
|
249
334
|
"""Clean up old/unused memory files."""
|
|
250
335
|
try:
|
|
251
|
-
output_format = getattr(args,
|
|
336
|
+
output_format = getattr(args, "format", "text")
|
|
337
|
+
agent_id = getattr(args, "agent_id", None)
|
|
338
|
+
dry_run = getattr(args, "dry_run", True)
|
|
339
|
+
|
|
340
|
+
# Use CRUD service for cleanup
|
|
341
|
+
result = self.crud_service.clean_memory(agent_id=agent_id, dry_run=dry_run)
|
|
342
|
+
|
|
343
|
+
if not result.get("success"):
|
|
344
|
+
return CommandResult.error_result(result.get("error", "Cleanup failed"))
|
|
252
345
|
|
|
253
|
-
if output_format in [
|
|
254
|
-
#
|
|
255
|
-
|
|
256
|
-
|
|
346
|
+
if output_format in ["json", "yaml"]:
|
|
347
|
+
# Return structured cleanup results
|
|
348
|
+
return CommandResult.success_result(
|
|
349
|
+
result.get("message", "Memory cleanup completed"), data=result
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
# Text output
|
|
353
|
+
print("🧹 Memory cleanup")
|
|
354
|
+
print("-" * 80)
|
|
355
|
+
|
|
356
|
+
if dry_run:
|
|
357
|
+
print("📊 Cleanup preview (dry run)")
|
|
358
|
+
candidates = result.get("cleanup_candidates", [])
|
|
359
|
+
if candidates:
|
|
360
|
+
print(f"Found {len(candidates)} files eligible for cleanup:")
|
|
361
|
+
for candidate in candidates:
|
|
362
|
+
print(
|
|
363
|
+
f" • {candidate['agent_id']}: {candidate['size_kb']:.1f} KB, {candidate['age_days']} days old"
|
|
364
|
+
)
|
|
365
|
+
print(f" Reason: {candidate['reason']}")
|
|
366
|
+
else:
|
|
367
|
+
print("No files eligible for cleanup")
|
|
257
368
|
else:
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
369
|
+
cleaned = result.get("cleaned_files", [])
|
|
370
|
+
if cleaned:
|
|
371
|
+
print(f"Cleaned {len(cleaned)} files")
|
|
372
|
+
else:
|
|
373
|
+
print(result.get("message", "No files cleaned"))
|
|
374
|
+
|
|
375
|
+
if result.get("note"):
|
|
376
|
+
print(f"\n⚠️ {result['note']}")
|
|
377
|
+
|
|
378
|
+
return CommandResult.success_result("Memory cleanup completed")
|
|
261
379
|
|
|
262
380
|
except Exception as e:
|
|
263
381
|
self.logger.error(f"Error cleaning memory: {e}", exc_info=True)
|
|
@@ -266,16 +384,33 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
266
384
|
def _optimize_memory(self, args) -> CommandResult:
|
|
267
385
|
"""Optimize memory files."""
|
|
268
386
|
try:
|
|
269
|
-
output_format = getattr(args,
|
|
387
|
+
output_format = getattr(args, "format", "text")
|
|
388
|
+
agent_id = getattr(args, "agent_id", None)
|
|
270
389
|
|
|
271
|
-
if output_format in [
|
|
272
|
-
# For structured output,
|
|
273
|
-
|
|
274
|
-
|
|
390
|
+
if output_format in ["json", "yaml"]:
|
|
391
|
+
# For structured output, perform optimization and return results
|
|
392
|
+
if agent_id:
|
|
393
|
+
result = self.memory_manager.optimize_memory(agent_id)
|
|
394
|
+
else:
|
|
395
|
+
result = self.memory_manager.optimize_memory()
|
|
396
|
+
return CommandResult.success_result(
|
|
397
|
+
"Memory optimization completed", data=result
|
|
398
|
+
)
|
|
399
|
+
# Text output using formatter
|
|
400
|
+
if agent_id:
|
|
401
|
+
print(f"📊 Optimizing memory for agent: {agent_id}")
|
|
402
|
+
result = self.memory_manager.optimize_memory(agent_id)
|
|
403
|
+
output = self.formatter.format_optimization_results(
|
|
404
|
+
result, is_single_agent=True
|
|
405
|
+
)
|
|
275
406
|
else:
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
407
|
+
print("📊 Optimizing all agent memories...")
|
|
408
|
+
result = self.memory_manager.optimize_memory()
|
|
409
|
+
output = self.formatter.format_optimization_results(
|
|
410
|
+
result, is_single_agent=False
|
|
411
|
+
)
|
|
412
|
+
print(output)
|
|
413
|
+
return CommandResult.success_result("Memory optimization completed")
|
|
279
414
|
|
|
280
415
|
except Exception as e:
|
|
281
416
|
self.logger.error(f"Error optimizing memory: {e}", exc_info=True)
|
|
@@ -284,16 +419,21 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
284
419
|
def _build_memory(self, args) -> CommandResult:
|
|
285
420
|
"""Build agent memories from project documentation."""
|
|
286
421
|
try:
|
|
287
|
-
output_format = getattr(args,
|
|
422
|
+
output_format = getattr(args, "format", "text")
|
|
288
423
|
|
|
289
|
-
if output_format in [
|
|
424
|
+
if output_format in ["json", "yaml"]:
|
|
290
425
|
# For structured output, return build results
|
|
291
|
-
build_data = {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
return CommandResult.success_result(
|
|
426
|
+
build_data = {
|
|
427
|
+
"built_memories": [],
|
|
428
|
+
"processed_files": [],
|
|
429
|
+
"summary": "Memory build completed",
|
|
430
|
+
}
|
|
431
|
+
return CommandResult.success_result(
|
|
432
|
+
"Memory build completed", data=build_data
|
|
433
|
+
)
|
|
434
|
+
# Text output using existing function
|
|
435
|
+
_build_memory(args, self.memory_manager)
|
|
436
|
+
return CommandResult.success_result("Memory build completed")
|
|
297
437
|
|
|
298
438
|
except Exception as e:
|
|
299
439
|
self.logger.error(f"Error building memory: {e}", exc_info=True)
|
|
@@ -302,16 +442,21 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
302
442
|
def _cross_reference_memory(self, args) -> CommandResult:
|
|
303
443
|
"""Find cross-references and common patterns."""
|
|
304
444
|
try:
|
|
305
|
-
output_format = getattr(args,
|
|
445
|
+
output_format = getattr(args, "format", "text")
|
|
306
446
|
|
|
307
|
-
if output_format in [
|
|
447
|
+
if output_format in ["json", "yaml"]:
|
|
308
448
|
# For structured output, return cross-reference results
|
|
309
|
-
crossref_data = {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
return CommandResult.success_result(
|
|
449
|
+
crossref_data = {
|
|
450
|
+
"common_patterns": [],
|
|
451
|
+
"agent_similarities": [],
|
|
452
|
+
"summary": "Cross-reference analysis completed",
|
|
453
|
+
}
|
|
454
|
+
return CommandResult.success_result(
|
|
455
|
+
"Cross-reference analysis completed", data=crossref_data
|
|
456
|
+
)
|
|
457
|
+
# Text output using existing function
|
|
458
|
+
_cross_reference_memory(args, self.memory_manager)
|
|
459
|
+
return CommandResult.success_result("Cross-reference analysis completed")
|
|
315
460
|
|
|
316
461
|
except Exception as e:
|
|
317
462
|
self.logger.error(f"Error cross-referencing memory: {e}", exc_info=True)
|
|
@@ -320,38 +465,27 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
320
465
|
def _route_memory_command(self, args) -> CommandResult:
|
|
321
466
|
"""Route memory command to appropriate agent."""
|
|
322
467
|
try:
|
|
323
|
-
output_format = getattr(args,
|
|
468
|
+
output_format = getattr(args, "format", "text")
|
|
324
469
|
|
|
325
|
-
if output_format in [
|
|
470
|
+
if output_format in ["json", "yaml"]:
|
|
326
471
|
# For structured output, return routing results
|
|
327
|
-
routing_data = {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
return CommandResult.success_result(
|
|
472
|
+
routing_data = {
|
|
473
|
+
"routed_to": "memory_agent",
|
|
474
|
+
"command": getattr(args, "command", ""),
|
|
475
|
+
"summary": "Command routed successfully",
|
|
476
|
+
}
|
|
477
|
+
return CommandResult.success_result(
|
|
478
|
+
"Command routed successfully", data=routing_data
|
|
479
|
+
)
|
|
480
|
+
# Text output using existing function
|
|
481
|
+
_route_memory_command(args, self.memory_manager)
|
|
482
|
+
return CommandResult.success_result("Command routed successfully")
|
|
333
483
|
|
|
334
484
|
except Exception as e:
|
|
335
485
|
self.logger.error(f"Error routing memory command: {e}", exc_info=True)
|
|
336
486
|
return CommandResult.error_result(f"Error routing memory command: {e}")
|
|
337
487
|
|
|
338
488
|
|
|
339
|
-
def manage_memory(args):
|
|
340
|
-
"""
|
|
341
|
-
Main entry point for memory management commands.
|
|
342
|
-
|
|
343
|
-
This function maintains backward compatibility while using the new MemoryCommand pattern.
|
|
344
|
-
"""
|
|
345
|
-
command = MemoryManagementCommand()
|
|
346
|
-
result = command.execute(args)
|
|
347
|
-
|
|
348
|
-
# Print result if structured output format is requested
|
|
349
|
-
if hasattr(args, 'format') and args.format in ['json', 'yaml']:
|
|
350
|
-
command.print_result(result, args)
|
|
351
|
-
|
|
352
|
-
return result.exit_code
|
|
353
|
-
|
|
354
|
-
|
|
355
489
|
def manage_memory(args) -> int:
|
|
356
490
|
"""Main entry point for memory management commands.
|
|
357
491
|
|
|
@@ -361,377 +495,31 @@ def manage_memory(args) -> int:
|
|
|
361
495
|
result = command.execute(args)
|
|
362
496
|
|
|
363
497
|
# Print result if structured output format is requested
|
|
364
|
-
if hasattr(args,
|
|
498
|
+
if hasattr(args, "format") and args.format in ["json", "yaml"]:
|
|
365
499
|
command.print_result(result, args)
|
|
366
500
|
|
|
367
501
|
return result.exit_code
|
|
368
502
|
|
|
369
503
|
|
|
370
|
-
|
|
371
|
-
"""
|
|
372
|
-
Initialize project-specific memories via agent delegation.
|
|
373
|
-
|
|
374
|
-
WHY: When starting with a new project, agents need project-specific knowledge
|
|
375
|
-
beyond what automatic analysis provides. This command triggers an agent task
|
|
376
|
-
to comprehensively scan the project and create custom memories.
|
|
377
|
-
|
|
378
|
-
Args:
|
|
379
|
-
args: Command line arguments (unused but kept for consistency)
|
|
380
|
-
memory_manager: AgentMemoryManager instance
|
|
381
|
-
"""
|
|
382
|
-
logger = get_logger("cli")
|
|
383
|
-
|
|
384
|
-
print("🚀 Initializing project-specific memories...")
|
|
385
|
-
print("=" * 80)
|
|
386
|
-
print()
|
|
387
|
-
print("This will analyze the project to:")
|
|
388
|
-
print(" 1. Scan project structure and documentation")
|
|
389
|
-
print(" 2. Analyze source code for patterns and conventions")
|
|
390
|
-
print(" 3. Create targeted memories for each agent type")
|
|
391
|
-
print(" 4. Add insights using 'claude-mpm memory add' commands")
|
|
392
|
-
print()
|
|
393
|
-
print("The analysis will cover:")
|
|
394
|
-
print(" • Project architecture and design patterns")
|
|
395
|
-
print(" • Coding conventions and standards")
|
|
396
|
-
print(" • Key modules and integration points")
|
|
397
|
-
print(" • Testing patterns and quality standards")
|
|
398
|
-
print(" • Performance considerations")
|
|
399
|
-
print(" • Domain-specific terminology")
|
|
400
|
-
print()
|
|
401
|
-
print("=" * 80)
|
|
402
|
-
print()
|
|
403
|
-
print("[Agent Task: Initialize Project-Specific Memories]")
|
|
404
|
-
print()
|
|
405
|
-
print("Please analyze this project and create custom memories for all agents.")
|
|
406
|
-
print()
|
|
407
|
-
print("Instructions:")
|
|
408
|
-
print("1. Scan the project structure, documentation, and source code")
|
|
409
|
-
print("2. Identify key patterns, conventions, and project-specific knowledge")
|
|
410
|
-
print("3. Create targeted memories for each agent type")
|
|
411
|
-
print("4. Use 'claude-mpm memory add <agent> <type> \"<content>\"' commands")
|
|
412
|
-
print()
|
|
413
|
-
print("Focus areas:")
|
|
414
|
-
print(" • Architectural patterns and design decisions")
|
|
415
|
-
print(" • Coding conventions from actual source code")
|
|
416
|
-
print(" • Key modules, APIs, and integration points")
|
|
417
|
-
print(" • Testing patterns and quality standards")
|
|
418
|
-
print(" • Performance considerations specific to this project")
|
|
419
|
-
print(" • Common pitfalls based on the codebase")
|
|
420
|
-
print(" • Domain-specific terminology and concepts")
|
|
421
|
-
print()
|
|
422
|
-
print("Example commands to use:")
|
|
423
|
-
print(
|
|
424
|
-
' claude-mpm memory add engineer pattern "Use dependency injection with @inject"'
|
|
425
|
-
)
|
|
426
|
-
print(
|
|
427
|
-
' claude-mpm memory add qa pattern "Test files follow test_<module>_<feature>.py"'
|
|
428
|
-
)
|
|
429
|
-
print(
|
|
430
|
-
' claude-mpm memory add research context "Project uses microservices architecture"'
|
|
431
|
-
)
|
|
432
|
-
print()
|
|
433
|
-
print("Begin by examining the project structure and key files.")
|
|
434
|
-
print()
|
|
435
|
-
print("=" * 80)
|
|
436
|
-
print()
|
|
437
|
-
print("📝 Note: Copy the task above to execute the memory initialization process.")
|
|
438
|
-
print(" Use 'claude-mpm memory add' commands to add discovered insights.")
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
def _show_status(memory_manager):
|
|
442
|
-
"""
|
|
443
|
-
Show comprehensive memory system status.
|
|
444
|
-
|
|
445
|
-
WHY: Users need to see memory system health, file sizes, optimization
|
|
446
|
-
opportunities, and agent-specific statistics to understand the system state.
|
|
447
|
-
|
|
448
|
-
Args:
|
|
449
|
-
memory_manager: AgentMemoryManager instance
|
|
450
|
-
"""
|
|
451
|
-
print("Agent Memory System Status")
|
|
452
|
-
print("-" * 80)
|
|
453
|
-
|
|
454
|
-
try:
|
|
455
|
-
# Get comprehensive status from memory manager
|
|
456
|
-
status = memory_manager.get_memory_status()
|
|
457
|
-
|
|
458
|
-
if not status.get("success", True):
|
|
459
|
-
print(f"❌ Error getting status: {status.get('error', 'Unknown error')}")
|
|
460
|
-
return
|
|
504
|
+
# Removed _init_memory - now handled by MemoryCRUDService.init_project_memories()
|
|
461
505
|
|
|
462
|
-
# Show system overview
|
|
463
|
-
system_health = status.get("system_health", "unknown")
|
|
464
|
-
health_emoji = {
|
|
465
|
-
"healthy": "✅",
|
|
466
|
-
"needs_optimization": "⚠️",
|
|
467
|
-
"high_usage": "📊",
|
|
468
|
-
"no_memory_dir": "📁",
|
|
469
|
-
}.get(system_health, "❓")
|
|
470
|
-
|
|
471
|
-
print(f"🧠 Memory System Health: {health_emoji} {system_health}")
|
|
472
|
-
print(f"📁 Memory Directory: {status.get('memory_directory', 'Unknown')}")
|
|
473
|
-
print(
|
|
474
|
-
f"🔧 System Enabled: {'Yes' if status.get('system_enabled', True) else 'No'}"
|
|
475
|
-
)
|
|
476
|
-
print(
|
|
477
|
-
f"📚 Auto Learning: {'Yes' if status.get('auto_learning', True) else 'No'}"
|
|
478
|
-
)
|
|
479
|
-
print(f"📊 Total Agents: {status.get('total_agents', 0)}")
|
|
480
|
-
print(f"💾 Total Size: {status.get('total_size_kb', 0):.1f} KB")
|
|
481
|
-
print()
|
|
482
|
-
|
|
483
|
-
# Show optimization opportunities
|
|
484
|
-
opportunities = status.get("optimization_opportunities", [])
|
|
485
|
-
if opportunities:
|
|
486
|
-
print(f"⚠️ Optimization Opportunities ({len(opportunities)}):")
|
|
487
|
-
for opportunity in opportunities[:5]: # Show top 5
|
|
488
|
-
print(f" • {opportunity}")
|
|
489
|
-
if len(opportunities) > 5:
|
|
490
|
-
print(f" ... and {len(opportunities) - 5} more")
|
|
491
|
-
print()
|
|
492
506
|
|
|
493
|
-
|
|
494
|
-
agents = status.get("agents", {})
|
|
495
|
-
if agents:
|
|
496
|
-
print(f"📋 Agent Memory Details:")
|
|
497
|
-
for agent_id, agent_info in sorted(agents.items()):
|
|
498
|
-
if "error" in agent_info:
|
|
499
|
-
print(f" ❌ {agent_id}: Error - {agent_info['error']}")
|
|
500
|
-
continue
|
|
501
|
-
|
|
502
|
-
size_kb = agent_info.get("size_kb", 0)
|
|
503
|
-
size_limit = agent_info.get("size_limit_kb", 8)
|
|
504
|
-
utilization = agent_info.get("size_utilization", 0)
|
|
505
|
-
sections = agent_info.get("sections", 0)
|
|
506
|
-
items = agent_info.get("items", 0)
|
|
507
|
-
last_modified = agent_info.get("last_modified", "Unknown")
|
|
508
|
-
auto_learning = agent_info.get("auto_learning", True)
|
|
509
|
-
|
|
510
|
-
# Format last modified time
|
|
511
|
-
try:
|
|
512
|
-
from datetime import datetime
|
|
513
|
-
|
|
514
|
-
dt = datetime.fromisoformat(last_modified.replace("Z", "+00:00"))
|
|
515
|
-
last_modified_str = dt.strftime("%Y-%m-%d %H:%M:%S")
|
|
516
|
-
except:
|
|
517
|
-
last_modified_str = last_modified
|
|
518
|
-
|
|
519
|
-
# Status indicator based on usage
|
|
520
|
-
if utilization > 90:
|
|
521
|
-
status_emoji = "🔴" # High usage
|
|
522
|
-
elif utilization > 70:
|
|
523
|
-
status_emoji = "🟡" # Medium usage
|
|
524
|
-
else:
|
|
525
|
-
status_emoji = "🟢" # Low usage
|
|
507
|
+
# Removed _show_status - functionality moved to MemoryManagementCommand._show_status()
|
|
526
508
|
|
|
527
|
-
print(f" {status_emoji} {agent_id}")
|
|
528
|
-
print(
|
|
529
|
-
f" Size: {size_kb:.1f} KB / {size_limit} KB ({utilization:.1f}%)"
|
|
530
|
-
)
|
|
531
|
-
print(f" Content: {sections} sections, {items} items")
|
|
532
|
-
print(f" Auto-learning: {'On' if auto_learning else 'Off'}")
|
|
533
|
-
print(f" Last modified: {last_modified_str}")
|
|
534
|
-
else:
|
|
535
|
-
print("📭 No agent memories found")
|
|
536
509
|
|
|
537
|
-
|
|
538
|
-
print(f"❌ Error showing status: {e}")
|
|
539
|
-
# Fallback to basic status display
|
|
540
|
-
_show_basic_status(memory_manager)
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
def _show_basic_status(memory_manager):
|
|
544
|
-
"""Fallback basic status display if comprehensive status fails."""
|
|
545
|
-
print("\n--- Basic Status (Fallback) ---")
|
|
546
|
-
|
|
547
|
-
memory_dir = memory_manager.memories_dir
|
|
548
|
-
if not memory_dir.exists():
|
|
549
|
-
print("📁 Memory directory not found - no agent memories stored yet")
|
|
550
|
-
print(f" Expected location: {memory_dir}")
|
|
551
|
-
return
|
|
510
|
+
# Removed _show_basic_status - functionality integrated into MemoryManagementCommand
|
|
552
511
|
|
|
553
|
-
# Support both old and new formats
|
|
554
|
-
memory_files = list(memory_dir.glob("*_memories.md"))
|
|
555
|
-
# Also check for old formats for backward compatibility
|
|
556
|
-
memory_files.extend(memory_dir.glob("*_agent.md"))
|
|
557
|
-
memory_files.extend([f for f in memory_dir.glob("*.md")
|
|
558
|
-
if f.name != "README.md" and not f.name.endswith("_memories.md") and not f.name.endswith("_agent.md")])
|
|
559
512
|
|
|
560
|
-
|
|
561
|
-
print("📭 No memory files found")
|
|
562
|
-
print(f" Memory directory: {memory_dir}")
|
|
563
|
-
return
|
|
513
|
+
# Removed _view_memory - functionality moved to MemoryCRUDService.read_memory()
|
|
564
514
|
|
|
565
|
-
print(f"📁 Memory directory: {memory_dir}")
|
|
566
|
-
print(f"📊 Total memory files: {len(memory_files)}")
|
|
567
515
|
|
|
568
|
-
|
|
569
|
-
for file_path in sorted(memory_files):
|
|
570
|
-
stat = file_path.stat()
|
|
571
|
-
size_kb = stat.st_size / 1024
|
|
572
|
-
total_size += stat.st_size
|
|
516
|
+
# Removed _add_learning - now handled by MemoryCRUDService.update_memory()
|
|
573
517
|
|
|
574
|
-
# Extract agent name from various formats
|
|
575
|
-
if file_path.name.endswith("_memories.md"):
|
|
576
|
-
agent_id = file_path.stem[:-9] # Remove "_memories"
|
|
577
|
-
elif file_path.name.endswith("_agent.md"):
|
|
578
|
-
agent_id = file_path.stem[:-6] # Remove "_agent"
|
|
579
|
-
else:
|
|
580
|
-
agent_id = file_path.stem
|
|
581
|
-
print(f" {agent_id}: {size_kb:.1f} KB")
|
|
582
518
|
|
|
583
|
-
|
|
519
|
+
# Removed _clean_memory - now handled by MemoryCRUDService.clean_memory()
|
|
584
520
|
|
|
585
521
|
|
|
586
|
-
|
|
587
|
-
"""
|
|
588
|
-
View agent memory file contents.
|
|
589
|
-
|
|
590
|
-
WHY: Users need to inspect what learnings an agent has accumulated
|
|
591
|
-
to understand its behavior and debug issues.
|
|
592
|
-
|
|
593
|
-
Args:
|
|
594
|
-
args: Command arguments with agent_id
|
|
595
|
-
memory_manager: AgentMemoryManager instance
|
|
596
|
-
"""
|
|
597
|
-
agent_id = args.agent_id
|
|
598
|
-
|
|
599
|
-
try:
|
|
600
|
-
memory_content = memory_manager.load_agent_memory(agent_id)
|
|
601
|
-
|
|
602
|
-
if not memory_content:
|
|
603
|
-
print(f"📭 No memory found for agent: {agent_id}")
|
|
604
|
-
return
|
|
605
|
-
|
|
606
|
-
print(f"🧠 Memory for agent: {agent_id}")
|
|
607
|
-
print("-" * 80)
|
|
608
|
-
print(memory_content)
|
|
609
|
-
|
|
610
|
-
except FileNotFoundError:
|
|
611
|
-
print(f"📭 No memory file found for agent: {agent_id}")
|
|
612
|
-
except Exception as e:
|
|
613
|
-
print(f"❌ Error viewing memory: {e}")
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
def _add_learning(args, memory_manager):
|
|
617
|
-
"""
|
|
618
|
-
Manually add learning to agent memory.
|
|
619
|
-
|
|
620
|
-
WHY: Allows manual injection of learnings for testing or correction
|
|
621
|
-
purposes, useful for debugging and development.
|
|
622
|
-
|
|
623
|
-
Args:
|
|
624
|
-
args: Command arguments with agent_id, learning_type, and content
|
|
625
|
-
memory_manager: AgentMemoryManager instance
|
|
626
|
-
"""
|
|
627
|
-
agent_id = args.agent_id
|
|
628
|
-
section = args.learning_type # Map learning_type to section name
|
|
629
|
-
content = args.content
|
|
630
|
-
|
|
631
|
-
# Map learning types to appropriate sections
|
|
632
|
-
section_map = {
|
|
633
|
-
"pattern": "Project Architecture",
|
|
634
|
-
"error": "Common Mistakes to Avoid",
|
|
635
|
-
"optimization": "Implementation Guidelines",
|
|
636
|
-
"preference": "Implementation Guidelines",
|
|
637
|
-
"context": "Current Technical Context",
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
section_name = section_map.get(section, "Current Technical Context")
|
|
641
|
-
|
|
642
|
-
try:
|
|
643
|
-
success = memory_manager.update_agent_memory(agent_id, section_name, content)
|
|
644
|
-
|
|
645
|
-
if success:
|
|
646
|
-
print(f"✅ Added {section} to {agent_id} memory in section: {section_name}")
|
|
647
|
-
print(f" Content: {content[:100]}{'...' if len(content) > 100 else ''}")
|
|
648
|
-
else:
|
|
649
|
-
print(f"❌ Failed to add learning to {agent_id} memory")
|
|
650
|
-
print(" Memory file may be at size limit or section may be full")
|
|
651
|
-
|
|
652
|
-
except Exception as e:
|
|
653
|
-
print(f"❌ Error adding learning: {e}")
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
def _clean_memory(args, memory_manager):
|
|
657
|
-
"""
|
|
658
|
-
Clean up old/unused memory files.
|
|
659
|
-
|
|
660
|
-
WHY: Memory files can accumulate over time. This provides a way to
|
|
661
|
-
clean up old or unused files to save disk space.
|
|
662
|
-
|
|
663
|
-
DESIGN DECISION: For Phase 1, this is a stub implementation.
|
|
664
|
-
Full cleanup logic will be implemented based on usage patterns.
|
|
665
|
-
|
|
666
|
-
Args:
|
|
667
|
-
args: Command arguments
|
|
668
|
-
memory_manager: AgentMemoryManager instance
|
|
669
|
-
"""
|
|
670
|
-
print("🧹 Memory cleanup")
|
|
671
|
-
print("-" * 80)
|
|
672
|
-
|
|
673
|
-
# For Phase 1, just show what would be cleaned
|
|
674
|
-
memory_dir = memory_manager.memories_dir
|
|
675
|
-
if not memory_dir.exists():
|
|
676
|
-
print("📁 No memory directory found - nothing to clean")
|
|
677
|
-
return
|
|
678
|
-
|
|
679
|
-
# Support both old and new formats
|
|
680
|
-
memory_files = list(memory_dir.glob("*_memories.md"))
|
|
681
|
-
# Also check for old formats for backward compatibility
|
|
682
|
-
memory_files.extend(memory_dir.glob("*_agent.md"))
|
|
683
|
-
memory_files.extend([f for f in memory_dir.glob("*.md")
|
|
684
|
-
if f.name != "README.md" and not f.name.endswith("_memories.md") and not f.name.endswith("_agent.md")])
|
|
685
|
-
if not memory_files:
|
|
686
|
-
print("📭 No memory files found - nothing to clean")
|
|
687
|
-
return
|
|
688
|
-
|
|
689
|
-
print(f"📊 Found {len(memory_files)} memory files")
|
|
690
|
-
print()
|
|
691
|
-
print("⚠️ Cleanup not yet implemented in Phase 1")
|
|
692
|
-
print(" Future cleanup will remove:")
|
|
693
|
-
print(" - Memory files older than 30 days with no recent access")
|
|
694
|
-
print(" - Corrupted memory files")
|
|
695
|
-
print(" - Memory files for non-existent agents")
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
def _optimize_memory(args, memory_manager):
|
|
699
|
-
"""
|
|
700
|
-
Optimize memory files by removing duplicates and consolidating similar items.
|
|
701
|
-
|
|
702
|
-
WHY: Memory files can become cluttered over time with duplicate or redundant
|
|
703
|
-
information. This command provides automated cleanup while preserving
|
|
704
|
-
important learnings.
|
|
705
|
-
|
|
706
|
-
Args:
|
|
707
|
-
args: Command arguments with optional agent_id
|
|
708
|
-
memory_manager: AgentMemoryManager instance
|
|
709
|
-
"""
|
|
710
|
-
print("🔧 Memory Optimization")
|
|
711
|
-
print("-" * 80)
|
|
712
|
-
|
|
713
|
-
agent_id = getattr(args, "agent_id", None)
|
|
714
|
-
|
|
715
|
-
try:
|
|
716
|
-
if agent_id:
|
|
717
|
-
print(f"📊 Optimizing memory for agent: {agent_id}")
|
|
718
|
-
result = memory_manager.optimize_memory(agent_id)
|
|
719
|
-
else:
|
|
720
|
-
print("📊 Optimizing all agent memories...")
|
|
721
|
-
result = memory_manager.optimize_memory()
|
|
722
|
-
|
|
723
|
-
if result.get("success"):
|
|
724
|
-
if agent_id:
|
|
725
|
-
# Single agent results
|
|
726
|
-
_display_single_optimization_result(result)
|
|
727
|
-
else:
|
|
728
|
-
# All agents results
|
|
729
|
-
_display_bulk_optimization_results(result)
|
|
730
|
-
else:
|
|
731
|
-
print(f"❌ Optimization failed: {result.get('error', 'Unknown error')}")
|
|
732
|
-
|
|
733
|
-
except Exception as e:
|
|
734
|
-
print(f"❌ Error during optimization: {e}")
|
|
522
|
+
# Removed _optimize_memory - functionality moved to MemoryManagementCommand._optimize_memory()
|
|
735
523
|
|
|
736
524
|
|
|
737
525
|
def _build_memory(args, memory_manager):
|
|
@@ -755,35 +543,11 @@ def _build_memory(args, memory_manager):
|
|
|
755
543
|
print("🔍 Analyzing project documentation...")
|
|
756
544
|
result = memory_manager.build_memories_from_docs(force_rebuild)
|
|
757
545
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
print(f" Agents affected: {result.get('total_agents_affected', 0)}")
|
|
764
|
-
|
|
765
|
-
if result.get("agents_affected"):
|
|
766
|
-
print(f" Affected agents: {', '.join(result['agents_affected'])}")
|
|
767
|
-
|
|
768
|
-
# Show file-specific results
|
|
769
|
-
files_results = result.get("files", {})
|
|
770
|
-
if files_results:
|
|
771
|
-
print("\n📄 File processing details:")
|
|
772
|
-
for file_path, file_result in files_results.items():
|
|
773
|
-
if file_result.get("success"):
|
|
774
|
-
extracted = file_result.get("items_extracted", 0)
|
|
775
|
-
created = file_result.get("memories_created", 0)
|
|
776
|
-
print(
|
|
777
|
-
f" {file_path}: {extracted} items extracted, {created} memories created"
|
|
778
|
-
)
|
|
779
|
-
|
|
780
|
-
if result.get("errors"):
|
|
781
|
-
print("\n⚠️ Errors encountered:")
|
|
782
|
-
for error in result["errors"]:
|
|
783
|
-
print(f" {error}")
|
|
784
|
-
|
|
785
|
-
else:
|
|
786
|
-
print(f"❌ Build failed: {result.get('error', 'Unknown error')}")
|
|
546
|
+
# Use formatter to display build results
|
|
547
|
+
quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
|
|
548
|
+
formatter = MemoryOutputFormatter(quiet=quiet)
|
|
549
|
+
output = formatter.format_build_results(result)
|
|
550
|
+
print(output)
|
|
787
551
|
|
|
788
552
|
except Exception as e:
|
|
789
553
|
print(f"❌ Error building memories: {e}")
|
|
@@ -800,291 +564,22 @@ def _cross_reference_memory(args, memory_manager):
|
|
|
800
564
|
args: Command arguments with optional query
|
|
801
565
|
memory_manager: AgentMemoryManager instance
|
|
802
566
|
"""
|
|
803
|
-
print("🔗 Memory Cross-Reference Analysis")
|
|
804
|
-
print("-" * 80)
|
|
805
|
-
|
|
806
567
|
query = getattr(args, "query", None)
|
|
807
568
|
|
|
808
569
|
try:
|
|
809
|
-
if query:
|
|
810
|
-
print(f"🔍 Searching for: '{query}'")
|
|
811
|
-
else:
|
|
812
|
-
print("🔍 Analyzing all agent memories for patterns...")
|
|
813
|
-
|
|
814
570
|
result = memory_manager.cross_reference_memories(query)
|
|
815
571
|
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
common_patterns = result.get("common_patterns", [])
|
|
822
|
-
if common_patterns:
|
|
823
|
-
print(f"\n🔄 Common patterns found ({len(common_patterns)}):")
|
|
824
|
-
for pattern in common_patterns[:10]: # Show top 10
|
|
825
|
-
agents = ", ".join(pattern["agents"])
|
|
826
|
-
print(f" • {pattern['pattern']}")
|
|
827
|
-
print(f" Found in: {agents} ({pattern['count']} instances)")
|
|
828
|
-
else:
|
|
829
|
-
print("\n🔄 No common patterns found")
|
|
830
|
-
|
|
831
|
-
# Display query matches if query was provided
|
|
832
|
-
if query and result.get("query_matches"):
|
|
833
|
-
print(f"\n🎯 Query matches for '{query}':")
|
|
834
|
-
for match in result["query_matches"]:
|
|
835
|
-
print(f" 📋 {match['agent']}:")
|
|
836
|
-
for line in match["matches"][:3]: # Show first 3 matches
|
|
837
|
-
print(f" • {line}")
|
|
838
|
-
|
|
839
|
-
# Display agent correlations
|
|
840
|
-
correlations = result.get("agent_correlations", {})
|
|
841
|
-
if correlations:
|
|
842
|
-
print(f"\n🤝 Agent knowledge correlations:")
|
|
843
|
-
sorted_correlations = sorted(
|
|
844
|
-
correlations.items(), key=lambda x: x[1], reverse=True
|
|
845
|
-
)
|
|
846
|
-
for agents, count in sorted_correlations[:5]: # Show top 5
|
|
847
|
-
print(f" {agents}: {count} common items")
|
|
848
|
-
else:
|
|
849
|
-
print("\n🤝 No significant correlations found")
|
|
572
|
+
# Use formatter to display cross-reference results
|
|
573
|
+
quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
|
|
574
|
+
formatter = MemoryOutputFormatter(quiet=quiet)
|
|
575
|
+
output = formatter.format_cross_reference(result, query)
|
|
576
|
+
print(output)
|
|
850
577
|
|
|
851
578
|
except Exception as e:
|
|
852
579
|
print(f"❌ Error during cross-reference analysis: {e}")
|
|
853
580
|
|
|
854
581
|
|
|
855
|
-
|
|
856
|
-
"""
|
|
857
|
-
Show agent memories in a user-friendly format with cross-references and patterns.
|
|
858
|
-
|
|
859
|
-
WHY: Users need to see agent memories in a readable format to understand
|
|
860
|
-
what agents have learned and identify common patterns across agents.
|
|
861
|
-
|
|
862
|
-
DESIGN DECISION: Added --raw flag to output structured JSON data for
|
|
863
|
-
programmatic processing, enabling external tools and scripts to access
|
|
864
|
-
all agent memories in a structured format.
|
|
865
|
-
|
|
866
|
-
Args:
|
|
867
|
-
args: Command arguments with optional agent_id, format, and raw flag
|
|
868
|
-
memory_manager: AgentMemoryManager instance
|
|
869
|
-
"""
|
|
870
|
-
agent_id = getattr(args, "agent_id", None)
|
|
871
|
-
format_type = getattr(args, "format", "detailed")
|
|
872
|
-
raw_output = getattr(args, "raw", False)
|
|
873
|
-
|
|
874
|
-
try:
|
|
875
|
-
if raw_output:
|
|
876
|
-
# Output structured JSON data
|
|
877
|
-
if agent_id:
|
|
878
|
-
# Get single agent memory in raw format
|
|
879
|
-
_output_single_agent_raw(agent_id, memory_manager)
|
|
880
|
-
else:
|
|
881
|
-
# Get all agent memories in raw format
|
|
882
|
-
_output_all_memories_raw(memory_manager)
|
|
883
|
-
else:
|
|
884
|
-
# Normal user-friendly display
|
|
885
|
-
print("🧠 Agent Memories Display")
|
|
886
|
-
print("-" * 80)
|
|
887
|
-
|
|
888
|
-
if agent_id:
|
|
889
|
-
_show_single_agent_memory(agent_id, format_type, memory_manager)
|
|
890
|
-
else:
|
|
891
|
-
_show_all_agent_memories(format_type, memory_manager)
|
|
892
|
-
|
|
893
|
-
except Exception as e:
|
|
894
|
-
if raw_output:
|
|
895
|
-
# Output error in JSON format for consistency
|
|
896
|
-
error_output = {
|
|
897
|
-
"success": False,
|
|
898
|
-
"error": str(e),
|
|
899
|
-
"timestamp": datetime.now().isoformat(),
|
|
900
|
-
}
|
|
901
|
-
print(json.dumps(error_output, indent=2))
|
|
902
|
-
else:
|
|
903
|
-
print(f"❌ Error showing memories: {e}")
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
def _show_single_agent_memory(agent_id, format_type, memory_manager):
|
|
907
|
-
"""Show memory for a single agent in the specified format."""
|
|
908
|
-
memory_content = memory_manager.load_agent_memory(agent_id)
|
|
909
|
-
|
|
910
|
-
if not memory_content:
|
|
911
|
-
print(f"📭 No memory found for agent: {agent_id}")
|
|
912
|
-
return
|
|
913
|
-
|
|
914
|
-
print(f"🤖 Agent: {agent_id}")
|
|
915
|
-
print("-" * 40)
|
|
916
|
-
|
|
917
|
-
if format_type == "full":
|
|
918
|
-
print(memory_content)
|
|
919
|
-
else:
|
|
920
|
-
# Parse and display memory sections
|
|
921
|
-
sections = _parse_memory_content(memory_content)
|
|
922
|
-
|
|
923
|
-
for section_name, items in sections.items():
|
|
924
|
-
if items:
|
|
925
|
-
print(f"\n📚 {section_name} ({len(items)} items):")
|
|
926
|
-
for i, item in enumerate(items[:5], 1): # Show first 5 items
|
|
927
|
-
print(f" {i}. {item}")
|
|
928
|
-
if len(items) > 5:
|
|
929
|
-
print(f" ... and {len(items) - 5} more")
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
def _show_all_agent_memories(format_type, memory_manager):
|
|
933
|
-
"""Show memories for all agents with cross-references."""
|
|
934
|
-
# Get all available agent memory files
|
|
935
|
-
memory_dir = memory_manager.memories_dir
|
|
936
|
-
if not memory_dir.exists():
|
|
937
|
-
print("📁 No memory directory found")
|
|
938
|
-
return
|
|
939
|
-
|
|
940
|
-
# Support both old and new formats
|
|
941
|
-
memory_files = list(memory_dir.glob("*_memories.md"))
|
|
942
|
-
# Also check for old formats for backward compatibility
|
|
943
|
-
memory_files.extend(memory_dir.glob("*_agent.md"))
|
|
944
|
-
memory_files.extend([f for f in memory_dir.glob("*.md")
|
|
945
|
-
if f.name != "README.md" and not f.name.endswith("_memories.md") and not f.name.endswith("_agent.md")])
|
|
946
|
-
if not memory_files:
|
|
947
|
-
print("📭 No agent memories found")
|
|
948
|
-
return
|
|
949
|
-
|
|
950
|
-
print(f"📊 Found memories for {len(memory_files)} agents")
|
|
951
|
-
print()
|
|
952
|
-
|
|
953
|
-
agent_memories = {}
|
|
954
|
-
total_items = 0
|
|
955
|
-
|
|
956
|
-
# Load all agent memories
|
|
957
|
-
for file_path in sorted(memory_files):
|
|
958
|
-
# Extract agent name from various formats
|
|
959
|
-
if file_path.name.endswith("_memories.md"):
|
|
960
|
-
agent_id = file_path.stem[:-9] # Remove "_memories"
|
|
961
|
-
elif file_path.name.endswith("_agent.md"):
|
|
962
|
-
agent_id = file_path.stem[:-6] # Remove "_agent"
|
|
963
|
-
else:
|
|
964
|
-
agent_id = file_path.stem
|
|
965
|
-
try:
|
|
966
|
-
memory_content = memory_manager.load_agent_memory(agent_id)
|
|
967
|
-
if memory_content:
|
|
968
|
-
sections = _parse_memory_content(memory_content)
|
|
969
|
-
agent_memories[agent_id] = sections
|
|
970
|
-
|
|
971
|
-
# Count items
|
|
972
|
-
item_count = sum(len(items) for items in sections.values())
|
|
973
|
-
total_items += item_count
|
|
974
|
-
|
|
975
|
-
if format_type == "summary":
|
|
976
|
-
print(f"🤖 {agent_id}")
|
|
977
|
-
print(f" 📚 {len(sections)} sections, {item_count} total items")
|
|
978
|
-
|
|
979
|
-
# Show section summary
|
|
980
|
-
for section_name, items in sections.items():
|
|
981
|
-
if items:
|
|
982
|
-
print(f" • {section_name}: {len(items)} items")
|
|
983
|
-
print()
|
|
984
|
-
elif format_type == "detailed":
|
|
985
|
-
print(f"🤖 {agent_id}")
|
|
986
|
-
print(f" 📚 {len(sections)} sections, {item_count} total items")
|
|
987
|
-
|
|
988
|
-
for section_name, items in sections.items():
|
|
989
|
-
if items:
|
|
990
|
-
print(f"\n 📖 {section_name}:")
|
|
991
|
-
for item in items[:3]: # Show first 3 items
|
|
992
|
-
print(f" • {item}")
|
|
993
|
-
if len(items) > 3:
|
|
994
|
-
print(f" ... and {len(items) - 3} more")
|
|
995
|
-
print()
|
|
996
|
-
except Exception as e:
|
|
997
|
-
print(f"❌ Error loading memory for {agent_id}: {e}")
|
|
998
|
-
|
|
999
|
-
print(f"📊 Total: {total_items} memory items across {len(agent_memories)} agents")
|
|
1000
|
-
|
|
1001
|
-
# Show cross-references if we have multiple agents
|
|
1002
|
-
if len(agent_memories) > 1:
|
|
1003
|
-
print("\n🔗 Cross-References and Common Patterns:")
|
|
1004
|
-
_find_common_patterns(agent_memories)
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
def _parse_memory_content(content):
|
|
1008
|
-
"""Parse memory content into sections and items."""
|
|
1009
|
-
sections = {}
|
|
1010
|
-
current_section = None
|
|
1011
|
-
current_items = []
|
|
1012
|
-
|
|
1013
|
-
for line in content.split("\n"):
|
|
1014
|
-
line = line.strip()
|
|
1015
|
-
|
|
1016
|
-
if line.startswith("## ") and not line.startswith("## Memory Usage"):
|
|
1017
|
-
# New section
|
|
1018
|
-
if current_section and current_items:
|
|
1019
|
-
sections[current_section] = current_items.copy()
|
|
1020
|
-
|
|
1021
|
-
current_section = line[3:].strip()
|
|
1022
|
-
current_items = []
|
|
1023
|
-
elif line.startswith("- ") and current_section:
|
|
1024
|
-
# Item in current section
|
|
1025
|
-
item = line[2:].strip()
|
|
1026
|
-
if item and len(item) > 5: # Filter out very short items
|
|
1027
|
-
current_items.append(item)
|
|
1028
|
-
|
|
1029
|
-
# Add final section
|
|
1030
|
-
if current_section and current_items:
|
|
1031
|
-
sections[current_section] = current_items
|
|
1032
|
-
|
|
1033
|
-
return sections
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
def _find_common_patterns(agent_memories):
|
|
1037
|
-
"""Find common patterns across agent memories."""
|
|
1038
|
-
pattern_count = {}
|
|
1039
|
-
agent_patterns = {}
|
|
1040
|
-
|
|
1041
|
-
# Collect all patterns and which agents have them
|
|
1042
|
-
for agent_id, sections in agent_memories.items():
|
|
1043
|
-
agent_patterns[agent_id] = set()
|
|
1044
|
-
|
|
1045
|
-
for section_name, items in sections.items():
|
|
1046
|
-
for item in items:
|
|
1047
|
-
# Normalize item for comparison (lowercase, basic cleanup)
|
|
1048
|
-
normalized = item.lower().strip()
|
|
1049
|
-
if len(normalized) > 10: # Skip very short items
|
|
1050
|
-
pattern_count[normalized] = pattern_count.get(normalized, 0) + 1
|
|
1051
|
-
agent_patterns[agent_id].add(normalized)
|
|
1052
|
-
|
|
1053
|
-
# Find patterns that appear in multiple agents
|
|
1054
|
-
common_patterns = [
|
|
1055
|
-
(pattern, count) for pattern, count in pattern_count.items() if count > 1
|
|
1056
|
-
]
|
|
1057
|
-
common_patterns.sort(key=lambda x: x[1], reverse=True)
|
|
1058
|
-
|
|
1059
|
-
if common_patterns:
|
|
1060
|
-
print("\n🔄 Most Common Patterns:")
|
|
1061
|
-
for pattern, count in common_patterns[:5]:
|
|
1062
|
-
# Find which agents have this pattern
|
|
1063
|
-
agents_with_pattern = [
|
|
1064
|
-
agent
|
|
1065
|
-
for agent, patterns in agent_patterns.items()
|
|
1066
|
-
if pattern in patterns
|
|
1067
|
-
]
|
|
1068
|
-
print(f" • {pattern[:80]}{'...' if len(pattern) > 80 else ''}")
|
|
1069
|
-
print(f" Found in: {', '.join(agents_with_pattern)} ({count} agents)")
|
|
1070
|
-
print()
|
|
1071
|
-
else:
|
|
1072
|
-
print(" No common patterns found across agents")
|
|
1073
|
-
|
|
1074
|
-
# Show agent similarities
|
|
1075
|
-
print("\n🤝 Agent Knowledge Similarity:")
|
|
1076
|
-
agents = list(agent_memories.keys())
|
|
1077
|
-
for i, agent1 in enumerate(agents):
|
|
1078
|
-
for agent2 in agents[i + 1 :]:
|
|
1079
|
-
common_items = len(agent_patterns[agent1] & agent_patterns[agent2])
|
|
1080
|
-
if common_items > 0:
|
|
1081
|
-
total_items = len(agent_patterns[agent1] | agent_patterns[agent2])
|
|
1082
|
-
similarity = (
|
|
1083
|
-
(common_items / total_items) * 100 if total_items > 0 else 0
|
|
1084
|
-
)
|
|
1085
|
-
print(
|
|
1086
|
-
f" {agent1} ↔ {agent2}: {common_items} common items ({similarity:.1f}% similarity)"
|
|
1087
|
-
)
|
|
582
|
+
# Note: Memory display functions have been moved to MemoryManagementCommand and MemoryCRUDService
|
|
1088
583
|
|
|
1089
584
|
|
|
1090
585
|
def _route_memory_command(args, memory_manager):
|
|
@@ -1123,7 +618,7 @@ def _route_memory_command(args, memory_manager):
|
|
|
1123
618
|
confidence = result.get("confidence", 0.0)
|
|
1124
619
|
reasoning = result.get("reasoning", "No reasoning provided")
|
|
1125
620
|
|
|
1126
|
-
print(
|
|
621
|
+
print("\n🎯 Routing Decision:")
|
|
1127
622
|
print(f" Target Agent: {target_agent}")
|
|
1128
623
|
print(f" Section: {section}")
|
|
1129
624
|
print(f" Confidence: {confidence:.2f}")
|
|
@@ -1132,7 +627,7 @@ def _route_memory_command(args, memory_manager):
|
|
|
1132
627
|
# Show agent scores if available
|
|
1133
628
|
agent_scores = result.get("agent_scores", {})
|
|
1134
629
|
if agent_scores:
|
|
1135
|
-
print(
|
|
630
|
+
print("\n📊 Agent Relevance Scores:")
|
|
1136
631
|
sorted_scores = sorted(
|
|
1137
632
|
[(agent, data["score"]) for agent, data in agent_scores.items()],
|
|
1138
633
|
key=lambda x: x[1],
|
|
@@ -1153,141 +648,18 @@ def _route_memory_command(args, memory_manager):
|
|
|
1153
648
|
|
|
1154
649
|
def _display_single_optimization_result(result):
|
|
1155
650
|
"""Display optimization results for a single agent."""
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
size_reduction_percent = result.get("size_reduction_percent", 0)
|
|
1161
|
-
|
|
1162
|
-
print(f"✅ Optimization completed for {agent_id}")
|
|
1163
|
-
print(f" Original size: {original_size:,} bytes")
|
|
1164
|
-
print(f" Optimized size: {optimized_size:,} bytes")
|
|
1165
|
-
print(f" Size reduction: {size_reduction:,} bytes ({size_reduction_percent}%)")
|
|
1166
|
-
|
|
1167
|
-
duplicates = result.get("duplicates_removed", 0)
|
|
1168
|
-
consolidated = result.get("items_consolidated", 0)
|
|
1169
|
-
reordered = result.get("items_reordered", 0)
|
|
1170
|
-
|
|
1171
|
-
if duplicates > 0:
|
|
1172
|
-
print(f" Duplicates removed: {duplicates}")
|
|
1173
|
-
if consolidated > 0:
|
|
1174
|
-
print(f" Items consolidated: {consolidated}")
|
|
1175
|
-
if reordered > 0:
|
|
1176
|
-
print(f" Sections reordered: {reordered}")
|
|
1177
|
-
|
|
1178
|
-
backup_path = result.get("backup_created")
|
|
1179
|
-
if backup_path:
|
|
1180
|
-
print(f" Backup created: {backup_path}")
|
|
651
|
+
quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
|
|
652
|
+
formatter = MemoryOutputFormatter(quiet=quiet)
|
|
653
|
+
output = formatter.format_optimization_results(result, is_single_agent=True)
|
|
654
|
+
print(output)
|
|
1181
655
|
|
|
1182
656
|
|
|
1183
657
|
def _display_bulk_optimization_results(result):
|
|
1184
658
|
"""Display optimization results for all agents."""
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
print(
|
|
1189
|
-
print(f" Agents optimized: {summary.get('agents_optimized', 0)}")
|
|
1190
|
-
print(f" Total size before: {summary.get('total_size_before', 0):,} bytes")
|
|
1191
|
-
print(f" Total size after: {summary.get('total_size_after', 0):,} bytes")
|
|
1192
|
-
print(
|
|
1193
|
-
f" Total reduction: {summary.get('total_size_reduction', 0):,} bytes ({summary.get('total_size_reduction_percent', 0)}%)"
|
|
1194
|
-
)
|
|
1195
|
-
print(f" Total duplicates removed: {summary.get('total_duplicates_removed', 0)}")
|
|
1196
|
-
print(f" Total items consolidated: {summary.get('total_items_consolidated', 0)}")
|
|
1197
|
-
|
|
1198
|
-
# Show per-agent summary
|
|
1199
|
-
agents_results = result.get("agents", {})
|
|
1200
|
-
if agents_results:
|
|
1201
|
-
print(f"\n📊 Per-agent results:")
|
|
1202
|
-
for agent_id, agent_result in agents_results.items():
|
|
1203
|
-
if agent_result.get("success"):
|
|
1204
|
-
reduction = agent_result.get("size_reduction_percent", 0)
|
|
1205
|
-
duplicates = agent_result.get("duplicates_removed", 0)
|
|
1206
|
-
consolidated = agent_result.get("items_consolidated", 0)
|
|
1207
|
-
|
|
1208
|
-
status_parts = []
|
|
1209
|
-
if duplicates > 0:
|
|
1210
|
-
status_parts.append(f"{duplicates} dupes")
|
|
1211
|
-
if consolidated > 0:
|
|
1212
|
-
status_parts.append(f"{consolidated} consolidated")
|
|
1213
|
-
|
|
1214
|
-
status = f" ({', '.join(status_parts)})" if status_parts else ""
|
|
1215
|
-
print(f" {agent_id}: {reduction}% reduction{status}")
|
|
1216
|
-
else:
|
|
1217
|
-
error = agent_result.get("error", "Unknown error")
|
|
1218
|
-
print(f" {agent_id}: ❌ {error}")
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
def _output_all_memories_raw(memory_manager):
|
|
1222
|
-
"""
|
|
1223
|
-
Output all agent memories in raw JSON format.
|
|
1224
|
-
|
|
1225
|
-
WHY: Provides programmatic access to all agent memories for external tools,
|
|
1226
|
-
scripts, or APIs that need to process or analyze the complete memory state.
|
|
1227
|
-
|
|
1228
|
-
Args:
|
|
1229
|
-
memory_manager: AgentMemoryManager instance
|
|
1230
|
-
"""
|
|
1231
|
-
try:
|
|
1232
|
-
raw_data = memory_manager.get_all_memories_raw()
|
|
1233
|
-
print(json.dumps(raw_data, indent=2, ensure_ascii=False))
|
|
1234
|
-
except Exception as e:
|
|
1235
|
-
error_output = {
|
|
1236
|
-
"success": False,
|
|
1237
|
-
"error": f"Failed to retrieve all memories: {str(e)}",
|
|
1238
|
-
"timestamp": datetime.now().isoformat(),
|
|
1239
|
-
}
|
|
1240
|
-
print(json.dumps(error_output, indent=2))
|
|
1241
|
-
|
|
659
|
+
quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
|
|
660
|
+
formatter = MemoryOutputFormatter(quiet=quiet)
|
|
661
|
+
output = formatter.format_optimization_results(result, is_single_agent=False)
|
|
662
|
+
print(output)
|
|
1242
663
|
|
|
1243
|
-
def _output_single_agent_raw(agent_id, memory_manager):
|
|
1244
|
-
"""
|
|
1245
|
-
Output single agent memory in raw JSON format.
|
|
1246
|
-
|
|
1247
|
-
WHY: Provides programmatic access to a specific agent's memory for
|
|
1248
|
-
targeted analysis or processing by external tools.
|
|
1249
|
-
|
|
1250
|
-
Args:
|
|
1251
|
-
agent_id: ID of the agent to retrieve memory for
|
|
1252
|
-
memory_manager: AgentMemoryManager instance
|
|
1253
|
-
"""
|
|
1254
|
-
try:
|
|
1255
|
-
# Get all memories and extract the specific agent
|
|
1256
|
-
all_memories = memory_manager.get_all_memories_raw()
|
|
1257
|
-
|
|
1258
|
-
if not all_memories.get("success", False):
|
|
1259
|
-
error_output = {
|
|
1260
|
-
"success": False,
|
|
1261
|
-
"error": all_memories.get("error", "Failed to retrieve memories"),
|
|
1262
|
-
"timestamp": datetime.now().isoformat(),
|
|
1263
|
-
}
|
|
1264
|
-
print(json.dumps(error_output, indent=2))
|
|
1265
|
-
return
|
|
1266
664
|
|
|
1267
|
-
|
|
1268
|
-
if agent_id not in agents:
|
|
1269
|
-
error_output = {
|
|
1270
|
-
"success": False,
|
|
1271
|
-
"error": f"No memory found for agent: {agent_id}",
|
|
1272
|
-
"available_agents": list(agents.keys()),
|
|
1273
|
-
"timestamp": datetime.now().isoformat(),
|
|
1274
|
-
}
|
|
1275
|
-
print(json.dumps(error_output, indent=2))
|
|
1276
|
-
return
|
|
1277
|
-
|
|
1278
|
-
# Return single agent data with metadata
|
|
1279
|
-
single_agent_output = {
|
|
1280
|
-
"success": True,
|
|
1281
|
-
"timestamp": all_memories["timestamp"],
|
|
1282
|
-
"agent": agents[agent_id],
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
print(json.dumps(single_agent_output, indent=2, ensure_ascii=False))
|
|
1286
|
-
|
|
1287
|
-
except Exception as e:
|
|
1288
|
-
error_output = {
|
|
1289
|
-
"success": False,
|
|
1290
|
-
"error": f"Failed to retrieve memory for agent {agent_id}: {str(e)}",
|
|
1291
|
-
"timestamp": datetime.now().isoformat(),
|
|
1292
|
-
}
|
|
1293
|
-
print(json.dumps(error_output, indent=2))
|
|
665
|
+
# Note: Raw output functions have been moved to MemoryCRUDService
|