claude-mpm 4.13.2__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_ENGINEER.md +286 -0
- claude_mpm/agents/BASE_PM.md +48 -17
- claude_mpm/agents/OUTPUT_STYLE.md +329 -11
- claude_mpm/agents/PM_INSTRUCTIONS.md +227 -8
- claude_mpm/agents/agent_loader.py +17 -5
- claude_mpm/agents/frontmatter_validator.py +284 -253
- claude_mpm/agents/templates/agentic-coder-optimizer.json +9 -2
- claude_mpm/agents/templates/api_qa.json +7 -1
- claude_mpm/agents/templates/clerk-ops.json +8 -1
- claude_mpm/agents/templates/code_analyzer.json +4 -1
- claude_mpm/agents/templates/dart_engineer.json +11 -1
- claude_mpm/agents/templates/data_engineer.json +11 -1
- claude_mpm/agents/templates/documentation.json +6 -1
- claude_mpm/agents/templates/engineer.json +18 -1
- claude_mpm/agents/templates/gcp_ops_agent.json +8 -1
- claude_mpm/agents/templates/golang_engineer.json +11 -1
- claude_mpm/agents/templates/java_engineer.json +12 -2
- claude_mpm/agents/templates/local_ops_agent.json +1217 -6
- claude_mpm/agents/templates/nextjs_engineer.json +11 -1
- claude_mpm/agents/templates/ops.json +8 -1
- claude_mpm/agents/templates/php-engineer.json +11 -1
- claude_mpm/agents/templates/project_organizer.json +10 -3
- claude_mpm/agents/templates/prompt-engineer.json +5 -1
- claude_mpm/agents/templates/python_engineer.json +11 -1
- claude_mpm/agents/templates/qa.json +7 -1
- claude_mpm/agents/templates/react_engineer.json +11 -1
- claude_mpm/agents/templates/refactoring_engineer.json +8 -1
- claude_mpm/agents/templates/research.json +4 -1
- claude_mpm/agents/templates/ruby-engineer.json +11 -1
- claude_mpm/agents/templates/rust_engineer.json +11 -1
- claude_mpm/agents/templates/security.json +6 -1
- claude_mpm/agents/templates/svelte-engineer.json +225 -0
- claude_mpm/agents/templates/ticketing.json +6 -1
- claude_mpm/agents/templates/typescript_engineer.json +11 -1
- claude_mpm/agents/templates/vercel_ops_agent.json +8 -1
- claude_mpm/agents/templates/version_control.json +8 -1
- claude_mpm/agents/templates/web_qa.json +7 -1
- claude_mpm/agents/templates/web_ui.json +11 -1
- claude_mpm/cli/__init__.py +34 -706
- 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 +204 -148
- 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 +7 -9
- claude_mpm/cli/commands/config.py +47 -13
- claude_mpm/cli/commands/configure.py +294 -1788
- 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 +39 -25
- claude_mpm/cli/commands/mpm_init_handler.py +8 -3
- 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/base_parser.py +98 -3
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- 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-help.md +3 -0
- 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/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/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/claude_hooks/response_tracking.py +35 -1
- claude_mpm/hooks/instruction_reinforcement.py +7 -2
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/services/agents/auto_config_manager.py +10 -11
- 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/registry/modification_tracker.py +5 -2
- claude_mpm/services/command_handler_service.py +11 -5
- claude_mpm/services/core/interfaces/__init__.py +74 -2
- 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/restart.py +307 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/models/__init__.py +33 -0
- claude_mpm/services/core/models/agent_config.py +12 -28
- 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/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 +36 -31
- 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/tools/external_mcp_services.py +71 -24
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
- claude_mpm/services/memory_hook_service.py +4 -1
- 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/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/tools/code_tree_analyzer.py +177 -141
- claude_mpm/tools/code_tree_events.py +4 -2
- claude_mpm/utils/agent_dependency_loader.py +2 -2
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/METADATA +117 -8
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/RECORD +238 -174
- claude_mpm/dashboard/static/css/code-tree.css +0 -1639
- 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.13.2.dist-info → claude_mpm-4.18.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Model Provider Interfaces for Claude MPM Framework
|
|
3
|
+
==================================================
|
|
4
|
+
|
|
5
|
+
WHY: This module defines the interfaces for content processing model providers,
|
|
6
|
+
enabling support for both local (Ollama) and cloud (Claude) models with
|
|
7
|
+
intelligent routing and auto-fallback capabilities.
|
|
8
|
+
|
|
9
|
+
DESIGN DECISION: Model providers implement a common interface (IModelProvider)
|
|
10
|
+
to enable polymorphic use and easy switching between providers. The abstraction
|
|
11
|
+
allows for provider-specific optimizations while maintaining a consistent API.
|
|
12
|
+
|
|
13
|
+
ARCHITECTURE:
|
|
14
|
+
- IModelProvider: Core provider interface for content analysis
|
|
15
|
+
- ModelCapability: Enum of supported content processing tasks
|
|
16
|
+
- ModelProvider: Enum of available provider types
|
|
17
|
+
- ModelResponse: Standardized response format across providers
|
|
18
|
+
|
|
19
|
+
USAGE:
|
|
20
|
+
provider = OllamaProvider()
|
|
21
|
+
if await provider.is_available():
|
|
22
|
+
response = await provider.analyze_content(
|
|
23
|
+
content="Your text here",
|
|
24
|
+
task=ModelCapability.SEO_ANALYSIS
|
|
25
|
+
)
|
|
26
|
+
if response.success:
|
|
27
|
+
print(f"Analysis from {response.model}: {response.result}")
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from abc import ABC, abstractmethod
|
|
31
|
+
from dataclasses import dataclass, field
|
|
32
|
+
from enum import Enum
|
|
33
|
+
from typing import Any, Dict, List, Optional
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ModelCapability(Enum):
|
|
37
|
+
"""
|
|
38
|
+
Content processing capabilities supported by model providers.
|
|
39
|
+
|
|
40
|
+
WHY: Defines task-specific analysis types for content processing.
|
|
41
|
+
Each capability may route to different models optimized for that task.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
SEO_ANALYSIS = "seo_analysis"
|
|
45
|
+
READABILITY = "readability"
|
|
46
|
+
GRAMMAR = "grammar"
|
|
47
|
+
SUMMARIZATION = "summarization"
|
|
48
|
+
KEYWORD_EXTRACTION = "keyword_extraction"
|
|
49
|
+
ACCESSIBILITY = "accessibility"
|
|
50
|
+
SENTIMENT = "sentiment"
|
|
51
|
+
GENERAL = "general"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ModelProvider(Enum):
|
|
55
|
+
"""
|
|
56
|
+
Available model provider backends.
|
|
57
|
+
|
|
58
|
+
WHY: Enables configuration-based routing between providers.
|
|
59
|
+
|
|
60
|
+
Values:
|
|
61
|
+
CLAUDE: Cloud-based Claude API (always available)
|
|
62
|
+
OLLAMA: Local Ollama installation (requires local setup)
|
|
63
|
+
AUTO: Intelligent routing with Ollama-first, Claude fallback
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
CLAUDE = "claude"
|
|
67
|
+
OLLAMA = "ollama"
|
|
68
|
+
AUTO = "auto"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass
|
|
72
|
+
class ModelResponse:
|
|
73
|
+
"""
|
|
74
|
+
Standardized response from model providers.
|
|
75
|
+
|
|
76
|
+
WHY: Provides consistent response format across all providers,
|
|
77
|
+
enabling transparent provider switching and unified error handling.
|
|
78
|
+
|
|
79
|
+
Attributes:
|
|
80
|
+
success: Whether the operation succeeded
|
|
81
|
+
provider: Name of provider that handled request (e.g., "ollama", "claude")
|
|
82
|
+
model: Specific model used (e.g., "llama3.3:70b", "claude-3-5-sonnet")
|
|
83
|
+
task: Task that was performed
|
|
84
|
+
result: Analysis result text
|
|
85
|
+
metadata: Provider-specific metadata (tokens, timing, etc.)
|
|
86
|
+
error: Error message if success=False
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
success: bool
|
|
90
|
+
provider: str
|
|
91
|
+
model: str
|
|
92
|
+
task: str
|
|
93
|
+
result: str
|
|
94
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
95
|
+
error: Optional[str] = None
|
|
96
|
+
|
|
97
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
98
|
+
"""Convert response to dictionary for serialization."""
|
|
99
|
+
return {
|
|
100
|
+
"success": self.success,
|
|
101
|
+
"provider": self.provider,
|
|
102
|
+
"model": self.model,
|
|
103
|
+
"task": self.task,
|
|
104
|
+
"result": self.result,
|
|
105
|
+
"metadata": self.metadata,
|
|
106
|
+
"error": self.error,
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class IModelProvider(ABC):
|
|
111
|
+
"""
|
|
112
|
+
Interface for content processing model providers.
|
|
113
|
+
|
|
114
|
+
WHY: Defines contract for all model providers (Claude, Ollama, future providers).
|
|
115
|
+
Enables polymorphic use and easy provider switching without changing client code.
|
|
116
|
+
|
|
117
|
+
DESIGN PATTERN: Strategy pattern - allows runtime selection of model provider
|
|
118
|
+
based on availability, configuration, and task requirements.
|
|
119
|
+
|
|
120
|
+
Implementations should:
|
|
121
|
+
- Handle provider-specific connection management
|
|
122
|
+
- Map capabilities to optimal models
|
|
123
|
+
- Provide robust error handling
|
|
124
|
+
- Return standardized ModelResponse objects
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
@abstractmethod
|
|
128
|
+
async def is_available(self) -> bool:
|
|
129
|
+
"""
|
|
130
|
+
Check if provider is available and functional.
|
|
131
|
+
|
|
132
|
+
WHY: Enables auto-fallback routing. Local providers may not always be
|
|
133
|
+
available (Ollama not running), while cloud providers need API keys.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
True if provider is ready to handle requests
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
@abstractmethod
|
|
140
|
+
async def analyze_content(
|
|
141
|
+
self,
|
|
142
|
+
content: str,
|
|
143
|
+
task: ModelCapability,
|
|
144
|
+
model: Optional[str] = None,
|
|
145
|
+
**kwargs,
|
|
146
|
+
) -> ModelResponse:
|
|
147
|
+
"""
|
|
148
|
+
Analyze content with specified task.
|
|
149
|
+
|
|
150
|
+
WHY: Core content processing method. Handles all analysis types
|
|
151
|
+
with task-specific prompting and model selection.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
content: Text content to analyze
|
|
155
|
+
task: Type of analysis to perform
|
|
156
|
+
model: Optional specific model to use (overrides default)
|
|
157
|
+
**kwargs: Provider-specific options (temperature, max_tokens, etc.)
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
ModelResponse with analysis results or error
|
|
161
|
+
|
|
162
|
+
Example:
|
|
163
|
+
response = await provider.analyze_content(
|
|
164
|
+
content="Your article text",
|
|
165
|
+
task=ModelCapability.SEO_ANALYSIS,
|
|
166
|
+
temperature=0.7
|
|
167
|
+
)
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
@abstractmethod
|
|
171
|
+
def get_supported_capabilities(self) -> List[ModelCapability]:
|
|
172
|
+
"""
|
|
173
|
+
Return list of capabilities this provider supports.
|
|
174
|
+
|
|
175
|
+
WHY: Enables capability-based routing. Some providers may not
|
|
176
|
+
support all task types.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
List of supported ModelCapability values
|
|
180
|
+
"""
|
|
181
|
+
|
|
182
|
+
@abstractmethod
|
|
183
|
+
async def get_available_models(self) -> List[str]:
|
|
184
|
+
"""
|
|
185
|
+
List models available from this provider.
|
|
186
|
+
|
|
187
|
+
WHY: Enables model validation and user selection. Local providers
|
|
188
|
+
may have different models installed than expected.
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
List of model names/identifiers
|
|
192
|
+
|
|
193
|
+
Example:
|
|
194
|
+
models = await provider.get_available_models()
|
|
195
|
+
# ["llama3.3:70b", "gemma2:9b", "mistral:7b"]
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
@abstractmethod
|
|
199
|
+
async def get_model_info(self, model: str) -> Dict[str, Any]:
|
|
200
|
+
"""
|
|
201
|
+
Get detailed information about a specific model.
|
|
202
|
+
|
|
203
|
+
WHY: Provides model metadata for UI display and capability checking.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
model: Model name/identifier
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
Dictionary with model details (size, parameters, capabilities, etc.)
|
|
210
|
+
"""
|
|
211
|
+
|
|
212
|
+
@abstractmethod
|
|
213
|
+
async def shutdown(self) -> None:
|
|
214
|
+
"""
|
|
215
|
+
Shutdown provider and cleanup resources.
|
|
216
|
+
|
|
217
|
+
WHY: Proper resource cleanup for connection pools, HTTP sessions, etc.
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class IModelRouter(ABC):
|
|
222
|
+
"""
|
|
223
|
+
Interface for intelligent model routing with fallback.
|
|
224
|
+
|
|
225
|
+
WHY: Manages provider selection and fallback logic. Routes requests
|
|
226
|
+
to optimal provider based on availability and configuration.
|
|
227
|
+
|
|
228
|
+
DESIGN PATTERN: Chain of Responsibility - tries providers in order
|
|
229
|
+
until one succeeds or all fail.
|
|
230
|
+
"""
|
|
231
|
+
|
|
232
|
+
@abstractmethod
|
|
233
|
+
async def analyze_content(
|
|
234
|
+
self,
|
|
235
|
+
content: str,
|
|
236
|
+
task: ModelCapability,
|
|
237
|
+
model: Optional[str] = None,
|
|
238
|
+
**kwargs,
|
|
239
|
+
) -> ModelResponse:
|
|
240
|
+
"""
|
|
241
|
+
Route content analysis to optimal provider.
|
|
242
|
+
|
|
243
|
+
WHY: Single entry point for all content analysis. Handles provider
|
|
244
|
+
selection, fallback, and error recovery transparently.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
content: Text content to analyze
|
|
248
|
+
task: Type of analysis to perform
|
|
249
|
+
model: Optional specific model to use
|
|
250
|
+
**kwargs: Provider-specific options
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
ModelResponse from successful provider
|
|
254
|
+
"""
|
|
255
|
+
|
|
256
|
+
@abstractmethod
|
|
257
|
+
def get_active_provider(self) -> Optional[str]:
|
|
258
|
+
"""
|
|
259
|
+
Get name of currently active provider.
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
Provider name or None if no provider active
|
|
263
|
+
"""
|
|
264
|
+
|
|
265
|
+
@abstractmethod
|
|
266
|
+
async def get_provider_status(self) -> Dict[str, Dict[str, Any]]:
|
|
267
|
+
"""
|
|
268
|
+
Get status of all configured providers.
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
Dictionary mapping provider names to status info
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
__all__ = [
|
|
276
|
+
"IModelProvider",
|
|
277
|
+
"IModelRouter",
|
|
278
|
+
"ModelCapability",
|
|
279
|
+
"ModelProvider",
|
|
280
|
+
"ModelResponse",
|
|
281
|
+
]
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Process Management Interfaces for Claude MPM Framework
|
|
3
|
+
=======================================================
|
|
4
|
+
|
|
5
|
+
WHY: This module defines interfaces for local process management operations,
|
|
6
|
+
enabling the local-ops-agent to spawn, track, and manage background processes
|
|
7
|
+
with proper isolation, state persistence, and port conflict prevention.
|
|
8
|
+
|
|
9
|
+
DESIGN DECISION: Process management interfaces are separated from other service
|
|
10
|
+
interfaces to maintain clear boundaries between deployment operations and other
|
|
11
|
+
system services.
|
|
12
|
+
|
|
13
|
+
ARCHITECTURE:
|
|
14
|
+
- ILocalProcessManager: Core interface for process lifecycle management
|
|
15
|
+
- IDeploymentStateManager: Interface for persistent state tracking
|
|
16
|
+
- Process data models defined in models/process.py
|
|
17
|
+
|
|
18
|
+
USAGE:
|
|
19
|
+
state_manager = DeploymentStateManager(state_file_path)
|
|
20
|
+
process_manager = LocalProcessManager(state_manager)
|
|
21
|
+
|
|
22
|
+
config = StartConfig(
|
|
23
|
+
command=["npm", "run", "dev"],
|
|
24
|
+
working_directory="/path/to/project",
|
|
25
|
+
port=3000
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
deployment = await process_manager.start(config)
|
|
29
|
+
print(f"Started process {deployment.process_id} on port {deployment.port}")
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from abc import ABC, abstractmethod
|
|
33
|
+
from typing import Dict, List, Optional
|
|
34
|
+
|
|
35
|
+
from claude_mpm.core.enums import ServiceState
|
|
36
|
+
from claude_mpm.services.core.models.process import (
|
|
37
|
+
DeploymentState,
|
|
38
|
+
ProcessInfo,
|
|
39
|
+
StartConfig,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class IDeploymentStateManager(ABC):
|
|
44
|
+
"""
|
|
45
|
+
Interface for deployment state persistence and management.
|
|
46
|
+
|
|
47
|
+
WHY: State persistence is critical for tracking processes across restarts
|
|
48
|
+
and preventing orphaned processes. This interface abstracts the storage
|
|
49
|
+
mechanism to enable different backends (JSON file, database, etc.).
|
|
50
|
+
|
|
51
|
+
DESIGN DECISION: Provides both low-level (save/load) and high-level (query)
|
|
52
|
+
operations to support different use cases. Uses file locking to prevent
|
|
53
|
+
corruption from concurrent access.
|
|
54
|
+
|
|
55
|
+
Thread Safety: All operations must be thread-safe with proper locking.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
@abstractmethod
|
|
59
|
+
def load_state(self) -> Dict[str, DeploymentState]:
|
|
60
|
+
"""
|
|
61
|
+
Load all deployment states from persistent storage.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
Dictionary mapping deployment_id to DeploymentState
|
|
65
|
+
|
|
66
|
+
Raises:
|
|
67
|
+
StateCorruptionError: If state file is corrupted
|
|
68
|
+
IOError: If state file cannot be read
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
@abstractmethod
|
|
72
|
+
def save_state(self, states: Dict[str, DeploymentState]) -> None:
|
|
73
|
+
"""
|
|
74
|
+
Save all deployment states to persistent storage.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
states: Dictionary mapping deployment_id to DeploymentState
|
|
78
|
+
|
|
79
|
+
Raises:
|
|
80
|
+
IOError: If state file cannot be written
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
@abstractmethod
|
|
84
|
+
def get_deployment(self, deployment_id: str) -> Optional[DeploymentState]:
|
|
85
|
+
"""
|
|
86
|
+
Get a specific deployment by ID.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
deployment_id: Unique deployment identifier
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
DeploymentState if found, None otherwise
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
@abstractmethod
|
|
96
|
+
def get_all_deployments(self) -> List[DeploymentState]:
|
|
97
|
+
"""
|
|
98
|
+
Get all tracked deployments.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
List of all DeploymentState objects
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
@abstractmethod
|
|
105
|
+
def get_deployments_by_status(self, status: ServiceState) -> List[DeploymentState]:
|
|
106
|
+
"""
|
|
107
|
+
Get all deployments with a specific status.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
status: ServiceState to filter by
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
List of matching DeploymentState objects
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
@abstractmethod
|
|
117
|
+
def get_deployment_by_port(self, port: int) -> Optional[DeploymentState]:
|
|
118
|
+
"""
|
|
119
|
+
Get deployment using a specific port.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
port: Port number to search for
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
DeploymentState if found, None otherwise
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
@abstractmethod
|
|
129
|
+
def get_deployments_by_project(
|
|
130
|
+
self, working_directory: str
|
|
131
|
+
) -> List[DeploymentState]:
|
|
132
|
+
"""
|
|
133
|
+
Get all deployments for a specific project directory.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
working_directory: Project directory path
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
List of matching DeploymentState objects
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
@abstractmethod
|
|
143
|
+
def add_deployment(self, deployment: DeploymentState) -> None:
|
|
144
|
+
"""
|
|
145
|
+
Add or update a deployment in state.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
deployment: DeploymentState to add/update
|
|
149
|
+
|
|
150
|
+
Raises:
|
|
151
|
+
IOError: If state cannot be persisted
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
@abstractmethod
|
|
155
|
+
def remove_deployment(self, deployment_id: str) -> bool:
|
|
156
|
+
"""
|
|
157
|
+
Remove a deployment from state.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
deployment_id: Unique deployment identifier
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
True if deployment was removed, False if not found
|
|
164
|
+
|
|
165
|
+
Raises:
|
|
166
|
+
IOError: If state cannot be persisted
|
|
167
|
+
"""
|
|
168
|
+
|
|
169
|
+
@abstractmethod
|
|
170
|
+
def update_deployment_status(
|
|
171
|
+
self, deployment_id: str, status: ServiceState
|
|
172
|
+
) -> bool:
|
|
173
|
+
"""
|
|
174
|
+
Update the status of a deployment.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
deployment_id: Unique deployment identifier
|
|
178
|
+
status: New ServiceState
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
True if updated, False if deployment not found
|
|
182
|
+
|
|
183
|
+
Raises:
|
|
184
|
+
IOError: If state cannot be persisted
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
@abstractmethod
|
|
188
|
+
def cleanup_dead_pids(self) -> int:
|
|
189
|
+
"""
|
|
190
|
+
Remove deployments with dead process IDs.
|
|
191
|
+
|
|
192
|
+
WHY: Processes may crash or be killed externally. This method cleans
|
|
193
|
+
up stale state entries for processes that no longer exist.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
Number of dead PIDs cleaned up
|
|
197
|
+
|
|
198
|
+
Raises:
|
|
199
|
+
IOError: If state cannot be persisted
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class ILocalProcessManager(ABC):
|
|
204
|
+
"""
|
|
205
|
+
Interface for local process lifecycle management.
|
|
206
|
+
|
|
207
|
+
WHY: Process management involves complex operations like spawning, tracking,
|
|
208
|
+
and terminating background processes. This interface abstracts these operations
|
|
209
|
+
to enable different implementations and improve testability.
|
|
210
|
+
|
|
211
|
+
DESIGN DECISION: Provides high-level operations (start, stop, restart) that
|
|
212
|
+
handle all the complexity internally including port checking, process group
|
|
213
|
+
isolation, and state tracking.
|
|
214
|
+
|
|
215
|
+
Process Lifecycle:
|
|
216
|
+
1. Start: Spawn process with isolation and port checking
|
|
217
|
+
2. Monitor: Track status and update state
|
|
218
|
+
3. Stop: Graceful shutdown with fallback to force kill
|
|
219
|
+
4. Cleanup: Remove state and release resources
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
@abstractmethod
|
|
223
|
+
def start(self, config: StartConfig) -> DeploymentState:
|
|
224
|
+
"""
|
|
225
|
+
Start a new background process.
|
|
226
|
+
|
|
227
|
+
WHY: Combines process spawning, port allocation, and state tracking in
|
|
228
|
+
a single operation to ensure consistency.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
config: Configuration for the process to start
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
DeploymentState with process information
|
|
235
|
+
|
|
236
|
+
Raises:
|
|
237
|
+
ProcessSpawnError: If process cannot be spawned
|
|
238
|
+
PortConflictError: If requested port is unavailable and no alternative found
|
|
239
|
+
ValueError: If configuration is invalid
|
|
240
|
+
"""
|
|
241
|
+
|
|
242
|
+
@abstractmethod
|
|
243
|
+
def stop(self, deployment_id: str, timeout: int = 10, force: bool = False) -> bool:
|
|
244
|
+
"""
|
|
245
|
+
Stop a running process.
|
|
246
|
+
|
|
247
|
+
WHY: Provides graceful shutdown with configurable timeout and force
|
|
248
|
+
option for stuck processes.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
deployment_id: Unique deployment identifier
|
|
252
|
+
timeout: Seconds to wait for graceful shutdown
|
|
253
|
+
force: If True, kill immediately without waiting
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
True if process stopped successfully
|
|
257
|
+
|
|
258
|
+
Raises:
|
|
259
|
+
ValueError: If deployment_id not found
|
|
260
|
+
"""
|
|
261
|
+
|
|
262
|
+
@abstractmethod
|
|
263
|
+
def restart(self, deployment_id: str, timeout: int = 10) -> DeploymentState:
|
|
264
|
+
"""
|
|
265
|
+
Restart a process (stop then start with same config).
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
deployment_id: Unique deployment identifier
|
|
269
|
+
timeout: Seconds to wait for graceful shutdown
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
New DeploymentState after restart
|
|
273
|
+
|
|
274
|
+
Raises:
|
|
275
|
+
ValueError: If deployment_id not found
|
|
276
|
+
ProcessSpawnError: If restart fails
|
|
277
|
+
"""
|
|
278
|
+
|
|
279
|
+
@abstractmethod
|
|
280
|
+
def get_status(self, deployment_id: str) -> Optional[ProcessInfo]:
|
|
281
|
+
"""
|
|
282
|
+
Get current status and runtime information for a process.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
deployment_id: Unique deployment identifier
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
ProcessInfo with current status, or None if not found
|
|
289
|
+
"""
|
|
290
|
+
|
|
291
|
+
@abstractmethod
|
|
292
|
+
def list_processes(
|
|
293
|
+
self, status_filter: Optional[ServiceState] = None
|
|
294
|
+
) -> List[ProcessInfo]:
|
|
295
|
+
"""
|
|
296
|
+
List all managed processes.
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
status_filter: Optional status to filter by
|
|
300
|
+
|
|
301
|
+
Returns:
|
|
302
|
+
List of ProcessInfo for all matching processes
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
@abstractmethod
|
|
306
|
+
def is_port_available(self, port: int) -> bool:
|
|
307
|
+
"""
|
|
308
|
+
Check if a port is available for use.
|
|
309
|
+
|
|
310
|
+
WHY: Port conflict prevention is critical for reliable deployments.
|
|
311
|
+
This check happens before process spawn.
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
port: Port number to check
|
|
315
|
+
|
|
316
|
+
Returns:
|
|
317
|
+
True if port is available
|
|
318
|
+
"""
|
|
319
|
+
|
|
320
|
+
@abstractmethod
|
|
321
|
+
def find_available_port(
|
|
322
|
+
self, preferred_port: int, max_attempts: int = 10
|
|
323
|
+
) -> Optional[int]:
|
|
324
|
+
"""
|
|
325
|
+
Find an available port starting from preferred_port.
|
|
326
|
+
|
|
327
|
+
WHY: Uses linear probing to find alternative ports when the preferred
|
|
328
|
+
port is unavailable. Respects protected port ranges.
|
|
329
|
+
|
|
330
|
+
Args:
|
|
331
|
+
preferred_port: Starting port number
|
|
332
|
+
max_attempts: Maximum number of ports to try
|
|
333
|
+
|
|
334
|
+
Returns:
|
|
335
|
+
Available port number, or None if none found
|
|
336
|
+
"""
|
|
337
|
+
|
|
338
|
+
@abstractmethod
|
|
339
|
+
def cleanup_orphans(self) -> int:
|
|
340
|
+
"""
|
|
341
|
+
Clean up orphaned process state entries.
|
|
342
|
+
|
|
343
|
+
WHY: Processes may crash or be killed externally, leaving stale state.
|
|
344
|
+
This method identifies and cleans up these orphans.
|
|
345
|
+
|
|
346
|
+
Returns:
|
|
347
|
+
Number of orphaned entries cleaned up
|
|
348
|
+
"""
|
|
349
|
+
|
|
350
|
+
@abstractmethod
|
|
351
|
+
def generate_deployment_id(
|
|
352
|
+
self, project_name: str, port: Optional[int] = None
|
|
353
|
+
) -> str:
|
|
354
|
+
"""
|
|
355
|
+
Generate a unique deployment ID.
|
|
356
|
+
|
|
357
|
+
WHY: Provides consistent ID generation with optional port suffix for
|
|
358
|
+
projects with multiple deployments.
|
|
359
|
+
|
|
360
|
+
Args:
|
|
361
|
+
project_name: Name of the project
|
|
362
|
+
port: Optional port number to include in ID
|
|
363
|
+
|
|
364
|
+
Returns:
|
|
365
|
+
Unique deployment identifier
|
|
366
|
+
"""
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
__all__ = [
|
|
370
|
+
"IDeploymentStateManager",
|
|
371
|
+
"ILocalProcessManager",
|
|
372
|
+
]
|