claude-mpm 4.1.0__py3-none-any.whl → 4.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/BUILD_NUMBER +1 -1
- claude_mpm/VERSION +1 -1
- claude_mpm/__main__.py +1 -1
- claude_mpm/agents/BASE_PM.md +74 -46
- claude_mpm/agents/INSTRUCTIONS.md +11 -153
- claude_mpm/agents/WORKFLOW.md +61 -321
- claude_mpm/agents/__init__.py +11 -11
- claude_mpm/agents/agent_loader.py +23 -20
- claude_mpm/agents/agent_loader_integration.py +1 -1
- claude_mpm/agents/agents_metadata.py +27 -0
- claude_mpm/agents/async_agent_loader.py +5 -8
- claude_mpm/agents/base_agent_loader.py +36 -25
- claude_mpm/agents/frontmatter_validator.py +6 -6
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +9 -9
- claude_mpm/agents/templates/api_qa.json +47 -2
- claude_mpm/agents/templates/imagemagick.json +256 -0
- claude_mpm/agents/templates/qa.json +41 -2
- claude_mpm/agents/templates/ticketing.json +5 -5
- claude_mpm/agents/templates/web_qa.json +133 -58
- claude_mpm/agents/templates/web_ui.json +3 -3
- claude_mpm/cli/__init__.py +51 -46
- claude_mpm/cli/__main__.py +1 -1
- claude_mpm/cli/commands/__init__.py +10 -12
- claude_mpm/cli/commands/agent_manager.py +186 -181
- claude_mpm/cli/commands/agents.py +271 -268
- claude_mpm/cli/commands/aggregate.py +30 -29
- claude_mpm/cli/commands/cleanup.py +50 -44
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
- claude_mpm/cli/commands/config.py +162 -127
- claude_mpm/cli/commands/doctor.py +52 -62
- claude_mpm/cli/commands/info.py +37 -25
- claude_mpm/cli/commands/mcp.py +3 -7
- claude_mpm/cli/commands/mcp_command_router.py +14 -18
- claude_mpm/cli/commands/mcp_install_commands.py +28 -23
- claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
- claude_mpm/cli/commands/mcp_server_commands.py +23 -17
- claude_mpm/cli/commands/memory.py +192 -141
- claude_mpm/cli/commands/monitor.py +117 -88
- claude_mpm/cli/commands/run.py +120 -84
- claude_mpm/cli/commands/run_config_checker.py +4 -5
- claude_mpm/cli/commands/socketio_monitor.py +17 -19
- claude_mpm/cli/commands/tickets.py +92 -92
- claude_mpm/cli/parser.py +1 -5
- claude_mpm/cli/parsers/__init__.py +1 -1
- claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
- claude_mpm/cli/parsers/agents_parser.py +2 -3
- claude_mpm/cli/parsers/base_parser.py +7 -5
- claude_mpm/cli/parsers/mcp_parser.py +4 -2
- claude_mpm/cli/parsers/monitor_parser.py +26 -18
- claude_mpm/cli/shared/__init__.py +10 -10
- claude_mpm/cli/shared/argument_patterns.py +57 -71
- claude_mpm/cli/shared/base_command.py +61 -53
- claude_mpm/cli/shared/error_handling.py +62 -58
- claude_mpm/cli/shared/output_formatters.py +78 -77
- claude_mpm/cli/startup_logging.py +204 -172
- claude_mpm/cli/utils.py +10 -11
- claude_mpm/cli_module/__init__.py +1 -1
- claude_mpm/cli_module/args.py +1 -1
- claude_mpm/cli_module/migration_example.py +5 -5
- claude_mpm/config/__init__.py +9 -9
- claude_mpm/config/agent_config.py +15 -14
- claude_mpm/config/experimental_features.py +4 -4
- claude_mpm/config/paths.py +0 -1
- claude_mpm/config/socketio_config.py +5 -6
- claude_mpm/constants.py +1 -2
- claude_mpm/core/__init__.py +8 -8
- claude_mpm/core/agent_name_normalizer.py +1 -1
- claude_mpm/core/agent_registry.py +20 -23
- claude_mpm/core/agent_session_manager.py +3 -3
- claude_mpm/core/base_service.py +7 -15
- claude_mpm/core/cache.py +4 -6
- claude_mpm/core/claude_runner.py +85 -113
- claude_mpm/core/config.py +43 -28
- claude_mpm/core/config_aliases.py +0 -9
- claude_mpm/core/config_constants.py +52 -30
- claude_mpm/core/constants.py +0 -1
- claude_mpm/core/container.py +18 -27
- claude_mpm/core/exceptions.py +2 -2
- claude_mpm/core/factories.py +10 -12
- claude_mpm/core/framework_loader.py +581 -280
- claude_mpm/core/hook_manager.py +26 -22
- claude_mpm/core/hook_performance_config.py +58 -47
- claude_mpm/core/injectable_service.py +1 -1
- claude_mpm/core/interactive_session.py +61 -152
- claude_mpm/core/interfaces.py +1 -100
- claude_mpm/core/lazy.py +5 -5
- claude_mpm/core/log_manager.py +587 -0
- claude_mpm/core/logger.py +125 -8
- claude_mpm/core/logging_config.py +15 -15
- claude_mpm/core/minimal_framework_loader.py +5 -8
- claude_mpm/core/oneshot_session.py +15 -33
- claude_mpm/core/optimized_agent_loader.py +4 -6
- claude_mpm/core/optimized_startup.py +2 -1
- claude_mpm/core/output_style_manager.py +147 -106
- claude_mpm/core/pm_hook_interceptor.py +0 -1
- claude_mpm/core/service_registry.py +11 -8
- claude_mpm/core/session_manager.py +1 -2
- claude_mpm/core/shared/__init__.py +1 -1
- claude_mpm/core/shared/config_loader.py +101 -97
- claude_mpm/core/shared/path_resolver.py +72 -68
- claude_mpm/core/shared/singleton_manager.py +56 -50
- claude_mpm/core/socketio_pool.py +26 -6
- claude_mpm/core/tool_access_control.py +4 -5
- claude_mpm/core/typing_utils.py +50 -59
- claude_mpm/core/unified_agent_registry.py +14 -19
- claude_mpm/core/unified_config.py +4 -6
- claude_mpm/core/unified_paths.py +197 -109
- claude_mpm/dashboard/open_dashboard.py +2 -4
- claude_mpm/experimental/cli_enhancements.py +51 -36
- claude_mpm/generators/agent_profile_generator.py +2 -4
- claude_mpm/hooks/base_hook.py +1 -2
- claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
- claude_mpm/hooks/claude_hooks/event_handlers.py +93 -38
- claude_mpm/hooks/claude_hooks/hook_handler.py +130 -76
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
- claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
- claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
- claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
- claude_mpm/hooks/memory_integration_hook.py +5 -5
- claude_mpm/hooks/tool_call_interceptor.py +1 -1
- claude_mpm/hooks/validation_hooks.py +4 -4
- claude_mpm/init.py +4 -9
- claude_mpm/models/__init__.py +2 -2
- claude_mpm/models/agent_session.py +11 -14
- claude_mpm/scripts/mcp_server.py +20 -11
- claude_mpm/scripts/mcp_wrapper.py +5 -5
- claude_mpm/scripts/mpm_doctor.py +321 -0
- claude_mpm/scripts/socketio_daemon.py +28 -25
- claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
- claude_mpm/scripts/socketio_server_manager.py +116 -95
- claude_mpm/services/__init__.py +49 -49
- claude_mpm/services/agent_capabilities_service.py +12 -18
- claude_mpm/services/agents/__init__.py +22 -22
- claude_mpm/services/agents/agent_builder.py +140 -119
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
- claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
- claude_mpm/services/agents/deployment/agent_deployment.py +136 -106
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
- claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
- claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
- claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
- claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
- claude_mpm/services/agents/deployment/agent_validator.py +0 -1
- claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
- claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
- claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
- claude_mpm/services/agents/deployment/config/__init__.py +1 -1
- claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
- claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
- claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
- claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
- claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
- claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
- claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
- claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
- claude_mpm/services/agents/deployment/results/__init__.py +1 -1
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
- claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
- claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
- claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
- claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
- claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
- claude_mpm/services/agents/loading/__init__.py +1 -1
- claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
- claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
- claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
- claude_mpm/services/agents/management/__init__.py +1 -1
- claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
- claude_mpm/services/agents/management/agent_management_service.py +5 -9
- claude_mpm/services/agents/memory/__init__.py +4 -4
- claude_mpm/services/agents/memory/agent_memory_manager.py +280 -160
- claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
- claude_mpm/services/agents/memory/content_manager.py +44 -38
- claude_mpm/services/agents/memory/template_generator.py +4 -6
- claude_mpm/services/agents/registry/__init__.py +10 -6
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
- claude_mpm/services/agents/registry/modification_tracker.py +3 -6
- claude_mpm/services/async_session_logger.py +1 -2
- claude_mpm/services/claude_session_logger.py +1 -2
- claude_mpm/services/command_deployment_service.py +173 -0
- claude_mpm/services/command_handler_service.py +20 -22
- claude_mpm/services/core/__init__.py +25 -25
- claude_mpm/services/core/base.py +0 -5
- claude_mpm/services/core/interfaces/__init__.py +32 -32
- claude_mpm/services/core/interfaces/agent.py +0 -21
- claude_mpm/services/core/interfaces/communication.py +0 -27
- claude_mpm/services/core/interfaces/infrastructure.py +0 -56
- claude_mpm/services/core/interfaces/service.py +0 -29
- claude_mpm/services/diagnostics/__init__.py +1 -1
- claude_mpm/services/diagnostics/checks/__init__.py +6 -6
- claude_mpm/services/diagnostics/checks/agent_check.py +89 -80
- claude_mpm/services/diagnostics/checks/base_check.py +12 -16
- claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
- claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
- claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
- claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
- claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
- claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
- claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
- claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
- claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
- claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
- claude_mpm/services/diagnostics/models.py +21 -19
- claude_mpm/services/event_aggregator.py +10 -17
- claude_mpm/services/event_bus/__init__.py +1 -1
- claude_mpm/services/event_bus/config.py +54 -35
- claude_mpm/services/event_bus/event_bus.py +76 -71
- claude_mpm/services/event_bus/relay.py +74 -64
- claude_mpm/services/events/__init__.py +11 -11
- claude_mpm/services/events/consumers/__init__.py +3 -3
- claude_mpm/services/events/consumers/dead_letter.py +71 -63
- claude_mpm/services/events/consumers/logging.py +39 -37
- claude_mpm/services/events/consumers/metrics.py +56 -57
- claude_mpm/services/events/consumers/socketio.py +82 -81
- claude_mpm/services/events/core.py +110 -99
- claude_mpm/services/events/interfaces.py +56 -72
- claude_mpm/services/events/producers/__init__.py +1 -1
- claude_mpm/services/events/producers/hook.py +38 -38
- claude_mpm/services/events/producers/system.py +46 -44
- claude_mpm/services/exceptions.py +81 -80
- claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
- claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
- claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
- claude_mpm/services/hook_service.py +6 -9
- claude_mpm/services/infrastructure/__init__.py +1 -1
- claude_mpm/services/infrastructure/context_preservation.py +8 -12
- claude_mpm/services/infrastructure/monitoring.py +21 -23
- claude_mpm/services/mcp_gateway/__init__.py +37 -37
- claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
- claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
- claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
- claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
- claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
- claude_mpm/services/mcp_gateway/core/base.py +0 -3
- claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
- claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
- claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
- claude_mpm/services/mcp_gateway/main.py +2 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
- claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
- claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
- claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
- claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
- claude_mpm/services/memory/__init__.py +3 -3
- claude_mpm/services/memory/builder.py +3 -6
- claude_mpm/services/memory/cache/__init__.py +1 -1
- claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
- claude_mpm/services/memory/cache/simple_cache.py +1 -1
- claude_mpm/services/memory/indexed_memory.py +5 -7
- claude_mpm/services/memory/optimizer.py +7 -10
- claude_mpm/services/memory/router.py +8 -9
- claude_mpm/services/memory_hook_service.py +48 -34
- claude_mpm/services/monitor_build_service.py +77 -73
- claude_mpm/services/port_manager.py +130 -108
- claude_mpm/services/project/analyzer.py +12 -10
- claude_mpm/services/project/registry.py +11 -11
- claude_mpm/services/recovery_manager.py +10 -19
- claude_mpm/services/response_tracker.py +0 -1
- claude_mpm/services/runner_configuration_service.py +19 -20
- claude_mpm/services/session_management_service.py +7 -11
- claude_mpm/services/shared/__init__.py +1 -1
- claude_mpm/services/shared/async_service_base.py +58 -50
- claude_mpm/services/shared/config_service_base.py +73 -67
- claude_mpm/services/shared/lifecycle_service_base.py +82 -78
- claude_mpm/services/shared/manager_base.py +94 -82
- claude_mpm/services/shared/service_factory.py +96 -98
- claude_mpm/services/socketio/__init__.py +3 -3
- claude_mpm/services/socketio/client_proxy.py +5 -5
- claude_mpm/services/socketio/event_normalizer.py +199 -181
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +5 -4
- claude_mpm/services/socketio/handlers/connection.py +163 -136
- claude_mpm/services/socketio/handlers/file.py +13 -14
- claude_mpm/services/socketio/handlers/git.py +12 -7
- claude_mpm/services/socketio/handlers/hook.py +49 -44
- claude_mpm/services/socketio/handlers/memory.py +0 -1
- claude_mpm/services/socketio/handlers/project.py +0 -1
- claude_mpm/services/socketio/handlers/registry.py +37 -19
- claude_mpm/services/socketio/migration_utils.py +98 -84
- claude_mpm/services/socketio/server/__init__.py +1 -1
- claude_mpm/services/socketio/server/broadcaster.py +81 -87
- claude_mpm/services/socketio/server/core.py +65 -54
- claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
- claude_mpm/services/socketio/server/main.py +64 -38
- claude_mpm/services/socketio_client_manager.py +10 -12
- claude_mpm/services/subprocess_launcher_service.py +4 -7
- claude_mpm/services/system_instructions_service.py +13 -14
- claude_mpm/services/ticket_manager.py +2 -2
- claude_mpm/services/utility_service.py +5 -13
- claude_mpm/services/version_control/__init__.py +16 -16
- claude_mpm/services/version_control/branch_strategy.py +5 -8
- claude_mpm/services/version_control/conflict_resolution.py +9 -23
- claude_mpm/services/version_control/git_operations.py +5 -7
- claude_mpm/services/version_control/semantic_versioning.py +16 -17
- claude_mpm/services/version_control/version_parser.py +13 -18
- claude_mpm/services/version_service.py +10 -11
- claude_mpm/storage/__init__.py +1 -1
- claude_mpm/storage/state_storage.py +22 -28
- claude_mpm/utils/__init__.py +6 -6
- claude_mpm/utils/agent_dependency_loader.py +47 -33
- claude_mpm/utils/config_manager.py +11 -14
- claude_mpm/utils/dependency_cache.py +1 -1
- claude_mpm/utils/dependency_manager.py +13 -17
- claude_mpm/utils/dependency_strategies.py +8 -10
- claude_mpm/utils/environment_context.py +3 -9
- claude_mpm/utils/error_handler.py +3 -13
- claude_mpm/utils/file_utils.py +1 -1
- claude_mpm/utils/path_operations.py +8 -12
- claude_mpm/utils/robust_installer.py +110 -33
- claude_mpm/utils/subprocess_utils.py +5 -6
- claude_mpm/validation/agent_validator.py +3 -6
- claude_mpm/validation/frontmatter_validator.py +1 -1
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/METADATA +1 -1
- claude_mpm-4.1.2.dist-info/RECORD +498 -0
- claude_mpm-4.1.0.dist-info/RECORD +0 -494
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
claude_mpm/core/logger.py
CHANGED
|
@@ -11,16 +11,22 @@ import json
|
|
|
11
11
|
import logging
|
|
12
12
|
import logging.handlers
|
|
13
13
|
import sys
|
|
14
|
+
import threading
|
|
14
15
|
import time
|
|
15
16
|
from collections import defaultdict
|
|
16
17
|
from datetime import datetime
|
|
17
18
|
from enum import Enum
|
|
18
19
|
from pathlib import Path
|
|
19
|
-
from typing import Any, Dict,
|
|
20
|
+
from typing import Any, Dict, Optional
|
|
21
|
+
|
|
22
|
+
from claude_mpm.core.unified_paths import get_project_root
|
|
20
23
|
|
|
21
24
|
# Rich support has been removed
|
|
22
25
|
HAS_RICH = False
|
|
23
26
|
|
|
27
|
+
# Thread lock for symlink creation to prevent race conditions
|
|
28
|
+
_symlink_lock = threading.Lock()
|
|
29
|
+
|
|
24
30
|
|
|
25
31
|
class LogLevel(Enum):
|
|
26
32
|
"""Log levels for different verbosity."""
|
|
@@ -225,8 +231,6 @@ def setup_logging(
|
|
|
225
231
|
# Use default log directory
|
|
226
232
|
if log_dir is None:
|
|
227
233
|
# Use deployment root for logs to keep everything centralized
|
|
228
|
-
from claude_mpm.core.unified_paths import get_project_root
|
|
229
|
-
|
|
230
234
|
deployment_root = get_project_root()
|
|
231
235
|
log_dir = deployment_root / ".claude-mpm" / "logs"
|
|
232
236
|
|
|
@@ -238,12 +242,59 @@ def setup_logging(
|
|
|
238
242
|
|
|
239
243
|
file_handler = logging.FileHandler(log_file)
|
|
240
244
|
|
|
241
|
-
#
|
|
245
|
+
# Clean up old MPM logs (using configured retention count)
|
|
246
|
+
try:
|
|
247
|
+
deleted_count = cleanup_old_mpm_logs(log_dir)
|
|
248
|
+
if deleted_count > 0:
|
|
249
|
+
# Log to the new file handler that we're about to add
|
|
250
|
+
pass # Deletion count will be logged when logger is ready
|
|
251
|
+
except Exception:
|
|
252
|
+
pass # Ignore cleanup errors
|
|
253
|
+
|
|
254
|
+
# Also create a symlink to latest log (with thread safety)
|
|
242
255
|
latest_link = log_dir / "latest.log"
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
256
|
+
|
|
257
|
+
# Use a lock to prevent race conditions in concurrent environments
|
|
258
|
+
with _symlink_lock:
|
|
259
|
+
# Remove existing symlink/file if it exists
|
|
260
|
+
# Note: We need to handle both regular files and symlinks (including broken ones)
|
|
261
|
+
try:
|
|
262
|
+
# unlink() works for both files and symlinks, even broken ones
|
|
263
|
+
# This is more robust than checking exists() which returns False for broken symlinks
|
|
264
|
+
if latest_link.is_symlink() or latest_link.exists():
|
|
265
|
+
latest_link.unlink()
|
|
266
|
+
except (OSError, PermissionError) as e:
|
|
267
|
+
# Log warning but continue - symlink is nice-to-have, not critical
|
|
268
|
+
logger.debug(f"Could not remove existing latest.log: {e}")
|
|
269
|
+
except Exception as e:
|
|
270
|
+
# Catch any other unexpected errors
|
|
271
|
+
logger.debug(f"Unexpected error removing latest.log: {e}")
|
|
272
|
+
|
|
273
|
+
# Create new symlink with proper error handling
|
|
274
|
+
try:
|
|
275
|
+
# Use relative path for better portability
|
|
276
|
+
latest_link.symlink_to(log_file.name)
|
|
277
|
+
except FileExistsError:
|
|
278
|
+
# This can happen in race conditions - try to remove and recreate
|
|
279
|
+
try:
|
|
280
|
+
latest_link.unlink()
|
|
281
|
+
latest_link.symlink_to(log_file.name)
|
|
282
|
+
except Exception as e:
|
|
283
|
+
logger.debug(
|
|
284
|
+
f"Could not recreate latest.log symlink after FileExistsError: {e}"
|
|
285
|
+
)
|
|
286
|
+
except (OSError, NotImplementedError) as e:
|
|
287
|
+
# Handle platforms where symlinks aren't supported (e.g., Windows without admin)
|
|
288
|
+
# or filesystem doesn't support symlinks
|
|
289
|
+
logger.debug(f"Could not create latest.log symlink: {e}")
|
|
290
|
+
# Fallback: try to create a regular file with reference to actual log
|
|
291
|
+
try:
|
|
292
|
+
latest_link.write_text(f"Latest log: {log_file.name}\n")
|
|
293
|
+
except Exception:
|
|
294
|
+
pass # Silently fail - logging should not break the application
|
|
295
|
+
except Exception as e:
|
|
296
|
+
# Catch any other unexpected errors to ensure logging doesn't break
|
|
297
|
+
logger.debug(f"Unexpected error creating latest.log symlink: {e}")
|
|
247
298
|
|
|
248
299
|
file_handler.setLevel(logging.DEBUG)
|
|
249
300
|
file_handler.setFormatter(formatter if json_format else detailed_formatter)
|
|
@@ -255,6 +306,72 @@ def setup_logging(
|
|
|
255
306
|
return logger
|
|
256
307
|
|
|
257
308
|
|
|
309
|
+
def cleanup_old_mpm_logs(
|
|
310
|
+
log_dir: Optional[Path] = None, keep_count: Optional[int] = None
|
|
311
|
+
) -> int:
|
|
312
|
+
"""
|
|
313
|
+
Clean up old MPM log files using time-based retention.
|
|
314
|
+
|
|
315
|
+
WHY: This function now delegates to LogManager for unified log management
|
|
316
|
+
with time-based retention instead of count-based.
|
|
317
|
+
|
|
318
|
+
DESIGN DECISIONS:
|
|
319
|
+
- Delegates to LogManager for consistency
|
|
320
|
+
- Uses time-based retention (48 hours default)
|
|
321
|
+
- Maintains backward compatibility
|
|
322
|
+
|
|
323
|
+
Args:
|
|
324
|
+
log_dir: Directory containing log files (defaults to .claude-mpm/logs)
|
|
325
|
+
keep_count: Ignored (kept for backward compatibility)
|
|
326
|
+
|
|
327
|
+
Returns:
|
|
328
|
+
Number of log files deleted
|
|
329
|
+
"""
|
|
330
|
+
try:
|
|
331
|
+
from .log_manager import get_log_manager
|
|
332
|
+
|
|
333
|
+
log_manager = get_log_manager()
|
|
334
|
+
|
|
335
|
+
# Use LogManager's time-based cleanup (48 hours default)
|
|
336
|
+
return log_manager.cleanup_old_mpm_logs(log_dir)
|
|
337
|
+
except ImportError:
|
|
338
|
+
# Fallback to old implementation if LogManager not available
|
|
339
|
+
# Get retention count from configuration if not specified
|
|
340
|
+
if keep_count is None:
|
|
341
|
+
from claude_mpm.core.config_constants import ConfigConstants
|
|
342
|
+
|
|
343
|
+
keep_count = (
|
|
344
|
+
ConfigConstants.get_logging_setting("mpm_logs_retention_count") or 10
|
|
345
|
+
)
|
|
346
|
+
if log_dir is None:
|
|
347
|
+
deployment_root = get_project_root()
|
|
348
|
+
log_dir = deployment_root / ".claude-mpm" / "logs"
|
|
349
|
+
|
|
350
|
+
if not log_dir.exists():
|
|
351
|
+
return 0
|
|
352
|
+
|
|
353
|
+
# Get all MPM log files
|
|
354
|
+
log_files = sorted(
|
|
355
|
+
log_dir.glob("mpm_*.log"), key=lambda p: p.stat().st_mtime, reverse=True
|
|
356
|
+
) # Newest first
|
|
357
|
+
|
|
358
|
+
if len(log_files) <= keep_count:
|
|
359
|
+
return 0 # Already within limit
|
|
360
|
+
|
|
361
|
+
# Delete older files beyond keep_count
|
|
362
|
+
deleted_count = 0
|
|
363
|
+
for log_file in log_files[
|
|
364
|
+
keep_count:
|
|
365
|
+
]: # Keep only the most recent keep_count files
|
|
366
|
+
try:
|
|
367
|
+
log_file.unlink()
|
|
368
|
+
deleted_count += 1
|
|
369
|
+
except Exception:
|
|
370
|
+
pass # Ignore deletion errors
|
|
371
|
+
|
|
372
|
+
return deleted_count
|
|
373
|
+
|
|
374
|
+
|
|
258
375
|
def get_logger(name: str) -> logging.Logger:
|
|
259
376
|
"""Get a logger instance."""
|
|
260
377
|
return logging.getLogger(f"claude_mpm.{name}")
|
|
@@ -18,21 +18,21 @@ while maintaining backwards compatibility.
|
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
20
|
import functools
|
|
21
|
-
import json
|
|
22
21
|
import logging
|
|
23
22
|
import time
|
|
24
23
|
from contextlib import contextmanager
|
|
25
|
-
from datetime import datetime
|
|
26
24
|
from pathlib import Path
|
|
27
25
|
from typing import Any, Dict, Optional, Union
|
|
28
26
|
|
|
29
27
|
from claude_mpm.core.logger import (
|
|
30
28
|
JsonFormatter,
|
|
31
|
-
StreamingHandler,
|
|
32
29
|
finalize_streaming_logs,
|
|
33
30
|
)
|
|
34
31
|
from claude_mpm.core.logger import get_logger as _get_logger
|
|
35
|
-
from claude_mpm.core.logger import
|
|
32
|
+
from claude_mpm.core.logger import (
|
|
33
|
+
log_async_performance,
|
|
34
|
+
log_performance,
|
|
35
|
+
)
|
|
36
36
|
from claude_mpm.core.logger import setup_logging as _setup_logging
|
|
37
37
|
|
|
38
38
|
# Standard log format for consistency
|
|
@@ -454,19 +454,19 @@ def log_with_level(
|
|
|
454
454
|
|
|
455
455
|
# Export main functions and decorators
|
|
456
456
|
__all__ = [
|
|
457
|
-
"get_logger",
|
|
458
|
-
"configure_logging",
|
|
459
|
-
"log_operation",
|
|
460
|
-
"log_performance_context",
|
|
461
|
-
"log_function_call",
|
|
462
|
-
"log_async_function_call",
|
|
463
|
-
"log_with_level",
|
|
464
|
-
"LogContext",
|
|
465
|
-
"ContextualLogger",
|
|
466
457
|
"LOGGING_STANDARDS",
|
|
467
458
|
"LOG_LEVELS",
|
|
459
|
+
"ContextualLogger",
|
|
460
|
+
"LogContext",
|
|
461
|
+
"configure_logging",
|
|
462
|
+
"finalize_streaming_logs",
|
|
463
|
+
"get_logger",
|
|
464
|
+
"log_async_function_call",
|
|
465
|
+
"log_async_performance",
|
|
466
|
+
"log_function_call",
|
|
467
|
+
"log_operation",
|
|
468
468
|
# Re-export from core.logger for backwards compatibility
|
|
469
469
|
"log_performance",
|
|
470
|
-
"
|
|
471
|
-
"
|
|
470
|
+
"log_performance_context",
|
|
471
|
+
"log_with_level",
|
|
472
472
|
]
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"""Minimal framework loader for better performance."""
|
|
2
2
|
|
|
3
|
+
import contextlib
|
|
3
4
|
from pathlib import Path
|
|
4
|
-
from typing import
|
|
5
|
+
from typing import Optional
|
|
5
6
|
|
|
6
7
|
try:
|
|
7
8
|
from ..core.logger import get_logger
|
|
@@ -45,18 +46,14 @@ class MinimalFrameworkLoader:
|
|
|
45
46
|
working_claude_path = Path.cwd() / "CLAUDE.md" # Legacy support
|
|
46
47
|
|
|
47
48
|
if working_instructions_path.exists():
|
|
48
|
-
|
|
49
|
+
with contextlib.suppress(Exception):
|
|
49
50
|
working_claude = working_instructions_path.read_text()
|
|
50
|
-
except:
|
|
51
|
-
pass
|
|
52
51
|
elif working_claude_path.exists():
|
|
53
|
-
|
|
52
|
+
with contextlib.suppress(Exception):
|
|
54
53
|
working_claude = working_claude_path.read_text()
|
|
55
|
-
except:
|
|
56
|
-
pass
|
|
57
54
|
|
|
58
55
|
# Build minimal framework
|
|
59
|
-
framework =
|
|
56
|
+
framework = """# Claude MPM Framework
|
|
60
57
|
|
|
61
58
|
You are a multi-agent orchestrator in the Claude MPM framework.
|
|
62
59
|
|
|
@@ -4,30 +4,14 @@ This module encapsulates the logic for running one-time Claude commands,
|
|
|
4
4
|
breaking down the monolithic run_oneshot method into focused, testable components.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
import contextlib
|
|
7
8
|
import os
|
|
8
9
|
import subprocess
|
|
9
10
|
import time
|
|
10
11
|
import uuid
|
|
11
|
-
from
|
|
12
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple
|
|
12
|
+
from typing import Any, Dict, Optional, Tuple
|
|
13
13
|
|
|
14
14
|
from claude_mpm.core.logger import get_logger
|
|
15
|
-
from claude_mpm.core.typing_utils import (
|
|
16
|
-
ErrorResult,
|
|
17
|
-
SessionConfig,
|
|
18
|
-
SessionEvent,
|
|
19
|
-
SessionId,
|
|
20
|
-
SessionResult,
|
|
21
|
-
SessionStatus,
|
|
22
|
-
SuccessResult,
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
if TYPE_CHECKING:
|
|
26
|
-
from claude_mpm.agents.memory.ticket_manager import TicketManager
|
|
27
|
-
from claude_mpm.core.claude_runner import ClaudeRunner
|
|
28
|
-
from claude_mpm.core.logger import ProjectLogger
|
|
29
|
-
from claude_mpm.services.response_logger import ResponseLogger
|
|
30
|
-
from claude_mpm.services.socketio_server import SocketIOClientProxy
|
|
31
15
|
|
|
32
16
|
|
|
33
17
|
class OneshotSession:
|
|
@@ -154,13 +138,13 @@ class OneshotSession:
|
|
|
154
138
|
|
|
155
139
|
# Add system instructions if available
|
|
156
140
|
system_prompt = self.runner._create_system_prompt()
|
|
157
|
-
|
|
141
|
+
|
|
158
142
|
# Debug: log the system prompt to check for issues
|
|
159
143
|
if system_prompt:
|
|
160
144
|
self.logger.debug(f"System prompt length: {len(system_prompt)}")
|
|
161
145
|
if "Path.cwd()" in system_prompt or "Path(" in system_prompt:
|
|
162
146
|
self.logger.warning("System prompt contains Python code references!")
|
|
163
|
-
|
|
147
|
+
|
|
164
148
|
if system_prompt and system_prompt != self._get_simple_context():
|
|
165
149
|
# The problem might be with insert positioning
|
|
166
150
|
# Let's add system prompt differently
|
|
@@ -189,17 +173,18 @@ class OneshotSession:
|
|
|
189
173
|
self.logger.debug(f"Running command: {' '.join(cmd[:5])}...")
|
|
190
174
|
if len(cmd) > 5:
|
|
191
175
|
self.logger.debug(f"Command has {len(cmd)} arguments total")
|
|
192
|
-
|
|
193
|
-
result = subprocess.run(
|
|
176
|
+
|
|
177
|
+
result = subprocess.run(
|
|
178
|
+
cmd, capture_output=True, text=True, env=env, check=False
|
|
179
|
+
)
|
|
194
180
|
|
|
195
181
|
if result.returncode == 0:
|
|
196
182
|
response = result.stdout.strip()
|
|
197
183
|
self._handle_successful_response(response, prompt)
|
|
198
184
|
return (True, response)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
return (False, error_msg)
|
|
185
|
+
error_msg = result.stderr or "Unknown error"
|
|
186
|
+
self._handle_error_response(error_msg, result.returncode)
|
|
187
|
+
return (False, error_msg)
|
|
203
188
|
|
|
204
189
|
except subprocess.TimeoutExpired as e:
|
|
205
190
|
return self._handle_timeout(e)
|
|
@@ -218,10 +203,8 @@ class OneshotSession:
|
|
|
218
203
|
"""Clean up the session and restore state."""
|
|
219
204
|
# Restore original working directory
|
|
220
205
|
if self.original_cwd:
|
|
221
|
-
|
|
206
|
+
with contextlib.suppress(Exception):
|
|
222
207
|
os.chdir(self.original_cwd)
|
|
223
|
-
except Exception:
|
|
224
|
-
pass
|
|
225
208
|
|
|
226
209
|
# Log session summary
|
|
227
210
|
if self.runner.project_logger:
|
|
@@ -268,11 +251,11 @@ class OneshotSession:
|
|
|
268
251
|
def _prepare_environment(self) -> Dict[str, str]:
|
|
269
252
|
"""Prepare the execution environment."""
|
|
270
253
|
env = os.environ.copy()
|
|
271
|
-
|
|
254
|
+
|
|
272
255
|
# Disable telemetry for Claude Code
|
|
273
256
|
# This ensures Claude Code doesn't send telemetry data during runtime
|
|
274
257
|
env["DISABLE_TELEMETRY"] = "1"
|
|
275
|
-
|
|
258
|
+
|
|
276
259
|
return env
|
|
277
260
|
|
|
278
261
|
def _build_command(self) -> list:
|
|
@@ -342,9 +325,8 @@ class OneshotSession:
|
|
|
342
325
|
def _handle_error_response(self, error_msg: str, return_code: int) -> None:
|
|
343
326
|
"""Handle an error response from Claude."""
|
|
344
327
|
print(f"Error: {error_msg}")
|
|
345
|
-
|
|
328
|
+
|
|
346
329
|
# Debug: print full traceback if available
|
|
347
|
-
import traceback
|
|
348
330
|
if "Traceback" in error_msg or "Error:" in error_msg:
|
|
349
331
|
self.logger.debug(f"Full error output:\n{error_msg}")
|
|
350
332
|
|
|
@@ -17,14 +17,13 @@ WHY optimized agent loading:
|
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
19
|
import asyncio
|
|
20
|
-
import hashlib
|
|
21
20
|
import json
|
|
22
21
|
import threading
|
|
23
22
|
import time
|
|
24
23
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
25
|
-
from dataclasses import dataclass
|
|
24
|
+
from dataclasses import dataclass
|
|
26
25
|
from datetime import datetime
|
|
27
|
-
from typing import Any, Dict, List, Optional
|
|
26
|
+
from typing import Any, Dict, List, Optional
|
|
28
27
|
|
|
29
28
|
try:
|
|
30
29
|
import aiofiles
|
|
@@ -34,8 +33,7 @@ except ImportError:
|
|
|
34
33
|
AIOFILES_AVAILABLE = False
|
|
35
34
|
|
|
36
35
|
from ..core.logger import get_logger
|
|
37
|
-
from .cache import
|
|
38
|
-
from .lazy import LazyService
|
|
36
|
+
from .cache import get_file_cache
|
|
39
37
|
|
|
40
38
|
|
|
41
39
|
@dataclass
|
|
@@ -308,7 +306,7 @@ class OptimizedAgentLoader:
|
|
|
308
306
|
self.metrics.cache_misses += 1
|
|
309
307
|
|
|
310
308
|
# Read file asynchronously
|
|
311
|
-
async with aiofiles.open(file_path,
|
|
309
|
+
async with aiofiles.open(file_path, encoding="utf-8") as f:
|
|
312
310
|
content = await f.read()
|
|
313
311
|
|
|
314
312
|
# Parse in executor to avoid blocking
|
|
@@ -20,7 +20,8 @@ import sys
|
|
|
20
20
|
import time
|
|
21
21
|
from concurrent.futures import ThreadPoolExecutor
|
|
22
22
|
from dataclasses import dataclass, field
|
|
23
|
-
from
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Any, Dict, List, Optional, Set
|
|
24
25
|
|
|
25
26
|
from ..core.logger import get_logger
|
|
26
27
|
from .cache import get_file_cache
|