claude-mpm 3.7.8__py3-none-any.whl → 3.8.1__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 (93) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +0 -106
  3. claude_mpm/agents/INSTRUCTIONS.md +0 -96
  4. claude_mpm/agents/MEMORY.md +88 -0
  5. claude_mpm/agents/WORKFLOW.md +86 -0
  6. claude_mpm/agents/templates/code_analyzer.json +2 -2
  7. claude_mpm/agents/templates/data_engineer.json +1 -1
  8. claude_mpm/agents/templates/documentation.json +1 -1
  9. claude_mpm/agents/templates/engineer.json +1 -1
  10. claude_mpm/agents/templates/ops.json +1 -1
  11. claude_mpm/agents/templates/qa.json +1 -1
  12. claude_mpm/agents/templates/research.json +1 -1
  13. claude_mpm/agents/templates/security.json +1 -1
  14. claude_mpm/agents/templates/ticketing.json +2 -7
  15. claude_mpm/agents/templates/version_control.json +1 -1
  16. claude_mpm/agents/templates/web_qa.json +2 -2
  17. claude_mpm/agents/templates/web_ui.json +2 -2
  18. claude_mpm/cli/__init__.py +2 -2
  19. claude_mpm/cli/commands/__init__.py +2 -1
  20. claude_mpm/cli/commands/tickets.py +596 -19
  21. claude_mpm/cli/parser.py +217 -5
  22. claude_mpm/config/__init__.py +30 -39
  23. claude_mpm/config/socketio_config.py +8 -5
  24. claude_mpm/constants.py +13 -0
  25. claude_mpm/core/__init__.py +8 -18
  26. claude_mpm/core/cache.py +596 -0
  27. claude_mpm/core/claude_runner.py +166 -622
  28. claude_mpm/core/config.py +5 -1
  29. claude_mpm/core/constants.py +339 -0
  30. claude_mpm/core/container.py +461 -22
  31. claude_mpm/core/exceptions.py +392 -0
  32. claude_mpm/core/framework_loader.py +208 -94
  33. claude_mpm/core/interactive_session.py +432 -0
  34. claude_mpm/core/interfaces.py +424 -0
  35. claude_mpm/core/lazy.py +467 -0
  36. claude_mpm/core/logging_config.py +444 -0
  37. claude_mpm/core/oneshot_session.py +465 -0
  38. claude_mpm/core/optimized_agent_loader.py +485 -0
  39. claude_mpm/core/optimized_startup.py +490 -0
  40. claude_mpm/core/service_registry.py +52 -26
  41. claude_mpm/core/socketio_pool.py +162 -5
  42. claude_mpm/core/types.py +292 -0
  43. claude_mpm/core/typing_utils.py +477 -0
  44. claude_mpm/hooks/claude_hooks/hook_handler.py +213 -99
  45. claude_mpm/init.py +2 -1
  46. claude_mpm/services/__init__.py +78 -14
  47. claude_mpm/services/agent/__init__.py +24 -0
  48. claude_mpm/services/agent/deployment.py +2548 -0
  49. claude_mpm/services/agent/management.py +598 -0
  50. claude_mpm/services/agent/registry.py +813 -0
  51. claude_mpm/services/agents/deployment/agent_deployment.py +587 -268
  52. claude_mpm/services/agents/memory/agent_memory_manager.py +156 -1
  53. claude_mpm/services/async_session_logger.py +8 -3
  54. claude_mpm/services/communication/__init__.py +21 -0
  55. claude_mpm/services/communication/socketio.py +1933 -0
  56. claude_mpm/services/communication/websocket.py +479 -0
  57. claude_mpm/services/core/__init__.py +123 -0
  58. claude_mpm/services/core/base.py +247 -0
  59. claude_mpm/services/core/interfaces.py +951 -0
  60. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +23 -23
  61. claude_mpm/services/framework_claude_md_generator.py +3 -2
  62. claude_mpm/services/health_monitor.py +4 -3
  63. claude_mpm/services/hook_service.py +64 -4
  64. claude_mpm/services/infrastructure/__init__.py +21 -0
  65. claude_mpm/services/infrastructure/logging.py +202 -0
  66. claude_mpm/services/infrastructure/monitoring.py +893 -0
  67. claude_mpm/services/memory/indexed_memory.py +648 -0
  68. claude_mpm/services/project/__init__.py +21 -0
  69. claude_mpm/services/project/analyzer.py +864 -0
  70. claude_mpm/services/project/registry.py +608 -0
  71. claude_mpm/services/project_analyzer.py +95 -2
  72. claude_mpm/services/recovery_manager.py +15 -9
  73. claude_mpm/services/socketio/__init__.py +25 -0
  74. claude_mpm/services/socketio/handlers/__init__.py +25 -0
  75. claude_mpm/services/socketio/handlers/base.py +121 -0
  76. claude_mpm/services/socketio/handlers/connection.py +198 -0
  77. claude_mpm/services/socketio/handlers/file.py +213 -0
  78. claude_mpm/services/socketio/handlers/git.py +723 -0
  79. claude_mpm/services/socketio/handlers/memory.py +27 -0
  80. claude_mpm/services/socketio/handlers/project.py +25 -0
  81. claude_mpm/services/socketio/handlers/registry.py +145 -0
  82. claude_mpm/services/socketio_client_manager.py +12 -7
  83. claude_mpm/services/socketio_server.py +156 -30
  84. claude_mpm/services/ticket_manager.py +170 -7
  85. claude_mpm/utils/error_handler.py +1 -1
  86. claude_mpm/validation/agent_validator.py +27 -14
  87. claude_mpm/validation/frontmatter_validator.py +231 -0
  88. {claude_mpm-3.7.8.dist-info → claude_mpm-3.8.1.dist-info}/METADATA +58 -21
  89. {claude_mpm-3.7.8.dist-info → claude_mpm-3.8.1.dist-info}/RECORD +93 -53
  90. {claude_mpm-3.7.8.dist-info → claude_mpm-3.8.1.dist-info}/WHEEL +0 -0
  91. {claude_mpm-3.7.8.dist-info → claude_mpm-3.8.1.dist-info}/entry_points.txt +0 -0
  92. {claude_mpm-3.7.8.dist-info → claude_mpm-3.8.1.dist-info}/licenses/LICENSE +0 -0
  93. {claude_mpm-3.7.8.dist-info → claude_mpm-3.8.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,951 @@
1
+ """
2
+ Core Service Interfaces for Claude PM Framework
3
+ ==============================================
4
+
5
+ This module defines the core service interfaces that establish contracts for
6
+ dependency injection, service discovery, and framework orchestration.
7
+
8
+ Phase 1 Refactoring: Interface extraction and dependency injection foundation
9
+ - IServiceContainer: Dependency injection container
10
+ - IAgentRegistry: Agent discovery and management
11
+ - IPromptCache: Performance-critical caching
12
+ - IHealthMonitor: Service health monitoring
13
+ - IConfigurationManager: Configuration management
14
+ - ITemplateManager: Template processing and rendering
15
+ - IServiceFactory: Service creation patterns
16
+
17
+ These interfaces reduce cyclomatic complexity and establish clean separation of concerns.
18
+ """
19
+
20
+ from abc import ABC, abstractmethod
21
+ from typing import Any, Dict, List, Optional, Set, Tuple, Union, TypeVar, Generic
22
+ from dataclasses import dataclass
23
+ from datetime import datetime
24
+ from pathlib import Path
25
+ import asyncio
26
+
27
+ # Type variables for generic interfaces
28
+ T = TypeVar('T')
29
+ ServiceType = TypeVar('ServiceType')
30
+
31
+
32
+ # Core dependency injection interfaces
33
+ class IServiceContainer(ABC):
34
+ """Service container interface for dependency injection"""
35
+
36
+ @abstractmethod
37
+ def register(self, service_type: type, implementation: type, singleton: bool = True) -> None:
38
+ """Register a service implementation"""
39
+ pass
40
+
41
+ @abstractmethod
42
+ def register_instance(self, service_type: type, instance: Any) -> None:
43
+ """Register a service instance"""
44
+ pass
45
+
46
+ @abstractmethod
47
+ def resolve(self, service_type: type) -> Any:
48
+ """Resolve a service by type"""
49
+ pass
50
+
51
+ @abstractmethod
52
+ def resolve_all(self, service_type: type) -> List[Any]:
53
+ """Resolve all implementations of a service type"""
54
+ pass
55
+
56
+ @abstractmethod
57
+ def is_registered(self, service_type: type) -> bool:
58
+ """Check if a service type is registered"""
59
+ pass
60
+
61
+
62
+ # Configuration management interfaces
63
+ class IConfigurationService(ABC):
64
+ """Interface for configuration service (legacy compatibility)"""
65
+
66
+ @abstractmethod
67
+ def get(self, key: str, default: Any = None) -> Any:
68
+ """Get configuration value by key"""
69
+ pass
70
+
71
+ @abstractmethod
72
+ def set(self, key: str, value: Any) -> None:
73
+ """Set configuration value"""
74
+ pass
75
+
76
+ @abstractmethod
77
+ def initialize(self) -> bool:
78
+ """Initialize configuration service"""
79
+ pass
80
+
81
+ @abstractmethod
82
+ def shutdown(self) -> None:
83
+ """Shutdown configuration service"""
84
+ pass
85
+
86
+ class IConfigurationManager(ABC):
87
+ """Interface for configuration management and validation"""
88
+
89
+ @abstractmethod
90
+ def get(self, key: str, default: Any = None) -> Any:
91
+ """Get configuration value by key"""
92
+ pass
93
+
94
+ @abstractmethod
95
+ def set(self, key: str, value: Any) -> None:
96
+ """Set configuration value"""
97
+ pass
98
+
99
+ @abstractmethod
100
+ def get_section(self, section: str) -> Dict[str, Any]:
101
+ """Get entire configuration section"""
102
+ pass
103
+
104
+ @abstractmethod
105
+ def validate_schema(self, schema: Dict[str, Any]) -> bool:
106
+ """Validate configuration against schema"""
107
+ pass
108
+
109
+ @abstractmethod
110
+ def reload(self) -> None:
111
+ """Reload configuration from sources"""
112
+ pass
113
+
114
+ @abstractmethod
115
+ def watch_changes(self, callback: callable) -> None:
116
+ """Watch for configuration changes"""
117
+ pass
118
+
119
+
120
+ # Cache service interface
121
+ class ICacheService(ABC):
122
+ """Interface for cache service operations"""
123
+
124
+ @abstractmethod
125
+ def get(self, key: str) -> Any:
126
+ """Get value from cache"""
127
+ pass
128
+
129
+ @abstractmethod
130
+ def set(self, key: str, value: Any, ttl: Optional[int] = None) -> None:
131
+ """Set value in cache with optional TTL"""
132
+ pass
133
+
134
+ @abstractmethod
135
+ def delete(self, key: str) -> bool:
136
+ """Delete key from cache"""
137
+ pass
138
+
139
+ @abstractmethod
140
+ def invalidate(self, pattern: str) -> int:
141
+ """Invalidate keys matching pattern"""
142
+ pass
143
+
144
+ @abstractmethod
145
+ def clear(self) -> None:
146
+ """Clear all cache entries"""
147
+ pass
148
+
149
+ @abstractmethod
150
+ def get_cache_metrics(self) -> Dict[str, Any]:
151
+ """Get cache performance metrics"""
152
+ pass
153
+
154
+
155
+ # Health monitoring interface
156
+ @dataclass
157
+ class HealthStatus:
158
+ """Health status data structure"""
159
+ status: str # healthy, degraded, unhealthy, unknown
160
+ message: str
161
+ timestamp: datetime
162
+ checks: Dict[str, bool]
163
+ metrics: Dict[str, Any]
164
+
165
+
166
+ class IHealthMonitor(ABC):
167
+ """Interface for service health monitoring"""
168
+
169
+ @abstractmethod
170
+ async def check_health(self, service_name: str) -> HealthStatus:
171
+ """Check health of a specific service"""
172
+ pass
173
+
174
+ @abstractmethod
175
+ async def get_system_health(self) -> HealthStatus:
176
+ """Get overall system health"""
177
+ pass
178
+
179
+ @abstractmethod
180
+ def register_health_check(self, service_name: str, check_func: callable) -> None:
181
+ """Register a health check function"""
182
+ pass
183
+
184
+ @abstractmethod
185
+ async def start_monitoring(self) -> None:
186
+ """Start health monitoring"""
187
+ pass
188
+
189
+ @abstractmethod
190
+ async def stop_monitoring(self) -> None:
191
+ """Stop health monitoring"""
192
+ pass
193
+
194
+
195
+ # Agent registry interface
196
+ @dataclass
197
+ class AgentMetadata:
198
+ """Enhanced agent metadata with specialization and model configuration support"""
199
+ name: str
200
+ type: str
201
+ path: str
202
+ tier: str
203
+ description: Optional[str] = None
204
+ version: Optional[str] = None
205
+ capabilities: List[str] = None
206
+ specializations: List[str] = None
207
+ frameworks: List[str] = None
208
+ domains: List[str] = None
209
+ roles: List[str] = None
210
+ is_hybrid: bool = False
211
+ validation_score: float = 0.0
212
+ last_modified: Optional[float] = None
213
+ # Model configuration fields
214
+ preferred_model: Optional[str] = None
215
+ model_config: Optional[Dict[str, Any]] = None
216
+
217
+ def __post_init__(self):
218
+ """Initialize default values for list fields"""
219
+ if self.capabilities is None:
220
+ self.capabilities = []
221
+ if self.specializations is None:
222
+ self.specializations = []
223
+ if self.frameworks is None:
224
+ self.frameworks = []
225
+ if self.domains is None:
226
+ self.domains = []
227
+ if self.roles is None:
228
+ self.roles = []
229
+ if self.model_config is None:
230
+ self.model_config = {}
231
+
232
+
233
+ class IAgentRegistry(ABC):
234
+ """Interface for agent discovery and management"""
235
+
236
+ @abstractmethod
237
+ async def discover_agents(self, force_refresh: bool = False) -> Dict[str, AgentMetadata]:
238
+ """Discover all available agents"""
239
+ pass
240
+
241
+ @abstractmethod
242
+ async def get_agent(self, agent_name: str) -> Optional[AgentMetadata]:
243
+ """Get specific agent metadata"""
244
+ pass
245
+
246
+ @abstractmethod
247
+ async def list_agents(self, agent_type: Optional[str] = None, tier: Optional[str] = None) -> List[AgentMetadata]:
248
+ """List agents with optional filtering"""
249
+ pass
250
+
251
+ @abstractmethod
252
+ async def get_specialized_agents(self, agent_type: str) -> List[AgentMetadata]:
253
+ """Get agents of a specific specialized type"""
254
+ pass
255
+
256
+ @abstractmethod
257
+ async def search_by_capability(self, capability: str) -> List[AgentMetadata]:
258
+ """Search agents by capability"""
259
+ pass
260
+
261
+ @abstractmethod
262
+ async def get_registry_stats(self) -> Dict[str, Any]:
263
+ """Get registry statistics"""
264
+ pass
265
+
266
+
267
+ # Prompt cache interface
268
+ @dataclass
269
+ class CacheEntry:
270
+ """Cache entry with metadata"""
271
+ key: str
272
+ value: Any
273
+ created_at: float
274
+ ttl: Optional[float] = None
275
+ access_count: int = 0
276
+ last_accessed: float = 0.0
277
+ size_bytes: int = 0
278
+ metadata: Dict[str, Any] = None
279
+
280
+ def __post_init__(self):
281
+ if self.metadata is None:
282
+ self.metadata = {}
283
+
284
+
285
+ class IPromptCache(ABC):
286
+ """Interface for high-performance prompt caching"""
287
+
288
+ @abstractmethod
289
+ def get(self, key: str) -> Optional[Any]:
290
+ """Get cached value by key"""
291
+ pass
292
+
293
+ @abstractmethod
294
+ def set(self, key: str, value: Any, ttl: Optional[float] = None, metadata: Optional[Dict[str, Any]] = None) -> bool:
295
+ """Set cached value with optional TTL"""
296
+ pass
297
+
298
+ @abstractmethod
299
+ def delete(self, key: str) -> bool:
300
+ """Delete cached value"""
301
+ pass
302
+
303
+ @abstractmethod
304
+ def invalidate(self, pattern: str) -> int:
305
+ """Invalidate cached values matching pattern"""
306
+ pass
307
+
308
+ @abstractmethod
309
+ def clear(self) -> None:
310
+ """Clear all cached values"""
311
+ pass
312
+
313
+ @abstractmethod
314
+ def get_metrics(self) -> Dict[str, Any]:
315
+ """Get cache performance metrics"""
316
+ pass
317
+
318
+
319
+ # Template management interface
320
+ @dataclass
321
+ class TemplateRenderContext:
322
+ """Context for template rendering"""
323
+ variables: Dict[str, Any]
324
+ metadata: Dict[str, Any]
325
+ target_path: Optional[Path] = None
326
+ template_id: Optional[str] = None
327
+
328
+
329
+ class ITemplateManager(ABC):
330
+ """Interface for template processing and rendering"""
331
+
332
+ @abstractmethod
333
+ async def render_template(self, template_content: str, context: TemplateRenderContext) -> str:
334
+ """Render template with given context"""
335
+ pass
336
+
337
+ @abstractmethod
338
+ async def load_template(self, template_id: str) -> Optional[str]:
339
+ """Load template by ID"""
340
+ pass
341
+
342
+ @abstractmethod
343
+ async def validate_template(self, template_content: str) -> Tuple[bool, List[str]]:
344
+ """Validate template syntax and variables"""
345
+ pass
346
+
347
+ @abstractmethod
348
+ def register_template_function(self, name: str, func: callable) -> None:
349
+ """Register custom template function"""
350
+ pass
351
+
352
+
353
+ # Service factory interface
354
+ class IServiceFactory(Generic[ServiceType], ABC):
355
+ """Generic interface for service factories"""
356
+
357
+ @abstractmethod
358
+ def create(self, **kwargs) -> ServiceType:
359
+ """Create service instance"""
360
+ pass
361
+
362
+ @abstractmethod
363
+ def create_with_config(self, config: Dict[str, Any]) -> ServiceType:
364
+ """Create service instance with configuration"""
365
+ pass
366
+
367
+ @abstractmethod
368
+ def supports_type(self, service_type: type) -> bool:
369
+ """Check if factory supports service type"""
370
+ pass
371
+
372
+
373
+ # Logging interface
374
+ class IStructuredLogger(ABC):
375
+ """Interface for structured logging"""
376
+
377
+ @abstractmethod
378
+ def debug(self, message: str, **kwargs) -> None:
379
+ """Log debug message with structured data"""
380
+ pass
381
+
382
+ @abstractmethod
383
+ def info(self, message: str, **kwargs) -> None:
384
+ """Log info message with structured data"""
385
+ pass
386
+
387
+ @abstractmethod
388
+ def warning(self, message: str, **kwargs) -> None:
389
+ """Log warning message with structured data"""
390
+ pass
391
+
392
+ @abstractmethod
393
+ def error(self, message: str, **kwargs) -> None:
394
+ """Log error message with structured data"""
395
+ pass
396
+
397
+ @abstractmethod
398
+ def critical(self, message: str, **kwargs) -> None:
399
+ """Log critical message with structured data"""
400
+ pass
401
+
402
+ @abstractmethod
403
+ def set_context(self, **kwargs) -> None:
404
+ """Set logging context for all subsequent messages"""
405
+ pass
406
+
407
+
408
+ # Service lifecycle interface
409
+ class IServiceLifecycle(ABC):
410
+ """Interface for service lifecycle management"""
411
+
412
+ @abstractmethod
413
+ async def initialize(self) -> None:
414
+ """Initialize the service"""
415
+ pass
416
+
417
+ @abstractmethod
418
+ async def start(self) -> None:
419
+ """Start the service"""
420
+ pass
421
+
422
+ @abstractmethod
423
+ async def stop(self) -> None:
424
+ """Stop the service"""
425
+ pass
426
+
427
+ @abstractmethod
428
+ async def restart(self) -> None:
429
+ """Restart the service"""
430
+ pass
431
+
432
+ @abstractmethod
433
+ def is_running(self) -> bool:
434
+ """Check if service is running"""
435
+ pass
436
+
437
+
438
+ # Error handling interface
439
+ class IErrorHandler(ABC):
440
+ """Interface for centralized error handling"""
441
+
442
+ @abstractmethod
443
+ def handle_error(self, error: Exception, context: Dict[str, Any]) -> None:
444
+ """Handle error with context"""
445
+ pass
446
+
447
+ @abstractmethod
448
+ def register_error_handler(self, error_type: type, handler: callable) -> None:
449
+ """Register error handler for specific error type"""
450
+ pass
451
+
452
+ @abstractmethod
453
+ def get_error_stats(self) -> Dict[str, Any]:
454
+ """Get error statistics"""
455
+ pass
456
+
457
+
458
+ # Performance monitoring interface
459
+ class IPerformanceMonitor(ABC):
460
+ """Interface for performance monitoring"""
461
+
462
+ @abstractmethod
463
+ def start_timer(self, operation: str) -> str:
464
+ """Start timing an operation"""
465
+ pass
466
+
467
+ @abstractmethod
468
+ def stop_timer(self, timer_id: str) -> float:
469
+ """Stop timing and return duration"""
470
+ pass
471
+
472
+ @abstractmethod
473
+ def record_metric(self, name: str, value: float, tags: Optional[Dict[str, str]] = None) -> None:
474
+ """Record a performance metric"""
475
+ pass
476
+
477
+ @abstractmethod
478
+ def get_metrics(self) -> Dict[str, Any]:
479
+ """Get performance metrics"""
480
+ pass
481
+
482
+
483
+ # Event system interface
484
+ class IEventBus(ABC):
485
+ """Interface for event-driven communication"""
486
+
487
+ @abstractmethod
488
+ def publish(self, event_type: str, data: Any) -> None:
489
+ """Publish an event"""
490
+ pass
491
+
492
+ @abstractmethod
493
+ def subscribe(self, event_type: str, handler: callable) -> str:
494
+ """Subscribe to events"""
495
+ pass
496
+
497
+ @abstractmethod
498
+ def unsubscribe(self, subscription_id: str) -> None:
499
+ """Unsubscribe from events"""
500
+ pass
501
+
502
+ @abstractmethod
503
+ async def publish_async(self, event_type: str, data: Any) -> None:
504
+ """Publish an event asynchronously"""
505
+ pass
506
+
507
+
508
+ # Agent deployment interface
509
+ class AgentDeploymentInterface(ABC):
510
+ """Interface for agent deployment operations.
511
+
512
+ WHY: Agent deployment needs to be decoupled from concrete implementations
513
+ to enable different deployment strategies (local, remote, containerized).
514
+ This interface ensures consistency across different deployment backends.
515
+
516
+ DESIGN DECISION: Methods return deployment status/results to enable
517
+ proper error handling and rollback operations when deployments fail.
518
+ """
519
+
520
+ @abstractmethod
521
+ def deploy_agents(self, force: bool = False, include_all: bool = False) -> Dict[str, Any]:
522
+ """Deploy agents to target environment.
523
+
524
+ Args:
525
+ force: Force deployment even if agents already exist
526
+ include_all: Include all agents, ignoring exclusion lists
527
+
528
+ Returns:
529
+ Dictionary with deployment results and status
530
+ """
531
+ pass
532
+
533
+ @abstractmethod
534
+ def validate_agent(self, agent_path: Path) -> Tuple[bool, List[str]]:
535
+ """Validate agent configuration and structure.
536
+
537
+ Args:
538
+ agent_path: Path to agent configuration file
539
+
540
+ Returns:
541
+ Tuple of (is_valid, list_of_errors)
542
+ """
543
+ pass
544
+
545
+ @abstractmethod
546
+ def clean_deployment(self, preserve_user_agents: bool = True) -> bool:
547
+ """Clean up deployed agents.
548
+
549
+ Args:
550
+ preserve_user_agents: Whether to keep user-created agents
551
+
552
+ Returns:
553
+ True if cleanup successful
554
+ """
555
+ pass
556
+
557
+ @abstractmethod
558
+ def get_deployment_status(self) -> Dict[str, Any]:
559
+ """Get current deployment status and metrics.
560
+
561
+ Returns:
562
+ Dictionary with deployment status information
563
+ """
564
+ pass
565
+
566
+
567
+ # Memory service interface
568
+ class MemoryServiceInterface(ABC):
569
+ """Interface for memory management operations.
570
+
571
+ WHY: Memory management is crucial for agent learning and context retention.
572
+ This interface abstracts memory storage, retrieval, and optimization to
573
+ enable different backends (file-based, database, distributed cache).
574
+
575
+ DESIGN DECISION: Memory operations return success/failure status to enable
576
+ proper error handling and fallback strategies when memory is unavailable.
577
+ """
578
+
579
+ @abstractmethod
580
+ def load_memory(self, agent_id: str) -> Optional[str]:
581
+ """Load memory for a specific agent.
582
+
583
+ Args:
584
+ agent_id: Identifier of the agent
585
+
586
+ Returns:
587
+ Memory content as string or None if not found
588
+ """
589
+ pass
590
+
591
+ @abstractmethod
592
+ def save_memory(self, agent_id: str, content: str) -> bool:
593
+ """Save memory for a specific agent.
594
+
595
+ Args:
596
+ agent_id: Identifier of the agent
597
+ content: Memory content to save
598
+
599
+ Returns:
600
+ True if save successful
601
+ """
602
+ pass
603
+
604
+ @abstractmethod
605
+ def validate_memory_size(self, content: str) -> Tuple[bool, Optional[str]]:
606
+ """Validate memory content size and structure.
607
+
608
+ Args:
609
+ content: Memory content to validate
610
+
611
+ Returns:
612
+ Tuple of (is_valid, error_message)
613
+ """
614
+ pass
615
+
616
+ @abstractmethod
617
+ def optimize_memory(self, agent_id: str) -> bool:
618
+ """Optimize memory by removing duplicates and consolidating entries.
619
+
620
+ Args:
621
+ agent_id: Identifier of the agent
622
+
623
+ Returns:
624
+ True if optimization successful
625
+ """
626
+ pass
627
+
628
+ @abstractmethod
629
+ def get_memory_metrics(self, agent_id: Optional[str] = None) -> Dict[str, Any]:
630
+ """Get memory usage metrics.
631
+
632
+ Args:
633
+ agent_id: Optional specific agent ID, or None for all
634
+
635
+ Returns:
636
+ Dictionary with memory metrics
637
+ """
638
+ pass
639
+
640
+
641
+ # Hook service interface
642
+ class HookServiceInterface(ABC):
643
+ """Interface for hook execution operations.
644
+
645
+ WHY: Hooks provide extensibility points for the framework, allowing plugins
646
+ and extensions to modify behavior. This interface ensures consistent hook
647
+ registration, priority handling, and execution across different hook systems.
648
+
649
+ DESIGN DECISION: Separate pre/post delegation methods for clarity and
650
+ performance - no runtime type checking needed during execution.
651
+ """
652
+
653
+ @abstractmethod
654
+ def register_hook(self, hook: Any) -> bool:
655
+ """Register a hook with the service.
656
+
657
+ Args:
658
+ hook: Hook instance to register
659
+
660
+ Returns:
661
+ True if registration successful
662
+ """
663
+ pass
664
+
665
+ @abstractmethod
666
+ def execute_pre_delegation_hooks(self, context: Any) -> Any:
667
+ """Execute all pre-delegation hooks.
668
+
669
+ Args:
670
+ context: Hook execution context
671
+
672
+ Returns:
673
+ Hook execution result
674
+ """
675
+ pass
676
+
677
+ @abstractmethod
678
+ def execute_post_delegation_hooks(self, context: Any) -> Any:
679
+ """Execute all post-delegation hooks.
680
+
681
+ Args:
682
+ context: Hook execution context
683
+
684
+ Returns:
685
+ Hook execution result
686
+ """
687
+ pass
688
+
689
+ @abstractmethod
690
+ def get_registered_hooks(self) -> Dict[str, List[Any]]:
691
+ """Get all registered hooks by type.
692
+
693
+ Returns:
694
+ Dictionary mapping hook types to lists of hooks
695
+ """
696
+ pass
697
+
698
+ @abstractmethod
699
+ def clear_hooks(self, hook_type: Optional[str] = None) -> None:
700
+ """Clear registered hooks.
701
+
702
+ Args:
703
+ hook_type: Optional specific hook type to clear, or None for all
704
+ """
705
+ pass
706
+
707
+
708
+ # WebSocket/SocketIO service interface
709
+ class SocketIOServiceInterface(ABC):
710
+ """Interface for WebSocket communication.
711
+
712
+ WHY: Real-time communication is essential for monitoring and interactive
713
+ features. This interface abstracts WebSocket/SocketIO implementation to
714
+ enable different transport mechanisms and fallback strategies.
715
+
716
+ DESIGN DECISION: Async methods for non-blocking I/O operations, with
717
+ support for both broadcast and targeted messaging.
718
+ """
719
+
720
+ @abstractmethod
721
+ async def start(self, host: str = "localhost", port: int = 8765) -> None:
722
+ """Start the WebSocket server.
723
+
724
+ Args:
725
+ host: Host to bind to
726
+ port: Port to listen on
727
+ """
728
+ pass
729
+
730
+ @abstractmethod
731
+ async def stop(self) -> None:
732
+ """Stop the WebSocket server."""
733
+ pass
734
+
735
+ @abstractmethod
736
+ async def emit(self, event: str, data: Any, room: Optional[str] = None) -> None:
737
+ """Emit an event to connected clients.
738
+
739
+ Args:
740
+ event: Event name
741
+ data: Event data
742
+ room: Optional room to target
743
+ """
744
+ pass
745
+
746
+ @abstractmethod
747
+ async def broadcast(self, event: str, data: Any) -> None:
748
+ """Broadcast event to all connected clients.
749
+
750
+ Args:
751
+ event: Event name
752
+ data: Event data
753
+ """
754
+ pass
755
+
756
+ @abstractmethod
757
+ def get_connection_count(self) -> int:
758
+ """Get number of connected clients.
759
+
760
+ Returns:
761
+ Number of active connections
762
+ """
763
+ pass
764
+
765
+ @abstractmethod
766
+ def is_running(self) -> bool:
767
+ """Check if server is running.
768
+
769
+ Returns:
770
+ True if server is active
771
+ """
772
+ pass
773
+
774
+
775
+ # Project analyzer interface
776
+ class ProjectAnalyzerInterface(ABC):
777
+ """Interface for project analysis operations.
778
+
779
+ WHY: Understanding project structure and characteristics is essential for
780
+ context-aware agent behavior. This interface abstracts project analysis
781
+ to support different project types and structures.
782
+
783
+ DESIGN DECISION: Returns structured data classes for type safety and
784
+ clear contracts between analysis and consumption components.
785
+ """
786
+
787
+ @abstractmethod
788
+ def analyze_project(self, project_path: Optional[Path] = None) -> Any:
789
+ """Analyze project characteristics.
790
+
791
+ Args:
792
+ project_path: Optional path to project, defaults to current
793
+
794
+ Returns:
795
+ ProjectCharacteristics or similar structured data
796
+ """
797
+ pass
798
+
799
+ @abstractmethod
800
+ def detect_technology_stack(self) -> List[str]:
801
+ """Detect technologies used in the project.
802
+
803
+ Returns:
804
+ List of detected technologies
805
+ """
806
+ pass
807
+
808
+ @abstractmethod
809
+ def analyze_code_patterns(self) -> Dict[str, Any]:
810
+ """Analyze code patterns and conventions.
811
+
812
+ Returns:
813
+ Dictionary of pattern analysis results
814
+ """
815
+ pass
816
+
817
+ @abstractmethod
818
+ def get_project_structure(self) -> Dict[str, Any]:
819
+ """Get project directory structure analysis.
820
+
821
+ Returns:
822
+ Dictionary representing project structure
823
+ """
824
+ pass
825
+
826
+ @abstractmethod
827
+ def identify_entry_points(self) -> List[Path]:
828
+ """Identify project entry points.
829
+
830
+ Returns:
831
+ List of entry point paths
832
+ """
833
+ pass
834
+
835
+
836
+ # Ticket manager interface
837
+ class TicketManagerInterface(ABC):
838
+ """Interface for ticket management operations.
839
+
840
+ WHY: Ticket management provides work tracking and organization. This
841
+ interface abstracts ticket operations to support different backend
842
+ systems (file-based, API-based, database).
843
+
844
+ DESIGN DECISION: Uses string IDs for flexibility across different
845
+ ticketing systems, with structured data returns for consistency.
846
+ """
847
+
848
+ @abstractmethod
849
+ def create_task(self, title: str, description: str, **kwargs) -> Optional[str]:
850
+ """Create a new task ticket.
851
+
852
+ Args:
853
+ title: Task title
854
+ description: Task description
855
+ **kwargs: Additional task properties
856
+
857
+ Returns:
858
+ Task ID if created successfully, None otherwise
859
+ """
860
+ pass
861
+
862
+ @abstractmethod
863
+ def update_task(self, task_id: str, **updates) -> bool:
864
+ """Update an existing task.
865
+
866
+ Args:
867
+ task_id: ID of task to update
868
+ **updates: Fields to update
869
+
870
+ Returns:
871
+ True if update successful
872
+ """
873
+ pass
874
+
875
+ @abstractmethod
876
+ def get_task(self, task_id: str) -> Optional[Dict[str, Any]]:
877
+ """Get task details.
878
+
879
+ Args:
880
+ task_id: ID of task to retrieve
881
+
882
+ Returns:
883
+ Task data dictionary or None if not found
884
+ """
885
+ pass
886
+
887
+ @abstractmethod
888
+ def list_tasks(self, status: Optional[str] = None, **filters) -> List[Dict[str, Any]]:
889
+ """List tasks with optional filtering.
890
+
891
+ Args:
892
+ status: Optional status filter
893
+ **filters: Additional filter criteria
894
+
895
+ Returns:
896
+ List of task dictionaries
897
+ """
898
+ pass
899
+
900
+ @abstractmethod
901
+ def close_task(self, task_id: str, resolution: Optional[str] = None) -> bool:
902
+ """Close a task.
903
+
904
+ Args:
905
+ task_id: ID of task to close
906
+ resolution: Optional resolution description
907
+
908
+ Returns:
909
+ True if close successful
910
+ """
911
+ pass
912
+
913
+
914
+ # Interface registry for dependency injection discovery
915
+ class InterfaceRegistry:
916
+ """Registry of all core interfaces for dependency injection"""
917
+
918
+ _interfaces = {
919
+ 'service_container': IServiceContainer,
920
+ 'configuration_manager': IConfigurationManager,
921
+ 'health_monitor': IHealthMonitor,
922
+ 'agent_registry': IAgentRegistry,
923
+ 'prompt_cache': IPromptCache,
924
+ 'template_manager': ITemplateManager,
925
+ 'structured_logger': IStructuredLogger,
926
+ 'service_lifecycle': IServiceLifecycle,
927
+ 'error_handler': IErrorHandler,
928
+ 'performance_monitor': IPerformanceMonitor,
929
+ 'event_bus': IEventBus,
930
+ 'agent_deployment': AgentDeploymentInterface,
931
+ 'memory_service': MemoryServiceInterface,
932
+ 'hook_service': HookServiceInterface,
933
+ 'socketio_service': SocketIOServiceInterface,
934
+ 'project_analyzer': ProjectAnalyzerInterface,
935
+ 'ticket_manager': TicketManagerInterface,
936
+ }
937
+
938
+ @classmethod
939
+ def get_interface(cls, name: str) -> Optional[type]:
940
+ """Get interface by name"""
941
+ return cls._interfaces.get(name)
942
+
943
+ @classmethod
944
+ def get_all_interfaces(cls) -> Dict[str, type]:
945
+ """Get all registered interfaces"""
946
+ return cls._interfaces.copy()
947
+
948
+ @classmethod
949
+ def register_interface(cls, name: str, interface: type) -> None:
950
+ """Register a new interface"""
951
+ cls._interfaces[name] = interface