empathy-framework 2.4.0__py3-none-any.whl → 3.8.2__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.
- coach_wizards/__init__.py +13 -12
- coach_wizards/accessibility_wizard.py +12 -12
- coach_wizards/api_wizard.py +12 -12
- coach_wizards/base_wizard.py +26 -20
- coach_wizards/cicd_wizard.py +15 -13
- coach_wizards/code_reviewer_README.md +60 -0
- coach_wizards/code_reviewer_wizard.py +180 -0
- coach_wizards/compliance_wizard.py +12 -12
- coach_wizards/database_wizard.py +12 -12
- coach_wizards/debugging_wizard.py +12 -12
- coach_wizards/documentation_wizard.py +12 -12
- coach_wizards/generate_wizards.py +1 -2
- coach_wizards/localization_wizard.py +101 -19
- coach_wizards/migration_wizard.py +12 -12
- coach_wizards/monitoring_wizard.py +12 -12
- coach_wizards/observability_wizard.py +12 -12
- coach_wizards/performance_wizard.py +12 -12
- coach_wizards/prompt_engineering_wizard.py +661 -0
- coach_wizards/refactoring_wizard.py +12 -12
- coach_wizards/scaling_wizard.py +12 -12
- coach_wizards/security_wizard.py +12 -12
- coach_wizards/testing_wizard.py +12 -12
- empathy_framework-3.8.2.dist-info/METADATA +1176 -0
- empathy_framework-3.8.2.dist-info/RECORD +333 -0
- empathy_framework-3.8.2.dist-info/entry_points.txt +22 -0
- {empathy_framework-2.4.0.dist-info → empathy_framework-3.8.2.dist-info}/top_level.txt +5 -1
- empathy_healthcare_plugin/__init__.py +1 -2
- empathy_healthcare_plugin/monitors/__init__.py +9 -0
- empathy_healthcare_plugin/monitors/clinical_protocol_monitor.py +315 -0
- empathy_healthcare_plugin/monitors/monitoring/__init__.py +44 -0
- empathy_healthcare_plugin/monitors/monitoring/protocol_checker.py +300 -0
- empathy_healthcare_plugin/monitors/monitoring/protocol_loader.py +214 -0
- empathy_healthcare_plugin/monitors/monitoring/sensor_parsers.py +306 -0
- empathy_healthcare_plugin/monitors/monitoring/trajectory_analyzer.py +389 -0
- empathy_llm_toolkit/__init__.py +7 -7
- empathy_llm_toolkit/agent_factory/__init__.py +53 -0
- empathy_llm_toolkit/agent_factory/adapters/__init__.py +85 -0
- empathy_llm_toolkit/agent_factory/adapters/autogen_adapter.py +312 -0
- empathy_llm_toolkit/agent_factory/adapters/crewai_adapter.py +454 -0
- empathy_llm_toolkit/agent_factory/adapters/haystack_adapter.py +298 -0
- empathy_llm_toolkit/agent_factory/adapters/langchain_adapter.py +362 -0
- empathy_llm_toolkit/agent_factory/adapters/langgraph_adapter.py +333 -0
- empathy_llm_toolkit/agent_factory/adapters/native.py +228 -0
- empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +426 -0
- empathy_llm_toolkit/agent_factory/base.py +305 -0
- empathy_llm_toolkit/agent_factory/crews/__init__.py +67 -0
- empathy_llm_toolkit/agent_factory/crews/code_review.py +1113 -0
- empathy_llm_toolkit/agent_factory/crews/health_check.py +1246 -0
- empathy_llm_toolkit/agent_factory/crews/refactoring.py +1128 -0
- empathy_llm_toolkit/agent_factory/crews/security_audit.py +1018 -0
- empathy_llm_toolkit/agent_factory/decorators.py +286 -0
- empathy_llm_toolkit/agent_factory/factory.py +558 -0
- empathy_llm_toolkit/agent_factory/framework.py +192 -0
- empathy_llm_toolkit/agent_factory/memory_integration.py +324 -0
- empathy_llm_toolkit/agent_factory/resilient.py +320 -0
- empathy_llm_toolkit/claude_memory.py +14 -15
- empathy_llm_toolkit/cli/__init__.py +8 -0
- empathy_llm_toolkit/cli/sync_claude.py +487 -0
- empathy_llm_toolkit/code_health.py +186 -28
- empathy_llm_toolkit/config/__init__.py +29 -0
- empathy_llm_toolkit/config/unified.py +295 -0
- empathy_llm_toolkit/contextual_patterns.py +11 -12
- empathy_llm_toolkit/core.py +168 -53
- empathy_llm_toolkit/git_pattern_extractor.py +17 -13
- empathy_llm_toolkit/levels.py +6 -13
- empathy_llm_toolkit/pattern_confidence.py +14 -18
- empathy_llm_toolkit/pattern_resolver.py +10 -12
- empathy_llm_toolkit/pattern_summary.py +16 -14
- empathy_llm_toolkit/providers.py +194 -28
- empathy_llm_toolkit/routing/__init__.py +32 -0
- empathy_llm_toolkit/routing/model_router.py +362 -0
- empathy_llm_toolkit/security/IMPLEMENTATION_SUMMARY.md +413 -0
- empathy_llm_toolkit/security/PHASE2_COMPLETE.md +384 -0
- empathy_llm_toolkit/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
- empathy_llm_toolkit/security/QUICK_REFERENCE.md +316 -0
- empathy_llm_toolkit/security/README.md +262 -0
- empathy_llm_toolkit/security/__init__.py +62 -0
- empathy_llm_toolkit/security/audit_logger.py +929 -0
- empathy_llm_toolkit/security/audit_logger_example.py +152 -0
- empathy_llm_toolkit/security/pii_scrubber.py +640 -0
- empathy_llm_toolkit/security/secrets_detector.py +678 -0
- empathy_llm_toolkit/security/secrets_detector_example.py +304 -0
- empathy_llm_toolkit/security/secure_memdocs.py +1192 -0
- empathy_llm_toolkit/security/secure_memdocs_example.py +278 -0
- empathy_llm_toolkit/session_status.py +20 -22
- empathy_llm_toolkit/state.py +28 -21
- empathy_llm_toolkit/wizards/__init__.py +38 -0
- empathy_llm_toolkit/wizards/base_wizard.py +364 -0
- empathy_llm_toolkit/wizards/customer_support_wizard.py +190 -0
- empathy_llm_toolkit/wizards/healthcare_wizard.py +362 -0
- empathy_llm_toolkit/wizards/patient_assessment_README.md +64 -0
- empathy_llm_toolkit/wizards/patient_assessment_wizard.py +193 -0
- empathy_llm_toolkit/wizards/technology_wizard.py +194 -0
- empathy_os/__init__.py +125 -84
- empathy_os/adaptive/__init__.py +13 -0
- empathy_os/adaptive/task_complexity.py +127 -0
- empathy_os/{monitoring.py → agent_monitoring.py} +28 -28
- empathy_os/cache/__init__.py +117 -0
- empathy_os/cache/base.py +166 -0
- empathy_os/cache/dependency_manager.py +253 -0
- empathy_os/cache/hash_only.py +248 -0
- empathy_os/cache/hybrid.py +390 -0
- empathy_os/cache/storage.py +282 -0
- empathy_os/cli.py +1516 -70
- empathy_os/cli_unified.py +597 -0
- empathy_os/config/__init__.py +63 -0
- empathy_os/config/xml_config.py +239 -0
- empathy_os/config.py +95 -37
- empathy_os/coordination.py +72 -68
- empathy_os/core.py +94 -107
- empathy_os/cost_tracker.py +74 -55
- empathy_os/dashboard/__init__.py +15 -0
- empathy_os/dashboard/server.py +743 -0
- empathy_os/discovery.py +17 -14
- empathy_os/emergence.py +21 -22
- empathy_os/exceptions.py +18 -30
- empathy_os/feedback_loops.py +30 -33
- empathy_os/levels.py +32 -35
- empathy_os/leverage_points.py +31 -32
- empathy_os/logging_config.py +19 -16
- empathy_os/memory/__init__.py +195 -0
- empathy_os/memory/claude_memory.py +466 -0
- empathy_os/memory/config.py +224 -0
- empathy_os/memory/control_panel.py +1298 -0
- empathy_os/memory/edges.py +179 -0
- empathy_os/memory/graph.py +567 -0
- empathy_os/memory/long_term.py +1194 -0
- empathy_os/memory/nodes.py +179 -0
- empathy_os/memory/redis_bootstrap.py +540 -0
- empathy_os/memory/security/__init__.py +31 -0
- empathy_os/memory/security/audit_logger.py +930 -0
- empathy_os/memory/security/pii_scrubber.py +640 -0
- empathy_os/memory/security/secrets_detector.py +678 -0
- empathy_os/memory/short_term.py +2119 -0
- empathy_os/memory/storage/__init__.py +15 -0
- empathy_os/memory/summary_index.py +583 -0
- empathy_os/memory/unified.py +619 -0
- empathy_os/metrics/__init__.py +12 -0
- empathy_os/metrics/prompt_metrics.py +190 -0
- empathy_os/models/__init__.py +136 -0
- empathy_os/models/__main__.py +13 -0
- empathy_os/models/cli.py +655 -0
- empathy_os/models/empathy_executor.py +354 -0
- empathy_os/models/executor.py +252 -0
- empathy_os/models/fallback.py +671 -0
- empathy_os/models/provider_config.py +563 -0
- empathy_os/models/registry.py +382 -0
- empathy_os/models/tasks.py +302 -0
- empathy_os/models/telemetry.py +548 -0
- empathy_os/models/token_estimator.py +378 -0
- empathy_os/models/validation.py +274 -0
- empathy_os/monitoring/__init__.py +52 -0
- empathy_os/monitoring/alerts.py +23 -0
- empathy_os/monitoring/alerts_cli.py +268 -0
- empathy_os/monitoring/multi_backend.py +271 -0
- empathy_os/monitoring/otel_backend.py +363 -0
- empathy_os/optimization/__init__.py +19 -0
- empathy_os/optimization/context_optimizer.py +272 -0
- empathy_os/pattern_library.py +30 -29
- empathy_os/persistence.py +35 -37
- empathy_os/platform_utils.py +261 -0
- empathy_os/plugins/__init__.py +28 -0
- empathy_os/plugins/base.py +361 -0
- empathy_os/plugins/registry.py +268 -0
- empathy_os/project_index/__init__.py +30 -0
- empathy_os/project_index/cli.py +335 -0
- empathy_os/project_index/crew_integration.py +430 -0
- empathy_os/project_index/index.py +425 -0
- empathy_os/project_index/models.py +501 -0
- empathy_os/project_index/reports.py +473 -0
- empathy_os/project_index/scanner.py +538 -0
- empathy_os/prompts/__init__.py +61 -0
- empathy_os/prompts/config.py +77 -0
- empathy_os/prompts/context.py +177 -0
- empathy_os/prompts/parser.py +285 -0
- empathy_os/prompts/registry.py +313 -0
- empathy_os/prompts/templates.py +208 -0
- empathy_os/redis_config.py +144 -58
- empathy_os/redis_memory.py +79 -77
- empathy_os/resilience/__init__.py +56 -0
- empathy_os/resilience/circuit_breaker.py +256 -0
- empathy_os/resilience/fallback.py +179 -0
- empathy_os/resilience/health.py +300 -0
- empathy_os/resilience/retry.py +209 -0
- empathy_os/resilience/timeout.py +135 -0
- empathy_os/routing/__init__.py +43 -0
- empathy_os/routing/chain_executor.py +433 -0
- empathy_os/routing/classifier.py +217 -0
- empathy_os/routing/smart_router.py +234 -0
- empathy_os/routing/wizard_registry.py +307 -0
- empathy_os/templates.py +19 -14
- empathy_os/trust/__init__.py +28 -0
- empathy_os/trust/circuit_breaker.py +579 -0
- empathy_os/trust_building.py +67 -58
- empathy_os/validation/__init__.py +19 -0
- empathy_os/validation/xml_validator.py +281 -0
- empathy_os/wizard_factory_cli.py +170 -0
- empathy_os/{workflows.py → workflow_commands.py} +131 -37
- empathy_os/workflows/__init__.py +360 -0
- empathy_os/workflows/base.py +1660 -0
- empathy_os/workflows/bug_predict.py +962 -0
- empathy_os/workflows/code_review.py +960 -0
- empathy_os/workflows/code_review_adapters.py +310 -0
- empathy_os/workflows/code_review_pipeline.py +720 -0
- empathy_os/workflows/config.py +600 -0
- empathy_os/workflows/dependency_check.py +648 -0
- empathy_os/workflows/document_gen.py +1069 -0
- empathy_os/workflows/documentation_orchestrator.py +1205 -0
- empathy_os/workflows/health_check.py +679 -0
- empathy_os/workflows/keyboard_shortcuts/__init__.py +39 -0
- empathy_os/workflows/keyboard_shortcuts/generators.py +386 -0
- empathy_os/workflows/keyboard_shortcuts/parsers.py +414 -0
- empathy_os/workflows/keyboard_shortcuts/prompts.py +295 -0
- empathy_os/workflows/keyboard_shortcuts/schema.py +193 -0
- empathy_os/workflows/keyboard_shortcuts/workflow.py +505 -0
- empathy_os/workflows/manage_documentation.py +804 -0
- empathy_os/workflows/new_sample_workflow1.py +146 -0
- empathy_os/workflows/new_sample_workflow1_README.md +150 -0
- empathy_os/workflows/perf_audit.py +687 -0
- empathy_os/workflows/pr_review.py +748 -0
- empathy_os/workflows/progress.py +445 -0
- empathy_os/workflows/progress_server.py +322 -0
- empathy_os/workflows/refactor_plan.py +693 -0
- empathy_os/workflows/release_prep.py +808 -0
- empathy_os/workflows/research_synthesis.py +404 -0
- empathy_os/workflows/secure_release.py +585 -0
- empathy_os/workflows/security_adapters.py +297 -0
- empathy_os/workflows/security_audit.py +1046 -0
- empathy_os/workflows/step_config.py +234 -0
- empathy_os/workflows/test5.py +125 -0
- empathy_os/workflows/test5_README.md +158 -0
- empathy_os/workflows/test_gen.py +1855 -0
- empathy_os/workflows/test_lifecycle.py +526 -0
- empathy_os/workflows/test_maintenance.py +626 -0
- empathy_os/workflows/test_maintenance_cli.py +590 -0
- empathy_os/workflows/test_maintenance_crew.py +821 -0
- empathy_os/workflows/xml_enhanced_crew.py +285 -0
- empathy_software_plugin/__init__.py +1 -2
- empathy_software_plugin/cli/__init__.py +120 -0
- empathy_software_plugin/cli/inspect.py +362 -0
- empathy_software_plugin/cli.py +49 -27
- empathy_software_plugin/plugin.py +4 -8
- empathy_software_plugin/wizards/__init__.py +42 -0
- empathy_software_plugin/wizards/advanced_debugging_wizard.py +392 -0
- empathy_software_plugin/wizards/agent_orchestration_wizard.py +511 -0
- empathy_software_plugin/wizards/ai_collaboration_wizard.py +503 -0
- empathy_software_plugin/wizards/ai_context_wizard.py +441 -0
- empathy_software_plugin/wizards/ai_documentation_wizard.py +503 -0
- empathy_software_plugin/wizards/base_wizard.py +288 -0
- empathy_software_plugin/wizards/book_chapter_wizard.py +519 -0
- empathy_software_plugin/wizards/code_review_wizard.py +606 -0
- empathy_software_plugin/wizards/debugging/__init__.py +50 -0
- empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +414 -0
- empathy_software_plugin/wizards/debugging/config_loaders.py +442 -0
- empathy_software_plugin/wizards/debugging/fix_applier.py +469 -0
- empathy_software_plugin/wizards/debugging/language_patterns.py +383 -0
- empathy_software_plugin/wizards/debugging/linter_parsers.py +470 -0
- empathy_software_plugin/wizards/debugging/verification.py +369 -0
- empathy_software_plugin/wizards/enhanced_testing_wizard.py +537 -0
- empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +816 -0
- empathy_software_plugin/wizards/multi_model_wizard.py +501 -0
- empathy_software_plugin/wizards/pattern_extraction_wizard.py +422 -0
- empathy_software_plugin/wizards/pattern_retriever_wizard.py +400 -0
- empathy_software_plugin/wizards/performance/__init__.py +9 -0
- empathy_software_plugin/wizards/performance/bottleneck_detector.py +221 -0
- empathy_software_plugin/wizards/performance/profiler_parsers.py +278 -0
- empathy_software_plugin/wizards/performance/trajectory_analyzer.py +429 -0
- empathy_software_plugin/wizards/performance_profiling_wizard.py +305 -0
- empathy_software_plugin/wizards/prompt_engineering_wizard.py +425 -0
- empathy_software_plugin/wizards/rag_pattern_wizard.py +461 -0
- empathy_software_plugin/wizards/security/__init__.py +32 -0
- empathy_software_plugin/wizards/security/exploit_analyzer.py +290 -0
- empathy_software_plugin/wizards/security/owasp_patterns.py +241 -0
- empathy_software_plugin/wizards/security/vulnerability_scanner.py +604 -0
- empathy_software_plugin/wizards/security_analysis_wizard.py +322 -0
- empathy_software_plugin/wizards/security_learning_wizard.py +740 -0
- empathy_software_plugin/wizards/tech_debt_wizard.py +726 -0
- empathy_software_plugin/wizards/testing/__init__.py +27 -0
- empathy_software_plugin/wizards/testing/coverage_analyzer.py +459 -0
- empathy_software_plugin/wizards/testing/quality_analyzer.py +531 -0
- empathy_software_plugin/wizards/testing/test_suggester.py +533 -0
- empathy_software_plugin/wizards/testing_wizard.py +274 -0
- hot_reload/README.md +473 -0
- hot_reload/__init__.py +62 -0
- hot_reload/config.py +84 -0
- hot_reload/integration.py +228 -0
- hot_reload/reloader.py +298 -0
- hot_reload/watcher.py +179 -0
- hot_reload/websocket.py +176 -0
- scaffolding/README.md +589 -0
- scaffolding/__init__.py +35 -0
- scaffolding/__main__.py +14 -0
- scaffolding/cli.py +240 -0
- test_generator/__init__.py +38 -0
- test_generator/__main__.py +14 -0
- test_generator/cli.py +226 -0
- test_generator/generator.py +325 -0
- test_generator/risk_analyzer.py +216 -0
- workflow_patterns/__init__.py +33 -0
- workflow_patterns/behavior.py +249 -0
- workflow_patterns/core.py +76 -0
- workflow_patterns/output.py +99 -0
- workflow_patterns/registry.py +255 -0
- workflow_patterns/structural.py +288 -0
- workflow_scaffolding/__init__.py +11 -0
- workflow_scaffolding/__main__.py +12 -0
- workflow_scaffolding/cli.py +206 -0
- workflow_scaffolding/generator.py +265 -0
- agents/code_inspection/patterns/inspection/recurring_B112.json +0 -18
- agents/code_inspection/patterns/inspection/recurring_F541.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_FORMAT.json +0 -25
- agents/code_inspection/patterns/inspection/recurring_bug_20250822_def456.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20250915_abc123.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_3c5b9951.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_97c0f72f.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_a0871d53.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_a9b6ec41.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_null_001.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_builtin.json +0 -16
- agents/compliance_anticipation_agent.py +0 -1427
- agents/epic_integration_wizard.py +0 -541
- agents/trust_building_behaviors.py +0 -891
- empathy_framework-2.4.0.dist-info/METADATA +0 -485
- empathy_framework-2.4.0.dist-info/RECORD +0 -102
- empathy_framework-2.4.0.dist-info/entry_points.txt +0 -6
- empathy_llm_toolkit/htmlcov/status.json +0 -1
- empathy_llm_toolkit/security/htmlcov/status.json +0 -1
- {empathy_framework-2.4.0.dist-info → empathy_framework-3.8.2.dist-info}/WHEEL +0 -0
- {empathy_framework-2.4.0.dist-info → empathy_framework-3.8.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,541 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Epic Integration Wizard - LangChain Agent
|
|
3
|
-
Multi-step wizard for configuring and testing Epic FHIR integration
|
|
4
|
-
|
|
5
|
-
Copyright 2025 Smart AI Memory, LLC
|
|
6
|
-
|
|
7
|
-
Licensed under Fair Source 0.9 (the "License");
|
|
8
|
-
you may not use this file except in compliance with the License.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
import logging
|
|
12
|
-
import operator
|
|
13
|
-
from collections.abc import Sequence
|
|
14
|
-
from datetime import datetime
|
|
15
|
-
from typing import Annotated, TypedDict
|
|
16
|
-
|
|
17
|
-
from langchain_core.messages import AIMessage, BaseMessage
|
|
18
|
-
from langgraph.graph import END, StateGraph
|
|
19
|
-
|
|
20
|
-
logger = logging.getLogger(__name__)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# =============================================================================
|
|
24
|
-
# Wizard State Management
|
|
25
|
-
# =============================================================================
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class WizardState(TypedDict):
|
|
29
|
-
"""
|
|
30
|
-
State for Epic Integration Wizard
|
|
31
|
-
|
|
32
|
-
Tracks all wizard steps, user inputs, validation results, and progress.
|
|
33
|
-
Microsoft-style linear progression with validation at each step.
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
|
-
# Wizard Progress
|
|
37
|
-
current_step: int # 1-7
|
|
38
|
-
completed_steps: list[int]
|
|
39
|
-
messages: Annotated[Sequence[BaseMessage], operator.add]
|
|
40
|
-
|
|
41
|
-
# Step 1: Prerequisites
|
|
42
|
-
prerequisites_checked: bool
|
|
43
|
-
prerequisites_passed: bool
|
|
44
|
-
missing_prerequisites: list[str]
|
|
45
|
-
|
|
46
|
-
# Step 2: Epic Credentials
|
|
47
|
-
epic_client_id: str
|
|
48
|
-
epic_client_secret: str
|
|
49
|
-
epic_fhir_base_url: str
|
|
50
|
-
epic_oauth_token_url: str
|
|
51
|
-
epic_sandbox_mode: bool
|
|
52
|
-
|
|
53
|
-
# Step 3: Connection Test
|
|
54
|
-
connection_test_passed: bool
|
|
55
|
-
connection_test_error: str
|
|
56
|
-
oauth_token_obtained: bool
|
|
57
|
-
|
|
58
|
-
# Step 4: Resource Permissions
|
|
59
|
-
selected_resources: list[str] # Patient, Condition, MedicationRequest, etc.
|
|
60
|
-
resource_scopes: list[str] # Patient.Read, Condition.Read, etc.
|
|
61
|
-
|
|
62
|
-
# Step 5: Test Patient Lookup
|
|
63
|
-
test_mrn: str
|
|
64
|
-
patient_data_retrieved: bool
|
|
65
|
-
patient_test_error: str
|
|
66
|
-
retrieved_patient_name: str
|
|
67
|
-
|
|
68
|
-
# Step 6: Review & Confirm
|
|
69
|
-
configuration_confirmed: bool
|
|
70
|
-
|
|
71
|
-
# Step 7: Complete
|
|
72
|
-
integration_activated: bool
|
|
73
|
-
activation_timestamp: str
|
|
74
|
-
|
|
75
|
-
# Error Handling
|
|
76
|
-
errors: list[str]
|
|
77
|
-
warnings: list[str]
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def create_initial_state() -> WizardState:
|
|
81
|
-
"""Create initial wizard state"""
|
|
82
|
-
return WizardState(
|
|
83
|
-
current_step=1,
|
|
84
|
-
completed_steps=[],
|
|
85
|
-
messages=[],
|
|
86
|
-
prerequisites_checked=False,
|
|
87
|
-
prerequisites_passed=False,
|
|
88
|
-
missing_prerequisites=[],
|
|
89
|
-
epic_client_id="",
|
|
90
|
-
epic_client_secret="",
|
|
91
|
-
epic_fhir_base_url="",
|
|
92
|
-
epic_oauth_token_url="",
|
|
93
|
-
epic_sandbox_mode=True,
|
|
94
|
-
connection_test_passed=False,
|
|
95
|
-
connection_test_error="",
|
|
96
|
-
oauth_token_obtained=False,
|
|
97
|
-
selected_resources=[],
|
|
98
|
-
resource_scopes=[],
|
|
99
|
-
test_mrn="",
|
|
100
|
-
patient_data_retrieved=False,
|
|
101
|
-
patient_test_error="",
|
|
102
|
-
retrieved_patient_name="",
|
|
103
|
-
configuration_confirmed=False,
|
|
104
|
-
integration_activated=False,
|
|
105
|
-
activation_timestamp="",
|
|
106
|
-
errors=[],
|
|
107
|
-
warnings=[],
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
# =============================================================================
|
|
112
|
-
# Wizard Nodes (Step Handlers)
|
|
113
|
-
# =============================================================================
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
async def step_1_prerequisites(state: WizardState) -> WizardState:
|
|
117
|
-
"""
|
|
118
|
-
Step 1: Check Prerequisites
|
|
119
|
-
|
|
120
|
-
Validates system readiness:
|
|
121
|
-
- Python version
|
|
122
|
-
- Required packages installed
|
|
123
|
-
- Environment variables configured
|
|
124
|
-
- Database connectivity
|
|
125
|
-
"""
|
|
126
|
-
logger.info("Step 1: Checking prerequisites")
|
|
127
|
-
|
|
128
|
-
missing = []
|
|
129
|
-
|
|
130
|
-
# Check required environment variables
|
|
131
|
-
import os
|
|
132
|
-
|
|
133
|
-
required_env_vars = ["OPENAI_API_KEY", "SECRET_KEY"]
|
|
134
|
-
for var in required_env_vars:
|
|
135
|
-
if not os.getenv(var):
|
|
136
|
-
missing.append(f"Environment variable: {var}")
|
|
137
|
-
|
|
138
|
-
# Check database (simplified for now)
|
|
139
|
-
try:
|
|
140
|
-
from src.config import settings
|
|
141
|
-
|
|
142
|
-
if not settings.database_url:
|
|
143
|
-
missing.append("Database configuration")
|
|
144
|
-
except Exception as e:
|
|
145
|
-
missing.append(f"Configuration error: {str(e)}")
|
|
146
|
-
|
|
147
|
-
state["prerequisites_checked"] = True
|
|
148
|
-
state["prerequisites_passed"] = len(missing) == 0
|
|
149
|
-
state["missing_prerequisites"] = missing
|
|
150
|
-
state["completed_steps"].append(1)
|
|
151
|
-
|
|
152
|
-
# Always allow proceeding to Step 2 for manual credential entry
|
|
153
|
-
# Even if automated prerequisites fail, user can still configure Epic manually
|
|
154
|
-
if state["prerequisites_passed"]:
|
|
155
|
-
state["messages"].append(
|
|
156
|
-
AIMessage(content="✅ All prerequisites met. Ready to configure Epic integration.")
|
|
157
|
-
)
|
|
158
|
-
else:
|
|
159
|
-
# Don't block progression - just warn user
|
|
160
|
-
state["warnings"].append(f"Some automated prerequisites missing: {', '.join(missing)}")
|
|
161
|
-
state["messages"].append(AIMessage(content=f"⚠️ Manual entry mode: {', '.join(missing)}"))
|
|
162
|
-
|
|
163
|
-
return state
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
async def step_2_credentials(state: WizardState) -> WizardState:
|
|
167
|
-
"""
|
|
168
|
-
Step 2: Epic Credentials Input
|
|
169
|
-
|
|
170
|
-
Collects and validates:
|
|
171
|
-
- Epic Client ID
|
|
172
|
-
- Epic Client Secret
|
|
173
|
-
- FHIR Base URL
|
|
174
|
-
- OAuth Token URL
|
|
175
|
-
- Sandbox mode flag
|
|
176
|
-
"""
|
|
177
|
-
logger.info("Step 2: Collecting Epic credentials")
|
|
178
|
-
|
|
179
|
-
# Validate credentials are provided
|
|
180
|
-
if not state.get("epic_client_id") or not state.get("epic_client_secret"):
|
|
181
|
-
state["errors"].append("Epic credentials required")
|
|
182
|
-
return state
|
|
183
|
-
|
|
184
|
-
if not state.get("epic_fhir_base_url"):
|
|
185
|
-
state["errors"].append("Epic FHIR base URL required")
|
|
186
|
-
return state
|
|
187
|
-
|
|
188
|
-
# Validate URL format
|
|
189
|
-
if not state["epic_fhir_base_url"].startswith("https://"):
|
|
190
|
-
state["warnings"].append("Epic FHIR URL should use HTTPS for security")
|
|
191
|
-
|
|
192
|
-
state["completed_steps"].append(2)
|
|
193
|
-
state["current_step"] = 3
|
|
194
|
-
state["messages"].append(
|
|
195
|
-
AIMessage(content="✅ Epic credentials collected. Ready to test connection.")
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
return state
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
async def step_3_connection_test(state: WizardState) -> WizardState:
|
|
202
|
-
"""
|
|
203
|
-
Step 3: Test Epic FHIR Connection
|
|
204
|
-
|
|
205
|
-
Validates:
|
|
206
|
-
- OAuth token can be obtained
|
|
207
|
-
- FHIR endpoint is reachable
|
|
208
|
-
- Credentials are valid
|
|
209
|
-
"""
|
|
210
|
-
logger.info("Step 3: Testing Epic FHIR connection")
|
|
211
|
-
|
|
212
|
-
try:
|
|
213
|
-
# Import Epic client
|
|
214
|
-
from src.integrations.epic_fhir_client import OAuthManager
|
|
215
|
-
|
|
216
|
-
# Create OAuth manager
|
|
217
|
-
oauth_manager = OAuthManager(
|
|
218
|
-
token_url=state["epic_oauth_token_url"],
|
|
219
|
-
client_id=state["epic_client_id"],
|
|
220
|
-
client_secret=state["epic_client_secret"],
|
|
221
|
-
)
|
|
222
|
-
|
|
223
|
-
# Attempt to get token
|
|
224
|
-
try:
|
|
225
|
-
await oauth_manager.get_access_token()
|
|
226
|
-
state["oauth_token_obtained"] = True
|
|
227
|
-
state["connection_test_passed"] = True
|
|
228
|
-
state["messages"].append(
|
|
229
|
-
AIMessage(content="✅ Successfully connected to Epic FHIR API")
|
|
230
|
-
)
|
|
231
|
-
except Exception as e:
|
|
232
|
-
state["connection_test_error"] = str(e)
|
|
233
|
-
state["connection_test_passed"] = False
|
|
234
|
-
state["errors"].append(f"OAuth token request failed: {str(e)}")
|
|
235
|
-
state["messages"].append(AIMessage(content=f"❌ Connection failed: {str(e)}"))
|
|
236
|
-
return state
|
|
237
|
-
|
|
238
|
-
state["completed_steps"].append(3)
|
|
239
|
-
state["current_step"] = 4
|
|
240
|
-
|
|
241
|
-
except Exception as e:
|
|
242
|
-
logger.error(f"Connection test failed: {e}", exc_info=True)
|
|
243
|
-
state["connection_test_error"] = str(e)
|
|
244
|
-
state["connection_test_passed"] = False
|
|
245
|
-
state["errors"].append(f"Connection test error: {str(e)}")
|
|
246
|
-
|
|
247
|
-
return state
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
async def step_4_resource_permissions(state: WizardState) -> WizardState:
|
|
251
|
-
"""
|
|
252
|
-
Step 4: Select FHIR Resources and Scopes
|
|
253
|
-
|
|
254
|
-
User selects which FHIR resources to enable:
|
|
255
|
-
- Patient (demographics)
|
|
256
|
-
- Condition (diagnoses)
|
|
257
|
-
- MedicationRequest (medications)
|
|
258
|
-
- Observation (vitals, labs)
|
|
259
|
-
- DocumentReference (clinical notes)
|
|
260
|
-
"""
|
|
261
|
-
logger.info("Step 4: Configuring resource permissions")
|
|
262
|
-
|
|
263
|
-
# Validate at least one resource is selected
|
|
264
|
-
if not state.get("selected_resources"):
|
|
265
|
-
state["errors"].append("At least one FHIR resource must be selected")
|
|
266
|
-
return state
|
|
267
|
-
|
|
268
|
-
# Map resources to OAuth scopes
|
|
269
|
-
resource_scope_map = {
|
|
270
|
-
"Patient": "Patient.Read",
|
|
271
|
-
"Condition": "Condition.Read",
|
|
272
|
-
"MedicationRequest": "MedicationRequest.Read",
|
|
273
|
-
"Observation": "Observation.Read",
|
|
274
|
-
"DocumentReference": "DocumentReference.Write",
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
scopes = [
|
|
278
|
-
resource_scope_map[resource]
|
|
279
|
-
for resource in state["selected_resources"]
|
|
280
|
-
if resource in resource_scope_map
|
|
281
|
-
]
|
|
282
|
-
|
|
283
|
-
state["resource_scopes"] = scopes
|
|
284
|
-
state["completed_steps"].append(4)
|
|
285
|
-
state["current_step"] = 5
|
|
286
|
-
state["messages"].append(
|
|
287
|
-
AIMessage(content=f"✅ Configured {len(scopes)} resource permissions: {', '.join(scopes)}")
|
|
288
|
-
)
|
|
289
|
-
|
|
290
|
-
return state
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
async def step_5_test_patient_lookup(state: WizardState) -> WizardState:
|
|
294
|
-
"""
|
|
295
|
-
Step 5: Test Patient Lookup
|
|
296
|
-
|
|
297
|
-
Validates end-to-end functionality:
|
|
298
|
-
- Search patient by MRN
|
|
299
|
-
- Retrieve patient demographics
|
|
300
|
-
- Fetch related resources (conditions, medications)
|
|
301
|
-
"""
|
|
302
|
-
logger.info("Step 5: Testing patient lookup")
|
|
303
|
-
|
|
304
|
-
if not state.get("test_mrn"):
|
|
305
|
-
state["errors"].append("Test MRN required for patient lookup")
|
|
306
|
-
return state
|
|
307
|
-
|
|
308
|
-
try:
|
|
309
|
-
from src.integrations.epic_fhir_client import EpicFHIRClient, OAuthManager
|
|
310
|
-
|
|
311
|
-
# Create Epic client
|
|
312
|
-
oauth_manager = OAuthManager(
|
|
313
|
-
token_url=state["epic_oauth_token_url"],
|
|
314
|
-
client_id=state["epic_client_id"],
|
|
315
|
-
client_secret=state["epic_client_secret"],
|
|
316
|
-
)
|
|
317
|
-
|
|
318
|
-
epic_client = EpicFHIRClient(
|
|
319
|
-
base_url=state["epic_fhir_base_url"], oauth_manager=oauth_manager
|
|
320
|
-
)
|
|
321
|
-
|
|
322
|
-
# Search for patient
|
|
323
|
-
search_result = await epic_client.get(
|
|
324
|
-
"/Patient",
|
|
325
|
-
params={"identifier": f"urn:oid:1.2.840.114350|{state['test_mrn']}"},
|
|
326
|
-
)
|
|
327
|
-
|
|
328
|
-
if search_result.get("total", 0) > 0:
|
|
329
|
-
patient = search_result["entry"][0]["resource"]
|
|
330
|
-
patient_name = f"{patient['name'][0]['given'][0]} {patient['name'][0]['family']}"
|
|
331
|
-
|
|
332
|
-
state["patient_data_retrieved"] = True
|
|
333
|
-
state["retrieved_patient_name"] = patient_name
|
|
334
|
-
state["messages"].append(
|
|
335
|
-
AIMessage(content=f"✅ Successfully retrieved patient: {patient_name}")
|
|
336
|
-
)
|
|
337
|
-
else:
|
|
338
|
-
state["patient_test_error"] = "Patient not found"
|
|
339
|
-
state["errors"].append(f"Patient with MRN {state['test_mrn']} not found")
|
|
340
|
-
state["messages"].append(
|
|
341
|
-
AIMessage(content=f"❌ Patient not found: MRN {state['test_mrn']}")
|
|
342
|
-
)
|
|
343
|
-
return state
|
|
344
|
-
|
|
345
|
-
state["completed_steps"].append(5)
|
|
346
|
-
state["current_step"] = 6
|
|
347
|
-
|
|
348
|
-
except Exception as e:
|
|
349
|
-
logger.error(f"Patient lookup failed: {e}", exc_info=True)
|
|
350
|
-
state["patient_test_error"] = str(e)
|
|
351
|
-
state["errors"].append(f"Patient lookup error: {str(e)}")
|
|
352
|
-
state["messages"].append(AIMessage(content=f"❌ Patient lookup failed: {str(e)}"))
|
|
353
|
-
|
|
354
|
-
return state
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
async def step_6_review_confirm(state: WizardState) -> WizardState:
|
|
358
|
-
"""
|
|
359
|
-
Step 6: Review and Confirm Configuration
|
|
360
|
-
|
|
361
|
-
Shows summary of all settings for final review:
|
|
362
|
-
- Epic endpoint and credentials
|
|
363
|
-
- Enabled resources
|
|
364
|
-
- Test results
|
|
365
|
-
"""
|
|
366
|
-
logger.info("Step 6: Review and confirm configuration")
|
|
367
|
-
|
|
368
|
-
if not state.get("configuration_confirmed"):
|
|
369
|
-
# User hasn't confirmed yet - show summary
|
|
370
|
-
summary = f"""
|
|
371
|
-
**Epic Integration Configuration Summary**
|
|
372
|
-
|
|
373
|
-
**Connection:**
|
|
374
|
-
- FHIR Endpoint: {state["epic_fhir_base_url"]}
|
|
375
|
-
- Sandbox Mode: {"Yes" if state["epic_sandbox_mode"] else "No"}
|
|
376
|
-
- Connection Test: {"✅ Passed" if state["connection_test_passed"] else "❌ Failed"}
|
|
377
|
-
|
|
378
|
-
**Resources Enabled:**
|
|
379
|
-
{chr(10).join(f"- {resource}" for resource in state["selected_resources"])}
|
|
380
|
-
|
|
381
|
-
**Test Results:**
|
|
382
|
-
- Patient Lookup: {"✅ Passed" if state["patient_data_retrieved"] else "❌ Failed"}
|
|
383
|
-
- Test Patient: {state.get("retrieved_patient_name", "N/A")}
|
|
384
|
-
|
|
385
|
-
Please confirm to activate integration.
|
|
386
|
-
"""
|
|
387
|
-
state["messages"].append(AIMessage(content=summary))
|
|
388
|
-
return state
|
|
389
|
-
|
|
390
|
-
state["completed_steps"].append(6)
|
|
391
|
-
state["current_step"] = 7
|
|
392
|
-
state["messages"].append(
|
|
393
|
-
AIMessage(content="✅ Configuration confirmed. Activating integration...")
|
|
394
|
-
)
|
|
395
|
-
|
|
396
|
-
return state
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
async def step_7_complete(state: WizardState) -> WizardState:
|
|
400
|
-
"""
|
|
401
|
-
Step 7: Complete Integration Setup
|
|
402
|
-
|
|
403
|
-
Finalizes configuration:
|
|
404
|
-
- Saves settings to database/config
|
|
405
|
-
- Activates Epic integration mode
|
|
406
|
-
- Generates setup report
|
|
407
|
-
"""
|
|
408
|
-
logger.info("Step 7: Completing Epic integration setup")
|
|
409
|
-
|
|
410
|
-
# Save configuration (simplified - would save to database in production)
|
|
411
|
-
try:
|
|
412
|
-
import os
|
|
413
|
-
|
|
414
|
-
# In production, save to database or config file
|
|
415
|
-
# For now, just set environment variables
|
|
416
|
-
os.environ["EPIC_FHIR_BASE_URL"] = state["epic_fhir_base_url"]
|
|
417
|
-
os.environ["EPIC_CLIENT_ID"] = state["epic_client_id"]
|
|
418
|
-
os.environ["EPIC_CLIENT_SECRET"] = state["epic_client_secret"]
|
|
419
|
-
os.environ["EPIC_OAUTH_TOKEN_URL"] = state["epic_oauth_token_url"]
|
|
420
|
-
|
|
421
|
-
state["integration_activated"] = True
|
|
422
|
-
state["activation_timestamp"] = datetime.utcnow().isoformat()
|
|
423
|
-
state["completed_steps"].append(7)
|
|
424
|
-
|
|
425
|
-
state["messages"].append(
|
|
426
|
-
AIMessage(
|
|
427
|
-
content=f"""
|
|
428
|
-
🎉 **Epic Integration Activated!**
|
|
429
|
-
|
|
430
|
-
Your AI Nurse Florence instance is now connected to Epic EHR.
|
|
431
|
-
|
|
432
|
-
**Activated at:** {state["activation_timestamp"]}
|
|
433
|
-
**Endpoint:** {state["epic_fhir_base_url"]}
|
|
434
|
-
**Resources:** {", ".join(state["selected_resources"])}
|
|
435
|
-
|
|
436
|
-
You can now:
|
|
437
|
-
- Scan patient MRN barcodes
|
|
438
|
-
- Auto-populate SBAR reports with Epic data
|
|
439
|
-
- Generate AI-enhanced care plans using live patient data
|
|
440
|
-
|
|
441
|
-
Next steps:
|
|
442
|
-
1. Train your staff on the Epic integration workflow
|
|
443
|
-
2. Review HIPAA compliance documentation
|
|
444
|
-
3. Monitor integration logs for any issues
|
|
445
|
-
"""
|
|
446
|
-
)
|
|
447
|
-
)
|
|
448
|
-
|
|
449
|
-
except Exception as e:
|
|
450
|
-
logger.error(f"Integration activation failed: {e}", exc_info=True)
|
|
451
|
-
state["errors"].append(f"Activation error: {str(e)}")
|
|
452
|
-
state["messages"].append(AIMessage(content=f"❌ Activation failed: {str(e)}"))
|
|
453
|
-
|
|
454
|
-
return state
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
# =============================================================================
|
|
458
|
-
# Workflow Routing
|
|
459
|
-
# =============================================================================
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
def should_continue(state: WizardState) -> str:
|
|
463
|
-
"""
|
|
464
|
-
Determine next step based on current state
|
|
465
|
-
|
|
466
|
-
Microsoft wizard pattern: linear progression with error handling
|
|
467
|
-
"""
|
|
468
|
-
# Check for blocking errors
|
|
469
|
-
if state.get("errors") and len(state["errors"]) > 0:
|
|
470
|
-
last_error = state["errors"][-1]
|
|
471
|
-
|
|
472
|
-
# Some errors are blocking
|
|
473
|
-
if "prerequisites" in last_error.lower():
|
|
474
|
-
return "prerequisites"
|
|
475
|
-
if "credentials" in last_error.lower():
|
|
476
|
-
return "credentials"
|
|
477
|
-
if "connection" in last_error.lower():
|
|
478
|
-
return "connection_test"
|
|
479
|
-
|
|
480
|
-
# Normal progression
|
|
481
|
-
current_step = state.get("current_step", 1)
|
|
482
|
-
|
|
483
|
-
if current_step == 1:
|
|
484
|
-
return "prerequisites"
|
|
485
|
-
elif current_step == 2:
|
|
486
|
-
return "credentials"
|
|
487
|
-
elif current_step == 3:
|
|
488
|
-
return "connection_test"
|
|
489
|
-
elif current_step == 4:
|
|
490
|
-
return "resource_permissions"
|
|
491
|
-
elif current_step == 5:
|
|
492
|
-
return "test_patient_lookup"
|
|
493
|
-
elif current_step == 6:
|
|
494
|
-
return "review_confirm"
|
|
495
|
-
elif current_step == 7:
|
|
496
|
-
return "complete"
|
|
497
|
-
else:
|
|
498
|
-
return END
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
# =============================================================================
|
|
502
|
-
# LangGraph Workflow
|
|
503
|
-
# =============================================================================
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
def create_epic_wizard_graph():
|
|
507
|
-
"""
|
|
508
|
-
Create LangGraph workflow for Epic Integration Wizard
|
|
509
|
-
|
|
510
|
-
Microsoft-style multi-step wizard:
|
|
511
|
-
Prerequisites → Credentials → Connection Test → Permissions → Patient Test → Review → Complete
|
|
512
|
-
"""
|
|
513
|
-
workflow = StateGraph(WizardState)
|
|
514
|
-
|
|
515
|
-
# Add nodes for each wizard step
|
|
516
|
-
workflow.add_node("prerequisites", step_1_prerequisites)
|
|
517
|
-
workflow.add_node("credentials", step_2_credentials)
|
|
518
|
-
workflow.add_node("connection_test", step_3_connection_test)
|
|
519
|
-
workflow.add_node("resource_permissions", step_4_resource_permissions)
|
|
520
|
-
workflow.add_node("test_patient_lookup", step_5_test_patient_lookup)
|
|
521
|
-
workflow.add_node("review_confirm", step_6_review_confirm)
|
|
522
|
-
workflow.add_node("complete", step_7_complete)
|
|
523
|
-
|
|
524
|
-
# Set entry point
|
|
525
|
-
workflow.set_entry_point("prerequisites")
|
|
526
|
-
|
|
527
|
-
# Add edges - linear progression (Microsoft wizard pattern)
|
|
528
|
-
# Prerequisites → Credentials → Connection Test → Permissions → Patient Test → Review → Complete
|
|
529
|
-
workflow.add_edge("prerequisites", "credentials")
|
|
530
|
-
workflow.add_edge("credentials", "connection_test")
|
|
531
|
-
workflow.add_edge("connection_test", "resource_permissions")
|
|
532
|
-
workflow.add_edge("resource_permissions", "test_patient_lookup")
|
|
533
|
-
workflow.add_edge("test_patient_lookup", "review_confirm")
|
|
534
|
-
workflow.add_edge("review_confirm", "complete")
|
|
535
|
-
workflow.add_edge("complete", END)
|
|
536
|
-
|
|
537
|
-
return workflow.compile()
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
# Create the compiled graph
|
|
541
|
-
epic_wizard_graph = create_epic_wizard_graph()
|