empathy-framework 3.2.3__py3-none-any.whl → 3.8.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coach_wizards/__init__.py +11 -12
- coach_wizards/accessibility_wizard.py +12 -12
- coach_wizards/api_wizard.py +12 -12
- coach_wizards/base_wizard.py +26 -20
- coach_wizards/cicd_wizard.py +15 -13
- coach_wizards/code_reviewer_README.md +60 -0
- coach_wizards/code_reviewer_wizard.py +180 -0
- coach_wizards/compliance_wizard.py +12 -12
- coach_wizards/database_wizard.py +12 -12
- coach_wizards/debugging_wizard.py +12 -12
- coach_wizards/documentation_wizard.py +12 -12
- coach_wizards/generate_wizards.py +1 -2
- coach_wizards/localization_wizard.py +101 -19
- coach_wizards/migration_wizard.py +12 -12
- coach_wizards/monitoring_wizard.py +12 -12
- coach_wizards/observability_wizard.py +12 -12
- coach_wizards/performance_wizard.py +12 -12
- coach_wizards/prompt_engineering_wizard.py +22 -25
- coach_wizards/refactoring_wizard.py +12 -12
- coach_wizards/scaling_wizard.py +12 -12
- coach_wizards/security_wizard.py +12 -12
- coach_wizards/testing_wizard.py +12 -12
- {empathy_framework-3.2.3.dist-info → empathy_framework-3.8.2.dist-info}/METADATA +513 -58
- empathy_framework-3.8.2.dist-info/RECORD +333 -0
- empathy_framework-3.8.2.dist-info/entry_points.txt +22 -0
- {empathy_framework-3.2.3.dist-info → empathy_framework-3.8.2.dist-info}/top_level.txt +5 -1
- empathy_healthcare_plugin/__init__.py +1 -2
- empathy_healthcare_plugin/monitors/__init__.py +9 -0
- empathy_healthcare_plugin/monitors/clinical_protocol_monitor.py +315 -0
- empathy_healthcare_plugin/monitors/monitoring/__init__.py +44 -0
- empathy_healthcare_plugin/monitors/monitoring/protocol_checker.py +300 -0
- empathy_healthcare_plugin/monitors/monitoring/protocol_loader.py +214 -0
- empathy_healthcare_plugin/monitors/monitoring/sensor_parsers.py +306 -0
- empathy_healthcare_plugin/monitors/monitoring/trajectory_analyzer.py +389 -0
- empathy_llm_toolkit/__init__.py +7 -7
- empathy_llm_toolkit/agent_factory/__init__.py +53 -0
- empathy_llm_toolkit/agent_factory/adapters/__init__.py +85 -0
- empathy_llm_toolkit/agent_factory/adapters/autogen_adapter.py +312 -0
- empathy_llm_toolkit/agent_factory/adapters/crewai_adapter.py +454 -0
- empathy_llm_toolkit/agent_factory/adapters/haystack_adapter.py +298 -0
- empathy_llm_toolkit/agent_factory/adapters/langchain_adapter.py +362 -0
- empathy_llm_toolkit/agent_factory/adapters/langgraph_adapter.py +333 -0
- empathy_llm_toolkit/agent_factory/adapters/native.py +228 -0
- empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +426 -0
- empathy_llm_toolkit/agent_factory/base.py +305 -0
- empathy_llm_toolkit/agent_factory/crews/__init__.py +67 -0
- empathy_llm_toolkit/agent_factory/crews/code_review.py +1113 -0
- empathy_llm_toolkit/agent_factory/crews/health_check.py +1246 -0
- empathy_llm_toolkit/agent_factory/crews/refactoring.py +1128 -0
- empathy_llm_toolkit/agent_factory/crews/security_audit.py +1018 -0
- empathy_llm_toolkit/agent_factory/decorators.py +286 -0
- empathy_llm_toolkit/agent_factory/factory.py +558 -0
- empathy_llm_toolkit/agent_factory/framework.py +192 -0
- empathy_llm_toolkit/agent_factory/memory_integration.py +324 -0
- empathy_llm_toolkit/agent_factory/resilient.py +320 -0
- empathy_llm_toolkit/claude_memory.py +14 -15
- empathy_llm_toolkit/cli/__init__.py +8 -0
- empathy_llm_toolkit/cli/sync_claude.py +487 -0
- empathy_llm_toolkit/code_health.py +177 -22
- empathy_llm_toolkit/config/__init__.py +29 -0
- empathy_llm_toolkit/config/unified.py +295 -0
- empathy_llm_toolkit/contextual_patterns.py +11 -12
- empathy_llm_toolkit/core.py +51 -49
- empathy_llm_toolkit/git_pattern_extractor.py +16 -12
- empathy_llm_toolkit/levels.py +6 -13
- empathy_llm_toolkit/pattern_confidence.py +14 -18
- empathy_llm_toolkit/pattern_resolver.py +10 -12
- empathy_llm_toolkit/pattern_summary.py +13 -11
- empathy_llm_toolkit/providers.py +194 -28
- empathy_llm_toolkit/routing/__init__.py +32 -0
- empathy_llm_toolkit/routing/model_router.py +362 -0
- empathy_llm_toolkit/security/IMPLEMENTATION_SUMMARY.md +413 -0
- empathy_llm_toolkit/security/PHASE2_COMPLETE.md +384 -0
- empathy_llm_toolkit/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
- empathy_llm_toolkit/security/QUICK_REFERENCE.md +316 -0
- empathy_llm_toolkit/security/README.md +262 -0
- empathy_llm_toolkit/security/__init__.py +62 -0
- empathy_llm_toolkit/security/audit_logger.py +929 -0
- empathy_llm_toolkit/security/audit_logger_example.py +152 -0
- empathy_llm_toolkit/security/pii_scrubber.py +640 -0
- empathy_llm_toolkit/security/secrets_detector.py +678 -0
- empathy_llm_toolkit/security/secrets_detector_example.py +304 -0
- empathy_llm_toolkit/security/secure_memdocs.py +1192 -0
- empathy_llm_toolkit/security/secure_memdocs_example.py +278 -0
- empathy_llm_toolkit/session_status.py +18 -20
- empathy_llm_toolkit/state.py +20 -21
- empathy_llm_toolkit/wizards/__init__.py +38 -0
- empathy_llm_toolkit/wizards/base_wizard.py +364 -0
- empathy_llm_toolkit/wizards/customer_support_wizard.py +190 -0
- empathy_llm_toolkit/wizards/healthcare_wizard.py +362 -0
- empathy_llm_toolkit/wizards/patient_assessment_README.md +64 -0
- empathy_llm_toolkit/wizards/patient_assessment_wizard.py +193 -0
- empathy_llm_toolkit/wizards/technology_wizard.py +194 -0
- empathy_os/__init__.py +76 -77
- empathy_os/adaptive/__init__.py +13 -0
- empathy_os/adaptive/task_complexity.py +127 -0
- empathy_os/{monitoring.py → agent_monitoring.py} +27 -27
- empathy_os/cache/__init__.py +117 -0
- empathy_os/cache/base.py +166 -0
- empathy_os/cache/dependency_manager.py +253 -0
- empathy_os/cache/hash_only.py +248 -0
- empathy_os/cache/hybrid.py +390 -0
- empathy_os/cache/storage.py +282 -0
- empathy_os/cli.py +515 -109
- empathy_os/cli_unified.py +189 -42
- empathy_os/config/__init__.py +63 -0
- empathy_os/config/xml_config.py +239 -0
- empathy_os/config.py +87 -36
- empathy_os/coordination.py +48 -54
- empathy_os/core.py +90 -99
- empathy_os/cost_tracker.py +20 -23
- empathy_os/dashboard/__init__.py +15 -0
- empathy_os/dashboard/server.py +743 -0
- empathy_os/discovery.py +9 -11
- empathy_os/emergence.py +20 -21
- empathy_os/exceptions.py +18 -30
- empathy_os/feedback_loops.py +27 -30
- empathy_os/levels.py +31 -34
- empathy_os/leverage_points.py +27 -28
- empathy_os/logging_config.py +11 -12
- empathy_os/memory/__init__.py +195 -0
- empathy_os/memory/claude_memory.py +466 -0
- empathy_os/memory/config.py +224 -0
- empathy_os/memory/control_panel.py +1298 -0
- empathy_os/memory/edges.py +179 -0
- empathy_os/memory/graph.py +567 -0
- empathy_os/memory/long_term.py +1194 -0
- empathy_os/memory/nodes.py +179 -0
- empathy_os/memory/redis_bootstrap.py +540 -0
- empathy_os/memory/security/__init__.py +31 -0
- empathy_os/memory/security/audit_logger.py +930 -0
- empathy_os/memory/security/pii_scrubber.py +640 -0
- empathy_os/memory/security/secrets_detector.py +678 -0
- empathy_os/memory/short_term.py +2119 -0
- empathy_os/memory/storage/__init__.py +15 -0
- empathy_os/memory/summary_index.py +583 -0
- empathy_os/memory/unified.py +619 -0
- empathy_os/metrics/__init__.py +12 -0
- empathy_os/metrics/prompt_metrics.py +190 -0
- empathy_os/models/__init__.py +136 -0
- empathy_os/models/__main__.py +13 -0
- empathy_os/models/cli.py +655 -0
- empathy_os/models/empathy_executor.py +354 -0
- empathy_os/models/executor.py +252 -0
- empathy_os/models/fallback.py +671 -0
- empathy_os/models/provider_config.py +563 -0
- empathy_os/models/registry.py +382 -0
- empathy_os/models/tasks.py +302 -0
- empathy_os/models/telemetry.py +548 -0
- empathy_os/models/token_estimator.py +378 -0
- empathy_os/models/validation.py +274 -0
- empathy_os/monitoring/__init__.py +52 -0
- empathy_os/monitoring/alerts.py +23 -0
- empathy_os/monitoring/alerts_cli.py +268 -0
- empathy_os/monitoring/multi_backend.py +271 -0
- empathy_os/monitoring/otel_backend.py +363 -0
- empathy_os/optimization/__init__.py +19 -0
- empathy_os/optimization/context_optimizer.py +272 -0
- empathy_os/pattern_library.py +29 -28
- empathy_os/persistence.py +30 -34
- empathy_os/platform_utils.py +261 -0
- empathy_os/plugins/__init__.py +28 -0
- empathy_os/plugins/base.py +361 -0
- empathy_os/plugins/registry.py +268 -0
- empathy_os/project_index/__init__.py +30 -0
- empathy_os/project_index/cli.py +335 -0
- empathy_os/project_index/crew_integration.py +430 -0
- empathy_os/project_index/index.py +425 -0
- empathy_os/project_index/models.py +501 -0
- empathy_os/project_index/reports.py +473 -0
- empathy_os/project_index/scanner.py +538 -0
- empathy_os/prompts/__init__.py +61 -0
- empathy_os/prompts/config.py +77 -0
- empathy_os/prompts/context.py +177 -0
- empathy_os/prompts/parser.py +285 -0
- empathy_os/prompts/registry.py +313 -0
- empathy_os/prompts/templates.py +208 -0
- empathy_os/redis_config.py +144 -58
- empathy_os/redis_memory.py +53 -56
- empathy_os/resilience/__init__.py +56 -0
- empathy_os/resilience/circuit_breaker.py +256 -0
- empathy_os/resilience/fallback.py +179 -0
- empathy_os/resilience/health.py +300 -0
- empathy_os/resilience/retry.py +209 -0
- empathy_os/resilience/timeout.py +135 -0
- empathy_os/routing/__init__.py +43 -0
- empathy_os/routing/chain_executor.py +433 -0
- empathy_os/routing/classifier.py +217 -0
- empathy_os/routing/smart_router.py +234 -0
- empathy_os/routing/wizard_registry.py +307 -0
- empathy_os/templates.py +12 -11
- empathy_os/trust/__init__.py +28 -0
- empathy_os/trust/circuit_breaker.py +579 -0
- empathy_os/trust_building.py +44 -36
- empathy_os/validation/__init__.py +19 -0
- empathy_os/validation/xml_validator.py +281 -0
- empathy_os/wizard_factory_cli.py +170 -0
- empathy_os/{workflows.py → workflow_commands.py} +123 -31
- empathy_os/workflows/__init__.py +360 -0
- empathy_os/workflows/base.py +1660 -0
- empathy_os/workflows/bug_predict.py +962 -0
- empathy_os/workflows/code_review.py +960 -0
- empathy_os/workflows/code_review_adapters.py +310 -0
- empathy_os/workflows/code_review_pipeline.py +720 -0
- empathy_os/workflows/config.py +600 -0
- empathy_os/workflows/dependency_check.py +648 -0
- empathy_os/workflows/document_gen.py +1069 -0
- empathy_os/workflows/documentation_orchestrator.py +1205 -0
- empathy_os/workflows/health_check.py +679 -0
- empathy_os/workflows/keyboard_shortcuts/__init__.py +39 -0
- empathy_os/workflows/keyboard_shortcuts/generators.py +386 -0
- empathy_os/workflows/keyboard_shortcuts/parsers.py +414 -0
- empathy_os/workflows/keyboard_shortcuts/prompts.py +295 -0
- empathy_os/workflows/keyboard_shortcuts/schema.py +193 -0
- empathy_os/workflows/keyboard_shortcuts/workflow.py +505 -0
- empathy_os/workflows/manage_documentation.py +804 -0
- empathy_os/workflows/new_sample_workflow1.py +146 -0
- empathy_os/workflows/new_sample_workflow1_README.md +150 -0
- empathy_os/workflows/perf_audit.py +687 -0
- empathy_os/workflows/pr_review.py +748 -0
- empathy_os/workflows/progress.py +445 -0
- empathy_os/workflows/progress_server.py +322 -0
- empathy_os/workflows/refactor_plan.py +693 -0
- empathy_os/workflows/release_prep.py +808 -0
- empathy_os/workflows/research_synthesis.py +404 -0
- empathy_os/workflows/secure_release.py +585 -0
- empathy_os/workflows/security_adapters.py +297 -0
- empathy_os/workflows/security_audit.py +1046 -0
- empathy_os/workflows/step_config.py +234 -0
- empathy_os/workflows/test5.py +125 -0
- empathy_os/workflows/test5_README.md +158 -0
- empathy_os/workflows/test_gen.py +1855 -0
- empathy_os/workflows/test_lifecycle.py +526 -0
- empathy_os/workflows/test_maintenance.py +626 -0
- empathy_os/workflows/test_maintenance_cli.py +590 -0
- empathy_os/workflows/test_maintenance_crew.py +821 -0
- empathy_os/workflows/xml_enhanced_crew.py +285 -0
- empathy_software_plugin/__init__.py +1 -2
- empathy_software_plugin/cli/__init__.py +120 -0
- empathy_software_plugin/cli/inspect.py +362 -0
- empathy_software_plugin/cli.py +35 -26
- empathy_software_plugin/plugin.py +4 -8
- empathy_software_plugin/wizards/__init__.py +42 -0
- empathy_software_plugin/wizards/advanced_debugging_wizard.py +392 -0
- empathy_software_plugin/wizards/agent_orchestration_wizard.py +511 -0
- empathy_software_plugin/wizards/ai_collaboration_wizard.py +503 -0
- empathy_software_plugin/wizards/ai_context_wizard.py +441 -0
- empathy_software_plugin/wizards/ai_documentation_wizard.py +503 -0
- empathy_software_plugin/wizards/base_wizard.py +288 -0
- empathy_software_plugin/wizards/book_chapter_wizard.py +519 -0
- empathy_software_plugin/wizards/code_review_wizard.py +606 -0
- empathy_software_plugin/wizards/debugging/__init__.py +50 -0
- empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +414 -0
- empathy_software_plugin/wizards/debugging/config_loaders.py +442 -0
- empathy_software_plugin/wizards/debugging/fix_applier.py +469 -0
- empathy_software_plugin/wizards/debugging/language_patterns.py +383 -0
- empathy_software_plugin/wizards/debugging/linter_parsers.py +470 -0
- empathy_software_plugin/wizards/debugging/verification.py +369 -0
- empathy_software_plugin/wizards/enhanced_testing_wizard.py +537 -0
- empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +816 -0
- empathy_software_plugin/wizards/multi_model_wizard.py +501 -0
- empathy_software_plugin/wizards/pattern_extraction_wizard.py +422 -0
- empathy_software_plugin/wizards/pattern_retriever_wizard.py +400 -0
- empathy_software_plugin/wizards/performance/__init__.py +9 -0
- empathy_software_plugin/wizards/performance/bottleneck_detector.py +221 -0
- empathy_software_plugin/wizards/performance/profiler_parsers.py +278 -0
- empathy_software_plugin/wizards/performance/trajectory_analyzer.py +429 -0
- empathy_software_plugin/wizards/performance_profiling_wizard.py +305 -0
- empathy_software_plugin/wizards/prompt_engineering_wizard.py +425 -0
- empathy_software_plugin/wizards/rag_pattern_wizard.py +461 -0
- empathy_software_plugin/wizards/security/__init__.py +32 -0
- empathy_software_plugin/wizards/security/exploit_analyzer.py +290 -0
- empathy_software_plugin/wizards/security/owasp_patterns.py +241 -0
- empathy_software_plugin/wizards/security/vulnerability_scanner.py +604 -0
- empathy_software_plugin/wizards/security_analysis_wizard.py +322 -0
- empathy_software_plugin/wizards/security_learning_wizard.py +740 -0
- empathy_software_plugin/wizards/tech_debt_wizard.py +726 -0
- empathy_software_plugin/wizards/testing/__init__.py +27 -0
- empathy_software_plugin/wizards/testing/coverage_analyzer.py +459 -0
- empathy_software_plugin/wizards/testing/quality_analyzer.py +531 -0
- empathy_software_plugin/wizards/testing/test_suggester.py +533 -0
- empathy_software_plugin/wizards/testing_wizard.py +274 -0
- hot_reload/README.md +473 -0
- hot_reload/__init__.py +62 -0
- hot_reload/config.py +84 -0
- hot_reload/integration.py +228 -0
- hot_reload/reloader.py +298 -0
- hot_reload/watcher.py +179 -0
- hot_reload/websocket.py +176 -0
- scaffolding/README.md +589 -0
- scaffolding/__init__.py +35 -0
- scaffolding/__main__.py +14 -0
- scaffolding/cli.py +240 -0
- test_generator/__init__.py +38 -0
- test_generator/__main__.py +14 -0
- test_generator/cli.py +226 -0
- test_generator/generator.py +325 -0
- test_generator/risk_analyzer.py +216 -0
- workflow_patterns/__init__.py +33 -0
- workflow_patterns/behavior.py +249 -0
- workflow_patterns/core.py +76 -0
- workflow_patterns/output.py +99 -0
- workflow_patterns/registry.py +255 -0
- workflow_patterns/structural.py +288 -0
- workflow_scaffolding/__init__.py +11 -0
- workflow_scaffolding/__main__.py +12 -0
- workflow_scaffolding/cli.py +206 -0
- workflow_scaffolding/generator.py +265 -0
- agents/code_inspection/patterns/inspection/recurring_B112.json +0 -18
- agents/code_inspection/patterns/inspection/recurring_F541.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_FORMAT.json +0 -25
- agents/code_inspection/patterns/inspection/recurring_bug_20250822_def456.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20250915_abc123.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_3c5b9951.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_97c0f72f.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_a0871d53.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_a9b6ec41.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_null_001.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_builtin.json +0 -16
- agents/compliance_anticipation_agent.py +0 -1427
- agents/epic_integration_wizard.py +0 -541
- agents/trust_building_behaviors.py +0 -891
- empathy_framework-3.2.3.dist-info/RECORD +0 -104
- empathy_framework-3.2.3.dist-info/entry_points.txt +0 -7
- empathy_llm_toolkit/htmlcov/status.json +0 -1
- empathy_llm_toolkit/security/htmlcov/status.json +0 -1
- {empathy_framework-3.2.3.dist-info → empathy_framework-3.8.2.dist-info}/WHEEL +0 -0
- {empathy_framework-3.2.3.dist-info → empathy_framework-3.8.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"""Behavioral workflow patterns.
|
|
2
|
+
|
|
3
|
+
Patterns for conditional execution and dynamic behavior.
|
|
4
|
+
|
|
5
|
+
Copyright 2025 Smart-AI-Memory
|
|
6
|
+
Licensed under Fair Source License 0.9
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from .core import CodeSection, PatternCategory, WorkflowComplexity, WorkflowPattern
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ConditionalTierPattern(WorkflowPattern):
|
|
15
|
+
"""Dynamic tier routing based on complexity or conditions.
|
|
16
|
+
|
|
17
|
+
Use for: Cost optimization by downgrading/skipping expensive stages.
|
|
18
|
+
Examples: bug-predict (skip premium if low risk), code-review (conditional architect review).
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
id: str = "conditional-tier"
|
|
22
|
+
name: str = "Conditional Tier Routing"
|
|
23
|
+
category: PatternCategory = PatternCategory.BEHAVIOR
|
|
24
|
+
description: str = "Dynamically adjust model tiers based on conditions"
|
|
25
|
+
complexity: WorkflowComplexity = WorkflowComplexity.MODERATE
|
|
26
|
+
use_cases: list[str] = [
|
|
27
|
+
"Cost optimization",
|
|
28
|
+
"Conditional premium tier usage",
|
|
29
|
+
"Complexity-based routing",
|
|
30
|
+
]
|
|
31
|
+
examples: list[str] = ["bug-predict", "code-review", "pr-review"]
|
|
32
|
+
requires: list[str] = ["multi-stage"]
|
|
33
|
+
risk_weight: float = 3.0
|
|
34
|
+
|
|
35
|
+
def generate_code_sections(self, context: dict[str, Any]) -> list[CodeSection]:
|
|
36
|
+
"""Generate code for conditional tier routing."""
|
|
37
|
+
threshold_param = context.get("threshold_param", "complexity_threshold")
|
|
38
|
+
threshold_default = context.get("threshold_default", "0.7")
|
|
39
|
+
metric_name = context.get("metric_name", "complexity_score")
|
|
40
|
+
|
|
41
|
+
return [
|
|
42
|
+
CodeSection(
|
|
43
|
+
location="init_method",
|
|
44
|
+
code=f""" self.{threshold_param} = {threshold_param} if {threshold_param} is not None else {threshold_default}
|
|
45
|
+
self._{metric_name}: float = 0.0""",
|
|
46
|
+
priority=1,
|
|
47
|
+
),
|
|
48
|
+
CodeSection(
|
|
49
|
+
location="methods",
|
|
50
|
+
code=f''' def should_skip_stage(self, stage_name: str, input_data: Any) -> tuple[bool, str | None]:
|
|
51
|
+
"""Conditionally downgrade or skip stages based on {metric_name}.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
stage_name: Name of the stage to check
|
|
55
|
+
input_data: Current workflow data
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Tuple of (should_skip, reason)
|
|
59
|
+
|
|
60
|
+
"""
|
|
61
|
+
# Example: Downgrade premium stage if metric below threshold
|
|
62
|
+
if stage_name == "recommend" or stage_name == "architect_review":
|
|
63
|
+
if self._{metric_name} < self.{threshold_param}:
|
|
64
|
+
# Downgrade to CAPABLE instead of skipping
|
|
65
|
+
self.tier_map[stage_name] = ModelTier.CAPABLE
|
|
66
|
+
logger.info(f"Downgraded {{stage_name}} to CAPABLE ({metric_name}: {{self._{metric_name}:.2f}})")
|
|
67
|
+
return False, None
|
|
68
|
+
return False, None''',
|
|
69
|
+
priority=2,
|
|
70
|
+
),
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class ConfigDrivenPattern(WorkflowPattern):
|
|
75
|
+
"""Load configuration from empathy.config.yml.
|
|
76
|
+
|
|
77
|
+
Use for: Configurable thresholds, options, and behavior.
|
|
78
|
+
Examples: bug-predict (risk threshold), health-check (check toggles).
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
id: str = "config-driven"
|
|
82
|
+
name: str = "Configuration-Driven Workflow"
|
|
83
|
+
category: PatternCategory = PatternCategory.BEHAVIOR
|
|
84
|
+
description: str = "Loads settings from empathy.config.yml"
|
|
85
|
+
complexity: WorkflowComplexity = WorkflowComplexity.SIMPLE
|
|
86
|
+
use_cases: list[str] = [
|
|
87
|
+
"Configurable thresholds",
|
|
88
|
+
"User-customizable behavior",
|
|
89
|
+
"Environment-specific settings",
|
|
90
|
+
]
|
|
91
|
+
examples: list[str] = ["bug-predict", "health-check", "security-audit"]
|
|
92
|
+
risk_weight: float = 1.5
|
|
93
|
+
|
|
94
|
+
def generate_code_sections(self, context: dict[str, Any]) -> list[CodeSection]:
|
|
95
|
+
"""Generate code for configuration loading."""
|
|
96
|
+
workflow_name = context.get("workflow_name", "my-workflow")
|
|
97
|
+
config_key = workflow_name.replace("-", "_")
|
|
98
|
+
config_params = context.get(
|
|
99
|
+
"config_params",
|
|
100
|
+
{
|
|
101
|
+
"threshold": 0.7,
|
|
102
|
+
"enabled": True,
|
|
103
|
+
},
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Generate defaults dict
|
|
107
|
+
defaults_code = " defaults = {\n"
|
|
108
|
+
for key, value in config_params.items():
|
|
109
|
+
if isinstance(value, str):
|
|
110
|
+
defaults_code += f' "{key}": "{value}",\n'
|
|
111
|
+
else:
|
|
112
|
+
defaults_code += f' "{key}": {value},\n'
|
|
113
|
+
defaults_code += " }"
|
|
114
|
+
|
|
115
|
+
# Generate config loading
|
|
116
|
+
return [
|
|
117
|
+
CodeSection(
|
|
118
|
+
location="imports",
|
|
119
|
+
code="import yaml\nfrom pathlib import Path",
|
|
120
|
+
priority=1,
|
|
121
|
+
),
|
|
122
|
+
CodeSection(
|
|
123
|
+
location="helper_functions",
|
|
124
|
+
code=f'''def _load_{config_key}_config() -> dict:
|
|
125
|
+
"""Load {config_key} configuration from empathy.config.yml.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Dict with {config_key} settings, or defaults if not found.
|
|
129
|
+
|
|
130
|
+
"""
|
|
131
|
+
{defaults_code}
|
|
132
|
+
|
|
133
|
+
config_paths = [
|
|
134
|
+
Path("empathy.config.yml"),
|
|
135
|
+
Path("empathy.config.yaml"),
|
|
136
|
+
Path(".empathy.yml"),
|
|
137
|
+
Path(".empathy.yaml"),
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
for config_path in config_paths:
|
|
141
|
+
if config_path.exists():
|
|
142
|
+
try:
|
|
143
|
+
with open(config_path) as f:
|
|
144
|
+
config = yaml.safe_load(f)
|
|
145
|
+
if config and "{config_key}" in config:
|
|
146
|
+
return {{**defaults, **config["{config_key}"]}}
|
|
147
|
+
except (yaml.YAMLError, OSError):
|
|
148
|
+
pass
|
|
149
|
+
|
|
150
|
+
return defaults''',
|
|
151
|
+
priority=1,
|
|
152
|
+
),
|
|
153
|
+
CodeSection(
|
|
154
|
+
location="init_method",
|
|
155
|
+
code=f""" # Load configuration
|
|
156
|
+
self._config = _load_{config_key}_config()""",
|
|
157
|
+
priority=1,
|
|
158
|
+
),
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class CodeScannerPattern(WorkflowPattern):
|
|
163
|
+
"""File scanning and analysis capabilities.
|
|
164
|
+
|
|
165
|
+
Use for: Code analysis workflows that scan files.
|
|
166
|
+
Examples: bug-predict, security-audit, test-gen.
|
|
167
|
+
"""
|
|
168
|
+
|
|
169
|
+
id: str = "code-scanner"
|
|
170
|
+
name: str = "Code Scanner"
|
|
171
|
+
category: PatternCategory = PatternCategory.BEHAVIOR
|
|
172
|
+
description: str = "Scan and analyze code files with pattern matching"
|
|
173
|
+
complexity: WorkflowComplexity = WorkflowComplexity.MODERATE
|
|
174
|
+
use_cases: list[str] = [
|
|
175
|
+
"Bug detection",
|
|
176
|
+
"Security scanning",
|
|
177
|
+
"Code analysis",
|
|
178
|
+
]
|
|
179
|
+
examples: list[str] = ["bug-predict", "security-audit"]
|
|
180
|
+
risk_weight: float = 2.0
|
|
181
|
+
|
|
182
|
+
def generate_code_sections(self, context: dict[str, Any]) -> list[CodeSection]:
|
|
183
|
+
"""Generate code for file scanning."""
|
|
184
|
+
scan_pattern = context.get("scan_pattern", "*.py")
|
|
185
|
+
|
|
186
|
+
return [
|
|
187
|
+
CodeSection(
|
|
188
|
+
location="imports",
|
|
189
|
+
code="import fnmatch\nfrom pathlib import Path",
|
|
190
|
+
priority=1,
|
|
191
|
+
),
|
|
192
|
+
CodeSection(
|
|
193
|
+
location="helper_functions",
|
|
194
|
+
code=f'''def _should_exclude_file(file_path: str, exclude_patterns: list[str]) -> bool:
|
|
195
|
+
"""Check if a file should be excluded based on glob patterns.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
file_path: Path to the file
|
|
199
|
+
exclude_patterns: List of glob patterns (e.g., "**/test_*.py")
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
True if the file matches any exclusion pattern.
|
|
203
|
+
|
|
204
|
+
"""
|
|
205
|
+
for pattern in exclude_patterns:
|
|
206
|
+
if "**" in pattern:
|
|
207
|
+
parts = pattern.split("**")
|
|
208
|
+
if len(parts) == 2:
|
|
209
|
+
prefix, suffix = parts
|
|
210
|
+
if prefix and not file_path.startswith(prefix.rstrip("/")):
|
|
211
|
+
continue
|
|
212
|
+
if suffix and fnmatch.fnmatch(file_path, f"*{{suffix}}"):
|
|
213
|
+
return True
|
|
214
|
+
elif fnmatch.fnmatch(file_path, pattern) or fnmatch.fnmatch(
|
|
215
|
+
Path(file_path).name,
|
|
216
|
+
pattern,
|
|
217
|
+
):
|
|
218
|
+
return True
|
|
219
|
+
return False
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _scan_files(
|
|
223
|
+
root_dir: str = ".",
|
|
224
|
+
pattern: str = "{scan_pattern}",
|
|
225
|
+
exclude: list[str] | None = None,
|
|
226
|
+
) -> list[Path]:
|
|
227
|
+
"""Scan directory for files matching pattern.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
root_dir: Root directory to scan
|
|
231
|
+
pattern: Glob pattern for files
|
|
232
|
+
exclude: Exclusion patterns
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
List of matching file paths
|
|
236
|
+
|
|
237
|
+
"""
|
|
238
|
+
exclude = exclude or []
|
|
239
|
+
root = Path(root_dir)
|
|
240
|
+
files = []
|
|
241
|
+
|
|
242
|
+
for file_path in root.rglob(pattern):
|
|
243
|
+
if file_path.is_file() and not _should_exclude_file(str(file_path), exclude):
|
|
244
|
+
files.append(file_path)
|
|
245
|
+
|
|
246
|
+
return files''',
|
|
247
|
+
priority=1,
|
|
248
|
+
),
|
|
249
|
+
]
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Core workflow pattern definitions.
|
|
2
|
+
|
|
3
|
+
Defines Pydantic models for workflow patterns extracted from existing workflows.
|
|
4
|
+
|
|
5
|
+
Copyright 2025 Smart-AI-Memory
|
|
6
|
+
Licensed under Fair Source License 0.9
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from enum import Enum
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from pydantic import BaseModel, Field
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PatternCategory(Enum):
|
|
17
|
+
"""Categories for workflow patterns."""
|
|
18
|
+
|
|
19
|
+
STRUCTURAL = "structural" # How workflow is organized
|
|
20
|
+
TIER = "tier" # Tier routing strategies
|
|
21
|
+
INTEGRATION = "integration" # External integrations
|
|
22
|
+
OUTPUT = "output" # Output formatting
|
|
23
|
+
BEHAVIOR = "behavior" # Behavioral patterns
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class WorkflowComplexity(Enum):
|
|
27
|
+
"""Workflow complexity levels."""
|
|
28
|
+
|
|
29
|
+
SIMPLE = "simple" # Single stage, no conditions
|
|
30
|
+
MODERATE = "moderate" # Multiple stages, some conditions
|
|
31
|
+
COMPLEX = "complex" # Multiple stages, conditional routing, crews
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class CodeSection:
|
|
36
|
+
"""A section of code to be generated."""
|
|
37
|
+
|
|
38
|
+
location: str # Where in the file (e.g., "imports", "class_body", "methods")
|
|
39
|
+
code: str # The code content
|
|
40
|
+
priority: int = 0 # Higher priority sections are placed first
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class WorkflowPattern(BaseModel):
|
|
44
|
+
"""Base model for workflow patterns."""
|
|
45
|
+
|
|
46
|
+
id: str = Field(..., description="Unique pattern identifier")
|
|
47
|
+
name: str = Field(..., description="Human-readable pattern name")
|
|
48
|
+
category: PatternCategory = Field(..., description="Pattern category")
|
|
49
|
+
description: str = Field(..., description="Pattern description")
|
|
50
|
+
complexity: WorkflowComplexity = Field(..., description="Pattern complexity")
|
|
51
|
+
use_cases: list[str] = Field(default_factory=list, description="When to use this pattern")
|
|
52
|
+
examples: list[str] = Field(
|
|
53
|
+
default_factory=list, description="Example workflows using this pattern"
|
|
54
|
+
)
|
|
55
|
+
conflicts_with: list[str] = Field(default_factory=list, description="Incompatible pattern IDs")
|
|
56
|
+
requires: list[str] = Field(default_factory=list, description="Required pattern IDs")
|
|
57
|
+
risk_weight: float = Field(
|
|
58
|
+
default=1.0, ge=0.0, le=5.0, description="Risk factor for testing (1=low, 5=high)"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def generate_code_sections(self, context: dict[str, Any]) -> list[CodeSection]:
|
|
62
|
+
"""Generate code sections for this pattern.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
context: Context dictionary with workflow metadata
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
List of CodeSection objects to be merged
|
|
69
|
+
|
|
70
|
+
"""
|
|
71
|
+
raise NotImplementedError("Subclasses must implement generate_code_sections")
|
|
72
|
+
|
|
73
|
+
class Config:
|
|
74
|
+
"""Pydantic config."""
|
|
75
|
+
|
|
76
|
+
use_enum_values = True
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Output formatting patterns.
|
|
2
|
+
|
|
3
|
+
Patterns for structured workflow results.
|
|
4
|
+
|
|
5
|
+
Copyright 2025 Smart-AI-Memory
|
|
6
|
+
Licensed under Fair Source License 0.9
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from .core import CodeSection, PatternCategory, WorkflowComplexity, WorkflowPattern
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ResultDataclassPattern(WorkflowPattern):
|
|
15
|
+
"""Structured output with dataclass.
|
|
16
|
+
|
|
17
|
+
Use for: Type-safe, structured workflow results.
|
|
18
|
+
Examples: health-check, release-prep.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
id: str = "result-dataclass"
|
|
22
|
+
name: str = "Result Dataclass"
|
|
23
|
+
category: PatternCategory = PatternCategory.OUTPUT
|
|
24
|
+
description: str = "Structured output format with dataclass"
|
|
25
|
+
complexity: WorkflowComplexity = WorkflowComplexity.SIMPLE
|
|
26
|
+
use_cases: list[str] = [
|
|
27
|
+
"Type-safe results",
|
|
28
|
+
"Structured output",
|
|
29
|
+
"API integration",
|
|
30
|
+
]
|
|
31
|
+
examples: list[str] = ["health-check", "release-prep"]
|
|
32
|
+
risk_weight: float = 1.0
|
|
33
|
+
|
|
34
|
+
def generate_code_sections(self, context: dict[str, Any]) -> list[CodeSection]:
|
|
35
|
+
"""Generate code for result dataclass."""
|
|
36
|
+
workflow_name = context.get("workflow_name", "my-workflow")
|
|
37
|
+
class_name = context.get("class_name", "MyWorkflow")
|
|
38
|
+
result_class_name = f"{class_name}Result"
|
|
39
|
+
|
|
40
|
+
# Get custom fields from context
|
|
41
|
+
custom_fields = context.get("result_fields", [])
|
|
42
|
+
|
|
43
|
+
# Generate custom fields code
|
|
44
|
+
custom_fields_code = ""
|
|
45
|
+
if custom_fields:
|
|
46
|
+
for field in custom_fields:
|
|
47
|
+
field_name = field.get("name", "custom_field")
|
|
48
|
+
field_type = field.get("type", "Any")
|
|
49
|
+
field_desc = field.get("description", "Custom field")
|
|
50
|
+
custom_fields_code += f" {field_name}: {field_type} # {field_desc}\n"
|
|
51
|
+
|
|
52
|
+
return [
|
|
53
|
+
CodeSection(
|
|
54
|
+
location="imports",
|
|
55
|
+
code="from dataclasses import dataclass, field",
|
|
56
|
+
priority=1,
|
|
57
|
+
),
|
|
58
|
+
CodeSection(
|
|
59
|
+
location="dataclasses",
|
|
60
|
+
code=f'''@dataclass
|
|
61
|
+
class {result_class_name}:
|
|
62
|
+
"""Result from {class_name} execution."""
|
|
63
|
+
|
|
64
|
+
success: bool
|
|
65
|
+
{custom_fields_code if custom_fields_code else " # Add custom fields here"}duration_seconds: float
|
|
66
|
+
cost: float
|
|
67
|
+
metadata: dict = field(default_factory=dict)''',
|
|
68
|
+
priority=1,
|
|
69
|
+
),
|
|
70
|
+
CodeSection(
|
|
71
|
+
location="methods",
|
|
72
|
+
code=f''' def _create_result(
|
|
73
|
+
self,
|
|
74
|
+
success: bool,
|
|
75
|
+
duration: float,
|
|
76
|
+
cost: float,
|
|
77
|
+
**kwargs: Any,
|
|
78
|
+
) -> {result_class_name}:
|
|
79
|
+
"""Create structured result.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
success: Whether workflow succeeded
|
|
83
|
+
duration: Execution duration in seconds
|
|
84
|
+
cost: Total cost in USD
|
|
85
|
+
**kwargs: Additional result fields
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
{result_class_name} instance
|
|
89
|
+
|
|
90
|
+
"""
|
|
91
|
+
return {result_class_name}(
|
|
92
|
+
success=success,
|
|
93
|
+
duration_seconds=duration,
|
|
94
|
+
cost=cost,
|
|
95
|
+
**kwargs,
|
|
96
|
+
)''',
|
|
97
|
+
priority=2,
|
|
98
|
+
),
|
|
99
|
+
]
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"""Workflow Pattern Registry.
|
|
2
|
+
|
|
3
|
+
Manages workflow patterns and provides pattern recommendation.
|
|
4
|
+
|
|
5
|
+
Copyright 2025 Smart-AI-Memory
|
|
6
|
+
Licensed under Fair Source License 0.9
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from .behavior import CodeScannerPattern, ConditionalTierPattern, ConfigDrivenPattern
|
|
12
|
+
from .core import PatternCategory, WorkflowComplexity, WorkflowPattern
|
|
13
|
+
from .output import ResultDataclassPattern
|
|
14
|
+
from .structural import CrewBasedPattern, MultiStagePattern, SingleStagePattern
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class WorkflowPatternRegistry:
|
|
18
|
+
"""Registry for workflow patterns."""
|
|
19
|
+
|
|
20
|
+
def __init__(self):
|
|
21
|
+
"""Initialize pattern registry."""
|
|
22
|
+
self._patterns: dict[str, WorkflowPattern] = {}
|
|
23
|
+
self._register_default_patterns()
|
|
24
|
+
|
|
25
|
+
def _register_default_patterns(self) -> None:
|
|
26
|
+
"""Register all default patterns."""
|
|
27
|
+
patterns = [
|
|
28
|
+
# Structural
|
|
29
|
+
SingleStagePattern(),
|
|
30
|
+
MultiStagePattern(),
|
|
31
|
+
CrewBasedPattern(),
|
|
32
|
+
# Behavioral
|
|
33
|
+
ConditionalTierPattern(),
|
|
34
|
+
ConfigDrivenPattern(),
|
|
35
|
+
CodeScannerPattern(),
|
|
36
|
+
# Output
|
|
37
|
+
ResultDataclassPattern(),
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
for pattern in patterns:
|
|
41
|
+
self._patterns[pattern.id] = pattern
|
|
42
|
+
|
|
43
|
+
def register(self, pattern: WorkflowPattern) -> None:
|
|
44
|
+
"""Register a new pattern.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
pattern: Pattern to register
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
self._patterns[pattern.id] = pattern
|
|
51
|
+
|
|
52
|
+
def get(self, pattern_id: str) -> WorkflowPattern | None:
|
|
53
|
+
"""Get pattern by ID.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
pattern_id: Pattern identifier
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
WorkflowPattern or None if not found
|
|
60
|
+
|
|
61
|
+
"""
|
|
62
|
+
return self._patterns.get(pattern_id)
|
|
63
|
+
|
|
64
|
+
def list_all(self) -> list[WorkflowPattern]:
|
|
65
|
+
"""List all registered patterns.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
List of all patterns
|
|
69
|
+
|
|
70
|
+
"""
|
|
71
|
+
return list(self._patterns.values())
|
|
72
|
+
|
|
73
|
+
def list_by_category(self, category: PatternCategory) -> list[WorkflowPattern]:
|
|
74
|
+
"""List patterns by category.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
category: Pattern category
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
List of patterns in category
|
|
81
|
+
|
|
82
|
+
"""
|
|
83
|
+
return [p for p in self._patterns.values() if p.category == category]
|
|
84
|
+
|
|
85
|
+
def list_by_complexity(self, complexity: WorkflowComplexity) -> list[WorkflowPattern]:
|
|
86
|
+
"""List patterns by complexity.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
complexity: Complexity level
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
List of patterns with specified complexity
|
|
93
|
+
|
|
94
|
+
"""
|
|
95
|
+
return [p for p in self._patterns.values() if p.complexity == complexity]
|
|
96
|
+
|
|
97
|
+
def search(self, query: str) -> list[WorkflowPattern]:
|
|
98
|
+
"""Search patterns by name or description.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
query: Search query
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
List of matching patterns
|
|
105
|
+
|
|
106
|
+
"""
|
|
107
|
+
query_lower = query.lower()
|
|
108
|
+
results = []
|
|
109
|
+
|
|
110
|
+
for pattern in self._patterns.values():
|
|
111
|
+
if (
|
|
112
|
+
query_lower in pattern.name.lower()
|
|
113
|
+
or query_lower in pattern.description.lower()
|
|
114
|
+
or any(query_lower in uc.lower() for uc in pattern.use_cases)
|
|
115
|
+
):
|
|
116
|
+
results.append(pattern)
|
|
117
|
+
|
|
118
|
+
return results
|
|
119
|
+
|
|
120
|
+
def recommend_for_workflow(
|
|
121
|
+
self,
|
|
122
|
+
workflow_type: str,
|
|
123
|
+
complexity: WorkflowComplexity | None = None,
|
|
124
|
+
) -> list[WorkflowPattern]:
|
|
125
|
+
"""Recommend patterns for a workflow type.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
workflow_type: Type of workflow (e.g., "code-analysis", "multi-agent")
|
|
129
|
+
complexity: Desired complexity level
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
List of recommended patterns
|
|
133
|
+
|
|
134
|
+
"""
|
|
135
|
+
recommendations = []
|
|
136
|
+
|
|
137
|
+
# Type-based recommendations
|
|
138
|
+
type_map = {
|
|
139
|
+
"code-analysis": ["multi-stage", "code-scanner", "conditional-tier"],
|
|
140
|
+
"simple": ["single-stage"],
|
|
141
|
+
"multi-agent": ["crew-based", "result-dataclass"],
|
|
142
|
+
"configurable": ["config-driven", "multi-stage"],
|
|
143
|
+
"cost-optimized": ["conditional-tier", "multi-stage"],
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
pattern_ids = type_map.get(workflow_type.lower(), [])
|
|
147
|
+
|
|
148
|
+
# Get patterns
|
|
149
|
+
for pattern_id in pattern_ids:
|
|
150
|
+
pattern = self.get(pattern_id)
|
|
151
|
+
if pattern:
|
|
152
|
+
if complexity is None or pattern.complexity == complexity:
|
|
153
|
+
recommendations.append(pattern)
|
|
154
|
+
|
|
155
|
+
# Always include progress tracking and telemetry (built-in)
|
|
156
|
+
# These are inherited from BaseWorkflow
|
|
157
|
+
|
|
158
|
+
return recommendations
|
|
159
|
+
|
|
160
|
+
def validate_pattern_combination(self, pattern_ids: list[str]) -> tuple[bool, str | None]:
|
|
161
|
+
"""Validate that pattern IDs can be used together.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
pattern_ids: List of pattern IDs to validate
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Tuple of (is_valid, error_message)
|
|
168
|
+
|
|
169
|
+
"""
|
|
170
|
+
patterns = []
|
|
171
|
+
for pattern_id in pattern_ids:
|
|
172
|
+
pattern = self.get(pattern_id)
|
|
173
|
+
if not pattern:
|
|
174
|
+
return False, f"Unknown pattern: {pattern_id}"
|
|
175
|
+
patterns.append(pattern)
|
|
176
|
+
|
|
177
|
+
# Check for conflicts
|
|
178
|
+
for pattern in patterns:
|
|
179
|
+
for other_pattern in patterns:
|
|
180
|
+
if other_pattern.id in pattern.conflicts_with:
|
|
181
|
+
return False, f"Conflict: {pattern.id} conflicts with {other_pattern.id}"
|
|
182
|
+
|
|
183
|
+
# Check for missing requirements
|
|
184
|
+
for pattern in patterns:
|
|
185
|
+
for required_id in pattern.requires:
|
|
186
|
+
if required_id not in pattern_ids:
|
|
187
|
+
return False, f"{pattern.id} requires {required_id}"
|
|
188
|
+
|
|
189
|
+
return True, None
|
|
190
|
+
|
|
191
|
+
def get_total_risk_weight(self, pattern_ids: list[str]) -> float:
|
|
192
|
+
"""Calculate total risk weight for pattern combination.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
pattern_ids: List of pattern IDs
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
Total risk weight
|
|
199
|
+
|
|
200
|
+
"""
|
|
201
|
+
total = 0.0
|
|
202
|
+
for pattern_id in pattern_ids:
|
|
203
|
+
pattern = self.get(pattern_id)
|
|
204
|
+
if pattern:
|
|
205
|
+
total += pattern.risk_weight
|
|
206
|
+
return total
|
|
207
|
+
|
|
208
|
+
def generate_code_sections(
|
|
209
|
+
self,
|
|
210
|
+
pattern_ids: list[str],
|
|
211
|
+
context: dict[str, Any],
|
|
212
|
+
) -> dict[str, list[Any]]:
|
|
213
|
+
"""Generate all code sections from patterns.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
pattern_ids: List of pattern IDs to use
|
|
217
|
+
context: Context dictionary for code generation
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
Dict mapping location to list of CodeSection objects
|
|
221
|
+
|
|
222
|
+
"""
|
|
223
|
+
from collections import defaultdict
|
|
224
|
+
|
|
225
|
+
sections_by_location = defaultdict(list)
|
|
226
|
+
|
|
227
|
+
for pattern_id in pattern_ids:
|
|
228
|
+
pattern = self.get(pattern_id)
|
|
229
|
+
if pattern:
|
|
230
|
+
sections = pattern.generate_code_sections(context)
|
|
231
|
+
for section in sections:
|
|
232
|
+
sections_by_location[section.location].append(section)
|
|
233
|
+
|
|
234
|
+
# Sort sections by priority within each location
|
|
235
|
+
for location in sections_by_location:
|
|
236
|
+
sections_by_location[location].sort(key=lambda s: -s.priority)
|
|
237
|
+
|
|
238
|
+
return dict(sections_by_location)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
# Global registry instance
|
|
242
|
+
_registry: WorkflowPatternRegistry | None = None
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def get_workflow_pattern_registry() -> WorkflowPatternRegistry:
|
|
246
|
+
"""Get the global workflow pattern registry.
|
|
247
|
+
|
|
248
|
+
Returns:
|
|
249
|
+
WorkflowPatternRegistry instance
|
|
250
|
+
|
|
251
|
+
"""
|
|
252
|
+
global _registry
|
|
253
|
+
if _registry is None:
|
|
254
|
+
_registry = WorkflowPatternRegistry()
|
|
255
|
+
return _registry
|