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
empathy_os/plugins/registry.py
CHANGED
|
@@ -9,7 +9,7 @@ Licensed under Fair Source 0.9
|
|
|
9
9
|
import logging
|
|
10
10
|
from importlib.metadata import entry_points
|
|
11
11
|
|
|
12
|
-
from .base import BasePlugin,
|
|
12
|
+
from .base import BasePlugin, BaseWorkflow, PluginValidationError
|
|
13
13
|
|
|
14
14
|
logger = logging.getLogger(__name__)
|
|
15
15
|
|
|
@@ -118,11 +118,11 @@ class PluginRegistry:
|
|
|
118
118
|
|
|
119
119
|
return list(self._plugins.keys())
|
|
120
120
|
|
|
121
|
-
def
|
|
122
|
-
"""List all
|
|
121
|
+
def list_all_workflows(self) -> dict[str, list[str]]:
|
|
122
|
+
"""List all workflows from all plugins.
|
|
123
123
|
|
|
124
124
|
Returns:
|
|
125
|
-
Dictionary mapping plugin_name -> list of
|
|
125
|
+
Dictionary mapping plugin_name -> list of workflow_ids
|
|
126
126
|
|
|
127
127
|
"""
|
|
128
128
|
if not self._auto_discovered:
|
|
@@ -130,19 +130,19 @@ class PluginRegistry:
|
|
|
130
130
|
|
|
131
131
|
result = {}
|
|
132
132
|
for plugin_name, plugin in self._plugins.items():
|
|
133
|
-
result[plugin_name] = plugin.
|
|
133
|
+
result[plugin_name] = plugin.list_workflows()
|
|
134
134
|
|
|
135
135
|
return result
|
|
136
136
|
|
|
137
|
-
def
|
|
138
|
-
"""Get a
|
|
137
|
+
def get_workflow(self, plugin_name: str, workflow_id: str) -> type[BaseWorkflow] | None:
|
|
138
|
+
"""Get a workflow from a specific plugin.
|
|
139
139
|
|
|
140
140
|
Args:
|
|
141
141
|
plugin_name: Plugin identifier
|
|
142
|
-
|
|
142
|
+
workflow_id: Workflow identifier within plugin
|
|
143
143
|
|
|
144
144
|
Returns:
|
|
145
|
-
|
|
145
|
+
Workflow class or None if not found
|
|
146
146
|
|
|
147
147
|
"""
|
|
148
148
|
plugin = self.get_plugin(plugin_name)
|
|
@@ -150,33 +150,33 @@ class PluginRegistry:
|
|
|
150
150
|
self.logger.warning(f"Plugin '{plugin_name}' not found")
|
|
151
151
|
return None
|
|
152
152
|
|
|
153
|
-
return plugin.
|
|
153
|
+
return plugin.get_workflow(workflow_id)
|
|
154
154
|
|
|
155
|
-
def
|
|
156
|
-
"""Get information about a
|
|
155
|
+
def get_workflow_info(self, plugin_name: str, workflow_id: str) -> dict | None:
|
|
156
|
+
"""Get information about a workflow.
|
|
157
157
|
|
|
158
158
|
Args:
|
|
159
159
|
plugin_name: Plugin identifier
|
|
160
|
-
|
|
160
|
+
workflow_id: Workflow identifier
|
|
161
161
|
|
|
162
162
|
Returns:
|
|
163
|
-
Dictionary with
|
|
163
|
+
Dictionary with workflow metadata or None
|
|
164
164
|
|
|
165
165
|
"""
|
|
166
166
|
plugin = self.get_plugin(plugin_name)
|
|
167
167
|
if not plugin:
|
|
168
168
|
return None
|
|
169
169
|
|
|
170
|
-
return plugin.
|
|
170
|
+
return plugin.get_workflow_info(workflow_id)
|
|
171
171
|
|
|
172
|
-
def
|
|
173
|
-
"""Find all
|
|
172
|
+
def find_workflows_by_level(self, empathy_level: int) -> list[dict]:
|
|
173
|
+
"""Find all workflows operating at a specific empathy level.
|
|
174
174
|
|
|
175
175
|
Args:
|
|
176
176
|
empathy_level: Target empathy level (1-5)
|
|
177
177
|
|
|
178
178
|
Returns:
|
|
179
|
-
List of
|
|
179
|
+
List of workflow info dictionaries
|
|
180
180
|
|
|
181
181
|
"""
|
|
182
182
|
if not self._auto_discovered:
|
|
@@ -184,22 +184,22 @@ class PluginRegistry:
|
|
|
184
184
|
|
|
185
185
|
results = []
|
|
186
186
|
for plugin_name, plugin in self._plugins.items():
|
|
187
|
-
for
|
|
188
|
-
info = plugin.
|
|
187
|
+
for workflow_id in plugin.list_workflows():
|
|
188
|
+
info = plugin.get_workflow_info(workflow_id)
|
|
189
189
|
if info and info.get("empathy_level") == empathy_level:
|
|
190
190
|
info["plugin"] = plugin_name
|
|
191
191
|
results.append(info)
|
|
192
192
|
|
|
193
193
|
return results
|
|
194
194
|
|
|
195
|
-
def
|
|
196
|
-
"""Find all
|
|
195
|
+
def find_workflows_by_domain(self, domain: str) -> list[dict]:
|
|
196
|
+
"""Find all workflows for a specific domain.
|
|
197
197
|
|
|
198
198
|
Args:
|
|
199
199
|
domain: Domain identifier (e.g., 'software', 'healthcare')
|
|
200
200
|
|
|
201
201
|
Returns:
|
|
202
|
-
List of
|
|
202
|
+
List of workflow info dictionaries
|
|
203
203
|
|
|
204
204
|
"""
|
|
205
205
|
if not self._auto_discovered:
|
|
@@ -209,8 +209,8 @@ class PluginRegistry:
|
|
|
209
209
|
for plugin_name, plugin in self._plugins.items():
|
|
210
210
|
metadata = plugin.get_metadata()
|
|
211
211
|
if metadata.domain == domain:
|
|
212
|
-
for
|
|
213
|
-
info = plugin.
|
|
212
|
+
for workflow_id in plugin.list_workflows():
|
|
213
|
+
info = plugin.get_workflow_info(workflow_id)
|
|
214
214
|
if info:
|
|
215
215
|
info["plugin"] = plugin_name
|
|
216
216
|
results.append(info)
|
|
@@ -227,26 +227,26 @@ class PluginRegistry:
|
|
|
227
227
|
if not self._auto_discovered:
|
|
228
228
|
self.auto_discover()
|
|
229
229
|
|
|
230
|
-
|
|
230
|
+
total_workflows = sum(len(plugin.list_workflows()) for plugin in self._plugins.values())
|
|
231
231
|
|
|
232
|
-
# Count
|
|
233
|
-
|
|
232
|
+
# Count workflows by level
|
|
233
|
+
workflows_by_level = {}
|
|
234
234
|
for level in range(1, 6):
|
|
235
|
-
|
|
235
|
+
workflows_by_level[f"level_{level}"] = len(self.find_workflows_by_level(level))
|
|
236
236
|
|
|
237
237
|
return {
|
|
238
238
|
"total_plugins": len(self._plugins),
|
|
239
|
-
"
|
|
239
|
+
"total_workflows": total_workflows,
|
|
240
240
|
"plugins": [
|
|
241
241
|
{
|
|
242
242
|
"name": name,
|
|
243
243
|
"domain": plugin.get_metadata().domain,
|
|
244
244
|
"version": plugin.get_metadata().version,
|
|
245
|
-
"
|
|
245
|
+
"workflow_count": len(plugin.list_workflows()),
|
|
246
246
|
}
|
|
247
247
|
for name, plugin in self._plugins.items()
|
|
248
248
|
],
|
|
249
|
-
"
|
|
249
|
+
"workflows_by_level": workflows_by_level,
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
|
|
@@ -8,6 +8,7 @@ Licensed under Fair Source 0.9
|
|
|
8
8
|
|
|
9
9
|
import json
|
|
10
10
|
import logging
|
|
11
|
+
from collections.abc import Iterator
|
|
11
12
|
from datetime import datetime
|
|
12
13
|
from pathlib import Path
|
|
13
14
|
from typing import Any
|
|
@@ -278,37 +279,70 @@ class ProjectIndex:
|
|
|
278
279
|
"""Get project summary."""
|
|
279
280
|
return self._summary
|
|
280
281
|
|
|
282
|
+
def iter_all_files(self) -> Iterator[FileRecord]:
|
|
283
|
+
"""Iterate over all file records (memory-efficient).
|
|
284
|
+
|
|
285
|
+
Use this when you don't need all records at once.
|
|
286
|
+
"""
|
|
287
|
+
yield from self._records.values()
|
|
288
|
+
|
|
281
289
|
def get_all_files(self) -> list[FileRecord]:
|
|
282
|
-
"""Get all file records.
|
|
283
|
-
|
|
290
|
+
"""Get all file records as a list.
|
|
291
|
+
|
|
292
|
+
Note: For large indexes, prefer iter_all_files() to avoid
|
|
293
|
+
loading all records into memory at once.
|
|
294
|
+
"""
|
|
295
|
+
return list(self.iter_all_files())
|
|
296
|
+
|
|
297
|
+
def iter_files_needing_tests(self) -> Iterator[FileRecord]:
|
|
298
|
+
"""Iterate over files that need tests (memory-efficient)."""
|
|
299
|
+
for r in self._records.values():
|
|
300
|
+
if r.test_requirement.value == "required" and not r.tests_exist:
|
|
301
|
+
yield r
|
|
284
302
|
|
|
285
303
|
def get_files_needing_tests(self) -> list[FileRecord]:
|
|
286
304
|
"""Get files that need tests but don't have them."""
|
|
287
|
-
return
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
305
|
+
return list(self.iter_files_needing_tests())
|
|
306
|
+
|
|
307
|
+
def iter_stale_files(self) -> Iterator[FileRecord]:
|
|
308
|
+
"""Iterate over files with stale tests (memory-efficient)."""
|
|
309
|
+
for r in self._records.values():
|
|
310
|
+
if r.is_stale:
|
|
311
|
+
yield r
|
|
292
312
|
|
|
293
313
|
def get_stale_files(self) -> list[FileRecord]:
|
|
294
314
|
"""Get files with stale tests."""
|
|
295
|
-
return
|
|
315
|
+
return list(self.iter_stale_files())
|
|
316
|
+
|
|
317
|
+
def iter_files_needing_attention(self) -> Iterator[FileRecord]:
|
|
318
|
+
"""Iterate over files that need attention (memory-efficient).
|
|
319
|
+
|
|
320
|
+
Note: For sorted results, use get_files_needing_attention().
|
|
321
|
+
"""
|
|
322
|
+
for r in self._records.values():
|
|
323
|
+
if r.needs_attention:
|
|
324
|
+
yield r
|
|
296
325
|
|
|
297
326
|
def get_files_needing_attention(self) -> list[FileRecord]:
|
|
298
|
-
"""Get files that need attention."""
|
|
327
|
+
"""Get files that need attention, sorted by impact score."""
|
|
299
328
|
return sorted(
|
|
300
|
-
|
|
329
|
+
self.iter_files_needing_attention(),
|
|
301
330
|
key=lambda r: -r.impact_score,
|
|
302
331
|
)
|
|
303
332
|
|
|
333
|
+
def iter_high_impact_files(self) -> Iterator[FileRecord]:
|
|
334
|
+
"""Iterate over high-impact files (memory-efficient).
|
|
335
|
+
|
|
336
|
+
Note: For sorted results, use get_high_impact_files().
|
|
337
|
+
"""
|
|
338
|
+
for r in self._records.values():
|
|
339
|
+
if r.impact_score >= self.config.high_impact_threshold:
|
|
340
|
+
yield r
|
|
341
|
+
|
|
304
342
|
def get_high_impact_files(self) -> list[FileRecord]:
|
|
305
343
|
"""Get high-impact files sorted by impact score."""
|
|
306
344
|
return sorted(
|
|
307
|
-
|
|
308
|
-
r
|
|
309
|
-
for r in self._records.values()
|
|
310
|
-
if r.impact_score >= self.config.high_impact_threshold
|
|
311
|
-
],
|
|
345
|
+
self.iter_high_impact_files(),
|
|
312
346
|
key=lambda r: -r.impact_score,
|
|
313
347
|
)
|
|
314
348
|
|
|
@@ -369,7 +369,7 @@ class IndexConfig:
|
|
|
369
369
|
"**/poetry.lock",
|
|
370
370
|
"**/Pipfile.lock",
|
|
371
371
|
# Archive directories
|
|
372
|
-
"**/
|
|
372
|
+
"**/archived_workflows/**",
|
|
373
373
|
],
|
|
374
374
|
)
|
|
375
375
|
|
|
@@ -453,7 +453,6 @@ class IndexConfig:
|
|
|
453
453
|
default_factory=lambda: [
|
|
454
454
|
"src",
|
|
455
455
|
"empathy_llm_toolkit",
|
|
456
|
-
"coach_wizards",
|
|
457
456
|
"empathy_software_plugin",
|
|
458
457
|
"empathy_healthcare_plugin",
|
|
459
458
|
],
|
|
@@ -49,7 +49,7 @@ class ReportGenerator:
|
|
|
49
49
|
"summary": {
|
|
50
50
|
"total_files_needing_tests": len(needing_tests),
|
|
51
51
|
"total_loc_untested": sum(r.lines_of_code for r in needing_tests),
|
|
52
|
-
"high_impact_untested":
|
|
52
|
+
"high_impact_untested": sum(1 for r in needing_tests if r.impact_score >= 5.0),
|
|
53
53
|
},
|
|
54
54
|
"priority_files": [
|
|
55
55
|
{
|
|
@@ -478,6 +478,7 @@ class ProjectScanner:
|
|
|
478
478
|
nested ast.walk() calls. Previous implementation was O(n²) due to
|
|
479
479
|
walking each function's subtree separately. This version is O(n).
|
|
480
480
|
"""
|
|
481
|
+
|
|
481
482
|
# Use inner class to maintain state during traversal
|
|
482
483
|
class MetricsVisitor(ast.NodeVisitor):
|
|
483
484
|
def __init__(self) -> None:
|
empathy_os/redis_memory.py
CHANGED
|
@@ -757,7 +757,9 @@ class RedisShortTermMemory:
|
|
|
757
757
|
return False
|
|
758
758
|
try:
|
|
759
759
|
return bool(self._client.ping())
|
|
760
|
-
except Exception:
|
|
760
|
+
except Exception: # noqa: BLE001
|
|
761
|
+
# INTENTIONAL: Health check is best-effort. Connection failure is non-fatal.
|
|
762
|
+
# Consumers will handle disconnection gracefully.
|
|
761
763
|
return False
|
|
762
764
|
|
|
763
765
|
def get_stats(self) -> dict:
|
|
@@ -768,17 +770,18 @@ class RedisShortTermMemory:
|
|
|
768
770
|
|
|
769
771
|
"""
|
|
770
772
|
if self.use_mock:
|
|
773
|
+
# Use generator expressions for memory-efficient counting
|
|
771
774
|
return {
|
|
772
775
|
"mode": "mock",
|
|
773
776
|
"total_keys": len(self._mock_storage),
|
|
774
|
-
"working_keys":
|
|
775
|
-
|
|
777
|
+
"working_keys": sum(
|
|
778
|
+
1 for k in self._mock_storage if k.startswith(self.PREFIX_WORKING)
|
|
776
779
|
),
|
|
777
|
-
"staged_keys":
|
|
778
|
-
|
|
780
|
+
"staged_keys": sum(
|
|
781
|
+
1 for k in self._mock_storage if k.startswith(self.PREFIX_STAGED)
|
|
779
782
|
),
|
|
780
|
-
"conflict_keys":
|
|
781
|
-
|
|
783
|
+
"conflict_keys": sum(
|
|
784
|
+
1 for k in self._mock_storage if k.startswith(self.PREFIX_CONFLICT)
|
|
782
785
|
),
|
|
783
786
|
}
|
|
784
787
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Empathy Framework Resilience Module
|
|
2
2
|
|
|
3
|
-
Provides reliability patterns for fault-tolerant
|
|
3
|
+
Provides reliability patterns for fault-tolerant workflow operations.
|
|
4
4
|
|
|
5
5
|
Usage:
|
|
6
6
|
from empathy_os.resilience import retry, circuit_breaker, timeout, fallback
|
empathy_os/resilience/health.py
CHANGED
|
@@ -229,18 +229,18 @@ def get_health_check() -> HealthCheck:
|
|
|
229
229
|
def register_default_checks(health: HealthCheck) -> None:
|
|
230
230
|
"""Register default health checks for Empathy Framework."""
|
|
231
231
|
|
|
232
|
-
@health.register("
|
|
233
|
-
async def
|
|
234
|
-
"""Check
|
|
232
|
+
@health.register("workflow_registry")
|
|
233
|
+
async def check_workflow_registry() -> dict[str, Any]:
|
|
234
|
+
"""Check workflow registry is loaded."""
|
|
235
235
|
try:
|
|
236
|
-
from empathy_os.routing import
|
|
236
|
+
from empathy_os.routing import WorkflowRegistry
|
|
237
237
|
|
|
238
|
-
registry =
|
|
239
|
-
|
|
238
|
+
registry = WorkflowRegistry()
|
|
239
|
+
workflow_count = len(registry.list_all())
|
|
240
240
|
return {
|
|
241
|
-
"healthy":
|
|
242
|
-
"
|
|
243
|
-
"message": f"{
|
|
241
|
+
"healthy": workflow_count > 0,
|
|
242
|
+
"workflow_count": workflow_count,
|
|
243
|
+
"message": f"{workflow_count} workflows registered",
|
|
244
244
|
}
|
|
245
245
|
except Exception as e:
|
|
246
246
|
return {"healthy": False, "message": str(e)}
|
|
@@ -279,7 +279,7 @@ def register_default_checks(health: HealthCheck) -> None:
|
|
|
279
279
|
decision = router.route_sync("test request")
|
|
280
280
|
return {
|
|
281
281
|
"healthy": decision is not None,
|
|
282
|
-
"
|
|
282
|
+
"primary_workflow": decision.primary_workflow,
|
|
283
283
|
}
|
|
284
284
|
except Exception as e:
|
|
285
285
|
return {"healthy": False, "message": str(e)}
|
empathy_os/routing/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Empathy Framework Routing Module
|
|
2
2
|
|
|
3
|
-
Intelligent request routing to
|
|
3
|
+
Intelligent request routing to workflows using LLM classification.
|
|
4
4
|
|
|
5
5
|
Usage:
|
|
6
6
|
from empathy_os.routing import SmartRouter, quick_route
|
|
@@ -8,7 +8,7 @@ Usage:
|
|
|
8
8
|
# Full router
|
|
9
9
|
router = SmartRouter()
|
|
10
10
|
decision = await router.route("Fix security issue in auth.py")
|
|
11
|
-
print(f"Use: {decision.
|
|
11
|
+
print(f"Use: {decision.primary_workflow}")
|
|
12
12
|
|
|
13
13
|
# Quick helper
|
|
14
14
|
decision = await quick_route("Optimize database queries")
|
|
@@ -20,10 +20,10 @@ Licensed under Fair Source 0.9
|
|
|
20
20
|
from .chain_executor import ChainConfig, ChainExecution, ChainExecutor, ChainStep, ChainTrigger
|
|
21
21
|
from .classifier import ClassificationResult, HaikuClassifier
|
|
22
22
|
from .smart_router import RoutingDecision, SmartRouter, quick_route
|
|
23
|
-
from .
|
|
23
|
+
from .workflow_registry import WORKFLOW_REGISTRY, WorkflowInfo, WorkflowRegistry
|
|
24
24
|
|
|
25
25
|
__all__ = [
|
|
26
|
-
"
|
|
26
|
+
"WORKFLOW_REGISTRY",
|
|
27
27
|
"ChainConfig",
|
|
28
28
|
"ChainExecution",
|
|
29
29
|
# Chain Executor
|
|
@@ -36,8 +36,8 @@ __all__ = [
|
|
|
36
36
|
"RoutingDecision",
|
|
37
37
|
# Smart Router
|
|
38
38
|
"SmartRouter",
|
|
39
|
-
"
|
|
40
|
-
#
|
|
41
|
-
"
|
|
39
|
+
"WorkflowInfo",
|
|
40
|
+
# Workflow Registry
|
|
41
|
+
"WorkflowRegistry",
|
|
42
42
|
"quick_route",
|
|
43
43
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Chain Executor
|
|
2
2
|
|
|
3
|
-
Executes
|
|
3
|
+
Executes workflow chains based on triggers and conditions.
|
|
4
4
|
Handles auto-chaining, approval workflows, and chain tracking.
|
|
5
5
|
|
|
6
6
|
Copyright 2025 Smart AI Memory, LLC
|
|
@@ -14,7 +14,7 @@ from typing import Any
|
|
|
14
14
|
|
|
15
15
|
import yaml
|
|
16
16
|
|
|
17
|
-
from .
|
|
17
|
+
from .workflow_registry import WorkflowRegistry
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
@dataclass
|
|
@@ -22,16 +22,16 @@ class ChainTrigger:
|
|
|
22
22
|
"""A trigger condition for auto-chaining."""
|
|
23
23
|
|
|
24
24
|
condition: str
|
|
25
|
-
|
|
25
|
+
next_workflow: str
|
|
26
26
|
approval_required: bool = False
|
|
27
27
|
reason: str = ""
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
@dataclass
|
|
31
31
|
class ChainConfig:
|
|
32
|
-
"""Configuration for a
|
|
32
|
+
"""Configuration for a workflow's chaining behavior."""
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
workflow_name: str
|
|
35
35
|
auto_chain: bool = True
|
|
36
36
|
description: str = ""
|
|
37
37
|
triggers: list[ChainTrigger] = field(default_factory=list)
|
|
@@ -41,7 +41,7 @@ class ChainConfig:
|
|
|
41
41
|
class ChainStep:
|
|
42
42
|
"""A step in an executed chain."""
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
workflow_name: str
|
|
45
45
|
triggered_by: str # condition or manual
|
|
46
46
|
approval_required: bool
|
|
47
47
|
approved: bool | None = None # None = pending
|
|
@@ -55,7 +55,7 @@ class ChainExecution:
|
|
|
55
55
|
"""Record of a chain execution."""
|
|
56
56
|
|
|
57
57
|
chain_id: str
|
|
58
|
-
|
|
58
|
+
initial_workflow: str
|
|
59
59
|
steps: list[ChainStep] = field(default_factory=list)
|
|
60
60
|
started_at: datetime = field(default_factory=datetime.now)
|
|
61
61
|
completed_at: datetime | None = None
|
|
@@ -64,12 +64,12 @@ class ChainExecution:
|
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
class ChainExecutor:
|
|
67
|
-
"""Executes
|
|
67
|
+
"""Executes workflow chains based on configuration and results.
|
|
68
68
|
|
|
69
69
|
Usage:
|
|
70
70
|
executor = ChainExecutor()
|
|
71
71
|
|
|
72
|
-
# Check for triggered chains after a
|
|
72
|
+
# Check for triggered chains after a workflow run
|
|
73
73
|
result = {"high_severity_count": 5, "vulnerability_type": "injection"}
|
|
74
74
|
next_steps = executor.get_triggered_chains("security-audit", result)
|
|
75
75
|
|
|
@@ -79,19 +79,19 @@ class ChainExecutor:
|
|
|
79
79
|
|
|
80
80
|
def __init__(
|
|
81
81
|
self,
|
|
82
|
-
config_path: str | Path = ".empathy/
|
|
82
|
+
config_path: str | Path = ".empathy/workflow_chains.yaml",
|
|
83
83
|
):
|
|
84
84
|
"""Initialize the chain executor.
|
|
85
85
|
|
|
86
86
|
Args:
|
|
87
|
-
config_path: Path to
|
|
87
|
+
config_path: Path to workflow_chains.yaml
|
|
88
88
|
|
|
89
89
|
"""
|
|
90
90
|
self.config_path = Path(config_path)
|
|
91
91
|
self._configs: dict[str, ChainConfig] = {}
|
|
92
92
|
self._templates: dict[str, list[str]] = {}
|
|
93
93
|
self._global_settings: dict[str, Any] = {}
|
|
94
|
-
self._registry =
|
|
94
|
+
self._registry = WorkflowRegistry()
|
|
95
95
|
self._executions: list[ChainExecution] = []
|
|
96
96
|
|
|
97
97
|
self._load_config()
|
|
@@ -110,20 +110,20 @@ class ChainExecutor:
|
|
|
110
110
|
|
|
111
111
|
# Load chain configs
|
|
112
112
|
chains = data.get("chains", {})
|
|
113
|
-
for
|
|
113
|
+
for workflow_name, config in chains.items():
|
|
114
114
|
triggers = []
|
|
115
115
|
for t in config.get("triggers", []):
|
|
116
116
|
triggers.append(
|
|
117
117
|
ChainTrigger(
|
|
118
118
|
condition=t.get("condition", ""),
|
|
119
|
-
|
|
119
|
+
next_workflow=t.get("next", ""),
|
|
120
120
|
approval_required=t.get("approval_required", False),
|
|
121
121
|
reason=t.get("reason", ""),
|
|
122
122
|
),
|
|
123
123
|
)
|
|
124
124
|
|
|
125
|
-
self._configs[
|
|
126
|
-
|
|
125
|
+
self._configs[workflow_name] = ChainConfig(
|
|
126
|
+
workflow_name=workflow_name,
|
|
127
127
|
auto_chain=config.get("auto_chain", True),
|
|
128
128
|
description=config.get("description", ""),
|
|
129
129
|
triggers=triggers,
|
|
@@ -139,14 +139,14 @@ class ChainExecutor:
|
|
|
139
139
|
|
|
140
140
|
def get_triggered_chains(
|
|
141
141
|
self,
|
|
142
|
-
|
|
142
|
+
workflow_name: str,
|
|
143
143
|
result: dict[str, Any],
|
|
144
144
|
) -> list[ChainTrigger]:
|
|
145
|
-
"""Get triggered chain steps based on
|
|
145
|
+
"""Get triggered chain steps based on workflow result.
|
|
146
146
|
|
|
147
147
|
Args:
|
|
148
|
-
|
|
149
|
-
result: The
|
|
148
|
+
workflow_name: The workflow that just completed
|
|
149
|
+
result: The workflow's result dictionary
|
|
150
150
|
|
|
151
151
|
Returns:
|
|
152
152
|
List of triggered ChainTriggers
|
|
@@ -155,7 +155,7 @@ class ChainExecutor:
|
|
|
155
155
|
if not self._global_settings.get("auto_chain_enabled", True):
|
|
156
156
|
return []
|
|
157
157
|
|
|
158
|
-
config = self._configs.get(
|
|
158
|
+
config = self._configs.get(workflow_name)
|
|
159
159
|
if not config or not config.auto_chain:
|
|
160
160
|
return []
|
|
161
161
|
|
|
@@ -227,25 +227,25 @@ class ChainExecutor:
|
|
|
227
227
|
|
|
228
228
|
def should_trigger_chain(
|
|
229
229
|
self,
|
|
230
|
-
|
|
230
|
+
workflow_name: str,
|
|
231
231
|
result: dict[str, Any],
|
|
232
232
|
) -> tuple[bool, list[ChainTrigger]]:
|
|
233
233
|
"""Check if a chain should be triggered and return triggers.
|
|
234
234
|
|
|
235
235
|
Args:
|
|
236
|
-
|
|
237
|
-
result: The
|
|
236
|
+
workflow_name: The workflow that completed
|
|
237
|
+
result: The workflow's result
|
|
238
238
|
|
|
239
239
|
Returns:
|
|
240
240
|
Tuple of (should_trigger, list_of_triggers)
|
|
241
241
|
|
|
242
242
|
"""
|
|
243
|
-
triggers = self.get_triggered_chains(
|
|
243
|
+
triggers = self.get_triggered_chains(workflow_name, result)
|
|
244
244
|
return len(triggers) > 0, triggers
|
|
245
245
|
|
|
246
|
-
def get_chain_config(self,
|
|
247
|
-
"""Get chain configuration for a
|
|
248
|
-
return self._configs.get(
|
|
246
|
+
def get_chain_config(self, workflow_name: str) -> ChainConfig | None:
|
|
247
|
+
"""Get chain configuration for a workflow."""
|
|
248
|
+
return self._configs.get(workflow_name)
|
|
249
249
|
|
|
250
250
|
def get_template(self, template_name: str) -> list[str] | None:
|
|
251
251
|
"""Get a chain template by name."""
|
|
@@ -257,13 +257,13 @@ class ChainExecutor:
|
|
|
257
257
|
|
|
258
258
|
def create_execution(
|
|
259
259
|
self,
|
|
260
|
-
|
|
260
|
+
initial_workflow: str,
|
|
261
261
|
triggered_steps: list[ChainTrigger] | None = None,
|
|
262
262
|
) -> ChainExecution:
|
|
263
263
|
"""Create a new chain execution record.
|
|
264
264
|
|
|
265
265
|
Args:
|
|
266
|
-
|
|
266
|
+
initial_workflow: The starting workflow
|
|
267
267
|
triggered_steps: Optional list of triggered next steps
|
|
268
268
|
|
|
269
269
|
Returns:
|
|
@@ -272,13 +272,13 @@ class ChainExecutor:
|
|
|
272
272
|
"""
|
|
273
273
|
execution = ChainExecution(
|
|
274
274
|
chain_id=f"chain_{datetime.now().strftime('%Y%m%d%H%M%S')}",
|
|
275
|
-
|
|
275
|
+
initial_workflow=initial_workflow,
|
|
276
276
|
)
|
|
277
277
|
|
|
278
278
|
# Add initial step
|
|
279
279
|
execution.steps.append(
|
|
280
280
|
ChainStep(
|
|
281
|
-
|
|
281
|
+
workflow_name=initial_workflow,
|
|
282
282
|
triggered_by="manual",
|
|
283
283
|
approval_required=False,
|
|
284
284
|
approved=True,
|
|
@@ -290,7 +290,7 @@ class ChainExecutor:
|
|
|
290
290
|
for trigger in triggered_steps:
|
|
291
291
|
execution.steps.append(
|
|
292
292
|
ChainStep(
|
|
293
|
-
|
|
293
|
+
workflow_name=trigger.next_workflow,
|
|
294
294
|
triggered_by=trigger.condition,
|
|
295
295
|
approval_required=trigger.approval_required,
|
|
296
296
|
),
|
|
@@ -358,15 +358,15 @@ class ChainExecutor:
|
|
|
358
358
|
step.result = result
|
|
359
359
|
|
|
360
360
|
# Check for new triggers
|
|
361
|
-
new_triggers = self.get_triggered_chains(step.
|
|
361
|
+
new_triggers = self.get_triggered_chains(step.workflow_name, result)
|
|
362
362
|
|
|
363
363
|
# Add new steps (if not already in chain)
|
|
364
|
-
|
|
364
|
+
existing_workflows = {s.workflow_name for s in execution.steps}
|
|
365
365
|
for trigger in new_triggers:
|
|
366
|
-
if trigger.
|
|
366
|
+
if trigger.next_workflow not in existing_workflows:
|
|
367
367
|
execution.steps.append(
|
|
368
368
|
ChainStep(
|
|
369
|
-
|
|
369
|
+
workflow_name=trigger.next_workflow,
|
|
370
370
|
triggered_by=trigger.condition,
|
|
371
371
|
approval_required=trigger.approval_required,
|
|
372
372
|
),
|