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.
- {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/METADATA +7 -6
- empathy_framework-4.7.0.dist-info/RECORD +354 -0
- {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/top_level.txt +0 -2
- empathy_healthcare_plugin/monitors/monitoring/__init__.py +9 -9
- empathy_llm_toolkit/agent_factory/__init__.py +6 -6
- empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +7 -10
- empathy_llm_toolkit/agents_md/__init__.py +22 -0
- empathy_llm_toolkit/agents_md/loader.py +218 -0
- empathy_llm_toolkit/agents_md/parser.py +271 -0
- empathy_llm_toolkit/agents_md/registry.py +307 -0
- empathy_llm_toolkit/commands/__init__.py +51 -0
- empathy_llm_toolkit/commands/context.py +375 -0
- empathy_llm_toolkit/commands/loader.py +301 -0
- empathy_llm_toolkit/commands/models.py +231 -0
- empathy_llm_toolkit/commands/parser.py +371 -0
- empathy_llm_toolkit/commands/registry.py +429 -0
- empathy_llm_toolkit/config/__init__.py +8 -8
- empathy_llm_toolkit/config/unified.py +3 -7
- empathy_llm_toolkit/context/__init__.py +22 -0
- empathy_llm_toolkit/context/compaction.py +455 -0
- empathy_llm_toolkit/context/manager.py +434 -0
- empathy_llm_toolkit/hooks/__init__.py +24 -0
- empathy_llm_toolkit/hooks/config.py +306 -0
- empathy_llm_toolkit/hooks/executor.py +289 -0
- empathy_llm_toolkit/hooks/registry.py +302 -0
- empathy_llm_toolkit/hooks/scripts/__init__.py +39 -0
- empathy_llm_toolkit/hooks/scripts/evaluate_session.py +201 -0
- empathy_llm_toolkit/hooks/scripts/first_time_init.py +285 -0
- empathy_llm_toolkit/hooks/scripts/pre_compact.py +207 -0
- empathy_llm_toolkit/hooks/scripts/session_end.py +183 -0
- empathy_llm_toolkit/hooks/scripts/session_start.py +163 -0
- empathy_llm_toolkit/hooks/scripts/suggest_compact.py +225 -0
- empathy_llm_toolkit/learning/__init__.py +30 -0
- empathy_llm_toolkit/learning/evaluator.py +438 -0
- empathy_llm_toolkit/learning/extractor.py +514 -0
- empathy_llm_toolkit/learning/storage.py +560 -0
- empathy_llm_toolkit/providers.py +4 -11
- empathy_llm_toolkit/security/__init__.py +17 -17
- empathy_llm_toolkit/utils/tokens.py +2 -5
- empathy_os/__init__.py +202 -70
- empathy_os/cache_monitor.py +5 -3
- empathy_os/cli/__init__.py +11 -55
- empathy_os/cli/__main__.py +29 -15
- empathy_os/cli/commands/inspection.py +21 -12
- empathy_os/cli/commands/memory.py +4 -12
- empathy_os/cli/commands/profiling.py +198 -0
- empathy_os/cli/commands/utilities.py +27 -7
- empathy_os/cli.py +28 -57
- empathy_os/cli_unified.py +525 -1164
- empathy_os/cost_tracker.py +9 -3
- empathy_os/dashboard/server.py +200 -2
- empathy_os/hot_reload/__init__.py +7 -7
- empathy_os/hot_reload/config.py +6 -7
- empathy_os/hot_reload/integration.py +35 -35
- empathy_os/hot_reload/reloader.py +57 -57
- empathy_os/hot_reload/watcher.py +28 -28
- empathy_os/hot_reload/websocket.py +2 -2
- empathy_os/memory/__init__.py +11 -4
- empathy_os/memory/claude_memory.py +1 -1
- empathy_os/memory/cross_session.py +8 -12
- empathy_os/memory/edges.py +6 -6
- empathy_os/memory/file_session.py +770 -0
- empathy_os/memory/graph.py +30 -30
- empathy_os/memory/nodes.py +6 -6
- empathy_os/memory/short_term.py +15 -9
- empathy_os/memory/unified.py +606 -140
- empathy_os/meta_workflows/agent_creator.py +3 -9
- empathy_os/meta_workflows/cli_meta_workflows.py +113 -53
- empathy_os/meta_workflows/form_engine.py +6 -18
- empathy_os/meta_workflows/intent_detector.py +64 -24
- empathy_os/meta_workflows/models.py +3 -1
- empathy_os/meta_workflows/pattern_learner.py +13 -31
- empathy_os/meta_workflows/plan_generator.py +55 -47
- empathy_os/meta_workflows/session_context.py +2 -3
- empathy_os/meta_workflows/workflow.py +20 -51
- empathy_os/models/cli.py +2 -2
- empathy_os/models/tasks.py +1 -2
- empathy_os/models/telemetry.py +4 -1
- empathy_os/models/token_estimator.py +3 -1
- empathy_os/monitoring/alerts.py +938 -9
- empathy_os/monitoring/alerts_cli.py +346 -183
- empathy_os/orchestration/execution_strategies.py +12 -29
- empathy_os/orchestration/pattern_learner.py +20 -26
- empathy_os/orchestration/real_tools.py +6 -15
- empathy_os/platform_utils.py +2 -1
- empathy_os/plugins/__init__.py +2 -2
- empathy_os/plugins/base.py +64 -64
- empathy_os/plugins/registry.py +32 -32
- empathy_os/project_index/index.py +49 -15
- empathy_os/project_index/models.py +1 -2
- empathy_os/project_index/reports.py +1 -1
- empathy_os/project_index/scanner.py +1 -0
- empathy_os/redis_memory.py +10 -7
- empathy_os/resilience/__init__.py +1 -1
- empathy_os/resilience/health.py +10 -10
- empathy_os/routing/__init__.py +7 -7
- empathy_os/routing/chain_executor.py +37 -37
- empathy_os/routing/classifier.py +36 -36
- empathy_os/routing/smart_router.py +40 -40
- empathy_os/routing/{wizard_registry.py → workflow_registry.py} +47 -47
- empathy_os/scaffolding/__init__.py +8 -8
- empathy_os/scaffolding/__main__.py +1 -1
- empathy_os/scaffolding/cli.py +28 -28
- empathy_os/socratic/__init__.py +3 -19
- empathy_os/socratic/ab_testing.py +25 -36
- empathy_os/socratic/blueprint.py +38 -38
- empathy_os/socratic/cli.py +34 -20
- empathy_os/socratic/collaboration.py +30 -28
- empathy_os/socratic/domain_templates.py +9 -1
- empathy_os/socratic/embeddings.py +17 -13
- empathy_os/socratic/engine.py +135 -70
- empathy_os/socratic/explainer.py +70 -60
- empathy_os/socratic/feedback.py +24 -19
- empathy_os/socratic/forms.py +15 -10
- empathy_os/socratic/generator.py +51 -35
- empathy_os/socratic/llm_analyzer.py +25 -23
- empathy_os/socratic/mcp_server.py +99 -159
- empathy_os/socratic/session.py +19 -13
- empathy_os/socratic/storage.py +98 -67
- empathy_os/socratic/success.py +38 -27
- empathy_os/socratic/visual_editor.py +51 -39
- empathy_os/socratic/web_ui.py +99 -66
- empathy_os/telemetry/cli.py +3 -1
- empathy_os/telemetry/usage_tracker.py +1 -3
- empathy_os/test_generator/__init__.py +3 -3
- empathy_os/test_generator/cli.py +28 -28
- empathy_os/test_generator/generator.py +64 -66
- empathy_os/test_generator/risk_analyzer.py +11 -11
- empathy_os/vscode_bridge.py +173 -0
- empathy_os/workflows/__init__.py +212 -120
- empathy_os/workflows/batch_processing.py +8 -24
- empathy_os/workflows/bug_predict.py +1 -1
- empathy_os/workflows/code_review.py +20 -5
- empathy_os/workflows/code_review_pipeline.py +13 -8
- empathy_os/workflows/keyboard_shortcuts/workflow.py +6 -2
- empathy_os/workflows/manage_documentation.py +1 -0
- empathy_os/workflows/orchestrated_health_check.py +6 -11
- empathy_os/workflows/orchestrated_release_prep.py +3 -3
- empathy_os/workflows/pr_review.py +18 -10
- empathy_os/workflows/progressive/__init__.py +2 -12
- empathy_os/workflows/progressive/cli.py +14 -37
- empathy_os/workflows/progressive/core.py +12 -12
- empathy_os/workflows/progressive/orchestrator.py +166 -144
- empathy_os/workflows/progressive/reports.py +22 -31
- empathy_os/workflows/progressive/telemetry.py +8 -14
- empathy_os/workflows/progressive/test_gen.py +29 -48
- empathy_os/workflows/progressive/workflow.py +31 -70
- empathy_os/workflows/release_prep.py +21 -6
- empathy_os/workflows/release_prep_crew.py +1 -0
- empathy_os/workflows/secure_release.py +13 -6
- empathy_os/workflows/security_audit.py +8 -3
- empathy_os/workflows/test_coverage_boost_crew.py +3 -2
- empathy_os/workflows/test_maintenance_crew.py +1 -0
- empathy_os/workflows/test_runner.py +16 -12
- empathy_software_plugin/SOFTWARE_PLUGIN_README.md +25 -703
- empathy_software_plugin/cli.py +0 -122
- coach_wizards/__init__.py +0 -45
- coach_wizards/accessibility_wizard.py +0 -91
- coach_wizards/api_wizard.py +0 -91
- coach_wizards/base_wizard.py +0 -209
- coach_wizards/cicd_wizard.py +0 -91
- coach_wizards/code_reviewer_README.md +0 -60
- coach_wizards/code_reviewer_wizard.py +0 -180
- coach_wizards/compliance_wizard.py +0 -91
- coach_wizards/database_wizard.py +0 -91
- coach_wizards/debugging_wizard.py +0 -91
- coach_wizards/documentation_wizard.py +0 -91
- coach_wizards/generate_wizards.py +0 -347
- coach_wizards/localization_wizard.py +0 -173
- coach_wizards/migration_wizard.py +0 -91
- coach_wizards/monitoring_wizard.py +0 -91
- coach_wizards/observability_wizard.py +0 -91
- coach_wizards/performance_wizard.py +0 -91
- coach_wizards/prompt_engineering_wizard.py +0 -661
- coach_wizards/refactoring_wizard.py +0 -91
- coach_wizards/scaling_wizard.py +0 -90
- coach_wizards/security_wizard.py +0 -92
- coach_wizards/testing_wizard.py +0 -91
- empathy_framework-4.6.6.dist-info/RECORD +0 -410
- empathy_llm_toolkit/wizards/__init__.py +0 -43
- empathy_llm_toolkit/wizards/base_wizard.py +0 -364
- empathy_llm_toolkit/wizards/customer_support_wizard.py +0 -190
- empathy_llm_toolkit/wizards/healthcare_wizard.py +0 -378
- empathy_llm_toolkit/wizards/patient_assessment_README.md +0 -64
- empathy_llm_toolkit/wizards/patient_assessment_wizard.py +0 -193
- empathy_llm_toolkit/wizards/technology_wizard.py +0 -209
- empathy_os/wizard_factory_cli.py +0 -170
- empathy_software_plugin/wizards/__init__.py +0 -42
- empathy_software_plugin/wizards/advanced_debugging_wizard.py +0 -395
- empathy_software_plugin/wizards/agent_orchestration_wizard.py +0 -511
- empathy_software_plugin/wizards/ai_collaboration_wizard.py +0 -503
- empathy_software_plugin/wizards/ai_context_wizard.py +0 -441
- empathy_software_plugin/wizards/ai_documentation_wizard.py +0 -503
- empathy_software_plugin/wizards/base_wizard.py +0 -288
- empathy_software_plugin/wizards/book_chapter_wizard.py +0 -519
- empathy_software_plugin/wizards/code_review_wizard.py +0 -604
- empathy_software_plugin/wizards/debugging/__init__.py +0 -50
- empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +0 -414
- empathy_software_plugin/wizards/debugging/config_loaders.py +0 -446
- empathy_software_plugin/wizards/debugging/fix_applier.py +0 -469
- empathy_software_plugin/wizards/debugging/language_patterns.py +0 -385
- empathy_software_plugin/wizards/debugging/linter_parsers.py +0 -470
- empathy_software_plugin/wizards/debugging/verification.py +0 -369
- empathy_software_plugin/wizards/enhanced_testing_wizard.py +0 -537
- empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +0 -816
- empathy_software_plugin/wizards/multi_model_wizard.py +0 -501
- empathy_software_plugin/wizards/pattern_extraction_wizard.py +0 -422
- empathy_software_plugin/wizards/pattern_retriever_wizard.py +0 -400
- empathy_software_plugin/wizards/performance/__init__.py +0 -9
- empathy_software_plugin/wizards/performance/bottleneck_detector.py +0 -221
- empathy_software_plugin/wizards/performance/profiler_parsers.py +0 -278
- empathy_software_plugin/wizards/performance/trajectory_analyzer.py +0 -429
- empathy_software_plugin/wizards/performance_profiling_wizard.py +0 -305
- empathy_software_plugin/wizards/prompt_engineering_wizard.py +0 -425
- empathy_software_plugin/wizards/rag_pattern_wizard.py +0 -461
- empathy_software_plugin/wizards/security/__init__.py +0 -32
- empathy_software_plugin/wizards/security/exploit_analyzer.py +0 -290
- empathy_software_plugin/wizards/security/owasp_patterns.py +0 -241
- empathy_software_plugin/wizards/security/vulnerability_scanner.py +0 -604
- empathy_software_plugin/wizards/security_analysis_wizard.py +0 -322
- empathy_software_plugin/wizards/security_learning_wizard.py +0 -740
- empathy_software_plugin/wizards/tech_debt_wizard.py +0 -726
- empathy_software_plugin/wizards/testing/__init__.py +0 -27
- empathy_software_plugin/wizards/testing/coverage_analyzer.py +0 -459
- empathy_software_plugin/wizards/testing/quality_analyzer.py +0 -525
- empathy_software_plugin/wizards/testing/test_suggester.py +0 -533
- empathy_software_plugin/wizards/testing_wizard.py +0 -274
- wizards/__init__.py +0 -82
- wizards/admission_assessment_wizard.py +0 -644
- wizards/care_plan.py +0 -321
- wizards/clinical_assessment.py +0 -769
- wizards/discharge_planning.py +0 -77
- wizards/discharge_summary_wizard.py +0 -468
- wizards/dosage_calculation.py +0 -497
- wizards/incident_report_wizard.py +0 -454
- wizards/medication_reconciliation.py +0 -85
- wizards/nursing_assessment.py +0 -171
- wizards/patient_education.py +0 -654
- wizards/quality_improvement.py +0 -705
- wizards/sbar_report.py +0 -324
- wizards/sbar_wizard.py +0 -608
- wizards/shift_handoff_wizard.py +0 -535
- wizards/soap_note_wizard.py +0 -679
- wizards/treatment_plan.py +0 -15
- {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/WHEEL +0 -0
- {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/entry_points.txt +0 -0
- {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"""Dynamic
|
|
1
|
+
"""Dynamic workflow reloader for hot-reload.
|
|
2
2
|
|
|
3
|
-
Handles reloading
|
|
3
|
+
Handles reloading workflow modules without server restart.
|
|
4
4
|
|
|
5
5
|
Copyright 2025 Smart AI Memory, LLC
|
|
6
6
|
Licensed under Fair Source 0.9
|
|
@@ -17,12 +17,12 @@ logger = logging.getLogger(__name__)
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class ReloadResult:
|
|
20
|
-
"""Result of a
|
|
20
|
+
"""Result of a workflow reload operation."""
|
|
21
21
|
|
|
22
22
|
def __init__(
|
|
23
23
|
self,
|
|
24
24
|
success: bool,
|
|
25
|
-
|
|
25
|
+
workflow_id: str,
|
|
26
26
|
message: str,
|
|
27
27
|
error: str | None = None,
|
|
28
28
|
):
|
|
@@ -30,13 +30,13 @@ class ReloadResult:
|
|
|
30
30
|
|
|
31
31
|
Args:
|
|
32
32
|
success: Whether reload succeeded
|
|
33
|
-
|
|
33
|
+
workflow_id: ID of workflow that was reloaded
|
|
34
34
|
message: Status message
|
|
35
35
|
error: Error message if failed
|
|
36
36
|
|
|
37
37
|
"""
|
|
38
38
|
self.success = success
|
|
39
|
-
self.
|
|
39
|
+
self.workflow_id = workflow_id
|
|
40
40
|
self.message = message
|
|
41
41
|
self.error = error
|
|
42
42
|
|
|
@@ -44,19 +44,19 @@ class ReloadResult:
|
|
|
44
44
|
"""Convert to dictionary."""
|
|
45
45
|
return {
|
|
46
46
|
"success": self.success,
|
|
47
|
-
"
|
|
47
|
+
"workflow_id": self.workflow_id,
|
|
48
48
|
"message": self.message,
|
|
49
49
|
"error": self.error,
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
class
|
|
54
|
-
"""Handles dynamic reloading of
|
|
53
|
+
class WorkflowReloader:
|
|
54
|
+
"""Handles dynamic reloading of workflow modules.
|
|
55
55
|
|
|
56
|
-
Supports hot-reload of
|
|
56
|
+
Supports hot-reload of workflows without server restart by:
|
|
57
57
|
1. Unloading old module from sys.modules
|
|
58
58
|
2. Reloading module with importlib
|
|
59
|
-
3. Re-registering
|
|
59
|
+
3. Re-registering workflow with workflow API
|
|
60
60
|
4. Notifying clients via callback
|
|
61
61
|
"""
|
|
62
62
|
|
|
@@ -68,7 +68,7 @@ class WizardReloader:
|
|
|
68
68
|
"""Initialize reloader.
|
|
69
69
|
|
|
70
70
|
Args:
|
|
71
|
-
register_callback: Function to register
|
|
71
|
+
register_callback: Function to register workflow (workflow_id, workflow_class) -> success
|
|
72
72
|
notification_callback: Optional function to notify clients of reload events
|
|
73
73
|
|
|
74
74
|
"""
|
|
@@ -76,18 +76,18 @@ class WizardReloader:
|
|
|
76
76
|
self.notification_callback = notification_callback
|
|
77
77
|
self._reload_count = 0
|
|
78
78
|
|
|
79
|
-
def
|
|
80
|
-
"""Reload a
|
|
79
|
+
def reload_workflow(self, workflow_id: str, file_path: str) -> ReloadResult:
|
|
80
|
+
"""Reload a workflow module.
|
|
81
81
|
|
|
82
82
|
Args:
|
|
83
|
-
|
|
84
|
-
file_path: Path to
|
|
83
|
+
workflow_id: Workflow identifier
|
|
84
|
+
file_path: Path to workflow file
|
|
85
85
|
|
|
86
86
|
Returns:
|
|
87
87
|
ReloadResult with outcome
|
|
88
88
|
|
|
89
89
|
"""
|
|
90
|
-
logger.info(f"Attempting to reload
|
|
90
|
+
logger.info(f"Attempting to reload workflow: {workflow_id} from {file_path}")
|
|
91
91
|
|
|
92
92
|
try:
|
|
93
93
|
# Get module name from file path
|
|
@@ -97,7 +97,7 @@ class WizardReloader:
|
|
|
97
97
|
logger.error(error_msg)
|
|
98
98
|
return ReloadResult(
|
|
99
99
|
success=False,
|
|
100
|
-
|
|
100
|
+
workflow_id=workflow_id,
|
|
101
101
|
message="Failed to reload",
|
|
102
102
|
error=error_msg,
|
|
103
103
|
)
|
|
@@ -111,60 +111,60 @@ class WizardReloader:
|
|
|
111
111
|
except ImportError as e:
|
|
112
112
|
error_msg = f"Failed to import module {module_name}: {e}"
|
|
113
113
|
logger.error(error_msg)
|
|
114
|
-
self._notify_reload_failed(
|
|
114
|
+
self._notify_reload_failed(workflow_id, error_msg)
|
|
115
115
|
return ReloadResult(
|
|
116
116
|
success=False,
|
|
117
|
-
|
|
117
|
+
workflow_id=workflow_id,
|
|
118
118
|
message="Import failed",
|
|
119
119
|
error=error_msg,
|
|
120
120
|
)
|
|
121
121
|
|
|
122
|
-
# Find
|
|
123
|
-
|
|
124
|
-
if not
|
|
125
|
-
error_msg = f"No
|
|
122
|
+
# Find workflow class in module
|
|
123
|
+
workflow_class = self._find_workflow_class(module)
|
|
124
|
+
if not workflow_class:
|
|
125
|
+
error_msg = f"No workflow class found in {module_name}"
|
|
126
126
|
logger.error(error_msg)
|
|
127
|
-
self._notify_reload_failed(
|
|
127
|
+
self._notify_reload_failed(workflow_id, error_msg)
|
|
128
128
|
return ReloadResult(
|
|
129
129
|
success=False,
|
|
130
|
-
|
|
131
|
-
message="No
|
|
130
|
+
workflow_id=workflow_id,
|
|
131
|
+
message="No workflow class found",
|
|
132
132
|
error=error_msg,
|
|
133
133
|
)
|
|
134
134
|
|
|
135
|
-
# Re-register
|
|
136
|
-
success = self.register_callback(
|
|
135
|
+
# Re-register workflow
|
|
136
|
+
success = self.register_callback(workflow_id, workflow_class)
|
|
137
137
|
|
|
138
138
|
if success:
|
|
139
139
|
self._reload_count += 1
|
|
140
140
|
logger.info(
|
|
141
|
-
f"✓ Successfully reloaded {
|
|
141
|
+
f"✓ Successfully reloaded {workflow_id} ({self._reload_count} total reloads)"
|
|
142
142
|
)
|
|
143
|
-
self._notify_reload_success(
|
|
143
|
+
self._notify_reload_success(workflow_id)
|
|
144
144
|
|
|
145
145
|
return ReloadResult(
|
|
146
146
|
success=True,
|
|
147
|
-
|
|
147
|
+
workflow_id=workflow_id,
|
|
148
148
|
message=f"Reloaded successfully (reload #{self._reload_count})",
|
|
149
149
|
)
|
|
150
150
|
else:
|
|
151
151
|
error_msg = "Registration failed"
|
|
152
|
-
logger.error(f"Failed to re-register {
|
|
153
|
-
self._notify_reload_failed(
|
|
152
|
+
logger.error(f"Failed to re-register {workflow_id}")
|
|
153
|
+
self._notify_reload_failed(workflow_id, error_msg)
|
|
154
154
|
return ReloadResult(
|
|
155
155
|
success=False,
|
|
156
|
-
|
|
156
|
+
workflow_id=workflow_id,
|
|
157
157
|
message="Registration failed",
|
|
158
158
|
error=error_msg,
|
|
159
159
|
)
|
|
160
160
|
|
|
161
161
|
except Exception as e:
|
|
162
|
-
error_msg = f"Unexpected error reloading {
|
|
162
|
+
error_msg = f"Unexpected error reloading {workflow_id}: {e}"
|
|
163
163
|
logger.exception(error_msg)
|
|
164
|
-
self._notify_reload_failed(
|
|
164
|
+
self._notify_reload_failed(workflow_id, str(e))
|
|
165
165
|
return ReloadResult(
|
|
166
166
|
success=False,
|
|
167
|
-
|
|
167
|
+
workflow_id=workflow_id,
|
|
168
168
|
message="Unexpected error",
|
|
169
169
|
error=str(e),
|
|
170
170
|
)
|
|
@@ -187,17 +187,17 @@ class WizardReloader:
|
|
|
187
187
|
return None
|
|
188
188
|
|
|
189
189
|
# Get parts relative to project root
|
|
190
|
-
# Try to find common patterns:
|
|
190
|
+
# Try to find common patterns: workflows/, empathy_software_plugin/workflows/
|
|
191
191
|
parts = path.parts
|
|
192
192
|
|
|
193
|
-
# Find
|
|
194
|
-
|
|
193
|
+
# Find workflow directory in path
|
|
194
|
+
workflow_dir_indices = [i for i, part in enumerate(parts) if "workflow" in part.lower()]
|
|
195
195
|
|
|
196
|
-
if not
|
|
196
|
+
if not workflow_dir_indices:
|
|
197
197
|
return None
|
|
198
198
|
|
|
199
|
-
# Take from first
|
|
200
|
-
start_idx =
|
|
199
|
+
# Take from first workflow directory
|
|
200
|
+
start_idx = workflow_dir_indices[0]
|
|
201
201
|
|
|
202
202
|
# Build module name
|
|
203
203
|
module_parts = list(parts[start_idx:])
|
|
@@ -228,38 +228,38 @@ class WizardReloader:
|
|
|
228
228
|
del sys.modules[submodule]
|
|
229
229
|
logger.debug(f"Unloaded submodule: {submodule}")
|
|
230
230
|
|
|
231
|
-
def
|
|
232
|
-
"""Find
|
|
231
|
+
def _find_workflow_class(self, module: Any) -> type | None:
|
|
232
|
+
"""Find workflow class in module.
|
|
233
233
|
|
|
234
234
|
Args:
|
|
235
235
|
module: Python module
|
|
236
236
|
|
|
237
237
|
Returns:
|
|
238
|
-
|
|
238
|
+
Workflow class or None if not found
|
|
239
239
|
|
|
240
240
|
"""
|
|
241
|
-
# Look for classes ending with "
|
|
241
|
+
# Look for classes ending with "Workflow"
|
|
242
242
|
for name in dir(module):
|
|
243
|
-
if name.endswith("
|
|
243
|
+
if name.endswith("Workflow") and not name.startswith("_"):
|
|
244
244
|
attr = getattr(module, name)
|
|
245
245
|
if isinstance(attr, type):
|
|
246
246
|
return attr
|
|
247
247
|
|
|
248
248
|
return None
|
|
249
249
|
|
|
250
|
-
def _notify_reload_success(self,
|
|
250
|
+
def _notify_reload_success(self, workflow_id: str) -> None:
|
|
251
251
|
"""Notify clients of successful reload.
|
|
252
252
|
|
|
253
253
|
Args:
|
|
254
|
-
|
|
254
|
+
workflow_id: ID of reloaded workflow
|
|
255
255
|
|
|
256
256
|
"""
|
|
257
257
|
if self.notification_callback:
|
|
258
258
|
try:
|
|
259
259
|
self.notification_callback(
|
|
260
260
|
{
|
|
261
|
-
"event": "
|
|
262
|
-
"
|
|
261
|
+
"event": "workflow_reloaded",
|
|
262
|
+
"workflow_id": workflow_id,
|
|
263
263
|
"success": True,
|
|
264
264
|
"reload_count": self._reload_count,
|
|
265
265
|
}
|
|
@@ -267,11 +267,11 @@ class WizardReloader:
|
|
|
267
267
|
except Exception as e:
|
|
268
268
|
logger.error(f"Error sending reload notification: {e}")
|
|
269
269
|
|
|
270
|
-
def _notify_reload_failed(self,
|
|
270
|
+
def _notify_reload_failed(self, workflow_id: str, error: str) -> None:
|
|
271
271
|
"""Notify clients of failed reload.
|
|
272
272
|
|
|
273
273
|
Args:
|
|
274
|
-
|
|
274
|
+
workflow_id: ID of workflow that failed to reload
|
|
275
275
|
error: Error message
|
|
276
276
|
|
|
277
277
|
"""
|
|
@@ -279,8 +279,8 @@ class WizardReloader:
|
|
|
279
279
|
try:
|
|
280
280
|
self.notification_callback(
|
|
281
281
|
{
|
|
282
|
-
"event": "
|
|
283
|
-
"
|
|
282
|
+
"event": "workflow_reload_failed",
|
|
283
|
+
"workflow_id": workflow_id,
|
|
284
284
|
"success": False,
|
|
285
285
|
"error": error,
|
|
286
286
|
}
|
empathy_os/hot_reload/watcher.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"""File system watcher for
|
|
1
|
+
"""File system watcher for workflow hot-reload.
|
|
2
2
|
|
|
3
|
-
Monitors
|
|
3
|
+
Monitors workflow directories for changes and triggers reloads.
|
|
4
4
|
|
|
5
5
|
Copyright 2025 Smart AI Memory, LLC
|
|
6
6
|
Licensed under Fair Source 0.9
|
|
@@ -16,14 +16,14 @@ from watchdog.observers import Observer
|
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
class
|
|
20
|
-
"""Handles file system events for
|
|
19
|
+
class WorkflowFileHandler(FileSystemEventHandler):
|
|
20
|
+
"""Handles file system events for workflow files."""
|
|
21
21
|
|
|
22
22
|
def __init__(self, reload_callback: Callable[[str, str], None]):
|
|
23
23
|
"""Initialize handler.
|
|
24
24
|
|
|
25
25
|
Args:
|
|
26
|
-
reload_callback: Function to call when
|
|
26
|
+
reload_callback: Function to call when workflow file changes (workflow_id, file_path)
|
|
27
27
|
|
|
28
28
|
"""
|
|
29
29
|
super().__init__()
|
|
@@ -61,24 +61,24 @@ class WizardFileHandler(FileSystemEventHandler):
|
|
|
61
61
|
try:
|
|
62
62
|
self._processing.add(file_path)
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
if
|
|
66
|
-
logger.info(f"Detected change in {
|
|
67
|
-
self.reload_callback(
|
|
64
|
+
workflow_id = self._extract_workflow_id(file_path)
|
|
65
|
+
if workflow_id:
|
|
66
|
+
logger.info(f"Detected change in {workflow_id} ({file_path})")
|
|
67
|
+
self.reload_callback(workflow_id, file_path)
|
|
68
68
|
|
|
69
69
|
except Exception as e:
|
|
70
70
|
logger.error(f"Error processing file change {file_path}: {e}")
|
|
71
71
|
finally:
|
|
72
72
|
self._processing.discard(file_path)
|
|
73
73
|
|
|
74
|
-
def
|
|
75
|
-
"""Extract
|
|
74
|
+
def _extract_workflow_id(self, file_path: str) -> str | None:
|
|
75
|
+
"""Extract workflow ID from file path.
|
|
76
76
|
|
|
77
77
|
Args:
|
|
78
|
-
file_path: Path to
|
|
78
|
+
file_path: Path to workflow file
|
|
79
79
|
|
|
80
80
|
Returns:
|
|
81
|
-
|
|
81
|
+
Workflow ID or None if cannot extract
|
|
82
82
|
|
|
83
83
|
"""
|
|
84
84
|
path = Path(file_path)
|
|
@@ -87,43 +87,43 @@ class WizardFileHandler(FileSystemEventHandler):
|
|
|
87
87
|
filename = path.stem
|
|
88
88
|
|
|
89
89
|
# Remove common suffixes
|
|
90
|
-
|
|
90
|
+
workflow_id = filename.replace("_workflow", "").replace("workflow_", "")
|
|
91
91
|
|
|
92
|
-
# Convert to
|
|
93
|
-
|
|
92
|
+
# Convert to workflow ID format (snake_case)
|
|
93
|
+
workflow_id = workflow_id.lower()
|
|
94
94
|
|
|
95
|
-
return
|
|
95
|
+
return workflow_id if workflow_id else None
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
class
|
|
99
|
-
"""Watches
|
|
98
|
+
class WorkflowFileWatcher:
|
|
99
|
+
"""Watches workflow directories for file changes.
|
|
100
100
|
|
|
101
101
|
Monitors specified directories and triggers reload callbacks
|
|
102
|
-
when
|
|
102
|
+
when workflow files are modified.
|
|
103
103
|
"""
|
|
104
104
|
|
|
105
|
-
def __init__(self,
|
|
105
|
+
def __init__(self, workflow_dirs: list[Path], reload_callback: Callable[[str, str], None]):
|
|
106
106
|
"""Initialize watcher.
|
|
107
107
|
|
|
108
108
|
Args:
|
|
109
|
-
|
|
110
|
-
reload_callback: Function to call on file changes (
|
|
109
|
+
workflow_dirs: List of directories to watch
|
|
110
|
+
reload_callback: Function to call on file changes (workflow_id, file_path)
|
|
111
111
|
|
|
112
112
|
"""
|
|
113
|
-
self.
|
|
113
|
+
self.workflow_dirs = [Path(d) for d in workflow_dirs]
|
|
114
114
|
self.reload_callback = reload_callback
|
|
115
115
|
self.observer = Observer()
|
|
116
|
-
self.event_handler =
|
|
116
|
+
self.event_handler = WorkflowFileHandler(reload_callback)
|
|
117
117
|
self._running = False
|
|
118
118
|
|
|
119
119
|
def start(self) -> None:
|
|
120
|
-
"""Start watching
|
|
120
|
+
"""Start watching workflow directories."""
|
|
121
121
|
if self._running:
|
|
122
122
|
logger.warning("Watcher already running")
|
|
123
123
|
return
|
|
124
124
|
|
|
125
125
|
valid_dirs = []
|
|
126
|
-
for directory in self.
|
|
126
|
+
for directory in self.workflow_dirs:
|
|
127
127
|
if not directory.exists():
|
|
128
128
|
logger.warning(f"Directory does not exist: {directory}")
|
|
129
129
|
continue
|
|
@@ -154,7 +154,7 @@ class WizardFileWatcher:
|
|
|
154
154
|
)
|
|
155
155
|
|
|
156
156
|
def stop(self) -> None:
|
|
157
|
-
"""Stop watching
|
|
157
|
+
"""Stop watching workflow directories."""
|
|
158
158
|
if not self._running:
|
|
159
159
|
return
|
|
160
160
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""WebSocket notification system for hot-reload events.
|
|
2
2
|
|
|
3
|
-
Notifies connected clients when
|
|
3
|
+
Notifies connected clients when workflows are reloaded.
|
|
4
4
|
|
|
5
5
|
Copyright 2025 Smart AI Memory, LLC
|
|
6
6
|
Licensed under Fair Source 0.9
|
|
@@ -143,7 +143,7 @@ def get_notification_manager() -> ReloadNotificationManager:
|
|
|
143
143
|
|
|
144
144
|
|
|
145
145
|
def create_notification_callback() -> Callable[[dict[str, Any]], None]:
|
|
146
|
-
"""Create a callback function for the
|
|
146
|
+
"""Create a callback function for the workflow reloader.
|
|
147
147
|
|
|
148
148
|
Returns:
|
|
149
149
|
Callback function that broadcasts notifications
|
empathy_os/memory/__init__.py
CHANGED
|
@@ -79,8 +79,11 @@ from .cross_session import (
|
|
|
79
79
|
generate_agent_id,
|
|
80
80
|
)
|
|
81
81
|
|
|
82
|
-
# Memory Graph (Cross-
|
|
83
|
-
from .edges import REVERSE_EDGE_TYPES,
|
|
82
|
+
# Memory Graph (Cross-Workflow Intelligence)
|
|
83
|
+
from .edges import REVERSE_EDGE_TYPES, WORKFLOW_EDGE_PATTERNS, Edge, EdgeType
|
|
84
|
+
|
|
85
|
+
# File-based session memory (always available, no Redis required)
|
|
86
|
+
from .file_session import FileSessionConfig, FileSessionMemory, get_file_session_memory
|
|
84
87
|
from .graph import MemoryGraph
|
|
85
88
|
|
|
86
89
|
# Long-term memory (Persistent patterns)
|
|
@@ -137,7 +140,7 @@ from .unified import Environment, MemoryConfig, UnifiedMemory
|
|
|
137
140
|
|
|
138
141
|
__all__ = [
|
|
139
142
|
"REVERSE_EDGE_TYPES",
|
|
140
|
-
"
|
|
143
|
+
"WORKFLOW_EDGE_PATTERNS",
|
|
141
144
|
"AccessTier",
|
|
142
145
|
"AgentContext",
|
|
143
146
|
"AgentCredentials",
|
|
@@ -152,6 +155,10 @@ __all__ = [
|
|
|
152
155
|
# Claude Memory
|
|
153
156
|
"ClaudeMemoryConfig",
|
|
154
157
|
"ClaudeMemoryLoader",
|
|
158
|
+
# File Session Memory (always available)
|
|
159
|
+
"FileSessionConfig",
|
|
160
|
+
"FileSessionMemory",
|
|
161
|
+
"get_file_session_memory",
|
|
155
162
|
"ConflictContext",
|
|
156
163
|
"ConflictResult",
|
|
157
164
|
"ConflictStrategy",
|
|
@@ -167,7 +174,7 @@ __all__ = [
|
|
|
167
174
|
"MemoryConfig",
|
|
168
175
|
# Control Panel
|
|
169
176
|
"MemoryControlPanel",
|
|
170
|
-
# Memory Graph (Cross-
|
|
177
|
+
# Memory Graph (Cross-Workflow Intelligence)
|
|
171
178
|
"MemoryGraph",
|
|
172
179
|
"MemoryPermissionError",
|
|
173
180
|
"MemoryStats",
|
|
@@ -405,7 +405,7 @@ This project uses the Empathy Framework for AI-powered software development assi
|
|
|
405
405
|
|
|
406
406
|
## Testing Standards
|
|
407
407
|
- Maintain 90%+ test coverage
|
|
408
|
-
- Write tests for all
|
|
408
|
+
- Write tests for all workflows
|
|
409
409
|
- Use pytest fixtures for common setup
|
|
410
410
|
- Mock external API calls
|
|
411
411
|
|
|
@@ -31,11 +31,7 @@ from typing import Any
|
|
|
31
31
|
|
|
32
32
|
import structlog
|
|
33
33
|
|
|
34
|
-
from .short_term import
|
|
35
|
-
AccessTier,
|
|
36
|
-
AgentCredentials,
|
|
37
|
-
RedisShortTermMemory,
|
|
38
|
-
)
|
|
34
|
+
from .short_term import AccessTier, AgentCredentials, RedisShortTermMemory
|
|
39
35
|
|
|
40
36
|
logger = structlog.get_logger(__name__)
|
|
41
37
|
|
|
@@ -571,8 +567,8 @@ class CrossSessionCoordinator:
|
|
|
571
567
|
|
|
572
568
|
if owner:
|
|
573
569
|
if isinstance(owner, bytes):
|
|
574
|
-
|
|
575
|
-
return owner
|
|
570
|
+
return owner.decode()
|
|
571
|
+
return str(owner)
|
|
576
572
|
|
|
577
573
|
return None
|
|
578
574
|
|
|
@@ -618,12 +614,12 @@ class CrossSessionCoordinator:
|
|
|
618
614
|
|
|
619
615
|
if event.get("event") == "session_joined":
|
|
620
616
|
session_info = SessionInfo.from_dict(event["session"])
|
|
621
|
-
for
|
|
622
|
-
|
|
617
|
+
for joined_handler in self._on_session_joined:
|
|
618
|
+
joined_handler(session_info)
|
|
623
619
|
elif event.get("event") == "session_left":
|
|
624
620
|
agent_id = event["agent_id"]
|
|
625
|
-
for
|
|
626
|
-
|
|
621
|
+
for left_handler in self._on_session_left:
|
|
622
|
+
left_handler(agent_id)
|
|
627
623
|
except (json.JSONDecodeError, KeyError, ValueError) as e:
|
|
628
624
|
logger.warning("invalid_session_event", error=str(e))
|
|
629
625
|
|
|
@@ -800,7 +796,7 @@ class BackgroundService:
|
|
|
800
796
|
Returns:
|
|
801
797
|
Dict with service status information
|
|
802
798
|
"""
|
|
803
|
-
status = {
|
|
799
|
+
status: dict[str, Any] = {
|
|
804
800
|
"running": self._running,
|
|
805
801
|
"agent_id": self._coordinator.agent_id if self._coordinator else None,
|
|
806
802
|
"active_sessions": 0,
|
empathy_os/memory/edges.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Memory Graph Edge Types
|
|
2
2
|
|
|
3
3
|
Defines edge types for connecting nodes in the knowledge graph.
|
|
4
|
-
Edges represent relationships between entities discovered by
|
|
4
|
+
Edges represent relationships between entities discovered by workflows.
|
|
5
5
|
|
|
6
6
|
Copyright 2025 Smart AI Memory, LLC
|
|
7
7
|
Licensed under Fair Source 0.9
|
|
@@ -74,7 +74,7 @@ class Edge:
|
|
|
74
74
|
|
|
75
75
|
# Context
|
|
76
76
|
description: str = ""
|
|
77
|
-
|
|
77
|
+
source_workflow: str = ""
|
|
78
78
|
|
|
79
79
|
# Additional data
|
|
80
80
|
metadata: dict[str, Any] = field(default_factory=dict)
|
|
@@ -91,7 +91,7 @@ class Edge:
|
|
|
91
91
|
"weight": self.weight,
|
|
92
92
|
"confidence": self.confidence,
|
|
93
93
|
"description": self.description,
|
|
94
|
-
"
|
|
94
|
+
"source_workflow": self.source_workflow,
|
|
95
95
|
"metadata": self.metadata,
|
|
96
96
|
"created_at": self.created_at.isoformat(),
|
|
97
97
|
}
|
|
@@ -106,7 +106,7 @@ class Edge:
|
|
|
106
106
|
weight=data.get("weight", 1.0),
|
|
107
107
|
confidence=data.get("confidence", 1.0),
|
|
108
108
|
description=data.get("description", ""),
|
|
109
|
-
|
|
109
|
+
source_workflow=data.get("source_workflow", data.get("source_wizard", "")),
|
|
110
110
|
metadata=data.get("metadata", {}),
|
|
111
111
|
created_at=(
|
|
112
112
|
datetime.fromisoformat(data["created_at"])
|
|
@@ -121,8 +121,8 @@ class Edge:
|
|
|
121
121
|
return f"{self.source_id}-{self.type.value}-{self.target_id}"
|
|
122
122
|
|
|
123
123
|
|
|
124
|
-
# Common edge patterns for
|
|
125
|
-
|
|
124
|
+
# Common edge patterns for workflow findings
|
|
125
|
+
WORKFLOW_EDGE_PATTERNS = {
|
|
126
126
|
"security-audit": [
|
|
127
127
|
(EdgeType.CAUSES, "vulnerability → vulnerability"),
|
|
128
128
|
(EdgeType.FIXED_BY, "vulnerability → fix"),
|