empathy-framework 4.6.6__py3-none-any.whl → 4.7.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 (247) hide show
  1. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/METADATA +7 -6
  2. empathy_framework-4.7.0.dist-info/RECORD +354 -0
  3. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/top_level.txt +0 -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.py +173 -0
  130. empathy_os/workflows/__init__.py +212 -120
  131. empathy_os/workflows/batch_processing.py +8 -24
  132. empathy_os/workflows/bug_predict.py +1 -1
  133. empathy_os/workflows/code_review.py +20 -5
  134. empathy_os/workflows/code_review_pipeline.py +13 -8
  135. empathy_os/workflows/keyboard_shortcuts/workflow.py +6 -2
  136. empathy_os/workflows/manage_documentation.py +1 -0
  137. empathy_os/workflows/orchestrated_health_check.py +6 -11
  138. empathy_os/workflows/orchestrated_release_prep.py +3 -3
  139. empathy_os/workflows/pr_review.py +18 -10
  140. empathy_os/workflows/progressive/__init__.py +2 -12
  141. empathy_os/workflows/progressive/cli.py +14 -37
  142. empathy_os/workflows/progressive/core.py +12 -12
  143. empathy_os/workflows/progressive/orchestrator.py +166 -144
  144. empathy_os/workflows/progressive/reports.py +22 -31
  145. empathy_os/workflows/progressive/telemetry.py +8 -14
  146. empathy_os/workflows/progressive/test_gen.py +29 -48
  147. empathy_os/workflows/progressive/workflow.py +31 -70
  148. empathy_os/workflows/release_prep.py +21 -6
  149. empathy_os/workflows/release_prep_crew.py +1 -0
  150. empathy_os/workflows/secure_release.py +13 -6
  151. empathy_os/workflows/security_audit.py +8 -3
  152. empathy_os/workflows/test_coverage_boost_crew.py +3 -2
  153. empathy_os/workflows/test_maintenance_crew.py +1 -0
  154. empathy_os/workflows/test_runner.py +16 -12
  155. empathy_software_plugin/SOFTWARE_PLUGIN_README.md +25 -703
  156. empathy_software_plugin/cli.py +0 -122
  157. coach_wizards/__init__.py +0 -45
  158. coach_wizards/accessibility_wizard.py +0 -91
  159. coach_wizards/api_wizard.py +0 -91
  160. coach_wizards/base_wizard.py +0 -209
  161. coach_wizards/cicd_wizard.py +0 -91
  162. coach_wizards/code_reviewer_README.md +0 -60
  163. coach_wizards/code_reviewer_wizard.py +0 -180
  164. coach_wizards/compliance_wizard.py +0 -91
  165. coach_wizards/database_wizard.py +0 -91
  166. coach_wizards/debugging_wizard.py +0 -91
  167. coach_wizards/documentation_wizard.py +0 -91
  168. coach_wizards/generate_wizards.py +0 -347
  169. coach_wizards/localization_wizard.py +0 -173
  170. coach_wizards/migration_wizard.py +0 -91
  171. coach_wizards/monitoring_wizard.py +0 -91
  172. coach_wizards/observability_wizard.py +0 -91
  173. coach_wizards/performance_wizard.py +0 -91
  174. coach_wizards/prompt_engineering_wizard.py +0 -661
  175. coach_wizards/refactoring_wizard.py +0 -91
  176. coach_wizards/scaling_wizard.py +0 -90
  177. coach_wizards/security_wizard.py +0 -92
  178. coach_wizards/testing_wizard.py +0 -91
  179. empathy_framework-4.6.6.dist-info/RECORD +0 -410
  180. empathy_llm_toolkit/wizards/__init__.py +0 -43
  181. empathy_llm_toolkit/wizards/base_wizard.py +0 -364
  182. empathy_llm_toolkit/wizards/customer_support_wizard.py +0 -190
  183. empathy_llm_toolkit/wizards/healthcare_wizard.py +0 -378
  184. empathy_llm_toolkit/wizards/patient_assessment_README.md +0 -64
  185. empathy_llm_toolkit/wizards/patient_assessment_wizard.py +0 -193
  186. empathy_llm_toolkit/wizards/technology_wizard.py +0 -209
  187. empathy_os/wizard_factory_cli.py +0 -170
  188. empathy_software_plugin/wizards/__init__.py +0 -42
  189. empathy_software_plugin/wizards/advanced_debugging_wizard.py +0 -395
  190. empathy_software_plugin/wizards/agent_orchestration_wizard.py +0 -511
  191. empathy_software_plugin/wizards/ai_collaboration_wizard.py +0 -503
  192. empathy_software_plugin/wizards/ai_context_wizard.py +0 -441
  193. empathy_software_plugin/wizards/ai_documentation_wizard.py +0 -503
  194. empathy_software_plugin/wizards/base_wizard.py +0 -288
  195. empathy_software_plugin/wizards/book_chapter_wizard.py +0 -519
  196. empathy_software_plugin/wizards/code_review_wizard.py +0 -604
  197. empathy_software_plugin/wizards/debugging/__init__.py +0 -50
  198. empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +0 -414
  199. empathy_software_plugin/wizards/debugging/config_loaders.py +0 -446
  200. empathy_software_plugin/wizards/debugging/fix_applier.py +0 -469
  201. empathy_software_plugin/wizards/debugging/language_patterns.py +0 -385
  202. empathy_software_plugin/wizards/debugging/linter_parsers.py +0 -470
  203. empathy_software_plugin/wizards/debugging/verification.py +0 -369
  204. empathy_software_plugin/wizards/enhanced_testing_wizard.py +0 -537
  205. empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +0 -816
  206. empathy_software_plugin/wizards/multi_model_wizard.py +0 -501
  207. empathy_software_plugin/wizards/pattern_extraction_wizard.py +0 -422
  208. empathy_software_plugin/wizards/pattern_retriever_wizard.py +0 -400
  209. empathy_software_plugin/wizards/performance/__init__.py +0 -9
  210. empathy_software_plugin/wizards/performance/bottleneck_detector.py +0 -221
  211. empathy_software_plugin/wizards/performance/profiler_parsers.py +0 -278
  212. empathy_software_plugin/wizards/performance/trajectory_analyzer.py +0 -429
  213. empathy_software_plugin/wizards/performance_profiling_wizard.py +0 -305
  214. empathy_software_plugin/wizards/prompt_engineering_wizard.py +0 -425
  215. empathy_software_plugin/wizards/rag_pattern_wizard.py +0 -461
  216. empathy_software_plugin/wizards/security/__init__.py +0 -32
  217. empathy_software_plugin/wizards/security/exploit_analyzer.py +0 -290
  218. empathy_software_plugin/wizards/security/owasp_patterns.py +0 -241
  219. empathy_software_plugin/wizards/security/vulnerability_scanner.py +0 -604
  220. empathy_software_plugin/wizards/security_analysis_wizard.py +0 -322
  221. empathy_software_plugin/wizards/security_learning_wizard.py +0 -740
  222. empathy_software_plugin/wizards/tech_debt_wizard.py +0 -726
  223. empathy_software_plugin/wizards/testing/__init__.py +0 -27
  224. empathy_software_plugin/wizards/testing/coverage_analyzer.py +0 -459
  225. empathy_software_plugin/wizards/testing/quality_analyzer.py +0 -525
  226. empathy_software_plugin/wizards/testing/test_suggester.py +0 -533
  227. empathy_software_plugin/wizards/testing_wizard.py +0 -274
  228. wizards/__init__.py +0 -82
  229. wizards/admission_assessment_wizard.py +0 -644
  230. wizards/care_plan.py +0 -321
  231. wizards/clinical_assessment.py +0 -769
  232. wizards/discharge_planning.py +0 -77
  233. wizards/discharge_summary_wizard.py +0 -468
  234. wizards/dosage_calculation.py +0 -497
  235. wizards/incident_report_wizard.py +0 -454
  236. wizards/medication_reconciliation.py +0 -85
  237. wizards/nursing_assessment.py +0 -171
  238. wizards/patient_education.py +0 -654
  239. wizards/quality_improvement.py +0 -705
  240. wizards/sbar_report.py +0 -324
  241. wizards/sbar_wizard.py +0 -608
  242. wizards/shift_handoff_wizard.py +0 -535
  243. wizards/soap_note_wizard.py +0 -679
  244. wizards/treatment_plan.py +0 -15
  245. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/WHEEL +0 -0
  246. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/entry_points.txt +0 -0
  247. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.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"]