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
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Memory Output Formatter Service
|
|
3
|
+
===============================
|
|
4
|
+
|
|
5
|
+
WHY: This service consolidates all memory display and formatting logic that was
|
|
6
|
+
previously duplicated throughout the memory.py command file, reducing code by ~250 lines
|
|
7
|
+
and providing consistent, reusable formatting across the entire memory subsystem.
|
|
8
|
+
|
|
9
|
+
DESIGN DECISIONS:
|
|
10
|
+
- Extract all formatting methods from memory.py into a reusable service
|
|
11
|
+
- Support multiple output formats (text, json, yaml, table)
|
|
12
|
+
- Implement quiet and verbose modes for flexible output control
|
|
13
|
+
- Maintain consistent emoji usage across all memory displays
|
|
14
|
+
- Follow established service patterns with interface-based design
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
from abc import ABC, abstractmethod
|
|
19
|
+
from datetime import datetime
|
|
20
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
21
|
+
|
|
22
|
+
import yaml
|
|
23
|
+
|
|
24
|
+
from ...core.logger import get_logger
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class IMemoryOutputFormatter(ABC):
|
|
28
|
+
"""Interface for memory output formatting service."""
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def format_status(self, status_data: Dict[str, Any], verbose: bool = False) -> str:
|
|
32
|
+
"""Format memory status display."""
|
|
33
|
+
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def format_memory_view(
|
|
36
|
+
self, agent_id: str, memory_content: str, format_type: str = "detailed"
|
|
37
|
+
) -> str:
|
|
38
|
+
"""Format memory viewing output."""
|
|
39
|
+
|
|
40
|
+
@abstractmethod
|
|
41
|
+
def format_optimization_results(
|
|
42
|
+
self, results: Dict[str, Any], is_single_agent: bool = True
|
|
43
|
+
) -> str:
|
|
44
|
+
"""Format optimization output."""
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def format_cross_reference(
|
|
48
|
+
self, cross_ref_data: Dict[str, Any], query: Optional[str] = None
|
|
49
|
+
) -> str:
|
|
50
|
+
"""Format pattern analysis output."""
|
|
51
|
+
|
|
52
|
+
@abstractmethod
|
|
53
|
+
def format_as_json(self, data: Dict[str, Any], pretty: bool = True) -> str:
|
|
54
|
+
"""Format data as JSON."""
|
|
55
|
+
|
|
56
|
+
@abstractmethod
|
|
57
|
+
def format_as_yaml(self, data: Dict[str, Any]) -> str:
|
|
58
|
+
"""Format data as YAML."""
|
|
59
|
+
|
|
60
|
+
@abstractmethod
|
|
61
|
+
def format_as_table(self, headers: List[str], rows: List[List[Any]]) -> str:
|
|
62
|
+
"""Format data as a table."""
|
|
63
|
+
|
|
64
|
+
@abstractmethod
|
|
65
|
+
def format_build_results(self, results: Dict[str, Any]) -> str:
|
|
66
|
+
"""Format memory build results."""
|
|
67
|
+
|
|
68
|
+
@abstractmethod
|
|
69
|
+
def format_agent_memories_summary(
|
|
70
|
+
self, agent_memories: Dict[str, Dict], format_type: str = "summary"
|
|
71
|
+
) -> str:
|
|
72
|
+
"""Format summary of all agent memories."""
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class MemoryOutputFormatter(IMemoryOutputFormatter):
|
|
76
|
+
"""Implementation of memory output formatting service."""
|
|
77
|
+
|
|
78
|
+
def __init__(self, quiet: bool = False):
|
|
79
|
+
"""
|
|
80
|
+
Initialize the memory output formatter.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
quiet: If True, minimize output (no emojis, minimal formatting)
|
|
84
|
+
"""
|
|
85
|
+
self.quiet = quiet
|
|
86
|
+
self.logger = get_logger(__name__)
|
|
87
|
+
|
|
88
|
+
# Emoji mappings for consistent usage
|
|
89
|
+
self.emojis = {
|
|
90
|
+
"success": "✅" if not quiet else "[OK]",
|
|
91
|
+
"error": "❌" if not quiet else "[ERROR]",
|
|
92
|
+
"warning": "⚠️" if not quiet else "[WARN]",
|
|
93
|
+
"info": "ℹ️" if not quiet else "[INFO]",
|
|
94
|
+
"memory": "🧠" if not quiet else "[MEMORY]",
|
|
95
|
+
"file": "📁" if not quiet else "[FILE]",
|
|
96
|
+
"agent": "🤖" if not quiet else "[AGENT]",
|
|
97
|
+
"stats": "📊" if not quiet else "[STATS]",
|
|
98
|
+
"clean": "🧹" if not quiet else "[CLEAN]",
|
|
99
|
+
"optimize": "🔧" if not quiet else "[OPTIMIZE]",
|
|
100
|
+
"build": "📚" if not quiet else "[BUILD]",
|
|
101
|
+
"link": "🔗" if not quiet else "[LINK]",
|
|
102
|
+
"search": "🔍" if not quiet else "[SEARCH]",
|
|
103
|
+
"target": "🎯" if not quiet else "[TARGET]",
|
|
104
|
+
"book": "📖" if not quiet else "[SECTION]",
|
|
105
|
+
"page": "📋" if not quiet else "[PAGE]",
|
|
106
|
+
"handshake": "🤝" if not quiet else "[CORRELATION]",
|
|
107
|
+
"cycle": "🔄" if not quiet else "[PATTERN]",
|
|
108
|
+
"rocket": "🚀" if not quiet else "[INIT]",
|
|
109
|
+
"disk": "💾" if not quiet else "[SIZE]",
|
|
110
|
+
"green": "🟢" if not quiet else "[LOW]",
|
|
111
|
+
"yellow": "🟡" if not quiet else "[MED]",
|
|
112
|
+
"red": "🔴" if not quiet else "[HIGH]",
|
|
113
|
+
"empty": "📭" if not quiet else "[EMPTY]",
|
|
114
|
+
"note": "📝" if not quiet else "[NOTE]",
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
def format_status(self, status_data: Dict[str, Any], verbose: bool = False) -> str:
|
|
118
|
+
"""Format memory status display."""
|
|
119
|
+
lines = []
|
|
120
|
+
lines.append("Agent Memory System Status")
|
|
121
|
+
lines.append("-" * 80)
|
|
122
|
+
|
|
123
|
+
if not status_data.get("success", True):
|
|
124
|
+
lines.append(
|
|
125
|
+
f"{self.emojis['error']} Error getting status: {status_data.get('error', 'Unknown error')}"
|
|
126
|
+
)
|
|
127
|
+
return "\n".join(lines)
|
|
128
|
+
|
|
129
|
+
# System overview
|
|
130
|
+
system_health = status_data.get("system_health")
|
|
131
|
+
if system_health is None:
|
|
132
|
+
system_health = "unknown"
|
|
133
|
+
health_emoji = {
|
|
134
|
+
"healthy": self.emojis["success"],
|
|
135
|
+
"needs_optimization": self.emojis["warning"],
|
|
136
|
+
"high_usage": self.emojis["stats"],
|
|
137
|
+
"no_memory_dir": self.emojis["file"],
|
|
138
|
+
}.get(system_health, self.emojis["info"])
|
|
139
|
+
|
|
140
|
+
lines.append(
|
|
141
|
+
f"{self.emojis['memory']} Memory System Health: {health_emoji} {system_health}"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# Handle null/None values properly
|
|
145
|
+
memory_dir = status_data.get("memory_directory")
|
|
146
|
+
lines.append(
|
|
147
|
+
f"{self.emojis['file']} Memory Directory: {memory_dir if memory_dir is not None else 'Unknown'}"
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
lines.append(
|
|
151
|
+
f"{self.emojis['optimize']} System Enabled: {'Yes' if status_data.get('system_enabled', True) else 'No'}"
|
|
152
|
+
)
|
|
153
|
+
lines.append(
|
|
154
|
+
f"{self.emojis['build']} Auto Learning: {'Yes' if status_data.get('auto_learning', True) else 'No'}"
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
total_agents = status_data.get("total_agents")
|
|
158
|
+
lines.append(
|
|
159
|
+
f"{self.emojis['stats']} Total Agents: {total_agents if total_agents is not None else 'Unknown'}"
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
lines.append(
|
|
163
|
+
f"{self.emojis['disk']} Total Size: {status_data.get('total_size_kb', 0):.1f} KB"
|
|
164
|
+
)
|
|
165
|
+
lines.append("")
|
|
166
|
+
|
|
167
|
+
# Optimization opportunities
|
|
168
|
+
opportunities = status_data.get("optimization_opportunities", [])
|
|
169
|
+
if opportunities:
|
|
170
|
+
lines.append(
|
|
171
|
+
f"{self.emojis['warning']} Optimization Opportunities ({len(opportunities)}):"
|
|
172
|
+
)
|
|
173
|
+
limit = 10 if verbose else 5
|
|
174
|
+
for opportunity in opportunities[:limit]:
|
|
175
|
+
lines.append(f" • {opportunity}")
|
|
176
|
+
if len(opportunities) > limit:
|
|
177
|
+
lines.append(f" ... and {len(opportunities) - limit} more")
|
|
178
|
+
lines.append("")
|
|
179
|
+
|
|
180
|
+
# Per-agent details
|
|
181
|
+
agents = status_data.get("agents", {})
|
|
182
|
+
if agents:
|
|
183
|
+
lines.append(f"{self.emojis['page']} Agent Memory Details:")
|
|
184
|
+
for agent_id, agent_info in sorted(agents.items()):
|
|
185
|
+
if "error" in agent_info:
|
|
186
|
+
lines.append(
|
|
187
|
+
f" {self.emojis['error']} {agent_id}: Error - {agent_info['error']}"
|
|
188
|
+
)
|
|
189
|
+
continue
|
|
190
|
+
|
|
191
|
+
size_kb = agent_info.get("size_kb", 0)
|
|
192
|
+
size_limit = agent_info.get("size_limit_kb", 8)
|
|
193
|
+
utilization = agent_info.get("size_utilization", 0)
|
|
194
|
+
sections = agent_info.get("sections", 0)
|
|
195
|
+
items = agent_info.get("items", 0)
|
|
196
|
+
last_modified = agent_info.get("last_modified", "Unknown")
|
|
197
|
+
auto_learning = agent_info.get("auto_learning", True)
|
|
198
|
+
|
|
199
|
+
# Format last modified time
|
|
200
|
+
try:
|
|
201
|
+
dt = datetime.fromisoformat(last_modified.replace("Z", "+00:00"))
|
|
202
|
+
last_modified_str = dt.strftime("%Y-%m-%d %H:%M:%S")
|
|
203
|
+
except:
|
|
204
|
+
last_modified_str = last_modified
|
|
205
|
+
|
|
206
|
+
# Status indicator based on usage
|
|
207
|
+
if utilization > 90:
|
|
208
|
+
status_emoji = self.emojis["red"]
|
|
209
|
+
elif utilization > 70:
|
|
210
|
+
status_emoji = self.emojis["yellow"]
|
|
211
|
+
else:
|
|
212
|
+
status_emoji = self.emojis["green"]
|
|
213
|
+
|
|
214
|
+
lines.append(f" {status_emoji} {agent_id}")
|
|
215
|
+
lines.append(
|
|
216
|
+
f" Size: {size_kb:.1f} KB / {size_limit} KB ({utilization:.1f}%)"
|
|
217
|
+
)
|
|
218
|
+
lines.append(f" Content: {sections} sections, {items} items")
|
|
219
|
+
lines.append(f" Auto-learning: {'On' if auto_learning else 'Off'}")
|
|
220
|
+
lines.append(f" Last modified: {last_modified_str}")
|
|
221
|
+
|
|
222
|
+
if verbose and agent_info.get("recent_items"):
|
|
223
|
+
lines.append(" Recent items:")
|
|
224
|
+
for item in agent_info["recent_items"][:3]:
|
|
225
|
+
lines.append(f" - {item}")
|
|
226
|
+
else:
|
|
227
|
+
lines.append(f"{self.emojis['empty']} No agent memories found")
|
|
228
|
+
|
|
229
|
+
return "\n".join(lines)
|
|
230
|
+
|
|
231
|
+
def format_memory_view(
|
|
232
|
+
self, agent_id: str, memory_content: str, format_type: str = "detailed"
|
|
233
|
+
) -> str:
|
|
234
|
+
"""Format memory viewing output."""
|
|
235
|
+
lines = []
|
|
236
|
+
|
|
237
|
+
if not memory_content:
|
|
238
|
+
lines.append(
|
|
239
|
+
f"{self.emojis['empty']} No memory found for agent: {agent_id}"
|
|
240
|
+
)
|
|
241
|
+
return "\n".join(lines)
|
|
242
|
+
|
|
243
|
+
lines.append(f"{self.emojis['agent']} Agent: {agent_id}")
|
|
244
|
+
lines.append("-" * 40)
|
|
245
|
+
|
|
246
|
+
if format_type == "full":
|
|
247
|
+
lines.append(memory_content)
|
|
248
|
+
else:
|
|
249
|
+
# Parse and display memory sections
|
|
250
|
+
sections = self._parse_memory_content(memory_content)
|
|
251
|
+
|
|
252
|
+
for section_name, items in sections.items():
|
|
253
|
+
if items:
|
|
254
|
+
lines.append(
|
|
255
|
+
f"\n{self.emojis['build']} {section_name} ({len(items)} items):"
|
|
256
|
+
)
|
|
257
|
+
limit = 10 if format_type == "detailed" else 5
|
|
258
|
+
for i, item in enumerate(items[:limit], 1):
|
|
259
|
+
lines.append(f" {i}. {item}")
|
|
260
|
+
if len(items) > limit:
|
|
261
|
+
lines.append(f" ... and {len(items) - limit} more")
|
|
262
|
+
|
|
263
|
+
return "\n".join(lines)
|
|
264
|
+
|
|
265
|
+
def format_optimization_results(
|
|
266
|
+
self, results: Dict[str, Any], is_single_agent: bool = True
|
|
267
|
+
) -> str:
|
|
268
|
+
"""Format optimization output."""
|
|
269
|
+
lines = []
|
|
270
|
+
|
|
271
|
+
if is_single_agent:
|
|
272
|
+
agent_id = results.get("agent_id", "unknown")
|
|
273
|
+
original_size = results.get("original_size", 0)
|
|
274
|
+
optimized_size = results.get("optimized_size", 0)
|
|
275
|
+
size_reduction = results.get("size_reduction", 0)
|
|
276
|
+
size_reduction_percent = results.get("size_reduction_percent", 0)
|
|
277
|
+
|
|
278
|
+
lines.append(
|
|
279
|
+
f"{self.emojis['success']} Optimization completed for {agent_id}"
|
|
280
|
+
)
|
|
281
|
+
lines.append(f" Original size: {original_size:,} bytes")
|
|
282
|
+
lines.append(f" Optimized size: {optimized_size:,} bytes")
|
|
283
|
+
lines.append(
|
|
284
|
+
f" Size reduction: {size_reduction:,} bytes ({size_reduction_percent}%)"
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
duplicates = results.get("duplicates_removed", 0)
|
|
288
|
+
consolidated = results.get("items_consolidated", 0)
|
|
289
|
+
reordered = results.get("items_reordered", 0)
|
|
290
|
+
|
|
291
|
+
if duplicates > 0:
|
|
292
|
+
lines.append(f" Duplicates removed: {duplicates}")
|
|
293
|
+
if consolidated > 0:
|
|
294
|
+
lines.append(f" Items consolidated: {consolidated}")
|
|
295
|
+
if reordered > 0:
|
|
296
|
+
lines.append(f" Sections reordered: {reordered}")
|
|
297
|
+
|
|
298
|
+
backup_path = results.get("backup_created")
|
|
299
|
+
if backup_path:
|
|
300
|
+
lines.append(f" Backup created: {backup_path}")
|
|
301
|
+
else:
|
|
302
|
+
# Bulk optimization results
|
|
303
|
+
summary = results.get("summary", {})
|
|
304
|
+
|
|
305
|
+
lines.append(f"{self.emojis['success']} Bulk optimization completed")
|
|
306
|
+
lines.append(f" Agents processed: {summary.get('agents_processed', 0)}")
|
|
307
|
+
lines.append(f" Agents optimized: {summary.get('agents_optimized', 0)}")
|
|
308
|
+
lines.append(
|
|
309
|
+
f" Total size before: {summary.get('total_size_before', 0):,} bytes"
|
|
310
|
+
)
|
|
311
|
+
lines.append(
|
|
312
|
+
f" Total size after: {summary.get('total_size_after', 0):,} bytes"
|
|
313
|
+
)
|
|
314
|
+
lines.append(
|
|
315
|
+
f" Total reduction: {summary.get('total_size_reduction', 0):,} bytes ({summary.get('total_size_reduction_percent', 0)}%)"
|
|
316
|
+
)
|
|
317
|
+
lines.append(
|
|
318
|
+
f" Total duplicates removed: {summary.get('total_duplicates_removed', 0)}"
|
|
319
|
+
)
|
|
320
|
+
lines.append(
|
|
321
|
+
f" Total items consolidated: {summary.get('total_items_consolidated', 0)}"
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
# Per-agent summary
|
|
325
|
+
agents_results = results.get("agents", {})
|
|
326
|
+
if agents_results:
|
|
327
|
+
lines.append(f"\n{self.emojis['stats']} Per-agent results:")
|
|
328
|
+
for agent_id, agent_result in agents_results.items():
|
|
329
|
+
if agent_result.get("success"):
|
|
330
|
+
reduction = agent_result.get("size_reduction_percent", 0)
|
|
331
|
+
duplicates = agent_result.get("duplicates_removed", 0)
|
|
332
|
+
consolidated = agent_result.get("items_consolidated", 0)
|
|
333
|
+
|
|
334
|
+
status_parts = []
|
|
335
|
+
if duplicates > 0:
|
|
336
|
+
status_parts.append(f"{duplicates} dupes")
|
|
337
|
+
if consolidated > 0:
|
|
338
|
+
status_parts.append(f"{consolidated} consolidated")
|
|
339
|
+
|
|
340
|
+
status = f" ({', '.join(status_parts)})" if status_parts else ""
|
|
341
|
+
lines.append(f" {agent_id}: {reduction}% reduction{status}")
|
|
342
|
+
else:
|
|
343
|
+
error = agent_result.get("error", "Unknown error")
|
|
344
|
+
lines.append(f" {agent_id}: {self.emojis['error']} {error}")
|
|
345
|
+
|
|
346
|
+
return "\n".join(lines)
|
|
347
|
+
|
|
348
|
+
def format_cross_reference(
|
|
349
|
+
self, cross_ref_data: Dict[str, Any], query: Optional[str] = None
|
|
350
|
+
) -> str:
|
|
351
|
+
"""Format pattern analysis output."""
|
|
352
|
+
lines = []
|
|
353
|
+
lines.append(f"{self.emojis['link']} Memory Cross-Reference Analysis")
|
|
354
|
+
lines.append("-" * 80)
|
|
355
|
+
|
|
356
|
+
if query:
|
|
357
|
+
lines.append(f"{self.emojis['search']} Searching for: '{query}'")
|
|
358
|
+
else:
|
|
359
|
+
lines.append(
|
|
360
|
+
f"{self.emojis['search']} Analyzing all agent memories for patterns..."
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
if cross_ref_data.get("success") is False:
|
|
364
|
+
lines.append(
|
|
365
|
+
f"{self.emojis['error']} Analysis failed: {cross_ref_data.get('error', 'Unknown error')}"
|
|
366
|
+
)
|
|
367
|
+
return "\n".join(lines)
|
|
368
|
+
|
|
369
|
+
# Display common patterns
|
|
370
|
+
common_patterns = cross_ref_data.get("common_patterns", [])
|
|
371
|
+
if common_patterns:
|
|
372
|
+
lines.append(
|
|
373
|
+
f"\n{self.emojis['cycle']} Common patterns found ({len(common_patterns)}):"
|
|
374
|
+
)
|
|
375
|
+
for pattern in common_patterns[:10]:
|
|
376
|
+
agents = ", ".join(pattern["agents"])
|
|
377
|
+
lines.append(f" • {pattern['pattern']}")
|
|
378
|
+
lines.append(f" Found in: {agents} ({pattern['count']} instances)")
|
|
379
|
+
else:
|
|
380
|
+
lines.append(f"\n{self.emojis['cycle']} No common patterns found")
|
|
381
|
+
|
|
382
|
+
# Display query matches if query was provided
|
|
383
|
+
if query and cross_ref_data.get("query_matches"):
|
|
384
|
+
lines.append(f"\n{self.emojis['target']} Query matches for '{query}':")
|
|
385
|
+
for match in cross_ref_data["query_matches"]:
|
|
386
|
+
lines.append(f" {self.emojis['page']} {match['agent']}:")
|
|
387
|
+
for line in match["matches"][:3]:
|
|
388
|
+
lines.append(f" • {line}")
|
|
389
|
+
|
|
390
|
+
# Display agent correlations
|
|
391
|
+
correlations = cross_ref_data.get("agent_correlations", {})
|
|
392
|
+
if correlations:
|
|
393
|
+
lines.append(f"\n{self.emojis['handshake']} Agent knowledge correlations:")
|
|
394
|
+
sorted_correlations = sorted(
|
|
395
|
+
correlations.items(), key=lambda x: x[1], reverse=True
|
|
396
|
+
)
|
|
397
|
+
for agents, count in sorted_correlations[:5]:
|
|
398
|
+
lines.append(f" {agents}: {count} common items")
|
|
399
|
+
else:
|
|
400
|
+
lines.append(
|
|
401
|
+
f"\n{self.emojis['handshake']} No significant correlations found"
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
return "\n".join(lines)
|
|
405
|
+
|
|
406
|
+
def format_as_json(self, data: Dict[str, Any], pretty: bool = True) -> str:
|
|
407
|
+
"""Format data as JSON."""
|
|
408
|
+
if pretty:
|
|
409
|
+
return json.dumps(data, indent=2, ensure_ascii=False)
|
|
410
|
+
return json.dumps(data, ensure_ascii=False)
|
|
411
|
+
|
|
412
|
+
def format_as_yaml(self, data: Dict[str, Any]) -> str:
|
|
413
|
+
"""Format data as YAML."""
|
|
414
|
+
return yaml.dump(data, default_flow_style=False, allow_unicode=True)
|
|
415
|
+
|
|
416
|
+
def format_as_table(self, headers: List[str], rows: List[List[Any]]) -> str:
|
|
417
|
+
"""Format data as a table."""
|
|
418
|
+
lines = []
|
|
419
|
+
|
|
420
|
+
# Calculate column widths
|
|
421
|
+
col_widths = [len(str(h)) for h in headers]
|
|
422
|
+
for row in rows:
|
|
423
|
+
for i, cell in enumerate(row):
|
|
424
|
+
col_widths[i] = max(col_widths[i], len(str(cell)))
|
|
425
|
+
|
|
426
|
+
# Create header
|
|
427
|
+
header_line = " | ".join(str(h).ljust(w) for h, w in zip(headers, col_widths))
|
|
428
|
+
lines.append(header_line)
|
|
429
|
+
lines.append("-" * len(header_line))
|
|
430
|
+
|
|
431
|
+
# Add rows
|
|
432
|
+
for row in rows:
|
|
433
|
+
row_line = " | ".join(
|
|
434
|
+
str(cell).ljust(w) for cell, w in zip(row, col_widths)
|
|
435
|
+
)
|
|
436
|
+
lines.append(row_line)
|
|
437
|
+
|
|
438
|
+
return "\n".join(lines)
|
|
439
|
+
|
|
440
|
+
def format_build_results(self, results: Dict[str, Any]) -> str:
|
|
441
|
+
"""Format memory build results."""
|
|
442
|
+
lines = []
|
|
443
|
+
lines.append(f"{self.emojis['build']} Memory Building from Documentation")
|
|
444
|
+
lines.append("-" * 80)
|
|
445
|
+
|
|
446
|
+
if results.get("success"):
|
|
447
|
+
lines.append(
|
|
448
|
+
f"{self.emojis['success']} Successfully processed documentation"
|
|
449
|
+
)
|
|
450
|
+
lines.append(f" Files processed: {results.get('files_processed', 0)}")
|
|
451
|
+
lines.append(f" Memories created: {results.get('memories_created', 0)}")
|
|
452
|
+
lines.append(f" Memories updated: {results.get('memories_updated', 0)}")
|
|
453
|
+
lines.append(
|
|
454
|
+
f" Agents affected: {results.get('total_agents_affected', 0)}"
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
if results.get("agents_affected"):
|
|
458
|
+
lines.append(
|
|
459
|
+
f" Affected agents: {', '.join(results['agents_affected'])}"
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
# Show file-specific results
|
|
463
|
+
files_results = results.get("files", {})
|
|
464
|
+
if files_results:
|
|
465
|
+
lines.append(f"\n{self.emojis['page']} File processing details:")
|
|
466
|
+
for file_path, file_result in files_results.items():
|
|
467
|
+
if file_result.get("success"):
|
|
468
|
+
extracted = file_result.get("items_extracted", 0)
|
|
469
|
+
created = file_result.get("memories_created", 0)
|
|
470
|
+
lines.append(
|
|
471
|
+
f" {file_path}: {extracted} items extracted, {created} memories created"
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
if results.get("errors"):
|
|
475
|
+
lines.append(f"\n{self.emojis['warning']} Errors encountered:")
|
|
476
|
+
for error in results["errors"]:
|
|
477
|
+
lines.append(f" {error}")
|
|
478
|
+
else:
|
|
479
|
+
lines.append(
|
|
480
|
+
f"{self.emojis['error']} Build failed: {results.get('error', 'Unknown error')}"
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
return "\n".join(lines)
|
|
484
|
+
|
|
485
|
+
def format_agent_memories_summary(
|
|
486
|
+
self, agent_memories: Dict[str, Dict], format_type: str = "summary"
|
|
487
|
+
) -> str:
|
|
488
|
+
"""Format summary of all agent memories."""
|
|
489
|
+
lines = []
|
|
490
|
+
|
|
491
|
+
if not agent_memories:
|
|
492
|
+
lines.append(f"{self.emojis['empty']} No agent memories found")
|
|
493
|
+
return "\n".join(lines)
|
|
494
|
+
|
|
495
|
+
lines.append(
|
|
496
|
+
f"{self.emojis['stats']} Found memories for {len(agent_memories)} agents"
|
|
497
|
+
)
|
|
498
|
+
lines.append("")
|
|
499
|
+
|
|
500
|
+
total_items = 0
|
|
501
|
+
for agent_id, sections in sorted(agent_memories.items()):
|
|
502
|
+
item_count = sum(len(items) for items in sections.values())
|
|
503
|
+
total_items += item_count
|
|
504
|
+
|
|
505
|
+
lines.append(f"{self.emojis['agent']} {agent_id}")
|
|
506
|
+
lines.append(
|
|
507
|
+
f" {self.emojis['build']} {len(sections)} sections, {item_count} total items"
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
if format_type == "summary":
|
|
511
|
+
# Show section summary
|
|
512
|
+
for section_name, items in sections.items():
|
|
513
|
+
if items:
|
|
514
|
+
lines.append(f" • {section_name}: {len(items)} items")
|
|
515
|
+
elif format_type == "detailed":
|
|
516
|
+
for section_name, items in sections.items():
|
|
517
|
+
if items:
|
|
518
|
+
lines.append(f"\n {self.emojis['book']} {section_name}:")
|
|
519
|
+
for item in items[:3]:
|
|
520
|
+
lines.append(f" • {item}")
|
|
521
|
+
if len(items) > 3:
|
|
522
|
+
lines.append(f" ... and {len(items) - 3} more")
|
|
523
|
+
lines.append("")
|
|
524
|
+
|
|
525
|
+
lines.append(
|
|
526
|
+
f"{self.emojis['stats']} Total: {total_items} memory items across {len(agent_memories)} agents"
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
# Show cross-references if we have multiple agents
|
|
530
|
+
if len(agent_memories) > 1:
|
|
531
|
+
lines.append(
|
|
532
|
+
f"\n{self.emojis['link']} Cross-References and Common Patterns:"
|
|
533
|
+
)
|
|
534
|
+
common_patterns = self._find_common_patterns(agent_memories)
|
|
535
|
+
if common_patterns:
|
|
536
|
+
lines.append(f"\n{self.emojis['cycle']} Most Common Patterns:")
|
|
537
|
+
for pattern, count, agents in common_patterns[:5]:
|
|
538
|
+
lines.append(
|
|
539
|
+
f" • {pattern[:80]}{'...' if len(pattern) > 80 else ''}"
|
|
540
|
+
)
|
|
541
|
+
lines.append(f" Found in: {', '.join(agents)} ({count} agents)")
|
|
542
|
+
else:
|
|
543
|
+
lines.append(" No common patterns found across agents")
|
|
544
|
+
|
|
545
|
+
return "\n".join(lines)
|
|
546
|
+
|
|
547
|
+
def _parse_memory_content(self, content: str) -> Dict[str, List[str]]:
|
|
548
|
+
"""Parse memory content into sections and items."""
|
|
549
|
+
sections = {}
|
|
550
|
+
current_section = None
|
|
551
|
+
current_items = []
|
|
552
|
+
|
|
553
|
+
for line in content.split("\n"):
|
|
554
|
+
line = line.strip()
|
|
555
|
+
|
|
556
|
+
if line.startswith("## ") and not line.startswith("## Memory Usage"):
|
|
557
|
+
# New section
|
|
558
|
+
if current_section and current_items:
|
|
559
|
+
sections[current_section] = current_items.copy()
|
|
560
|
+
|
|
561
|
+
current_section = line[3:].strip()
|
|
562
|
+
current_items = []
|
|
563
|
+
elif line.startswith("- ") and current_section:
|
|
564
|
+
# Item in current section
|
|
565
|
+
item = line[2:].strip()
|
|
566
|
+
if item and len(item) > 5: # Filter out very short items
|
|
567
|
+
current_items.append(item)
|
|
568
|
+
|
|
569
|
+
# Add final section
|
|
570
|
+
if current_section and current_items:
|
|
571
|
+
sections[current_section] = current_items
|
|
572
|
+
|
|
573
|
+
return sections
|
|
574
|
+
|
|
575
|
+
def _find_common_patterns(
|
|
576
|
+
self, agent_memories: Dict[str, Dict]
|
|
577
|
+
) -> List[Tuple[str, int, List[str]]]:
|
|
578
|
+
"""Find common patterns across agent memories."""
|
|
579
|
+
pattern_agents = {}
|
|
580
|
+
|
|
581
|
+
# Collect all patterns and which agents have them
|
|
582
|
+
for agent_id, sections in agent_memories.items():
|
|
583
|
+
seen_patterns = set()
|
|
584
|
+
|
|
585
|
+
for _section_name, items in sections.items():
|
|
586
|
+
for item in items:
|
|
587
|
+
# Normalize item for comparison (lowercase, basic cleanup)
|
|
588
|
+
normalized = item.lower().strip()
|
|
589
|
+
if len(normalized) > 10 and normalized not in seen_patterns:
|
|
590
|
+
if normalized not in pattern_agents:
|
|
591
|
+
pattern_agents[normalized] = []
|
|
592
|
+
pattern_agents[normalized].append(agent_id)
|
|
593
|
+
seen_patterns.add(normalized)
|
|
594
|
+
|
|
595
|
+
# Find patterns that appear in multiple agents
|
|
596
|
+
common_patterns = []
|
|
597
|
+
for pattern, agents in pattern_agents.items():
|
|
598
|
+
if len(agents) > 1:
|
|
599
|
+
common_patterns.append((pattern, len(agents), agents))
|
|
600
|
+
|
|
601
|
+
# Sort by number of agents
|
|
602
|
+
common_patterns.sort(key=lambda x: x[1], reverse=True)
|
|
603
|
+
|
|
604
|
+
return common_patterns
|