empathy-framework 3.7.0__py3-none-any.whl → 3.8.0__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 (274) 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.8.0.dist-info}/METADATA +148 -11
  4. empathy_framework-3.8.0.dist-info/RECORD +333 -0
  5. {empathy_framework-3.7.0.dist-info → empathy_framework-3.8.0.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/cache/__init__.py +117 -0
  64. empathy_os/cache/base.py +166 -0
  65. empathy_os/cache/dependency_manager.py +253 -0
  66. empathy_os/cache/hash_only.py +248 -0
  67. empathy_os/cache/hybrid.py +390 -0
  68. empathy_os/cache/storage.py +282 -0
  69. empathy_os/cli.py +118 -8
  70. empathy_os/cli_unified.py +121 -1
  71. empathy_os/config/__init__.py +63 -0
  72. empathy_os/config/xml_config.py +239 -0
  73. empathy_os/config.py +2 -1
  74. empathy_os/dashboard/__init__.py +15 -0
  75. empathy_os/dashboard/server.py +743 -0
  76. empathy_os/memory/__init__.py +195 -0
  77. empathy_os/memory/claude_memory.py +466 -0
  78. empathy_os/memory/config.py +224 -0
  79. empathy_os/memory/control_panel.py +1298 -0
  80. empathy_os/memory/edges.py +179 -0
  81. empathy_os/memory/graph.py +567 -0
  82. empathy_os/memory/long_term.py +1194 -0
  83. empathy_os/memory/nodes.py +179 -0
  84. empathy_os/memory/redis_bootstrap.py +540 -0
  85. empathy_os/memory/security/__init__.py +31 -0
  86. empathy_os/memory/security/audit_logger.py +930 -0
  87. empathy_os/memory/security/pii_scrubber.py +640 -0
  88. empathy_os/memory/security/secrets_detector.py +678 -0
  89. empathy_os/memory/short_term.py +2119 -0
  90. empathy_os/memory/storage/__init__.py +15 -0
  91. empathy_os/memory/summary_index.py +583 -0
  92. empathy_os/memory/unified.py +619 -0
  93. empathy_os/metrics/__init__.py +12 -0
  94. empathy_os/metrics/prompt_metrics.py +190 -0
  95. empathy_os/models/__init__.py +136 -0
  96. empathy_os/models/__main__.py +13 -0
  97. empathy_os/models/cli.py +655 -0
  98. empathy_os/models/empathy_executor.py +354 -0
  99. empathy_os/models/executor.py +252 -0
  100. empathy_os/models/fallback.py +671 -0
  101. empathy_os/models/provider_config.py +563 -0
  102. empathy_os/models/registry.py +382 -0
  103. empathy_os/models/tasks.py +302 -0
  104. empathy_os/models/telemetry.py +548 -0
  105. empathy_os/models/token_estimator.py +378 -0
  106. empathy_os/models/validation.py +274 -0
  107. empathy_os/monitoring/__init__.py +52 -0
  108. empathy_os/monitoring/alerts.py +23 -0
  109. empathy_os/monitoring/alerts_cli.py +268 -0
  110. empathy_os/monitoring/multi_backend.py +271 -0
  111. empathy_os/monitoring/otel_backend.py +363 -0
  112. empathy_os/optimization/__init__.py +19 -0
  113. empathy_os/optimization/context_optimizer.py +272 -0
  114. empathy_os/plugins/__init__.py +28 -0
  115. empathy_os/plugins/base.py +361 -0
  116. empathy_os/plugins/registry.py +268 -0
  117. empathy_os/project_index/__init__.py +30 -0
  118. empathy_os/project_index/cli.py +335 -0
  119. empathy_os/project_index/crew_integration.py +430 -0
  120. empathy_os/project_index/index.py +425 -0
  121. empathy_os/project_index/models.py +501 -0
  122. empathy_os/project_index/reports.py +473 -0
  123. empathy_os/project_index/scanner.py +538 -0
  124. empathy_os/prompts/__init__.py +61 -0
  125. empathy_os/prompts/config.py +77 -0
  126. empathy_os/prompts/context.py +177 -0
  127. empathy_os/prompts/parser.py +285 -0
  128. empathy_os/prompts/registry.py +313 -0
  129. empathy_os/prompts/templates.py +208 -0
  130. empathy_os/resilience/__init__.py +56 -0
  131. empathy_os/resilience/circuit_breaker.py +256 -0
  132. empathy_os/resilience/fallback.py +179 -0
  133. empathy_os/resilience/health.py +300 -0
  134. empathy_os/resilience/retry.py +209 -0
  135. empathy_os/resilience/timeout.py +135 -0
  136. empathy_os/routing/__init__.py +43 -0
  137. empathy_os/routing/chain_executor.py +433 -0
  138. empathy_os/routing/classifier.py +217 -0
  139. empathy_os/routing/smart_router.py +234 -0
  140. empathy_os/routing/wizard_registry.py +307 -0
  141. empathy_os/trust/__init__.py +28 -0
  142. empathy_os/trust/circuit_breaker.py +579 -0
  143. empathy_os/validation/__init__.py +19 -0
  144. empathy_os/validation/xml_validator.py +281 -0
  145. empathy_os/wizard_factory_cli.py +170 -0
  146. empathy_os/workflows/__init__.py +360 -0
  147. empathy_os/workflows/base.py +1660 -0
  148. empathy_os/workflows/bug_predict.py +962 -0
  149. empathy_os/workflows/code_review.py +960 -0
  150. empathy_os/workflows/code_review_adapters.py +310 -0
  151. empathy_os/workflows/code_review_pipeline.py +720 -0
  152. empathy_os/workflows/config.py +600 -0
  153. empathy_os/workflows/dependency_check.py +648 -0
  154. empathy_os/workflows/document_gen.py +1069 -0
  155. empathy_os/workflows/documentation_orchestrator.py +1205 -0
  156. empathy_os/workflows/health_check.py +679 -0
  157. empathy_os/workflows/keyboard_shortcuts/__init__.py +39 -0
  158. empathy_os/workflows/keyboard_shortcuts/generators.py +386 -0
  159. empathy_os/workflows/keyboard_shortcuts/parsers.py +414 -0
  160. empathy_os/workflows/keyboard_shortcuts/prompts.py +295 -0
  161. empathy_os/workflows/keyboard_shortcuts/schema.py +193 -0
  162. empathy_os/workflows/keyboard_shortcuts/workflow.py +505 -0
  163. empathy_os/workflows/manage_documentation.py +804 -0
  164. empathy_os/workflows/new_sample_workflow1.py +146 -0
  165. empathy_os/workflows/new_sample_workflow1_README.md +150 -0
  166. empathy_os/workflows/perf_audit.py +687 -0
  167. empathy_os/workflows/pr_review.py +748 -0
  168. empathy_os/workflows/progress.py +445 -0
  169. empathy_os/workflows/progress_server.py +322 -0
  170. empathy_os/workflows/refactor_plan.py +693 -0
  171. empathy_os/workflows/release_prep.py +808 -0
  172. empathy_os/workflows/research_synthesis.py +404 -0
  173. empathy_os/workflows/secure_release.py +585 -0
  174. empathy_os/workflows/security_adapters.py +297 -0
  175. empathy_os/workflows/security_audit.py +1046 -0
  176. empathy_os/workflows/step_config.py +234 -0
  177. empathy_os/workflows/test5.py +125 -0
  178. empathy_os/workflows/test5_README.md +158 -0
  179. empathy_os/workflows/test_gen.py +1855 -0
  180. empathy_os/workflows/test_lifecycle.py +526 -0
  181. empathy_os/workflows/test_maintenance.py +626 -0
  182. empathy_os/workflows/test_maintenance_cli.py +590 -0
  183. empathy_os/workflows/test_maintenance_crew.py +821 -0
  184. empathy_os/workflows/xml_enhanced_crew.py +285 -0
  185. empathy_software_plugin/cli/__init__.py +120 -0
  186. empathy_software_plugin/cli/inspect.py +362 -0
  187. empathy_software_plugin/cli.py +3 -1
  188. empathy_software_plugin/wizards/__init__.py +42 -0
  189. empathy_software_plugin/wizards/advanced_debugging_wizard.py +392 -0
  190. empathy_software_plugin/wizards/agent_orchestration_wizard.py +511 -0
  191. empathy_software_plugin/wizards/ai_collaboration_wizard.py +503 -0
  192. empathy_software_plugin/wizards/ai_context_wizard.py +441 -0
  193. empathy_software_plugin/wizards/ai_documentation_wizard.py +503 -0
  194. empathy_software_plugin/wizards/base_wizard.py +288 -0
  195. empathy_software_plugin/wizards/book_chapter_wizard.py +519 -0
  196. empathy_software_plugin/wizards/code_review_wizard.py +606 -0
  197. empathy_software_plugin/wizards/debugging/__init__.py +50 -0
  198. empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +414 -0
  199. empathy_software_plugin/wizards/debugging/config_loaders.py +442 -0
  200. empathy_software_plugin/wizards/debugging/fix_applier.py +469 -0
  201. empathy_software_plugin/wizards/debugging/language_patterns.py +383 -0
  202. empathy_software_plugin/wizards/debugging/linter_parsers.py +470 -0
  203. empathy_software_plugin/wizards/debugging/verification.py +369 -0
  204. empathy_software_plugin/wizards/enhanced_testing_wizard.py +537 -0
  205. empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +816 -0
  206. empathy_software_plugin/wizards/multi_model_wizard.py +501 -0
  207. empathy_software_plugin/wizards/pattern_extraction_wizard.py +422 -0
  208. empathy_software_plugin/wizards/pattern_retriever_wizard.py +400 -0
  209. empathy_software_plugin/wizards/performance/__init__.py +9 -0
  210. empathy_software_plugin/wizards/performance/bottleneck_detector.py +221 -0
  211. empathy_software_plugin/wizards/performance/profiler_parsers.py +278 -0
  212. empathy_software_plugin/wizards/performance/trajectory_analyzer.py +429 -0
  213. empathy_software_plugin/wizards/performance_profiling_wizard.py +305 -0
  214. empathy_software_plugin/wizards/prompt_engineering_wizard.py +425 -0
  215. empathy_software_plugin/wizards/rag_pattern_wizard.py +461 -0
  216. empathy_software_plugin/wizards/security/__init__.py +32 -0
  217. empathy_software_plugin/wizards/security/exploit_analyzer.py +290 -0
  218. empathy_software_plugin/wizards/security/owasp_patterns.py +241 -0
  219. empathy_software_plugin/wizards/security/vulnerability_scanner.py +604 -0
  220. empathy_software_plugin/wizards/security_analysis_wizard.py +322 -0
  221. empathy_software_plugin/wizards/security_learning_wizard.py +740 -0
  222. empathy_software_plugin/wizards/tech_debt_wizard.py +726 -0
  223. empathy_software_plugin/wizards/testing/__init__.py +27 -0
  224. empathy_software_plugin/wizards/testing/coverage_analyzer.py +459 -0
  225. empathy_software_plugin/wizards/testing/quality_analyzer.py +531 -0
  226. empathy_software_plugin/wizards/testing/test_suggester.py +533 -0
  227. empathy_software_plugin/wizards/testing_wizard.py +274 -0
  228. hot_reload/README.md +473 -0
  229. hot_reload/__init__.py +62 -0
  230. hot_reload/config.py +84 -0
  231. hot_reload/integration.py +228 -0
  232. hot_reload/reloader.py +298 -0
  233. hot_reload/watcher.py +179 -0
  234. hot_reload/websocket.py +176 -0
  235. scaffolding/README.md +589 -0
  236. scaffolding/__init__.py +35 -0
  237. scaffolding/__main__.py +14 -0
  238. scaffolding/cli.py +240 -0
  239. test_generator/__init__.py +38 -0
  240. test_generator/__main__.py +14 -0
  241. test_generator/cli.py +226 -0
  242. test_generator/generator.py +325 -0
  243. test_generator/risk_analyzer.py +216 -0
  244. workflow_patterns/__init__.py +33 -0
  245. workflow_patterns/behavior.py +249 -0
  246. workflow_patterns/core.py +76 -0
  247. workflow_patterns/output.py +99 -0
  248. workflow_patterns/registry.py +255 -0
  249. workflow_patterns/structural.py +288 -0
  250. workflow_scaffolding/__init__.py +11 -0
  251. workflow_scaffolding/__main__.py +12 -0
  252. workflow_scaffolding/cli.py +206 -0
  253. workflow_scaffolding/generator.py +265 -0
  254. agents/code_inspection/patterns/inspection/recurring_B112.json +0 -18
  255. agents/code_inspection/patterns/inspection/recurring_F541.json +0 -16
  256. agents/code_inspection/patterns/inspection/recurring_FORMAT.json +0 -25
  257. agents/code_inspection/patterns/inspection/recurring_bug_20250822_def456.json +0 -16
  258. agents/code_inspection/patterns/inspection/recurring_bug_20250915_abc123.json +0 -16
  259. agents/code_inspection/patterns/inspection/recurring_bug_20251212_3c5b9951.json +0 -16
  260. agents/code_inspection/patterns/inspection/recurring_bug_20251212_97c0f72f.json +0 -16
  261. agents/code_inspection/patterns/inspection/recurring_bug_20251212_a0871d53.json +0 -16
  262. agents/code_inspection/patterns/inspection/recurring_bug_20251212_a9b6ec41.json +0 -16
  263. agents/code_inspection/patterns/inspection/recurring_bug_null_001.json +0 -16
  264. agents/code_inspection/patterns/inspection/recurring_builtin.json +0 -16
  265. agents/compliance_anticipation_agent.py +0 -1422
  266. agents/compliance_db.py +0 -339
  267. agents/epic_integration_wizard.py +0 -530
  268. agents/notifications.py +0 -291
  269. agents/trust_building_behaviors.py +0 -872
  270. empathy_framework-3.7.0.dist-info/RECORD +0 -105
  271. {empathy_framework-3.7.0.dist-info → empathy_framework-3.8.0.dist-info}/WHEEL +0 -0
  272. {empathy_framework-3.7.0.dist-info → empathy_framework-3.8.0.dist-info}/entry_points.txt +0 -0
  273. {empathy_framework-3.7.0.dist-info → empathy_framework-3.8.0.dist-info}/licenses/LICENSE +0 -0
  274. /empathy_os/{monitoring.py → agent_monitoring.py} +0 -0
@@ -9,6 +9,7 @@ Licensed under Fair Source 0.9
9
9
 
10
10
  import asyncio
11
11
  import json
12
+ import logging
12
13
  import shutil
13
14
  import subprocess
14
15
  from dataclasses import dataclass, field
@@ -17,6 +18,8 @@ from enum import Enum
17
18
  from pathlib import Path
18
19
  from typing import Any
19
20
 
21
+ logger = logging.getLogger(__name__)
22
+
20
23
 
21
24
  class HealthStatus(Enum):
22
25
  """Health check result status."""
@@ -311,13 +314,23 @@ class HealthCheckRunner:
311
314
  handler,
312
315
  config: dict,
313
316
  ) -> CheckResult:
314
- """Run a check handler asynchronously."""
317
+ """Run a check handler asynchronously.
318
+
319
+ This uses broad exception handling intentionally for graceful degradation.
320
+ Health checks are optional features - the system should continue even if some checks fail.
321
+
322
+ Note:
323
+ Full exception context is preserved via logger.exception() for debugging.
324
+ """
315
325
  start_time = datetime.now()
316
326
  try:
317
327
  result: CheckResult = await asyncio.to_thread(handler, config)
318
328
  result.duration_ms = int((datetime.now() - start_time).total_seconds() * 1000)
319
329
  return result
320
330
  except Exception as e:
331
+ # INTENTIONAL: Broad exception handler for graceful degradation of optional checks
332
+ # Full traceback preserved for debugging
333
+ logger.exception(f"Health check failed for {category.value}: {e}")
321
334
  return CheckResult(
322
335
  category=category,
323
336
  status=HealthStatus.ERROR,
@@ -390,7 +403,30 @@ class HealthCheckRunner:
390
403
  details={"total_files_checked": len({i.file_path for i in issues}) or "all"},
391
404
  )
392
405
 
406
+ except json.JSONDecodeError as e:
407
+ # Tool output not in expected JSON format
408
+ logger.warning(f"Lint check JSON parse error ({tool}): {e}")
409
+ return CheckResult(
410
+ category=CheckCategory.LINT,
411
+ status=HealthStatus.ERROR,
412
+ score=0,
413
+ tool_used=tool,
414
+ details={"error": f"Failed to parse {tool} output: {e}"},
415
+ )
416
+ except subprocess.SubprocessError as e:
417
+ # Tool execution failed
418
+ logger.error(f"Lint check subprocess error ({tool}): {e}")
419
+ return CheckResult(
420
+ category=CheckCategory.LINT,
421
+ status=HealthStatus.ERROR,
422
+ score=0,
423
+ tool_used=tool,
424
+ details={"error": f"Failed to run {tool}: {e}"},
425
+ )
393
426
  except Exception as e:
427
+ # Unexpected errors - preserve full context for debugging
428
+ # INTENTIONAL: Broad handler for graceful degradation of optional check
429
+ logger.exception(f"Unexpected error in lint check ({tool}): {e}")
394
430
  return CheckResult(
395
431
  category=CheckCategory.LINT,
396
432
  status=HealthStatus.ERROR,
@@ -475,7 +511,20 @@ class HealthCheckRunner:
475
511
  details={"files_need_formatting": len(issues)},
476
512
  )
477
513
 
514
+ except subprocess.SubprocessError as e:
515
+ # Tool execution failed
516
+ logger.error(f"Format check subprocess error ({tool}): {e}")
517
+ return CheckResult(
518
+ category=CheckCategory.FORMAT,
519
+ status=HealthStatus.ERROR,
520
+ score=0,
521
+ tool_used=tool,
522
+ details={"error": f"Failed to run {tool}: {e}"},
523
+ )
478
524
  except Exception as e:
525
+ # Unexpected errors - preserve full context for debugging
526
+ # INTENTIONAL: Broad handler for graceful degradation of optional check
527
+ logger.exception(f"Unexpected error in format check ({tool}): {e}")
479
528
  return CheckResult(
480
529
  category=CheckCategory.FORMAT,
481
530
  status=HealthStatus.ERROR,
@@ -569,7 +618,30 @@ class HealthCheckRunner:
569
618
  details={"type_errors": len(issues)},
570
619
  )
571
620
 
621
+ except json.JSONDecodeError as e:
622
+ # Tool output not in expected JSON format (pyright specific)
623
+ logger.warning(f"Type check JSON parse error ({tool}): {e}")
624
+ return CheckResult(
625
+ category=CheckCategory.TYPES,
626
+ status=HealthStatus.ERROR,
627
+ score=0,
628
+ tool_used=tool,
629
+ details={"error": f"Failed to parse {tool} output: {e}"},
630
+ )
631
+ except subprocess.SubprocessError as e:
632
+ # Tool execution failed
633
+ logger.error(f"Type check subprocess error ({tool}): {e}")
634
+ return CheckResult(
635
+ category=CheckCategory.TYPES,
636
+ status=HealthStatus.ERROR,
637
+ score=0,
638
+ tool_used=tool,
639
+ details={"error": f"Failed to run {tool}: {e}"},
640
+ )
572
641
  except Exception as e:
642
+ # Unexpected errors - preserve full context for debugging
643
+ # INTENTIONAL: Broad handler for graceful degradation of optional check
644
+ logger.exception(f"Unexpected error in type check ({tool}): {e}")
573
645
  return CheckResult(
574
646
  category=CheckCategory.TYPES,
575
647
  status=HealthStatus.ERROR,
@@ -681,6 +753,8 @@ class HealthCheckRunner:
681
753
  )
682
754
 
683
755
  except subprocess.TimeoutExpired:
756
+ # Tests took too long - specific timeout error
757
+ logger.error(f"Test check timeout ({tool}): Tests took longer than 5 minutes")
684
758
  return CheckResult(
685
759
  category=CheckCategory.TESTS,
686
760
  status=HealthStatus.ERROR,
@@ -688,7 +762,20 @@ class HealthCheckRunner:
688
762
  tool_used=tool,
689
763
  details={"error": "Test suite timed out after 5 minutes"},
690
764
  )
765
+ except subprocess.SubprocessError as e:
766
+ # Tool execution failed
767
+ logger.error(f"Test check subprocess error ({tool}): {e}")
768
+ return CheckResult(
769
+ category=CheckCategory.TESTS,
770
+ status=HealthStatus.ERROR,
771
+ score=0,
772
+ tool_used=tool,
773
+ details={"error": f"Failed to run {tool}: {e}"},
774
+ )
691
775
  except Exception as e:
776
+ # Unexpected errors - preserve full context for debugging
777
+ # INTENTIONAL: Broad handler for graceful degradation of optional check
778
+ logger.exception(f"Unexpected error in test check ({tool}): {e}")
692
779
  return CheckResult(
693
780
  category=CheckCategory.TESTS,
694
781
  status=HealthStatus.ERROR,
@@ -761,7 +848,30 @@ class HealthCheckRunner:
761
848
  },
762
849
  )
763
850
 
851
+ except json.JSONDecodeError as e:
852
+ # Tool output not in expected JSON format
853
+ logger.warning(f"Security check JSON parse error ({tool}): {e}")
854
+ return CheckResult(
855
+ category=CheckCategory.SECURITY,
856
+ status=HealthStatus.ERROR,
857
+ score=0,
858
+ tool_used=tool,
859
+ details={"error": f"Failed to parse {tool} output: {e}"},
860
+ )
861
+ except subprocess.SubprocessError as e:
862
+ # Tool execution failed
863
+ logger.error(f"Security check subprocess error ({tool}): {e}")
864
+ return CheckResult(
865
+ category=CheckCategory.SECURITY,
866
+ status=HealthStatus.ERROR,
867
+ score=0,
868
+ tool_used=tool,
869
+ details={"error": f"Failed to run {tool}: {e}"},
870
+ )
764
871
  except Exception as e:
872
+ # Unexpected errors - preserve full context for debugging
873
+ # INTENTIONAL: Broad handler for graceful degradation of optional check
874
+ logger.exception(f"Unexpected error in security check ({tool}): {e}")
765
875
  return CheckResult(
766
876
  category=CheckCategory.SECURITY,
767
877
  status=HealthStatus.ERROR,
@@ -824,7 +934,30 @@ class HealthCheckRunner:
824
934
  details={"vulnerable_packages": len(issues)},
825
935
  )
826
936
 
937
+ except json.JSONDecodeError as e:
938
+ # Tool output not in expected JSON format
939
+ logger.warning(f"Dependency check JSON parse error ({tool}): {e}")
940
+ return CheckResult(
941
+ category=CheckCategory.DEPS,
942
+ status=HealthStatus.ERROR,
943
+ score=0,
944
+ tool_used=tool,
945
+ details={"error": f"Failed to parse {tool} output: {e}"},
946
+ )
947
+ except subprocess.SubprocessError as e:
948
+ # Tool execution failed
949
+ logger.error(f"Dependency check subprocess error ({tool}): {e}")
950
+ return CheckResult(
951
+ category=CheckCategory.DEPS,
952
+ status=HealthStatus.ERROR,
953
+ score=0,
954
+ tool_used=tool,
955
+ details={"error": f"Failed to run {tool}: {e}"},
956
+ )
827
957
  except Exception as e:
958
+ # Unexpected errors - preserve full context for debugging
959
+ # INTENTIONAL: Broad handler for graceful degradation of optional check
960
+ logger.exception(f"Unexpected error in dependency check ({tool}): {e}")
828
961
  return CheckResult(
829
962
  category=CheckCategory.DEPS,
830
963
  status=HealthStatus.ERROR,
@@ -920,7 +1053,14 @@ class AutoFixer:
920
1053
  return results
921
1054
 
922
1055
  async def _apply_fix(self, issue: HealthIssue) -> bool:
923
- """Apply a single fix."""
1056
+ """Apply a single fix.
1057
+
1058
+ This uses broad exception handling intentionally for graceful degradation.
1059
+ Auto-fixes are optional - the system should continue even if some fixes fail.
1060
+
1061
+ Note:
1062
+ Full exception context is preserved via logger.exception() for debugging.
1063
+ """
924
1064
  if not issue.fix_command:
925
1065
  return False
926
1066
 
@@ -932,7 +1072,14 @@ class AutoFixer:
932
1072
  text=True,
933
1073
  )
934
1074
  return result.returncode == 0
935
- except Exception:
1075
+ except subprocess.SubprocessError as e:
1076
+ # Fix command execution failed
1077
+ logger.error(f"Auto-fix subprocess error for {issue.file_path}: {e}")
1078
+ return False
1079
+ except Exception as e:
1080
+ # Unexpected errors - preserve full context for debugging
1081
+ # INTENTIONAL: Broad handler for graceful degradation of optional auto-fix
1082
+ logger.exception(f"Unexpected error applying fix to {issue.file_path}: {e}")
936
1083
  return False
937
1084
 
938
1085
 
@@ -0,0 +1,29 @@
1
+ """Empathy Framework Configuration Module
2
+
3
+ Provides unified configuration models for agents, wizards, and workflows.
4
+
5
+ Copyright 2025 Smart-AI-Memory
6
+ Licensed under Fair Source License 0.9
7
+ """
8
+
9
+ from empathy_llm_toolkit.config.unified import (
10
+ AgentOperationError,
11
+ BookProductionConfig,
12
+ MemDocsConfig,
13
+ ModelTier,
14
+ Provider,
15
+ RedisConfig,
16
+ UnifiedAgentConfig,
17
+ WorkflowMode,
18
+ )
19
+
20
+ __all__ = [
21
+ "AgentOperationError",
22
+ "BookProductionConfig",
23
+ "MemDocsConfig",
24
+ "ModelTier",
25
+ "Provider",
26
+ "RedisConfig",
27
+ "UnifiedAgentConfig",
28
+ "WorkflowMode",
29
+ ]
@@ -0,0 +1,295 @@
1
+ """Unified Agent Configuration
2
+
3
+ Single source of truth for all agent, wizard, and workflow configuration.
4
+ Uses Pydantic for validation and type safety.
5
+
6
+ This resolves the AgentConfig duplication between:
7
+ - empathy_llm_toolkit/agent_factory/base.py
8
+ - agents/book_production/base.py
9
+
10
+ Copyright 2025 Smart-AI-Memory
11
+ Licensed under Fair Source License 0.9
12
+ """
13
+
14
+ from enum import Enum
15
+ from typing import Any, Literal
16
+
17
+ from pydantic import BaseModel, Field, field_validator
18
+
19
+
20
+ class ModelTier(str, Enum):
21
+ """Model tier for cost optimization."""
22
+
23
+ CHEAP = "cheap" # Haiku - fast, low cost
24
+ CAPABLE = "capable" # Sonnet - balanced
25
+ PREMIUM = "premium" # Opus - highest quality
26
+
27
+
28
+ class Provider(str, Enum):
29
+ """LLM provider options."""
30
+
31
+ ANTHROPIC = "anthropic"
32
+ OPENAI = "openai"
33
+ LOCAL = "local"
34
+
35
+
36
+ class WorkflowMode(str, Enum):
37
+ """Workflow execution modes."""
38
+
39
+ SEQUENTIAL = "sequential"
40
+ PARALLEL = "parallel"
41
+ GRAPH = "graph"
42
+ CONVERSATION = "conversation"
43
+
44
+
45
+ class AgentOperationError(Exception):
46
+ """Error during agent operation with context."""
47
+
48
+ def __init__(self, operation: str, cause: Exception):
49
+ self.operation = operation
50
+ self.cause = cause
51
+ super().__init__(f"Agent operation '{operation}' failed: {cause}")
52
+
53
+
54
+ class UnifiedAgentConfig(BaseModel):
55
+ """Unified configuration model for all agents.
56
+
57
+ This is the single source of truth for agent configuration,
58
+ replacing duplicate definitions across the codebase.
59
+
60
+ Example:
61
+ config = UnifiedAgentConfig(
62
+ name="researcher",
63
+ role="researcher",
64
+ model_tier=ModelTier.CAPABLE,
65
+ empathy_level=4
66
+ )
67
+
68
+ """
69
+
70
+ # Identity
71
+ name: str = Field(..., min_length=1, description="Unique agent name")
72
+ role: str = Field(default="custom", description="Agent role (researcher, writer, etc.)")
73
+ description: str = Field(default="", description="Agent description")
74
+
75
+ # Model selection
76
+ model_tier: ModelTier = Field(
77
+ default=ModelTier.CAPABLE,
78
+ description="Model tier for cost optimization",
79
+ )
80
+ model_override: str | None = Field(
81
+ default=None,
82
+ description="Specific model ID to use (overrides tier)",
83
+ )
84
+ provider: Provider = Field(default=Provider.ANTHROPIC, description="LLM provider")
85
+
86
+ # Empathy Framework features
87
+ empathy_level: int = Field(
88
+ default=4,
89
+ ge=1,
90
+ le=5,
91
+ description="Empathy level (1=Basic, 4=Anticipatory, 5=Transformative)",
92
+ )
93
+
94
+ # Feature flags
95
+ memory_enabled: bool = Field(default=True, description="Enable conversation memory")
96
+ pattern_learning: bool = Field(default=True, description="Enable pattern learning")
97
+ cost_tracking: bool = Field(default=True, description="Track API costs")
98
+ use_patterns: bool = Field(default=True, description="Use learned patterns")
99
+
100
+ # LLM parameters
101
+ temperature: float = Field(default=0.7, ge=0.0, le=2.0)
102
+ max_tokens: int = Field(default=4096, ge=1, le=200000)
103
+ timeout: int = Field(default=120, ge=1, description="Timeout in seconds")
104
+
105
+ # Retry configuration
106
+ retry_attempts: int = Field(default=3, ge=0, le=10)
107
+ retry_delay: float = Field(default=1.0, ge=0.0)
108
+
109
+ # System prompt
110
+ system_prompt: str | None = Field(default=None, description="Custom system prompt")
111
+
112
+ # Tools and capabilities
113
+ tools: list[Any] = Field(default_factory=list, description="Agent tools")
114
+ capabilities: list[str] = Field(default_factory=list, description="Agent capabilities")
115
+
116
+ # Framework-specific options
117
+ framework_options: dict[str, Any] = Field(
118
+ default_factory=dict,
119
+ description="Framework-specific configuration",
120
+ )
121
+
122
+ # Extensions
123
+ extra: dict[str, Any] = Field(
124
+ default_factory=dict,
125
+ description="Additional custom configuration",
126
+ )
127
+
128
+ @field_validator("role")
129
+ @classmethod
130
+ def normalize_role(cls, v: str) -> str:
131
+ """Normalize role to lowercase."""
132
+ return v.lower().strip()
133
+
134
+ def get_model_id(self) -> str:
135
+ """Get the actual model ID based on tier and provider.
136
+
137
+ Returns:
138
+ Model identifier string
139
+
140
+ """
141
+ if self.model_override:
142
+ return self.model_override
143
+
144
+ # Model mapping by provider and tier
145
+ models = {
146
+ Provider.ANTHROPIC: {
147
+ ModelTier.CHEAP: "claude-3-haiku-20240307",
148
+ ModelTier.CAPABLE: "claude-sonnet-4-20250514",
149
+ ModelTier.PREMIUM: "claude-opus-4-20250514",
150
+ },
151
+ Provider.OPENAI: {
152
+ ModelTier.CHEAP: "gpt-4o-mini",
153
+ ModelTier.CAPABLE: "gpt-4o",
154
+ ModelTier.PREMIUM: "gpt-4o",
155
+ },
156
+ Provider.LOCAL: {
157
+ ModelTier.CHEAP: "llama3.2:3b",
158
+ ModelTier.CAPABLE: "llama3.1:8b",
159
+ ModelTier.PREMIUM: "llama3.1:70b",
160
+ },
161
+ }
162
+
163
+ return models.get(self.provider, {}).get(
164
+ self.model_tier,
165
+ "claude-sonnet-4-20250514", # Fallback
166
+ )
167
+
168
+ def for_book_production(self) -> "BookProductionConfig":
169
+ """Convert to BookProductionConfig for backward compatibility.
170
+
171
+ Returns:
172
+ BookProductionConfig instance
173
+
174
+ """
175
+ return BookProductionConfig(
176
+ agent_config=self,
177
+ memdocs_config=MemDocsConfig(),
178
+ redis_config=RedisConfig(),
179
+ )
180
+
181
+ class Config:
182
+ """Pydantic configuration."""
183
+
184
+ use_enum_values = True
185
+
186
+
187
+ class MemDocsConfig(BaseModel):
188
+ """Configuration for MemDocs pattern storage integration."""
189
+
190
+ enabled: bool = Field(default=True, description="Enable MemDocs integration")
191
+ project: str = Field(default="empathy-framework", description="Project identifier")
192
+
193
+ collections: dict[str, str] = Field(
194
+ default_factory=lambda: {
195
+ "patterns": "learned_patterns",
196
+ "exemplars": "exemplar_examples",
197
+ "transformations": "transformation_examples",
198
+ "feedback": "quality_feedback",
199
+ },
200
+ description="Collection name mappings",
201
+ )
202
+
203
+ # Storage settings
204
+ storage_path: str = Field(default="./patterns", description="Local storage path")
205
+ encryption_enabled: bool = Field(default=False, description="Enable encryption")
206
+
207
+
208
+ class RedisConfig(BaseModel):
209
+ """Configuration for Redis state management."""
210
+
211
+ enabled: bool = Field(default=True, description="Enable Redis")
212
+ host: str = Field(default="localhost", description="Redis host")
213
+ port: int = Field(default=6379, ge=1, le=65535)
214
+ db: int = Field(default=0, ge=0, le=15)
215
+ password: str | None = Field(default=None, description="Redis password")
216
+
217
+ prefix: str = Field(default="empathy", description="Key prefix")
218
+ ttl: int = Field(default=86400, ge=0, description="Default TTL in seconds")
219
+
220
+ # Connection pool settings
221
+ max_connections: int = Field(default=10, ge=1)
222
+ socket_timeout: float = Field(default=5.0, ge=0.1)
223
+
224
+
225
+ class BookProductionConfig(BaseModel):
226
+ """Unified configuration for book production agents.
227
+
228
+ Combines UnifiedAgentConfig with production-specific settings.
229
+ This replaces the duplicate AgentConfig in agents/book_production/base.py.
230
+ """
231
+
232
+ agent_config: UnifiedAgentConfig
233
+ memdocs_config: MemDocsConfig = Field(default_factory=MemDocsConfig)
234
+ redis_config: RedisConfig = Field(default_factory=RedisConfig)
235
+
236
+ # Book production specific
237
+ chapter_max_words: int = Field(default=5000, ge=100)
238
+ include_code_examples: bool = Field(default=True)
239
+ target_reading_level: Literal["beginner", "intermediate", "advanced"] = "intermediate"
240
+
241
+ @property
242
+ def model(self) -> str:
243
+ """Get model ID for backward compatibility."""
244
+ return self.agent_config.get_model_id()
245
+
246
+ @property
247
+ def max_tokens(self) -> int:
248
+ """Get max tokens for backward compatibility."""
249
+ return self.agent_config.max_tokens
250
+
251
+ @property
252
+ def temperature(self) -> float:
253
+ """Get temperature for backward compatibility."""
254
+ return self.agent_config.temperature
255
+
256
+ @property
257
+ def timeout(self) -> int:
258
+ """Get timeout for backward compatibility."""
259
+ return self.agent_config.timeout
260
+
261
+ @property
262
+ def retry_attempts(self) -> int:
263
+ """Get retry attempts for backward compatibility."""
264
+ return self.agent_config.retry_attempts
265
+
266
+ @property
267
+ def retry_delay(self) -> float:
268
+ """Get retry delay for backward compatibility."""
269
+ return self.agent_config.retry_delay
270
+
271
+
272
+ class WorkflowConfig(BaseModel):
273
+ """Configuration for agent workflows."""
274
+
275
+ name: str = Field(..., min_length=1)
276
+ description: str = Field(default="")
277
+ mode: WorkflowMode = Field(default=WorkflowMode.SEQUENTIAL)
278
+
279
+ # Execution settings
280
+ max_iterations: int = Field(default=10, ge=1, le=100)
281
+ timeout_seconds: int = Field(default=300, ge=1)
282
+
283
+ # State management
284
+ state_schema: dict[str, Any] | None = Field(default=None)
285
+ checkpointing: bool = Field(default=True)
286
+
287
+ # Error handling
288
+ retry_on_error: bool = Field(default=True)
289
+ max_retries: int = Field(default=3, ge=0)
290
+
291
+ # Framework options
292
+ framework_options: dict[str, Any] = Field(default_factory=dict)
293
+
294
+ class Config:
295
+ use_enum_values = True
@@ -0,0 +1,32 @@
1
+ """Empathy Framework Model Routing
2
+
3
+ Smart routing of tasks to appropriate model tiers for cost optimization:
4
+ - CHEAP tier: Triage, summarization, classification (Haiku/GPT-4o-mini)
5
+ - CAPABLE tier: Code generation, analysis, sub-agent work (Sonnet/GPT-4o)
6
+ - PREMIUM tier: Coordination, synthesis, critical decisions (Opus/o1)
7
+
8
+ Example:
9
+ >>> from empathy_llm_toolkit.routing import ModelRouter
10
+ >>>
11
+ >>> router = ModelRouter()
12
+ >>> model = router.route("summarize", provider="anthropic")
13
+ >>> print(model) # claude-3-5-haiku-20241022
14
+ >>>
15
+ >>> model = router.route("coordinate", provider="anthropic")
16
+ >>> print(model) # claude-opus-4-20250514
17
+ >>>
18
+ >>> cost = router.estimate_cost("fix_bug", input_tokens=5000, output_tokens=1000)
19
+ >>> print(f"Estimated cost: ${cost:.4f}")
20
+
21
+ Copyright 2025 Smart AI Memory, LLC
22
+ Licensed under Fair Source 0.9
23
+
24
+ """
25
+
26
+ from .model_router import ModelRouter, ModelTier, TaskRouting
27
+
28
+ __all__ = [
29
+ "ModelRouter",
30
+ "ModelTier",
31
+ "TaskRouting",
32
+ ]