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
|
@@ -11,11 +11,7 @@ The MetaOrchestrator is responsible for:
|
|
|
11
11
|
import logging
|
|
12
12
|
from typing import Any
|
|
13
13
|
|
|
14
|
-
from empathy_os.workflows.progressive.core import
|
|
15
|
-
EscalationConfig,
|
|
16
|
-
Tier,
|
|
17
|
-
TierResult,
|
|
18
|
-
)
|
|
14
|
+
from empathy_os.workflows.progressive.core import EscalationConfig, Tier, TierResult
|
|
19
15
|
|
|
20
16
|
logger = logging.getLogger(__name__)
|
|
21
17
|
|
|
@@ -50,15 +46,11 @@ class MetaOrchestrator:
|
|
|
50
46
|
self.tier_history: dict[Tier, list[float]] = {
|
|
51
47
|
Tier.CHEAP: [],
|
|
52
48
|
Tier.CAPABLE: [],
|
|
53
|
-
Tier.PREMIUM: []
|
|
49
|
+
Tier.PREMIUM: [],
|
|
54
50
|
}
|
|
55
51
|
|
|
56
52
|
def should_escalate(
|
|
57
|
-
self,
|
|
58
|
-
tier: Tier,
|
|
59
|
-
result: TierResult,
|
|
60
|
-
attempt: int,
|
|
61
|
-
config: EscalationConfig
|
|
53
|
+
self, tier: Tier, result: TierResult, attempt: int, config: EscalationConfig
|
|
62
54
|
) -> tuple[bool, str]:
|
|
63
55
|
"""Determine if tier should escalate to next tier.
|
|
64
56
|
|
|
@@ -104,9 +96,7 @@ class MetaOrchestrator:
|
|
|
104
96
|
return False, "Premium tier is final"
|
|
105
97
|
|
|
106
98
|
def _check_cheap_escalation(
|
|
107
|
-
self,
|
|
108
|
-
result: TierResult,
|
|
109
|
-
config: EscalationConfig
|
|
99
|
+
self, result: TierResult, config: EscalationConfig
|
|
110
100
|
) -> tuple[bool, str]:
|
|
111
101
|
"""Check if cheap tier should escalate to capable.
|
|
112
102
|
|
|
@@ -127,24 +117,30 @@ class MetaOrchestrator:
|
|
|
127
117
|
|
|
128
118
|
# Check syntax errors (prioritize over CQS)
|
|
129
119
|
if syntax_error_count > config.cheap_to_capable_max_syntax_errors:
|
|
130
|
-
return
|
|
120
|
+
return (
|
|
121
|
+
True,
|
|
122
|
+
f"{syntax_error_count} syntax errors exceeds limit {config.cheap_to_capable_max_syntax_errors}",
|
|
123
|
+
)
|
|
131
124
|
|
|
132
125
|
# Check failure rate
|
|
133
126
|
if failure_rate > config.cheap_to_capable_failure_rate:
|
|
134
|
-
return
|
|
127
|
+
return (
|
|
128
|
+
True,
|
|
129
|
+
f"Failure rate {failure_rate:.1%} exceeds threshold {config.cheap_to_capable_failure_rate:.1%}",
|
|
130
|
+
)
|
|
135
131
|
|
|
136
132
|
# Check CQS threshold
|
|
137
133
|
if cqs < config.cheap_to_capable_min_cqs:
|
|
138
|
-
return
|
|
134
|
+
return (
|
|
135
|
+
True,
|
|
136
|
+
f"Quality score {cqs:.1f} below threshold {config.cheap_to_capable_min_cqs}",
|
|
137
|
+
)
|
|
139
138
|
|
|
140
139
|
# All checks passed, no escalation needed
|
|
141
140
|
return False, f"Quality acceptable (CQS={cqs:.1f})"
|
|
142
141
|
|
|
143
142
|
def _check_capable_escalation(
|
|
144
|
-
self,
|
|
145
|
-
result: TierResult,
|
|
146
|
-
attempt: int,
|
|
147
|
-
config: EscalationConfig
|
|
143
|
+
self, result: TierResult, attempt: int, config: EscalationConfig
|
|
148
144
|
) -> tuple[bool, str]:
|
|
149
145
|
"""Check if capable tier should escalate to premium.
|
|
150
146
|
|
|
@@ -165,15 +161,24 @@ class MetaOrchestrator:
|
|
|
165
161
|
|
|
166
162
|
# Check max attempts first
|
|
167
163
|
if attempt >= config.capable_max_attempts:
|
|
168
|
-
return
|
|
164
|
+
return (
|
|
165
|
+
True,
|
|
166
|
+
f"Max attempts ({config.capable_max_attempts}) reached without achieving target quality",
|
|
167
|
+
)
|
|
169
168
|
|
|
170
169
|
# Check syntax errors (strict for capable tier)
|
|
171
170
|
if syntax_error_count > config.capable_to_premium_max_syntax_errors:
|
|
172
|
-
return
|
|
171
|
+
return (
|
|
172
|
+
True,
|
|
173
|
+
f"{syntax_error_count} syntax errors exceeds limit {config.capable_to_premium_max_syntax_errors}",
|
|
174
|
+
)
|
|
173
175
|
|
|
174
176
|
# Check failure rate
|
|
175
177
|
if failure_rate > config.capable_to_premium_failure_rate:
|
|
176
|
-
return
|
|
178
|
+
return (
|
|
179
|
+
True,
|
|
180
|
+
f"Failure rate {failure_rate:.1%} exceeds threshold {config.capable_to_premium_failure_rate:.1%}",
|
|
181
|
+
)
|
|
177
182
|
|
|
178
183
|
# Check stagnation (consecutive runs with <5% improvement)
|
|
179
184
|
# Only check if we have enough history
|
|
@@ -181,7 +186,7 @@ class MetaOrchestrator:
|
|
|
181
186
|
is_stagnant, stagnation_reason = self._detect_stagnation(
|
|
182
187
|
self.tier_history[Tier.CAPABLE],
|
|
183
188
|
config.improvement_threshold,
|
|
184
|
-
config.consecutive_stagnation_limit
|
|
189
|
+
config.consecutive_stagnation_limit,
|
|
185
190
|
)
|
|
186
191
|
|
|
187
192
|
if is_stagnant:
|
|
@@ -189,16 +194,16 @@ class MetaOrchestrator:
|
|
|
189
194
|
|
|
190
195
|
# Check CQS threshold (after stagnation check)
|
|
191
196
|
if cqs < config.capable_to_premium_min_cqs and attempt >= config.capable_min_attempts:
|
|
192
|
-
return
|
|
197
|
+
return (
|
|
198
|
+
True,
|
|
199
|
+
f"Quality score {cqs:.1f} below threshold {config.capable_to_premium_min_cqs}",
|
|
200
|
+
)
|
|
193
201
|
|
|
194
202
|
# No escalation needed
|
|
195
203
|
return False, f"Quality acceptable (CQS={cqs:.1f}), continuing improvement"
|
|
196
204
|
|
|
197
205
|
def _detect_stagnation(
|
|
198
|
-
self,
|
|
199
|
-
cqs_history: list[float],
|
|
200
|
-
improvement_threshold: float,
|
|
201
|
-
consecutive_limit: int
|
|
206
|
+
self, cqs_history: list[float], improvement_threshold: float, consecutive_limit: int
|
|
202
207
|
) -> tuple[bool, str]:
|
|
203
208
|
"""Detect if improvement has stagnated.
|
|
204
209
|
|
|
@@ -246,10 +251,7 @@ class MetaOrchestrator:
|
|
|
246
251
|
return False, "No stagnation detected"
|
|
247
252
|
|
|
248
253
|
def build_tier_prompt(
|
|
249
|
-
self,
|
|
250
|
-
tier: Tier,
|
|
251
|
-
base_task: str,
|
|
252
|
-
failure_context: dict[str, Any] | None = None
|
|
254
|
+
self, tier: Tier, base_task: str, failure_context: dict[str, Any] | None = None
|
|
253
255
|
) -> str:
|
|
254
256
|
"""Build XML-enhanced prompt with failure context.
|
|
255
257
|
|
|
@@ -304,11 +306,7 @@ class MetaOrchestrator:
|
|
|
304
306
|
</instructions>
|
|
305
307
|
</task>"""
|
|
306
308
|
|
|
307
|
-
def _build_capable_prompt(
|
|
308
|
-
self,
|
|
309
|
-
base_task: str,
|
|
310
|
-
failure_context: dict[str, Any] | None
|
|
311
|
-
) -> str:
|
|
309
|
+
def _build_capable_prompt(self, base_task: str, failure_context: dict[str, Any] | None) -> str:
|
|
312
310
|
"""Build enhanced prompt for capable tier with failure context.
|
|
313
311
|
|
|
314
312
|
Args:
|
|
@@ -359,12 +357,14 @@ class MetaOrchestrator:
|
|
|
359
357
|
# Add failure pattern analysis
|
|
360
358
|
if failure_patterns:
|
|
361
359
|
prompt_parts.append(" <failure_analysis>")
|
|
362
|
-
prompt_parts.append(
|
|
360
|
+
prompt_parts.append(
|
|
361
|
+
f" <total_failures>{failure_patterns.get('total_failures', 0)}</total_failures>"
|
|
362
|
+
)
|
|
363
363
|
prompt_parts.append(" <patterns>")
|
|
364
364
|
|
|
365
365
|
error_types = failure_patterns.get("error_types", {})
|
|
366
366
|
for error_type, count in sorted(error_types.items(), key=lambda x: -x[1]):
|
|
367
|
-
prompt_parts.append(f
|
|
367
|
+
prompt_parts.append(f' <pattern type="{error_type}" count="{count}" />')
|
|
368
368
|
|
|
369
369
|
prompt_parts.append(" </patterns>")
|
|
370
370
|
|
|
@@ -382,68 +382,74 @@ class MetaOrchestrator:
|
|
|
382
382
|
error = example.get("error", "Unknown error")
|
|
383
383
|
code_snippet = example.get("code", "")[:200] # Limit snippet length
|
|
384
384
|
|
|
385
|
-
prompt_parts.append(f
|
|
385
|
+
prompt_parts.append(f' <example number="{i}">')
|
|
386
386
|
prompt_parts.append(f" <error>{self._escape_xml(error)}</error>")
|
|
387
387
|
if code_snippet:
|
|
388
|
-
prompt_parts.append(
|
|
388
|
+
prompt_parts.append(
|
|
389
|
+
f" <code_snippet>{self._escape_xml(code_snippet)}</code_snippet>"
|
|
390
|
+
)
|
|
389
391
|
prompt_parts.append(" </example>")
|
|
390
392
|
|
|
391
393
|
prompt_parts.append(" </failed_attempts>")
|
|
392
394
|
prompt_parts.append("")
|
|
393
395
|
|
|
394
|
-
prompt_parts.extend(
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
396
|
+
prompt_parts.extend(
|
|
397
|
+
[
|
|
398
|
+
" <improvement_needed>",
|
|
399
|
+
" The cheap tier struggled with these items. Analyze the failure",
|
|
400
|
+
" patterns above and generate improved solutions that specifically",
|
|
401
|
+
" address these issues.",
|
|
402
|
+
" </improvement_needed>",
|
|
403
|
+
" </context_from_previous_tier>",
|
|
404
|
+
"",
|
|
405
|
+
" <your_task>",
|
|
406
|
+
" Generate improved output that avoids the specific failure patterns identified above.",
|
|
407
|
+
"",
|
|
408
|
+
" <quality_requirements>",
|
|
409
|
+
" <pass_rate>80%+</pass_rate>",
|
|
410
|
+
" <coverage>70%+</coverage>",
|
|
411
|
+
" <quality_score>80+</quality_score>",
|
|
412
|
+
" </quality_requirements>",
|
|
413
|
+
"",
|
|
414
|
+
" <focus_areas>",
|
|
415
|
+
]
|
|
416
|
+
)
|
|
413
417
|
|
|
414
418
|
# Add targeted focus areas based on failure patterns
|
|
415
419
|
if failure_patterns:
|
|
416
420
|
error_types = failure_patterns.get("error_types", {})
|
|
417
421
|
if "async_errors" in error_types:
|
|
418
|
-
prompt_parts.append(
|
|
422
|
+
prompt_parts.append(
|
|
423
|
+
' <focus area="async">Proper async/await patterns and error handling</focus>'
|
|
424
|
+
)
|
|
419
425
|
if "mocking_errors" in error_types:
|
|
420
|
-
prompt_parts.append(
|
|
426
|
+
prompt_parts.append(
|
|
427
|
+
' <focus area="mocking">Correct mock setup and teardown</focus>'
|
|
428
|
+
)
|
|
421
429
|
if "syntax_errors" in error_types:
|
|
422
|
-
prompt_parts.append(
|
|
430
|
+
prompt_parts.append(
|
|
431
|
+
' <focus area="syntax">Valid Python syntax and imports</focus>'
|
|
432
|
+
)
|
|
423
433
|
if "other_errors" in error_types:
|
|
424
|
-
prompt_parts.append(
|
|
434
|
+
prompt_parts.append(
|
|
435
|
+
' <focus area="general">Edge cases and error handling</focus>'
|
|
436
|
+
)
|
|
425
437
|
else:
|
|
426
438
|
# Default focus areas
|
|
427
|
-
prompt_parts.extend(
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
"</task>"
|
|
438
|
-
])
|
|
439
|
+
prompt_parts.extend(
|
|
440
|
+
[
|
|
441
|
+
' <focus area="syntax">Correct syntax and structure</focus>',
|
|
442
|
+
' <focus area="coverage">Comprehensive test coverage</focus>',
|
|
443
|
+
' <focus area="errors">Proper error handling</focus>',
|
|
444
|
+
' <focus area="edge_cases">Edge case coverage</focus>',
|
|
445
|
+
]
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
prompt_parts.extend([" </focus_areas>", " </your_task>", "</task>"])
|
|
439
449
|
|
|
440
450
|
return "\n".join(prompt_parts)
|
|
441
451
|
|
|
442
|
-
def _build_premium_prompt(
|
|
443
|
-
self,
|
|
444
|
-
base_task: str,
|
|
445
|
-
failure_context: dict[str, Any] | None
|
|
446
|
-
) -> str:
|
|
452
|
+
def _build_premium_prompt(self, base_task: str, failure_context: dict[str, Any] | None) -> str:
|
|
447
453
|
"""Build comprehensive prompt for premium tier.
|
|
448
454
|
|
|
449
455
|
Args:
|
|
@@ -503,25 +509,35 @@ class MetaOrchestrator:
|
|
|
503
509
|
# Add detailed failure analysis
|
|
504
510
|
if failure_patterns:
|
|
505
511
|
prompt_parts.append(" <persistent_issues>")
|
|
506
|
-
prompt_parts.append(
|
|
512
|
+
prompt_parts.append(
|
|
513
|
+
f" <total_failures>{failure_patterns.get('total_failures', 0)}</total_failures>"
|
|
514
|
+
)
|
|
507
515
|
prompt_parts.append(" <failure_patterns>")
|
|
508
516
|
|
|
509
517
|
error_types = failure_patterns.get("error_types", {})
|
|
510
518
|
for error_type, count in sorted(error_types.items(), key=lambda x: -x[1]):
|
|
511
|
-
prompt_parts.append(f
|
|
519
|
+
prompt_parts.append(f' <pattern type="{error_type}" count="{count}">')
|
|
512
520
|
|
|
513
521
|
# Add specific guidance per error type
|
|
514
522
|
if error_type == "async_errors":
|
|
515
|
-
prompt_parts.append(
|
|
523
|
+
prompt_parts.append(
|
|
524
|
+
" <guidance>Use proper async/await patterns, handle timeouts correctly</guidance>"
|
|
525
|
+
)
|
|
516
526
|
elif error_type == "mocking_errors":
|
|
517
|
-
prompt_parts.append(
|
|
527
|
+
prompt_parts.append(
|
|
528
|
+
" <guidance>Ensure mocks are properly configured and reset</guidance>"
|
|
529
|
+
)
|
|
518
530
|
elif error_type == "syntax_errors":
|
|
519
|
-
prompt_parts.append(
|
|
531
|
+
prompt_parts.append(
|
|
532
|
+
" <guidance>Double-check syntax, imports, and type annotations</guidance>"
|
|
533
|
+
)
|
|
520
534
|
|
|
521
535
|
prompt_parts.append(" </pattern>")
|
|
522
536
|
|
|
523
537
|
prompt_parts.append(" </failure_patterns>")
|
|
524
|
-
prompt_parts.append(
|
|
538
|
+
prompt_parts.append(
|
|
539
|
+
f" <primary_issue>{failure_patterns.get('primary_issue', 'unknown')}</primary_issue>"
|
|
540
|
+
)
|
|
525
541
|
prompt_parts.append(" </persistent_issues>")
|
|
526
542
|
prompt_parts.append("")
|
|
527
543
|
|
|
@@ -535,67 +551,77 @@ class MetaOrchestrator:
|
|
|
535
551
|
code_snippet = example.get("code", "")[:300] # More context for premium
|
|
536
552
|
quality_score = example.get("quality_score", 0)
|
|
537
553
|
|
|
538
|
-
prompt_parts.append(f
|
|
554
|
+
prompt_parts.append(f' <attempt number="{i}" quality_score="{quality_score}">')
|
|
539
555
|
prompt_parts.append(f" <error>{self._escape_xml(error)}</error>")
|
|
540
556
|
if code_snippet:
|
|
541
|
-
prompt_parts.append(
|
|
557
|
+
prompt_parts.append(
|
|
558
|
+
f" <code_snippet>{self._escape_xml(code_snippet)}</code_snippet>"
|
|
559
|
+
)
|
|
542
560
|
prompt_parts.append(" </attempt>")
|
|
543
561
|
|
|
544
562
|
prompt_parts.append(" </capable_tier_attempts>")
|
|
545
563
|
prompt_parts.append("")
|
|
546
564
|
|
|
547
|
-
prompt_parts.extend(
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
565
|
+
prompt_parts.extend(
|
|
566
|
+
[
|
|
567
|
+
" </escalation_context>",
|
|
568
|
+
"",
|
|
569
|
+
" <expert_task>",
|
|
570
|
+
" <critical_notice>",
|
|
571
|
+
" You are the FINAL tier in the progressive escalation system.",
|
|
572
|
+
" Previous tiers (cheap and capable) have attempted this task",
|
|
573
|
+
" multiple times and could not achieve the required quality.",
|
|
574
|
+
"",
|
|
575
|
+
" This is the last automated attempt before human review.",
|
|
576
|
+
" Excellence is not optional - it is required.",
|
|
577
|
+
" </critical_notice>",
|
|
578
|
+
"",
|
|
579
|
+
" <expert_techniques>",
|
|
580
|
+
" Apply sophisticated approaches:",
|
|
581
|
+
" - Deep analysis of why previous attempts failed",
|
|
582
|
+
" - Production-grade error handling and edge cases",
|
|
583
|
+
" - Comprehensive documentation and clarity",
|
|
584
|
+
" - Defensive programming against subtle bugs",
|
|
585
|
+
]
|
|
586
|
+
)
|
|
567
587
|
|
|
568
588
|
# Add specific techniques based on failure patterns
|
|
569
589
|
if failure_patterns:
|
|
570
590
|
error_types = failure_patterns.get("error_types", {})
|
|
571
591
|
if "async_errors" in error_types:
|
|
572
|
-
prompt_parts.append(
|
|
592
|
+
prompt_parts.append(
|
|
593
|
+
" - Advanced async patterns (asyncio.gather, proper timeouts)"
|
|
594
|
+
)
|
|
573
595
|
if "mocking_errors" in error_types:
|
|
574
|
-
prompt_parts.append(
|
|
596
|
+
prompt_parts.append(
|
|
597
|
+
" - Sophisticated mocking (pytest fixtures, proper lifecycle)"
|
|
598
|
+
)
|
|
575
599
|
if "syntax_errors" in error_types:
|
|
576
600
|
prompt_parts.append(" - Rigorous syntax validation before submission")
|
|
577
601
|
|
|
578
|
-
prompt_parts.extend(
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
602
|
+
prompt_parts.extend(
|
|
603
|
+
[
|
|
604
|
+
" </expert_techniques>",
|
|
605
|
+
"",
|
|
606
|
+
" <quality_requirements>",
|
|
607
|
+
" <pass_rate>95%+</pass_rate>",
|
|
608
|
+
" <coverage>85%+</coverage>",
|
|
609
|
+
" <quality_score>95+</quality_score>",
|
|
610
|
+
" <zero_syntax_errors>MANDATORY</zero_syntax_errors>",
|
|
611
|
+
" </quality_requirements>",
|
|
612
|
+
"",
|
|
613
|
+
" <success_criteria>",
|
|
614
|
+
" Your implementation must:",
|
|
615
|
+
" 1. Address ALL failure patterns identified above",
|
|
616
|
+
" 2. Achieve exceptional quality scores (95+)",
|
|
617
|
+
" 3. Have zero syntax errors or runtime failures",
|
|
618
|
+
" 4. Include comprehensive edge case coverage",
|
|
619
|
+
" 5. Be production-ready with proper documentation",
|
|
620
|
+
" </success_criteria>",
|
|
621
|
+
" </expert_task>",
|
|
622
|
+
"</task>",
|
|
623
|
+
]
|
|
624
|
+
)
|
|
599
625
|
|
|
600
626
|
return "\n".join(prompt_parts)
|
|
601
627
|
|
|
@@ -613,8 +639,7 @@ class MetaOrchestrator:
|
|
|
613
639
|
'Error: <missing>'
|
|
614
640
|
"""
|
|
615
641
|
return (
|
|
616
|
-
text
|
|
617
|
-
.replace("&", "&")
|
|
642
|
+
text.replace("&", "&")
|
|
618
643
|
.replace("<", "<")
|
|
619
644
|
.replace(">", ">")
|
|
620
645
|
.replace('"', """)
|
|
@@ -622,9 +647,7 @@ class MetaOrchestrator:
|
|
|
622
647
|
)
|
|
623
648
|
|
|
624
649
|
def create_agent_team(
|
|
625
|
-
self,
|
|
626
|
-
tier: Tier,
|
|
627
|
-
failure_context: dict[str, Any] | None = None
|
|
650
|
+
self, tier: Tier, failure_context: dict[str, Any] | None = None
|
|
628
651
|
) -> list[str]:
|
|
629
652
|
"""Create specialized agent team for tier.
|
|
630
653
|
|
|
@@ -658,10 +681,7 @@ class MetaOrchestrator:
|
|
|
658
681
|
else: # PREMIUM
|
|
659
682
|
return ["generator", "analyzer", "reviewer"]
|
|
660
683
|
|
|
661
|
-
def analyze_failure_patterns(
|
|
662
|
-
self,
|
|
663
|
-
failures: list[dict[str, Any]]
|
|
664
|
-
) -> dict[str, Any]:
|
|
684
|
+
def analyze_failure_patterns(self, failures: list[dict[str, Any]]) -> dict[str, Any]:
|
|
665
685
|
"""Analyze failure patterns to inform next tier.
|
|
666
686
|
|
|
667
687
|
Groups failures by type and identifies common issues.
|
|
@@ -697,5 +717,7 @@ class MetaOrchestrator:
|
|
|
697
717
|
return {
|
|
698
718
|
"total_failures": len(failures),
|
|
699
719
|
"error_types": error_types,
|
|
700
|
-
"primary_issue":
|
|
720
|
+
"primary_issue": (
|
|
721
|
+
max(error_types.items(), key=lambda x: x[1])[0] if error_types else "unknown"
|
|
722
|
+
),
|
|
701
723
|
}
|
|
@@ -13,10 +13,7 @@ from pathlib import Path
|
|
|
13
13
|
from typing import Any
|
|
14
14
|
|
|
15
15
|
from empathy_os.config import _validate_file_path
|
|
16
|
-
from empathy_os.workflows.progressive.core import
|
|
17
|
-
ProgressiveWorkflowResult,
|
|
18
|
-
Tier,
|
|
19
|
-
)
|
|
16
|
+
from empathy_os.workflows.progressive.core import ProgressiveWorkflowResult, Tier
|
|
20
17
|
|
|
21
18
|
logger = logging.getLogger(__name__)
|
|
22
19
|
|
|
@@ -61,7 +58,9 @@ def generate_progression_report(result: ProgressiveWorkflowResult) -> str:
|
|
|
61
58
|
|
|
62
59
|
# Cost savings
|
|
63
60
|
if result.cost_savings > 0:
|
|
64
|
-
report.append(
|
|
61
|
+
report.append(
|
|
62
|
+
f"Cost Savings: ${result.cost_savings:.2f} ({result.cost_savings_percent:.0f}% vs all-Premium)"
|
|
63
|
+
)
|
|
65
64
|
report.append("")
|
|
66
65
|
|
|
67
66
|
report.append("TIER BREAKDOWN:")
|
|
@@ -69,11 +68,7 @@ def generate_progression_report(result: ProgressiveWorkflowResult) -> str:
|
|
|
69
68
|
|
|
70
69
|
# Tier-by-tier breakdown
|
|
71
70
|
for tier_result in result.tier_results:
|
|
72
|
-
tier_emoji = {
|
|
73
|
-
Tier.CHEAP: "💰",
|
|
74
|
-
Tier.CAPABLE: "📊",
|
|
75
|
-
Tier.PREMIUM: "💎"
|
|
76
|
-
}[tier_result.tier]
|
|
71
|
+
tier_emoji = {Tier.CHEAP: "💰", Tier.CAPABLE: "📊", Tier.PREMIUM: "💎"}[tier_result.tier]
|
|
77
72
|
|
|
78
73
|
report.append(f"{tier_emoji} {tier_result.tier.value.upper()} Tier ({tier_result.model})")
|
|
79
74
|
report.append(f" • Items: {len(tier_result.generated_items)}")
|
|
@@ -147,14 +142,16 @@ def save_results_to_disk(result: ProgressiveWorkflowResult, storage_path: str) -
|
|
|
147
142
|
summary = {
|
|
148
143
|
"workflow": result.workflow_name,
|
|
149
144
|
"task_id": result.task_id,
|
|
150
|
-
"timestamp":
|
|
145
|
+
"timestamp": (
|
|
146
|
+
result.tier_results[0].timestamp.isoformat() if result.tier_results else None
|
|
147
|
+
),
|
|
151
148
|
"total_cost": result.total_cost,
|
|
152
149
|
"total_duration": result.total_duration,
|
|
153
150
|
"cost_savings": result.cost_savings,
|
|
154
151
|
"cost_savings_percent": result.cost_savings_percent,
|
|
155
152
|
"success": result.success,
|
|
156
153
|
"tier_count": len(result.tier_results),
|
|
157
|
-
"final_cqs": result.final_result.quality_score if result.final_result else 0
|
|
154
|
+
"final_cqs": result.final_result.quality_score if result.final_result else 0,
|
|
158
155
|
}
|
|
159
156
|
|
|
160
157
|
summary_file = validated_dir / "summary.json"
|
|
@@ -179,9 +176,9 @@ def save_results_to_disk(result: ProgressiveWorkflowResult, storage_path: str) -
|
|
|
179
176
|
"test_pass_rate": tier_result.failure_analysis.test_pass_rate,
|
|
180
177
|
"coverage": tier_result.failure_analysis.coverage_percent,
|
|
181
178
|
"assertion_depth": tier_result.failure_analysis.assertion_depth,
|
|
182
|
-
"confidence": tier_result.failure_analysis.confidence_score
|
|
179
|
+
"confidence": tier_result.failure_analysis.confidence_score,
|
|
183
180
|
},
|
|
184
|
-
"item_count": len(tier_result.generated_items)
|
|
181
|
+
"item_count": len(tier_result.generated_items),
|
|
185
182
|
}
|
|
186
183
|
|
|
187
184
|
tier_file = validated_dir / f"tier_{i}_{tier_result.tier.value}.json"
|
|
@@ -222,7 +219,9 @@ def _format_duration(seconds: float) -> str:
|
|
|
222
219
|
return f"{minutes}m {remaining_seconds}s"
|
|
223
220
|
|
|
224
221
|
|
|
225
|
-
def load_result_from_disk(
|
|
222
|
+
def load_result_from_disk(
|
|
223
|
+
task_id: str, storage_path: str = ".empathy/progressive_runs"
|
|
224
|
+
) -> dict[str, Any]:
|
|
226
225
|
"""Load saved result from disk.
|
|
227
226
|
|
|
228
227
|
Args:
|
|
@@ -262,11 +261,7 @@ def load_result_from_disk(task_id: str, storage_path: str = ".empathy/progressiv
|
|
|
262
261
|
report_file = task_dir / "report.txt"
|
|
263
262
|
report = report_file.read_text() if report_file.exists() else ""
|
|
264
263
|
|
|
265
|
-
return {
|
|
266
|
-
"summary": summary,
|
|
267
|
-
"tier_results": tier_results,
|
|
268
|
-
"report": report
|
|
269
|
-
}
|
|
264
|
+
return {"summary": summary, "tier_results": tier_results, "report": report}
|
|
270
265
|
|
|
271
266
|
|
|
272
267
|
def list_saved_results(storage_path: str = ".empathy/progressive_runs") -> list[dict[str, Any]]:
|
|
@@ -311,9 +306,7 @@ def list_saved_results(storage_path: str = ".empathy/progressive_runs") -> list[
|
|
|
311
306
|
|
|
312
307
|
|
|
313
308
|
def cleanup_old_results(
|
|
314
|
-
storage_path: str = ".empathy/progressive_runs",
|
|
315
|
-
retention_days: int = 30,
|
|
316
|
-
dry_run: bool = False
|
|
309
|
+
storage_path: str = ".empathy/progressive_runs", retention_days: int = 30, dry_run: bool = False
|
|
317
310
|
) -> tuple[int, int]:
|
|
318
311
|
"""Clean up old progressive workflow results.
|
|
319
312
|
|
|
@@ -363,6 +356,7 @@ def cleanup_old_results(
|
|
|
363
356
|
# Old result, delete it
|
|
364
357
|
if not dry_run:
|
|
365
358
|
import shutil
|
|
359
|
+
|
|
366
360
|
shutil.rmtree(task_dir)
|
|
367
361
|
logger.info(f"Deleted old result: {task_dir.name}")
|
|
368
362
|
else:
|
|
@@ -378,9 +372,7 @@ def cleanup_old_results(
|
|
|
378
372
|
return (deleted_count, retained_count)
|
|
379
373
|
|
|
380
374
|
|
|
381
|
-
def generate_cost_analytics(
|
|
382
|
-
storage_path: str = ".empathy/progressive_runs"
|
|
383
|
-
) -> dict[str, Any]:
|
|
375
|
+
def generate_cost_analytics(storage_path: str = ".empathy/progressive_runs") -> dict[str, Any]:
|
|
384
376
|
"""Generate cost optimization analytics from saved results.
|
|
385
377
|
|
|
386
378
|
Analyzes historical progressive workflow runs to provide insights:
|
|
@@ -408,7 +400,7 @@ def generate_cost_analytics(
|
|
|
408
400
|
"total_runs": 0,
|
|
409
401
|
"total_cost": 0.0,
|
|
410
402
|
"total_savings": 0.0,
|
|
411
|
-
"avg_savings_percent": 0.0
|
|
403
|
+
"avg_savings_percent": 0.0,
|
|
412
404
|
}
|
|
413
405
|
|
|
414
406
|
total_runs = len(results)
|
|
@@ -417,8 +409,7 @@ def generate_cost_analytics(
|
|
|
417
409
|
|
|
418
410
|
# Calculate average savings percent (weighted by cost)
|
|
419
411
|
weighted_savings = sum(
|
|
420
|
-
r.get("cost_savings_percent", 0) * r.get("total_cost", 0)
|
|
421
|
-
for r in results
|
|
412
|
+
r.get("cost_savings_percent", 0) * r.get("total_cost", 0) for r in results
|
|
422
413
|
)
|
|
423
414
|
avg_savings_percent = weighted_savings / total_cost if total_cost > 0 else 0
|
|
424
415
|
|
|
@@ -450,7 +441,7 @@ def generate_cost_analytics(
|
|
|
450
441
|
"runs": 0,
|
|
451
442
|
"total_cost": 0.0,
|
|
452
443
|
"total_savings": 0.0,
|
|
453
|
-
"successes": 0
|
|
444
|
+
"successes": 0,
|
|
454
445
|
}
|
|
455
446
|
|
|
456
447
|
stats = workflow_stats[workflow]
|
|
@@ -476,7 +467,7 @@ def generate_cost_analytics(
|
|
|
476
467
|
"avg_final_cqs": round(avg_cqs, 1),
|
|
477
468
|
"tier_usage": tier_usage,
|
|
478
469
|
"tier_costs": tier_costs,
|
|
479
|
-
"workflow_stats": workflow_stats
|
|
470
|
+
"workflow_stats": workflow_stats,
|
|
480
471
|
}
|
|
481
472
|
|
|
482
473
|
|