attune-ai 2.0.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.
- attune/__init__.py +358 -0
- attune/adaptive/__init__.py +13 -0
- attune/adaptive/task_complexity.py +127 -0
- attune/agent_monitoring.py +414 -0
- attune/cache/__init__.py +117 -0
- attune/cache/base.py +166 -0
- attune/cache/dependency_manager.py +256 -0
- attune/cache/hash_only.py +251 -0
- attune/cache/hybrid.py +457 -0
- attune/cache/storage.py +285 -0
- attune/cache_monitor.py +356 -0
- attune/cache_stats.py +298 -0
- attune/cli/__init__.py +152 -0
- attune/cli/__main__.py +12 -0
- attune/cli/commands/__init__.py +1 -0
- attune/cli/commands/batch.py +264 -0
- attune/cli/commands/cache.py +248 -0
- attune/cli/commands/help.py +331 -0
- attune/cli/commands/info.py +140 -0
- attune/cli/commands/inspect.py +436 -0
- attune/cli/commands/inspection.py +57 -0
- attune/cli/commands/memory.py +48 -0
- attune/cli/commands/metrics.py +92 -0
- attune/cli/commands/orchestrate.py +184 -0
- attune/cli/commands/patterns.py +207 -0
- attune/cli/commands/profiling.py +202 -0
- attune/cli/commands/provider.py +98 -0
- attune/cli/commands/routing.py +285 -0
- attune/cli/commands/setup.py +96 -0
- attune/cli/commands/status.py +235 -0
- attune/cli/commands/sync.py +166 -0
- attune/cli/commands/tier.py +121 -0
- attune/cli/commands/utilities.py +114 -0
- attune/cli/commands/workflow.py +579 -0
- attune/cli/core.py +32 -0
- attune/cli/parsers/__init__.py +68 -0
- attune/cli/parsers/batch.py +118 -0
- attune/cli/parsers/cache.py +65 -0
- attune/cli/parsers/help.py +41 -0
- attune/cli/parsers/info.py +26 -0
- attune/cli/parsers/inspect.py +66 -0
- attune/cli/parsers/metrics.py +42 -0
- attune/cli/parsers/orchestrate.py +61 -0
- attune/cli/parsers/patterns.py +54 -0
- attune/cli/parsers/provider.py +40 -0
- attune/cli/parsers/routing.py +110 -0
- attune/cli/parsers/setup.py +42 -0
- attune/cli/parsers/status.py +47 -0
- attune/cli/parsers/sync.py +31 -0
- attune/cli/parsers/tier.py +33 -0
- attune/cli/parsers/workflow.py +77 -0
- attune/cli/utils/__init__.py +1 -0
- attune/cli/utils/data.py +242 -0
- attune/cli/utils/helpers.py +68 -0
- attune/cli_legacy.py +3957 -0
- attune/cli_minimal.py +1159 -0
- attune/cli_router.py +437 -0
- attune/cli_unified.py +814 -0
- attune/config/__init__.py +66 -0
- attune/config/xml_config.py +286 -0
- attune/config.py +545 -0
- attune/coordination.py +870 -0
- attune/core.py +1511 -0
- attune/core_modules/__init__.py +15 -0
- attune/cost_tracker.py +626 -0
- attune/dashboard/__init__.py +41 -0
- attune/dashboard/app.py +512 -0
- attune/dashboard/simple_server.py +435 -0
- attune/dashboard/standalone_server.py +547 -0
- attune/discovery.py +306 -0
- attune/emergence.py +306 -0
- attune/exceptions.py +123 -0
- attune/feedback_loops.py +373 -0
- attune/hot_reload/README.md +473 -0
- attune/hot_reload/__init__.py +62 -0
- attune/hot_reload/config.py +83 -0
- attune/hot_reload/integration.py +229 -0
- attune/hot_reload/reloader.py +298 -0
- attune/hot_reload/watcher.py +183 -0
- attune/hot_reload/websocket.py +177 -0
- attune/levels.py +577 -0
- attune/leverage_points.py +441 -0
- attune/logging_config.py +261 -0
- attune/mcp/__init__.py +10 -0
- attune/mcp/server.py +506 -0
- attune/memory/__init__.py +237 -0
- attune/memory/claude_memory.py +469 -0
- attune/memory/config.py +224 -0
- attune/memory/control_panel.py +1290 -0
- attune/memory/control_panel_support.py +145 -0
- attune/memory/cross_session.py +845 -0
- attune/memory/edges.py +179 -0
- attune/memory/encryption.py +159 -0
- attune/memory/file_session.py +770 -0
- attune/memory/graph.py +570 -0
- attune/memory/long_term.py +913 -0
- attune/memory/long_term_types.py +99 -0
- attune/memory/mixins/__init__.py +25 -0
- attune/memory/mixins/backend_init_mixin.py +249 -0
- attune/memory/mixins/capabilities_mixin.py +208 -0
- attune/memory/mixins/handoff_mixin.py +208 -0
- attune/memory/mixins/lifecycle_mixin.py +49 -0
- attune/memory/mixins/long_term_mixin.py +352 -0
- attune/memory/mixins/promotion_mixin.py +109 -0
- attune/memory/mixins/short_term_mixin.py +182 -0
- attune/memory/nodes.py +179 -0
- attune/memory/redis_bootstrap.py +540 -0
- attune/memory/security/__init__.py +31 -0
- attune/memory/security/audit_logger.py +932 -0
- attune/memory/security/pii_scrubber.py +640 -0
- attune/memory/security/secrets_detector.py +678 -0
- attune/memory/short_term.py +2192 -0
- attune/memory/simple_storage.py +302 -0
- attune/memory/storage/__init__.py +15 -0
- attune/memory/storage_backend.py +167 -0
- attune/memory/summary_index.py +583 -0
- attune/memory/types.py +446 -0
- attune/memory/unified.py +182 -0
- attune/meta_workflows/__init__.py +74 -0
- attune/meta_workflows/agent_creator.py +248 -0
- attune/meta_workflows/builtin_templates.py +567 -0
- attune/meta_workflows/cli_commands/__init__.py +56 -0
- attune/meta_workflows/cli_commands/agent_commands.py +321 -0
- attune/meta_workflows/cli_commands/analytics_commands.py +442 -0
- attune/meta_workflows/cli_commands/config_commands.py +232 -0
- attune/meta_workflows/cli_commands/memory_commands.py +182 -0
- attune/meta_workflows/cli_commands/template_commands.py +354 -0
- attune/meta_workflows/cli_commands/workflow_commands.py +382 -0
- attune/meta_workflows/cli_meta_workflows.py +59 -0
- attune/meta_workflows/form_engine.py +292 -0
- attune/meta_workflows/intent_detector.py +409 -0
- attune/meta_workflows/models.py +569 -0
- attune/meta_workflows/pattern_learner.py +738 -0
- attune/meta_workflows/plan_generator.py +384 -0
- attune/meta_workflows/session_context.py +397 -0
- attune/meta_workflows/template_registry.py +229 -0
- attune/meta_workflows/workflow.py +984 -0
- attune/metrics/__init__.py +12 -0
- attune/metrics/collector.py +31 -0
- attune/metrics/prompt_metrics.py +194 -0
- attune/models/__init__.py +172 -0
- attune/models/__main__.py +13 -0
- attune/models/adaptive_routing.py +437 -0
- attune/models/auth_cli.py +444 -0
- attune/models/auth_strategy.py +450 -0
- attune/models/cli.py +655 -0
- attune/models/empathy_executor.py +354 -0
- attune/models/executor.py +257 -0
- attune/models/fallback.py +762 -0
- attune/models/provider_config.py +282 -0
- attune/models/registry.py +472 -0
- attune/models/tasks.py +359 -0
- attune/models/telemetry/__init__.py +71 -0
- attune/models/telemetry/analytics.py +594 -0
- attune/models/telemetry/backend.py +196 -0
- attune/models/telemetry/data_models.py +431 -0
- attune/models/telemetry/storage.py +489 -0
- attune/models/token_estimator.py +420 -0
- attune/models/validation.py +280 -0
- attune/monitoring/__init__.py +52 -0
- attune/monitoring/alerts.py +946 -0
- attune/monitoring/alerts_cli.py +448 -0
- attune/monitoring/multi_backend.py +271 -0
- attune/monitoring/otel_backend.py +362 -0
- attune/optimization/__init__.py +19 -0
- attune/optimization/context_optimizer.py +272 -0
- attune/orchestration/__init__.py +67 -0
- attune/orchestration/agent_templates.py +707 -0
- attune/orchestration/config_store.py +499 -0
- attune/orchestration/execution_strategies.py +2111 -0
- attune/orchestration/meta_orchestrator.py +1168 -0
- attune/orchestration/pattern_learner.py +696 -0
- attune/orchestration/real_tools.py +931 -0
- attune/pattern_cache.py +187 -0
- attune/pattern_library.py +542 -0
- attune/patterns/debugging/all_patterns.json +81 -0
- attune/patterns/debugging/workflow_20260107_1770825e.json +77 -0
- attune/patterns/refactoring_memory.json +89 -0
- attune/persistence.py +564 -0
- attune/platform_utils.py +265 -0
- attune/plugins/__init__.py +28 -0
- attune/plugins/base.py +361 -0
- attune/plugins/registry.py +268 -0
- attune/project_index/__init__.py +32 -0
- attune/project_index/cli.py +335 -0
- attune/project_index/index.py +667 -0
- attune/project_index/models.py +504 -0
- attune/project_index/reports.py +474 -0
- attune/project_index/scanner.py +777 -0
- attune/project_index/scanner_parallel.py +291 -0
- attune/prompts/__init__.py +61 -0
- attune/prompts/config.py +77 -0
- attune/prompts/context.py +177 -0
- attune/prompts/parser.py +285 -0
- attune/prompts/registry.py +313 -0
- attune/prompts/templates.py +208 -0
- attune/redis_config.py +302 -0
- attune/redis_memory.py +799 -0
- attune/resilience/__init__.py +56 -0
- attune/resilience/circuit_breaker.py +256 -0
- attune/resilience/fallback.py +179 -0
- attune/resilience/health.py +300 -0
- attune/resilience/retry.py +209 -0
- attune/resilience/timeout.py +135 -0
- attune/routing/__init__.py +43 -0
- attune/routing/chain_executor.py +433 -0
- attune/routing/classifier.py +217 -0
- attune/routing/smart_router.py +234 -0
- attune/routing/workflow_registry.py +343 -0
- attune/scaffolding/README.md +589 -0
- attune/scaffolding/__init__.py +35 -0
- attune/scaffolding/__main__.py +14 -0
- attune/scaffolding/cli.py +240 -0
- attune/scaffolding/templates/base_wizard.py.jinja2 +121 -0
- attune/scaffolding/templates/coach_wizard.py.jinja2 +321 -0
- attune/scaffolding/templates/domain_wizard.py.jinja2 +408 -0
- attune/scaffolding/templates/linear_flow_wizard.py.jinja2 +203 -0
- attune/socratic/__init__.py +256 -0
- attune/socratic/ab_testing.py +958 -0
- attune/socratic/blueprint.py +533 -0
- attune/socratic/cli.py +703 -0
- attune/socratic/collaboration.py +1114 -0
- attune/socratic/domain_templates.py +924 -0
- attune/socratic/embeddings.py +738 -0
- attune/socratic/engine.py +794 -0
- attune/socratic/explainer.py +682 -0
- attune/socratic/feedback.py +772 -0
- attune/socratic/forms.py +629 -0
- attune/socratic/generator.py +732 -0
- attune/socratic/llm_analyzer.py +637 -0
- attune/socratic/mcp_server.py +702 -0
- attune/socratic/session.py +312 -0
- attune/socratic/storage.py +667 -0
- attune/socratic/success.py +730 -0
- attune/socratic/visual_editor.py +860 -0
- attune/socratic/web_ui.py +958 -0
- attune/telemetry/__init__.py +39 -0
- attune/telemetry/agent_coordination.py +475 -0
- attune/telemetry/agent_tracking.py +367 -0
- attune/telemetry/approval_gates.py +545 -0
- attune/telemetry/cli.py +1231 -0
- attune/telemetry/commands/__init__.py +14 -0
- attune/telemetry/commands/dashboard_commands.py +696 -0
- attune/telemetry/event_streaming.py +409 -0
- attune/telemetry/feedback_loop.py +567 -0
- attune/telemetry/usage_tracker.py +591 -0
- attune/templates.py +754 -0
- attune/test_generator/__init__.py +38 -0
- attune/test_generator/__main__.py +14 -0
- attune/test_generator/cli.py +234 -0
- attune/test_generator/generator.py +355 -0
- attune/test_generator/risk_analyzer.py +216 -0
- attune/test_generator/templates/unit_test.py.jinja2 +272 -0
- attune/tier_recommender.py +384 -0
- attune/tools.py +183 -0
- attune/trust/__init__.py +28 -0
- attune/trust/circuit_breaker.py +579 -0
- attune/trust_building.py +527 -0
- attune/validation/__init__.py +19 -0
- attune/validation/xml_validator.py +281 -0
- attune/vscode_bridge.py +173 -0
- attune/workflow_commands.py +780 -0
- attune/workflow_patterns/__init__.py +33 -0
- attune/workflow_patterns/behavior.py +249 -0
- attune/workflow_patterns/core.py +76 -0
- attune/workflow_patterns/output.py +99 -0
- attune/workflow_patterns/registry.py +255 -0
- attune/workflow_patterns/structural.py +288 -0
- attune/workflows/__init__.py +539 -0
- attune/workflows/autonomous_test_gen.py +1268 -0
- attune/workflows/base.py +2667 -0
- attune/workflows/batch_processing.py +342 -0
- attune/workflows/bug_predict.py +1084 -0
- attune/workflows/builder.py +273 -0
- attune/workflows/caching.py +253 -0
- attune/workflows/code_review.py +1048 -0
- attune/workflows/code_review_adapters.py +312 -0
- attune/workflows/code_review_pipeline.py +722 -0
- attune/workflows/config.py +645 -0
- attune/workflows/dependency_check.py +644 -0
- attune/workflows/document_gen/__init__.py +25 -0
- attune/workflows/document_gen/config.py +30 -0
- attune/workflows/document_gen/report_formatter.py +162 -0
- attune/workflows/document_gen/workflow.py +1426 -0
- attune/workflows/document_manager.py +216 -0
- attune/workflows/document_manager_README.md +134 -0
- attune/workflows/documentation_orchestrator.py +1205 -0
- attune/workflows/history.py +510 -0
- attune/workflows/keyboard_shortcuts/__init__.py +39 -0
- attune/workflows/keyboard_shortcuts/generators.py +391 -0
- attune/workflows/keyboard_shortcuts/parsers.py +416 -0
- attune/workflows/keyboard_shortcuts/prompts.py +295 -0
- attune/workflows/keyboard_shortcuts/schema.py +193 -0
- attune/workflows/keyboard_shortcuts/workflow.py +509 -0
- attune/workflows/llm_base.py +363 -0
- attune/workflows/manage_docs.py +87 -0
- attune/workflows/manage_docs_README.md +134 -0
- attune/workflows/manage_documentation.py +821 -0
- attune/workflows/new_sample_workflow1.py +149 -0
- attune/workflows/new_sample_workflow1_README.md +150 -0
- attune/workflows/orchestrated_health_check.py +849 -0
- attune/workflows/orchestrated_release_prep.py +600 -0
- attune/workflows/output.py +413 -0
- attune/workflows/perf_audit.py +863 -0
- attune/workflows/pr_review.py +762 -0
- attune/workflows/progress.py +785 -0
- attune/workflows/progress_server.py +322 -0
- attune/workflows/progressive/README 2.md +454 -0
- attune/workflows/progressive/README.md +454 -0
- attune/workflows/progressive/__init__.py +82 -0
- attune/workflows/progressive/cli.py +219 -0
- attune/workflows/progressive/core.py +488 -0
- attune/workflows/progressive/orchestrator.py +723 -0
- attune/workflows/progressive/reports.py +520 -0
- attune/workflows/progressive/telemetry.py +274 -0
- attune/workflows/progressive/test_gen.py +495 -0
- attune/workflows/progressive/workflow.py +589 -0
- attune/workflows/refactor_plan.py +694 -0
- attune/workflows/release_prep.py +895 -0
- attune/workflows/release_prep_crew.py +969 -0
- attune/workflows/research_synthesis.py +404 -0
- attune/workflows/routing.py +168 -0
- attune/workflows/secure_release.py +593 -0
- attune/workflows/security_adapters.py +297 -0
- attune/workflows/security_audit.py +1329 -0
- attune/workflows/security_audit_phase3.py +355 -0
- attune/workflows/seo_optimization.py +633 -0
- attune/workflows/step_config.py +234 -0
- attune/workflows/telemetry_mixin.py +269 -0
- attune/workflows/test5.py +125 -0
- attune/workflows/test5_README.md +158 -0
- attune/workflows/test_coverage_boost_crew.py +849 -0
- attune/workflows/test_gen/__init__.py +52 -0
- attune/workflows/test_gen/ast_analyzer.py +249 -0
- attune/workflows/test_gen/config.py +88 -0
- attune/workflows/test_gen/data_models.py +38 -0
- attune/workflows/test_gen/report_formatter.py +289 -0
- attune/workflows/test_gen/test_templates.py +381 -0
- attune/workflows/test_gen/workflow.py +655 -0
- attune/workflows/test_gen.py +54 -0
- attune/workflows/test_gen_behavioral.py +477 -0
- attune/workflows/test_gen_parallel.py +341 -0
- attune/workflows/test_lifecycle.py +526 -0
- attune/workflows/test_maintenance.py +627 -0
- attune/workflows/test_maintenance_cli.py +590 -0
- attune/workflows/test_maintenance_crew.py +840 -0
- attune/workflows/test_runner.py +622 -0
- attune/workflows/tier_tracking.py +531 -0
- attune/workflows/xml_enhanced_crew.py +285 -0
- attune_ai-2.0.0.dist-info/METADATA +1026 -0
- attune_ai-2.0.0.dist-info/RECORD +457 -0
- attune_ai-2.0.0.dist-info/WHEEL +5 -0
- attune_ai-2.0.0.dist-info/entry_points.txt +26 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE +201 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +101 -0
- attune_ai-2.0.0.dist-info/top_level.txt +5 -0
- attune_healthcare/__init__.py +13 -0
- attune_healthcare/monitors/__init__.py +9 -0
- attune_healthcare/monitors/clinical_protocol_monitor.py +315 -0
- attune_healthcare/monitors/monitoring/__init__.py +44 -0
- attune_healthcare/monitors/monitoring/protocol_checker.py +300 -0
- attune_healthcare/monitors/monitoring/protocol_loader.py +214 -0
- attune_healthcare/monitors/monitoring/sensor_parsers.py +306 -0
- attune_healthcare/monitors/monitoring/trajectory_analyzer.py +389 -0
- attune_llm/README.md +553 -0
- attune_llm/__init__.py +28 -0
- attune_llm/agent_factory/__init__.py +53 -0
- attune_llm/agent_factory/adapters/__init__.py +85 -0
- attune_llm/agent_factory/adapters/autogen_adapter.py +312 -0
- attune_llm/agent_factory/adapters/crewai_adapter.py +483 -0
- attune_llm/agent_factory/adapters/haystack_adapter.py +298 -0
- attune_llm/agent_factory/adapters/langchain_adapter.py +362 -0
- attune_llm/agent_factory/adapters/langgraph_adapter.py +333 -0
- attune_llm/agent_factory/adapters/native.py +228 -0
- attune_llm/agent_factory/adapters/wizard_adapter.py +423 -0
- attune_llm/agent_factory/base.py +305 -0
- attune_llm/agent_factory/crews/__init__.py +67 -0
- attune_llm/agent_factory/crews/code_review.py +1113 -0
- attune_llm/agent_factory/crews/health_check.py +1262 -0
- attune_llm/agent_factory/crews/refactoring.py +1128 -0
- attune_llm/agent_factory/crews/security_audit.py +1018 -0
- attune_llm/agent_factory/decorators.py +287 -0
- attune_llm/agent_factory/factory.py +558 -0
- attune_llm/agent_factory/framework.py +193 -0
- attune_llm/agent_factory/memory_integration.py +328 -0
- attune_llm/agent_factory/resilient.py +320 -0
- attune_llm/agents_md/__init__.py +22 -0
- attune_llm/agents_md/loader.py +218 -0
- attune_llm/agents_md/parser.py +271 -0
- attune_llm/agents_md/registry.py +307 -0
- attune_llm/claude_memory.py +466 -0
- attune_llm/cli/__init__.py +8 -0
- attune_llm/cli/sync_claude.py +487 -0
- attune_llm/code_health.py +1313 -0
- attune_llm/commands/__init__.py +51 -0
- attune_llm/commands/context.py +375 -0
- attune_llm/commands/loader.py +301 -0
- attune_llm/commands/models.py +231 -0
- attune_llm/commands/parser.py +371 -0
- attune_llm/commands/registry.py +429 -0
- attune_llm/config/__init__.py +29 -0
- attune_llm/config/unified.py +291 -0
- attune_llm/context/__init__.py +22 -0
- attune_llm/context/compaction.py +455 -0
- attune_llm/context/manager.py +434 -0
- attune_llm/contextual_patterns.py +361 -0
- attune_llm/core.py +907 -0
- attune_llm/git_pattern_extractor.py +435 -0
- attune_llm/hooks/__init__.py +24 -0
- attune_llm/hooks/config.py +306 -0
- attune_llm/hooks/executor.py +289 -0
- attune_llm/hooks/registry.py +302 -0
- attune_llm/hooks/scripts/__init__.py +39 -0
- attune_llm/hooks/scripts/evaluate_session.py +201 -0
- attune_llm/hooks/scripts/first_time_init.py +285 -0
- attune_llm/hooks/scripts/pre_compact.py +207 -0
- attune_llm/hooks/scripts/session_end.py +183 -0
- attune_llm/hooks/scripts/session_start.py +163 -0
- attune_llm/hooks/scripts/suggest_compact.py +225 -0
- attune_llm/learning/__init__.py +30 -0
- attune_llm/learning/evaluator.py +438 -0
- attune_llm/learning/extractor.py +514 -0
- attune_llm/learning/storage.py +560 -0
- attune_llm/levels.py +227 -0
- attune_llm/pattern_confidence.py +414 -0
- attune_llm/pattern_resolver.py +272 -0
- attune_llm/pattern_summary.py +350 -0
- attune_llm/providers.py +967 -0
- attune_llm/routing/__init__.py +32 -0
- attune_llm/routing/model_router.py +362 -0
- attune_llm/security/IMPLEMENTATION_SUMMARY.md +413 -0
- attune_llm/security/PHASE2_COMPLETE.md +384 -0
- attune_llm/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
- attune_llm/security/QUICK_REFERENCE.md +316 -0
- attune_llm/security/README.md +262 -0
- attune_llm/security/__init__.py +62 -0
- attune_llm/security/audit_logger.py +929 -0
- attune_llm/security/audit_logger_example.py +152 -0
- attune_llm/security/pii_scrubber.py +640 -0
- attune_llm/security/secrets_detector.py +678 -0
- attune_llm/security/secrets_detector_example.py +304 -0
- attune_llm/security/secure_memdocs.py +1192 -0
- attune_llm/security/secure_memdocs_example.py +278 -0
- attune_llm/session_status.py +745 -0
- attune_llm/state.py +246 -0
- attune_llm/utils/__init__.py +5 -0
- attune_llm/utils/tokens.py +349 -0
- attune_software/SOFTWARE_PLUGIN_README.md +57 -0
- attune_software/__init__.py +13 -0
- attune_software/cli/__init__.py +120 -0
- attune_software/cli/inspect.py +362 -0
- attune_software/cli.py +574 -0
- attune_software/plugin.py +188 -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
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""Smart Router
|
|
2
|
+
|
|
3
|
+
Intelligent dispatcher that analyzes developer input and routes
|
|
4
|
+
to the appropriate workflow(s) using LLM classification.
|
|
5
|
+
|
|
6
|
+
Copyright 2025 Smart AI Memory, LLC
|
|
7
|
+
Licensed under Fair Source 0.9
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from .classifier import ClassificationResult, HaikuClassifier
|
|
14
|
+
from .workflow_registry import WorkflowInfo, WorkflowRegistry
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class RoutingDecision:
|
|
19
|
+
"""Decision from the smart router."""
|
|
20
|
+
|
|
21
|
+
primary_workflow: str
|
|
22
|
+
secondary_workflows: list[str] = field(default_factory=list)
|
|
23
|
+
confidence: float = 0.0
|
|
24
|
+
reasoning: str = ""
|
|
25
|
+
suggested_chain: list[str] = field(default_factory=list)
|
|
26
|
+
context: dict[str, Any] = field(default_factory=dict)
|
|
27
|
+
|
|
28
|
+
# Metadata
|
|
29
|
+
classification_method: str = "llm" # llm, keyword, manual
|
|
30
|
+
request_summary: str = ""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class SmartRouter:
|
|
34
|
+
"""Routes developer requests to appropriate workflow(s).
|
|
35
|
+
|
|
36
|
+
Uses LLM classification (Haiku) to understand natural language
|
|
37
|
+
requests and route them to the best workflow(s).
|
|
38
|
+
|
|
39
|
+
Usage:
|
|
40
|
+
router = SmartRouter()
|
|
41
|
+
|
|
42
|
+
# Async routing (preferred - uses LLM)
|
|
43
|
+
decision = await router.route("Fix the security issue in auth.py")
|
|
44
|
+
print(f"Primary: {decision.primary_workflow}")
|
|
45
|
+
print(f"Confidence: {decision.confidence}")
|
|
46
|
+
|
|
47
|
+
# Sync routing (keyword fallback)
|
|
48
|
+
decision = router.route_sync("Optimize database queries")
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self, api_key: str | None = None):
|
|
52
|
+
"""Initialize the smart router.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
api_key: Optional Anthropic API key for LLM classification
|
|
56
|
+
|
|
57
|
+
"""
|
|
58
|
+
self._registry = WorkflowRegistry()
|
|
59
|
+
self._classifier = HaikuClassifier(api_key=api_key)
|
|
60
|
+
|
|
61
|
+
async def route(
|
|
62
|
+
self,
|
|
63
|
+
request: str,
|
|
64
|
+
context: dict[str, Any] | None = None,
|
|
65
|
+
) -> RoutingDecision:
|
|
66
|
+
"""Route a request to the appropriate workflow(s).
|
|
67
|
+
|
|
68
|
+
Uses LLM classification for accurate natural language understanding.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
request: Developer's natural language request
|
|
72
|
+
context: Optional context (current file, project info, etc.)
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
RoutingDecision with workflow recommendations
|
|
76
|
+
|
|
77
|
+
"""
|
|
78
|
+
# Classify the request
|
|
79
|
+
classification = await self._classifier.classify(
|
|
80
|
+
request=request,
|
|
81
|
+
context=context,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Build suggested chain based on workflow triggers
|
|
85
|
+
suggested_chain = self._build_chain(classification)
|
|
86
|
+
|
|
87
|
+
# Merge extracted context
|
|
88
|
+
merged_context = {**(context or {}), **classification.extracted_context}
|
|
89
|
+
|
|
90
|
+
return RoutingDecision(
|
|
91
|
+
primary_workflow=classification.primary_workflow,
|
|
92
|
+
secondary_workflows=classification.secondary_workflows,
|
|
93
|
+
confidence=classification.confidence,
|
|
94
|
+
reasoning=classification.reasoning,
|
|
95
|
+
suggested_chain=suggested_chain,
|
|
96
|
+
context=merged_context,
|
|
97
|
+
classification_method="llm",
|
|
98
|
+
request_summary=request[:100],
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
def route_sync(
|
|
102
|
+
self,
|
|
103
|
+
request: str,
|
|
104
|
+
context: dict[str, Any] | None = None,
|
|
105
|
+
) -> RoutingDecision:
|
|
106
|
+
"""Synchronous routing using keyword matching.
|
|
107
|
+
|
|
108
|
+
Faster but less accurate than LLM classification.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
request: Developer's request
|
|
112
|
+
context: Optional context
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
RoutingDecision with workflow recommendations
|
|
116
|
+
|
|
117
|
+
"""
|
|
118
|
+
classification = self._classifier.classify_sync(
|
|
119
|
+
request=request,
|
|
120
|
+
context=context,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
suggested_chain = self._build_chain(classification)
|
|
124
|
+
|
|
125
|
+
return RoutingDecision(
|
|
126
|
+
primary_workflow=classification.primary_workflow,
|
|
127
|
+
secondary_workflows=classification.secondary_workflows,
|
|
128
|
+
confidence=classification.confidence,
|
|
129
|
+
reasoning=classification.reasoning,
|
|
130
|
+
suggested_chain=suggested_chain,
|
|
131
|
+
context=context or {},
|
|
132
|
+
classification_method="keyword",
|
|
133
|
+
request_summary=request[:100],
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
def _build_chain(self, classification: ClassificationResult) -> list[str]:
|
|
137
|
+
"""Build suggested workflow chain based on triggers."""
|
|
138
|
+
chain = [classification.primary_workflow]
|
|
139
|
+
|
|
140
|
+
# Add secondary workflows to chain
|
|
141
|
+
for secondary in classification.secondary_workflows:
|
|
142
|
+
if secondary not in chain:
|
|
143
|
+
chain.append(secondary)
|
|
144
|
+
|
|
145
|
+
# Check for auto-chain triggers from primary workflow
|
|
146
|
+
triggers = self._registry.get_chain_triggers(classification.primary_workflow)
|
|
147
|
+
for trigger in triggers:
|
|
148
|
+
next_workflow = trigger.get("next")
|
|
149
|
+
if next_workflow and next_workflow not in chain:
|
|
150
|
+
chain.append(next_workflow)
|
|
151
|
+
|
|
152
|
+
return chain
|
|
153
|
+
|
|
154
|
+
def get_workflow_info(self, name: str) -> WorkflowInfo | None:
|
|
155
|
+
"""Get information about a specific workflow."""
|
|
156
|
+
return self._registry.get(name)
|
|
157
|
+
|
|
158
|
+
def list_workflows(self) -> list[WorkflowInfo]:
|
|
159
|
+
"""List all available workflows."""
|
|
160
|
+
return self._registry.list_all()
|
|
161
|
+
|
|
162
|
+
def suggest_for_file(self, file_path: str) -> list[str]:
|
|
163
|
+
"""Suggest workflows based on file type.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
file_path: Path to the file
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
List of suggested workflow names
|
|
170
|
+
|
|
171
|
+
"""
|
|
172
|
+
suggestions = []
|
|
173
|
+
|
|
174
|
+
# Get file extension
|
|
175
|
+
ext = "." + file_path.rsplit(".", 1)[-1] if "." in file_path else ""
|
|
176
|
+
filename = file_path.rsplit("/", 1)[-1]
|
|
177
|
+
|
|
178
|
+
for workflow in self._registry.list_all():
|
|
179
|
+
if ext in workflow.handles_file_types or filename in workflow.handles_file_types:
|
|
180
|
+
suggestions.append(workflow.name)
|
|
181
|
+
|
|
182
|
+
# Default suggestions if no matches
|
|
183
|
+
if not suggestions:
|
|
184
|
+
suggestions = ["code-review", "security-audit"]
|
|
185
|
+
|
|
186
|
+
return suggestions
|
|
187
|
+
|
|
188
|
+
def suggest_for_error(self, error_type: str) -> list[str]:
|
|
189
|
+
"""Suggest workflows based on error type.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
error_type: Type of error (e.g., "TypeError", "SecurityError")
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
List of suggested workflow names
|
|
196
|
+
|
|
197
|
+
"""
|
|
198
|
+
error_lower = error_type.lower()
|
|
199
|
+
|
|
200
|
+
# Map error types to workflows
|
|
201
|
+
error_workflow_map = {
|
|
202
|
+
"security": ["security-audit", "code-review"],
|
|
203
|
+
"type": ["code-review", "bug-predict"],
|
|
204
|
+
"null": ["bug-predict", "test-gen"],
|
|
205
|
+
"undefined": ["bug-predict", "test-gen"],
|
|
206
|
+
"timeout": ["perf-audit", "bug-predict"],
|
|
207
|
+
"memory": ["perf-audit", "code-review"],
|
|
208
|
+
"import": ["dependency-check", "code-review"],
|
|
209
|
+
"permission": ["security-audit", "code-review"],
|
|
210
|
+
"syntax": ["code-review"],
|
|
211
|
+
"test": ["test-gen", "bug-predict"],
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
for keyword, workflows in error_workflow_map.items():
|
|
215
|
+
if keyword in error_lower:
|
|
216
|
+
return workflows
|
|
217
|
+
|
|
218
|
+
return ["bug-predict", "code-review"]
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
# Convenience function for quick routing
|
|
222
|
+
async def quick_route(request: str, context: dict | None = None) -> RoutingDecision:
|
|
223
|
+
"""Quick routing helper.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
request: Developer request
|
|
227
|
+
context: Optional context
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
RoutingDecision
|
|
231
|
+
|
|
232
|
+
"""
|
|
233
|
+
router = SmartRouter()
|
|
234
|
+
return await router.route(request, context)
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
"""Workflow Registry
|
|
2
|
+
|
|
3
|
+
Central registry of available workflows with their descriptions,
|
|
4
|
+
capabilities, and auto-chain rules.
|
|
5
|
+
|
|
6
|
+
Copyright 2025 Smart AI Memory, LLC
|
|
7
|
+
Licensed under Fair Source 0.9
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from collections.abc import Callable
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class WorkflowInfo:
|
|
17
|
+
"""Information about a registered workflow."""
|
|
18
|
+
|
|
19
|
+
name: str
|
|
20
|
+
description: str
|
|
21
|
+
keywords: list[str] # Keywords for classification
|
|
22
|
+
|
|
23
|
+
# Classification hints
|
|
24
|
+
primary_domain: str = "" # security, performance, testing, etc.
|
|
25
|
+
handles_file_types: list[str] = field(default_factory=list)
|
|
26
|
+
complexity: str = "medium" # low, medium, high
|
|
27
|
+
|
|
28
|
+
# Chaining configuration
|
|
29
|
+
auto_chain: bool = False
|
|
30
|
+
chain_triggers: list[dict[str, Any]] = field(default_factory=list)
|
|
31
|
+
|
|
32
|
+
# Optional workflow class or factory
|
|
33
|
+
workflow_class: type | None = None
|
|
34
|
+
factory: Callable[..., Any] | None = None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Default workflow registry
|
|
38
|
+
WORKFLOW_REGISTRY: dict[str, WorkflowInfo] = {
|
|
39
|
+
# Workflows (cost-optimized pipelines)
|
|
40
|
+
"security-audit": WorkflowInfo(
|
|
41
|
+
name="security-audit",
|
|
42
|
+
description="Analyze code for security vulnerabilities, injection risks, compliance",
|
|
43
|
+
keywords=[
|
|
44
|
+
"security",
|
|
45
|
+
"vulnerability",
|
|
46
|
+
"injection",
|
|
47
|
+
"xss",
|
|
48
|
+
"sql",
|
|
49
|
+
"auth",
|
|
50
|
+
"authentication",
|
|
51
|
+
"authorization",
|
|
52
|
+
"sensitive",
|
|
53
|
+
"credential",
|
|
54
|
+
"password",
|
|
55
|
+
"secret",
|
|
56
|
+
"owasp",
|
|
57
|
+
"cve",
|
|
58
|
+
"exploit",
|
|
59
|
+
],
|
|
60
|
+
primary_domain="security",
|
|
61
|
+
handles_file_types=[".py", ".js", ".ts", ".java", ".go", ".rb"],
|
|
62
|
+
auto_chain=True,
|
|
63
|
+
chain_triggers=[
|
|
64
|
+
{"condition": "high_severity_count > 0", "next": "dependency-check"},
|
|
65
|
+
{"condition": "vulnerability_type == 'injection'", "next": "code-review"},
|
|
66
|
+
],
|
|
67
|
+
),
|
|
68
|
+
"code-review": WorkflowInfo(
|
|
69
|
+
name="code-review",
|
|
70
|
+
description="Review code for quality, best practices, maintainability, and bugs",
|
|
71
|
+
keywords=[
|
|
72
|
+
"review",
|
|
73
|
+
"code",
|
|
74
|
+
"quality",
|
|
75
|
+
"lint",
|
|
76
|
+
"style",
|
|
77
|
+
"convention",
|
|
78
|
+
"best practice",
|
|
79
|
+
"maintainability",
|
|
80
|
+
"readable",
|
|
81
|
+
"clean",
|
|
82
|
+
"refactor",
|
|
83
|
+
"smell",
|
|
84
|
+
],
|
|
85
|
+
primary_domain="quality",
|
|
86
|
+
handles_file_types=[".py", ".js", ".ts", ".java", ".go", ".rb", ".cpp", ".c"],
|
|
87
|
+
auto_chain=True,
|
|
88
|
+
chain_triggers=[
|
|
89
|
+
{"condition": "has_complexity_issues", "next": "refactor-plan"},
|
|
90
|
+
],
|
|
91
|
+
),
|
|
92
|
+
"bug-predict": WorkflowInfo(
|
|
93
|
+
name="bug-predict",
|
|
94
|
+
description="Predict potential bugs based on code patterns and historical data",
|
|
95
|
+
keywords=[
|
|
96
|
+
"bug",
|
|
97
|
+
"error",
|
|
98
|
+
"crash",
|
|
99
|
+
"exception",
|
|
100
|
+
"fail",
|
|
101
|
+
"broken",
|
|
102
|
+
"fix",
|
|
103
|
+
"issue",
|
|
104
|
+
"problem",
|
|
105
|
+
"defect",
|
|
106
|
+
"null",
|
|
107
|
+
"undefined",
|
|
108
|
+
],
|
|
109
|
+
primary_domain="debugging",
|
|
110
|
+
auto_chain=True,
|
|
111
|
+
chain_triggers=[
|
|
112
|
+
{"condition": "risk_score > 0.7", "next": "test-gen"},
|
|
113
|
+
],
|
|
114
|
+
),
|
|
115
|
+
"perf-audit": WorkflowInfo(
|
|
116
|
+
name="perf-audit",
|
|
117
|
+
description="Analyze code for performance issues, bottlenecks, optimizations",
|
|
118
|
+
keywords=[
|
|
119
|
+
"performance",
|
|
120
|
+
"perf",
|
|
121
|
+
"slow",
|
|
122
|
+
"fast",
|
|
123
|
+
"speed",
|
|
124
|
+
"optimize",
|
|
125
|
+
"bottleneck",
|
|
126
|
+
"memory",
|
|
127
|
+
"cpu",
|
|
128
|
+
"latency",
|
|
129
|
+
"throughput",
|
|
130
|
+
"cache",
|
|
131
|
+
"profile",
|
|
132
|
+
],
|
|
133
|
+
primary_domain="performance",
|
|
134
|
+
auto_chain=True,
|
|
135
|
+
chain_triggers=[
|
|
136
|
+
{"condition": "hotspot_count > 5", "next": "refactor-plan"},
|
|
137
|
+
],
|
|
138
|
+
),
|
|
139
|
+
"refactor-plan": WorkflowInfo(
|
|
140
|
+
name="refactor-plan",
|
|
141
|
+
description="Plan code refactoring to improve structure, reduce complexity",
|
|
142
|
+
keywords=[
|
|
143
|
+
"refactor",
|
|
144
|
+
"restructure",
|
|
145
|
+
"reorganize",
|
|
146
|
+
"simplify",
|
|
147
|
+
"complexity",
|
|
148
|
+
"architecture",
|
|
149
|
+
"design",
|
|
150
|
+
"pattern",
|
|
151
|
+
"clean",
|
|
152
|
+
],
|
|
153
|
+
primary_domain="architecture",
|
|
154
|
+
auto_chain=False, # Require approval for refactoring
|
|
155
|
+
),
|
|
156
|
+
"test-gen": WorkflowInfo(
|
|
157
|
+
name="test-gen",
|
|
158
|
+
description="Generate test cases and improve test coverage",
|
|
159
|
+
keywords=[
|
|
160
|
+
"test",
|
|
161
|
+
"testing",
|
|
162
|
+
"unit",
|
|
163
|
+
"integration",
|
|
164
|
+
"coverage",
|
|
165
|
+
"pytest",
|
|
166
|
+
"jest",
|
|
167
|
+
"mock",
|
|
168
|
+
"assert",
|
|
169
|
+
"spec",
|
|
170
|
+
],
|
|
171
|
+
primary_domain="testing",
|
|
172
|
+
handles_file_types=[".py", ".js", ".ts", ".java"],
|
|
173
|
+
auto_chain=True,
|
|
174
|
+
chain_triggers=[
|
|
175
|
+
{"condition": "coverage_low", "next": "bug-predict"},
|
|
176
|
+
],
|
|
177
|
+
),
|
|
178
|
+
"doc-gen": WorkflowInfo(
|
|
179
|
+
name="doc-gen",
|
|
180
|
+
description="Generate documentation from code including API docs, READMEs, and guides",
|
|
181
|
+
keywords=[
|
|
182
|
+
"document",
|
|
183
|
+
"doc",
|
|
184
|
+
"readme",
|
|
185
|
+
"api",
|
|
186
|
+
"explain",
|
|
187
|
+
"describe",
|
|
188
|
+
"comment",
|
|
189
|
+
"docstring",
|
|
190
|
+
"jsdoc",
|
|
191
|
+
],
|
|
192
|
+
primary_domain="documentation",
|
|
193
|
+
auto_chain=False,
|
|
194
|
+
),
|
|
195
|
+
"seo-optimization": WorkflowInfo(
|
|
196
|
+
name="seo-optimization",
|
|
197
|
+
description="Audit and optimize SEO for documentation sites (meta tags, content structure, technical SEO, links)",
|
|
198
|
+
keywords=[
|
|
199
|
+
"seo",
|
|
200
|
+
"search",
|
|
201
|
+
"optimization",
|
|
202
|
+
"meta",
|
|
203
|
+
"meta tag",
|
|
204
|
+
"meta description",
|
|
205
|
+
"title tag",
|
|
206
|
+
"opengraph",
|
|
207
|
+
"og:title",
|
|
208
|
+
"og:description",
|
|
209
|
+
"twitter card",
|
|
210
|
+
"sitemap",
|
|
211
|
+
"robots.txt",
|
|
212
|
+
"keywords",
|
|
213
|
+
"search engine",
|
|
214
|
+
"google",
|
|
215
|
+
"ranking",
|
|
216
|
+
"visibility",
|
|
217
|
+
"documentation seo",
|
|
218
|
+
"mkdocs seo",
|
|
219
|
+
"content optimization",
|
|
220
|
+
"headings",
|
|
221
|
+
"h1",
|
|
222
|
+
"canonical",
|
|
223
|
+
"broken links",
|
|
224
|
+
"internal links",
|
|
225
|
+
"schema markup",
|
|
226
|
+
],
|
|
227
|
+
primary_domain="documentation",
|
|
228
|
+
handles_file_types=[".md", ".html"],
|
|
229
|
+
auto_chain=False, # SEO fixes require approval
|
|
230
|
+
),
|
|
231
|
+
"dependency-check": WorkflowInfo(
|
|
232
|
+
name="dependency-check",
|
|
233
|
+
description="Audit dependencies for vulnerabilities, updates, and license issues",
|
|
234
|
+
keywords=[
|
|
235
|
+
"dependency",
|
|
236
|
+
"package",
|
|
237
|
+
"npm",
|
|
238
|
+
"pip",
|
|
239
|
+
"library",
|
|
240
|
+
"version",
|
|
241
|
+
"update",
|
|
242
|
+
"outdated",
|
|
243
|
+
"license",
|
|
244
|
+
"vulnerability",
|
|
245
|
+
],
|
|
246
|
+
primary_domain="dependencies",
|
|
247
|
+
handles_file_types=["requirements.txt", "package.json", "pyproject.toml", "Cargo.toml"],
|
|
248
|
+
auto_chain=True,
|
|
249
|
+
chain_triggers=[
|
|
250
|
+
{"condition": "critical_vuln_count > 0", "next": "security-audit"},
|
|
251
|
+
],
|
|
252
|
+
),
|
|
253
|
+
"release-prep": WorkflowInfo(
|
|
254
|
+
name="release-prep",
|
|
255
|
+
description="Pre-release quality gate with health checks, security scan, and changelog",
|
|
256
|
+
keywords=[
|
|
257
|
+
"release",
|
|
258
|
+
"deploy",
|
|
259
|
+
"publish",
|
|
260
|
+
"ship",
|
|
261
|
+
"version",
|
|
262
|
+
"changelog",
|
|
263
|
+
"ready",
|
|
264
|
+
"production",
|
|
265
|
+
],
|
|
266
|
+
primary_domain="release",
|
|
267
|
+
auto_chain=False, # Always require approval
|
|
268
|
+
),
|
|
269
|
+
"research": WorkflowInfo(
|
|
270
|
+
name="research",
|
|
271
|
+
description="Research and synthesize information from multiple sources",
|
|
272
|
+
keywords=[
|
|
273
|
+
"research",
|
|
274
|
+
"investigate",
|
|
275
|
+
"explore",
|
|
276
|
+
"analyze",
|
|
277
|
+
"study",
|
|
278
|
+
"understand",
|
|
279
|
+
"learn",
|
|
280
|
+
"compare",
|
|
281
|
+
],
|
|
282
|
+
primary_domain="research",
|
|
283
|
+
auto_chain=False,
|
|
284
|
+
),
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class WorkflowRegistry:
|
|
289
|
+
"""Registry for managing available workflows.
|
|
290
|
+
|
|
291
|
+
Usage:
|
|
292
|
+
registry = WorkflowRegistry()
|
|
293
|
+
info = registry.get("security-audit")
|
|
294
|
+
all_workflows = registry.list_all()
|
|
295
|
+
"""
|
|
296
|
+
|
|
297
|
+
def __init__(self):
|
|
298
|
+
"""Initialize with default workflows."""
|
|
299
|
+
self._workflows: dict[str, WorkflowInfo] = dict(WORKFLOW_REGISTRY)
|
|
300
|
+
|
|
301
|
+
def register(self, info: WorkflowInfo) -> None:
|
|
302
|
+
"""Register a new workflow."""
|
|
303
|
+
self._workflows[info.name] = info
|
|
304
|
+
|
|
305
|
+
def get(self, name: str) -> WorkflowInfo | None:
|
|
306
|
+
"""Get workflow info by name."""
|
|
307
|
+
return self._workflows.get(name)
|
|
308
|
+
|
|
309
|
+
def list_all(self) -> list[WorkflowInfo]:
|
|
310
|
+
"""List all registered workflows."""
|
|
311
|
+
return list(self._workflows.values())
|
|
312
|
+
|
|
313
|
+
def find_by_domain(self, domain: str) -> list[WorkflowInfo]:
|
|
314
|
+
"""Find workflows by primary domain."""
|
|
315
|
+
return [w for w in self._workflows.values() if w.primary_domain == domain]
|
|
316
|
+
|
|
317
|
+
def find_by_keyword(self, keyword: str) -> list[WorkflowInfo]:
|
|
318
|
+
"""Find workflows that handle a keyword."""
|
|
319
|
+
keyword = keyword.lower()
|
|
320
|
+
return [
|
|
321
|
+
w for w in self._workflows.values() if any(keyword in kw.lower() for kw in w.keywords)
|
|
322
|
+
]
|
|
323
|
+
|
|
324
|
+
def get_descriptions_for_classification(self) -> dict[str, str]:
|
|
325
|
+
"""Get workflow name to description mapping for LLM classification."""
|
|
326
|
+
return {
|
|
327
|
+
name: f"{info.description} (domain: {info.primary_domain})"
|
|
328
|
+
for name, info in self._workflows.items()
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
def get_chain_triggers(self, workflow_name: str) -> list[dict[str, Any]]:
|
|
332
|
+
"""Get auto-chain triggers for a workflow."""
|
|
333
|
+
info = self._workflows.get(workflow_name)
|
|
334
|
+
if info and info.auto_chain:
|
|
335
|
+
return info.chain_triggers
|
|
336
|
+
return []
|
|
337
|
+
|
|
338
|
+
def unregister(self, name: str) -> bool:
|
|
339
|
+
"""Remove a workflow from the registry."""
|
|
340
|
+
if name in self._workflows:
|
|
341
|
+
del self._workflows[name]
|
|
342
|
+
return True
|
|
343
|
+
return False
|