kubiya-control-plane-api 0.9.15__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.
- control_plane_api/LICENSE +676 -0
- control_plane_api/README.md +350 -0
- control_plane_api/__init__.py +4 -0
- control_plane_api/__version__.py +8 -0
- control_plane_api/alembic/README +1 -0
- control_plane_api/alembic/env.py +121 -0
- control_plane_api/alembic/script.py.mako +28 -0
- control_plane_api/alembic/versions/2613c65c3dbe_initial_database_setup.py +32 -0
- control_plane_api/alembic/versions/2df520d4927d_merge_heads.py +28 -0
- control_plane_api/alembic/versions/43abf98d6a01_add_paused_status_to_executions.py +73 -0
- control_plane_api/alembic/versions/6289854264cb_merge_multiple_heads.py +28 -0
- control_plane_api/alembic/versions/6a4d4dc3d8dc_generate_execution_transitions.py +50 -0
- control_plane_api/alembic/versions/87d11cf0a783_add_disconnected_status_to_worker_.py +44 -0
- control_plane_api/alembic/versions/add_ephemeral_queue_support.py +85 -0
- control_plane_api/alembic/versions/add_model_type_to_llm_models.py +31 -0
- control_plane_api/alembic/versions/add_plan_executions_table.py +114 -0
- control_plane_api/alembic/versions/add_trace_span_tables.py +154 -0
- control_plane_api/alembic/versions/add_user_info_to_traces.py +36 -0
- control_plane_api/alembic/versions/adjusting_foreign_keys.py +32 -0
- control_plane_api/alembic/versions/b4983d976db2_initial_tables.py +1128 -0
- control_plane_api/alembic/versions/d181a3b40e71_rename_custom_metadata_to_metadata_in_.py +50 -0
- control_plane_api/alembic/versions/df9117888e82_add_missing_columns.py +82 -0
- control_plane_api/alembic/versions/f25de6ad895a_missing_migrations.py +34 -0
- control_plane_api/alembic/versions/f71305fb69b9_fix_ephemeral_queue_deletion_foreign_key.py +54 -0
- control_plane_api/alembic/versions/mark_local_exec_queues_as_ephemeral.py +68 -0
- control_plane_api/alembic.ini +148 -0
- control_plane_api/api/index.py +12 -0
- control_plane_api/app/__init__.py +11 -0
- control_plane_api/app/activities/__init__.py +20 -0
- control_plane_api/app/activities/agent_activities.py +384 -0
- control_plane_api/app/activities/plan_generation_activities.py +499 -0
- control_plane_api/app/activities/team_activities.py +424 -0
- control_plane_api/app/activities/temporal_cloud_activities.py +588 -0
- control_plane_api/app/config/__init__.py +35 -0
- control_plane_api/app/config/api_config.py +469 -0
- control_plane_api/app/config/config_loader.py +224 -0
- control_plane_api/app/config/model_pricing.py +323 -0
- control_plane_api/app/config/storage_config.py +159 -0
- control_plane_api/app/config.py +115 -0
- control_plane_api/app/controllers/__init__.py +0 -0
- control_plane_api/app/controllers/execution_environment_controller.py +1315 -0
- control_plane_api/app/database.py +135 -0
- control_plane_api/app/exceptions.py +408 -0
- control_plane_api/app/lib/__init__.py +11 -0
- control_plane_api/app/lib/environment.py +65 -0
- control_plane_api/app/lib/event_bus/__init__.py +17 -0
- control_plane_api/app/lib/event_bus/base.py +136 -0
- control_plane_api/app/lib/event_bus/manager.py +335 -0
- control_plane_api/app/lib/event_bus/providers/__init__.py +6 -0
- control_plane_api/app/lib/event_bus/providers/http_provider.py +166 -0
- control_plane_api/app/lib/event_bus/providers/nats_provider.py +324 -0
- control_plane_api/app/lib/event_bus/providers/redis_provider.py +233 -0
- control_plane_api/app/lib/event_bus/providers/websocket_provider.py +497 -0
- control_plane_api/app/lib/job_executor.py +330 -0
- control_plane_api/app/lib/kubiya_client.py +293 -0
- control_plane_api/app/lib/litellm_pricing.py +166 -0
- control_plane_api/app/lib/mcp_validation.py +163 -0
- control_plane_api/app/lib/nats/__init__.py +13 -0
- control_plane_api/app/lib/nats/credentials_manager.py +288 -0
- control_plane_api/app/lib/nats/listener.py +374 -0
- control_plane_api/app/lib/planning_prompt_builder.py +153 -0
- control_plane_api/app/lib/planning_tools/__init__.py +41 -0
- control_plane_api/app/lib/planning_tools/agents.py +409 -0
- control_plane_api/app/lib/planning_tools/agno_toolkit.py +836 -0
- control_plane_api/app/lib/planning_tools/base.py +119 -0
- control_plane_api/app/lib/planning_tools/cognitive_memory_tools.py +403 -0
- control_plane_api/app/lib/planning_tools/context_graph_tools.py +545 -0
- control_plane_api/app/lib/planning_tools/environments.py +218 -0
- control_plane_api/app/lib/planning_tools/knowledge.py +204 -0
- control_plane_api/app/lib/planning_tools/models.py +93 -0
- control_plane_api/app/lib/planning_tools/planning_service.py +646 -0
- control_plane_api/app/lib/planning_tools/resources.py +242 -0
- control_plane_api/app/lib/planning_tools/teams.py +334 -0
- control_plane_api/app/lib/policy_enforcer_client.py +1016 -0
- control_plane_api/app/lib/redis_client.py +803 -0
- control_plane_api/app/lib/sqlalchemy_utils.py +486 -0
- control_plane_api/app/lib/state_transition_tools/__init__.py +7 -0
- control_plane_api/app/lib/state_transition_tools/execution_context.py +388 -0
- control_plane_api/app/lib/storage/__init__.py +20 -0
- control_plane_api/app/lib/storage/base_provider.py +274 -0
- control_plane_api/app/lib/storage/provider_factory.py +157 -0
- control_plane_api/app/lib/storage/vercel_blob_provider.py +468 -0
- control_plane_api/app/lib/supabase.py +71 -0
- control_plane_api/app/lib/supabase_utils.py +138 -0
- control_plane_api/app/lib/task_planning/__init__.py +138 -0
- control_plane_api/app/lib/task_planning/agent_factory.py +308 -0
- control_plane_api/app/lib/task_planning/agents.py +389 -0
- control_plane_api/app/lib/task_planning/cache.py +218 -0
- control_plane_api/app/lib/task_planning/entity_resolver.py +273 -0
- control_plane_api/app/lib/task_planning/helpers.py +293 -0
- control_plane_api/app/lib/task_planning/hooks.py +474 -0
- control_plane_api/app/lib/task_planning/models.py +503 -0
- control_plane_api/app/lib/task_planning/plan_validator.py +166 -0
- control_plane_api/app/lib/task_planning/planning_workflow.py +2911 -0
- control_plane_api/app/lib/task_planning/runner.py +656 -0
- control_plane_api/app/lib/task_planning/streaming_hook.py +213 -0
- control_plane_api/app/lib/task_planning/workflow.py +424 -0
- control_plane_api/app/lib/templating/__init__.py +88 -0
- control_plane_api/app/lib/templating/compiler.py +278 -0
- control_plane_api/app/lib/templating/engine.py +178 -0
- control_plane_api/app/lib/templating/parsers/__init__.py +29 -0
- control_plane_api/app/lib/templating/parsers/base.py +96 -0
- control_plane_api/app/lib/templating/parsers/env.py +85 -0
- control_plane_api/app/lib/templating/parsers/graph.py +112 -0
- control_plane_api/app/lib/templating/parsers/secret.py +87 -0
- control_plane_api/app/lib/templating/parsers/simple.py +81 -0
- control_plane_api/app/lib/templating/resolver.py +366 -0
- control_plane_api/app/lib/templating/types.py +214 -0
- control_plane_api/app/lib/templating/validator.py +201 -0
- control_plane_api/app/lib/temporal_client.py +232 -0
- control_plane_api/app/lib/temporal_credentials_cache.py +178 -0
- control_plane_api/app/lib/temporal_credentials_service.py +203 -0
- control_plane_api/app/lib/validation/__init__.py +24 -0
- control_plane_api/app/lib/validation/runtime_validation.py +388 -0
- control_plane_api/app/main.py +531 -0
- control_plane_api/app/middleware/__init__.py +10 -0
- control_plane_api/app/middleware/auth.py +645 -0
- control_plane_api/app/middleware/exception_handler.py +267 -0
- control_plane_api/app/middleware/prometheus_middleware.py +173 -0
- control_plane_api/app/middleware/rate_limiting.py +384 -0
- control_plane_api/app/middleware/request_id.py +202 -0
- control_plane_api/app/models/__init__.py +40 -0
- control_plane_api/app/models/agent.py +90 -0
- control_plane_api/app/models/analytics.py +206 -0
- control_plane_api/app/models/associations.py +107 -0
- control_plane_api/app/models/auth_user.py +73 -0
- control_plane_api/app/models/context.py +161 -0
- control_plane_api/app/models/custom_integration.py +99 -0
- control_plane_api/app/models/environment.py +64 -0
- control_plane_api/app/models/execution.py +125 -0
- control_plane_api/app/models/execution_transition.py +50 -0
- control_plane_api/app/models/job.py +159 -0
- control_plane_api/app/models/llm_model.py +78 -0
- control_plane_api/app/models/orchestration.py +66 -0
- control_plane_api/app/models/plan_execution.py +102 -0
- control_plane_api/app/models/presence.py +49 -0
- control_plane_api/app/models/project.py +61 -0
- control_plane_api/app/models/project_management.py +85 -0
- control_plane_api/app/models/session.py +29 -0
- control_plane_api/app/models/skill.py +155 -0
- control_plane_api/app/models/system_tables.py +43 -0
- control_plane_api/app/models/task_planning.py +372 -0
- control_plane_api/app/models/team.py +86 -0
- control_plane_api/app/models/trace.py +257 -0
- control_plane_api/app/models/user_profile.py +54 -0
- control_plane_api/app/models/worker.py +221 -0
- control_plane_api/app/models/workflow.py +161 -0
- control_plane_api/app/models/workspace.py +50 -0
- control_plane_api/app/observability/__init__.py +177 -0
- control_plane_api/app/observability/context_logging.py +475 -0
- control_plane_api/app/observability/decorators.py +337 -0
- control_plane_api/app/observability/local_span_processor.py +702 -0
- control_plane_api/app/observability/metrics.py +303 -0
- control_plane_api/app/observability/middleware.py +246 -0
- control_plane_api/app/observability/optional.py +115 -0
- control_plane_api/app/observability/tracing.py +382 -0
- control_plane_api/app/policies/README.md +149 -0
- control_plane_api/app/policies/approved_users.rego +62 -0
- control_plane_api/app/policies/business_hours.rego +51 -0
- control_plane_api/app/policies/rate_limiting.rego +100 -0
- control_plane_api/app/policies/tool_enforcement/README.md +336 -0
- control_plane_api/app/policies/tool_enforcement/bash_command_validation.rego +71 -0
- control_plane_api/app/policies/tool_enforcement/business_hours_enforcement.rego +82 -0
- control_plane_api/app/policies/tool_enforcement/mcp_tool_allowlist.rego +58 -0
- control_plane_api/app/policies/tool_enforcement/production_safeguards.rego +80 -0
- control_plane_api/app/policies/tool_enforcement/role_based_tool_access.rego +44 -0
- control_plane_api/app/policies/tool_restrictions.rego +86 -0
- control_plane_api/app/routers/__init__.py +4 -0
- control_plane_api/app/routers/agents.py +382 -0
- control_plane_api/app/routers/agents_v2.py +1598 -0
- control_plane_api/app/routers/analytics.py +1310 -0
- control_plane_api/app/routers/auth.py +59 -0
- control_plane_api/app/routers/client_config.py +57 -0
- control_plane_api/app/routers/context_graph.py +561 -0
- control_plane_api/app/routers/context_manager.py +577 -0
- control_plane_api/app/routers/custom_integrations.py +490 -0
- control_plane_api/app/routers/enforcer.py +132 -0
- control_plane_api/app/routers/environment_context.py +252 -0
- control_plane_api/app/routers/environments.py +761 -0
- control_plane_api/app/routers/execution_environment.py +847 -0
- control_plane_api/app/routers/executions/__init__.py +28 -0
- control_plane_api/app/routers/executions/router.py +286 -0
- control_plane_api/app/routers/executions/services/__init__.py +22 -0
- control_plane_api/app/routers/executions/services/demo_worker_health.py +156 -0
- control_plane_api/app/routers/executions/services/status_service.py +420 -0
- control_plane_api/app/routers/executions/services/test_worker_health.py +480 -0
- control_plane_api/app/routers/executions/services/worker_health.py +514 -0
- control_plane_api/app/routers/executions/streaming/__init__.py +22 -0
- control_plane_api/app/routers/executions/streaming/deduplication.py +352 -0
- control_plane_api/app/routers/executions/streaming/event_buffer.py +353 -0
- control_plane_api/app/routers/executions/streaming/event_formatter.py +964 -0
- control_plane_api/app/routers/executions/streaming/history_loader.py +588 -0
- control_plane_api/app/routers/executions/streaming/live_source.py +693 -0
- control_plane_api/app/routers/executions/streaming/streamer.py +849 -0
- control_plane_api/app/routers/executions.py +4888 -0
- control_plane_api/app/routers/health.py +165 -0
- control_plane_api/app/routers/health_v2.py +394 -0
- control_plane_api/app/routers/integration_templates.py +496 -0
- control_plane_api/app/routers/integrations.py +287 -0
- control_plane_api/app/routers/jobs.py +1809 -0
- control_plane_api/app/routers/metrics.py +517 -0
- control_plane_api/app/routers/models.py +82 -0
- control_plane_api/app/routers/models_v2.py +628 -0
- control_plane_api/app/routers/plan_executions.py +1481 -0
- control_plane_api/app/routers/plan_generation_async.py +304 -0
- control_plane_api/app/routers/policies.py +669 -0
- control_plane_api/app/routers/presence.py +234 -0
- control_plane_api/app/routers/projects.py +987 -0
- control_plane_api/app/routers/runners.py +379 -0
- control_plane_api/app/routers/runtimes.py +172 -0
- control_plane_api/app/routers/secrets.py +171 -0
- control_plane_api/app/routers/skills.py +1010 -0
- control_plane_api/app/routers/skills_definitions.py +140 -0
- control_plane_api/app/routers/storage.py +456 -0
- control_plane_api/app/routers/task_planning.py +611 -0
- control_plane_api/app/routers/task_queues.py +650 -0
- control_plane_api/app/routers/team_context.py +274 -0
- control_plane_api/app/routers/teams.py +1747 -0
- control_plane_api/app/routers/templates.py +248 -0
- control_plane_api/app/routers/traces.py +571 -0
- control_plane_api/app/routers/websocket_client.py +479 -0
- control_plane_api/app/routers/websocket_executions_status.py +437 -0
- control_plane_api/app/routers/websocket_gateway.py +323 -0
- control_plane_api/app/routers/websocket_traces.py +576 -0
- control_plane_api/app/routers/worker_queues.py +2555 -0
- control_plane_api/app/routers/worker_websocket.py +419 -0
- control_plane_api/app/routers/workers.py +1004 -0
- control_plane_api/app/routers/workflows.py +204 -0
- control_plane_api/app/runtimes/__init__.py +6 -0
- control_plane_api/app/runtimes/validation.py +344 -0
- control_plane_api/app/schemas/__init__.py +1 -0
- control_plane_api/app/schemas/job_schemas.py +302 -0
- control_plane_api/app/schemas/mcp_schemas.py +311 -0
- control_plane_api/app/schemas/template_schemas.py +133 -0
- control_plane_api/app/schemas/trace_schemas.py +168 -0
- control_plane_api/app/schemas/worker_queue_observability_schemas.py +165 -0
- control_plane_api/app/services/__init__.py +1 -0
- control_plane_api/app/services/agno_planning_strategy.py +233 -0
- control_plane_api/app/services/agno_service.py +838 -0
- control_plane_api/app/services/claude_code_planning_service.py +203 -0
- control_plane_api/app/services/context_graph_client.py +224 -0
- control_plane_api/app/services/custom_integration_service.py +415 -0
- control_plane_api/app/services/integration_resolution_service.py +345 -0
- control_plane_api/app/services/litellm_service.py +394 -0
- control_plane_api/app/services/plan_generator.py +79 -0
- control_plane_api/app/services/planning_strategy.py +66 -0
- control_plane_api/app/services/planning_strategy_factory.py +118 -0
- control_plane_api/app/services/policy_service.py +615 -0
- control_plane_api/app/services/state_transition_service.py +755 -0
- control_plane_api/app/services/storage_service.py +593 -0
- control_plane_api/app/services/temporal_cloud_provisioning.py +150 -0
- control_plane_api/app/services/toolsets/context_graph_skill.py +432 -0
- control_plane_api/app/services/trace_retention.py +354 -0
- control_plane_api/app/services/worker_queue_metrics_service.py +190 -0
- control_plane_api/app/services/workflow_cancellation_manager.py +135 -0
- control_plane_api/app/services/workflow_operations_service.py +611 -0
- control_plane_api/app/skills/__init__.py +100 -0
- control_plane_api/app/skills/base.py +239 -0
- control_plane_api/app/skills/builtin/__init__.py +37 -0
- control_plane_api/app/skills/builtin/agent_communication/__init__.py +8 -0
- control_plane_api/app/skills/builtin/agent_communication/skill.py +246 -0
- control_plane_api/app/skills/builtin/code_ingestion/__init__.py +4 -0
- control_plane_api/app/skills/builtin/code_ingestion/skill.py +267 -0
- control_plane_api/app/skills/builtin/cognitive_memory/__init__.py +4 -0
- control_plane_api/app/skills/builtin/cognitive_memory/skill.py +174 -0
- control_plane_api/app/skills/builtin/contextual_awareness/__init__.py +4 -0
- control_plane_api/app/skills/builtin/contextual_awareness/skill.py +387 -0
- control_plane_api/app/skills/builtin/data_visualization/__init__.py +4 -0
- control_plane_api/app/skills/builtin/data_visualization/skill.py +154 -0
- control_plane_api/app/skills/builtin/docker/__init__.py +4 -0
- control_plane_api/app/skills/builtin/docker/skill.py +104 -0
- control_plane_api/app/skills/builtin/file_generation/__init__.py +4 -0
- control_plane_api/app/skills/builtin/file_generation/skill.py +94 -0
- control_plane_api/app/skills/builtin/file_system/__init__.py +4 -0
- control_plane_api/app/skills/builtin/file_system/skill.py +110 -0
- control_plane_api/app/skills/builtin/knowledge_api/__init__.py +5 -0
- control_plane_api/app/skills/builtin/knowledge_api/skill.py +124 -0
- control_plane_api/app/skills/builtin/python/__init__.py +4 -0
- control_plane_api/app/skills/builtin/python/skill.py +92 -0
- control_plane_api/app/skills/builtin/remote_filesystem/__init__.py +5 -0
- control_plane_api/app/skills/builtin/remote_filesystem/skill.py +170 -0
- control_plane_api/app/skills/builtin/shell/__init__.py +4 -0
- control_plane_api/app/skills/builtin/shell/skill.py +161 -0
- control_plane_api/app/skills/builtin/slack/__init__.py +3 -0
- control_plane_api/app/skills/builtin/slack/skill.py +302 -0
- control_plane_api/app/skills/builtin/workflow_executor/__init__.py +4 -0
- control_plane_api/app/skills/builtin/workflow_executor/skill.py +469 -0
- control_plane_api/app/skills/business_intelligence.py +189 -0
- control_plane_api/app/skills/config.py +63 -0
- control_plane_api/app/skills/loaders/__init__.py +14 -0
- control_plane_api/app/skills/loaders/base.py +73 -0
- control_plane_api/app/skills/loaders/filesystem_loader.py +199 -0
- control_plane_api/app/skills/registry.py +125 -0
- control_plane_api/app/utils/helpers.py +12 -0
- control_plane_api/app/utils/workflow_executor.py +354 -0
- control_plane_api/app/workflows/__init__.py +11 -0
- control_plane_api/app/workflows/agent_execution.py +520 -0
- control_plane_api/app/workflows/agent_execution_with_skills.py +223 -0
- control_plane_api/app/workflows/namespace_provisioning.py +326 -0
- control_plane_api/app/workflows/plan_generation.py +254 -0
- control_plane_api/app/workflows/team_execution.py +442 -0
- control_plane_api/scripts/seed_models.py +240 -0
- control_plane_api/scripts/validate_existing_tool_names.py +492 -0
- control_plane_api/shared/__init__.py +8 -0
- control_plane_api/shared/version.py +17 -0
- control_plane_api/test_deduplication.py +274 -0
- control_plane_api/test_executor_deduplication_e2e.py +309 -0
- control_plane_api/test_job_execution_e2e.py +283 -0
- control_plane_api/test_real_integration.py +193 -0
- control_plane_api/version.py +38 -0
- control_plane_api/worker/__init__.py +0 -0
- control_plane_api/worker/activities/__init__.py +0 -0
- control_plane_api/worker/activities/agent_activities.py +1585 -0
- control_plane_api/worker/activities/approval_activities.py +234 -0
- control_plane_api/worker/activities/job_activities.py +199 -0
- control_plane_api/worker/activities/runtime_activities.py +1167 -0
- control_plane_api/worker/activities/skill_activities.py +282 -0
- control_plane_api/worker/activities/team_activities.py +479 -0
- control_plane_api/worker/agent_runtime_server.py +370 -0
- control_plane_api/worker/binary_manager.py +333 -0
- control_plane_api/worker/config/__init__.py +31 -0
- control_plane_api/worker/config/worker_config.py +273 -0
- control_plane_api/worker/control_plane_client.py +1491 -0
- control_plane_api/worker/examples/analytics_integration_example.py +362 -0
- control_plane_api/worker/health_monitor.py +159 -0
- control_plane_api/worker/metrics.py +237 -0
- control_plane_api/worker/models/__init__.py +1 -0
- control_plane_api/worker/models/error_events.py +105 -0
- control_plane_api/worker/models/inputs.py +89 -0
- control_plane_api/worker/runtimes/__init__.py +35 -0
- control_plane_api/worker/runtimes/agent_runtime/runtime.py +485 -0
- control_plane_api/worker/runtimes/agno/__init__.py +34 -0
- control_plane_api/worker/runtimes/agno/config.py +248 -0
- control_plane_api/worker/runtimes/agno/hooks.py +385 -0
- control_plane_api/worker/runtimes/agno/mcp_builder.py +195 -0
- control_plane_api/worker/runtimes/agno/runtime.py +1063 -0
- control_plane_api/worker/runtimes/agno/utils.py +163 -0
- control_plane_api/worker/runtimes/base.py +979 -0
- control_plane_api/worker/runtimes/claude_code/__init__.py +38 -0
- control_plane_api/worker/runtimes/claude_code/cleanup.py +184 -0
- control_plane_api/worker/runtimes/claude_code/client_pool.py +529 -0
- control_plane_api/worker/runtimes/claude_code/config.py +829 -0
- control_plane_api/worker/runtimes/claude_code/hooks.py +482 -0
- control_plane_api/worker/runtimes/claude_code/litellm_proxy.py +1702 -0
- control_plane_api/worker/runtimes/claude_code/mcp_builder.py +467 -0
- control_plane_api/worker/runtimes/claude_code/mcp_discovery.py +558 -0
- control_plane_api/worker/runtimes/claude_code/runtime.py +1546 -0
- control_plane_api/worker/runtimes/claude_code/tool_mapper.py +403 -0
- control_plane_api/worker/runtimes/claude_code/utils.py +149 -0
- control_plane_api/worker/runtimes/factory.py +173 -0
- control_plane_api/worker/runtimes/model_utils.py +107 -0
- control_plane_api/worker/runtimes/validation.py +93 -0
- control_plane_api/worker/services/__init__.py +1 -0
- control_plane_api/worker/services/agent_communication_tools.py +908 -0
- control_plane_api/worker/services/agent_executor.py +485 -0
- control_plane_api/worker/services/agent_executor_v2.py +793 -0
- control_plane_api/worker/services/analytics_collector.py +457 -0
- control_plane_api/worker/services/analytics_service.py +464 -0
- control_plane_api/worker/services/approval_tools.py +310 -0
- control_plane_api/worker/services/approval_tools_agno.py +207 -0
- control_plane_api/worker/services/cancellation_manager.py +177 -0
- control_plane_api/worker/services/code_ingestion_tools.py +465 -0
- control_plane_api/worker/services/contextual_awareness_tools.py +405 -0
- control_plane_api/worker/services/data_visualization.py +834 -0
- control_plane_api/worker/services/event_publisher.py +531 -0
- control_plane_api/worker/services/jira_tools.py +257 -0
- control_plane_api/worker/services/remote_filesystem_tools.py +498 -0
- control_plane_api/worker/services/runtime_analytics.py +328 -0
- control_plane_api/worker/services/session_service.py +365 -0
- control_plane_api/worker/services/skill_context_enhancement.py +181 -0
- control_plane_api/worker/services/skill_factory.py +471 -0
- control_plane_api/worker/services/system_prompt_enhancement.py +410 -0
- control_plane_api/worker/services/team_executor.py +715 -0
- control_plane_api/worker/services/team_executor_v2.py +1866 -0
- control_plane_api/worker/services/tool_enforcement.py +254 -0
- control_plane_api/worker/services/workflow_executor/__init__.py +52 -0
- control_plane_api/worker/services/workflow_executor/event_processor.py +287 -0
- control_plane_api/worker/services/workflow_executor/event_publisher.py +210 -0
- control_plane_api/worker/services/workflow_executor/executors/__init__.py +15 -0
- control_plane_api/worker/services/workflow_executor/executors/base.py +270 -0
- control_plane_api/worker/services/workflow_executor/executors/json_executor.py +50 -0
- control_plane_api/worker/services/workflow_executor/executors/python_executor.py +50 -0
- control_plane_api/worker/services/workflow_executor/models.py +142 -0
- control_plane_api/worker/services/workflow_executor_tools.py +1748 -0
- control_plane_api/worker/skills/__init__.py +12 -0
- control_plane_api/worker/skills/builtin/context_graph_search/README.md +213 -0
- control_plane_api/worker/skills/builtin/context_graph_search/__init__.py +5 -0
- control_plane_api/worker/skills/builtin/context_graph_search/agno_impl.py +808 -0
- control_plane_api/worker/skills/builtin/context_graph_search/skill.yaml +67 -0
- control_plane_api/worker/skills/builtin/contextual_awareness/__init__.py +4 -0
- control_plane_api/worker/skills/builtin/contextual_awareness/agno_impl.py +62 -0
- control_plane_api/worker/skills/builtin/data_visualization/agno_impl.py +18 -0
- control_plane_api/worker/skills/builtin/data_visualization/skill.yaml +84 -0
- control_plane_api/worker/skills/builtin/docker/agno_impl.py +65 -0
- control_plane_api/worker/skills/builtin/docker/skill.yaml +60 -0
- control_plane_api/worker/skills/builtin/file_generation/agno_impl.py +47 -0
- control_plane_api/worker/skills/builtin/file_generation/skill.yaml +64 -0
- control_plane_api/worker/skills/builtin/file_system/agno_impl.py +32 -0
- control_plane_api/worker/skills/builtin/file_system/skill.yaml +54 -0
- control_plane_api/worker/skills/builtin/knowledge_api/__init__.py +4 -0
- control_plane_api/worker/skills/builtin/knowledge_api/agno_impl.py +50 -0
- control_plane_api/worker/skills/builtin/knowledge_api/skill.yaml +66 -0
- control_plane_api/worker/skills/builtin/python/agno_impl.py +25 -0
- control_plane_api/worker/skills/builtin/python/skill.yaml +60 -0
- control_plane_api/worker/skills/builtin/schema_fix_mixin.py +260 -0
- control_plane_api/worker/skills/builtin/shell/agno_impl.py +31 -0
- control_plane_api/worker/skills/builtin/shell/skill.yaml +60 -0
- control_plane_api/worker/skills/builtin/slack/__init__.py +3 -0
- control_plane_api/worker/skills/builtin/slack/agno_impl.py +1282 -0
- control_plane_api/worker/skills/builtin/slack/skill.yaml +276 -0
- control_plane_api/worker/skills/builtin/workflow_executor/agno_impl.py +62 -0
- control_plane_api/worker/skills/builtin/workflow_executor/skill.yaml +79 -0
- control_plane_api/worker/skills/loaders/__init__.py +5 -0
- control_plane_api/worker/skills/loaders/base.py +23 -0
- control_plane_api/worker/skills/loaders/filesystem_loader.py +357 -0
- control_plane_api/worker/skills/registry.py +208 -0
- control_plane_api/worker/tests/__init__.py +1 -0
- control_plane_api/worker/tests/conftest.py +12 -0
- control_plane_api/worker/tests/e2e/__init__.py +0 -0
- control_plane_api/worker/tests/e2e/test_context_graph_real_api.py +338 -0
- control_plane_api/worker/tests/e2e/test_context_graph_templates_e2e.py +523 -0
- control_plane_api/worker/tests/e2e/test_enforcement_e2e.py +344 -0
- control_plane_api/worker/tests/e2e/test_execution_flow.py +571 -0
- control_plane_api/worker/tests/e2e/test_single_execution_mode.py +656 -0
- control_plane_api/worker/tests/integration/__init__.py +0 -0
- control_plane_api/worker/tests/integration/test_builtin_skills_fixes.py +245 -0
- control_plane_api/worker/tests/integration/test_context_graph_search_integration.py +365 -0
- control_plane_api/worker/tests/integration/test_control_plane_integration.py +308 -0
- control_plane_api/worker/tests/integration/test_hook_enforcement_integration.py +579 -0
- control_plane_api/worker/tests/integration/test_scheduled_job_workflow.py +237 -0
- control_plane_api/worker/tests/integration/test_system_prompt_enhancement_integration.py +343 -0
- control_plane_api/worker/tests/unit/__init__.py +0 -0
- control_plane_api/worker/tests/unit/test_builtin_skill_autoload.py +396 -0
- control_plane_api/worker/tests/unit/test_context_graph_search.py +450 -0
- control_plane_api/worker/tests/unit/test_context_graph_templates.py +403 -0
- control_plane_api/worker/tests/unit/test_control_plane_client.py +401 -0
- control_plane_api/worker/tests/unit/test_control_plane_client_jobs.py +345 -0
- control_plane_api/worker/tests/unit/test_job_activities.py +353 -0
- control_plane_api/worker/tests/unit/test_skill_context_enhancement.py +321 -0
- control_plane_api/worker/tests/unit/test_system_prompt_enhancement.py +415 -0
- control_plane_api/worker/tests/unit/test_tool_enforcement.py +324 -0
- control_plane_api/worker/utils/__init__.py +1 -0
- control_plane_api/worker/utils/chunk_batcher.py +330 -0
- control_plane_api/worker/utils/environment.py +65 -0
- control_plane_api/worker/utils/error_publisher.py +260 -0
- control_plane_api/worker/utils/event_batcher.py +256 -0
- control_plane_api/worker/utils/logging_config.py +335 -0
- control_plane_api/worker/utils/logging_helper.py +326 -0
- control_plane_api/worker/utils/parameter_validator.py +120 -0
- control_plane_api/worker/utils/retry_utils.py +60 -0
- control_plane_api/worker/utils/streaming_utils.py +665 -0
- control_plane_api/worker/utils/tool_validation.py +332 -0
- control_plane_api/worker/utils/workspace_manager.py +163 -0
- control_plane_api/worker/websocket_client.py +393 -0
- control_plane_api/worker/worker.py +1297 -0
- control_plane_api/worker/workflows/__init__.py +0 -0
- control_plane_api/worker/workflows/agent_execution.py +909 -0
- control_plane_api/worker/workflows/scheduled_job_wrapper.py +332 -0
- control_plane_api/worker/workflows/team_execution.py +611 -0
- kubiya_control_plane_api-0.9.15.dist-info/METADATA +354 -0
- kubiya_control_plane_api-0.9.15.dist-info/RECORD +479 -0
- kubiya_control_plane_api-0.9.15.dist-info/WHEEL +5 -0
- kubiya_control_plane_api-0.9.15.dist-info/entry_points.txt +5 -0
- kubiya_control_plane_api-0.9.15.dist-info/licenses/LICENSE +676 -0
- kubiya_control_plane_api-0.9.15.dist-info/top_level.txt +3 -0
- scripts/__init__.py +1 -0
- scripts/migrations.py +39 -0
- scripts/seed_worker_queues.py +128 -0
- scripts/setup_agent_runtime.py +142 -0
- worker_internal/__init__.py +1 -0
- worker_internal/planner/__init__.py +1 -0
- worker_internal/planner/activities.py +1499 -0
- worker_internal/planner/agent_tools.py +197 -0
- worker_internal/planner/event_models.py +148 -0
- worker_internal/planner/event_publisher.py +67 -0
- worker_internal/planner/models.py +199 -0
- worker_internal/planner/retry_logic.py +134 -0
- worker_internal/planner/worker.py +300 -0
- worker_internal/planner/workflows.py +970 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Planning Agent Streaming Hook
|
|
3
|
+
|
|
4
|
+
Captures agent execution events (tool calls, reasoning) during task planning
|
|
5
|
+
and publishes them for real-time UI streaming.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Callable, Any, Optional
|
|
9
|
+
import time
|
|
10
|
+
import uuid
|
|
11
|
+
import structlog
|
|
12
|
+
|
|
13
|
+
logger = structlog.get_logger()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PlanningStreamingHook:
|
|
17
|
+
"""
|
|
18
|
+
Hook to capture and stream agent execution events during planning.
|
|
19
|
+
|
|
20
|
+
Similar to worker execution streaming but optimized for planning agents.
|
|
21
|
+
Captures:
|
|
22
|
+
- Tool executions (start/complete)
|
|
23
|
+
- Reasoning/thinking content
|
|
24
|
+
- Agent state transitions
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, event_publisher: Callable):
|
|
28
|
+
"""
|
|
29
|
+
Initialize streaming hook.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
event_publisher: Async function to publish events (yield SSE messages)
|
|
33
|
+
"""
|
|
34
|
+
self.event_publisher = event_publisher
|
|
35
|
+
self.active_tools = {} # tool_id -> tool info
|
|
36
|
+
self.tool_count = 0
|
|
37
|
+
self.thinking_buffer = [] # Buffer for thinking content
|
|
38
|
+
self.last_thinking_time = 0 # Debounce thinking events
|
|
39
|
+
|
|
40
|
+
def create_tool_hook(self) -> Callable:
|
|
41
|
+
"""
|
|
42
|
+
Create tool execution hook for Agno agent.
|
|
43
|
+
|
|
44
|
+
This hook captures tool calls before execution and publishes events
|
|
45
|
+
for real-time streaming to the UI.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Tool hook function compatible with Agno agent
|
|
49
|
+
"""
|
|
50
|
+
def tool_hook(
|
|
51
|
+
name: str = None,
|
|
52
|
+
function_name: str = None,
|
|
53
|
+
function: Callable = None,
|
|
54
|
+
arguments: dict = None,
|
|
55
|
+
**kwargs,
|
|
56
|
+
) -> Any:
|
|
57
|
+
"""Hook called by Agno when tools are executed"""
|
|
58
|
+
tool_name = name or function_name or "unknown_tool"
|
|
59
|
+
tool_args = arguments or {}
|
|
60
|
+
|
|
61
|
+
# Generate unique tool ID
|
|
62
|
+
self.tool_count += 1
|
|
63
|
+
tool_id = f"{tool_name}_{self.tool_count}_{uuid.uuid4().hex[:8]}"
|
|
64
|
+
|
|
65
|
+
logger.info(
|
|
66
|
+
"planning_tool_started",
|
|
67
|
+
tool_name=tool_name,
|
|
68
|
+
tool_id=tool_id,
|
|
69
|
+
args_keys=list(tool_args.keys()) if isinstance(tool_args, dict) else None
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# Track tool start time
|
|
73
|
+
start_time = time.time()
|
|
74
|
+
self.active_tools[tool_id] = {
|
|
75
|
+
"name": tool_name,
|
|
76
|
+
"start_time": start_time,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# Publish tool_started event
|
|
80
|
+
try:
|
|
81
|
+
logger.info("publishing_tool_started", tool_name=tool_name, tool_id=tool_id)
|
|
82
|
+
self.event_publisher({
|
|
83
|
+
"event": "tool_call",
|
|
84
|
+
"data": {
|
|
85
|
+
"tool_name": tool_name,
|
|
86
|
+
"tool_id": tool_id,
|
|
87
|
+
"tool_arguments": tool_args,
|
|
88
|
+
"timestamp": start_time,
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
logger.info("tool_started_event_published", tool_name=tool_name)
|
|
92
|
+
except Exception as e:
|
|
93
|
+
logger.error("failed_to_publish_tool_started", error=str(e))
|
|
94
|
+
|
|
95
|
+
# Execute the tool
|
|
96
|
+
result = None
|
|
97
|
+
error = None
|
|
98
|
+
status = "success"
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
if function and callable(function):
|
|
102
|
+
result = function(**tool_args) if tool_args else function()
|
|
103
|
+
else:
|
|
104
|
+
raise ValueError(f"Function not callable: {function}")
|
|
105
|
+
except Exception as e:
|
|
106
|
+
error = e
|
|
107
|
+
status = "failed"
|
|
108
|
+
result = str(e)
|
|
109
|
+
logger.error(
|
|
110
|
+
"planning_tool_failed",
|
|
111
|
+
tool_name=tool_name,
|
|
112
|
+
tool_id=tool_id,
|
|
113
|
+
error=str(e)
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Calculate duration
|
|
117
|
+
end_time = time.time()
|
|
118
|
+
duration = end_time - start_time
|
|
119
|
+
|
|
120
|
+
# Format result for streaming with smart truncation
|
|
121
|
+
result_str = str(result) if result else ""
|
|
122
|
+
MAX_RESULT_SIZE = 5000 # Increased from 1000 to preserve more context
|
|
123
|
+
|
|
124
|
+
if len(result_str) > MAX_RESULT_SIZE:
|
|
125
|
+
# Smart truncation: keep start and end, truncate middle
|
|
126
|
+
start_chunk = result_str[:2500]
|
|
127
|
+
end_chunk = result_str[-2500:]
|
|
128
|
+
result_str = f"{start_chunk}\n... ({len(result_str)} chars total, middle section truncated) ...\n{end_chunk}"
|
|
129
|
+
|
|
130
|
+
# Publish tool_completed event
|
|
131
|
+
try:
|
|
132
|
+
self.event_publisher({
|
|
133
|
+
"event": "tool_result",
|
|
134
|
+
"data": {
|
|
135
|
+
"tool_name": tool_name,
|
|
136
|
+
"tool_id": tool_id,
|
|
137
|
+
"status": status,
|
|
138
|
+
"result": result_str,
|
|
139
|
+
"duration": duration,
|
|
140
|
+
"timestamp": end_time,
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
except Exception as e:
|
|
144
|
+
logger.error("failed_to_publish_tool_completed", error=str(e))
|
|
145
|
+
|
|
146
|
+
# Clean up tracking
|
|
147
|
+
self.active_tools.pop(tool_id, None)
|
|
148
|
+
|
|
149
|
+
logger.info(
|
|
150
|
+
"planning_tool_completed",
|
|
151
|
+
tool_name=tool_name,
|
|
152
|
+
tool_id=tool_id,
|
|
153
|
+
status=status,
|
|
154
|
+
duration=f"{duration:.2f}s"
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Return result or raise error
|
|
158
|
+
if error:
|
|
159
|
+
raise error
|
|
160
|
+
return result
|
|
161
|
+
|
|
162
|
+
return tool_hook
|
|
163
|
+
|
|
164
|
+
def create_thinking_hook(self) -> Callable:
|
|
165
|
+
"""
|
|
166
|
+
Create thinking/reasoning hook for capturing LLM thoughts.
|
|
167
|
+
|
|
168
|
+
This hook captures LLM reasoning content as it's generated
|
|
169
|
+
and streams it in real-time to the UI with debouncing.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
Thinking hook function compatible with Agno agent
|
|
173
|
+
"""
|
|
174
|
+
def thinking_hook(content: str, **kwargs):
|
|
175
|
+
"""Hook called when LLM generates reasoning content"""
|
|
176
|
+
if not content or len(content.strip()) == 0:
|
|
177
|
+
return
|
|
178
|
+
|
|
179
|
+
# Debounce: Only publish every 200ms to avoid flooding
|
|
180
|
+
current_time = time.time()
|
|
181
|
+
if current_time - self.last_thinking_time < 0.2:
|
|
182
|
+
self.thinking_buffer.append(content)
|
|
183
|
+
return
|
|
184
|
+
|
|
185
|
+
# Flush buffer if we have content
|
|
186
|
+
if self.thinking_buffer:
|
|
187
|
+
content = " ".join(self.thinking_buffer) + " " + content
|
|
188
|
+
self.thinking_buffer = []
|
|
189
|
+
|
|
190
|
+
self.last_thinking_time = current_time
|
|
191
|
+
|
|
192
|
+
# Truncate very long thinking to avoid overwhelming the UI
|
|
193
|
+
MAX_THINKING_LENGTH = 500
|
|
194
|
+
if len(content) > MAX_THINKING_LENGTH:
|
|
195
|
+
content = content[:MAX_THINKING_LENGTH] + "..."
|
|
196
|
+
|
|
197
|
+
try:
|
|
198
|
+
logger.debug("publishing_thinking", length=len(content))
|
|
199
|
+
self.event_publisher({
|
|
200
|
+
"event": "thinking",
|
|
201
|
+
"data": {
|
|
202
|
+
"content": content,
|
|
203
|
+
"timestamp": current_time,
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
except Exception as e:
|
|
207
|
+
logger.error("failed_to_publish_thinking", error=str(e))
|
|
208
|
+
|
|
209
|
+
return thinking_hook
|
|
210
|
+
|
|
211
|
+
def get_active_tools_count(self) -> int:
|
|
212
|
+
"""Get count of currently executing tools"""
|
|
213
|
+
return len(self.active_tools)
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Task Planning Workflow Factory - Creates and configures planning workflows
|
|
3
|
+
|
|
4
|
+
This module provides factory functions to create Agno workflows for task planning:
|
|
5
|
+
- create_planning_workflow(): Standard 2-step workflow
|
|
6
|
+
- create_fast_workflow(): Single-step workflow for --local mode
|
|
7
|
+
|
|
8
|
+
The workflow orchestrates agents through defined steps with:
|
|
9
|
+
- Pre-fetched data caching
|
|
10
|
+
- Model configuration (Sonnet for reliability)
|
|
11
|
+
- Validation hooks
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from typing import Optional, Dict, Any
|
|
15
|
+
import os
|
|
16
|
+
import structlog
|
|
17
|
+
|
|
18
|
+
from sqlalchemy.orm import Session
|
|
19
|
+
from agno.workflow import Workflow
|
|
20
|
+
from agno.models.litellm import LiteLLM
|
|
21
|
+
|
|
22
|
+
from .cache import get_cached_prefetch, set_cached_prefetch
|
|
23
|
+
from .agents import (
|
|
24
|
+
create_analysis_and_selection_agent,
|
|
25
|
+
create_plan_generation_agent,
|
|
26
|
+
create_fast_selection_agent,
|
|
27
|
+
)
|
|
28
|
+
from .hooks import validate_prefetch_context
|
|
29
|
+
|
|
30
|
+
logger = structlog.get_logger()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# ============================================================================
|
|
34
|
+
# Model Configuration
|
|
35
|
+
# ============================================================================
|
|
36
|
+
|
|
37
|
+
def get_litellm_config() -> tuple[str, str]:
|
|
38
|
+
"""
|
|
39
|
+
Get LiteLLM API configuration from environment.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Tuple of (api_url, api_key)
|
|
43
|
+
|
|
44
|
+
Raises:
|
|
45
|
+
ValueError: If LITELLM_API_KEY is not set
|
|
46
|
+
"""
|
|
47
|
+
api_url = (
|
|
48
|
+
os.getenv("LITELLM_API_URL") or
|
|
49
|
+
os.getenv("LITELLM_API_BASE") or
|
|
50
|
+
"https://llm-proxy.kubiya.ai"
|
|
51
|
+
).strip()
|
|
52
|
+
|
|
53
|
+
api_key = os.getenv("LITELLM_API_KEY", "").strip()
|
|
54
|
+
if not api_key:
|
|
55
|
+
raise ValueError("LITELLM_API_KEY environment variable not set")
|
|
56
|
+
|
|
57
|
+
return api_url, api_key
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def create_model(
|
|
61
|
+
model_id: str,
|
|
62
|
+
api_url: str,
|
|
63
|
+
api_key: str,
|
|
64
|
+
timeout: int = 60
|
|
65
|
+
) -> LiteLLM:
|
|
66
|
+
"""
|
|
67
|
+
Create a LiteLLM model instance.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
model_id: Model identifier (e.g., "kubiya/claude-sonnet-4")
|
|
71
|
+
api_url: LiteLLM API base URL
|
|
72
|
+
api_key: LiteLLM API key
|
|
73
|
+
timeout: Request timeout in seconds
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Configured LiteLLM instance
|
|
77
|
+
"""
|
|
78
|
+
return LiteLLM(
|
|
79
|
+
id=f"openai/{model_id}",
|
|
80
|
+
api_base=api_url,
|
|
81
|
+
api_key=api_key,
|
|
82
|
+
request_params={"timeout": timeout}
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# ============================================================================
|
|
87
|
+
# Pre-fetch Resources
|
|
88
|
+
# ============================================================================
|
|
89
|
+
|
|
90
|
+
def prefetch_resources(
|
|
91
|
+
db: Session,
|
|
92
|
+
organization_id: str,
|
|
93
|
+
api_token: str,
|
|
94
|
+
outer_context: Optional[Dict[str, Any]] = None
|
|
95
|
+
) -> Dict[str, Any]:
|
|
96
|
+
"""
|
|
97
|
+
Pre-fetch organization resources with caching.
|
|
98
|
+
|
|
99
|
+
Fetches top 20 of each resource type (agents, teams, environments, queues)
|
|
100
|
+
and caches for 5 minutes to avoid repeated DB calls.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
db: Database session
|
|
104
|
+
organization_id: Organization ID
|
|
105
|
+
api_token: API token for authentication
|
|
106
|
+
outer_context: Optional pre-provided context (skips fetch)
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Dict with pre-fetched resources
|
|
110
|
+
"""
|
|
111
|
+
# Check cache first
|
|
112
|
+
cached = get_cached_prefetch(organization_id)
|
|
113
|
+
if cached and not outer_context:
|
|
114
|
+
logger.info("using_cached_prefetch", organization_id=organization_id[:8])
|
|
115
|
+
return cached.copy()
|
|
116
|
+
|
|
117
|
+
# Validate any provided outer_context
|
|
118
|
+
if outer_context:
|
|
119
|
+
outer_context = validate_prefetch_context(outer_context)
|
|
120
|
+
# If outer_context has data, use it (don't override with DB fetch)
|
|
121
|
+
if outer_context.get("agents") or outer_context.get("teams"):
|
|
122
|
+
logger.info(
|
|
123
|
+
"using_provided_context",
|
|
124
|
+
agents=len(outer_context.get("agents", [])),
|
|
125
|
+
teams=len(outer_context.get("teams", []))
|
|
126
|
+
)
|
|
127
|
+
return outer_context
|
|
128
|
+
|
|
129
|
+
# Fetch fresh data from database
|
|
130
|
+
logger.info("pre_fetching_top_resources", organization_id=organization_id[:8])
|
|
131
|
+
|
|
132
|
+
from control_plane_api.app.lib.planning_tools.planning_service import PlanningService
|
|
133
|
+
|
|
134
|
+
planning_service = PlanningService(db, organization_id, api_token)
|
|
135
|
+
result = {}
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
# Execute fetches SEQUENTIALLY to avoid SQLAlchemy session issues
|
|
139
|
+
agents_data = planning_service.list_agents(limit=20, status=None)
|
|
140
|
+
teams_data = planning_service.list_teams(limit=20, status=None)
|
|
141
|
+
# Don't filter by status - environments may have status="ready" or "active"
|
|
142
|
+
envs_data = planning_service.list_environments(status=None, limit=20)
|
|
143
|
+
queues_data = planning_service.list_worker_queues(limit=20)
|
|
144
|
+
|
|
145
|
+
result["agents"] = agents_data[:20]
|
|
146
|
+
result["teams"] = teams_data[:20]
|
|
147
|
+
result["environments"] = envs_data[:20]
|
|
148
|
+
|
|
149
|
+
# Sort worker queues by active_workers DESC
|
|
150
|
+
sorted_queues = sorted(
|
|
151
|
+
queues_data[:20],
|
|
152
|
+
key=lambda q: q.get("active_workers", 0),
|
|
153
|
+
reverse=True
|
|
154
|
+
)
|
|
155
|
+
result["worker_queues"] = sorted_queues
|
|
156
|
+
|
|
157
|
+
result["pre_fetch_note"] = "Top 20 resources. Use tools for more specific searches."
|
|
158
|
+
|
|
159
|
+
logger.info(
|
|
160
|
+
"pre_fetch_completed",
|
|
161
|
+
agents_count=len(result["agents"]),
|
|
162
|
+
teams_count=len(result["teams"]),
|
|
163
|
+
envs_count=len(result["environments"]),
|
|
164
|
+
queues_count=len(result["worker_queues"])
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# Cache for subsequent requests
|
|
168
|
+
set_cached_prefetch(organization_id, result)
|
|
169
|
+
|
|
170
|
+
except Exception as e:
|
|
171
|
+
import traceback
|
|
172
|
+
logger.warning(
|
|
173
|
+
"pre_fetch_failed",
|
|
174
|
+
error=str(e),
|
|
175
|
+
traceback=traceback.format_exc()
|
|
176
|
+
)
|
|
177
|
+
# Return empty context - agent will use tools instead
|
|
178
|
+
result = {}
|
|
179
|
+
|
|
180
|
+
return result
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
# ============================================================================
|
|
184
|
+
# Main Workflow Factory
|
|
185
|
+
# ============================================================================
|
|
186
|
+
|
|
187
|
+
def create_planning_workflow(
|
|
188
|
+
db: Session,
|
|
189
|
+
organization_id: str,
|
|
190
|
+
api_token: str,
|
|
191
|
+
quick_mode: bool = False,
|
|
192
|
+
outer_context: Optional[Dict[str, Any]] = None
|
|
193
|
+
) -> Workflow:
|
|
194
|
+
"""
|
|
195
|
+
Create the task planning workflow.
|
|
196
|
+
|
|
197
|
+
Creates a 2-step workflow:
|
|
198
|
+
- Step 1: Analysis & Resource Selection (tool calling + structured output)
|
|
199
|
+
- Step 2: Plan Generation (structured output only)
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
db: Database session
|
|
203
|
+
organization_id: Organization ID (required)
|
|
204
|
+
api_token: API token (required)
|
|
205
|
+
quick_mode: Deprecated, kept for compatibility
|
|
206
|
+
outer_context: Optional pre-fetched context
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
Configured Workflow instance
|
|
210
|
+
|
|
211
|
+
Raises:
|
|
212
|
+
ValueError: If required parameters are missing
|
|
213
|
+
"""
|
|
214
|
+
if not organization_id:
|
|
215
|
+
raise ValueError("organization_id is required")
|
|
216
|
+
if not api_token:
|
|
217
|
+
raise ValueError("api_token is required")
|
|
218
|
+
|
|
219
|
+
# Get LiteLLM configuration
|
|
220
|
+
api_url, api_key = get_litellm_config()
|
|
221
|
+
|
|
222
|
+
# Get model IDs from environment
|
|
223
|
+
step1_model_id = os.getenv("STEP1_MODEL", "kubiya/claude-sonnet-4").strip()
|
|
224
|
+
step2_model_id = os.getenv("STEP2_MODEL", "kubiya/claude-sonnet-4").strip()
|
|
225
|
+
|
|
226
|
+
logger.info(
|
|
227
|
+
"model_configuration",
|
|
228
|
+
step1_model=step1_model_id,
|
|
229
|
+
step2_model=step2_model_id,
|
|
230
|
+
message="Using Sonnet for both steps (reliable structured output)"
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# Create model instances
|
|
234
|
+
step1_model = create_model(step1_model_id, api_url, api_key, timeout=60)
|
|
235
|
+
step2_model = create_model(step2_model_id, api_url, api_key, timeout=60)
|
|
236
|
+
|
|
237
|
+
# Pre-fetch resources with caching
|
|
238
|
+
outer_context = prefetch_resources(db, organization_id, api_token, outer_context)
|
|
239
|
+
|
|
240
|
+
# Create planning toolkit for Step 1 tools
|
|
241
|
+
from control_plane_api.app.lib.planning_tools.agno_toolkit import PlanningToolkit
|
|
242
|
+
planning_toolkit = PlanningToolkit(db, organization_id, api_token)
|
|
243
|
+
|
|
244
|
+
# Create agents
|
|
245
|
+
step1_agent = create_analysis_and_selection_agent(
|
|
246
|
+
model=step1_model,
|
|
247
|
+
planning_toolkit=planning_toolkit,
|
|
248
|
+
outer_context=outer_context
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
step2_agent = create_plan_generation_agent(step2_model)
|
|
252
|
+
|
|
253
|
+
# Create 2-step workflow
|
|
254
|
+
workflow = Workflow(
|
|
255
|
+
name="Task Planning Workflow",
|
|
256
|
+
steps=[step1_agent, step2_agent],
|
|
257
|
+
description="2-step task planning: (1) Analysis & Selection, (2) Plan Generation"
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# Store references for validation and runtime access
|
|
261
|
+
workflow._planning_toolkit = planning_toolkit
|
|
262
|
+
workflow._outer_context = outer_context
|
|
263
|
+
workflow._organization_id = organization_id
|
|
264
|
+
|
|
265
|
+
logger.info(
|
|
266
|
+
"planning_workflow_created",
|
|
267
|
+
steps=2,
|
|
268
|
+
pre_fetched_data=bool(outer_context)
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
return workflow
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
# ============================================================================
|
|
275
|
+
# Fast Workflow Factory (--local mode)
|
|
276
|
+
# ============================================================================
|
|
277
|
+
|
|
278
|
+
def create_fast_planning_workflow(
|
|
279
|
+
db: Session,
|
|
280
|
+
organization_id: str,
|
|
281
|
+
api_token: str,
|
|
282
|
+
outer_context: Dict[str, Any]
|
|
283
|
+
) -> Workflow:
|
|
284
|
+
"""
|
|
285
|
+
Create a fast single-step workflow for --local mode.
|
|
286
|
+
|
|
287
|
+
Uses pre-fetched data only (no API calls) for maximum speed.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
db: Database session
|
|
291
|
+
organization_id: Organization ID
|
|
292
|
+
api_token: API token
|
|
293
|
+
outer_context: Pre-fetched context (required for fast mode)
|
|
294
|
+
|
|
295
|
+
Returns:
|
|
296
|
+
Configured single-step Workflow
|
|
297
|
+
|
|
298
|
+
Raises:
|
|
299
|
+
ValueError: If outer_context is empty
|
|
300
|
+
"""
|
|
301
|
+
if not outer_context or (not outer_context.get("agents") and not outer_context.get("teams")):
|
|
302
|
+
raise ValueError("outer_context with agents or teams is required for fast mode")
|
|
303
|
+
|
|
304
|
+
# Get LiteLLM configuration
|
|
305
|
+
api_url, api_key = get_litellm_config()
|
|
306
|
+
|
|
307
|
+
# Use faster model for single-step
|
|
308
|
+
model_id = os.getenv("FAST_MODEL", "kubiya/claude-sonnet-4").strip()
|
|
309
|
+
model = create_model(model_id, api_url, api_key, timeout=30)
|
|
310
|
+
|
|
311
|
+
# Validate context
|
|
312
|
+
outer_context = validate_prefetch_context(outer_context)
|
|
313
|
+
|
|
314
|
+
# Create fast selection agent
|
|
315
|
+
fast_agent = create_fast_selection_agent(model, outer_context)
|
|
316
|
+
|
|
317
|
+
# Create single-step workflow
|
|
318
|
+
workflow = Workflow(
|
|
319
|
+
name="Fast Selection Workflow",
|
|
320
|
+
steps=[fast_agent],
|
|
321
|
+
description="Single-step fast selection for --local mode"
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
workflow._outer_context = outer_context
|
|
325
|
+
workflow._organization_id = organization_id
|
|
326
|
+
|
|
327
|
+
logger.info(
|
|
328
|
+
"fast_workflow_created",
|
|
329
|
+
agents_count=len(outer_context.get("agents", [])),
|
|
330
|
+
teams_count=len(outer_context.get("teams", []))
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
return workflow
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
# ============================================================================
|
|
337
|
+
# Workflow Configuration Helpers
|
|
338
|
+
# ============================================================================
|
|
339
|
+
|
|
340
|
+
class WorkflowConfig:
|
|
341
|
+
"""Configuration for task planning workflows."""
|
|
342
|
+
|
|
343
|
+
def __init__(
|
|
344
|
+
self,
|
|
345
|
+
step1_model: str = "kubiya/claude-sonnet-4",
|
|
346
|
+
step2_model: str = "kubiya/claude-sonnet-4",
|
|
347
|
+
step1_timeout: int = 60,
|
|
348
|
+
step2_timeout: int = 60,
|
|
349
|
+
cache_ttl: int = 300,
|
|
350
|
+
prefer_runtime: str = "claude_code"
|
|
351
|
+
):
|
|
352
|
+
self.step1_model = step1_model
|
|
353
|
+
self.step2_model = step2_model
|
|
354
|
+
self.step1_timeout = step1_timeout
|
|
355
|
+
self.step2_timeout = step2_timeout
|
|
356
|
+
self.cache_ttl = cache_ttl
|
|
357
|
+
self.prefer_runtime = prefer_runtime
|
|
358
|
+
|
|
359
|
+
@classmethod
|
|
360
|
+
def from_env(cls) -> 'WorkflowConfig':
|
|
361
|
+
"""Create config from environment variables."""
|
|
362
|
+
return cls(
|
|
363
|
+
step1_model=os.getenv("STEP1_MODEL", "kubiya/claude-sonnet-4"),
|
|
364
|
+
step2_model=os.getenv("STEP2_MODEL", "kubiya/claude-sonnet-4"),
|
|
365
|
+
step1_timeout=int(os.getenv("STEP1_TIMEOUT", "60")),
|
|
366
|
+
step2_timeout=int(os.getenv("STEP2_TIMEOUT", "60")),
|
|
367
|
+
cache_ttl=int(os.getenv("PREFETCH_CACHE_TTL", "300")),
|
|
368
|
+
prefer_runtime=os.getenv("PREFER_RUNTIME", "claude_code")
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def create_workflow_with_config(
|
|
373
|
+
db: Session,
|
|
374
|
+
organization_id: str,
|
|
375
|
+
api_token: str,
|
|
376
|
+
config: WorkflowConfig,
|
|
377
|
+
outer_context: Optional[Dict[str, Any]] = None
|
|
378
|
+
) -> Workflow:
|
|
379
|
+
"""
|
|
380
|
+
Create workflow with explicit configuration.
|
|
381
|
+
|
|
382
|
+
Args:
|
|
383
|
+
db: Database session
|
|
384
|
+
organization_id: Organization ID
|
|
385
|
+
api_token: API token
|
|
386
|
+
config: Workflow configuration
|
|
387
|
+
outer_context: Optional pre-fetched context
|
|
388
|
+
|
|
389
|
+
Returns:
|
|
390
|
+
Configured Workflow
|
|
391
|
+
"""
|
|
392
|
+
api_url, api_key = get_litellm_config()
|
|
393
|
+
|
|
394
|
+
step1_model = create_model(config.step1_model, api_url, api_key, config.step1_timeout)
|
|
395
|
+
step2_model = create_model(config.step2_model, api_url, api_key, config.step2_timeout)
|
|
396
|
+
|
|
397
|
+
# Pre-fetch with config
|
|
398
|
+
outer_context = prefetch_resources(db, organization_id, api_token, outer_context)
|
|
399
|
+
|
|
400
|
+
# Add preferred runtime to context
|
|
401
|
+
if outer_context and not outer_context.get("preferred_runtime"):
|
|
402
|
+
outer_context["preferred_runtime"] = config.prefer_runtime
|
|
403
|
+
|
|
404
|
+
from control_plane_api.app.lib.planning_tools.agno_toolkit import PlanningToolkit
|
|
405
|
+
planning_toolkit = PlanningToolkit(db, organization_id, api_token)
|
|
406
|
+
|
|
407
|
+
step1_agent = create_analysis_and_selection_agent(
|
|
408
|
+
model=step1_model,
|
|
409
|
+
planning_toolkit=planning_toolkit,
|
|
410
|
+
outer_context=outer_context
|
|
411
|
+
)
|
|
412
|
+
step2_agent = create_plan_generation_agent(step2_model)
|
|
413
|
+
|
|
414
|
+
workflow = Workflow(
|
|
415
|
+
name="Task Planning Workflow",
|
|
416
|
+
steps=[step1_agent, step2_agent],
|
|
417
|
+
description="Configured 2-step task planning workflow"
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
workflow._planning_toolkit = planning_toolkit
|
|
421
|
+
workflow._outer_context = outer_context
|
|
422
|
+
workflow._config = config
|
|
423
|
+
|
|
424
|
+
return workflow
|