claude-mpm 4.21.0__py3-none-any.whl → 5.0.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/VERSION +1 -1
- claude_mpm/agents/BASE_PM.md +12 -0
- claude_mpm/agents/OUTPUT_STYLE.md +3 -48
- claude_mpm/agents/PM_INSTRUCTIONS.md +632 -334
- claude_mpm/agents/WORKFLOW.md +75 -2
- claude_mpm/agents/__init__.py +6 -0
- claude_mpm/agents/agent_loader.py +1 -4
- claude_mpm/agents/base_agent.json +6 -3
- claude_mpm/agents/frontmatter_validator.py +1 -1
- claude_mpm/agents/templates/{circuit_breakers.md → circuit-breakers.md} +370 -3
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +89 -19
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/cli/__init__.py +38 -2
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +125 -20
- claude_mpm/cli/commands/agents.py +684 -13
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/aggregate.py +1 -1
- claude_mpm/cli/commands/analyze.py +3 -3
- claude_mpm/cli/commands/auto_configure.py +2 -6
- claude_mpm/cli/commands/cleanup.py +1 -1
- claude_mpm/cli/commands/config.py +7 -4
- claude_mpm/cli/commands/configure.py +478 -44
- claude_mpm/cli/commands/configure_agent_display.py +4 -4
- claude_mpm/cli/commands/configure_navigation.py +63 -46
- claude_mpm/cli/commands/debug.py +12 -12
- claude_mpm/cli/commands/doctor.py +10 -2
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/local_deploy.py +1 -4
- claude_mpm/cli/commands/mcp_install_commands.py +1 -1
- claude_mpm/cli/commands/mpm_init/core.py +50 -2
- claude_mpm/cli/commands/mpm_init/git_activity.py +10 -10
- claude_mpm/cli/commands/mpm_init/prompts.py +6 -6
- claude_mpm/cli/commands/run.py +124 -128
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +435 -1
- claude_mpm/cli/executor.py +78 -3
- claude_mpm/cli/interactive/agent_wizard.py +919 -41
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +173 -4
- claude_mpm/cli/parsers/base_parser.py +49 -0
- claude_mpm/cli/parsers/config_parser.py +96 -43
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +138 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/startup.py +499 -84
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/utils.py +1 -1
- claude_mpm/cli_module/commands.py +1 -1
- claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
- claude_mpm/commands/mpm-agents-detect.md +9 -0
- claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
- claude_mpm/commands/mpm-agents-recommend.md +9 -0
- claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
- claude_mpm/commands/mpm-doctor.md +9 -0
- claude_mpm/commands/mpm-help.md +14 -2
- claude_mpm/commands/mpm-init.md +27 -2
- claude_mpm/commands/mpm-monitor.md +9 -0
- claude_mpm/commands/mpm-session-resume.md +381 -0
- claude_mpm/commands/mpm-status.md +9 -0
- claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
- claude_mpm/commands/mpm-ticket-view.md +552 -0
- claude_mpm/commands/mpm-version.md +9 -0
- claude_mpm/commands/mpm.md +11 -0
- claude_mpm/config/agent_presets.py +258 -0
- claude_mpm/config/agent_sources.py +325 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/constants.py +12 -0
- claude_mpm/core/api_validator.py +1 -1
- claude_mpm/core/claude_runner.py +17 -10
- claude_mpm/core/config.py +24 -0
- claude_mpm/core/constants.py +1 -1
- claude_mpm/core/framework/__init__.py +3 -16
- claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
- claude_mpm/core/framework/processors/metadata_processor.py +1 -1
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +41 -2
- claude_mpm/core/interactive_session.py +112 -5
- claude_mpm/core/logger.py +3 -1
- claude_mpm/core/oneshot_session.py +94 -4
- claude_mpm/dashboard/static/css/activity.css +69 -69
- claude_mpm/dashboard/static/css/connection-status.css +10 -10
- claude_mpm/dashboard/static/css/dashboard.css +15 -15
- claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
- claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
- claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
- claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
- claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
- claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
- claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
- claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
- claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
- claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
- claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
- claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
- claude_mpm/dashboard/static/js/connection-manager.js +76 -76
- claude_mpm/dashboard/static/js/dashboard.js +76 -58
- claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
- claude_mpm/dashboard/static/js/socket-client.js +138 -121
- claude_mpm/dashboard/templates/code_simple.html +23 -23
- claude_mpm/dashboard/templates/index.html +18 -18
- claude_mpm/experimental/cli_enhancements.py +1 -5
- claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
- claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
- claude_mpm/hooks/claude_hooks/installer.py +45 -0
- claude_mpm/hooks/failure_learning/__init__.py +2 -8
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
- claude_mpm/hooks/kuzu_response_hook.py +1 -5
- claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
- claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/scripts/claude-hook-handler.sh +3 -3
- claude_mpm/scripts/start_activity_logging.py +3 -1
- claude_mpm/services/agents/agent_builder.py +45 -9
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- claude_mpm/services/agents/agent_selection_service.py +484 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
- claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
- claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
- claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
- claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
- claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +115 -15
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +363 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
- claude_mpm/services/agents/git_source_manager.py +629 -0
- claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
- claude_mpm/services/agents/local_template_manager.py +50 -10
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1055 -0
- claude_mpm/services/agents/startup_sync.py +239 -0
- claude_mpm/services/agents/toolchain_detector.py +474 -0
- claude_mpm/services/cli/session_pause_manager.py +1 -1
- claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
- claude_mpm/services/command_deployment_service.py +92 -1
- claude_mpm/services/core/base.py +26 -11
- claude_mpm/services/core/interfaces/__init__.py +1 -3
- claude_mpm/services/core/interfaces/health.py +1 -4
- claude_mpm/services/core/models/__init__.py +2 -11
- claude_mpm/services/diagnostics/checks/__init__.py +4 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
- claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
- claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
- claude_mpm/services/event_bus/direct_relay.py +3 -3
- claude_mpm/services/event_bus/event_bus.py +36 -3
- claude_mpm/services/event_bus/relay.py +23 -7
- claude_mpm/services/events/consumers/logging.py +1 -2
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +494 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
- claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
- claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +3 -13
- claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
- claude_mpm/services/local_ops/health_manager.py +1 -4
- claude_mpm/services/local_ops/process_manager.py +1 -1
- claude_mpm/services/local_ops/resource_monitor.py +2 -2
- claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
- claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
- claude_mpm/services/memory/failure_tracker.py +19 -4
- claude_mpm/services/memory/optimizer.py +1 -1
- claude_mpm/services/model/model_router.py +8 -9
- claude_mpm/services/monitor/daemon.py +1 -1
- claude_mpm/services/monitor/server.py +2 -2
- claude_mpm/services/native_agent_converter.py +356 -0
- claude_mpm/services/port_manager.py +1 -1
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/project/documentation_manager.py +2 -1
- claude_mpm/services/project/toolchain_analyzer.py +3 -1
- claude_mpm/services/runner_configuration_service.py +1 -0
- claude_mpm/services/self_upgrade_service.py +165 -7
- claude_mpm/services/skills/__init__.py +18 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +955 -0
- claude_mpm/services/socketio/handlers/connection.py +1 -1
- claude_mpm/services/socketio/handlers/git.py +2 -2
- claude_mpm/services/socketio/server/core.py +1 -4
- claude_mpm/services/socketio/server/main.py +1 -3
- claude_mpm/services/system_instructions_service.py +1 -3
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
- claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
- claude_mpm/services/unified/unified_deployment.py +1 -5
- claude_mpm/services/version_control/conflict_resolution.py +6 -4
- claude_mpm/services/visualization/__init__.py +1 -5
- claude_mpm/services/visualization/mermaid_generator.py +2 -3
- claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
- claude_mpm/skills/bundled/performance-profiling.md +6 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +2 -2
- claude_mpm/skills/skills_registry.py +0 -1
- claude_mpm/templates/questions/__init__.py +38 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +311 -0
- claude_mpm/templates/questions/project_init.py +385 -0
- claude_mpm/templates/questions/ticket_mgmt.py +394 -0
- claude_mpm/tools/__main__.py +8 -8
- claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
- claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
- claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
- claude_mpm/tools/code_tree_analyzer/core.py +380 -0
- claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
- claude_mpm/tools/code_tree_analyzer/events.py +168 -0
- claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
- claude_mpm/tools/code_tree_analyzer/models.py +39 -0
- claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
- claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
- claude_mpm/utils/agent_dependency_loader.py +80 -13
- claude_mpm/utils/dependency_cache.py +3 -1
- claude_mpm/utils/gitignore.py +241 -0
- claude_mpm/utils/log_cleanup.py +3 -3
- claude_mpm/utils/progress.py +383 -0
- claude_mpm/utils/robust_installer.py +3 -5
- claude_mpm/utils/structured_questions.py +619 -0
- {claude_mpm-4.21.0.dist-info → claude_mpm-5.0.2.dist-info}/METADATA +429 -59
- {claude_mpm-4.21.0.dist-info → claude_mpm-5.0.2.dist-info}/RECORD +264 -427
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
- claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
- claude_mpm/agents/templates/agent-manager.json +0 -273
- claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
- claude_mpm/agents/templates/api_qa.json +0 -180
- claude_mpm/agents/templates/clerk-ops.json +0 -235
- claude_mpm/agents/templates/code_analyzer.json +0 -101
- claude_mpm/agents/templates/content-agent.json +0 -358
- claude_mpm/agents/templates/dart_engineer.json +0 -307
- claude_mpm/agents/templates/data_engineer.json +0 -225
- claude_mpm/agents/templates/documentation.json +0 -211
- claude_mpm/agents/templates/engineer.json +0 -210
- claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
- claude_mpm/agents/templates/golang_engineer.json +0 -270
- claude_mpm/agents/templates/imagemagick.json +0 -264
- claude_mpm/agents/templates/java_engineer.json +0 -346
- claude_mpm/agents/templates/local_ops_agent.json +0 -1840
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
- claude_mpm/agents/templates/memory_manager.json +0 -158
- claude_mpm/agents/templates/nextjs_engineer.json +0 -285
- claude_mpm/agents/templates/ops.json +0 -185
- claude_mpm/agents/templates/php-engineer.json +0 -287
- claude_mpm/agents/templates/product_owner.json +0 -338
- claude_mpm/agents/templates/project_organizer.json +0 -140
- claude_mpm/agents/templates/prompt-engineer.json +0 -737
- claude_mpm/agents/templates/python_engineer.json +0 -387
- claude_mpm/agents/templates/qa.json +0 -242
- claude_mpm/agents/templates/react_engineer.json +0 -238
- claude_mpm/agents/templates/refactoring_engineer.json +0 -276
- claude_mpm/agents/templates/research.json +0 -188
- claude_mpm/agents/templates/ruby-engineer.json +0 -280
- claude_mpm/agents/templates/rust_engineer.json +0 -275
- claude_mpm/agents/templates/security.json +0 -202
- claude_mpm/agents/templates/svelte-engineer.json +0 -225
- claude_mpm/agents/templates/ticketing.json +0 -177
- claude_mpm/agents/templates/typescript_engineer.json +0 -285
- claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
- claude_mpm/agents/templates/version_control.json +0 -157
- claude_mpm/agents/templates/web_qa.json +0 -399
- claude_mpm/agents/templates/web_ui.json +0 -189
- claude_mpm/commands/mpm-tickets.md +0 -102
- claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
- claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
- claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
- claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
- claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
- claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
- claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
- claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
- claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
- claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
- claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
- claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
- claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
- claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
- claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
- claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
- claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
- claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
- claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
- claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
- claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
- claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
- claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
- claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
- claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
- claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/built/connection-manager.js +0 -536
- claude_mpm/dashboard/static/built/dashboard.js +0 -2
- claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/built/react/events.js +0 -30
- claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
- claude_mpm/dashboard/static/built/shared/logger.js +0 -385
- claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
- claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/built/socket-client.js +0 -2
- claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/dist/dashboard.js +0 -2
- claude_mpm/dashboard/static/dist/react/events.js +0 -30
- claude_mpm/dashboard/static/dist/socket-client.js +0 -2
- claude_mpm/dashboard/static/events.html +0 -607
- claude_mpm/dashboard/static/index.html +0 -635
- claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/js/shared/logger.js +0 -385
- claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
- claude_mpm/dashboard/static/legacy/activity.html +0 -736
- claude_mpm/dashboard/static/legacy/agents.html +0 -786
- claude_mpm/dashboard/static/legacy/files.html +0 -747
- claude_mpm/dashboard/static/legacy/tools.html +0 -831
- claude_mpm/dashboard/static/monitors.html +0 -431
- claude_mpm/dashboard/static/production/events.html +0 -659
- claude_mpm/dashboard/static/production/main.html +0 -698
- claude_mpm/dashboard/static/production/monitors.html +0 -483
- claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
- claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
- claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
- claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
- claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
- claude_mpm/tools/code_tree_analyzer.py +0 -1825
- /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
- /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
- /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
- /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
- {claude_mpm-4.21.0.dist-info → claude_mpm-5.0.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.21.0.dist-info → claude_mpm-5.0.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.21.0.dist-info → claude_mpm-5.0.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.21.0.dist-info → claude_mpm-5.0.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Python Analyzer
|
|
4
|
+
===============
|
|
5
|
+
|
|
6
|
+
Analyzes Python source code using AST.
|
|
7
|
+
|
|
8
|
+
WHY: Python's built-in AST module provides rich structural information
|
|
9
|
+
that we can leverage for detailed analysis.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import ast
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import List, Optional
|
|
15
|
+
|
|
16
|
+
from ...core.logging_config import get_logger
|
|
17
|
+
from ..code_tree_events import CodeNodeEvent, CodeTreeEventEmitter
|
|
18
|
+
from .models import CodeNode
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class PythonAnalyzer:
|
|
22
|
+
"""Analyzes Python source code using AST."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, emitter: Optional[CodeTreeEventEmitter] = None):
|
|
25
|
+
self.logger = get_logger(__name__)
|
|
26
|
+
self.emitter = emitter
|
|
27
|
+
|
|
28
|
+
def analyze_file(self, file_path: Path) -> List[CodeNode]:
|
|
29
|
+
"""Analyze a Python file and extract code structure.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
file_path: Path to Python file
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
List of code nodes found in the file
|
|
36
|
+
"""
|
|
37
|
+
nodes = []
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
with Path(file_path).open(
|
|
41
|
+
encoding="utf-8",
|
|
42
|
+
) as f:
|
|
43
|
+
source = f.read()
|
|
44
|
+
|
|
45
|
+
tree = ast.parse(source, filename=str(file_path))
|
|
46
|
+
nodes = self._extract_nodes(tree, file_path, source)
|
|
47
|
+
|
|
48
|
+
except SyntaxError as e:
|
|
49
|
+
self.logger.warning(f"Syntax error in {file_path}: {e}")
|
|
50
|
+
if self.emitter:
|
|
51
|
+
self.emitter.emit_error(str(file_path), f"Syntax error: {e}")
|
|
52
|
+
except Exception as e:
|
|
53
|
+
self.logger.error(f"Error analyzing {file_path}: {e}")
|
|
54
|
+
if self.emitter:
|
|
55
|
+
self.emitter.emit_error(str(file_path), str(e))
|
|
56
|
+
|
|
57
|
+
return nodes
|
|
58
|
+
|
|
59
|
+
def _extract_nodes(
|
|
60
|
+
self, tree: ast.AST, file_path: Path, source: str
|
|
61
|
+
) -> List[CodeNode]:
|
|
62
|
+
"""Extract code nodes from AST tree.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
tree: AST tree
|
|
66
|
+
file_path: Source file path
|
|
67
|
+
source: Source code text
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
List of extracted code nodes
|
|
71
|
+
"""
|
|
72
|
+
nodes = []
|
|
73
|
+
source.splitlines()
|
|
74
|
+
|
|
75
|
+
class NodeVisitor(ast.NodeVisitor):
|
|
76
|
+
def __init__(self, parent_name: Optional[str] = None):
|
|
77
|
+
self.parent_name = parent_name
|
|
78
|
+
self.current_class = None
|
|
79
|
+
|
|
80
|
+
def visit_ClassDef(self, node):
|
|
81
|
+
# Extract class information
|
|
82
|
+
class_node = CodeNode(
|
|
83
|
+
file_path=str(file_path),
|
|
84
|
+
node_type="class",
|
|
85
|
+
name=node.name,
|
|
86
|
+
line_start=node.lineno,
|
|
87
|
+
line_end=node.end_lineno or node.lineno,
|
|
88
|
+
has_docstring=bool(ast.get_docstring(node)),
|
|
89
|
+
decorators=[self._decorator_name(d) for d in node.decorator_list],
|
|
90
|
+
parent=self.parent_name,
|
|
91
|
+
complexity=self._calculate_complexity(node),
|
|
92
|
+
signature=self._get_class_signature(node),
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
nodes.append(class_node)
|
|
96
|
+
|
|
97
|
+
# Emit event if emitter is available
|
|
98
|
+
if self.emitter:
|
|
99
|
+
self.emitter.emit_node(
|
|
100
|
+
CodeNodeEvent(
|
|
101
|
+
file_path=str(file_path),
|
|
102
|
+
node_type="class",
|
|
103
|
+
name=node.name,
|
|
104
|
+
line_start=node.lineno,
|
|
105
|
+
line_end=node.end_lineno or node.lineno,
|
|
106
|
+
complexity=class_node.complexity,
|
|
107
|
+
has_docstring=class_node.has_docstring,
|
|
108
|
+
decorators=class_node.decorators,
|
|
109
|
+
parent=self.parent_name,
|
|
110
|
+
children_count=len(node.body),
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Visit class members
|
|
115
|
+
old_class = self.current_class
|
|
116
|
+
self.current_class = node.name
|
|
117
|
+
for child in node.body:
|
|
118
|
+
if isinstance(child, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
119
|
+
self.visit_FunctionDef(child, is_method=True)
|
|
120
|
+
self.current_class = old_class
|
|
121
|
+
|
|
122
|
+
def visit_FunctionDef(self, node, is_method=False):
|
|
123
|
+
# Determine node type
|
|
124
|
+
node_type = "method" if is_method else "function"
|
|
125
|
+
parent = self.current_class if is_method else self.parent_name
|
|
126
|
+
|
|
127
|
+
# Extract function information
|
|
128
|
+
func_node = CodeNode(
|
|
129
|
+
file_path=str(file_path),
|
|
130
|
+
node_type=node_type,
|
|
131
|
+
name=node.name,
|
|
132
|
+
line_start=node.lineno,
|
|
133
|
+
line_end=node.end_lineno or node.lineno,
|
|
134
|
+
has_docstring=bool(ast.get_docstring(node)),
|
|
135
|
+
decorators=[self._decorator_name(d) for d in node.decorator_list],
|
|
136
|
+
parent=parent,
|
|
137
|
+
complexity=self._calculate_complexity(node),
|
|
138
|
+
signature=self._get_function_signature(node),
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
nodes.append(func_node)
|
|
142
|
+
|
|
143
|
+
# Emit event if emitter is available
|
|
144
|
+
if self.emitter:
|
|
145
|
+
self.emitter.emit_node(
|
|
146
|
+
CodeNodeEvent(
|
|
147
|
+
file_path=str(file_path),
|
|
148
|
+
node_type=node_type,
|
|
149
|
+
name=node.name,
|
|
150
|
+
line_start=node.lineno,
|
|
151
|
+
line_end=node.end_lineno or node.lineno,
|
|
152
|
+
complexity=func_node.complexity,
|
|
153
|
+
has_docstring=func_node.has_docstring,
|
|
154
|
+
decorators=func_node.decorators,
|
|
155
|
+
parent=parent,
|
|
156
|
+
children_count=0,
|
|
157
|
+
)
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
def visit_Assign(self, node):
|
|
161
|
+
# Handle module-level variable assignments
|
|
162
|
+
if self.current_class is None: # Only module-level assignments
|
|
163
|
+
for target in node.targets:
|
|
164
|
+
if isinstance(target, ast.Name):
|
|
165
|
+
var_node = CodeNode(
|
|
166
|
+
file_path=str(file_path),
|
|
167
|
+
node_type="variable",
|
|
168
|
+
name=target.id,
|
|
169
|
+
line_start=node.lineno,
|
|
170
|
+
line_end=node.end_lineno or node.lineno,
|
|
171
|
+
parent=self.parent_name,
|
|
172
|
+
complexity=0,
|
|
173
|
+
signature=f"{target.id} = ...",
|
|
174
|
+
)
|
|
175
|
+
nodes.append(var_node)
|
|
176
|
+
|
|
177
|
+
# Emit event if emitter is available
|
|
178
|
+
if self.emitter:
|
|
179
|
+
self.emitter.emit_node(
|
|
180
|
+
CodeNodeEvent(
|
|
181
|
+
file_path=str(file_path),
|
|
182
|
+
node_type="variable",
|
|
183
|
+
name=target.id,
|
|
184
|
+
line_start=node.lineno,
|
|
185
|
+
line_end=node.end_lineno or node.lineno,
|
|
186
|
+
parent=self.parent_name,
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def visit_AsyncFunctionDef(self, node):
|
|
191
|
+
self.visit_FunctionDef(node)
|
|
192
|
+
|
|
193
|
+
def _decorator_name(self, decorator):
|
|
194
|
+
"""Extract decorator name from AST node."""
|
|
195
|
+
if isinstance(decorator, ast.Name):
|
|
196
|
+
return decorator.id
|
|
197
|
+
if isinstance(decorator, ast.Call):
|
|
198
|
+
if isinstance(decorator.func, ast.Name):
|
|
199
|
+
return decorator.func.id
|
|
200
|
+
if isinstance(decorator.func, ast.Attribute):
|
|
201
|
+
return decorator.func.attr
|
|
202
|
+
return "unknown"
|
|
203
|
+
|
|
204
|
+
def _calculate_complexity(self, node):
|
|
205
|
+
"""Calculate cyclomatic complexity of a node."""
|
|
206
|
+
complexity = 1 # Base complexity
|
|
207
|
+
|
|
208
|
+
for child in ast.walk(node):
|
|
209
|
+
if isinstance(
|
|
210
|
+
child, (ast.If, ast.While, ast.For, ast.ExceptHandler)
|
|
211
|
+
):
|
|
212
|
+
complexity += 1
|
|
213
|
+
elif isinstance(child, ast.BoolOp):
|
|
214
|
+
complexity += len(child.values) - 1
|
|
215
|
+
|
|
216
|
+
return complexity
|
|
217
|
+
|
|
218
|
+
def _get_function_signature(self, node):
|
|
219
|
+
"""Extract function signature."""
|
|
220
|
+
args = []
|
|
221
|
+
for arg in node.args.args:
|
|
222
|
+
args.append(arg.arg)
|
|
223
|
+
return f"{node.name}({', '.join(args)})"
|
|
224
|
+
|
|
225
|
+
def _get_class_signature(self, node):
|
|
226
|
+
"""Extract class signature."""
|
|
227
|
+
bases = []
|
|
228
|
+
for base in node.bases:
|
|
229
|
+
if isinstance(base, ast.Name):
|
|
230
|
+
bases.append(base.id)
|
|
231
|
+
base_str = f"({', '.join(bases)})" if bases else ""
|
|
232
|
+
return f"class {node.name}{base_str}"
|
|
233
|
+
|
|
234
|
+
# Extract imports
|
|
235
|
+
for node in ast.walk(tree):
|
|
236
|
+
if isinstance(node, ast.Import):
|
|
237
|
+
for alias in node.names:
|
|
238
|
+
import_node = CodeNode(
|
|
239
|
+
file_path=str(file_path),
|
|
240
|
+
node_type="import",
|
|
241
|
+
name=alias.name,
|
|
242
|
+
line_start=node.lineno,
|
|
243
|
+
line_end=node.end_lineno or node.lineno,
|
|
244
|
+
signature=f"import {alias.name}",
|
|
245
|
+
)
|
|
246
|
+
nodes.append(import_node)
|
|
247
|
+
|
|
248
|
+
elif isinstance(node, ast.ImportFrom):
|
|
249
|
+
module = node.module or ""
|
|
250
|
+
for alias in node.names:
|
|
251
|
+
import_node = CodeNode(
|
|
252
|
+
file_path=str(file_path),
|
|
253
|
+
node_type="import",
|
|
254
|
+
name=f"{module}.{alias.name}",
|
|
255
|
+
line_start=node.lineno,
|
|
256
|
+
line_end=node.end_lineno or node.lineno,
|
|
257
|
+
signature=f"from {module} import {alias.name}",
|
|
258
|
+
)
|
|
259
|
+
nodes.append(import_node)
|
|
260
|
+
|
|
261
|
+
# Visit all nodes
|
|
262
|
+
visitor = NodeVisitor()
|
|
263
|
+
visitor.emitter = self.emitter
|
|
264
|
+
visitor.visit(tree)
|
|
265
|
+
|
|
266
|
+
return nodes
|
|
267
|
+
|
|
268
|
+
def _get_assignment_signature(self, node: ast.Assign, var_name: str) -> str:
|
|
269
|
+
"""Get assignment signature string."""
|
|
270
|
+
try:
|
|
271
|
+
# Try to get a simple representation of the value
|
|
272
|
+
if isinstance(node.value, ast.Constant):
|
|
273
|
+
if isinstance(node.value.value, str):
|
|
274
|
+
return f'{var_name} = "{node.value.value}"'
|
|
275
|
+
return f"{var_name} = {node.value.value}"
|
|
276
|
+
if isinstance(node.value, ast.Name):
|
|
277
|
+
return f"{var_name} = {node.value.id}"
|
|
278
|
+
if isinstance(node.value, ast.List):
|
|
279
|
+
return f"{var_name} = [...]"
|
|
280
|
+
if isinstance(node.value, ast.Dict):
|
|
281
|
+
return f"{var_name} = {{...}}"
|
|
282
|
+
return f"{var_name} = ..."
|
|
283
|
+
except Exception:
|
|
284
|
+
return f"{var_name} = ..."
|
|
@@ -16,6 +16,7 @@ import sys
|
|
|
16
16
|
import time
|
|
17
17
|
from typing import Any, Dict, List, Optional, Set, Tuple
|
|
18
18
|
|
|
19
|
+
import yaml
|
|
19
20
|
from packaging.requirements import InvalidRequirement, Requirement
|
|
20
21
|
|
|
21
22
|
from ..core.logger import get_logger
|
|
@@ -89,10 +90,48 @@ class AgentDependencyLoader:
|
|
|
89
90
|
self.deployed_agents = deployed_agents
|
|
90
91
|
return deployed_agents
|
|
91
92
|
|
|
93
|
+
def _extract_yaml_frontmatter(self, content: str) -> Optional[Dict[str, Any]]:
|
|
94
|
+
"""
|
|
95
|
+
Extract and parse YAML frontmatter from markdown.
|
|
96
|
+
|
|
97
|
+
Frontmatter must be at the start of the file, delimited by '---'.
|
|
98
|
+
Example:
|
|
99
|
+
---
|
|
100
|
+
name: agent_name
|
|
101
|
+
dependencies:
|
|
102
|
+
python:
|
|
103
|
+
- package>=1.0.0
|
|
104
|
+
---
|
|
105
|
+
# Agent content...
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
content: File content to parse
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Parsed YAML frontmatter as dict, or None if not found/invalid
|
|
112
|
+
"""
|
|
113
|
+
if not content.strip().startswith("---"):
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
# Split on --- delimiters
|
|
117
|
+
parts = content.split("---", 2)
|
|
118
|
+
if len(parts) < 3:
|
|
119
|
+
return None
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
return yaml.safe_load(parts[1])
|
|
123
|
+
except yaml.YAMLError as e:
|
|
124
|
+
logger.warning(f"Failed to parse YAML frontmatter: {e}")
|
|
125
|
+
return None
|
|
126
|
+
|
|
92
127
|
def load_agent_dependencies(self) -> Dict[str, Dict]:
|
|
93
128
|
"""
|
|
94
129
|
Load dependency information for deployed agents from their source configs.
|
|
95
130
|
|
|
131
|
+
Searches for agent configuration in both markdown (.md) and JSON (.json) formats.
|
|
132
|
+
Markdown files with YAML frontmatter are searched first for better maintainability.
|
|
133
|
+
Falls back to JSON format for backward compatibility.
|
|
134
|
+
|
|
96
135
|
Returns:
|
|
97
136
|
Dictionary mapping agent IDs to their dependency requirements
|
|
98
137
|
"""
|
|
@@ -106,19 +145,47 @@ class AgentDependencyLoader:
|
|
|
106
145
|
]
|
|
107
146
|
|
|
108
147
|
for agent_id in self.deployed_agents:
|
|
109
|
-
|
|
148
|
+
found = False
|
|
149
|
+
|
|
150
|
+
# Try to find the agent's config (markdown first, then JSON)
|
|
110
151
|
for config_dir in config_paths:
|
|
111
|
-
|
|
112
|
-
|
|
152
|
+
if found:
|
|
153
|
+
break
|
|
154
|
+
|
|
155
|
+
# Try markdown first (current format with YAML frontmatter)
|
|
156
|
+
md_file = config_dir / f"{agent_id}.md"
|
|
157
|
+
if md_file.exists():
|
|
113
158
|
try:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
159
|
+
content = md_file.read_text(encoding="utf-8")
|
|
160
|
+
frontmatter = self._extract_yaml_frontmatter(content)
|
|
161
|
+
if frontmatter and "dependencies" in frontmatter:
|
|
162
|
+
agent_dependencies[agent_id] = frontmatter["dependencies"]
|
|
163
|
+
logger.debug(
|
|
164
|
+
f"Loaded dependencies for {agent_id} from markdown"
|
|
165
|
+
)
|
|
166
|
+
found = True
|
|
167
|
+
break
|
|
120
168
|
except Exception as e:
|
|
121
|
-
logger.warning(f"Failed to load
|
|
169
|
+
logger.warning(f"Failed to load markdown for {agent_id}: {e}")
|
|
170
|
+
|
|
171
|
+
# Fall back to JSON for backward compatibility
|
|
172
|
+
if not found:
|
|
173
|
+
json_file = config_dir / f"{agent_id}.json"
|
|
174
|
+
if json_file.exists():
|
|
175
|
+
try:
|
|
176
|
+
with json_file.open() as f:
|
|
177
|
+
config = json.load(f)
|
|
178
|
+
if "dependencies" in config:
|
|
179
|
+
agent_dependencies[agent_id] = config[
|
|
180
|
+
"dependencies"
|
|
181
|
+
]
|
|
182
|
+
logger.debug(
|
|
183
|
+
f"Loaded dependencies for {agent_id} from JSON"
|
|
184
|
+
)
|
|
185
|
+
found = True
|
|
186
|
+
break
|
|
187
|
+
except Exception as e:
|
|
188
|
+
logger.warning(f"Failed to load JSON for {agent_id}: {e}")
|
|
122
189
|
|
|
123
190
|
self.agent_dependencies = agent_dependencies
|
|
124
191
|
logger.debug(f"Loaded dependencies for {len(agent_dependencies)} agents")
|
|
@@ -678,7 +745,7 @@ class AgentDependencyLoader:
|
|
|
678
745
|
logger.info(
|
|
679
746
|
f"Auto-installing {len(results['summary']['missing_python'])} missing dependencies..."
|
|
680
747
|
)
|
|
681
|
-
success,
|
|
748
|
+
success, _error = self.install_missing_dependencies(
|
|
682
749
|
results["summary"]["missing_python"]
|
|
683
750
|
)
|
|
684
751
|
if success:
|
|
@@ -777,7 +844,7 @@ class AgentDependencyLoader:
|
|
|
777
844
|
import sys
|
|
778
845
|
|
|
779
846
|
if sys.version_info >= (3, 13):
|
|
780
|
-
|
|
847
|
+
_compatible, incompatible = self.check_python_compatibility(
|
|
781
848
|
summary["missing_python"]
|
|
782
849
|
)
|
|
783
850
|
if incompatible:
|
|
@@ -949,7 +1016,7 @@ class AgentDependencyLoader:
|
|
|
949
1016
|
Returns:
|
|
950
1017
|
Cached results or None if not available/valid.
|
|
951
1018
|
"""
|
|
952
|
-
has_changed,
|
|
1019
|
+
has_changed, _current_hash = self.has_agents_changed()
|
|
953
1020
|
|
|
954
1021
|
if not has_changed:
|
|
955
1022
|
state = self.load_deployment_state()
|
|
@@ -333,7 +333,9 @@ class SmartDependencyChecker:
|
|
|
333
333
|
return True, "No valid cache, checking needed"
|
|
334
334
|
|
|
335
335
|
def get_or_check_dependencies(
|
|
336
|
-
self,
|
|
336
|
+
self,
|
|
337
|
+
loader,
|
|
338
|
+
force_check: bool = False, # AgentDependencyLoader instance
|
|
337
339
|
) -> Tuple[Dict, bool]:
|
|
338
340
|
"""
|
|
339
341
|
Get dependency results from cache or perform check.
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"""GitIgnore management utilities.
|
|
2
|
+
|
|
3
|
+
This module provides functionality to safely manage .gitignore entries,
|
|
4
|
+
ensuring claude-mpm configuration directories are excluded from version control.
|
|
5
|
+
|
|
6
|
+
Design Decisions:
|
|
7
|
+
- In-memory set for duplicate detection (O(1) lookups)
|
|
8
|
+
- Preserves existing file formatting and comments
|
|
9
|
+
- Adds section headers for clarity
|
|
10
|
+
- Handles edge cases (missing newlines, empty files, etc.)
|
|
11
|
+
|
|
12
|
+
Trade-offs:
|
|
13
|
+
- Simplicity: File append vs. full parse/rewrite (chosen append for safety)
|
|
14
|
+
- Performance: Read entire file vs. streaming (file is small, simplicity wins)
|
|
15
|
+
- Safety: Non-destructive append only, never modifies existing entries
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import List, Set, Tuple
|
|
20
|
+
|
|
21
|
+
from claude_mpm.core.logging_utils import get_logger
|
|
22
|
+
|
|
23
|
+
logger = get_logger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class GitIgnoreManager:
|
|
27
|
+
"""Manages .gitignore file updates safely and non-destructively.
|
|
28
|
+
|
|
29
|
+
Design Pattern: Builder pattern for fluent API
|
|
30
|
+
- Initialize with project directory
|
|
31
|
+
- Call ensure_entries() to add patterns
|
|
32
|
+
- Returns summary of changes made
|
|
33
|
+
|
|
34
|
+
Performance:
|
|
35
|
+
- Time Complexity: O(n) where n = existing .gitignore lines
|
|
36
|
+
- Space Complexity: O(n) for storing unique entries in set
|
|
37
|
+
- Expected Performance: <1ms for typical .gitignore files (<1000 lines)
|
|
38
|
+
|
|
39
|
+
Error Handling:
|
|
40
|
+
- FileNotFoundError: Creates new .gitignore if missing
|
|
41
|
+
- PermissionError: Propagated to caller for appropriate handling
|
|
42
|
+
- UnicodeDecodeError: Logged and treated as binary file (skip)
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self, project_dir: Path):
|
|
46
|
+
"""Initialize with project directory.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
project_dir: Path to project root (where .gitignore lives)
|
|
50
|
+
"""
|
|
51
|
+
self.project_dir = Path(project_dir)
|
|
52
|
+
self.gitignore_path = self.project_dir / ".gitignore"
|
|
53
|
+
|
|
54
|
+
def ensure_entries(self, entries: List[str]) -> Tuple[List[str], List[str]]:
|
|
55
|
+
"""Ensure specified entries exist in .gitignore.
|
|
56
|
+
|
|
57
|
+
Non-destructive operation that:
|
|
58
|
+
1. Reads existing entries (if file exists)
|
|
59
|
+
2. Identifies which entries are missing
|
|
60
|
+
3. Appends only missing entries with section header
|
|
61
|
+
4. Preserves all existing content and formatting
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
entries: List of gitignore patterns to add (e.g., [".claude-mpm/"])
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Tuple of (added_entries, existing_entries)
|
|
68
|
+
- added_entries: Patterns that were added to .gitignore
|
|
69
|
+
- existing_entries: Patterns that were already present
|
|
70
|
+
|
|
71
|
+
Example:
|
|
72
|
+
>>> manager = GitIgnoreManager(Path("."))
|
|
73
|
+
>>> added, existing = manager.ensure_entries([".claude-mpm/"])
|
|
74
|
+
>>> print(f"Added: {added}, Already present: {existing}")
|
|
75
|
+
Added: ['.claude-mpm/'], Already present: []
|
|
76
|
+
"""
|
|
77
|
+
# Read existing entries
|
|
78
|
+
existing = self._read_existing_entries()
|
|
79
|
+
|
|
80
|
+
# Determine what needs to be added
|
|
81
|
+
to_add = [e for e in entries if e not in existing]
|
|
82
|
+
already_present = [e for e in entries if e in existing]
|
|
83
|
+
|
|
84
|
+
if to_add:
|
|
85
|
+
self._append_entries(to_add)
|
|
86
|
+
logger.info(f"Added {len(to_add)} entries to .gitignore: {to_add}")
|
|
87
|
+
|
|
88
|
+
if already_present:
|
|
89
|
+
logger.debug(f"Entries already in .gitignore: {already_present}")
|
|
90
|
+
|
|
91
|
+
return to_add, already_present
|
|
92
|
+
|
|
93
|
+
def _read_existing_entries(self) -> Set[str]:
|
|
94
|
+
"""Read existing .gitignore entries.
|
|
95
|
+
|
|
96
|
+
Parses .gitignore file and extracts all non-comment, non-blank patterns.
|
|
97
|
+
Handles edge cases:
|
|
98
|
+
- File doesn't exist -> returns empty set
|
|
99
|
+
- File is binary -> logs warning, returns empty set
|
|
100
|
+
- File has no newline at end -> handled correctly
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Set of existing gitignore patterns (stripped, normalized)
|
|
104
|
+
"""
|
|
105
|
+
if not self.gitignore_path.exists():
|
|
106
|
+
logger.debug(".gitignore does not exist, will create new file")
|
|
107
|
+
return set()
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
with open(self.gitignore_path, encoding="utf-8") as f:
|
|
111
|
+
# Strip whitespace and comments, filter blanks
|
|
112
|
+
entries = {
|
|
113
|
+
line.strip()
|
|
114
|
+
for line in f
|
|
115
|
+
if line.strip() and not line.strip().startswith("#")
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
logger.debug(f"Found {len(entries)} existing entries in .gitignore")
|
|
119
|
+
return entries
|
|
120
|
+
|
|
121
|
+
except UnicodeDecodeError:
|
|
122
|
+
logger.warning(
|
|
123
|
+
f".gitignore appears to be binary, cannot parse: {self.gitignore_path}"
|
|
124
|
+
)
|
|
125
|
+
return set()
|
|
126
|
+
except Exception as e:
|
|
127
|
+
logger.error(f"Error reading .gitignore: {e}")
|
|
128
|
+
raise
|
|
129
|
+
|
|
130
|
+
def _append_entries(self, entries: List[str]) -> None:
|
|
131
|
+
"""Append entries to .gitignore with proper formatting.
|
|
132
|
+
|
|
133
|
+
Handles formatting edge cases:
|
|
134
|
+
- Ensures blank line before new section (if file exists and isn't empty)
|
|
135
|
+
- Adds section header comment for clarity
|
|
136
|
+
- Ensures each entry on its own line
|
|
137
|
+
- Handles missing trailing newline in existing file
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
entries: List of patterns to append
|
|
141
|
+
|
|
142
|
+
Raises:
|
|
143
|
+
PermissionError: If cannot write to .gitignore
|
|
144
|
+
OSError: If disk is full or other I/O error
|
|
145
|
+
"""
|
|
146
|
+
mode = "a" if self.gitignore_path.exists() else "w"
|
|
147
|
+
|
|
148
|
+
try:
|
|
149
|
+
with open(self.gitignore_path, mode, encoding="utf-8") as f:
|
|
150
|
+
# Add blank line before entries if file exists and isn't empty
|
|
151
|
+
if mode == "a" and self.gitignore_path.stat().st_size > 0:
|
|
152
|
+
# Check if last line has newline
|
|
153
|
+
with open(self.gitignore_path, "rb") as check:
|
|
154
|
+
check.seek(-1, 2) # Seek to last byte
|
|
155
|
+
last_byte = check.read(1)
|
|
156
|
+
if last_byte != b"\n":
|
|
157
|
+
f.write("\n")
|
|
158
|
+
|
|
159
|
+
f.write("\n# Claude MPM configuration\n")
|
|
160
|
+
else:
|
|
161
|
+
# New file or empty file - add header without extra blank line
|
|
162
|
+
f.write("# Claude MPM configuration\n")
|
|
163
|
+
|
|
164
|
+
for entry in entries:
|
|
165
|
+
f.write(f"{entry}\n")
|
|
166
|
+
|
|
167
|
+
logger.info(f"Updated .gitignore at {self.gitignore_path}")
|
|
168
|
+
|
|
169
|
+
except PermissionError:
|
|
170
|
+
logger.error(
|
|
171
|
+
f"Permission denied writing to .gitignore: {self.gitignore_path}"
|
|
172
|
+
)
|
|
173
|
+
raise
|
|
174
|
+
except OSError as e:
|
|
175
|
+
logger.error(f"I/O error writing to .gitignore: {e}")
|
|
176
|
+
raise
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def ensure_claude_mpm_gitignore(project_dir: str = ".") -> dict:
|
|
180
|
+
"""Ensure claude-mpm directories are in .gitignore.
|
|
181
|
+
|
|
182
|
+
Convenience function that wraps GitIgnoreManager to add standard
|
|
183
|
+
claude-mpm configuration directories to .gitignore.
|
|
184
|
+
|
|
185
|
+
Standard Entries Added:
|
|
186
|
+
- .claude-mpm/: Main configuration directory
|
|
187
|
+
- .claude/agents/: Agent runtime files
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
project_dir: Project directory path (default: current directory)
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Dictionary with operation results:
|
|
194
|
+
- added: List of patterns that were added
|
|
195
|
+
- existing: List of patterns that were already present
|
|
196
|
+
- gitignore_path: Path to the .gitignore file
|
|
197
|
+
|
|
198
|
+
Example:
|
|
199
|
+
>>> result = ensure_claude_mpm_gitignore()
|
|
200
|
+
>>> if result["added"]:
|
|
201
|
+
... print(f"Added {len(result['added'])} entries to .gitignore")
|
|
202
|
+
|
|
203
|
+
Error Handling:
|
|
204
|
+
- PermissionError: Returns error dict with status="error"
|
|
205
|
+
- FileNotFoundError on parent dir: Returns error dict
|
|
206
|
+
- All other exceptions: Propagated to caller
|
|
207
|
+
"""
|
|
208
|
+
try:
|
|
209
|
+
manager = GitIgnoreManager(Path(project_dir))
|
|
210
|
+
|
|
211
|
+
# Standard claude-mpm entries
|
|
212
|
+
entries_to_add = [
|
|
213
|
+
".claude-mpm/",
|
|
214
|
+
".claude/agents/",
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
added, existing = manager.ensure_entries(entries_to_add)
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
"status": "success",
|
|
221
|
+
"added": added,
|
|
222
|
+
"existing": existing,
|
|
223
|
+
"gitignore_path": str(manager.gitignore_path),
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
except PermissionError as e:
|
|
227
|
+
logger.error(f"Permission denied updating .gitignore: {e}")
|
|
228
|
+
return {
|
|
229
|
+
"status": "error",
|
|
230
|
+
"error": f"Permission denied: {e}",
|
|
231
|
+
"added": [],
|
|
232
|
+
"existing": [],
|
|
233
|
+
}
|
|
234
|
+
except FileNotFoundError as e:
|
|
235
|
+
logger.error(f"Project directory not found: {e}")
|
|
236
|
+
return {
|
|
237
|
+
"status": "error",
|
|
238
|
+
"error": f"Directory not found: {e}",
|
|
239
|
+
"added": [],
|
|
240
|
+
"existing": [],
|
|
241
|
+
}
|