claude-mpm 4.7.4__py3-none-any.whl → 4.18.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_AGENT_TEMPLATE.md +118 -0
- claude_mpm/agents/BASE_ENGINEER.md +286 -0
- claude_mpm/agents/BASE_PM.md +106 -1
- claude_mpm/agents/OUTPUT_STYLE.md +329 -11
- claude_mpm/agents/PM_INSTRUCTIONS.md +397 -459
- claude_mpm/agents/agent_loader.py +17 -5
- claude_mpm/agents/frontmatter_validator.py +284 -253
- claude_mpm/agents/templates/README.md +465 -0
- claude_mpm/agents/templates/agent-manager.json +4 -1
- claude_mpm/agents/templates/agentic-coder-optimizer.json +13 -3
- claude_mpm/agents/templates/api_qa.json +11 -2
- claude_mpm/agents/templates/circuit_breakers.md +638 -0
- claude_mpm/agents/templates/clerk-ops.json +12 -2
- claude_mpm/agents/templates/code_analyzer.json +8 -2
- claude_mpm/agents/templates/content-agent.json +358 -0
- claude_mpm/agents/templates/dart_engineer.json +15 -2
- claude_mpm/agents/templates/data_engineer.json +15 -2
- claude_mpm/agents/templates/documentation.json +10 -2
- claude_mpm/agents/templates/engineer.json +21 -1
- claude_mpm/agents/templates/gcp_ops_agent.json +12 -2
- claude_mpm/agents/templates/git_file_tracking.md +584 -0
- claude_mpm/agents/templates/golang_engineer.json +270 -0
- claude_mpm/agents/templates/imagemagick.json +4 -1
- claude_mpm/agents/templates/java_engineer.json +346 -0
- claude_mpm/agents/templates/local_ops_agent.json +1227 -6
- claude_mpm/agents/templates/memory_manager.json +4 -1
- claude_mpm/agents/templates/nextjs_engineer.json +141 -133
- claude_mpm/agents/templates/ops.json +12 -2
- claude_mpm/agents/templates/php-engineer.json +270 -174
- claude_mpm/agents/templates/pm_examples.md +474 -0
- claude_mpm/agents/templates/pm_red_flags.md +240 -0
- claude_mpm/agents/templates/product_owner.json +338 -0
- claude_mpm/agents/templates/project_organizer.json +14 -4
- claude_mpm/agents/templates/prompt-engineer.json +13 -2
- claude_mpm/agents/templates/python_engineer.json +174 -81
- claude_mpm/agents/templates/qa.json +11 -2
- claude_mpm/agents/templates/react_engineer.json +16 -3
- claude_mpm/agents/templates/refactoring_engineer.json +12 -2
- claude_mpm/agents/templates/research.json +34 -21
- claude_mpm/agents/templates/response_format.md +583 -0
- claude_mpm/agents/templates/ruby-engineer.json +129 -192
- claude_mpm/agents/templates/rust_engineer.json +270 -0
- claude_mpm/agents/templates/security.json +10 -2
- claude_mpm/agents/templates/svelte-engineer.json +225 -0
- claude_mpm/agents/templates/ticketing.json +10 -2
- claude_mpm/agents/templates/typescript_engineer.json +116 -125
- claude_mpm/agents/templates/validation_templates.md +312 -0
- claude_mpm/agents/templates/vercel_ops_agent.json +12 -2
- claude_mpm/agents/templates/version_control.json +12 -2
- claude_mpm/agents/templates/web_qa.json +11 -2
- claude_mpm/agents/templates/web_ui.json +15 -2
- claude_mpm/cli/__init__.py +34 -614
- claude_mpm/cli/commands/agent_manager.py +25 -12
- claude_mpm/cli/commands/agent_state_manager.py +186 -0
- claude_mpm/cli/commands/agents.py +235 -148
- claude_mpm/cli/commands/agents_detect.py +380 -0
- claude_mpm/cli/commands/agents_recommend.py +309 -0
- claude_mpm/cli/commands/aggregate.py +7 -3
- claude_mpm/cli/commands/analyze.py +9 -4
- claude_mpm/cli/commands/analyze_code.py +7 -2
- claude_mpm/cli/commands/auto_configure.py +570 -0
- claude_mpm/cli/commands/config.py +47 -13
- claude_mpm/cli/commands/configure.py +419 -1571
- claude_mpm/cli/commands/configure_agent_display.py +261 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +167 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/local_deploy.py +537 -0
- claude_mpm/cli/commands/memory.py +54 -20
- claude_mpm/cli/commands/mpm_init.py +585 -196
- claude_mpm/cli/commands/mpm_init_handler.py +37 -3
- claude_mpm/cli/commands/search.py +170 -4
- claude_mpm/cli/commands/upgrade.py +152 -0
- claude_mpm/cli/executor.py +202 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +3 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parsers/__init__.py +7 -1
- claude_mpm/cli/parsers/agents_parser.py +9 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +245 -0
- claude_mpm/cli/parsers/base_parser.py +110 -3
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +65 -5
- claude_mpm/cli/shared/output_formatters.py +28 -19
- claude_mpm/cli/startup.py +481 -0
- claude_mpm/cli/utils.py +52 -1
- claude_mpm/commands/mpm-agents-detect.md +168 -0
- claude_mpm/commands/mpm-agents-recommend.md +214 -0
- claude_mpm/commands/mpm-agents.md +75 -1
- claude_mpm/commands/mpm-auto-configure.md +217 -0
- claude_mpm/commands/mpm-help.md +163 -0
- claude_mpm/commands/mpm-init.md +148 -3
- claude_mpm/commands/mpm-version.md +113 -0
- claude_mpm/commands/mpm.md +1 -0
- claude_mpm/config/agent_config.py +2 -2
- claude_mpm/config/model_config.py +428 -0
- claude_mpm/constants.py +1 -0
- claude_mpm/core/base_service.py +13 -12
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/factories.py +1 -1
- claude_mpm/core/instruction_reinforcement_hook.py +2 -1
- claude_mpm/core/interactive_session.py +9 -3
- claude_mpm/core/log_manager.py +2 -0
- claude_mpm/core/logging_config.py +6 -2
- claude_mpm/core/oneshot_session.py +8 -4
- claude_mpm/core/optimized_agent_loader.py +3 -3
- claude_mpm/core/output_style_manager.py +12 -192
- claude_mpm/core/service_registry.py +5 -1
- claude_mpm/core/types.py +2 -9
- claude_mpm/core/typing_utils.py +7 -6
- claude_mpm/dashboard/static/js/dashboard.js +0 -14
- claude_mpm/dashboard/templates/index.html +3 -41
- claude_mpm/hooks/__init__.py +20 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +4 -2
- claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +23 -2
- claude_mpm/hooks/failure_learning/__init__.py +60 -0
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +235 -0
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +217 -0
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +286 -0
- claude_mpm/hooks/instruction_reinforcement.py +7 -2
- claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
- claude_mpm/hooks/kuzu_memory_hook.py +37 -12
- claude_mpm/hooks/kuzu_response_hook.py +183 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/services/agents/__init__.py +18 -5
- claude_mpm/services/agents/auto_config_manager.py +796 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
- claude_mpm/services/agents/deployment/agent_validator.py +17 -1
- claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
- claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
- claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
- claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
- claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
- claude_mpm/services/agents/local_template_manager.py +1 -1
- claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
- claude_mpm/services/agents/observers.py +547 -0
- claude_mpm/services/agents/recommender.py +568 -0
- claude_mpm/services/agents/registry/modification_tracker.py +5 -2
- claude_mpm/services/command_handler_service.py +11 -5
- claude_mpm/services/core/__init__.py +33 -1
- claude_mpm/services/core/interfaces/__init__.py +90 -3
- claude_mpm/services/core/interfaces/agent.py +184 -0
- claude_mpm/services/core/interfaces/health.py +172 -0
- claude_mpm/services/core/interfaces/model.py +281 -0
- claude_mpm/services/core/interfaces/process.py +372 -0
- claude_mpm/services/core/interfaces/project.py +121 -0
- claude_mpm/services/core/interfaces/restart.py +307 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/memory_manager.py +11 -24
- claude_mpm/services/core/models/__init__.py +79 -0
- claude_mpm/services/core/models/agent_config.py +381 -0
- claude_mpm/services/core/models/health.py +162 -0
- claude_mpm/services/core/models/process.py +235 -0
- claude_mpm/services/core/models/restart.py +302 -0
- claude_mpm/services/core/models/stability.py +264 -0
- claude_mpm/services/core/models/toolchain.py +306 -0
- claude_mpm/services/core/path_resolver.py +23 -7
- claude_mpm/services/diagnostics/__init__.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_check.py +25 -24
- claude_mpm/services/diagnostics/checks/claude_code_check.py +24 -23
- claude_mpm/services/diagnostics/checks/common_issues_check.py +25 -24
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -23
- claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
- claude_mpm/services/diagnostics/checks/installation_check.py +30 -29
- claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
- claude_mpm/services/diagnostics/checks/mcp_check.py +50 -36
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +38 -33
- claude_mpm/services/diagnostics/checks/monitor_check.py +23 -22
- claude_mpm/services/diagnostics/checks/startup_log_check.py +9 -8
- claude_mpm/services/diagnostics/diagnostic_runner.py +6 -5
- claude_mpm/services/diagnostics/doctor_reporter.py +28 -25
- claude_mpm/services/diagnostics/models.py +19 -24
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
- claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
- claude_mpm/services/infrastructure/monitoring/base.py +5 -13
- claude_mpm/services/infrastructure/monitoring/network.py +7 -6
- claude_mpm/services/infrastructure/monitoring/process.py +13 -12
- claude_mpm/services/infrastructure/monitoring/resources.py +7 -6
- claude_mpm/services/infrastructure/monitoring/service.py +16 -15
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/local_ops/__init__.py +163 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
- claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
- claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
- claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
- claude_mpm/services/local_ops/health_manager.py +430 -0
- claude_mpm/services/local_ops/log_monitor.py +396 -0
- claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
- claude_mpm/services/local_ops/process_manager.py +595 -0
- claude_mpm/services/local_ops/resource_monitor.py +331 -0
- claude_mpm/services/local_ops/restart_manager.py +401 -0
- claude_mpm/services/local_ops/restart_policy.py +387 -0
- claude_mpm/services/local_ops/state_manager.py +372 -0
- claude_mpm/services/local_ops/unified_manager.py +600 -0
- claude_mpm/services/mcp_config_manager.py +9 -4
- claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
- claude_mpm/services/mcp_gateway/core/base.py +18 -31
- claude_mpm/services/mcp_gateway/main.py +30 -0
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +206 -32
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +25 -5
- claude_mpm/services/mcp_service_verifier.py +1 -1
- claude_mpm/services/memory/failure_tracker.py +563 -0
- claude_mpm/services/memory_hook_service.py +165 -4
- claude_mpm/services/model/__init__.py +147 -0
- claude_mpm/services/model/base_provider.py +365 -0
- claude_mpm/services/model/claude_provider.py +412 -0
- claude_mpm/services/model/model_router.py +453 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/daemon_manager.py +3 -2
- claude_mpm/services/monitor/handlers/dashboard.py +2 -1
- claude_mpm/services/monitor/handlers/hooks.py +2 -1
- claude_mpm/services/monitor/management/lifecycle.py +3 -2
- claude_mpm/services/monitor/server.py +2 -1
- claude_mpm/services/project/__init__.py +23 -0
- claude_mpm/services/project/detection_strategies.py +719 -0
- claude_mpm/services/project/toolchain_analyzer.py +581 -0
- claude_mpm/services/self_upgrade_service.py +342 -0
- claude_mpm/services/session_management_service.py +3 -2
- claude_mpm/services/session_manager.py +205 -1
- claude_mpm/services/shared/async_service_base.py +16 -27
- claude_mpm/services/shared/lifecycle_service_base.py +1 -14
- claude_mpm/services/socketio/handlers/__init__.py +5 -2
- claude_mpm/services/socketio/handlers/hook.py +13 -2
- claude_mpm/services/socketio/handlers/registry.py +4 -2
- claude_mpm/services/socketio/server/main.py +10 -8
- claude_mpm/services/subprocess_launcher_service.py +14 -5
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +6 -5
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +7 -6
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +5 -4
- claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
- claude_mpm/services/unified/deployment_strategies/local.py +6 -5
- claude_mpm/services/unified/deployment_strategies/utils.py +6 -5
- claude_mpm/services/unified/deployment_strategies/vercel.py +7 -6
- claude_mpm/services/unified/interfaces.py +3 -1
- claude_mpm/services/unified/unified_analyzer.py +14 -10
- claude_mpm/services/unified/unified_config.py +2 -1
- claude_mpm/services/unified/unified_deployment.py +9 -4
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/skills/__init__.py +21 -0
- claude_mpm/skills/bundled/__init__.py +6 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +567 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/security-scanning.md +327 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +286 -0
- claude_mpm/skills/skill_manager.py +310 -0
- claude_mpm/storage/state_storage.py +15 -15
- claude_mpm/tools/code_tree_analyzer.py +177 -141
- claude_mpm/tools/code_tree_events.py +4 -2
- claude_mpm/utils/agent_dependency_loader.py +40 -20
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/git_analyzer.py +407 -0
- claude_mpm/utils/robust_installer.py +73 -19
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/METADATA +129 -12
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/RECORD +295 -193
- claude_mpm/dashboard/static/css/code-tree.css +0 -1639
- claude_mpm/dashboard/static/index-hub-backup.html +0 -713
- claude_mpm/dashboard/static/js/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/js/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/js/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/js/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/js/components/code-tree.js +0 -5869
- claude_mpm/dashboard/static/js/components/code-viewer.js +0 -1386
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
- claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
- claude_mpm/services/project/analyzer_refactored.py +0 -450
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Model Configuration Management for Claude MPM Framework
|
|
3
|
+
=======================================================
|
|
4
|
+
|
|
5
|
+
WHY: Centralizes configuration for model providers, routing strategy, and
|
|
6
|
+
model selection. Supports configuration files, environment variables, and
|
|
7
|
+
programmatic configuration.
|
|
8
|
+
|
|
9
|
+
DESIGN DECISION: Uses Pydantic for configuration validation and type safety.
|
|
10
|
+
Supports loading from YAML files and environment variables with sensible defaults.
|
|
11
|
+
|
|
12
|
+
CONFIGURATION STRUCTURE:
|
|
13
|
+
```yaml
|
|
14
|
+
content_agent:
|
|
15
|
+
model_provider: auto # auto|ollama|claude|privacy
|
|
16
|
+
|
|
17
|
+
ollama:
|
|
18
|
+
enabled: true
|
|
19
|
+
host: http://localhost:11434
|
|
20
|
+
fallback_to_cloud: true
|
|
21
|
+
timeout: 30
|
|
22
|
+
models:
|
|
23
|
+
seo_analysis: llama3.3:70b
|
|
24
|
+
readability: gemma2:9b
|
|
25
|
+
grammar: qwen3:14b
|
|
26
|
+
summarization: mistral:7b
|
|
27
|
+
keyword_extraction: seoassistant
|
|
28
|
+
|
|
29
|
+
claude:
|
|
30
|
+
enabled: true
|
|
31
|
+
model: claude-3-5-sonnet-20241022
|
|
32
|
+
max_tokens: 4096
|
|
33
|
+
temperature: 0.7
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
ENVIRONMENT VARIABLES:
|
|
37
|
+
- MODEL_PROVIDER: Override provider strategy
|
|
38
|
+
- OLLAMA_HOST: Override Ollama endpoint
|
|
39
|
+
- OLLAMA_ENABLED: Enable/disable Ollama
|
|
40
|
+
- CLAUDE_ENABLED: Enable/disable Claude
|
|
41
|
+
- ANTHROPIC_API_KEY: Claude API key
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
import os
|
|
45
|
+
from pathlib import Path
|
|
46
|
+
from typing import Any, Dict, Optional
|
|
47
|
+
|
|
48
|
+
from pydantic import BaseModel, Field
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
import yaml
|
|
52
|
+
except ImportError:
|
|
53
|
+
yaml = None # type: ignore
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class OllamaConfig(BaseModel):
|
|
57
|
+
"""
|
|
58
|
+
Configuration for Ollama provider.
|
|
59
|
+
|
|
60
|
+
WHY: Separates Ollama-specific settings for better organization
|
|
61
|
+
and validation.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
enabled: bool = Field(default=True, description="Enable Ollama provider")
|
|
65
|
+
host: str = Field(
|
|
66
|
+
default="http://localhost:11434",
|
|
67
|
+
description="Ollama API endpoint",
|
|
68
|
+
)
|
|
69
|
+
fallback_to_cloud: bool = Field(
|
|
70
|
+
default=True,
|
|
71
|
+
description="Allow fallback to cloud on Ollama failure",
|
|
72
|
+
)
|
|
73
|
+
timeout: int = Field(default=30, description="Request timeout in seconds")
|
|
74
|
+
models: Dict[str, str] = Field(
|
|
75
|
+
default_factory=dict,
|
|
76
|
+
description="Task-specific model mappings",
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
class Config:
|
|
80
|
+
"""Pydantic config."""
|
|
81
|
+
|
|
82
|
+
extra = "allow"
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class ClaudeConfig(BaseModel):
|
|
86
|
+
"""
|
|
87
|
+
Configuration for Claude provider.
|
|
88
|
+
|
|
89
|
+
WHY: Separates Claude-specific settings for better organization
|
|
90
|
+
and validation.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
enabled: bool = Field(default=True, description="Enable Claude provider")
|
|
94
|
+
model: str = Field(
|
|
95
|
+
default="claude-3-5-sonnet-20241022",
|
|
96
|
+
description="Default Claude model",
|
|
97
|
+
)
|
|
98
|
+
max_tokens: int = Field(
|
|
99
|
+
default=4096,
|
|
100
|
+
description="Maximum response tokens",
|
|
101
|
+
)
|
|
102
|
+
temperature: float = Field(
|
|
103
|
+
default=0.7,
|
|
104
|
+
description="Sampling temperature (0.0-1.0)",
|
|
105
|
+
)
|
|
106
|
+
api_key: Optional[str] = Field(
|
|
107
|
+
default=None,
|
|
108
|
+
description="Anthropic API key (can use env var)",
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
class Config:
|
|
112
|
+
"""Pydantic config."""
|
|
113
|
+
|
|
114
|
+
extra = "allow"
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class ModelProviderConfig(BaseModel):
|
|
118
|
+
"""
|
|
119
|
+
Main model provider configuration.
|
|
120
|
+
|
|
121
|
+
WHY: Top-level configuration containing all model-related settings.
|
|
122
|
+
Validates configuration at load time to catch errors early.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
provider: str = Field(
|
|
126
|
+
default="auto",
|
|
127
|
+
description="Provider strategy: auto|ollama|claude|privacy",
|
|
128
|
+
)
|
|
129
|
+
ollama: OllamaConfig = Field(
|
|
130
|
+
default_factory=OllamaConfig,
|
|
131
|
+
description="Ollama provider configuration",
|
|
132
|
+
)
|
|
133
|
+
claude: ClaudeConfig = Field(
|
|
134
|
+
default_factory=ClaudeConfig,
|
|
135
|
+
description="Claude provider configuration",
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
class Config:
|
|
139
|
+
"""Pydantic config."""
|
|
140
|
+
|
|
141
|
+
extra = "allow"
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class ModelConfigManager:
|
|
145
|
+
"""
|
|
146
|
+
Manager for model configuration.
|
|
147
|
+
|
|
148
|
+
WHY: Provides centralized configuration loading with support for
|
|
149
|
+
multiple sources (files, env vars, defaults) and validation.
|
|
150
|
+
|
|
151
|
+
Usage:
|
|
152
|
+
manager = ModelConfigManager()
|
|
153
|
+
config = manager.load_config()
|
|
154
|
+
|
|
155
|
+
# Get router config
|
|
156
|
+
router_config = manager.get_router_config(config)
|
|
157
|
+
|
|
158
|
+
# Get provider configs
|
|
159
|
+
ollama_config = manager.get_ollama_config(config)
|
|
160
|
+
claude_config = manager.get_claude_config(config)
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
DEFAULT_CONFIG_PATHS = [
|
|
164
|
+
".claude/configuration.yaml",
|
|
165
|
+
"configuration.yaml",
|
|
166
|
+
".claude-mpm/configuration.yaml",
|
|
167
|
+
str(Path("~/.claude-mpm/configuration.yaml").expanduser()),
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
@staticmethod
|
|
171
|
+
def load_config(
|
|
172
|
+
config_path: Optional[str] = None,
|
|
173
|
+
) -> ModelProviderConfig:
|
|
174
|
+
"""
|
|
175
|
+
Load model configuration from file and environment.
|
|
176
|
+
|
|
177
|
+
WHY: Supports multiple configuration sources with priority:
|
|
178
|
+
1. Explicit config_path parameter
|
|
179
|
+
2. Environment variables
|
|
180
|
+
3. Configuration file
|
|
181
|
+
4. Default values
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
config_path: Optional path to configuration file
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
ModelProviderConfig with merged settings
|
|
188
|
+
"""
|
|
189
|
+
config_data: Dict[str, Any] = {}
|
|
190
|
+
|
|
191
|
+
# Try to load from file
|
|
192
|
+
if config_path and Path(config_path).exists():
|
|
193
|
+
config_data = ModelConfigManager._load_yaml_file(config_path)
|
|
194
|
+
else:
|
|
195
|
+
# Try default paths
|
|
196
|
+
for default_path in ModelConfigManager.DEFAULT_CONFIG_PATHS:
|
|
197
|
+
if Path(default_path).exists():
|
|
198
|
+
config_data = ModelConfigManager._load_yaml_file(default_path)
|
|
199
|
+
break
|
|
200
|
+
|
|
201
|
+
# Extract content_agent section if present
|
|
202
|
+
if "content_agent" in config_data:
|
|
203
|
+
config_data = config_data["content_agent"]
|
|
204
|
+
|
|
205
|
+
# Override with environment variables
|
|
206
|
+
config_data = ModelConfigManager._apply_env_overrides(config_data)
|
|
207
|
+
|
|
208
|
+
# Create and validate config
|
|
209
|
+
try:
|
|
210
|
+
return ModelProviderConfig(**config_data)
|
|
211
|
+
except Exception as e:
|
|
212
|
+
# If validation fails, return default config
|
|
213
|
+
print(f"Warning: Failed to load config: {e}. Using defaults.")
|
|
214
|
+
return ModelProviderConfig()
|
|
215
|
+
|
|
216
|
+
@staticmethod
|
|
217
|
+
def _load_yaml_file(path: str) -> Dict[str, Any]:
|
|
218
|
+
"""
|
|
219
|
+
Load YAML configuration file.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
path: Path to YAML file
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
Dictionary of configuration
|
|
226
|
+
"""
|
|
227
|
+
if yaml is None:
|
|
228
|
+
return {}
|
|
229
|
+
|
|
230
|
+
try:
|
|
231
|
+
path_obj = Path(path)
|
|
232
|
+
with path_obj.open() as f:
|
|
233
|
+
data = yaml.safe_load(f)
|
|
234
|
+
return data or {}
|
|
235
|
+
except Exception as e:
|
|
236
|
+
print(f"Warning: Failed to load {path}: {e}")
|
|
237
|
+
return {}
|
|
238
|
+
|
|
239
|
+
@staticmethod
|
|
240
|
+
def _apply_env_overrides(config: Dict[str, Any]) -> Dict[str, Any]:
|
|
241
|
+
"""
|
|
242
|
+
Apply environment variable overrides.
|
|
243
|
+
|
|
244
|
+
WHY: Allows runtime configuration without modifying files.
|
|
245
|
+
Useful for containerized deployments and CI/CD.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
config: Base configuration
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
Configuration with env overrides applied
|
|
252
|
+
"""
|
|
253
|
+
# Provider strategy
|
|
254
|
+
if "MODEL_PROVIDER" in os.environ:
|
|
255
|
+
config["provider"] = os.environ["MODEL_PROVIDER"]
|
|
256
|
+
|
|
257
|
+
# Ollama settings
|
|
258
|
+
if "ollama" not in config:
|
|
259
|
+
config["ollama"] = {}
|
|
260
|
+
|
|
261
|
+
if "OLLAMA_ENABLED" in os.environ:
|
|
262
|
+
config["ollama"]["enabled"] = os.environ["OLLAMA_ENABLED"].lower() == "true"
|
|
263
|
+
|
|
264
|
+
if "OLLAMA_HOST" in os.environ:
|
|
265
|
+
config["ollama"]["host"] = os.environ["OLLAMA_HOST"]
|
|
266
|
+
|
|
267
|
+
if "OLLAMA_TIMEOUT" in os.environ:
|
|
268
|
+
try:
|
|
269
|
+
config["ollama"]["timeout"] = int(os.environ["OLLAMA_TIMEOUT"])
|
|
270
|
+
except ValueError:
|
|
271
|
+
pass
|
|
272
|
+
|
|
273
|
+
if "OLLAMA_FALLBACK_TO_CLOUD" in os.environ:
|
|
274
|
+
config["ollama"]["fallback_to_cloud"] = (
|
|
275
|
+
os.environ["OLLAMA_FALLBACK_TO_CLOUD"].lower() == "true"
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
# Claude settings
|
|
279
|
+
if "claude" not in config:
|
|
280
|
+
config["claude"] = {}
|
|
281
|
+
|
|
282
|
+
if "CLAUDE_ENABLED" in os.environ:
|
|
283
|
+
config["claude"]["enabled"] = os.environ["CLAUDE_ENABLED"].lower() == "true"
|
|
284
|
+
|
|
285
|
+
if "ANTHROPIC_API_KEY" in os.environ:
|
|
286
|
+
config["claude"]["api_key"] = os.environ["ANTHROPIC_API_KEY"]
|
|
287
|
+
|
|
288
|
+
if "CLAUDE_MODEL" in os.environ:
|
|
289
|
+
config["claude"]["model"] = os.environ["CLAUDE_MODEL"]
|
|
290
|
+
|
|
291
|
+
if "CLAUDE_MAX_TOKENS" in os.environ:
|
|
292
|
+
try:
|
|
293
|
+
config["claude"]["max_tokens"] = int(os.environ["CLAUDE_MAX_TOKENS"])
|
|
294
|
+
except ValueError:
|
|
295
|
+
pass
|
|
296
|
+
|
|
297
|
+
if "CLAUDE_TEMPERATURE" in os.environ:
|
|
298
|
+
try:
|
|
299
|
+
config["claude"]["temperature"] = float(
|
|
300
|
+
os.environ["CLAUDE_TEMPERATURE"]
|
|
301
|
+
)
|
|
302
|
+
except ValueError:
|
|
303
|
+
pass
|
|
304
|
+
|
|
305
|
+
return config
|
|
306
|
+
|
|
307
|
+
@staticmethod
|
|
308
|
+
def get_router_config(config: ModelProviderConfig) -> Dict[str, Any]:
|
|
309
|
+
"""
|
|
310
|
+
Get router configuration from model config.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
config: Model provider configuration
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
Dictionary suitable for ModelRouter initialization
|
|
317
|
+
"""
|
|
318
|
+
return {
|
|
319
|
+
"strategy": config.provider,
|
|
320
|
+
"fallback_enabled": config.ollama.fallback_to_cloud,
|
|
321
|
+
"ollama_config": ModelConfigManager.get_ollama_config(config),
|
|
322
|
+
"claude_config": ModelConfigManager.get_claude_config(config),
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
@staticmethod
|
|
326
|
+
def get_ollama_config(config: ModelProviderConfig) -> Dict[str, Any]:
|
|
327
|
+
"""
|
|
328
|
+
Get Ollama provider configuration.
|
|
329
|
+
|
|
330
|
+
Args:
|
|
331
|
+
config: Model provider configuration
|
|
332
|
+
|
|
333
|
+
Returns:
|
|
334
|
+
Dictionary suitable for OllamaProvider initialization
|
|
335
|
+
"""
|
|
336
|
+
return {
|
|
337
|
+
"host": config.ollama.host,
|
|
338
|
+
"timeout": config.ollama.timeout,
|
|
339
|
+
"models": config.ollama.models,
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
@staticmethod
|
|
343
|
+
def get_claude_config(config: ModelProviderConfig) -> Dict[str, Any]:
|
|
344
|
+
"""
|
|
345
|
+
Get Claude provider configuration.
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
config: Model provider configuration
|
|
349
|
+
|
|
350
|
+
Returns:
|
|
351
|
+
Dictionary suitable for ClaudeProvider initialization
|
|
352
|
+
"""
|
|
353
|
+
return {
|
|
354
|
+
"api_key": config.claude.api_key,
|
|
355
|
+
"model": config.claude.model,
|
|
356
|
+
"max_tokens": config.claude.max_tokens,
|
|
357
|
+
"temperature": config.claude.temperature,
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
@staticmethod
|
|
361
|
+
def create_sample_config(output_path: str) -> None:
|
|
362
|
+
"""
|
|
363
|
+
Create sample configuration file.
|
|
364
|
+
|
|
365
|
+
WHY: Helps users get started with proper configuration.
|
|
366
|
+
|
|
367
|
+
Args:
|
|
368
|
+
output_path: Path where to write sample config
|
|
369
|
+
"""
|
|
370
|
+
sample_config = """# Claude MPM Model Provider Configuration
|
|
371
|
+
# ==========================================
|
|
372
|
+
|
|
373
|
+
content_agent:
|
|
374
|
+
# Provider strategy: auto|ollama|claude|privacy
|
|
375
|
+
# - auto: Try Ollama first, fallback to Claude
|
|
376
|
+
# - ollama: Local-only, fail if unavailable
|
|
377
|
+
# - claude: Cloud-only, always use Claude
|
|
378
|
+
# - privacy: Like ollama but with privacy-focused error messages
|
|
379
|
+
model_provider: auto
|
|
380
|
+
|
|
381
|
+
# Ollama Configuration (local models)
|
|
382
|
+
ollama:
|
|
383
|
+
enabled: true
|
|
384
|
+
host: http://localhost:11434
|
|
385
|
+
fallback_to_cloud: true # Allow fallback to Claude on error
|
|
386
|
+
timeout: 30 # Request timeout in seconds
|
|
387
|
+
|
|
388
|
+
# Task-specific model mappings (optional)
|
|
389
|
+
# Defaults are provided if not specified
|
|
390
|
+
models:
|
|
391
|
+
seo_analysis: llama3.3:70b
|
|
392
|
+
readability: gemma2:9b
|
|
393
|
+
grammar: qwen3:14b
|
|
394
|
+
summarization: mistral:7b
|
|
395
|
+
keyword_extraction: seoassistant
|
|
396
|
+
accessibility: gemma2:9b
|
|
397
|
+
sentiment: gemma2:9b
|
|
398
|
+
general: gemma2:9b
|
|
399
|
+
|
|
400
|
+
# Claude Configuration (cloud models)
|
|
401
|
+
claude:
|
|
402
|
+
enabled: true
|
|
403
|
+
model: claude-3-5-sonnet-20241022
|
|
404
|
+
max_tokens: 4096
|
|
405
|
+
temperature: 0.7
|
|
406
|
+
# api_key: sk-ant-... # Or use ANTHROPIC_API_KEY env var
|
|
407
|
+
|
|
408
|
+
# Environment Variable Overrides:
|
|
409
|
+
# - MODEL_PROVIDER: Override provider strategy
|
|
410
|
+
# - OLLAMA_HOST: Override Ollama endpoint
|
|
411
|
+
# - OLLAMA_ENABLED: Enable/disable Ollama (true/false)
|
|
412
|
+
# - CLAUDE_ENABLED: Enable/disable Claude (true/false)
|
|
413
|
+
# - ANTHROPIC_API_KEY: Claude API key
|
|
414
|
+
# - CLAUDE_MODEL: Override Claude model
|
|
415
|
+
"""
|
|
416
|
+
|
|
417
|
+
output_path_obj = Path(output_path)
|
|
418
|
+
output_path_obj.parent.mkdir(parents=True, exist_ok=True)
|
|
419
|
+
with output_path_obj.open("w") as f:
|
|
420
|
+
f.write(sample_config)
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
__all__ = [
|
|
424
|
+
"ClaudeConfig",
|
|
425
|
+
"ModelConfigManager",
|
|
426
|
+
"ModelProviderConfig",
|
|
427
|
+
"OllamaConfig",
|
|
428
|
+
]
|
claude_mpm/constants.py
CHANGED
claude_mpm/core/base_service.py
CHANGED
|
@@ -31,6 +31,7 @@ from pathlib import Path
|
|
|
31
31
|
from typing import Any, Dict, List, Optional
|
|
32
32
|
|
|
33
33
|
from .config import Config
|
|
34
|
+
from .enums import HealthStatus
|
|
34
35
|
from .mixins import LoggerMixin
|
|
35
36
|
|
|
36
37
|
|
|
@@ -38,7 +39,7 @@ from .mixins import LoggerMixin
|
|
|
38
39
|
class ServiceHealth:
|
|
39
40
|
"""Service health status information."""
|
|
40
41
|
|
|
41
|
-
status:
|
|
42
|
+
status: HealthStatus # Type-safe health status using enum
|
|
42
43
|
message: str
|
|
43
44
|
timestamp: str
|
|
44
45
|
metrics: Dict[str, Any] = field(default_factory=dict)
|
|
@@ -142,7 +143,7 @@ class BaseService(LoggerMixin, ABC):
|
|
|
142
143
|
|
|
143
144
|
# Health and metrics
|
|
144
145
|
self._health = ServiceHealth(
|
|
145
|
-
status=
|
|
146
|
+
status=HealthStatus.UNKNOWN,
|
|
146
147
|
message="Service not started",
|
|
147
148
|
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
148
149
|
)
|
|
@@ -235,7 +236,7 @@ class BaseService(LoggerMixin, ABC):
|
|
|
235
236
|
except Exception as e:
|
|
236
237
|
self.logger.error(f"Failed to start service {self.name}: {e}")
|
|
237
238
|
self._health = ServiceHealth(
|
|
238
|
-
status=
|
|
239
|
+
status=HealthStatus.UNHEALTHY,
|
|
239
240
|
message=f"Startup failed: {e!s}",
|
|
240
241
|
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
241
242
|
checks={"startup": False},
|
|
@@ -272,7 +273,7 @@ class BaseService(LoggerMixin, ABC):
|
|
|
272
273
|
|
|
273
274
|
# Update health status
|
|
274
275
|
self._health = ServiceHealth(
|
|
275
|
-
status=
|
|
276
|
+
status=HealthStatus.HEALTHY,
|
|
276
277
|
message="Service started successfully",
|
|
277
278
|
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
278
279
|
checks={"startup": True},
|
|
@@ -336,7 +337,7 @@ class BaseService(LoggerMixin, ABC):
|
|
|
336
337
|
|
|
337
338
|
# Update health status
|
|
338
339
|
self._health = ServiceHealth(
|
|
339
|
-
status=
|
|
340
|
+
status=HealthStatus.UNKNOWN,
|
|
340
341
|
message="Service stopped",
|
|
341
342
|
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
342
343
|
checks={"running": False},
|
|
@@ -372,16 +373,16 @@ class BaseService(LoggerMixin, ABC):
|
|
|
372
373
|
|
|
373
374
|
# Determine overall status
|
|
374
375
|
if not checks["running"]:
|
|
375
|
-
status =
|
|
376
|
+
status = HealthStatus.UNHEALTHY
|
|
376
377
|
message = "Service is not running"
|
|
377
378
|
elif all(checks.values()):
|
|
378
|
-
status =
|
|
379
|
+
status = HealthStatus.HEALTHY
|
|
379
380
|
message = "All health checks passed"
|
|
380
381
|
elif any(checks.values()):
|
|
381
|
-
status =
|
|
382
|
+
status = HealthStatus.DEGRADED
|
|
382
383
|
message = "Some health checks failed"
|
|
383
384
|
else:
|
|
384
|
-
status =
|
|
385
|
+
status = HealthStatus.UNHEALTHY
|
|
385
386
|
message = "Multiple health checks failed"
|
|
386
387
|
|
|
387
388
|
# Update health status
|
|
@@ -402,7 +403,7 @@ class BaseService(LoggerMixin, ABC):
|
|
|
402
403
|
except Exception as e:
|
|
403
404
|
self.logger.error(f"Health check failed for {self.name}: {e}")
|
|
404
405
|
self._health = ServiceHealth(
|
|
405
|
-
status=
|
|
406
|
+
status=HealthStatus.UNHEALTHY,
|
|
406
407
|
message=f"Health check error: {e!s}",
|
|
407
408
|
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
408
409
|
checks={"health_check_error": True},
|
|
@@ -593,7 +594,7 @@ class BaseService(LoggerMixin, ABC):
|
|
|
593
594
|
)
|
|
594
595
|
else:
|
|
595
596
|
return ServiceHealth(
|
|
596
|
-
status=
|
|
597
|
+
status=HealthStatus.DEGRADED,
|
|
597
598
|
message="Service circuit breaker is open",
|
|
598
599
|
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
599
600
|
checks={"circuit_breaker": False},
|
|
@@ -604,7 +605,7 @@ class BaseService(LoggerMixin, ABC):
|
|
|
604
605
|
health = await self.health_check()
|
|
605
606
|
|
|
606
607
|
# Update circuit breaker
|
|
607
|
-
if health.status in
|
|
608
|
+
if health.status in (HealthStatus.HEALTHY, HealthStatus.DEGRADED):
|
|
608
609
|
self._record_circuit_success()
|
|
609
610
|
else:
|
|
610
611
|
self._record_circuit_failure()
|