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,619 @@
1
+ """Unified Memory Interface for Empathy Framework
2
+
3
+ Provides a single API for both short-term (Redis) and long-term (persistent) memory,
4
+ with automatic pattern promotion and environment-aware storage backend selection.
5
+
6
+ Usage:
7
+ from empathy_os.memory import UnifiedMemory
8
+
9
+ memory = UnifiedMemory(
10
+ user_id="agent@company.com",
11
+ environment="production", # or "staging", "development"
12
+ )
13
+
14
+ # Short-term operations
15
+ memory.stash("working_data", {"key": "value"})
16
+ data = memory.retrieve("working_data")
17
+
18
+ # Long-term operations
19
+ result = memory.persist_pattern(content, pattern_type="algorithm")
20
+ pattern = memory.recall_pattern(pattern_id)
21
+
22
+ # Pattern promotion
23
+ memory.promote_pattern(staged_pattern_id)
24
+
25
+ Copyright 2025 Smart AI Memory, LLC
26
+ Licensed under Fair Source 0.9
27
+ """
28
+
29
+ import os
30
+ import uuid
31
+ from dataclasses import dataclass, field
32
+ from datetime import datetime
33
+ from enum import Enum
34
+ from typing import Any
35
+
36
+ import structlog
37
+
38
+ from .claude_memory import ClaudeMemoryConfig
39
+ from .config import get_redis_memory
40
+ from .long_term import Classification, SecureMemDocsIntegration
41
+ from .redis_bootstrap import RedisStartMethod, RedisStatus, ensure_redis
42
+ from .short_term import (
43
+ AccessTier,
44
+ AgentCredentials,
45
+ RedisShortTermMemory,
46
+ StagedPattern,
47
+ TTLStrategy,
48
+ )
49
+
50
+ logger = structlog.get_logger(__name__)
51
+
52
+
53
+ class Environment(Enum):
54
+ """Deployment environment for storage configuration."""
55
+
56
+ DEVELOPMENT = "development"
57
+ STAGING = "staging"
58
+ PRODUCTION = "production"
59
+
60
+
61
+ @dataclass
62
+ class MemoryConfig:
63
+ """Configuration for unified memory system."""
64
+
65
+ # Environment
66
+ environment: Environment = Environment.DEVELOPMENT
67
+
68
+ # Short-term memory settings
69
+ redis_url: str | None = None
70
+ redis_host: str = "localhost"
71
+ redis_port: int = 6379
72
+ redis_mock: bool = False
73
+ redis_auto_start: bool = True # Auto-start Redis if not running
74
+ default_ttl_seconds: int = 3600 # 1 hour
75
+
76
+ # Long-term memory settings
77
+ storage_dir: str = "./memdocs_storage"
78
+ encryption_enabled: bool = True
79
+
80
+ # Claude memory settings
81
+ claude_memory_enabled: bool = True
82
+ load_enterprise_memory: bool = True
83
+ load_project_memory: bool = True
84
+ load_user_memory: bool = True
85
+
86
+ # Pattern promotion settings
87
+ auto_promote_threshold: float = 0.8 # Confidence threshold for auto-promotion
88
+
89
+ @classmethod
90
+ def from_environment(cls) -> "MemoryConfig":
91
+ """Create configuration from environment variables.
92
+
93
+ Environment Variables:
94
+ EMPATHY_ENV: Environment (development/staging/production)
95
+ REDIS_URL: Redis connection URL
96
+ EMPATHY_REDIS_MOCK: Use mock Redis (true/false)
97
+ EMPATHY_STORAGE_DIR: Long-term storage directory
98
+ EMPATHY_ENCRYPTION: Enable encryption (true/false)
99
+ """
100
+ env_str = os.getenv("EMPATHY_ENV", "development").lower()
101
+ environment = (
102
+ Environment(env_str)
103
+ if env_str in [e.value for e in Environment]
104
+ else Environment.DEVELOPMENT
105
+ )
106
+
107
+ return cls(
108
+ environment=environment,
109
+ redis_url=os.getenv("REDIS_URL"),
110
+ redis_host=os.getenv("EMPATHY_REDIS_HOST", "localhost"),
111
+ redis_port=int(os.getenv("EMPATHY_REDIS_PORT", "6379")),
112
+ redis_mock=os.getenv("EMPATHY_REDIS_MOCK", "").lower() == "true",
113
+ redis_auto_start=os.getenv("EMPATHY_REDIS_AUTO_START", "true").lower() == "true",
114
+ storage_dir=os.getenv("EMPATHY_STORAGE_DIR", "./memdocs_storage"),
115
+ encryption_enabled=os.getenv("EMPATHY_ENCRYPTION", "true").lower() == "true",
116
+ claude_memory_enabled=os.getenv("EMPATHY_CLAUDE_MEMORY", "true").lower() == "true",
117
+ )
118
+
119
+
120
+ @dataclass
121
+ class UnifiedMemory:
122
+ """Unified interface for short-term and long-term memory.
123
+
124
+ Provides:
125
+ - Short-term memory (Redis): Fast, TTL-based working memory
126
+ - Long-term memory (Persistent): Cross-session pattern storage
127
+ - Pattern promotion: Move validated patterns from short to long-term
128
+ - Environment-aware configuration: Auto-detect storage backends
129
+ """
130
+
131
+ user_id: str
132
+ config: MemoryConfig = field(default_factory=MemoryConfig.from_environment)
133
+ access_tier: AccessTier = AccessTier.CONTRIBUTOR
134
+
135
+ # Internal state
136
+ _short_term: RedisShortTermMemory | None = field(default=None, init=False)
137
+ _long_term: SecureMemDocsIntegration | None = field(default=None, init=False)
138
+ _redis_status: RedisStatus | None = field(default=None, init=False)
139
+ _initialized: bool = field(default=False, init=False)
140
+
141
+ def __post_init__(self):
142
+ """Initialize memory backends based on configuration."""
143
+ self._initialize_backends()
144
+
145
+ def _initialize_backends(self):
146
+ """Initialize short-term and long-term memory backends."""
147
+ if self._initialized:
148
+ return
149
+
150
+ # Initialize short-term memory (Redis)
151
+ try:
152
+ if self.config.redis_mock:
153
+ self._short_term = RedisShortTermMemory(use_mock=True)
154
+ self._redis_status = RedisStatus(
155
+ available=False,
156
+ method=RedisStartMethod.MOCK,
157
+ message="Mock mode explicitly enabled",
158
+ )
159
+ elif self.config.redis_url:
160
+ self._short_term = get_redis_memory(url=self.config.redis_url)
161
+ self._redis_status = RedisStatus(
162
+ available=True,
163
+ method=RedisStartMethod.ALREADY_RUNNING,
164
+ message="Connected via REDIS_URL",
165
+ )
166
+ # Use auto-start if enabled
167
+ elif self.config.redis_auto_start:
168
+ self._redis_status = ensure_redis(
169
+ host=self.config.redis_host,
170
+ port=self.config.redis_port,
171
+ auto_start=True,
172
+ verbose=True,
173
+ )
174
+ if self._redis_status.available:
175
+ self._short_term = RedisShortTermMemory(
176
+ host=self.config.redis_host,
177
+ port=self.config.redis_port,
178
+ use_mock=False,
179
+ )
180
+ else:
181
+ self._short_term = RedisShortTermMemory(use_mock=True)
182
+ else:
183
+ self._short_term = get_redis_memory()
184
+ self._redis_status = RedisStatus(
185
+ available=True,
186
+ method=RedisStartMethod.ALREADY_RUNNING,
187
+ message="Connected to existing Redis",
188
+ )
189
+
190
+ logger.info(
191
+ "short_term_memory_initialized",
192
+ mock_mode=self.config.redis_mock or not self._redis_status.available,
193
+ redis_method=self._redis_status.method.value if self._redis_status else "unknown",
194
+ environment=self.config.environment.value,
195
+ )
196
+ except Exception as e:
197
+ logger.warning("short_term_memory_failed", error=str(e))
198
+ self._short_term = RedisShortTermMemory(use_mock=True)
199
+ self._redis_status = RedisStatus(
200
+ available=False,
201
+ method=RedisStartMethod.MOCK,
202
+ message=f"Failed to initialize: {e}",
203
+ )
204
+
205
+ # Initialize long-term memory (SecureMemDocs)
206
+ try:
207
+ claude_config = ClaudeMemoryConfig(
208
+ enabled=self.config.claude_memory_enabled,
209
+ load_enterprise=self.config.load_enterprise_memory,
210
+ load_project=self.config.load_project_memory,
211
+ load_user=self.config.load_user_memory,
212
+ )
213
+ self._long_term = SecureMemDocsIntegration(
214
+ claude_memory_config=claude_config,
215
+ storage_dir=self.config.storage_dir,
216
+ enable_encryption=self.config.encryption_enabled,
217
+ )
218
+
219
+ logger.info(
220
+ "long_term_memory_initialized",
221
+ storage_dir=self.config.storage_dir,
222
+ encryption=self.config.encryption_enabled,
223
+ )
224
+ except Exception as e:
225
+ logger.error("long_term_memory_failed", error=str(e))
226
+ self._long_term = None
227
+
228
+ self._initialized = True
229
+
230
+ @property
231
+ def credentials(self) -> AgentCredentials:
232
+ """Get agent credentials for short-term memory operations."""
233
+ return AgentCredentials(agent_id=self.user_id, tier=self.access_tier)
234
+
235
+ def get_backend_status(self) -> dict[str, Any]:
236
+ """Get the current status of all memory backends.
237
+
238
+ Returns a structured dict suitable for health checks, debugging,
239
+ and dashboard display. Can be serialized to JSON.
240
+
241
+ Returns:
242
+ dict with keys:
243
+ - environment: Current environment (development/staging/production)
244
+ - short_term: Status of Redis-based short-term memory
245
+ - long_term: Status of persistent long-term memory
246
+ - initialized: Whether backends have been initialized
247
+
248
+ Example:
249
+ >>> memory = UnifiedMemory(user_id="agent")
250
+ >>> status = memory.get_backend_status()
251
+ >>> print(status["short_term"]["available"])
252
+ True
253
+
254
+ """
255
+ short_term_status: dict[str, Any] = {
256
+ "available": False,
257
+ "mock": True,
258
+ "method": "unknown",
259
+ "message": "Not initialized",
260
+ }
261
+
262
+ if self._redis_status:
263
+ short_term_status = {
264
+ "available": self._redis_status.available,
265
+ "mock": not self._redis_status.available
266
+ or self._redis_status.method == RedisStartMethod.MOCK,
267
+ "method": self._redis_status.method.value,
268
+ "message": self._redis_status.message,
269
+ }
270
+
271
+ long_term_status: dict[str, Any] = {
272
+ "available": self._long_term is not None,
273
+ "storage_dir": self.config.storage_dir,
274
+ "encryption_enabled": self.config.encryption_enabled,
275
+ }
276
+
277
+ return {
278
+ "environment": self.config.environment.value,
279
+ "initialized": self._initialized,
280
+ "short_term": short_term_status,
281
+ "long_term": long_term_status,
282
+ }
283
+
284
+ # =========================================================================
285
+ # SHORT-TERM MEMORY OPERATIONS
286
+ # =========================================================================
287
+
288
+ def stash(self, key: str, value: Any, ttl_seconds: int | None = None) -> bool:
289
+ """Store data in short-term memory with TTL.
290
+
291
+ Args:
292
+ key: Storage key
293
+ value: Data to store (must be JSON-serializable)
294
+ ttl_seconds: Time-to-live in seconds (default from config)
295
+
296
+ Returns:
297
+ True if stored successfully
298
+
299
+ """
300
+ if not self._short_term:
301
+ logger.warning("short_term_memory_unavailable")
302
+ return False
303
+
304
+ # Map ttl_seconds to TTLStrategy (use WORKING_RESULTS as default)
305
+ ttl_strategy = TTLStrategy.WORKING_RESULTS
306
+ if ttl_seconds is not None:
307
+ # Find closest TTL strategy or use working results
308
+ if ttl_seconds <= TTLStrategy.COORDINATION.value:
309
+ ttl_strategy = TTLStrategy.COORDINATION
310
+ elif ttl_seconds <= TTLStrategy.SESSION.value:
311
+ ttl_strategy = TTLStrategy.SESSION
312
+ elif ttl_seconds <= TTLStrategy.WORKING_RESULTS.value:
313
+ ttl_strategy = TTLStrategy.WORKING_RESULTS
314
+ elif ttl_seconds <= TTLStrategy.STAGED_PATTERNS.value:
315
+ ttl_strategy = TTLStrategy.STAGED_PATTERNS
316
+ else:
317
+ ttl_strategy = TTLStrategy.CONFLICT_CONTEXT
318
+
319
+ return self._short_term.stash(key, value, self.credentials, ttl_strategy)
320
+
321
+ def retrieve(self, key: str) -> Any | None:
322
+ """Retrieve data from short-term memory.
323
+
324
+ Args:
325
+ key: Storage key
326
+
327
+ Returns:
328
+ Stored data or None if not found
329
+
330
+ """
331
+ if not self._short_term:
332
+ return None
333
+
334
+ return self._short_term.retrieve(key, self.credentials)
335
+
336
+ def stage_pattern(
337
+ self,
338
+ pattern_data: dict[str, Any],
339
+ pattern_type: str = "general",
340
+ ttl_hours: int = 24,
341
+ ) -> str | None:
342
+ """Stage a pattern for validation before long-term storage.
343
+
344
+ Args:
345
+ pattern_data: Pattern content and metadata
346
+ pattern_type: Type of pattern (algorithm, protocol, etc.)
347
+ ttl_hours: Hours before staged pattern expires (not used in current impl)
348
+
349
+ Returns:
350
+ Staged pattern ID or None if failed
351
+
352
+ """
353
+ if not self._short_term:
354
+ logger.warning("short_term_memory_unavailable")
355
+ return None
356
+
357
+ # Create a StagedPattern object from the pattern_data dict
358
+ pattern_id = f"staged_{uuid.uuid4().hex[:12]}"
359
+ staged_pattern = StagedPattern(
360
+ pattern_id=pattern_id,
361
+ agent_id=self.user_id,
362
+ pattern_type=pattern_type,
363
+ name=pattern_data.get("name", f"Pattern {pattern_id[:8]}"),
364
+ description=pattern_data.get("description", ""),
365
+ code=pattern_data.get("code"),
366
+ context=pattern_data.get("context", {}),
367
+ confidence=pattern_data.get("confidence", 0.5),
368
+ staged_at=datetime.now(),
369
+ interests=pattern_data.get("interests", []),
370
+ )
371
+ # Store content in context if provided
372
+ if "content" in pattern_data:
373
+ staged_pattern.context["content"] = pattern_data["content"]
374
+
375
+ success = self._short_term.stage_pattern(staged_pattern, self.credentials)
376
+ return pattern_id if success else None
377
+
378
+ def get_staged_patterns(self) -> list[dict]:
379
+ """Get all staged patterns awaiting validation.
380
+
381
+ Returns:
382
+ List of staged patterns with metadata
383
+
384
+ """
385
+ if not self._short_term:
386
+ return []
387
+
388
+ staged_list = self._short_term.list_staged_patterns(self.credentials)
389
+ return [p.to_dict() for p in staged_list]
390
+
391
+ # =========================================================================
392
+ # LONG-TERM MEMORY OPERATIONS
393
+ # =========================================================================
394
+
395
+ def persist_pattern(
396
+ self,
397
+ content: str,
398
+ pattern_type: str,
399
+ classification: Classification | str | None = None,
400
+ auto_classify: bool = True,
401
+ metadata: dict[str, Any] | None = None,
402
+ ) -> dict[str, Any] | None:
403
+ """Store a pattern in long-term memory with security controls.
404
+
405
+ Args:
406
+ content: Pattern content
407
+ pattern_type: Type of pattern (algorithm, protocol, etc.)
408
+ classification: Security classification (PUBLIC/INTERNAL/SENSITIVE)
409
+ auto_classify: Auto-detect classification from content
410
+ metadata: Additional metadata to store
411
+
412
+ Returns:
413
+ Storage result with pattern_id and classification, or None if failed
414
+
415
+ """
416
+ if not self._long_term:
417
+ logger.error("long_term_memory_unavailable")
418
+ return None
419
+
420
+ try:
421
+ # Convert string classification to enum if needed
422
+ explicit_class = None
423
+ if classification is not None:
424
+ if isinstance(classification, str):
425
+ explicit_class = Classification[classification.upper()]
426
+ else:
427
+ explicit_class = classification
428
+
429
+ result = self._long_term.store_pattern(
430
+ content=content,
431
+ pattern_type=pattern_type,
432
+ user_id=self.user_id,
433
+ explicit_classification=explicit_class,
434
+ auto_classify=auto_classify,
435
+ custom_metadata=metadata,
436
+ )
437
+ logger.info(
438
+ "pattern_persisted",
439
+ pattern_id=result.get("pattern_id"),
440
+ classification=result.get("classification"),
441
+ )
442
+ return result
443
+ except Exception as e:
444
+ logger.error("persist_pattern_failed", error=str(e))
445
+ return None
446
+
447
+ def recall_pattern(
448
+ self,
449
+ pattern_id: str,
450
+ check_permissions: bool = True,
451
+ ) -> dict[str, Any] | None:
452
+ """Retrieve a pattern from long-term memory.
453
+
454
+ Args:
455
+ pattern_id: ID of pattern to retrieve
456
+ check_permissions: Verify user has access to pattern
457
+
458
+ Returns:
459
+ Pattern data with content and metadata, or None if not found
460
+
461
+ """
462
+ if not self._long_term:
463
+ logger.error("long_term_memory_unavailable")
464
+ return None
465
+
466
+ try:
467
+ return self._long_term.retrieve_pattern(
468
+ pattern_id=pattern_id,
469
+ user_id=self.user_id,
470
+ check_permissions=check_permissions,
471
+ )
472
+ except Exception as e:
473
+ logger.error("recall_pattern_failed", pattern_id=pattern_id, error=str(e))
474
+ return None
475
+
476
+ def search_patterns(
477
+ self,
478
+ query: str | None = None,
479
+ pattern_type: str | None = None,
480
+ classification: Classification | None = None,
481
+ limit: int = 10,
482
+ ) -> list[dict[str, Any]]:
483
+ """Search patterns in long-term memory.
484
+
485
+ Args:
486
+ query: Text to search for in pattern content
487
+ pattern_type: Filter by pattern type
488
+ classification: Filter by classification level
489
+ limit: Maximum results to return
490
+
491
+ Returns:
492
+ List of matching patterns
493
+
494
+ """
495
+ if not self._long_term:
496
+ return []
497
+
498
+ # Note: Full search implementation depends on storage backend
499
+ # For now, return patterns matching type/classification
500
+ patterns: list[dict[str, Any]] = []
501
+ # This would be implemented based on the storage backend
502
+ return patterns
503
+
504
+ # =========================================================================
505
+ # PATTERN PROMOTION (SHORT-TERM → LONG-TERM)
506
+ # =========================================================================
507
+
508
+ def promote_pattern(
509
+ self,
510
+ staged_pattern_id: str,
511
+ classification: Classification | str | None = None,
512
+ auto_classify: bool = True,
513
+ ) -> dict[str, Any] | None:
514
+ """Promote a staged pattern from short-term to long-term memory.
515
+
516
+ Args:
517
+ staged_pattern_id: ID of staged pattern to promote
518
+ classification: Override classification (or auto-detect)
519
+ auto_classify: Auto-detect classification from content
520
+
521
+ Returns:
522
+ Long-term storage result, or None if failed
523
+
524
+ """
525
+ if not self._short_term or not self._long_term:
526
+ logger.error("memory_backends_unavailable")
527
+ return None
528
+
529
+ # Retrieve staged pattern
530
+ staged_patterns = self.get_staged_patterns()
531
+ staged = next(
532
+ (p for p in staged_patterns if p.get("pattern_id") == staged_pattern_id),
533
+ None,
534
+ )
535
+
536
+ if not staged:
537
+ logger.warning("staged_pattern_not_found", pattern_id=staged_pattern_id)
538
+ return None
539
+
540
+ # Persist to long-term storage
541
+ # Content is stored in context dict by stage_pattern
542
+ context = staged.get("context", {})
543
+ content = context.get("content", "") or staged.get("description", "")
544
+ result = self.persist_pattern(
545
+ content=content,
546
+ pattern_type=staged.get("pattern_type", "general"),
547
+ classification=classification,
548
+ auto_classify=auto_classify,
549
+ metadata=context,
550
+ )
551
+
552
+ if result:
553
+ # Remove from staging (use promote_pattern which handles deletion)
554
+ try:
555
+ self._short_term.promote_pattern(staged_pattern_id, self.credentials)
556
+ except PermissionError:
557
+ # If we can't promote (delete from staging), just log it
558
+ logger.warning("could_not_remove_from_staging", pattern_id=staged_pattern_id)
559
+ logger.info(
560
+ "pattern_promoted",
561
+ staged_id=staged_pattern_id,
562
+ long_term_id=result.get("pattern_id"),
563
+ )
564
+
565
+ return result
566
+
567
+ # =========================================================================
568
+ # UTILITY METHODS
569
+ # =========================================================================
570
+
571
+ @property
572
+ def has_short_term(self) -> bool:
573
+ """Check if short-term memory is available."""
574
+ return self._short_term is not None
575
+
576
+ @property
577
+ def has_long_term(self) -> bool:
578
+ """Check if long-term memory is available."""
579
+ return self._long_term is not None
580
+
581
+ @property
582
+ def redis_status(self) -> RedisStatus | None:
583
+ """Get Redis connection status."""
584
+ return self._redis_status
585
+
586
+ @property
587
+ def using_real_redis(self) -> bool:
588
+ """Check if using real Redis (not mock)."""
589
+ return (
590
+ self._redis_status is not None
591
+ and self._redis_status.available
592
+ and self._redis_status.method != RedisStartMethod.MOCK
593
+ )
594
+
595
+ def health_check(self) -> dict[str, Any]:
596
+ """Check health of memory backends.
597
+
598
+ Returns:
599
+ Status of each memory backend
600
+
601
+ """
602
+ redis_info: dict[str, Any] = {
603
+ "available": self.has_short_term,
604
+ "mock_mode": not self.using_real_redis,
605
+ }
606
+ if self._redis_status:
607
+ redis_info["method"] = self._redis_status.method.value
608
+ redis_info["host"] = self._redis_status.host
609
+ redis_info["port"] = self._redis_status.port
610
+
611
+ return {
612
+ "short_term": redis_info,
613
+ "long_term": {
614
+ "available": self.has_long_term,
615
+ "storage_dir": self.config.storage_dir,
616
+ "encryption": self.config.encryption_enabled,
617
+ },
618
+ "environment": self.config.environment.value,
619
+ }
@@ -0,0 +1,12 @@
1
+ """Prompt performance metrics tracking and analysis.
2
+
3
+ This module provides tools for tracking, analyzing, and optimizing
4
+ prompt performance across the Empathy Framework.
5
+
6
+ Copyright 2026 Smart-AI-Memory
7
+ Licensed under Fair Source License 0.9
8
+ """
9
+
10
+ from empathy_os.metrics.prompt_metrics import MetricsTracker, PromptMetrics
11
+
12
+ __all__ = ["MetricsTracker", "PromptMetrics"]