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.
Files changed (250) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_ENGINEER.md +286 -0
  3. claude_mpm/agents/BASE_PM.md +48 -17
  4. claude_mpm/agents/OUTPUT_STYLE.md +329 -11
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +227 -8
  6. claude_mpm/agents/agent_loader.py +17 -5
  7. claude_mpm/agents/frontmatter_validator.py +284 -253
  8. claude_mpm/agents/templates/agentic-coder-optimizer.json +9 -2
  9. claude_mpm/agents/templates/api_qa.json +7 -1
  10. claude_mpm/agents/templates/clerk-ops.json +8 -1
  11. claude_mpm/agents/templates/code_analyzer.json +4 -1
  12. claude_mpm/agents/templates/dart_engineer.json +11 -1
  13. claude_mpm/agents/templates/data_engineer.json +11 -1
  14. claude_mpm/agents/templates/documentation.json +6 -1
  15. claude_mpm/agents/templates/engineer.json +18 -1
  16. claude_mpm/agents/templates/gcp_ops_agent.json +8 -1
  17. claude_mpm/agents/templates/golang_engineer.json +11 -1
  18. claude_mpm/agents/templates/java_engineer.json +12 -2
  19. claude_mpm/agents/templates/local_ops_agent.json +1217 -6
  20. claude_mpm/agents/templates/nextjs_engineer.json +11 -1
  21. claude_mpm/agents/templates/ops.json +8 -1
  22. claude_mpm/agents/templates/php-engineer.json +11 -1
  23. claude_mpm/agents/templates/project_organizer.json +10 -3
  24. claude_mpm/agents/templates/prompt-engineer.json +5 -1
  25. claude_mpm/agents/templates/python_engineer.json +11 -1
  26. claude_mpm/agents/templates/qa.json +7 -1
  27. claude_mpm/agents/templates/react_engineer.json +11 -1
  28. claude_mpm/agents/templates/refactoring_engineer.json +8 -1
  29. claude_mpm/agents/templates/research.json +4 -1
  30. claude_mpm/agents/templates/ruby-engineer.json +11 -1
  31. claude_mpm/agents/templates/rust_engineer.json +11 -1
  32. claude_mpm/agents/templates/security.json +6 -1
  33. claude_mpm/agents/templates/svelte-engineer.json +225 -0
  34. claude_mpm/agents/templates/ticketing.json +6 -1
  35. claude_mpm/agents/templates/typescript_engineer.json +11 -1
  36. claude_mpm/agents/templates/vercel_ops_agent.json +8 -1
  37. claude_mpm/agents/templates/version_control.json +8 -1
  38. claude_mpm/agents/templates/web_qa.json +7 -1
  39. claude_mpm/agents/templates/web_ui.json +11 -1
  40. claude_mpm/cli/__init__.py +34 -706
  41. claude_mpm/cli/commands/agent_manager.py +25 -12
  42. claude_mpm/cli/commands/agent_state_manager.py +186 -0
  43. claude_mpm/cli/commands/agents.py +204 -148
  44. claude_mpm/cli/commands/aggregate.py +7 -3
  45. claude_mpm/cli/commands/analyze.py +9 -4
  46. claude_mpm/cli/commands/analyze_code.py +7 -2
  47. claude_mpm/cli/commands/auto_configure.py +7 -9
  48. claude_mpm/cli/commands/config.py +47 -13
  49. claude_mpm/cli/commands/configure.py +294 -1788
  50. claude_mpm/cli/commands/configure_agent_display.py +261 -0
  51. claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
  52. claude_mpm/cli/commands/configure_hook_manager.py +225 -0
  53. claude_mpm/cli/commands/configure_models.py +18 -0
  54. claude_mpm/cli/commands/configure_navigation.py +167 -0
  55. claude_mpm/cli/commands/configure_paths.py +104 -0
  56. claude_mpm/cli/commands/configure_persistence.py +254 -0
  57. claude_mpm/cli/commands/configure_startup_manager.py +646 -0
  58. claude_mpm/cli/commands/configure_template_editor.py +497 -0
  59. claude_mpm/cli/commands/configure_validators.py +73 -0
  60. claude_mpm/cli/commands/local_deploy.py +537 -0
  61. claude_mpm/cli/commands/memory.py +54 -20
  62. claude_mpm/cli/commands/mpm_init.py +39 -25
  63. claude_mpm/cli/commands/mpm_init_handler.py +8 -3
  64. claude_mpm/cli/executor.py +202 -0
  65. claude_mpm/cli/helpers.py +105 -0
  66. claude_mpm/cli/interactive/__init__.py +3 -0
  67. claude_mpm/cli/interactive/skills_wizard.py +491 -0
  68. claude_mpm/cli/parsers/__init__.py +7 -1
  69. claude_mpm/cli/parsers/base_parser.py +98 -3
  70. claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
  71. claude_mpm/cli/shared/output_formatters.py +28 -19
  72. claude_mpm/cli/startup.py +481 -0
  73. claude_mpm/cli/utils.py +52 -1
  74. claude_mpm/commands/mpm-help.md +3 -0
  75. claude_mpm/commands/mpm-version.md +113 -0
  76. claude_mpm/commands/mpm.md +1 -0
  77. claude_mpm/config/agent_config.py +2 -2
  78. claude_mpm/config/model_config.py +428 -0
  79. claude_mpm/core/base_service.py +13 -12
  80. claude_mpm/core/enums.py +452 -0
  81. claude_mpm/core/factories.py +1 -1
  82. claude_mpm/core/instruction_reinforcement_hook.py +2 -1
  83. claude_mpm/core/interactive_session.py +9 -3
  84. claude_mpm/core/logging_config.py +6 -2
  85. claude_mpm/core/oneshot_session.py +8 -4
  86. claude_mpm/core/optimized_agent_loader.py +3 -3
  87. claude_mpm/core/output_style_manager.py +12 -192
  88. claude_mpm/core/service_registry.py +5 -1
  89. claude_mpm/core/types.py +2 -9
  90. claude_mpm/core/typing_utils.py +7 -6
  91. claude_mpm/dashboard/static/js/dashboard.js +0 -14
  92. claude_mpm/dashboard/templates/index.html +3 -41
  93. claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
  94. claude_mpm/hooks/instruction_reinforcement.py +7 -2
  95. claude_mpm/models/resume_log.py +340 -0
  96. claude_mpm/services/agents/auto_config_manager.py +10 -11
  97. claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
  98. claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
  99. claude_mpm/services/agents/deployment/agent_validator.py +17 -1
  100. claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
  101. claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
  102. claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
  103. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
  104. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
  105. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
  106. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
  107. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
  108. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
  109. claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
  110. claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
  111. claude_mpm/services/agents/local_template_manager.py +1 -1
  112. claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
  113. claude_mpm/services/agents/registry/modification_tracker.py +5 -2
  114. claude_mpm/services/command_handler_service.py +11 -5
  115. claude_mpm/services/core/interfaces/__init__.py +74 -2
  116. claude_mpm/services/core/interfaces/health.py +172 -0
  117. claude_mpm/services/core/interfaces/model.py +281 -0
  118. claude_mpm/services/core/interfaces/process.py +372 -0
  119. claude_mpm/services/core/interfaces/restart.py +307 -0
  120. claude_mpm/services/core/interfaces/stability.py +260 -0
  121. claude_mpm/services/core/models/__init__.py +33 -0
  122. claude_mpm/services/core/models/agent_config.py +12 -28
  123. claude_mpm/services/core/models/health.py +162 -0
  124. claude_mpm/services/core/models/process.py +235 -0
  125. claude_mpm/services/core/models/restart.py +302 -0
  126. claude_mpm/services/core/models/stability.py +264 -0
  127. claude_mpm/services/core/path_resolver.py +23 -7
  128. claude_mpm/services/diagnostics/__init__.py +2 -2
  129. claude_mpm/services/diagnostics/checks/agent_check.py +25 -24
  130. claude_mpm/services/diagnostics/checks/claude_code_check.py +24 -23
  131. claude_mpm/services/diagnostics/checks/common_issues_check.py +25 -24
  132. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -23
  133. claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
  134. claude_mpm/services/diagnostics/checks/installation_check.py +30 -29
  135. claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
  136. claude_mpm/services/diagnostics/checks/mcp_check.py +50 -36
  137. claude_mpm/services/diagnostics/checks/mcp_services_check.py +36 -31
  138. claude_mpm/services/diagnostics/checks/monitor_check.py +23 -22
  139. claude_mpm/services/diagnostics/checks/startup_log_check.py +9 -8
  140. claude_mpm/services/diagnostics/diagnostic_runner.py +6 -5
  141. claude_mpm/services/diagnostics/doctor_reporter.py +28 -25
  142. claude_mpm/services/diagnostics/models.py +19 -24
  143. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
  144. claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
  145. claude_mpm/services/infrastructure/monitoring/base.py +5 -13
  146. claude_mpm/services/infrastructure/monitoring/network.py +7 -6
  147. claude_mpm/services/infrastructure/monitoring/process.py +13 -12
  148. claude_mpm/services/infrastructure/monitoring/resources.py +7 -6
  149. claude_mpm/services/infrastructure/monitoring/service.py +16 -15
  150. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  151. claude_mpm/services/local_ops/__init__.py +163 -0
  152. claude_mpm/services/local_ops/crash_detector.py +257 -0
  153. claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
  154. claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
  155. claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
  156. claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
  157. claude_mpm/services/local_ops/health_manager.py +430 -0
  158. claude_mpm/services/local_ops/log_monitor.py +396 -0
  159. claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
  160. claude_mpm/services/local_ops/process_manager.py +595 -0
  161. claude_mpm/services/local_ops/resource_monitor.py +331 -0
  162. claude_mpm/services/local_ops/restart_manager.py +401 -0
  163. claude_mpm/services/local_ops/restart_policy.py +387 -0
  164. claude_mpm/services/local_ops/state_manager.py +372 -0
  165. claude_mpm/services/local_ops/unified_manager.py +600 -0
  166. claude_mpm/services/mcp_config_manager.py +9 -4
  167. claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
  168. claude_mpm/services/mcp_gateway/core/base.py +18 -31
  169. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +71 -24
  170. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
  171. claude_mpm/services/memory_hook_service.py +4 -1
  172. claude_mpm/services/model/__init__.py +147 -0
  173. claude_mpm/services/model/base_provider.py +365 -0
  174. claude_mpm/services/model/claude_provider.py +412 -0
  175. claude_mpm/services/model/model_router.py +453 -0
  176. claude_mpm/services/model/ollama_provider.py +415 -0
  177. claude_mpm/services/monitor/daemon_manager.py +3 -2
  178. claude_mpm/services/monitor/handlers/dashboard.py +2 -1
  179. claude_mpm/services/monitor/handlers/hooks.py +2 -1
  180. claude_mpm/services/monitor/management/lifecycle.py +3 -2
  181. claude_mpm/services/monitor/server.py +2 -1
  182. claude_mpm/services/session_management_service.py +3 -2
  183. claude_mpm/services/session_manager.py +205 -1
  184. claude_mpm/services/shared/async_service_base.py +16 -27
  185. claude_mpm/services/shared/lifecycle_service_base.py +1 -14
  186. claude_mpm/services/socketio/handlers/__init__.py +5 -2
  187. claude_mpm/services/socketio/handlers/hook.py +13 -2
  188. claude_mpm/services/socketio/handlers/registry.py +4 -2
  189. claude_mpm/services/socketio/server/main.py +10 -8
  190. claude_mpm/services/subprocess_launcher_service.py +14 -5
  191. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +8 -7
  192. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +6 -5
  193. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +8 -7
  194. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +7 -6
  195. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +5 -4
  196. claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
  197. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
  198. claude_mpm/services/unified/deployment_strategies/local.py +6 -5
  199. claude_mpm/services/unified/deployment_strategies/utils.py +6 -5
  200. claude_mpm/services/unified/deployment_strategies/vercel.py +7 -6
  201. claude_mpm/services/unified/interfaces.py +3 -1
  202. claude_mpm/services/unified/unified_analyzer.py +14 -10
  203. claude_mpm/services/unified/unified_config.py +2 -1
  204. claude_mpm/services/unified/unified_deployment.py +9 -4
  205. claude_mpm/services/version_service.py +104 -1
  206. claude_mpm/skills/__init__.py +21 -0
  207. claude_mpm/skills/bundled/__init__.py +6 -0
  208. claude_mpm/skills/bundled/api-documentation.md +393 -0
  209. claude_mpm/skills/bundled/async-testing.md +571 -0
  210. claude_mpm/skills/bundled/code-review.md +143 -0
  211. claude_mpm/skills/bundled/database-migration.md +199 -0
  212. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  213. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  214. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  215. claude_mpm/skills/bundled/git-workflow.md +414 -0
  216. claude_mpm/skills/bundled/imagemagick.md +204 -0
  217. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  218. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  219. claude_mpm/skills/bundled/pdf.md +141 -0
  220. claude_mpm/skills/bundled/performance-profiling.md +567 -0
  221. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  222. claude_mpm/skills/bundled/security-scanning.md +327 -0
  223. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  224. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  225. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  226. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  227. claude_mpm/skills/bundled/xlsx.md +157 -0
  228. claude_mpm/skills/registry.py +286 -0
  229. claude_mpm/skills/skill_manager.py +310 -0
  230. claude_mpm/tools/code_tree_analyzer.py +177 -141
  231. claude_mpm/tools/code_tree_events.py +4 -2
  232. claude_mpm/utils/agent_dependency_loader.py +2 -2
  233. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/METADATA +117 -8
  234. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/RECORD +238 -174
  235. claude_mpm/dashboard/static/css/code-tree.css +0 -1639
  236. claude_mpm/dashboard/static/js/components/code-tree/tree-breadcrumb.js +0 -353
  237. claude_mpm/dashboard/static/js/components/code-tree/tree-constants.js +0 -235
  238. claude_mpm/dashboard/static/js/components/code-tree/tree-search.js +0 -409
  239. claude_mpm/dashboard/static/js/components/code-tree/tree-utils.js +0 -435
  240. claude_mpm/dashboard/static/js/components/code-tree.js +0 -5869
  241. claude_mpm/dashboard/static/js/components/code-viewer.js +0 -1386
  242. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
  243. claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
  244. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
  245. claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
  246. claude_mpm/services/project/analyzer_refactored.py +0 -450
  247. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/WHEEL +0 -0
  248. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/entry_points.txt +0 -0
  249. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/licenses/LICENSE +0 -0
  250. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,365 @@
1
+ """
2
+ Base Model Provider Implementation for Claude MPM Framework
3
+ ===========================================================
4
+
5
+ WHY: Provides common functionality for all model providers, reducing
6
+ duplication and ensuring consistent behavior across implementations.
7
+
8
+ DESIGN DECISION: Abstract base class extends both BaseService and IModelProvider,
9
+ providing service lifecycle management plus model-specific utilities.
10
+
11
+ RESPONSIBILITIES:
12
+ - Common error handling and logging
13
+ - Task-specific prompt generation
14
+ - Response formatting and validation
15
+ - Performance metrics tracking
16
+ - Retry logic for transient failures
17
+ """
18
+
19
+ import asyncio
20
+ import time
21
+ from abc import abstractmethod
22
+ from typing import Any, Dict, Optional
23
+
24
+ from claude_mpm.core.logger import get_logger
25
+ from claude_mpm.services.core.base import BaseService
26
+ from claude_mpm.services.core.interfaces.model import (
27
+ IModelProvider,
28
+ ModelCapability,
29
+ ModelResponse,
30
+ )
31
+
32
+
33
+ class BaseModelProvider(BaseService, IModelProvider):
34
+ """
35
+ Abstract base class for model providers.
36
+
37
+ WHY: Centralizes common provider functionality like prompt generation,
38
+ error handling, and response formatting.
39
+
40
+ Usage:
41
+ class MyProvider(BaseModelProvider):
42
+ async def analyze_content(self, content, task, model=None, **kwargs):
43
+ prompt = self.get_task_prompt(task, content)
44
+ # Call provider API
45
+ return self.create_response(...)
46
+ """
47
+
48
+ # Task-specific prompt templates
49
+ TASK_PROMPTS: Dict[ModelCapability, str] = {
50
+ ModelCapability.SEO_ANALYSIS: """Analyze the following content for SEO effectiveness. Provide:
51
+ 1. Primary and secondary keywords identified
52
+ 2. Keyword density analysis
53
+ 3. Meta description recommendation
54
+ 4. Title tag optimization suggestions
55
+ 5. Content structure analysis (H1, H2, etc.)
56
+ 6. SEO score (0-100) with justification
57
+
58
+ Content to analyze:
59
+ {content}
60
+
61
+ Provide your analysis in a structured format.""",
62
+ ModelCapability.READABILITY: """Analyze the readability of the following content. Provide:
63
+ 1. Readability score (Flesch-Kincaid or similar)
64
+ 2. Average sentence length
65
+ 3. Complex word count
66
+ 4. Grade level assessment
67
+ 5. Suggestions for improvement
68
+ 6. Overall readability rating (Easy/Medium/Hard)
69
+
70
+ Content to analyze:
71
+ {content}
72
+
73
+ Provide your analysis in a structured format.""",
74
+ ModelCapability.GRAMMAR: """Perform a grammar and style check on the following content. Identify:
75
+ 1. Grammatical errors with corrections
76
+ 2. Spelling mistakes
77
+ 3. Punctuation issues
78
+ 4. Style inconsistencies
79
+ 5. Clarity improvements
80
+ 6. Overall quality score (0-100)
81
+
82
+ Content to analyze:
83
+ {content}
84
+
85
+ Provide your analysis in a structured format.""",
86
+ ModelCapability.SUMMARIZATION: """Provide a comprehensive summary of the following content:
87
+ 1. Main topic and key points (3-5 bullet points)
88
+ 2. Supporting details
89
+ 3. Conclusions or recommendations
90
+ 4. One-sentence TL;DR
91
+
92
+ Content to summarize:
93
+ {content}
94
+
95
+ Provide your summary in a structured format.""",
96
+ ModelCapability.KEYWORD_EXTRACTION: """Extract and analyze keywords from the following content:
97
+ 1. Primary keywords (top 5-10)
98
+ 2. Long-tail keyword phrases
99
+ 3. Semantic relationships between keywords
100
+ 4. Keyword relevance scores
101
+ 5. Suggested additional keywords
102
+
103
+ Content to analyze:
104
+ {content}
105
+
106
+ Provide your keyword analysis in a structured format.""",
107
+ ModelCapability.ACCESSIBILITY: """Analyze the accessibility of the following content:
108
+ 1. Language complexity level
109
+ 2. Inclusivity assessment
110
+ 3. Plain language recommendations
111
+ 4. Potential barriers for readers with disabilities
112
+ 5. WCAG compliance suggestions
113
+ 6. Accessibility score (0-100)
114
+
115
+ Content to analyze:
116
+ {content}
117
+
118
+ Provide your analysis in a structured format.""",
119
+ ModelCapability.SENTIMENT: """Analyze the sentiment and tone of the following content:
120
+ 1. Overall sentiment (Positive/Negative/Neutral)
121
+ 2. Sentiment score (-1 to +1)
122
+ 3. Emotional tone detected
123
+ 4. Audience perception analysis
124
+ 5. Tone consistency evaluation
125
+
126
+ Content to analyze:
127
+ {content}
128
+
129
+ Provide your analysis in a structured format.""",
130
+ ModelCapability.GENERAL: """Analyze the following content and provide:
131
+ 1. Overview and main themes
132
+ 2. Quality assessment
133
+ 3. Structural analysis
134
+ 4. Improvement suggestions
135
+ 5. Overall effectiveness rating
136
+
137
+ Content to analyze:
138
+ {content}
139
+
140
+ Provide your analysis in a structured format.""",
141
+ }
142
+
143
+ def __init__(
144
+ self,
145
+ provider_name: str,
146
+ config: Optional[Dict[str, Any]] = None,
147
+ ):
148
+ """
149
+ Initialize base model provider.
150
+
151
+ Args:
152
+ provider_name: Name of the provider (e.g., "ollama", "claude")
153
+ config: Provider-specific configuration
154
+ """
155
+ super().__init__(service_name=f"{provider_name}_provider", config=config)
156
+ self.provider_name = provider_name
157
+ self.logger = get_logger(f"model.{provider_name}")
158
+ self._request_count = 0
159
+ self._error_count = 0
160
+ self._total_latency = 0.0
161
+
162
+ def get_task_prompt(self, task: ModelCapability, content: str) -> str:
163
+ """
164
+ Generate task-specific prompt.
165
+
166
+ WHY: Centralizes prompt engineering. Tasks require different analysis
167
+ approaches and output formats.
168
+
169
+ Args:
170
+ task: Type of analysis to perform
171
+ content: Content to analyze
172
+
173
+ Returns:
174
+ Formatted prompt string
175
+ """
176
+ template = self.TASK_PROMPTS.get(
177
+ task, self.TASK_PROMPTS[ModelCapability.GENERAL]
178
+ )
179
+ return template.format(content=content)
180
+
181
+ def create_response(
182
+ self,
183
+ success: bool,
184
+ model: str,
185
+ task: ModelCapability,
186
+ result: str = "",
187
+ metadata: Optional[Dict[str, Any]] = None,
188
+ error: Optional[str] = None,
189
+ ) -> ModelResponse:
190
+ """
191
+ Create standardized model response.
192
+
193
+ WHY: Ensures consistent response format across all providers.
194
+
195
+ Args:
196
+ success: Whether operation succeeded
197
+ model: Model used
198
+ task: Task performed
199
+ result: Analysis result
200
+ metadata: Additional metadata
201
+ error: Error message if failed
202
+
203
+ Returns:
204
+ ModelResponse object
205
+ """
206
+ return ModelResponse(
207
+ success=success,
208
+ provider=self.provider_name,
209
+ model=model,
210
+ task=task.value,
211
+ result=result,
212
+ metadata=metadata or {},
213
+ error=error,
214
+ )
215
+
216
+ async def analyze_with_retry(
217
+ self,
218
+ analyze_func,
219
+ content: str,
220
+ task: ModelCapability,
221
+ model: Optional[str] = None,
222
+ max_retries: int = 3,
223
+ **kwargs,
224
+ ) -> ModelResponse:
225
+ """
226
+ Execute analysis with retry logic.
227
+
228
+ WHY: Handles transient failures (network issues, rate limits, etc.)
229
+ without requiring retry logic in each provider implementation.
230
+
231
+ Args:
232
+ analyze_func: Async function to call for analysis
233
+ content: Content to analyze
234
+ task: Task to perform
235
+ model: Optional model to use
236
+ max_retries: Maximum retry attempts
237
+ **kwargs: Additional arguments for analyze_func
238
+
239
+ Returns:
240
+ ModelResponse from successful attempt or final error
241
+ """
242
+ last_error = None
243
+
244
+ for attempt in range(max_retries):
245
+ try:
246
+ start_time = time.time()
247
+ response = await analyze_func(content, task, model, **kwargs)
248
+ latency = time.time() - start_time
249
+
250
+ # Track metrics
251
+ self._request_count += 1
252
+ self._total_latency += latency
253
+
254
+ if response.success:
255
+ response.metadata["latency_seconds"] = latency
256
+ response.metadata["attempt"] = attempt + 1
257
+ self.log_debug(
258
+ f"Analysis completed in {latency:.2f}s (attempt {attempt + 1})"
259
+ )
260
+ return response
261
+ last_error = response.error
262
+ self._error_count += 1
263
+
264
+ except Exception as e:
265
+ last_error = str(e)
266
+ self._error_count += 1
267
+ self.log_warning(
268
+ f"Analysis attempt {attempt + 1} failed: {e}",
269
+ exc_info=True,
270
+ )
271
+
272
+ # Wait before retry (exponential backoff)
273
+ if attempt < max_retries - 1:
274
+ wait_time = 2**attempt # 1s, 2s, 4s
275
+ self.log_info(f"Retrying in {wait_time}s...")
276
+ await asyncio.sleep(wait_time)
277
+
278
+ # All retries failed
279
+ self.log_error(f"All {max_retries} attempts failed. Last error: {last_error}")
280
+ return self.create_response(
281
+ success=False,
282
+ model=model or "unknown",
283
+ task=task,
284
+ error=f"Failed after {max_retries} attempts: {last_error}",
285
+ )
286
+
287
+ def validate_content(self, content: str, max_length: Optional[int] = None) -> bool:
288
+ """
289
+ Validate content before analysis.
290
+
291
+ WHY: Prevents invalid requests and provides early error detection.
292
+
293
+ Args:
294
+ content: Content to validate
295
+ max_length: Optional maximum length in characters
296
+
297
+ Returns:
298
+ True if valid, False otherwise
299
+ """
300
+ if not content or not content.strip():
301
+ self.log_warning("Empty content provided for analysis")
302
+ return False
303
+
304
+ if max_length and len(content) > max_length:
305
+ self.log_warning(
306
+ f"Content length {len(content)} exceeds maximum {max_length}"
307
+ )
308
+ return False
309
+
310
+ return True
311
+
312
+ def get_metrics(self) -> Dict[str, Any]:
313
+ """
314
+ Get provider performance metrics.
315
+
316
+ Returns:
317
+ Dictionary of metrics (request count, error rate, avg latency)
318
+ """
319
+ avg_latency = (
320
+ self._total_latency / self._request_count if self._request_count > 0 else 0
321
+ )
322
+ error_rate = (
323
+ self._error_count / self._request_count if self._request_count > 0 else 0
324
+ )
325
+
326
+ return {
327
+ "provider": self.provider_name,
328
+ "request_count": self._request_count,
329
+ "error_count": self._error_count,
330
+ "error_rate": error_rate,
331
+ "avg_latency_seconds": avg_latency,
332
+ }
333
+
334
+ async def initialize(self) -> bool:
335
+ """
336
+ Initialize provider.
337
+
338
+ Subclasses should override to perform provider-specific setup.
339
+
340
+ Returns:
341
+ True if initialization successful
342
+ """
343
+ self.log_info(f"Initializing {self.provider_name} provider")
344
+ self._initialized = True
345
+ return True
346
+
347
+ async def shutdown(self) -> None:
348
+ """
349
+ Shutdown provider and cleanup resources.
350
+
351
+ Subclasses should override to perform provider-specific cleanup.
352
+ """
353
+ self.log_info(f"Shutting down {self.provider_name} provider")
354
+ self._shutdown = True
355
+
356
+ @abstractmethod
357
+ async def get_model_info(self, model: str) -> Dict[str, Any]:
358
+ """
359
+ Get model information.
360
+
361
+ Must be implemented by subclasses.
362
+ """
363
+
364
+
365
+ __all__ = ["BaseModelProvider"]