empathy-framework 3.7.0__py3-none-any.whl → 3.7.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 (267) hide show
  1. coach_wizards/code_reviewer_README.md +60 -0
  2. coach_wizards/code_reviewer_wizard.py +180 -0
  3. {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/METADATA +20 -2
  4. empathy_framework-3.7.1.dist-info/RECORD +327 -0
  5. {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/top_level.txt +5 -1
  6. empathy_healthcare_plugin/monitors/__init__.py +9 -0
  7. empathy_healthcare_plugin/monitors/clinical_protocol_monitor.py +315 -0
  8. empathy_healthcare_plugin/monitors/monitoring/__init__.py +44 -0
  9. empathy_healthcare_plugin/monitors/monitoring/protocol_checker.py +300 -0
  10. empathy_healthcare_plugin/monitors/monitoring/protocol_loader.py +214 -0
  11. empathy_healthcare_plugin/monitors/monitoring/sensor_parsers.py +306 -0
  12. empathy_healthcare_plugin/monitors/monitoring/trajectory_analyzer.py +389 -0
  13. empathy_llm_toolkit/agent_factory/__init__.py +53 -0
  14. empathy_llm_toolkit/agent_factory/adapters/__init__.py +85 -0
  15. empathy_llm_toolkit/agent_factory/adapters/autogen_adapter.py +312 -0
  16. empathy_llm_toolkit/agent_factory/adapters/crewai_adapter.py +454 -0
  17. empathy_llm_toolkit/agent_factory/adapters/haystack_adapter.py +298 -0
  18. empathy_llm_toolkit/agent_factory/adapters/langchain_adapter.py +362 -0
  19. empathy_llm_toolkit/agent_factory/adapters/langgraph_adapter.py +333 -0
  20. empathy_llm_toolkit/agent_factory/adapters/native.py +228 -0
  21. empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +426 -0
  22. empathy_llm_toolkit/agent_factory/base.py +305 -0
  23. empathy_llm_toolkit/agent_factory/crews/__init__.py +67 -0
  24. empathy_llm_toolkit/agent_factory/crews/code_review.py +1113 -0
  25. empathy_llm_toolkit/agent_factory/crews/health_check.py +1246 -0
  26. empathy_llm_toolkit/agent_factory/crews/refactoring.py +1128 -0
  27. empathy_llm_toolkit/agent_factory/crews/security_audit.py +1018 -0
  28. empathy_llm_toolkit/agent_factory/decorators.py +286 -0
  29. empathy_llm_toolkit/agent_factory/factory.py +558 -0
  30. empathy_llm_toolkit/agent_factory/framework.py +192 -0
  31. empathy_llm_toolkit/agent_factory/memory_integration.py +324 -0
  32. empathy_llm_toolkit/agent_factory/resilient.py +320 -0
  33. empathy_llm_toolkit/cli/__init__.py +8 -0
  34. empathy_llm_toolkit/cli/sync_claude.py +487 -0
  35. empathy_llm_toolkit/code_health.py +150 -3
  36. empathy_llm_toolkit/config/__init__.py +29 -0
  37. empathy_llm_toolkit/config/unified.py +295 -0
  38. empathy_llm_toolkit/routing/__init__.py +32 -0
  39. empathy_llm_toolkit/routing/model_router.py +362 -0
  40. empathy_llm_toolkit/security/IMPLEMENTATION_SUMMARY.md +413 -0
  41. empathy_llm_toolkit/security/PHASE2_COMPLETE.md +384 -0
  42. empathy_llm_toolkit/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
  43. empathy_llm_toolkit/security/QUICK_REFERENCE.md +316 -0
  44. empathy_llm_toolkit/security/README.md +262 -0
  45. empathy_llm_toolkit/security/__init__.py +62 -0
  46. empathy_llm_toolkit/security/audit_logger.py +929 -0
  47. empathy_llm_toolkit/security/audit_logger_example.py +152 -0
  48. empathy_llm_toolkit/security/pii_scrubber.py +640 -0
  49. empathy_llm_toolkit/security/secrets_detector.py +678 -0
  50. empathy_llm_toolkit/security/secrets_detector_example.py +304 -0
  51. empathy_llm_toolkit/security/secure_memdocs.py +1192 -0
  52. empathy_llm_toolkit/security/secure_memdocs_example.py +278 -0
  53. empathy_llm_toolkit/wizards/__init__.py +38 -0
  54. empathy_llm_toolkit/wizards/base_wizard.py +364 -0
  55. empathy_llm_toolkit/wizards/customer_support_wizard.py +190 -0
  56. empathy_llm_toolkit/wizards/healthcare_wizard.py +362 -0
  57. empathy_llm_toolkit/wizards/patient_assessment_README.md +64 -0
  58. empathy_llm_toolkit/wizards/patient_assessment_wizard.py +193 -0
  59. empathy_llm_toolkit/wizards/technology_wizard.py +194 -0
  60. empathy_os/__init__.py +52 -52
  61. empathy_os/adaptive/__init__.py +13 -0
  62. empathy_os/adaptive/task_complexity.py +127 -0
  63. empathy_os/cli.py +118 -8
  64. empathy_os/cli_unified.py +121 -1
  65. empathy_os/config/__init__.py +63 -0
  66. empathy_os/config/xml_config.py +239 -0
  67. empathy_os/dashboard/__init__.py +15 -0
  68. empathy_os/dashboard/server.py +743 -0
  69. empathy_os/memory/__init__.py +195 -0
  70. empathy_os/memory/claude_memory.py +466 -0
  71. empathy_os/memory/config.py +224 -0
  72. empathy_os/memory/control_panel.py +1298 -0
  73. empathy_os/memory/edges.py +179 -0
  74. empathy_os/memory/graph.py +567 -0
  75. empathy_os/memory/long_term.py +1193 -0
  76. empathy_os/memory/nodes.py +179 -0
  77. empathy_os/memory/redis_bootstrap.py +540 -0
  78. empathy_os/memory/security/__init__.py +31 -0
  79. empathy_os/memory/security/audit_logger.py +930 -0
  80. empathy_os/memory/security/pii_scrubber.py +640 -0
  81. empathy_os/memory/security/secrets_detector.py +678 -0
  82. empathy_os/memory/short_term.py +2119 -0
  83. empathy_os/memory/storage/__init__.py +15 -0
  84. empathy_os/memory/summary_index.py +583 -0
  85. empathy_os/memory/unified.py +619 -0
  86. empathy_os/metrics/__init__.py +12 -0
  87. empathy_os/metrics/prompt_metrics.py +190 -0
  88. empathy_os/models/__init__.py +136 -0
  89. empathy_os/models/__main__.py +13 -0
  90. empathy_os/models/cli.py +655 -0
  91. empathy_os/models/empathy_executor.py +354 -0
  92. empathy_os/models/executor.py +252 -0
  93. empathy_os/models/fallback.py +671 -0
  94. empathy_os/models/provider_config.py +563 -0
  95. empathy_os/models/registry.py +382 -0
  96. empathy_os/models/tasks.py +302 -0
  97. empathy_os/models/telemetry.py +548 -0
  98. empathy_os/models/token_estimator.py +378 -0
  99. empathy_os/models/validation.py +274 -0
  100. empathy_os/monitoring/__init__.py +52 -0
  101. empathy_os/monitoring/alerts.py +23 -0
  102. empathy_os/monitoring/alerts_cli.py +268 -0
  103. empathy_os/monitoring/multi_backend.py +271 -0
  104. empathy_os/monitoring/otel_backend.py +363 -0
  105. empathy_os/optimization/__init__.py +19 -0
  106. empathy_os/optimization/context_optimizer.py +272 -0
  107. empathy_os/plugins/__init__.py +28 -0
  108. empathy_os/plugins/base.py +361 -0
  109. empathy_os/plugins/registry.py +268 -0
  110. empathy_os/project_index/__init__.py +30 -0
  111. empathy_os/project_index/cli.py +335 -0
  112. empathy_os/project_index/crew_integration.py +430 -0
  113. empathy_os/project_index/index.py +425 -0
  114. empathy_os/project_index/models.py +501 -0
  115. empathy_os/project_index/reports.py +473 -0
  116. empathy_os/project_index/scanner.py +538 -0
  117. empathy_os/prompts/__init__.py +61 -0
  118. empathy_os/prompts/config.py +77 -0
  119. empathy_os/prompts/context.py +177 -0
  120. empathy_os/prompts/parser.py +285 -0
  121. empathy_os/prompts/registry.py +313 -0
  122. empathy_os/prompts/templates.py +208 -0
  123. empathy_os/resilience/__init__.py +56 -0
  124. empathy_os/resilience/circuit_breaker.py +256 -0
  125. empathy_os/resilience/fallback.py +179 -0
  126. empathy_os/resilience/health.py +300 -0
  127. empathy_os/resilience/retry.py +209 -0
  128. empathy_os/resilience/timeout.py +135 -0
  129. empathy_os/routing/__init__.py +43 -0
  130. empathy_os/routing/chain_executor.py +433 -0
  131. empathy_os/routing/classifier.py +217 -0
  132. empathy_os/routing/smart_router.py +234 -0
  133. empathy_os/routing/wizard_registry.py +307 -0
  134. empathy_os/trust/__init__.py +28 -0
  135. empathy_os/trust/circuit_breaker.py +579 -0
  136. empathy_os/validation/__init__.py +19 -0
  137. empathy_os/validation/xml_validator.py +281 -0
  138. empathy_os/wizard_factory_cli.py +170 -0
  139. empathy_os/workflows/__init__.py +360 -0
  140. empathy_os/workflows/base.py +1530 -0
  141. empathy_os/workflows/bug_predict.py +962 -0
  142. empathy_os/workflows/code_review.py +960 -0
  143. empathy_os/workflows/code_review_adapters.py +310 -0
  144. empathy_os/workflows/code_review_pipeline.py +720 -0
  145. empathy_os/workflows/config.py +600 -0
  146. empathy_os/workflows/dependency_check.py +648 -0
  147. empathy_os/workflows/document_gen.py +1069 -0
  148. empathy_os/workflows/documentation_orchestrator.py +1205 -0
  149. empathy_os/workflows/health_check.py +679 -0
  150. empathy_os/workflows/keyboard_shortcuts/__init__.py +39 -0
  151. empathy_os/workflows/keyboard_shortcuts/generators.py +386 -0
  152. empathy_os/workflows/keyboard_shortcuts/parsers.py +414 -0
  153. empathy_os/workflows/keyboard_shortcuts/prompts.py +295 -0
  154. empathy_os/workflows/keyboard_shortcuts/schema.py +193 -0
  155. empathy_os/workflows/keyboard_shortcuts/workflow.py +505 -0
  156. empathy_os/workflows/manage_documentation.py +804 -0
  157. empathy_os/workflows/new_sample_workflow1.py +146 -0
  158. empathy_os/workflows/new_sample_workflow1_README.md +150 -0
  159. empathy_os/workflows/perf_audit.py +687 -0
  160. empathy_os/workflows/pr_review.py +748 -0
  161. empathy_os/workflows/progress.py +445 -0
  162. empathy_os/workflows/progress_server.py +322 -0
  163. empathy_os/workflows/refactor_plan.py +691 -0
  164. empathy_os/workflows/release_prep.py +808 -0
  165. empathy_os/workflows/research_synthesis.py +404 -0
  166. empathy_os/workflows/secure_release.py +585 -0
  167. empathy_os/workflows/security_adapters.py +297 -0
  168. empathy_os/workflows/security_audit.py +1050 -0
  169. empathy_os/workflows/step_config.py +234 -0
  170. empathy_os/workflows/test5.py +125 -0
  171. empathy_os/workflows/test5_README.md +158 -0
  172. empathy_os/workflows/test_gen.py +1855 -0
  173. empathy_os/workflows/test_lifecycle.py +526 -0
  174. empathy_os/workflows/test_maintenance.py +626 -0
  175. empathy_os/workflows/test_maintenance_cli.py +590 -0
  176. empathy_os/workflows/test_maintenance_crew.py +821 -0
  177. empathy_os/workflows/xml_enhanced_crew.py +285 -0
  178. empathy_software_plugin/cli/__init__.py +120 -0
  179. empathy_software_plugin/cli/inspect.py +362 -0
  180. empathy_software_plugin/cli.py +3 -1
  181. empathy_software_plugin/wizards/__init__.py +42 -0
  182. empathy_software_plugin/wizards/advanced_debugging_wizard.py +392 -0
  183. empathy_software_plugin/wizards/agent_orchestration_wizard.py +511 -0
  184. empathy_software_plugin/wizards/ai_collaboration_wizard.py +503 -0
  185. empathy_software_plugin/wizards/ai_context_wizard.py +441 -0
  186. empathy_software_plugin/wizards/ai_documentation_wizard.py +503 -0
  187. empathy_software_plugin/wizards/base_wizard.py +288 -0
  188. empathy_software_plugin/wizards/book_chapter_wizard.py +519 -0
  189. empathy_software_plugin/wizards/code_review_wizard.py +606 -0
  190. empathy_software_plugin/wizards/debugging/__init__.py +50 -0
  191. empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +414 -0
  192. empathy_software_plugin/wizards/debugging/config_loaders.py +442 -0
  193. empathy_software_plugin/wizards/debugging/fix_applier.py +469 -0
  194. empathy_software_plugin/wizards/debugging/language_patterns.py +383 -0
  195. empathy_software_plugin/wizards/debugging/linter_parsers.py +470 -0
  196. empathy_software_plugin/wizards/debugging/verification.py +369 -0
  197. empathy_software_plugin/wizards/enhanced_testing_wizard.py +537 -0
  198. empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +816 -0
  199. empathy_software_plugin/wizards/multi_model_wizard.py +501 -0
  200. empathy_software_plugin/wizards/pattern_extraction_wizard.py +422 -0
  201. empathy_software_plugin/wizards/pattern_retriever_wizard.py +400 -0
  202. empathy_software_plugin/wizards/performance/__init__.py +9 -0
  203. empathy_software_plugin/wizards/performance/bottleneck_detector.py +221 -0
  204. empathy_software_plugin/wizards/performance/profiler_parsers.py +278 -0
  205. empathy_software_plugin/wizards/performance/trajectory_analyzer.py +429 -0
  206. empathy_software_plugin/wizards/performance_profiling_wizard.py +305 -0
  207. empathy_software_plugin/wizards/prompt_engineering_wizard.py +425 -0
  208. empathy_software_plugin/wizards/rag_pattern_wizard.py +461 -0
  209. empathy_software_plugin/wizards/security/__init__.py +32 -0
  210. empathy_software_plugin/wizards/security/exploit_analyzer.py +290 -0
  211. empathy_software_plugin/wizards/security/owasp_patterns.py +241 -0
  212. empathy_software_plugin/wizards/security/vulnerability_scanner.py +604 -0
  213. empathy_software_plugin/wizards/security_analysis_wizard.py +322 -0
  214. empathy_software_plugin/wizards/security_learning_wizard.py +740 -0
  215. empathy_software_plugin/wizards/tech_debt_wizard.py +726 -0
  216. empathy_software_plugin/wizards/testing/__init__.py +27 -0
  217. empathy_software_plugin/wizards/testing/coverage_analyzer.py +459 -0
  218. empathy_software_plugin/wizards/testing/quality_analyzer.py +531 -0
  219. empathy_software_plugin/wizards/testing/test_suggester.py +533 -0
  220. empathy_software_plugin/wizards/testing_wizard.py +274 -0
  221. hot_reload/README.md +473 -0
  222. hot_reload/__init__.py +62 -0
  223. hot_reload/config.py +84 -0
  224. hot_reload/integration.py +228 -0
  225. hot_reload/reloader.py +298 -0
  226. hot_reload/watcher.py +179 -0
  227. hot_reload/websocket.py +176 -0
  228. scaffolding/README.md +589 -0
  229. scaffolding/__init__.py +35 -0
  230. scaffolding/__main__.py +14 -0
  231. scaffolding/cli.py +240 -0
  232. test_generator/__init__.py +38 -0
  233. test_generator/__main__.py +14 -0
  234. test_generator/cli.py +226 -0
  235. test_generator/generator.py +325 -0
  236. test_generator/risk_analyzer.py +216 -0
  237. workflow_patterns/__init__.py +33 -0
  238. workflow_patterns/behavior.py +249 -0
  239. workflow_patterns/core.py +76 -0
  240. workflow_patterns/output.py +99 -0
  241. workflow_patterns/registry.py +255 -0
  242. workflow_patterns/structural.py +288 -0
  243. workflow_scaffolding/__init__.py +11 -0
  244. workflow_scaffolding/__main__.py +12 -0
  245. workflow_scaffolding/cli.py +206 -0
  246. workflow_scaffolding/generator.py +265 -0
  247. agents/code_inspection/patterns/inspection/recurring_B112.json +0 -18
  248. agents/code_inspection/patterns/inspection/recurring_F541.json +0 -16
  249. agents/code_inspection/patterns/inspection/recurring_FORMAT.json +0 -25
  250. agents/code_inspection/patterns/inspection/recurring_bug_20250822_def456.json +0 -16
  251. agents/code_inspection/patterns/inspection/recurring_bug_20250915_abc123.json +0 -16
  252. agents/code_inspection/patterns/inspection/recurring_bug_20251212_3c5b9951.json +0 -16
  253. agents/code_inspection/patterns/inspection/recurring_bug_20251212_97c0f72f.json +0 -16
  254. agents/code_inspection/patterns/inspection/recurring_bug_20251212_a0871d53.json +0 -16
  255. agents/code_inspection/patterns/inspection/recurring_bug_20251212_a9b6ec41.json +0 -16
  256. agents/code_inspection/patterns/inspection/recurring_bug_null_001.json +0 -16
  257. agents/code_inspection/patterns/inspection/recurring_builtin.json +0 -16
  258. agents/compliance_anticipation_agent.py +0 -1422
  259. agents/compliance_db.py +0 -339
  260. agents/epic_integration_wizard.py +0 -530
  261. agents/notifications.py +0 -291
  262. agents/trust_building_behaviors.py +0 -872
  263. empathy_framework-3.7.0.dist-info/RECORD +0 -105
  264. {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/WHEEL +0 -0
  265. {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/entry_points.txt +0 -0
  266. {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/licenses/LICENSE +0 -0
  267. /empathy_os/{monitoring.py → agent_monitoring.py} +0 -0
@@ -0,0 +1,320 @@
1
+ """Resilient Agent Wrapper
2
+
3
+ Applies production-ready resilience patterns (circuit breaker, retry, timeout,
4
+ fallback) to any agent created by the Agent Factory.
5
+
6
+ Usage:
7
+ from empathy_llm_toolkit.agent_factory import AgentFactory
8
+ from empathy_llm_toolkit.agent_factory.resilient import ResilientAgent, ResilienceConfig
9
+
10
+ factory = AgentFactory()
11
+ agent = factory.create_agent(name="researcher", role="researcher")
12
+
13
+ # Wrap with resilience
14
+ resilient_agent = ResilientAgent(agent, ResilienceConfig(
15
+ enable_circuit_breaker=True,
16
+ failure_threshold=3,
17
+ enable_retry=True,
18
+ max_attempts=3
19
+ ))
20
+
21
+ result = await resilient_agent.invoke("Research AI trends")
22
+
23
+ Copyright 2025 Smart-AI-Memory
24
+ Licensed under Fair Source License 0.9
25
+ """
26
+
27
+ import asyncio
28
+ import functools
29
+ import logging
30
+ from dataclasses import dataclass, field
31
+ from typing import Any
32
+
33
+ from empathy_llm_toolkit.agent_factory.base import AgentConfig, BaseAgent
34
+
35
+ logger = logging.getLogger(__name__)
36
+
37
+
38
+ @dataclass
39
+ class ResilienceConfig:
40
+ """Configuration for resilience patterns."""
41
+
42
+ # Circuit Breaker
43
+ enable_circuit_breaker: bool = True
44
+ failure_threshold: int = 3
45
+ reset_timeout: float = 60.0
46
+ half_open_max_calls: int = 3
47
+
48
+ # Retry
49
+ enable_retry: bool = True
50
+ max_attempts: int = 2
51
+ initial_delay: float = 1.0
52
+ backoff_factor: float = 2.0
53
+ max_delay: float = 30.0
54
+ jitter: bool = True
55
+
56
+ # Timeout
57
+ enable_timeout: bool = True
58
+ timeout_seconds: float = 30.0
59
+
60
+ # Fallback
61
+ enable_fallback: bool = False
62
+ fallback_value: Any = field(
63
+ default_factory=lambda: {
64
+ "output": "Service temporarily unavailable",
65
+ "metadata": {"fallback": True},
66
+ },
67
+ )
68
+
69
+ @classmethod
70
+ def from_agent_config(cls, config: AgentConfig) -> "ResilienceConfig":
71
+ """Create ResilienceConfig from AgentConfig resilience fields."""
72
+ return cls(
73
+ enable_circuit_breaker=getattr(config, "resilience_enabled", False),
74
+ failure_threshold=getattr(config, "circuit_breaker_threshold", 3),
75
+ enable_retry=getattr(config, "resilience_enabled", False),
76
+ max_attempts=getattr(config, "retry_max_attempts", 2),
77
+ enable_timeout=getattr(config, "resilience_enabled", False),
78
+ timeout_seconds=getattr(config, "timeout_seconds", 30.0),
79
+ )
80
+
81
+
82
+ class ResilientAgent(BaseAgent):
83
+ """Agent wrapper that applies resilience patterns.
84
+
85
+ Wraps any BaseAgent implementation with:
86
+ - Circuit breaker: Prevents cascading failures
87
+ - Retry with backoff: Handles transient errors
88
+ - Timeout: Prevents hanging operations
89
+ - Fallback: Graceful degradation
90
+
91
+ The wrapper preserves the underlying agent's interface while adding
92
+ fault tolerance capabilities.
93
+ """
94
+
95
+ def __init__(self, agent: BaseAgent, config: ResilienceConfig | None = None):
96
+ """Initialize resilient agent wrapper.
97
+
98
+ Args:
99
+ agent: The underlying agent to wrap
100
+ config: Resilience configuration (uses defaults if not provided)
101
+
102
+ """
103
+ # Initialize with wrapped agent's config
104
+ super().__init__(agent.config)
105
+ self._wrapped = agent
106
+ self._resilience_config = config or ResilienceConfig()
107
+ self._circuit_breaker: Any = None
108
+ self._setup_resilience()
109
+
110
+ def _setup_resilience(self) -> None:
111
+ """Set up resilience decorators based on config."""
112
+ config = self._resilience_config
113
+
114
+ # Set up circuit breaker if enabled
115
+ if config.enable_circuit_breaker:
116
+ try:
117
+ from empathy_os.resilience import CircuitBreaker
118
+
119
+ self._circuit_breaker = CircuitBreaker(
120
+ name=f"agent_{self.name}",
121
+ failure_threshold=config.failure_threshold,
122
+ reset_timeout=config.reset_timeout,
123
+ half_open_max_calls=config.half_open_max_calls,
124
+ )
125
+ except ImportError:
126
+ logger.warning("empathy_os.resilience not available, circuit breaker disabled")
127
+
128
+ async def invoke(self, input_data: str | dict, context: dict | None = None) -> dict:
129
+ """Invoke the agent with resilience patterns applied.
130
+
131
+ Args:
132
+ input_data: User input or structured data
133
+ context: Optional context (previous results, shared state)
134
+
135
+ Returns:
136
+ Dict with at least {"output": str, "metadata": dict}
137
+
138
+ Raises:
139
+ CircuitOpenError: If circuit breaker is open
140
+ asyncio.TimeoutError: If operation times out and no fallback
141
+ Exception: If all retries exhausted and no fallback
142
+
143
+ """
144
+ config = self._resilience_config
145
+
146
+ # Build the resilient call chain
147
+ async def _call():
148
+ return await self._wrapped.invoke(input_data, context)
149
+
150
+ # Apply timeout
151
+ if config.enable_timeout:
152
+ _call = self._with_timeout(_call, config.timeout_seconds)
153
+
154
+ # Apply retry
155
+ if config.enable_retry:
156
+ _call = self._with_retry(
157
+ _call,
158
+ config.max_attempts,
159
+ config.initial_delay,
160
+ config.backoff_factor,
161
+ config.max_delay,
162
+ config.jitter,
163
+ )
164
+
165
+ # Apply circuit breaker
166
+ if config.enable_circuit_breaker and self._circuit_breaker:
167
+ _call = self._with_circuit_breaker(_call)
168
+
169
+ # Execute with optional fallback
170
+ try:
171
+ result = await _call()
172
+ # Add resilience metadata
173
+ if "metadata" in result:
174
+ result["metadata"]["resilience"] = {
175
+ "circuit_breaker_enabled": config.enable_circuit_breaker,
176
+ "retry_enabled": config.enable_retry,
177
+ "timeout_enabled": config.enable_timeout,
178
+ }
179
+ return dict(result)
180
+ except Exception as e:
181
+ if config.enable_fallback:
182
+ logger.warning(f"Agent {self.name} failed, using fallback: {e}")
183
+ fallback = config.fallback_value
184
+ if callable(fallback):
185
+ return dict(fallback(input_data, context, e))
186
+ return dict(fallback) if isinstance(fallback, dict) else {"output": fallback}
187
+ raise
188
+
189
+ async def stream(self, input_data: str | dict, context: dict | None = None):
190
+ """Stream agent response with resilience patterns.
191
+
192
+ Note: Streaming has limited resilience support (timeout only).
193
+ Circuit breaker and retry work at the full response level.
194
+ """
195
+ config = self._resilience_config
196
+
197
+ async def _stream():
198
+ async for chunk in self._wrapped.stream(input_data, context):
199
+ yield chunk
200
+
201
+ # Apply timeout to entire stream
202
+ if config.enable_timeout:
203
+ try:
204
+ async with asyncio.timeout(config.timeout_seconds): # type: ignore[attr-defined]
205
+ async for chunk in _stream():
206
+ yield chunk
207
+ except asyncio.TimeoutError:
208
+ if config.enable_fallback:
209
+ yield {"output": "Stream timed out", "metadata": {"fallback": True}}
210
+ else:
211
+ raise
212
+ else:
213
+ async for chunk in _stream():
214
+ yield chunk
215
+
216
+ def _with_timeout(self, func, timeout_seconds: float):
217
+ """Wrap function with timeout."""
218
+
219
+ @functools.wraps(func)
220
+ async def wrapper():
221
+ return await asyncio.wait_for(func(), timeout=timeout_seconds)
222
+
223
+ return wrapper
224
+
225
+ def _with_retry(
226
+ self,
227
+ func,
228
+ max_attempts: int,
229
+ initial_delay: float,
230
+ backoff_factor: float,
231
+ max_delay: float,
232
+ jitter: bool,
233
+ ):
234
+ """Wrap function with retry logic."""
235
+ import random
236
+
237
+ @functools.wraps(func)
238
+ async def wrapper():
239
+ last_exception = None
240
+ delay = initial_delay
241
+
242
+ for attempt in range(max_attempts):
243
+ try:
244
+ return await func()
245
+ except asyncio.TimeoutError:
246
+ # Don't retry timeouts by default
247
+ raise
248
+ except Exception as e:
249
+ last_exception = e
250
+ if attempt < max_attempts - 1:
251
+ actual_delay = delay
252
+ if jitter:
253
+ actual_delay = delay * (0.5 + random.random())
254
+ actual_delay = min(actual_delay, max_delay)
255
+ logger.debug(
256
+ f"Agent {self.name} attempt {attempt + 1} failed, "
257
+ f"retrying in {actual_delay:.2f}s: {e}",
258
+ )
259
+ await asyncio.sleep(actual_delay)
260
+ delay = min(delay * backoff_factor, max_delay)
261
+
262
+ raise last_exception
263
+
264
+ return wrapper
265
+
266
+ def _with_circuit_breaker(self, func):
267
+ """Wrap function with circuit breaker."""
268
+
269
+ @functools.wraps(func)
270
+ async def wrapper():
271
+ from empathy_os.resilience import CircuitOpenError
272
+
273
+ # Check if circuit is open (failing fast)
274
+ if self._circuit_breaker.is_open:
275
+ reset_time = self._circuit_breaker.get_time_until_reset()
276
+ raise CircuitOpenError(
277
+ name=f"agent_{self.name}",
278
+ reset_time=reset_time,
279
+ )
280
+
281
+ try:
282
+ result = await func()
283
+ self._circuit_breaker.record_success()
284
+ return result
285
+ except Exception as e:
286
+ self._circuit_breaker.record_failure(e)
287
+ raise
288
+
289
+ return wrapper
290
+
291
+ # Delegate other methods to wrapped agent
292
+ def add_tool(self, tool: Any) -> None:
293
+ """Add a tool to the wrapped agent."""
294
+ self._wrapped.add_tool(tool)
295
+
296
+ def get_conversation_history(self) -> list[dict]:
297
+ """Get conversation history from wrapped agent."""
298
+ return self._wrapped.get_conversation_history()
299
+
300
+ def clear_history(self) -> None:
301
+ """Clear conversation history in wrapped agent."""
302
+ self._wrapped.clear_history()
303
+
304
+ @property
305
+ def model(self) -> str:
306
+ """Get the model being used by wrapped agent."""
307
+ return self._wrapped.model
308
+
309
+ @property
310
+ def circuit_state(self) -> str | None:
311
+ """Get current circuit breaker state."""
312
+ if self._circuit_breaker:
313
+ return str(self._circuit_breaker.state.value)
314
+ return None
315
+
316
+ def reset_circuit_breaker(self) -> None:
317
+ """Manually reset the circuit breaker."""
318
+ if self._circuit_breaker:
319
+ self._circuit_breaker.reset()
320
+ logger.info(f"Circuit breaker reset for agent {self.name}")
@@ -0,0 +1,8 @@
1
+ """Empathy Framework CLI Tools
2
+
3
+ Commands:
4
+ - empathy sync-claude: Sync patterns to .claude/rules/empathy/
5
+
6
+ Copyright 2025 Smart AI Memory, LLC
7
+ Licensed under Fair Source 0.9
8
+ """