empathy-framework 4.6.6__py3-none-any.whl → 4.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 (273) hide show
  1. empathy_framework-4.7.1.dist-info/METADATA +690 -0
  2. empathy_framework-4.7.1.dist-info/RECORD +379 -0
  3. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/top_level.txt +1 -2
  4. empathy_healthcare_plugin/monitors/monitoring/__init__.py +9 -9
  5. empathy_llm_toolkit/agent_factory/__init__.py +6 -6
  6. empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +7 -10
  7. empathy_llm_toolkit/agents_md/__init__.py +22 -0
  8. empathy_llm_toolkit/agents_md/loader.py +218 -0
  9. empathy_llm_toolkit/agents_md/parser.py +271 -0
  10. empathy_llm_toolkit/agents_md/registry.py +307 -0
  11. empathy_llm_toolkit/commands/__init__.py +51 -0
  12. empathy_llm_toolkit/commands/context.py +375 -0
  13. empathy_llm_toolkit/commands/loader.py +301 -0
  14. empathy_llm_toolkit/commands/models.py +231 -0
  15. empathy_llm_toolkit/commands/parser.py +371 -0
  16. empathy_llm_toolkit/commands/registry.py +429 -0
  17. empathy_llm_toolkit/config/__init__.py +8 -8
  18. empathy_llm_toolkit/config/unified.py +3 -7
  19. empathy_llm_toolkit/context/__init__.py +22 -0
  20. empathy_llm_toolkit/context/compaction.py +455 -0
  21. empathy_llm_toolkit/context/manager.py +434 -0
  22. empathy_llm_toolkit/hooks/__init__.py +24 -0
  23. empathy_llm_toolkit/hooks/config.py +306 -0
  24. empathy_llm_toolkit/hooks/executor.py +289 -0
  25. empathy_llm_toolkit/hooks/registry.py +302 -0
  26. empathy_llm_toolkit/hooks/scripts/__init__.py +39 -0
  27. empathy_llm_toolkit/hooks/scripts/evaluate_session.py +201 -0
  28. empathy_llm_toolkit/hooks/scripts/first_time_init.py +285 -0
  29. empathy_llm_toolkit/hooks/scripts/pre_compact.py +207 -0
  30. empathy_llm_toolkit/hooks/scripts/session_end.py +183 -0
  31. empathy_llm_toolkit/hooks/scripts/session_start.py +163 -0
  32. empathy_llm_toolkit/hooks/scripts/suggest_compact.py +225 -0
  33. empathy_llm_toolkit/learning/__init__.py +30 -0
  34. empathy_llm_toolkit/learning/evaluator.py +438 -0
  35. empathy_llm_toolkit/learning/extractor.py +514 -0
  36. empathy_llm_toolkit/learning/storage.py +560 -0
  37. empathy_llm_toolkit/providers.py +4 -11
  38. empathy_llm_toolkit/security/__init__.py +17 -17
  39. empathy_llm_toolkit/utils/tokens.py +2 -5
  40. empathy_os/__init__.py +202 -70
  41. empathy_os/cache_monitor.py +5 -3
  42. empathy_os/cli/__init__.py +11 -55
  43. empathy_os/cli/__main__.py +29 -15
  44. empathy_os/cli/commands/inspection.py +21 -12
  45. empathy_os/cli/commands/memory.py +4 -12
  46. empathy_os/cli/commands/profiling.py +198 -0
  47. empathy_os/cli/commands/utilities.py +27 -7
  48. empathy_os/cli.py +28 -57
  49. empathy_os/cli_unified.py +525 -1164
  50. empathy_os/cost_tracker.py +9 -3
  51. empathy_os/dashboard/server.py +200 -2
  52. empathy_os/hot_reload/__init__.py +7 -7
  53. empathy_os/hot_reload/config.py +6 -7
  54. empathy_os/hot_reload/integration.py +35 -35
  55. empathy_os/hot_reload/reloader.py +57 -57
  56. empathy_os/hot_reload/watcher.py +28 -28
  57. empathy_os/hot_reload/websocket.py +2 -2
  58. empathy_os/memory/__init__.py +11 -4
  59. empathy_os/memory/claude_memory.py +1 -1
  60. empathy_os/memory/cross_session.py +8 -12
  61. empathy_os/memory/edges.py +6 -6
  62. empathy_os/memory/file_session.py +770 -0
  63. empathy_os/memory/graph.py +30 -30
  64. empathy_os/memory/nodes.py +6 -6
  65. empathy_os/memory/short_term.py +15 -9
  66. empathy_os/memory/unified.py +606 -140
  67. empathy_os/meta_workflows/agent_creator.py +3 -9
  68. empathy_os/meta_workflows/cli_meta_workflows.py +113 -53
  69. empathy_os/meta_workflows/form_engine.py +6 -18
  70. empathy_os/meta_workflows/intent_detector.py +64 -24
  71. empathy_os/meta_workflows/models.py +3 -1
  72. empathy_os/meta_workflows/pattern_learner.py +13 -31
  73. empathy_os/meta_workflows/plan_generator.py +55 -47
  74. empathy_os/meta_workflows/session_context.py +2 -3
  75. empathy_os/meta_workflows/workflow.py +20 -51
  76. empathy_os/models/cli.py +2 -2
  77. empathy_os/models/tasks.py +1 -2
  78. empathy_os/models/telemetry.py +4 -1
  79. empathy_os/models/token_estimator.py +3 -1
  80. empathy_os/monitoring/alerts.py +938 -9
  81. empathy_os/monitoring/alerts_cli.py +346 -183
  82. empathy_os/orchestration/execution_strategies.py +12 -29
  83. empathy_os/orchestration/pattern_learner.py +20 -26
  84. empathy_os/orchestration/real_tools.py +6 -15
  85. empathy_os/platform_utils.py +2 -1
  86. empathy_os/plugins/__init__.py +2 -2
  87. empathy_os/plugins/base.py +64 -64
  88. empathy_os/plugins/registry.py +32 -32
  89. empathy_os/project_index/index.py +49 -15
  90. empathy_os/project_index/models.py +1 -2
  91. empathy_os/project_index/reports.py +1 -1
  92. empathy_os/project_index/scanner.py +1 -0
  93. empathy_os/redis_memory.py +10 -7
  94. empathy_os/resilience/__init__.py +1 -1
  95. empathy_os/resilience/health.py +10 -10
  96. empathy_os/routing/__init__.py +7 -7
  97. empathy_os/routing/chain_executor.py +37 -37
  98. empathy_os/routing/classifier.py +36 -36
  99. empathy_os/routing/smart_router.py +40 -40
  100. empathy_os/routing/{wizard_registry.py → workflow_registry.py} +47 -47
  101. empathy_os/scaffolding/__init__.py +8 -8
  102. empathy_os/scaffolding/__main__.py +1 -1
  103. empathy_os/scaffolding/cli.py +28 -28
  104. empathy_os/socratic/__init__.py +3 -19
  105. empathy_os/socratic/ab_testing.py +25 -36
  106. empathy_os/socratic/blueprint.py +38 -38
  107. empathy_os/socratic/cli.py +34 -20
  108. empathy_os/socratic/collaboration.py +30 -28
  109. empathy_os/socratic/domain_templates.py +9 -1
  110. empathy_os/socratic/embeddings.py +17 -13
  111. empathy_os/socratic/engine.py +135 -70
  112. empathy_os/socratic/explainer.py +70 -60
  113. empathy_os/socratic/feedback.py +24 -19
  114. empathy_os/socratic/forms.py +15 -10
  115. empathy_os/socratic/generator.py +51 -35
  116. empathy_os/socratic/llm_analyzer.py +25 -23
  117. empathy_os/socratic/mcp_server.py +99 -159
  118. empathy_os/socratic/session.py +19 -13
  119. empathy_os/socratic/storage.py +98 -67
  120. empathy_os/socratic/success.py +38 -27
  121. empathy_os/socratic/visual_editor.py +51 -39
  122. empathy_os/socratic/web_ui.py +99 -66
  123. empathy_os/telemetry/cli.py +3 -1
  124. empathy_os/telemetry/usage_tracker.py +1 -3
  125. empathy_os/test_generator/__init__.py +3 -3
  126. empathy_os/test_generator/cli.py +28 -28
  127. empathy_os/test_generator/generator.py +64 -66
  128. empathy_os/test_generator/risk_analyzer.py +11 -11
  129. empathy_os/vscode_bridge 2.py +173 -0
  130. empathy_os/vscode_bridge.py +173 -0
  131. empathy_os/workflows/__init__.py +212 -120
  132. empathy_os/workflows/batch_processing.py +8 -24
  133. empathy_os/workflows/bug_predict.py +1 -1
  134. empathy_os/workflows/code_review.py +20 -5
  135. empathy_os/workflows/code_review_pipeline.py +13 -8
  136. empathy_os/workflows/keyboard_shortcuts/workflow.py +6 -2
  137. empathy_os/workflows/manage_documentation.py +1 -0
  138. empathy_os/workflows/orchestrated_health_check.py +6 -11
  139. empathy_os/workflows/orchestrated_release_prep.py +3 -3
  140. empathy_os/workflows/pr_review.py +18 -10
  141. empathy_os/workflows/progressive/README 2.md +454 -0
  142. empathy_os/workflows/progressive/__init__ 2.py +92 -0
  143. empathy_os/workflows/progressive/__init__.py +2 -12
  144. empathy_os/workflows/progressive/cli 2.py +242 -0
  145. empathy_os/workflows/progressive/cli.py +14 -37
  146. empathy_os/workflows/progressive/core 2.py +488 -0
  147. empathy_os/workflows/progressive/core.py +12 -12
  148. empathy_os/workflows/progressive/orchestrator 2.py +701 -0
  149. empathy_os/workflows/progressive/orchestrator.py +166 -144
  150. empathy_os/workflows/progressive/reports 2.py +528 -0
  151. empathy_os/workflows/progressive/reports.py +22 -31
  152. empathy_os/workflows/progressive/telemetry 2.py +280 -0
  153. empathy_os/workflows/progressive/telemetry.py +8 -14
  154. empathy_os/workflows/progressive/test_gen 2.py +514 -0
  155. empathy_os/workflows/progressive/test_gen.py +29 -48
  156. empathy_os/workflows/progressive/workflow 2.py +628 -0
  157. empathy_os/workflows/progressive/workflow.py +31 -70
  158. empathy_os/workflows/release_prep.py +21 -6
  159. empathy_os/workflows/release_prep_crew.py +1 -0
  160. empathy_os/workflows/secure_release.py +13 -6
  161. empathy_os/workflows/security_audit.py +8 -3
  162. empathy_os/workflows/test_coverage_boost_crew.py +3 -2
  163. empathy_os/workflows/test_maintenance_crew.py +1 -0
  164. empathy_os/workflows/test_runner.py +16 -12
  165. empathy_software_plugin/SOFTWARE_PLUGIN_README.md +25 -703
  166. empathy_software_plugin/cli.py +0 -122
  167. patterns/README.md +119 -0
  168. patterns/__init__.py +95 -0
  169. patterns/behavior.py +298 -0
  170. patterns/code_review_memory.json +441 -0
  171. patterns/core.py +97 -0
  172. patterns/debugging.json +3763 -0
  173. patterns/empathy.py +268 -0
  174. patterns/health_check_memory.json +505 -0
  175. patterns/input.py +161 -0
  176. patterns/memory_graph.json +8 -0
  177. patterns/refactoring_memory.json +1113 -0
  178. patterns/registry.py +663 -0
  179. patterns/security_memory.json +8 -0
  180. patterns/structural.py +415 -0
  181. patterns/validation.py +194 -0
  182. coach_wizards/__init__.py +0 -45
  183. coach_wizards/accessibility_wizard.py +0 -91
  184. coach_wizards/api_wizard.py +0 -91
  185. coach_wizards/base_wizard.py +0 -209
  186. coach_wizards/cicd_wizard.py +0 -91
  187. coach_wizards/code_reviewer_README.md +0 -60
  188. coach_wizards/code_reviewer_wizard.py +0 -180
  189. coach_wizards/compliance_wizard.py +0 -91
  190. coach_wizards/database_wizard.py +0 -91
  191. coach_wizards/debugging_wizard.py +0 -91
  192. coach_wizards/documentation_wizard.py +0 -91
  193. coach_wizards/generate_wizards.py +0 -347
  194. coach_wizards/localization_wizard.py +0 -173
  195. coach_wizards/migration_wizard.py +0 -91
  196. coach_wizards/monitoring_wizard.py +0 -91
  197. coach_wizards/observability_wizard.py +0 -91
  198. coach_wizards/performance_wizard.py +0 -91
  199. coach_wizards/prompt_engineering_wizard.py +0 -661
  200. coach_wizards/refactoring_wizard.py +0 -91
  201. coach_wizards/scaling_wizard.py +0 -90
  202. coach_wizards/security_wizard.py +0 -92
  203. coach_wizards/testing_wizard.py +0 -91
  204. empathy_framework-4.6.6.dist-info/METADATA +0 -1597
  205. empathy_framework-4.6.6.dist-info/RECORD +0 -410
  206. empathy_llm_toolkit/wizards/__init__.py +0 -43
  207. empathy_llm_toolkit/wizards/base_wizard.py +0 -364
  208. empathy_llm_toolkit/wizards/customer_support_wizard.py +0 -190
  209. empathy_llm_toolkit/wizards/healthcare_wizard.py +0 -378
  210. empathy_llm_toolkit/wizards/patient_assessment_README.md +0 -64
  211. empathy_llm_toolkit/wizards/patient_assessment_wizard.py +0 -193
  212. empathy_llm_toolkit/wizards/technology_wizard.py +0 -209
  213. empathy_os/wizard_factory_cli.py +0 -170
  214. empathy_software_plugin/wizards/__init__.py +0 -42
  215. empathy_software_plugin/wizards/advanced_debugging_wizard.py +0 -395
  216. empathy_software_plugin/wizards/agent_orchestration_wizard.py +0 -511
  217. empathy_software_plugin/wizards/ai_collaboration_wizard.py +0 -503
  218. empathy_software_plugin/wizards/ai_context_wizard.py +0 -441
  219. empathy_software_plugin/wizards/ai_documentation_wizard.py +0 -503
  220. empathy_software_plugin/wizards/base_wizard.py +0 -288
  221. empathy_software_plugin/wizards/book_chapter_wizard.py +0 -519
  222. empathy_software_plugin/wizards/code_review_wizard.py +0 -604
  223. empathy_software_plugin/wizards/debugging/__init__.py +0 -50
  224. empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +0 -414
  225. empathy_software_plugin/wizards/debugging/config_loaders.py +0 -446
  226. empathy_software_plugin/wizards/debugging/fix_applier.py +0 -469
  227. empathy_software_plugin/wizards/debugging/language_patterns.py +0 -385
  228. empathy_software_plugin/wizards/debugging/linter_parsers.py +0 -470
  229. empathy_software_plugin/wizards/debugging/verification.py +0 -369
  230. empathy_software_plugin/wizards/enhanced_testing_wizard.py +0 -537
  231. empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +0 -816
  232. empathy_software_plugin/wizards/multi_model_wizard.py +0 -501
  233. empathy_software_plugin/wizards/pattern_extraction_wizard.py +0 -422
  234. empathy_software_plugin/wizards/pattern_retriever_wizard.py +0 -400
  235. empathy_software_plugin/wizards/performance/__init__.py +0 -9
  236. empathy_software_plugin/wizards/performance/bottleneck_detector.py +0 -221
  237. empathy_software_plugin/wizards/performance/profiler_parsers.py +0 -278
  238. empathy_software_plugin/wizards/performance/trajectory_analyzer.py +0 -429
  239. empathy_software_plugin/wizards/performance_profiling_wizard.py +0 -305
  240. empathy_software_plugin/wizards/prompt_engineering_wizard.py +0 -425
  241. empathy_software_plugin/wizards/rag_pattern_wizard.py +0 -461
  242. empathy_software_plugin/wizards/security/__init__.py +0 -32
  243. empathy_software_plugin/wizards/security/exploit_analyzer.py +0 -290
  244. empathy_software_plugin/wizards/security/owasp_patterns.py +0 -241
  245. empathy_software_plugin/wizards/security/vulnerability_scanner.py +0 -604
  246. empathy_software_plugin/wizards/security_analysis_wizard.py +0 -322
  247. empathy_software_plugin/wizards/security_learning_wizard.py +0 -740
  248. empathy_software_plugin/wizards/tech_debt_wizard.py +0 -726
  249. empathy_software_plugin/wizards/testing/__init__.py +0 -27
  250. empathy_software_plugin/wizards/testing/coverage_analyzer.py +0 -459
  251. empathy_software_plugin/wizards/testing/quality_analyzer.py +0 -525
  252. empathy_software_plugin/wizards/testing/test_suggester.py +0 -533
  253. empathy_software_plugin/wizards/testing_wizard.py +0 -274
  254. wizards/__init__.py +0 -82
  255. wizards/admission_assessment_wizard.py +0 -644
  256. wizards/care_plan.py +0 -321
  257. wizards/clinical_assessment.py +0 -769
  258. wizards/discharge_planning.py +0 -77
  259. wizards/discharge_summary_wizard.py +0 -468
  260. wizards/dosage_calculation.py +0 -497
  261. wizards/incident_report_wizard.py +0 -454
  262. wizards/medication_reconciliation.py +0 -85
  263. wizards/nursing_assessment.py +0 -171
  264. wizards/patient_education.py +0 -654
  265. wizards/quality_improvement.py +0 -705
  266. wizards/sbar_report.py +0 -324
  267. wizards/sbar_wizard.py +0 -608
  268. wizards/shift_handoff_wizard.py +0 -535
  269. wizards/soap_note_wizard.py +0 -679
  270. wizards/treatment_plan.py +0 -15
  271. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/WHEEL +0 -0
  272. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/entry_points.txt +0 -0
  273. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,644 +0,0 @@
1
- """
2
- Admission Assessment Wizard Router - AI Nurse Florence
3
- Following Wizard Pattern Implementation from SOAP and Shift Handoff wizards
4
-
5
- Structured patient admission workflow for comprehensive initial assessment.
6
- Based on evidence-based nursing admission assessment standards.
7
- """
8
-
9
- import logging
10
- from datetime import datetime
11
- from typing import Any
12
- from uuid import uuid4
13
-
14
- from fastapi import APIRouter, HTTPException, status
15
- from src.services import get_service
16
- from src.utils.api_responses import create_success_response
17
- from src.utils.config import get_settings
18
-
19
- logger = logging.getLogger(__name__)
20
-
21
- # Conditional translation import
22
- try:
23
- from src.services.translation_service import translate_text
24
-
25
- _has_translation = True
26
- except ImportError:
27
- _has_translation = False
28
-
29
- async def translate_text(
30
- text: str,
31
- target_language: str,
32
- source_language: str = "en",
33
- context: str = "medical",
34
- ):
35
- return {"translated_text": text, "success": False}
36
-
37
-
38
- # Settings following coding instructions
39
- settings = get_settings()
40
-
41
- router = APIRouter(
42
- prefix="/wizards/admission-assessment",
43
- tags=["clinical-wizards"],
44
- responses={
45
- 404: {"description": "Wizard session not found"},
46
- 422: {"description": "Invalid wizard step data"},
47
- 500: {"description": "Wizard processing error"},
48
- },
49
- )
50
-
51
- # Session storage (Redis in production, memory for development)
52
- try:
53
- from src.utils.redis_cache import get_redis_client
54
-
55
- _has_redis = True
56
- except ImportError:
57
- _has_redis = False
58
-
59
- _wizard_sessions: dict[str, dict[str, Any]] = {}
60
-
61
-
62
- # Admission assessment wizard steps
63
- ADMISSION_ASSESSMENT_STEPS = {
64
- 1: {
65
- "step": 1,
66
- "title": "Patient Demographics & Chief Complaint",
67
- "prompt": "Gather patient identification and reason for admission",
68
- "fields": [
69
- "patient_name",
70
- "date_of_birth",
71
- "gender",
72
- "admission_date",
73
- "chief_complaint",
74
- "referring_provider",
75
- ],
76
- "help_text": "Start with basic patient information and primary reason for admission",
77
- },
78
- 2: {
79
- "step": 2,
80
- "title": "Medical History & Medications",
81
- "prompt": "Document past medical history and current medications",
82
- "fields": [
83
- "past_medical_history",
84
- "past_surgical_history",
85
- "current_medications",
86
- "allergies",
87
- "immunization_status",
88
- "family_history",
89
- ],
90
- "help_text": "Include chronic conditions, previous surgeries, all medications, allergies, and relevant family history",
91
- },
92
- 3: {
93
- "step": 3,
94
- "title": "Review of Systems",
95
- "prompt": "Conduct comprehensive systems review",
96
- "fields": [
97
- "cardiovascular",
98
- "respiratory",
99
- "gastrointestinal",
100
- "genitourinary",
101
- "neurological",
102
- "musculoskeletal",
103
- "integumentary",
104
- "psychosocial",
105
- ],
106
- "help_text": "Document findings for each body system. Note any abnormalities or patient concerns.",
107
- },
108
- 4: {
109
- "step": 4,
110
- "title": "Physical Assessment & Vital Signs",
111
- "prompt": "Record initial physical examination and vital signs",
112
- "fields": [
113
- "vital_signs",
114
- "height_weight",
115
- "general_appearance",
116
- "physical_exam_findings",
117
- "pain_assessment",
118
- "fall_risk_score",
119
- ],
120
- "help_text": "Include complete vital signs, measurements, general appearance, and initial physical findings",
121
- },
122
- 5: {
123
- "step": 5,
124
- "title": "Psychosocial & Discharge Planning",
125
- "prompt": "Assess psychosocial factors and begin discharge planning",
126
- "fields": [
127
- "living_situation",
128
- "support_system",
129
- "advance_directives",
130
- "code_status",
131
- "barriers_to_care",
132
- "discharge_planning_needs",
133
- ],
134
- "help_text": "Document living situation, support systems, advance care planning, and anticipated discharge needs",
135
- },
136
- 6: {
137
- "step": 6,
138
- "title": "Initial Care Plan & Orders",
139
- "prompt": "Establish initial nursing care plan and verify orders",
140
- "fields": [
141
- "nursing_diagnoses",
142
- "care_priorities",
143
- "patient_goals",
144
- "pending_orders",
145
- "patient_education_needs",
146
- "follow_up_required",
147
- ],
148
- "help_text": "Identify nursing diagnoses, set priorities, establish patient-centered goals, and note education needs",
149
- },
150
- 7: {
151
- "step": 7,
152
- "title": "Review & Finalize",
153
- "prompt": "Review your admission assessment and finalize the document",
154
- "fields": ["review_complete", "user_approved"],
155
- "help_text": "Review all sections of the admission assessment. Click 'Generate Preview' to see the formatted assessment. You can go back to edit any section before finalizing.",
156
- "is_review_step": True,
157
- },
158
- }
159
-
160
-
161
- # Educational banner for all admission assessment outputs
162
- EDU_BANNER = """
163
- ⚕️ EDUCATIONAL TOOL NOTICE ⚕️
164
- This admission assessment wizard is an educational tool for healthcare professionals.
165
- All clinical assessments should be reviewed and validated by qualified providers.
166
- Never rely solely on automated tools for clinical decision-making or documentation.
167
- """
168
-
169
-
170
- async def _store_wizard_session(wizard_id: str, session_data: dict[str, Any]) -> bool:
171
- """Store wizard session in Redis (preferred) or memory (fallback)"""
172
- try:
173
- if _has_redis:
174
- redis_client = await get_redis_client()
175
- if redis_client:
176
- import json
177
-
178
- cache_key = f"wizard:admission_assessment:{wizard_id}"
179
- await redis_client.setex(
180
- cache_key, 7200, json.dumps(session_data) # 2 hour TTL - FIXED: use JSON
181
- )
182
- logger.info(f"Stored admission assessment wizard session {wizard_id} in Redis")
183
- return True
184
- except Exception as e:
185
- logger.warning(f"Failed to store session in Redis: {e}, using memory fallback")
186
-
187
- # Memory fallback
188
- _wizard_sessions[wizard_id] = session_data
189
- logger.info(f"Stored admission assessment wizard session {wizard_id} in memory")
190
- return True
191
-
192
-
193
- async def _get_wizard_session(wizard_id: str) -> dict[str, Any] | None:
194
- """Retrieve wizard session from Redis (preferred) or memory (fallback)"""
195
- try:
196
- if _has_redis:
197
- redis_client = await get_redis_client()
198
- if redis_client:
199
- import json
200
-
201
- cache_key = f"wizard:admission_assessment:{wizard_id}"
202
- session_str = await redis_client.get(cache_key)
203
- if session_str:
204
- # SECURITY FIX: Use json.loads() instead of ast.literal_eval()
205
- return json.loads(session_str)
206
- except Exception as e:
207
- logger.warning(f"Failed to retrieve session from Redis: {e}, checking memory")
208
-
209
- # Memory fallback
210
- return _wizard_sessions.get(wizard_id)
211
-
212
-
213
- def _get_step_data(step: int) -> dict[str, Any]:
214
- """Get step configuration data"""
215
- if step not in ADMISSION_ASSESSMENT_STEPS:
216
- raise HTTPException(
217
- status_code=status.HTTP_400_BAD_REQUEST,
218
- detail=f"Invalid step number: {step}",
219
- )
220
-
221
- step_config = ADMISSION_ASSESSMENT_STEPS[step]
222
- return {
223
- "step": step,
224
- "title": step_config["title"],
225
- "prompt": step_config["prompt"],
226
- "fields": step_config["fields"],
227
- "help_text": step_config["help_text"],
228
- }
229
-
230
-
231
- def _generate_admission_assessment_report(collected_data: dict[str, Any]) -> dict[str, Any]:
232
- """Generate final admission assessment report from collected data"""
233
-
234
- # Generate formatted narrative
235
- narrative = f"""
236
- ADMISSION ASSESSMENT
237
- Date: {collected_data.get('admission_date', datetime.now().strftime('%Y-%m-%d %H:%M'))}
238
-
239
- PATIENT DEMOGRAPHICS
240
- Name: {collected_data.get('patient_name', 'Not documented')}
241
- Date of Birth: {collected_data.get('date_of_birth', 'Not documented')}
242
- Gender: {collected_data.get('gender', 'Not documented')}
243
- Chief Complaint: {collected_data.get('chief_complaint', 'Not documented')}
244
- Referring Provider: {collected_data.get('referring_provider', 'Not documented')}
245
-
246
- MEDICAL HISTORY
247
- Past Medical History: {collected_data.get('past_medical_history', 'Not documented')}
248
- Past Surgical History: {collected_data.get('past_surgical_history', 'Not documented')}
249
- Current Medications: {collected_data.get('current_medications', 'Not documented')}
250
- Allergies: {collected_data.get('allergies', 'NKDA')}
251
- Immunizations: {collected_data.get('immunization_status', 'Not documented')}
252
- Family History: {collected_data.get('family_history', 'Not documented')}
253
-
254
- REVIEW OF SYSTEMS
255
- Cardiovascular: {collected_data.get('cardiovascular', 'Not documented')}
256
- Respiratory: {collected_data.get('respiratory', 'Not documented')}
257
- Gastrointestinal: {collected_data.get('gastrointestinal', 'Not documented')}
258
- Genitourinary: {collected_data.get('genitourinary', 'Not documented')}
259
- Neurological: {collected_data.get('neurological', 'Not documented')}
260
- Musculoskeletal: {collected_data.get('musculoskeletal', 'Not documented')}
261
- Integumentary: {collected_data.get('integumentary', 'Not documented')}
262
- Psychosocial: {collected_data.get('psychosocial', 'Not documented')}
263
-
264
- PHYSICAL ASSESSMENT
265
- Vital Signs: {collected_data.get('vital_signs', 'Not documented')}
266
- Height/Weight: {collected_data.get('height_weight', 'Not documented')}
267
- General Appearance: {collected_data.get('general_appearance', 'Not documented')}
268
- Physical Exam: {collected_data.get('physical_exam_findings', 'Not documented')}
269
- Pain Assessment: {collected_data.get('pain_assessment', 'Not documented')}
270
- Fall Risk Score: {collected_data.get('fall_risk_score', 'Not assessed')}
271
-
272
- PSYCHOSOCIAL & DISCHARGE PLANNING
273
- Living Situation: {collected_data.get('living_situation', 'Not documented')}
274
- Support System: {collected_data.get('support_system', 'Not documented')}
275
- Advance Directives: {collected_data.get('advance_directives', 'Not documented')}
276
- Code Status: {collected_data.get('code_status', 'Not documented')}
277
- Barriers to Care: {collected_data.get('barriers_to_care', 'None identified')}
278
- Discharge Planning Needs: {collected_data.get('discharge_planning_needs', 'Not documented')}
279
-
280
- INITIAL CARE PLAN
281
- Nursing Diagnoses: {collected_data.get('nursing_diagnoses', 'Not documented')}
282
- Care Priorities: {collected_data.get('care_priorities', 'Not documented')}
283
- Patient Goals: {collected_data.get('patient_goals', 'Not documented')}
284
- Pending Orders: {collected_data.get('pending_orders', 'None noted')}
285
- Patient Education Needs: {collected_data.get('patient_education_needs', 'Not documented')}
286
- Follow-up Required: {collected_data.get('follow_up_required', 'Not documented')}
287
-
288
- Completed by: [Nurse Name]
289
- Date/Time: {datetime.now().strftime('%Y-%m-%d %H:%M')}
290
- """
291
-
292
- return {
293
- "admission_assessment": collected_data,
294
- "narrative": narrative.strip(),
295
- "metadata": {
296
- "generated_at": datetime.now().isoformat(),
297
- "admission_date": collected_data.get(
298
- "admission_date", datetime.now().strftime("%Y-%m-%d %H:%M")
299
- ),
300
- "wizard_type": "admission_assessment",
301
- },
302
- "banner": EDU_BANNER,
303
- }
304
-
305
-
306
- @router.post("/start", summary="Start Admission Assessment Wizard")
307
- async def start_admission_assessment_wizard():
308
- """
309
- Initialize a new admission assessment documentation wizard session.
310
-
311
- Admission assessment is the comprehensive initial evaluation performed
312
- when a patient is admitted to a healthcare facility.
313
-
314
- Returns a wizard session ID and first step configuration.
315
- """
316
- try:
317
- wizard_id = str(uuid4())
318
-
319
- session_data = {
320
- "wizard_id": wizard_id,
321
- "wizard_type": "admission_assessment",
322
- "current_step": 1,
323
- "total_steps": 7,
324
- "collected_data": {},
325
- "created_at": datetime.now().isoformat(),
326
- "updated_at": datetime.now().isoformat(),
327
- }
328
-
329
- # Store session
330
- await _store_wizard_session(wizard_id, session_data)
331
-
332
- # Get first step data
333
- step_data = _get_step_data(1)
334
-
335
- response_data = {
336
- "wizard_session": session_data,
337
- "current_step": step_data,
338
- "progress": {"current": 1, "total": 6, "percentage": 17},
339
- "banner": EDU_BANNER,
340
- }
341
-
342
- return create_success_response(
343
- data=response_data,
344
- message="Admission assessment wizard started successfully",
345
- )
346
-
347
- except Exception as e:
348
- logger.error(f"Failed to start admission assessment wizard: {e}")
349
- raise HTTPException(
350
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
351
- detail=f"Failed to start admission assessment wizard: {str(e)}",
352
- )
353
-
354
-
355
- @router.post("/{wizard_id}/step", summary="Submit admission assessment wizard step")
356
- async def submit_admission_assessment_step(wizard_id: str, step_data: dict[str, Any]):
357
- """
358
- Submit data for current step and advance to next step.
359
-
360
- The wizard will validate the data, store it, and either:
361
- - Return the next step configuration (if more steps remain)
362
- - Return the complete admission assessment report (if all steps completed)
363
- """
364
- try:
365
- # Retrieve session
366
- session = await _get_wizard_session(wizard_id)
367
- if not session:
368
- raise HTTPException(
369
- status_code=status.HTTP_404_NOT_FOUND,
370
- detail=f"Wizard session {wizard_id} not found",
371
- )
372
-
373
- current_step = session["current_step"]
374
- total_steps = session["total_steps"]
375
-
376
- # Validate step number
377
- submitted_step = step_data.get("step", current_step)
378
- if submitted_step != current_step:
379
- raise HTTPException(
380
- status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
381
- detail=f"Expected step {current_step}, got step {submitted_step}",
382
- )
383
-
384
- # Store submitted data
385
- session["collected_data"].update(step_data.get("data", {}))
386
- session["updated_at"] = datetime.now().isoformat()
387
-
388
- # Advance to next step (but don't auto-complete, even on final step)
389
- if current_step < total_steps:
390
- next_step = current_step + 1
391
- session["current_step"] = next_step
392
- else:
393
- # On review step - stay on same step, don't auto-complete
394
- next_step = current_step
395
-
396
- await _store_wizard_session(wizard_id, session)
397
-
398
- # Get next step configuration
399
- next_step_data = _get_step_data(next_step)
400
-
401
- response_data = {
402
- "wizard_session": session,
403
- "current_step": next_step_data,
404
- "progress": {
405
- "current": next_step,
406
- "total": total_steps,
407
- "percentage": int((next_step / total_steps) * 100),
408
- },
409
- }
410
-
411
- return create_success_response(
412
- data=response_data,
413
- message=f"Step {current_step} completed, moved to step {next_step}",
414
- )
415
-
416
- except HTTPException:
417
- raise
418
- except Exception as e:
419
- logger.error(f"Failed to process admission assessment wizard step: {e}")
420
- raise HTTPException(
421
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
422
- detail=f"Failed to process wizard step: {str(e)}",
423
- )
424
-
425
-
426
- @router.post("/{wizard_id}/enhance", summary="Enhance admission assessment text with AI")
427
- async def enhance_admission_assessment_text(wizard_id: str, text_data: dict[str, Any]):
428
- """
429
- Enhance user-provided text with AI to improve clinical documentation quality.
430
-
431
- Uses the chat service to refine language, add clinical terminology,
432
- and improve clarity while preserving the original meaning.
433
- """
434
- try:
435
- # Verify wizard session exists
436
- session = await _get_wizard_session(wizard_id)
437
- if not session:
438
- raise HTTPException(
439
- status_code=status.HTTP_404_NOT_FOUND,
440
- detail=f"Wizard session {wizard_id} not found",
441
- )
442
-
443
- original_text = text_data.get("text", "")
444
- field_name = text_data.get("field", "text")
445
-
446
- if not original_text:
447
- raise HTTPException(
448
- status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
449
- detail="No text provided for enhancement",
450
- )
451
-
452
- # Get chat service
453
- chat_service = get_service("chat")
454
-
455
- # Create enhancement prompt
456
- enhancement_prompt = f"""
457
- You are assisting with admission assessment documentation. Please enhance the following text
458
- to be more professional and clinically appropriate while preserving the original meaning:
459
-
460
- Field: {field_name}
461
- Original text: {original_text}
462
-
463
- Please provide an enhanced version that:
464
- - Uses appropriate clinical terminology
465
- - Is clear and concise
466
- - Maintains professional tone
467
- - Preserves all key information
468
- - Follows nursing admission assessment documentation standards
469
-
470
- Enhanced text:"""
471
-
472
- # Call chat service for enhancement
473
- chat_response = await chat_service.chat(
474
- message=enhancement_prompt,
475
- conversation_id=f"admission_enhance_{wizard_id}",
476
- context={"wizard_id": wizard_id, "field": field_name},
477
- )
478
-
479
- enhanced_text = chat_response.get("response", original_text)
480
-
481
- response_data = {
482
- "original_text": original_text,
483
- "enhanced_text": enhanced_text,
484
- "field": field_name,
485
- }
486
-
487
- return create_success_response(data=response_data, message="Text enhanced successfully")
488
-
489
- except HTTPException:
490
- raise
491
- except Exception as e:
492
- logger.error(f"Failed to enhance admission assessment text: {e}")
493
- raise HTTPException(
494
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
495
- detail=f"Failed to enhance text: {str(e)}",
496
- )
497
-
498
-
499
- @router.post("/{wizard_id}/preview", summary="Preview admission assessment report")
500
- async def preview_admission_assessment_report(wizard_id: str):
501
- """
502
- Generate preview of admission assessment report without finalizing.
503
-
504
- This endpoint allows users to see the formatted admission assessment before
505
- finalizing it. The report is NOT marked as complete. Users can
506
- still go back and edit data after previewing.
507
- """
508
- try:
509
- session = await _get_wizard_session(wizard_id)
510
- if not session:
511
- raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Session not found")
512
-
513
- # Verify user is on review step
514
- if session["current_step"] != session["total_steps"]:
515
- raise HTTPException(
516
- status_code=status.HTTP_400_BAD_REQUEST,
517
- detail=f"Not on review step. Complete steps 1-{session['total_steps']-1} first.",
518
- )
519
-
520
- # Generate preview report (does NOT mark as complete)
521
- preview_report = _generate_admission_assessment_report(session["collected_data"])
522
-
523
- # Store preview in session
524
- session["preview_report"] = preview_report
525
- session["preview_generated_at"] = datetime.now().isoformat()
526
- await _store_wizard_session(wizard_id, session)
527
-
528
- response_data = {
529
- "preview": preview_report,
530
- "wizard_session": session,
531
- "message": "Review the admission assessment above. Click 'Finalize Report' to save, or go back to edit any section.",
532
- }
533
-
534
- return create_success_response(data=response_data, message="Preview generated successfully")
535
-
536
- except HTTPException:
537
- raise
538
- except Exception as e:
539
- raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
540
-
541
-
542
- @router.post("/{wizard_id}/save", summary="Finalize admission assessment report")
543
- async def save_admission_assessment_report(wizard_id: str, approval_data: dict[str, Any]):
544
- """
545
- Finalize and save the admission assessment report after user review and approval.
546
-
547
- Requires that the user has:
548
- 1. Generated a preview first (/preview endpoint)
549
- 2. Explicitly approved the report (user_approved: true)
550
-
551
- Only after calling this endpoint is the report marked as complete.
552
- """
553
- try:
554
- session = await _get_wizard_session(wizard_id)
555
- if not session:
556
- raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Session not found")
557
-
558
- # Verify preview was generated
559
- if "preview_report" not in session:
560
- raise HTTPException(
561
- status_code=status.HTTP_400_BAD_REQUEST,
562
- detail="Must generate preview before saving. Call /preview endpoint first.",
563
- )
564
-
565
- # Verify user explicitly approved
566
- if not approval_data.get("user_approved", False):
567
- raise HTTPException(
568
- status_code=status.HTTP_400_BAD_REQUEST,
569
- detail="User approval required. Set 'user_approved': true in request body.",
570
- )
571
-
572
- # NOW we mark as complete
573
- session["completed"] = True
574
- session["completed_at"] = datetime.now().isoformat()
575
- session["final_report"] = session["preview_report"]
576
- session["user_approved"] = True
577
-
578
- await _store_wizard_session(wizard_id, session)
579
-
580
- response_data = {
581
- "wizard_session": session,
582
- "report": session["final_report"],
583
- "completed": True,
584
- }
585
-
586
- return create_success_response(
587
- data=response_data, message="Admission assessment finalized successfully"
588
- )
589
-
590
- except HTTPException:
591
- raise
592
- except Exception as e:
593
- raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
594
-
595
-
596
- @router.get("/{wizard_id}/report", summary="Get admission assessment report")
597
- async def get_admission_assessment_report(wizard_id: str):
598
- """
599
- Retrieve the completed admission assessment report.
600
-
601
- Only available after all wizard steps have been completed.
602
- Returns the structured assessment data and formatted narrative.
603
- """
604
- try:
605
- # Retrieve session
606
- session = await _get_wizard_session(wizard_id)
607
- if not session:
608
- raise HTTPException(
609
- status_code=status.HTTP_404_NOT_FOUND,
610
- detail=f"Wizard session {wizard_id} not found",
611
- )
612
-
613
- # Check if completed
614
- if not session.get("completed", False):
615
- raise HTTPException(
616
- status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
617
- detail="Admission assessment wizard not yet completed. Complete all steps first.",
618
- )
619
-
620
- # Generate report
621
- report = _generate_admission_assessment_report(session["collected_data"])
622
-
623
- response_data = {
624
- "wizard_session": session,
625
- "report": report,
626
- }
627
-
628
- return create_success_response(
629
- data=response_data,
630
- message="Admission assessment report retrieved successfully",
631
- )
632
-
633
- except HTTPException:
634
- raise
635
- except Exception as e:
636
- logger.error(f"Failed to retrieve admission assessment report: {e}")
637
- raise HTTPException(
638
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
639
- detail=f"Failed to retrieve report: {str(e)}",
640
- )
641
-
642
-
643
- # Export router
644
- __all__ = ["router"]