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,732 @@
|
|
|
1
|
+
"""Agent and Workflow Generator
|
|
2
|
+
|
|
3
|
+
Generates concrete agents and workflows from blueprints.
|
|
4
|
+
|
|
5
|
+
This module transforms abstract blueprints (from Socratic questioning)
|
|
6
|
+
into runnable agent instances and workflow configurations.
|
|
7
|
+
|
|
8
|
+
Copyright 2026 Smart-AI-Memory
|
|
9
|
+
Licensed under Fair Source License 0.9
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
from datetime import datetime
|
|
17
|
+
from typing import TYPE_CHECKING, Any
|
|
18
|
+
|
|
19
|
+
from .blueprint import (
|
|
20
|
+
AgentBlueprint,
|
|
21
|
+
AgentRole,
|
|
22
|
+
AgentSpec,
|
|
23
|
+
StageSpec,
|
|
24
|
+
ToolCategory,
|
|
25
|
+
ToolSpec,
|
|
26
|
+
WorkflowBlueprint,
|
|
27
|
+
)
|
|
28
|
+
from .success import SuccessCriteria
|
|
29
|
+
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
from ..workflows.xml_enhanced_crew import XMLAgent
|
|
32
|
+
|
|
33
|
+
logger = logging.getLogger(__name__)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# =============================================================================
|
|
37
|
+
# AGENT TEMPLATES
|
|
38
|
+
# =============================================================================
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class AgentTemplate:
|
|
43
|
+
"""Template for generating specialized agents.
|
|
44
|
+
|
|
45
|
+
Templates provide pre-configured agent specifications that can be
|
|
46
|
+
customized based on Socratic questioning results.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
id: str
|
|
50
|
+
name: str
|
|
51
|
+
role: AgentRole
|
|
52
|
+
base_goal: str
|
|
53
|
+
base_backstory: str
|
|
54
|
+
default_tools: list[str]
|
|
55
|
+
quality_focus: list[str]
|
|
56
|
+
languages: list[str] # Empty = all languages
|
|
57
|
+
model_tier: str = "capable"
|
|
58
|
+
custom_instructions: list[str] = field(default_factory=list)
|
|
59
|
+
|
|
60
|
+
def create_spec(
|
|
61
|
+
self,
|
|
62
|
+
customizations: dict[str, Any] | None = None,
|
|
63
|
+
) -> AgentSpec:
|
|
64
|
+
"""Create an AgentSpec from this template.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
customizations: Override template defaults
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
AgentSpec with customizations applied
|
|
71
|
+
"""
|
|
72
|
+
customizations = customizations or {}
|
|
73
|
+
|
|
74
|
+
# Build goal with customizations
|
|
75
|
+
goal = customizations.get("goal", self.base_goal)
|
|
76
|
+
if "goal_suffix" in customizations:
|
|
77
|
+
goal = f"{goal} {customizations['goal_suffix']}"
|
|
78
|
+
|
|
79
|
+
# Build backstory with customizations
|
|
80
|
+
backstory = customizations.get("backstory", self.base_backstory)
|
|
81
|
+
if "expertise" in customizations:
|
|
82
|
+
backstory = f"{backstory} Specialized in: {', '.join(customizations['expertise'])}."
|
|
83
|
+
|
|
84
|
+
# Merge languages
|
|
85
|
+
languages = customizations.get("languages", self.languages)
|
|
86
|
+
|
|
87
|
+
# Merge quality focus
|
|
88
|
+
quality = list(self.quality_focus)
|
|
89
|
+
if "quality_focus" in customizations:
|
|
90
|
+
quality.extend(customizations["quality_focus"])
|
|
91
|
+
quality = list(dict.fromkeys(quality)) # Dedupe preserving order
|
|
92
|
+
|
|
93
|
+
# Build tools
|
|
94
|
+
tools = self._build_tools(customizations.get("tools", []))
|
|
95
|
+
|
|
96
|
+
return AgentSpec(
|
|
97
|
+
id=customizations.get("id", self.id),
|
|
98
|
+
name=customizations.get("name", self.name),
|
|
99
|
+
role=self.role,
|
|
100
|
+
goal=goal,
|
|
101
|
+
backstory=backstory,
|
|
102
|
+
tools=tools,
|
|
103
|
+
quality_focus=quality,
|
|
104
|
+
model_tier=customizations.get("model_tier", self.model_tier),
|
|
105
|
+
custom_instructions=self.custom_instructions + customizations.get("instructions", []),
|
|
106
|
+
languages=languages,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
def _build_tools(self, additional_tools: list[str]) -> list[ToolSpec]:
|
|
110
|
+
"""Build tool specifications."""
|
|
111
|
+
tools = []
|
|
112
|
+
all_tool_ids = list(dict.fromkeys(self.default_tools + additional_tools))
|
|
113
|
+
|
|
114
|
+
for tool_id in all_tool_ids:
|
|
115
|
+
tool_spec = TOOL_REGISTRY.get(tool_id)
|
|
116
|
+
if tool_spec:
|
|
117
|
+
tools.append(tool_spec)
|
|
118
|
+
|
|
119
|
+
return tools
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
# =============================================================================
|
|
123
|
+
# TOOL REGISTRY
|
|
124
|
+
# =============================================================================
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
TOOL_REGISTRY: dict[str, ToolSpec] = {
|
|
128
|
+
"grep_code": ToolSpec(
|
|
129
|
+
id="grep_code",
|
|
130
|
+
name="Code Search",
|
|
131
|
+
category=ToolCategory.CODE_SEARCH,
|
|
132
|
+
description="Search codebase for patterns using regex",
|
|
133
|
+
parameters={
|
|
134
|
+
"pattern": {"type": "string", "required": True},
|
|
135
|
+
"file_glob": {"type": "string", "required": False},
|
|
136
|
+
"case_sensitive": {"type": "boolean", "default": False},
|
|
137
|
+
},
|
|
138
|
+
),
|
|
139
|
+
"read_file": ToolSpec(
|
|
140
|
+
id="read_file",
|
|
141
|
+
name="Read File",
|
|
142
|
+
category=ToolCategory.CODE_ANALYSIS,
|
|
143
|
+
description="Read file contents",
|
|
144
|
+
parameters={
|
|
145
|
+
"path": {"type": "string", "required": True},
|
|
146
|
+
"start_line": {"type": "integer", "required": False},
|
|
147
|
+
"end_line": {"type": "integer", "required": False},
|
|
148
|
+
},
|
|
149
|
+
),
|
|
150
|
+
"analyze_ast": ToolSpec(
|
|
151
|
+
id="analyze_ast",
|
|
152
|
+
name="AST Analysis",
|
|
153
|
+
category=ToolCategory.CODE_ANALYSIS,
|
|
154
|
+
description="Parse and analyze code abstract syntax tree",
|
|
155
|
+
parameters={
|
|
156
|
+
"code": {"type": "string", "required": True},
|
|
157
|
+
"language": {"type": "string", "required": True},
|
|
158
|
+
},
|
|
159
|
+
),
|
|
160
|
+
"security_scan": ToolSpec(
|
|
161
|
+
id="security_scan",
|
|
162
|
+
name="Security Scanner",
|
|
163
|
+
category=ToolCategory.SECURITY,
|
|
164
|
+
description="Run security vulnerability scanner",
|
|
165
|
+
parameters={
|
|
166
|
+
"path": {"type": "string", "required": True},
|
|
167
|
+
"rules": {"type": "array", "required": False},
|
|
168
|
+
},
|
|
169
|
+
cost_tier="moderate",
|
|
170
|
+
),
|
|
171
|
+
"run_linter": ToolSpec(
|
|
172
|
+
id="run_linter",
|
|
173
|
+
name="Run Linter",
|
|
174
|
+
category=ToolCategory.LINTING,
|
|
175
|
+
description="Run code linter and return issues",
|
|
176
|
+
parameters={
|
|
177
|
+
"path": {"type": "string", "required": True},
|
|
178
|
+
"config": {"type": "string", "required": False},
|
|
179
|
+
},
|
|
180
|
+
),
|
|
181
|
+
"run_tests": ToolSpec(
|
|
182
|
+
id="run_tests",
|
|
183
|
+
name="Run Tests",
|
|
184
|
+
category=ToolCategory.TESTING,
|
|
185
|
+
description="Execute test suite and return results",
|
|
186
|
+
parameters={
|
|
187
|
+
"path": {"type": "string", "required": False},
|
|
188
|
+
"coverage": {"type": "boolean", "default": True},
|
|
189
|
+
},
|
|
190
|
+
cost_tier="moderate",
|
|
191
|
+
),
|
|
192
|
+
"edit_file": ToolSpec(
|
|
193
|
+
id="edit_file",
|
|
194
|
+
name="Edit File",
|
|
195
|
+
category=ToolCategory.CODE_MODIFICATION,
|
|
196
|
+
description="Make targeted edits to a file",
|
|
197
|
+
parameters={
|
|
198
|
+
"path": {"type": "string", "required": True},
|
|
199
|
+
"old_text": {"type": "string", "required": True},
|
|
200
|
+
"new_text": {"type": "string", "required": True},
|
|
201
|
+
},
|
|
202
|
+
is_mutating=True,
|
|
203
|
+
requires_confirmation=True,
|
|
204
|
+
),
|
|
205
|
+
"query_patterns": ToolSpec(
|
|
206
|
+
id="query_patterns",
|
|
207
|
+
name="Query Pattern Library",
|
|
208
|
+
category=ToolCategory.KNOWLEDGE,
|
|
209
|
+
description="Search learned patterns for similar issues",
|
|
210
|
+
parameters={
|
|
211
|
+
"query": {"type": "string", "required": True},
|
|
212
|
+
"limit": {"type": "integer", "default": 5},
|
|
213
|
+
},
|
|
214
|
+
),
|
|
215
|
+
"complexity_analysis": ToolSpec(
|
|
216
|
+
id="complexity_analysis",
|
|
217
|
+
name="Complexity Analysis",
|
|
218
|
+
category=ToolCategory.CODE_ANALYSIS,
|
|
219
|
+
description="Calculate code complexity metrics",
|
|
220
|
+
parameters={
|
|
221
|
+
"path": {"type": "string", "required": True},
|
|
222
|
+
},
|
|
223
|
+
),
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
# =============================================================================
|
|
228
|
+
# AGENT TEMPLATE REGISTRY
|
|
229
|
+
# =============================================================================
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
AGENT_TEMPLATES: dict[str, AgentTemplate] = {
|
|
233
|
+
"security_reviewer": AgentTemplate(
|
|
234
|
+
id="security_reviewer",
|
|
235
|
+
name="Security Reviewer",
|
|
236
|
+
role=AgentRole.AUDITOR,
|
|
237
|
+
base_goal="Identify security vulnerabilities and recommend mitigations",
|
|
238
|
+
base_backstory=(
|
|
239
|
+
"Expert security analyst with deep knowledge of OWASP Top 10, "
|
|
240
|
+
"secure coding practices, and common vulnerability patterns."
|
|
241
|
+
),
|
|
242
|
+
default_tools=["grep_code", "read_file", "security_scan", "query_patterns"],
|
|
243
|
+
quality_focus=["security"],
|
|
244
|
+
languages=[],
|
|
245
|
+
model_tier="capable",
|
|
246
|
+
custom_instructions=[
|
|
247
|
+
"Prioritize critical and high severity issues",
|
|
248
|
+
"Provide specific code locations for each finding",
|
|
249
|
+
"Include remediation recommendations",
|
|
250
|
+
],
|
|
251
|
+
),
|
|
252
|
+
"code_quality_reviewer": AgentTemplate(
|
|
253
|
+
id="code_quality_reviewer",
|
|
254
|
+
name="Code Quality Reviewer",
|
|
255
|
+
role=AgentRole.REVIEWER,
|
|
256
|
+
base_goal="Assess code quality, maintainability, and adherence to best practices",
|
|
257
|
+
base_backstory=(
|
|
258
|
+
"Experienced code reviewer with expertise in clean code principles, "
|
|
259
|
+
"design patterns, and maintainability best practices."
|
|
260
|
+
),
|
|
261
|
+
default_tools=["grep_code", "read_file", "run_linter", "complexity_analysis"],
|
|
262
|
+
quality_focus=["maintainability", "reliability"],
|
|
263
|
+
languages=[],
|
|
264
|
+
model_tier="capable",
|
|
265
|
+
),
|
|
266
|
+
"performance_analyzer": AgentTemplate(
|
|
267
|
+
id="performance_analyzer",
|
|
268
|
+
name="Performance Analyzer",
|
|
269
|
+
role=AgentRole.ANALYZER,
|
|
270
|
+
base_goal="Identify performance bottlenecks and optimization opportunities",
|
|
271
|
+
base_backstory=(
|
|
272
|
+
"Performance optimization specialist with expertise in algorithmic "
|
|
273
|
+
"complexity, memory management, and scalability patterns."
|
|
274
|
+
),
|
|
275
|
+
default_tools=["grep_code", "read_file", "complexity_analysis", "analyze_ast"],
|
|
276
|
+
quality_focus=["performance"],
|
|
277
|
+
languages=[],
|
|
278
|
+
model_tier="capable",
|
|
279
|
+
),
|
|
280
|
+
"test_generator": AgentTemplate(
|
|
281
|
+
id="test_generator",
|
|
282
|
+
name="Test Generator",
|
|
283
|
+
role=AgentRole.GENERATOR,
|
|
284
|
+
base_goal="Generate comprehensive test cases for untested code",
|
|
285
|
+
base_backstory=(
|
|
286
|
+
"Testing expert skilled in unit testing, integration testing, "
|
|
287
|
+
"and test-driven development methodologies."
|
|
288
|
+
),
|
|
289
|
+
default_tools=["read_file", "analyze_ast", "run_tests", "edit_file"],
|
|
290
|
+
quality_focus=["testability", "reliability"],
|
|
291
|
+
languages=[],
|
|
292
|
+
model_tier="capable",
|
|
293
|
+
custom_instructions=[
|
|
294
|
+
"Generate both happy path and edge case tests",
|
|
295
|
+
"Follow the existing test patterns in the codebase",
|
|
296
|
+
"Ensure tests are deterministic and isolated",
|
|
297
|
+
],
|
|
298
|
+
),
|
|
299
|
+
"documentation_writer": AgentTemplate(
|
|
300
|
+
id="documentation_writer",
|
|
301
|
+
name="Documentation Writer",
|
|
302
|
+
role=AgentRole.GENERATOR,
|
|
303
|
+
base_goal="Generate clear, comprehensive documentation",
|
|
304
|
+
base_backstory=(
|
|
305
|
+
"Technical writer with expertise in API documentation, "
|
|
306
|
+
"code comments, and developer guides."
|
|
307
|
+
),
|
|
308
|
+
default_tools=["read_file", "analyze_ast", "grep_code"],
|
|
309
|
+
quality_focus=["maintainability"],
|
|
310
|
+
languages=[],
|
|
311
|
+
model_tier="cheap",
|
|
312
|
+
),
|
|
313
|
+
"style_enforcer": AgentTemplate(
|
|
314
|
+
id="style_enforcer",
|
|
315
|
+
name="Style Enforcer",
|
|
316
|
+
role=AgentRole.REVIEWER,
|
|
317
|
+
base_goal="Ensure code follows team style guidelines",
|
|
318
|
+
base_backstory=(
|
|
319
|
+
"Code style expert with knowledge of language-specific "
|
|
320
|
+
"conventions and formatting standards."
|
|
321
|
+
),
|
|
322
|
+
default_tools=["run_linter", "read_file"],
|
|
323
|
+
quality_focus=["maintainability"],
|
|
324
|
+
languages=[],
|
|
325
|
+
model_tier="cheap",
|
|
326
|
+
),
|
|
327
|
+
"result_synthesizer": AgentTemplate(
|
|
328
|
+
id="result_synthesizer",
|
|
329
|
+
name="Result Synthesizer",
|
|
330
|
+
role=AgentRole.REPORTER,
|
|
331
|
+
base_goal="Synthesize findings into clear, actionable reports",
|
|
332
|
+
base_backstory=(
|
|
333
|
+
"Technical communicator skilled at translating complex "
|
|
334
|
+
"findings into understandable recommendations."
|
|
335
|
+
),
|
|
336
|
+
default_tools=["query_patterns"],
|
|
337
|
+
quality_focus=[],
|
|
338
|
+
languages=[],
|
|
339
|
+
model_tier="cheap",
|
|
340
|
+
),
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
# =============================================================================
|
|
345
|
+
# AGENT GENERATOR
|
|
346
|
+
# =============================================================================
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
class AgentGenerator:
|
|
350
|
+
"""Generates agents and workflows from blueprints.
|
|
351
|
+
|
|
352
|
+
Example:
|
|
353
|
+
>>> generator = AgentGenerator()
|
|
354
|
+
>>>
|
|
355
|
+
>>> # Generate from blueprint
|
|
356
|
+
>>> blueprint = WorkflowBlueprint(...)
|
|
357
|
+
>>> workflow = generator.generate_workflow(blueprint)
|
|
358
|
+
>>>
|
|
359
|
+
>>> # Generate from template
|
|
360
|
+
>>> agent = generator.generate_agent_from_template(
|
|
361
|
+
... "security_reviewer",
|
|
362
|
+
... customizations={"languages": ["python"]}
|
|
363
|
+
... )
|
|
364
|
+
"""
|
|
365
|
+
|
|
366
|
+
def __init__(self):
|
|
367
|
+
"""Initialize the generator."""
|
|
368
|
+
self.templates = AGENT_TEMPLATES.copy()
|
|
369
|
+
self.tools = TOOL_REGISTRY.copy()
|
|
370
|
+
|
|
371
|
+
def register_template(self, template: AgentTemplate) -> None:
|
|
372
|
+
"""Register a custom agent template."""
|
|
373
|
+
self.templates[template.id] = template
|
|
374
|
+
|
|
375
|
+
def register_tool(self, tool: ToolSpec) -> None:
|
|
376
|
+
"""Register a custom tool."""
|
|
377
|
+
self.tools[tool.id] = tool
|
|
378
|
+
|
|
379
|
+
def generate_agent_from_template(
|
|
380
|
+
self,
|
|
381
|
+
template_id: str,
|
|
382
|
+
customizations: dict[str, Any] | None = None,
|
|
383
|
+
) -> AgentBlueprint:
|
|
384
|
+
"""Generate an agent blueprint from a template.
|
|
385
|
+
|
|
386
|
+
Args:
|
|
387
|
+
template_id: ID of the template to use
|
|
388
|
+
customizations: Override template defaults
|
|
389
|
+
|
|
390
|
+
Returns:
|
|
391
|
+
AgentBlueprint ready for instantiation
|
|
392
|
+
|
|
393
|
+
Raises:
|
|
394
|
+
ValueError: If template not found
|
|
395
|
+
"""
|
|
396
|
+
template = self.templates.get(template_id)
|
|
397
|
+
if not template:
|
|
398
|
+
raise ValueError(f"Unknown template: {template_id}")
|
|
399
|
+
|
|
400
|
+
spec = template.create_spec(customizations)
|
|
401
|
+
|
|
402
|
+
return AgentBlueprint(
|
|
403
|
+
spec=spec,
|
|
404
|
+
generated_from="template",
|
|
405
|
+
template_id=template_id,
|
|
406
|
+
customizations=customizations or {},
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
def generate_agents_for_requirements(
|
|
410
|
+
self,
|
|
411
|
+
requirements: dict[str, Any],
|
|
412
|
+
) -> list[AgentBlueprint]:
|
|
413
|
+
"""Generate appropriate agents based on requirements.
|
|
414
|
+
|
|
415
|
+
This is the core intelligent generation that maps requirements
|
|
416
|
+
(from Socratic questioning) to agent configurations.
|
|
417
|
+
|
|
418
|
+
Args:
|
|
419
|
+
requirements: Requirements gathered from Socratic session
|
|
420
|
+
- quality_focus: list of quality attributes
|
|
421
|
+
- languages: list of programming languages
|
|
422
|
+
- automation_level: advisory/semi_auto/fully_auto
|
|
423
|
+
- domain: domain (e.g., "code_review", "testing")
|
|
424
|
+
|
|
425
|
+
Returns:
|
|
426
|
+
List of AgentBlueprints for a complete team
|
|
427
|
+
"""
|
|
428
|
+
agents: list[AgentBlueprint] = []
|
|
429
|
+
quality_focus = requirements.get("quality_focus", [])
|
|
430
|
+
languages = requirements.get("languages", [])
|
|
431
|
+
automation = requirements.get("automation_level", "semi_auto")
|
|
432
|
+
|
|
433
|
+
# Map quality focus to agent templates
|
|
434
|
+
quality_to_templates = {
|
|
435
|
+
"security": ["security_reviewer"],
|
|
436
|
+
"performance": ["performance_analyzer"],
|
|
437
|
+
"maintainability": ["code_quality_reviewer", "documentation_writer"],
|
|
438
|
+
"reliability": ["code_quality_reviewer", "test_generator"],
|
|
439
|
+
"testability": ["test_generator"],
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
# Collect needed templates
|
|
443
|
+
needed_templates: set[str] = set()
|
|
444
|
+
for quality in quality_focus:
|
|
445
|
+
templates = quality_to_templates.get(quality, [])
|
|
446
|
+
needed_templates.update(templates)
|
|
447
|
+
|
|
448
|
+
# Default to basic code review if no specific focus
|
|
449
|
+
if not needed_templates:
|
|
450
|
+
needed_templates.add("code_quality_reviewer")
|
|
451
|
+
|
|
452
|
+
# Add synthesizer for results aggregation
|
|
453
|
+
if len(needed_templates) > 1:
|
|
454
|
+
needed_templates.add("result_synthesizer")
|
|
455
|
+
|
|
456
|
+
# Generate agent for each template
|
|
457
|
+
for template_id in needed_templates:
|
|
458
|
+
customizations = {
|
|
459
|
+
"languages": languages,
|
|
460
|
+
"quality_focus": quality_focus,
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
# Adjust for automation level
|
|
464
|
+
if automation == "fully_auto":
|
|
465
|
+
customizations["instructions"] = [
|
|
466
|
+
"Apply fixes automatically where safe",
|
|
467
|
+
"Minimize human review requirements",
|
|
468
|
+
]
|
|
469
|
+
elif automation == "advisory":
|
|
470
|
+
customizations["instructions"] = [
|
|
471
|
+
"Provide recommendations only",
|
|
472
|
+
"Do not modify any files",
|
|
473
|
+
]
|
|
474
|
+
|
|
475
|
+
try:
|
|
476
|
+
agent = self.generate_agent_from_template(template_id, customizations)
|
|
477
|
+
agents.append(agent)
|
|
478
|
+
except ValueError:
|
|
479
|
+
logger.warning(f"Template not found: {template_id}")
|
|
480
|
+
|
|
481
|
+
return agents
|
|
482
|
+
|
|
483
|
+
def generate_workflow(
|
|
484
|
+
self,
|
|
485
|
+
blueprint: WorkflowBlueprint,
|
|
486
|
+
) -> GeneratedWorkflow:
|
|
487
|
+
"""Generate a complete workflow from a blueprint.
|
|
488
|
+
|
|
489
|
+
Args:
|
|
490
|
+
blueprint: The workflow blueprint to generate from
|
|
491
|
+
|
|
492
|
+
Returns:
|
|
493
|
+
GeneratedWorkflow ready for execution
|
|
494
|
+
"""
|
|
495
|
+
# Validate blueprint
|
|
496
|
+
is_valid, errors = blueprint.validate()
|
|
497
|
+
if not is_valid:
|
|
498
|
+
raise ValueError(f"Invalid blueprint: {'; '.join(errors)}")
|
|
499
|
+
|
|
500
|
+
# Generate XML agents from blueprints
|
|
501
|
+
xml_agents = []
|
|
502
|
+
for agent_bp in blueprint.agents:
|
|
503
|
+
xml_agent = self._create_xml_agent(agent_bp.spec)
|
|
504
|
+
xml_agents.append(xml_agent)
|
|
505
|
+
|
|
506
|
+
# Build stage configuration
|
|
507
|
+
stages_config = []
|
|
508
|
+
for stage in blueprint.stages:
|
|
509
|
+
stages_config.append(
|
|
510
|
+
{
|
|
511
|
+
"id": stage.id,
|
|
512
|
+
"name": stage.name,
|
|
513
|
+
"agents": stage.agent_ids,
|
|
514
|
+
"parallel": stage.parallel,
|
|
515
|
+
"depends_on": stage.depends_on,
|
|
516
|
+
"timeout": stage.timeout,
|
|
517
|
+
}
|
|
518
|
+
)
|
|
519
|
+
|
|
520
|
+
return GeneratedWorkflow(
|
|
521
|
+
blueprint=blueprint,
|
|
522
|
+
agents=xml_agents,
|
|
523
|
+
stages=stages_config,
|
|
524
|
+
generated_at=datetime.now().isoformat(),
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
def _create_xml_agent(self, spec: AgentSpec) -> XMLAgent:
|
|
528
|
+
"""Create an XMLAgent from a spec."""
|
|
529
|
+
from ..workflows.xml_enhanced_crew import XMLAgent
|
|
530
|
+
|
|
531
|
+
return XMLAgent(
|
|
532
|
+
role=spec.name,
|
|
533
|
+
goal=spec.goal,
|
|
534
|
+
backstory=spec.backstory,
|
|
535
|
+
expertise_level="expert" if spec.model_tier != "cheap" else "competent",
|
|
536
|
+
custom_instructions=spec.custom_instructions,
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
def create_workflow_blueprint(
|
|
540
|
+
self,
|
|
541
|
+
name: str,
|
|
542
|
+
description: str,
|
|
543
|
+
agents: list[AgentBlueprint],
|
|
544
|
+
quality_focus: list[str],
|
|
545
|
+
automation_level: str,
|
|
546
|
+
success_criteria: SuccessCriteria | None = None,
|
|
547
|
+
) -> WorkflowBlueprint:
|
|
548
|
+
"""Create a workflow blueprint with automatic staging.
|
|
549
|
+
|
|
550
|
+
Args:
|
|
551
|
+
name: Workflow name
|
|
552
|
+
description: Workflow description
|
|
553
|
+
agents: Agent blueprints to include
|
|
554
|
+
quality_focus: Quality attributes to optimize for
|
|
555
|
+
automation_level: Level of automation
|
|
556
|
+
success_criteria: Optional success criteria
|
|
557
|
+
|
|
558
|
+
Returns:
|
|
559
|
+
Complete WorkflowBlueprint
|
|
560
|
+
"""
|
|
561
|
+
# Group agents by role for staging
|
|
562
|
+
analyzers = [
|
|
563
|
+
a
|
|
564
|
+
for a in agents
|
|
565
|
+
if a.spec.role in (AgentRole.ANALYZER, AgentRole.REVIEWER, AgentRole.AUDITOR)
|
|
566
|
+
]
|
|
567
|
+
generators = [a for a in agents if a.spec.role == AgentRole.GENERATOR]
|
|
568
|
+
reporters = [a for a in agents if a.spec.role == AgentRole.REPORTER]
|
|
569
|
+
|
|
570
|
+
stages = []
|
|
571
|
+
|
|
572
|
+
# Stage 1: Analysis (parallel)
|
|
573
|
+
if analyzers:
|
|
574
|
+
stages.append(
|
|
575
|
+
StageSpec(
|
|
576
|
+
id="analysis",
|
|
577
|
+
name="Analysis",
|
|
578
|
+
description="Analyze code and identify issues",
|
|
579
|
+
agent_ids=[a.spec.id for a in analyzers],
|
|
580
|
+
parallel=True,
|
|
581
|
+
output_aggregation="merge",
|
|
582
|
+
)
|
|
583
|
+
)
|
|
584
|
+
|
|
585
|
+
# Stage 2: Generation (sequential, depends on analysis)
|
|
586
|
+
if generators:
|
|
587
|
+
stages.append(
|
|
588
|
+
StageSpec(
|
|
589
|
+
id="generation",
|
|
590
|
+
name="Generation",
|
|
591
|
+
description="Generate fixes and improvements",
|
|
592
|
+
agent_ids=[a.spec.id for a in generators],
|
|
593
|
+
parallel=False,
|
|
594
|
+
depends_on=["analysis"] if analyzers else [],
|
|
595
|
+
)
|
|
596
|
+
)
|
|
597
|
+
|
|
598
|
+
# Stage 3: Synthesis (always last)
|
|
599
|
+
if reporters:
|
|
600
|
+
depends = []
|
|
601
|
+
if analyzers:
|
|
602
|
+
depends.append("analysis")
|
|
603
|
+
if generators:
|
|
604
|
+
depends.append("generation")
|
|
605
|
+
|
|
606
|
+
stages.append(
|
|
607
|
+
StageSpec(
|
|
608
|
+
id="synthesis",
|
|
609
|
+
name="Synthesis",
|
|
610
|
+
description="Synthesize findings into report",
|
|
611
|
+
agent_ids=[a.spec.id for a in reporters],
|
|
612
|
+
parallel=False,
|
|
613
|
+
depends_on=depends,
|
|
614
|
+
)
|
|
615
|
+
)
|
|
616
|
+
|
|
617
|
+
return WorkflowBlueprint(
|
|
618
|
+
name=name,
|
|
619
|
+
description=description,
|
|
620
|
+
agents=agents,
|
|
621
|
+
stages=stages,
|
|
622
|
+
quality_focus=quality_focus,
|
|
623
|
+
automation_level=automation_level,
|
|
624
|
+
success_criteria=success_criteria,
|
|
625
|
+
generated_at=datetime.now().isoformat(),
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
@dataclass
|
|
630
|
+
class GeneratedWorkflow:
|
|
631
|
+
"""A generated, runnable workflow.
|
|
632
|
+
|
|
633
|
+
Contains all the components needed to execute the workflow.
|
|
634
|
+
"""
|
|
635
|
+
|
|
636
|
+
# Source blueprint
|
|
637
|
+
blueprint: WorkflowBlueprint
|
|
638
|
+
|
|
639
|
+
# Generated XMLAgent instances
|
|
640
|
+
agents: list[Any] # XMLAgent
|
|
641
|
+
|
|
642
|
+
# Stage configuration
|
|
643
|
+
stages: list[dict[str, Any]]
|
|
644
|
+
|
|
645
|
+
# Generation timestamp
|
|
646
|
+
generated_at: str = ""
|
|
647
|
+
|
|
648
|
+
# Whether workflow has been validated
|
|
649
|
+
validated: bool = False
|
|
650
|
+
|
|
651
|
+
async def execute(
|
|
652
|
+
self,
|
|
653
|
+
input_data: dict[str, Any],
|
|
654
|
+
progress_callback: Any = None,
|
|
655
|
+
) -> dict[str, Any]:
|
|
656
|
+
"""Execute the workflow.
|
|
657
|
+
|
|
658
|
+
Args:
|
|
659
|
+
input_data: Input data for the workflow
|
|
660
|
+
progress_callback: Optional progress callback
|
|
661
|
+
|
|
662
|
+
Returns:
|
|
663
|
+
Workflow results
|
|
664
|
+
"""
|
|
665
|
+
# This is a simplified execution - real implementation would
|
|
666
|
+
# integrate with BaseWorkflow
|
|
667
|
+
results: dict[str, Any] = {
|
|
668
|
+
"stages": {},
|
|
669
|
+
"agents": {},
|
|
670
|
+
"final_output": None,
|
|
671
|
+
"success": False,
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
for stage_config in self.stages:
|
|
675
|
+
stage_id = stage_config["id"]
|
|
676
|
+
agent_ids = stage_config["agents"]
|
|
677
|
+
|
|
678
|
+
stage_results = []
|
|
679
|
+
for agent_id in agent_ids:
|
|
680
|
+
# Find agent
|
|
681
|
+
agent = next(
|
|
682
|
+
(
|
|
683
|
+
a
|
|
684
|
+
for a in self.agents
|
|
685
|
+
if hasattr(a, "role") and self._match_agent(a, agent_id)
|
|
686
|
+
),
|
|
687
|
+
None,
|
|
688
|
+
)
|
|
689
|
+
if agent:
|
|
690
|
+
# Execute agent (simplified)
|
|
691
|
+
result = {
|
|
692
|
+
"agent_id": agent_id,
|
|
693
|
+
"status": "completed",
|
|
694
|
+
"output": f"Agent {agent_id} completed",
|
|
695
|
+
}
|
|
696
|
+
stage_results.append(result)
|
|
697
|
+
|
|
698
|
+
results["stages"][stage_id] = stage_results
|
|
699
|
+
|
|
700
|
+
results["success"] = True
|
|
701
|
+
results["final_output"] = results["stages"]
|
|
702
|
+
|
|
703
|
+
return results
|
|
704
|
+
|
|
705
|
+
def _match_agent(self, agent: Any, agent_id: str) -> bool:
|
|
706
|
+
"""Check if an agent matches an ID."""
|
|
707
|
+
# Match by role name (simplified)
|
|
708
|
+
if hasattr(agent, "role"):
|
|
709
|
+
return agent_id.replace("_", " ").lower() in agent.role.lower()
|
|
710
|
+
return False
|
|
711
|
+
|
|
712
|
+
def describe(self) -> str:
|
|
713
|
+
"""Get human-readable description of the workflow."""
|
|
714
|
+
lines = [
|
|
715
|
+
f"Workflow: {self.blueprint.name}",
|
|
716
|
+
f"Description: {self.blueprint.description}",
|
|
717
|
+
"",
|
|
718
|
+
f"Agents ({len(self.agents)}):",
|
|
719
|
+
]
|
|
720
|
+
|
|
721
|
+
for agent in self.agents:
|
|
722
|
+
if hasattr(agent, "role"):
|
|
723
|
+
lines.append(f" - {agent.role}: {getattr(agent, 'goal', 'N/A')}")
|
|
724
|
+
|
|
725
|
+
lines.append("")
|
|
726
|
+
lines.append(f"Stages ({len(self.stages)}):")
|
|
727
|
+
|
|
728
|
+
for stage in self.stages:
|
|
729
|
+
parallel = "parallel" if stage.get("parallel") else "sequential"
|
|
730
|
+
lines.append(f" - {stage['name']} ({parallel}): {', '.join(stage['agents'])}")
|
|
731
|
+
|
|
732
|
+
return "\n".join(lines)
|