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,569 @@
|
|
|
1
|
+
"""Core data models for meta-workflow system.
|
|
2
|
+
|
|
3
|
+
This module defines the data structures for:
|
|
4
|
+
- Form schemas and responses (Socratic questioning)
|
|
5
|
+
- Agent composition rules and specs (dynamic agent generation)
|
|
6
|
+
- Meta-workflow templates and results (orchestration)
|
|
7
|
+
|
|
8
|
+
Created: 2026-01-17
|
|
9
|
+
Purpose: Enable dynamic workflow creation via forms + agent teams
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import uuid
|
|
14
|
+
from dataclasses import asdict, dataclass, field
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
from enum import Enum
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
# =============================================================================
|
|
20
|
+
# Enums
|
|
21
|
+
# =============================================================================
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class QuestionType(str, Enum):
|
|
25
|
+
"""Types of form questions supported."""
|
|
26
|
+
|
|
27
|
+
TEXT_INPUT = "text_input"
|
|
28
|
+
SINGLE_SELECT = "single_select"
|
|
29
|
+
MULTI_SELECT = "multi_select"
|
|
30
|
+
BOOLEAN = "boolean"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TierStrategy(str, Enum):
|
|
34
|
+
"""Model tier escalation strategies for agents."""
|
|
35
|
+
|
|
36
|
+
CHEAP_ONLY = "cheap_only" # Use only cheap tier
|
|
37
|
+
PROGRESSIVE = "progressive" # Escalate cheap → capable → premium
|
|
38
|
+
CAPABLE_FIRST = "capable_first" # Start at capable, escalate to premium if needed
|
|
39
|
+
PREMIUM_ONLY = "premium_only" # Use only premium tier
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# =============================================================================
|
|
43
|
+
# Form Components
|
|
44
|
+
# =============================================================================
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class FormQuestion:
|
|
49
|
+
"""A single question in a Socratic form.
|
|
50
|
+
|
|
51
|
+
Attributes:
|
|
52
|
+
id: Unique identifier for this question
|
|
53
|
+
text: The question text shown to user
|
|
54
|
+
type: Question type (text_input, single_select, etc.)
|
|
55
|
+
options: Available options for select questions
|
|
56
|
+
default: Default value if user doesn't provide one
|
|
57
|
+
help_text: Additional help text shown to user
|
|
58
|
+
required: Whether this question must be answered
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
id: str
|
|
62
|
+
text: str
|
|
63
|
+
type: QuestionType
|
|
64
|
+
options: list[str] = field(default_factory=list)
|
|
65
|
+
default: str | None = None
|
|
66
|
+
help_text: str | None = None
|
|
67
|
+
required: bool = True
|
|
68
|
+
|
|
69
|
+
def to_ask_user_format(self) -> dict[str, Any]:
|
|
70
|
+
"""Convert to format compatible with AskUserQuestion tool.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Dictionary with question data for AskUserQuestion
|
|
74
|
+
"""
|
|
75
|
+
# Boolean questions convert to Yes/No select
|
|
76
|
+
if self.type == QuestionType.BOOLEAN:
|
|
77
|
+
return {
|
|
78
|
+
"question_id": self.id,
|
|
79
|
+
"question": self.text,
|
|
80
|
+
"type": "single_select",
|
|
81
|
+
"options": ["Yes", "No"],
|
|
82
|
+
"default": self.default, # Preserve default for boolean questions
|
|
83
|
+
"help_text": self.help_text,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
"question_id": self.id,
|
|
88
|
+
"question": self.text,
|
|
89
|
+
"type": self.type.value,
|
|
90
|
+
"options": self.options,
|
|
91
|
+
"default": self.default,
|
|
92
|
+
"help_text": self.help_text,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@dataclass
|
|
97
|
+
class FormSchema:
|
|
98
|
+
"""Schema defining a collection of questions for a meta-workflow.
|
|
99
|
+
|
|
100
|
+
Attributes:
|
|
101
|
+
title: Form title
|
|
102
|
+
description: Form description
|
|
103
|
+
questions: List of questions to ask
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
title: str
|
|
107
|
+
description: str
|
|
108
|
+
questions: list[FormQuestion] = field(default_factory=list)
|
|
109
|
+
|
|
110
|
+
def get_question_batches(self, batch_size: int = 4) -> list[list[FormQuestion]]:
|
|
111
|
+
"""Batch questions for asking (AskUserQuestion supports max 4 at once).
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
batch_size: Maximum questions per batch (default: 4)
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
List of question batches
|
|
118
|
+
"""
|
|
119
|
+
batches = []
|
|
120
|
+
for i in range(0, len(self.questions), batch_size):
|
|
121
|
+
batches.append(self.questions[i : i + batch_size])
|
|
122
|
+
return batches
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@dataclass
|
|
126
|
+
class FormResponse:
|
|
127
|
+
"""User's responses to a form.
|
|
128
|
+
|
|
129
|
+
Attributes:
|
|
130
|
+
template_id: ID of template this response is for
|
|
131
|
+
responses: Dictionary mapping question_id → user's answer
|
|
132
|
+
timestamp: When response was submitted
|
|
133
|
+
response_id: Unique ID for this response
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
template_id: str
|
|
137
|
+
responses: dict[str, Any] = field(default_factory=dict)
|
|
138
|
+
timestamp: str = field(default_factory=lambda: datetime.now().isoformat())
|
|
139
|
+
response_id: str = field(
|
|
140
|
+
default_factory=lambda: f"resp-{datetime.now().strftime('%Y%m%d-%H%M%S')}"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
def get(self, question_id: str, default: Any = None) -> Any:
|
|
144
|
+
"""Get response for a question.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
question_id: ID of question
|
|
148
|
+
default: Default value if not found
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
User's response or default
|
|
152
|
+
"""
|
|
153
|
+
return self.responses.get(question_id, default)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# =============================================================================
|
|
157
|
+
# Agent Components
|
|
158
|
+
# =============================================================================
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@dataclass
|
|
162
|
+
class AgentCompositionRule:
|
|
163
|
+
"""Rule defining when and how to create an agent.
|
|
164
|
+
|
|
165
|
+
Attributes:
|
|
166
|
+
role: Agent's role/purpose
|
|
167
|
+
base_template: Base agent template to use
|
|
168
|
+
tier_strategy: Model tier escalation strategy
|
|
169
|
+
tools: List of tools agent can use
|
|
170
|
+
required_responses: Conditions that must be met (question_id → required value)
|
|
171
|
+
config_mapping: Map form responses to agent config (form_key → config_key)
|
|
172
|
+
success_criteria: List of success criteria for this agent
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
role: str
|
|
176
|
+
base_template: str
|
|
177
|
+
tier_strategy: TierStrategy
|
|
178
|
+
tools: list[str] = field(default_factory=list)
|
|
179
|
+
required_responses: dict[str, str | list[str]] = field(default_factory=dict)
|
|
180
|
+
config_mapping: dict[str, str] = field(default_factory=dict)
|
|
181
|
+
success_criteria: list[str] = field(default_factory=list)
|
|
182
|
+
|
|
183
|
+
def should_create(self, response: FormResponse) -> bool:
|
|
184
|
+
"""Check if agent should be created based on form responses.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
response: User's form responses
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
True if all required conditions are met
|
|
191
|
+
"""
|
|
192
|
+
for key, required_value in self.required_responses.items():
|
|
193
|
+
user_response = response.get(key)
|
|
194
|
+
|
|
195
|
+
# Multi-select: check if required value in list
|
|
196
|
+
if isinstance(user_response, list):
|
|
197
|
+
# If required_value is a list, check if ANY match
|
|
198
|
+
if isinstance(required_value, list):
|
|
199
|
+
if not any(rv in user_response for rv in required_value):
|
|
200
|
+
return False
|
|
201
|
+
# Single required value must be in user's selections
|
|
202
|
+
else:
|
|
203
|
+
if required_value not in user_response:
|
|
204
|
+
return False
|
|
205
|
+
|
|
206
|
+
# Single value: exact match required
|
|
207
|
+
else:
|
|
208
|
+
if isinstance(required_value, list):
|
|
209
|
+
# User must have picked one of the allowed values
|
|
210
|
+
if user_response not in required_value:
|
|
211
|
+
return False
|
|
212
|
+
else:
|
|
213
|
+
# Exact match
|
|
214
|
+
if user_response != required_value:
|
|
215
|
+
return False
|
|
216
|
+
|
|
217
|
+
return True
|
|
218
|
+
|
|
219
|
+
def create_agent_config(self, response: FormResponse) -> dict[str, Any]:
|
|
220
|
+
"""Create agent configuration from form responses.
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
response: User's form responses
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
Agent configuration dictionary
|
|
227
|
+
"""
|
|
228
|
+
config = {}
|
|
229
|
+
for form_key, config_key in self.config_mapping.items():
|
|
230
|
+
value = response.get(form_key)
|
|
231
|
+
if value is not None:
|
|
232
|
+
config[config_key] = value
|
|
233
|
+
return config
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
@dataclass
|
|
237
|
+
class AgentSpec:
|
|
238
|
+
"""Specification for a dynamically created agent instance.
|
|
239
|
+
|
|
240
|
+
Attributes:
|
|
241
|
+
role: Agent's role/purpose
|
|
242
|
+
base_template: Base agent template used
|
|
243
|
+
tier_strategy: Model tier escalation strategy
|
|
244
|
+
tools: List of tools agent can use
|
|
245
|
+
config: Agent-specific configuration
|
|
246
|
+
success_criteria: List of success criteria
|
|
247
|
+
agent_id: Unique identifier for this agent instance
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
role: str
|
|
251
|
+
base_template: str
|
|
252
|
+
tier_strategy: TierStrategy
|
|
253
|
+
tools: list[str] = field(default_factory=list)
|
|
254
|
+
config: dict[str, Any] = field(default_factory=dict)
|
|
255
|
+
success_criteria: list[str] = field(default_factory=list)
|
|
256
|
+
agent_id: str = field(default_factory=lambda: f"agent-{uuid.uuid4().hex[:12]}")
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
# =============================================================================
|
|
260
|
+
# Meta-Workflow Components
|
|
261
|
+
# =============================================================================
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
@dataclass
|
|
265
|
+
class MetaWorkflowTemplate:
|
|
266
|
+
"""Template defining a complete meta-workflow.
|
|
267
|
+
|
|
268
|
+
Attributes:
|
|
269
|
+
template_id: Unique identifier for this template
|
|
270
|
+
name: Human-readable name
|
|
271
|
+
description: Description of what this workflow does
|
|
272
|
+
version: Template version
|
|
273
|
+
tags: Tags for categorization
|
|
274
|
+
author: Template author
|
|
275
|
+
form_schema: Form questions to ask user
|
|
276
|
+
agent_composition_rules: Rules for creating agents
|
|
277
|
+
estimated_cost_range: Estimated cost range (min, max)
|
|
278
|
+
estimated_duration_minutes: Estimated duration in minutes
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
template_id: str
|
|
282
|
+
name: str
|
|
283
|
+
description: str
|
|
284
|
+
form_schema: FormSchema
|
|
285
|
+
agent_composition_rules: list[AgentCompositionRule] = field(default_factory=list)
|
|
286
|
+
version: str = "1.0.0"
|
|
287
|
+
tags: list[str] = field(default_factory=list)
|
|
288
|
+
author: str = "system"
|
|
289
|
+
estimated_cost_range: tuple[float, float] = (0.05, 0.50)
|
|
290
|
+
estimated_duration_minutes: int = 5
|
|
291
|
+
|
|
292
|
+
def to_json(self) -> str:
|
|
293
|
+
"""Serialize template to JSON string.
|
|
294
|
+
|
|
295
|
+
Returns:
|
|
296
|
+
JSON string representation
|
|
297
|
+
"""
|
|
298
|
+
data = {
|
|
299
|
+
"template_id": self.template_id,
|
|
300
|
+
"name": self.name,
|
|
301
|
+
"description": self.description,
|
|
302
|
+
"version": self.version,
|
|
303
|
+
"tags": self.tags,
|
|
304
|
+
"author": self.author,
|
|
305
|
+
"estimated_cost_range": list(self.estimated_cost_range),
|
|
306
|
+
"estimated_duration_minutes": self.estimated_duration_minutes,
|
|
307
|
+
"form_schema": {
|
|
308
|
+
"title": self.form_schema.title,
|
|
309
|
+
"description": self.form_schema.description,
|
|
310
|
+
"questions": [
|
|
311
|
+
{
|
|
312
|
+
"id": q.id,
|
|
313
|
+
"text": q.text,
|
|
314
|
+
"type": q.type.value,
|
|
315
|
+
"options": q.options,
|
|
316
|
+
"default": q.default,
|
|
317
|
+
"help_text": q.help_text,
|
|
318
|
+
"required": q.required,
|
|
319
|
+
}
|
|
320
|
+
for q in self.form_schema.questions
|
|
321
|
+
],
|
|
322
|
+
},
|
|
323
|
+
"agent_composition_rules": [
|
|
324
|
+
{
|
|
325
|
+
"role": rule.role,
|
|
326
|
+
"base_template": rule.base_template,
|
|
327
|
+
"tier_strategy": rule.tier_strategy.value,
|
|
328
|
+
"tools": rule.tools,
|
|
329
|
+
"required_responses": rule.required_responses,
|
|
330
|
+
"config_mapping": rule.config_mapping,
|
|
331
|
+
"success_criteria": rule.success_criteria,
|
|
332
|
+
}
|
|
333
|
+
for rule in self.agent_composition_rules
|
|
334
|
+
],
|
|
335
|
+
}
|
|
336
|
+
return json.dumps(data, indent=2)
|
|
337
|
+
|
|
338
|
+
@staticmethod
|
|
339
|
+
def from_json(json_str: str) -> "MetaWorkflowTemplate":
|
|
340
|
+
"""Deserialize template from JSON string.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
json_str: JSON string representation
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
MetaWorkflowTemplate instance
|
|
347
|
+
|
|
348
|
+
Raises:
|
|
349
|
+
ValueError: If JSON is invalid or missing required fields
|
|
350
|
+
"""
|
|
351
|
+
try:
|
|
352
|
+
data = json.loads(json_str)
|
|
353
|
+
except json.JSONDecodeError as e:
|
|
354
|
+
raise ValueError(f"Invalid JSON: {e}") from e
|
|
355
|
+
|
|
356
|
+
# Parse form schema
|
|
357
|
+
form_schema = FormSchema(
|
|
358
|
+
title=data["form_schema"]["title"],
|
|
359
|
+
description=data["form_schema"]["description"],
|
|
360
|
+
questions=[
|
|
361
|
+
FormQuestion(
|
|
362
|
+
id=q["id"],
|
|
363
|
+
text=q["text"],
|
|
364
|
+
type=QuestionType(q["type"]),
|
|
365
|
+
options=q.get("options", []),
|
|
366
|
+
default=q.get("default"),
|
|
367
|
+
help_text=q.get("help_text"),
|
|
368
|
+
required=q.get("required", True),
|
|
369
|
+
)
|
|
370
|
+
for q in data["form_schema"]["questions"]
|
|
371
|
+
],
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
# Parse agent composition rules
|
|
375
|
+
rules = [
|
|
376
|
+
AgentCompositionRule(
|
|
377
|
+
role=rule["role"],
|
|
378
|
+
base_template=rule["base_template"],
|
|
379
|
+
tier_strategy=TierStrategy(rule["tier_strategy"]),
|
|
380
|
+
tools=rule.get("tools", []),
|
|
381
|
+
required_responses=rule.get("required_responses", {}),
|
|
382
|
+
config_mapping=rule.get("config_mapping", {}),
|
|
383
|
+
success_criteria=rule.get("success_criteria", []),
|
|
384
|
+
)
|
|
385
|
+
for rule in data.get("agent_composition_rules", [])
|
|
386
|
+
]
|
|
387
|
+
|
|
388
|
+
return MetaWorkflowTemplate(
|
|
389
|
+
template_id=data["template_id"],
|
|
390
|
+
name=data["name"],
|
|
391
|
+
description=data["description"],
|
|
392
|
+
version=data.get("version", "1.0.0"),
|
|
393
|
+
tags=data.get("tags", []),
|
|
394
|
+
author=data.get("author", "system"),
|
|
395
|
+
form_schema=form_schema,
|
|
396
|
+
agent_composition_rules=rules,
|
|
397
|
+
estimated_cost_range=tuple(data.get("estimated_cost_range", [0.05, 0.50])),
|
|
398
|
+
estimated_duration_minutes=data.get("estimated_duration_minutes", 5),
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
@dataclass
|
|
403
|
+
class AgentExecutionResult:
|
|
404
|
+
"""Result from executing a single agent.
|
|
405
|
+
|
|
406
|
+
Attributes:
|
|
407
|
+
agent_id: ID of agent that executed
|
|
408
|
+
role: Agent's role
|
|
409
|
+
success: Whether agent succeeded
|
|
410
|
+
cost: Cost of execution
|
|
411
|
+
duration: Duration in seconds
|
|
412
|
+
tier_used: Model tier used
|
|
413
|
+
output: Agent's output/result
|
|
414
|
+
error: Error message if failed
|
|
415
|
+
"""
|
|
416
|
+
|
|
417
|
+
agent_id: str
|
|
418
|
+
role: str
|
|
419
|
+
success: bool
|
|
420
|
+
cost: float
|
|
421
|
+
duration: float
|
|
422
|
+
tier_used: str
|
|
423
|
+
output: str | dict[str, Any]
|
|
424
|
+
error: str | None = None
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
@dataclass
|
|
428
|
+
class MetaWorkflowResult:
|
|
429
|
+
"""Result from executing a complete meta-workflow.
|
|
430
|
+
|
|
431
|
+
Attributes:
|
|
432
|
+
run_id: Unique ID for this execution
|
|
433
|
+
template_id: ID of template used
|
|
434
|
+
timestamp: When execution started
|
|
435
|
+
form_responses: User's form responses
|
|
436
|
+
agents_created: List of agents that were created
|
|
437
|
+
agent_results: Results from agent executions
|
|
438
|
+
total_cost: Total cost of execution
|
|
439
|
+
total_duration: Total duration in seconds
|
|
440
|
+
success: Whether workflow succeeded
|
|
441
|
+
error: Error message if failed
|
|
442
|
+
"""
|
|
443
|
+
|
|
444
|
+
run_id: str
|
|
445
|
+
template_id: str
|
|
446
|
+
timestamp: str
|
|
447
|
+
form_responses: FormResponse
|
|
448
|
+
agents_created: list[AgentSpec] = field(default_factory=list)
|
|
449
|
+
agent_results: list[AgentExecutionResult] = field(default_factory=list)
|
|
450
|
+
total_cost: float = 0.0
|
|
451
|
+
total_duration: float = 0.0
|
|
452
|
+
success: bool = True
|
|
453
|
+
error: str | None = None
|
|
454
|
+
|
|
455
|
+
def to_dict(self) -> dict[str, Any]:
|
|
456
|
+
"""Convert result to dictionary for serialization.
|
|
457
|
+
|
|
458
|
+
Returns:
|
|
459
|
+
Dictionary representation
|
|
460
|
+
"""
|
|
461
|
+
return {
|
|
462
|
+
"run_id": self.run_id,
|
|
463
|
+
"template_id": self.template_id,
|
|
464
|
+
"timestamp": self.timestamp,
|
|
465
|
+
"form_responses": asdict(self.form_responses),
|
|
466
|
+
"agents_created": [asdict(agent) for agent in self.agents_created],
|
|
467
|
+
"agent_results": [asdict(result) for result in self.agent_results],
|
|
468
|
+
"total_cost": self.total_cost,
|
|
469
|
+
"total_duration": self.total_duration,
|
|
470
|
+
"success": self.success,
|
|
471
|
+
"error": self.error,
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
def to_json(self) -> str:
|
|
475
|
+
"""Serialize result to JSON string.
|
|
476
|
+
|
|
477
|
+
Returns:
|
|
478
|
+
JSON string representation
|
|
479
|
+
"""
|
|
480
|
+
return json.dumps(self.to_dict(), indent=2)
|
|
481
|
+
|
|
482
|
+
@staticmethod
|
|
483
|
+
def from_dict(data: dict[str, Any]) -> "MetaWorkflowResult":
|
|
484
|
+
"""Create result from dictionary.
|
|
485
|
+
|
|
486
|
+
Args:
|
|
487
|
+
data: Dictionary representation
|
|
488
|
+
|
|
489
|
+
Returns:
|
|
490
|
+
MetaWorkflowResult instance
|
|
491
|
+
"""
|
|
492
|
+
form_responses = FormResponse(
|
|
493
|
+
template_id=data["form_responses"]["template_id"],
|
|
494
|
+
responses=data["form_responses"]["responses"],
|
|
495
|
+
timestamp=data["form_responses"]["timestamp"],
|
|
496
|
+
response_id=data["form_responses"]["response_id"],
|
|
497
|
+
)
|
|
498
|
+
|
|
499
|
+
agents_created = [
|
|
500
|
+
AgentSpec(
|
|
501
|
+
role=agent["role"],
|
|
502
|
+
base_template=agent["base_template"],
|
|
503
|
+
tier_strategy=TierStrategy(agent["tier_strategy"]),
|
|
504
|
+
tools=agent["tools"],
|
|
505
|
+
config=agent["config"],
|
|
506
|
+
success_criteria=agent["success_criteria"],
|
|
507
|
+
agent_id=agent["agent_id"],
|
|
508
|
+
)
|
|
509
|
+
for agent in data.get("agents_created", [])
|
|
510
|
+
]
|
|
511
|
+
|
|
512
|
+
agent_results = [
|
|
513
|
+
AgentExecutionResult(
|
|
514
|
+
agent_id=result["agent_id"],
|
|
515
|
+
role=result["role"],
|
|
516
|
+
success=result["success"],
|
|
517
|
+
cost=result["cost"],
|
|
518
|
+
duration=result["duration"],
|
|
519
|
+
tier_used=result["tier_used"],
|
|
520
|
+
output=result["output"],
|
|
521
|
+
error=result.get("error"),
|
|
522
|
+
)
|
|
523
|
+
for result in data.get("agent_results", [])
|
|
524
|
+
]
|
|
525
|
+
|
|
526
|
+
return MetaWorkflowResult(
|
|
527
|
+
run_id=data["run_id"],
|
|
528
|
+
template_id=data["template_id"],
|
|
529
|
+
timestamp=data["timestamp"],
|
|
530
|
+
form_responses=form_responses,
|
|
531
|
+
agents_created=agents_created,
|
|
532
|
+
agent_results=agent_results,
|
|
533
|
+
total_cost=data.get("total_cost", 0.0),
|
|
534
|
+
total_duration=data.get("total_duration", 0.0),
|
|
535
|
+
success=data.get("success", True),
|
|
536
|
+
error=data.get("error"),
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
# =============================================================================
|
|
541
|
+
# Insight/Analytics Components
|
|
542
|
+
# =============================================================================
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
@dataclass
|
|
546
|
+
class PatternInsight:
|
|
547
|
+
"""An insight learned from analyzing workflow patterns.
|
|
548
|
+
|
|
549
|
+
Attributes:
|
|
550
|
+
insight_type: Type of insight (cost, tier_performance, agent_count, etc.)
|
|
551
|
+
description: Human-readable description
|
|
552
|
+
confidence: Confidence level (0.0 to 1.0)
|
|
553
|
+
data: Supporting data for this insight
|
|
554
|
+
sample_size: Number of runs this insight is based on
|
|
555
|
+
"""
|
|
556
|
+
|
|
557
|
+
insight_type: str
|
|
558
|
+
description: str
|
|
559
|
+
confidence: float
|
|
560
|
+
data: dict[str, Any] = field(default_factory=dict)
|
|
561
|
+
sample_size: int = 0
|
|
562
|
+
|
|
563
|
+
def to_dict(self) -> dict[str, Any]:
|
|
564
|
+
"""Convert to dictionary.
|
|
565
|
+
|
|
566
|
+
Returns:
|
|
567
|
+
Dictionary representation
|
|
568
|
+
"""
|
|
569
|
+
return asdict(self)
|