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,374 @@
|
|
|
1
|
+
"""NATS event listener for control plane."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Dict, Any, Optional, Set
|
|
5
|
+
import asyncio
|
|
6
|
+
import structlog
|
|
7
|
+
|
|
8
|
+
logger = structlog.get_logger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class NATSEventListener:
|
|
12
|
+
"""
|
|
13
|
+
Control plane listener for NATS events from workers.
|
|
14
|
+
|
|
15
|
+
Subscribes to org-specific subjects and processes events by storing them
|
|
16
|
+
in Redis for UI consumption (same flow as HTTP/WebSocket events).
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
nats_url: str,
|
|
22
|
+
credentials_file: str,
|
|
23
|
+
jetstream_enabled: bool = True,
|
|
24
|
+
stream_name: str = "EVENTS",
|
|
25
|
+
):
|
|
26
|
+
"""
|
|
27
|
+
Initialize NATS event listener.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
nats_url: NATS server URL
|
|
31
|
+
credentials_file: Path to control plane NATS credentials file
|
|
32
|
+
jetstream_enabled: Enable JetStream for durable consumers
|
|
33
|
+
stream_name: JetStream stream name
|
|
34
|
+
"""
|
|
35
|
+
self.nats_url = nats_url
|
|
36
|
+
self.credentials_file = credentials_file
|
|
37
|
+
self.jetstream_enabled = jetstream_enabled
|
|
38
|
+
self.stream_name = stream_name
|
|
39
|
+
|
|
40
|
+
self.nc = None # NATS connection
|
|
41
|
+
self.js = None # JetStream context
|
|
42
|
+
self.subscriptions: Dict[str, Any] = {} # org_id -> subscription
|
|
43
|
+
self._running = False
|
|
44
|
+
|
|
45
|
+
async def start(self) -> None:
|
|
46
|
+
"""Start NATS listener and connect to server."""
|
|
47
|
+
if self._running:
|
|
48
|
+
logger.warning("nats_listener_already_running")
|
|
49
|
+
return
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
# Import nats-py
|
|
53
|
+
try:
|
|
54
|
+
import nats
|
|
55
|
+
from nats.errors import TimeoutError, NoServersError
|
|
56
|
+
except ImportError:
|
|
57
|
+
raise ImportError(
|
|
58
|
+
"nats-py is required for NATS listener. "
|
|
59
|
+
"Install it with: pip install nats-py"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Connect to NATS
|
|
63
|
+
self.nc = await nats.connect(
|
|
64
|
+
servers=[self.nats_url],
|
|
65
|
+
user_credentials=self.credentials_file,
|
|
66
|
+
max_reconnect_attempts=-1, # Infinite reconnects
|
|
67
|
+
reconnect_time_wait=2,
|
|
68
|
+
ping_interval=20,
|
|
69
|
+
max_outstanding_pings=3,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# Initialize JetStream if enabled
|
|
73
|
+
if self.jetstream_enabled:
|
|
74
|
+
self.js = self.nc.jetstream()
|
|
75
|
+
|
|
76
|
+
self._running = True
|
|
77
|
+
|
|
78
|
+
logger.info(
|
|
79
|
+
"nats_listener_started",
|
|
80
|
+
url=self.nats_url,
|
|
81
|
+
jetstream_enabled=self.jetstream_enabled,
|
|
82
|
+
credentials_file=self.credentials_file,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
except ImportError as e:
|
|
86
|
+
logger.error(
|
|
87
|
+
"nats_listener_dependency_missing",
|
|
88
|
+
error=str(e),
|
|
89
|
+
)
|
|
90
|
+
raise
|
|
91
|
+
|
|
92
|
+
except Exception as e:
|
|
93
|
+
logger.error(
|
|
94
|
+
"nats_listener_start_failed",
|
|
95
|
+
error=str(e),
|
|
96
|
+
url=self.nats_url,
|
|
97
|
+
)
|
|
98
|
+
raise
|
|
99
|
+
|
|
100
|
+
async def subscribe_organization(self, organization_id: str) -> None:
|
|
101
|
+
"""
|
|
102
|
+
Subscribe to all events for an organization.
|
|
103
|
+
|
|
104
|
+
Subject: events.{organization_id}.>
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
organization_id: Organization ID to subscribe to
|
|
108
|
+
|
|
109
|
+
Raises:
|
|
110
|
+
RuntimeError: If listener not started
|
|
111
|
+
Exception: If subscription fails
|
|
112
|
+
"""
|
|
113
|
+
if not self._running or not self.nc:
|
|
114
|
+
raise RuntimeError("NATS listener not started")
|
|
115
|
+
|
|
116
|
+
if organization_id in self.subscriptions:
|
|
117
|
+
logger.warning(
|
|
118
|
+
"nats_org_already_subscribed",
|
|
119
|
+
organization_id=organization_id,
|
|
120
|
+
)
|
|
121
|
+
return
|
|
122
|
+
|
|
123
|
+
subject = f"events.{organization_id}.>"
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
async def message_handler(msg):
|
|
127
|
+
"""Handle incoming NATS message."""
|
|
128
|
+
try:
|
|
129
|
+
# Parse message
|
|
130
|
+
event_data = json.loads(msg.data.decode())
|
|
131
|
+
|
|
132
|
+
# Process event (store in Redis)
|
|
133
|
+
await self._process_event(event_data)
|
|
134
|
+
|
|
135
|
+
# Acknowledge message
|
|
136
|
+
if hasattr(msg, "ack"):
|
|
137
|
+
await msg.ack()
|
|
138
|
+
|
|
139
|
+
except json.JSONDecodeError as e:
|
|
140
|
+
logger.error(
|
|
141
|
+
"nats_message_invalid_json",
|
|
142
|
+
error=str(e),
|
|
143
|
+
subject=msg.subject,
|
|
144
|
+
)
|
|
145
|
+
# Negative acknowledgment for retry
|
|
146
|
+
if hasattr(msg, "nak"):
|
|
147
|
+
await msg.nak()
|
|
148
|
+
|
|
149
|
+
except Exception as e:
|
|
150
|
+
logger.error(
|
|
151
|
+
"nats_message_process_error",
|
|
152
|
+
error=str(e),
|
|
153
|
+
subject=msg.subject,
|
|
154
|
+
)
|
|
155
|
+
# Negative acknowledgment for retry
|
|
156
|
+
if hasattr(msg, "nak"):
|
|
157
|
+
await msg.nak()
|
|
158
|
+
|
|
159
|
+
if self.jetstream_enabled and self.js:
|
|
160
|
+
# Subscribe with JetStream (durable consumer)
|
|
161
|
+
consumer_name = f"control-plane-{organization_id}"
|
|
162
|
+
|
|
163
|
+
sub = await self.js.subscribe(
|
|
164
|
+
subject,
|
|
165
|
+
durable=consumer_name,
|
|
166
|
+
cb=message_handler,
|
|
167
|
+
manual_ack=True,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
logger.info(
|
|
171
|
+
"nats_jetstream_org_subscribed",
|
|
172
|
+
organization_id=organization_id,
|
|
173
|
+
subject=subject,
|
|
174
|
+
consumer=consumer_name,
|
|
175
|
+
)
|
|
176
|
+
else:
|
|
177
|
+
# Subscribe without JetStream
|
|
178
|
+
sub = await self.nc.subscribe(subject, cb=message_handler)
|
|
179
|
+
|
|
180
|
+
logger.info(
|
|
181
|
+
"nats_org_subscribed",
|
|
182
|
+
organization_id=organization_id,
|
|
183
|
+
subject=subject,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
self.subscriptions[organization_id] = sub
|
|
187
|
+
|
|
188
|
+
except Exception as e:
|
|
189
|
+
logger.error(
|
|
190
|
+
"nats_org_subscribe_failed",
|
|
191
|
+
error=str(e),
|
|
192
|
+
organization_id=organization_id,
|
|
193
|
+
subject=subject,
|
|
194
|
+
)
|
|
195
|
+
raise
|
|
196
|
+
|
|
197
|
+
async def unsubscribe_organization(self, organization_id: str) -> None:
|
|
198
|
+
"""
|
|
199
|
+
Unsubscribe from organization events.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
organization_id: Organization ID to unsubscribe from
|
|
203
|
+
"""
|
|
204
|
+
if organization_id not in self.subscriptions:
|
|
205
|
+
logger.warning(
|
|
206
|
+
"nats_org_not_subscribed",
|
|
207
|
+
organization_id=organization_id,
|
|
208
|
+
)
|
|
209
|
+
return
|
|
210
|
+
|
|
211
|
+
try:
|
|
212
|
+
sub = self.subscriptions[organization_id]
|
|
213
|
+
await sub.unsubscribe()
|
|
214
|
+
del self.subscriptions[organization_id]
|
|
215
|
+
|
|
216
|
+
logger.info(
|
|
217
|
+
"nats_org_unsubscribed",
|
|
218
|
+
organization_id=organization_id,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
except Exception as e:
|
|
222
|
+
logger.error(
|
|
223
|
+
"nats_org_unsubscribe_failed",
|
|
224
|
+
error=str(e),
|
|
225
|
+
organization_id=organization_id,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
async def _process_event(self, event_data: Dict[str, Any]) -> None:
|
|
229
|
+
"""
|
|
230
|
+
Process event received from NATS.
|
|
231
|
+
|
|
232
|
+
Stores event in Redis for UI consumption (same as HTTP/WebSocket flow).
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
event_data: Event data from NATS message
|
|
236
|
+
"""
|
|
237
|
+
try:
|
|
238
|
+
# Extract event fields
|
|
239
|
+
execution_id = event_data.get("execution_id")
|
|
240
|
+
event_type = event_data.get("event_type")
|
|
241
|
+
data = event_data.get("data")
|
|
242
|
+
timestamp = event_data.get("timestamp")
|
|
243
|
+
worker_id = event_data.get("worker_id")
|
|
244
|
+
organization_id = event_data.get("organization_id")
|
|
245
|
+
|
|
246
|
+
if not all([execution_id, event_type, data]):
|
|
247
|
+
logger.warning(
|
|
248
|
+
"nats_event_missing_required_fields",
|
|
249
|
+
event_data=event_data,
|
|
250
|
+
)
|
|
251
|
+
return
|
|
252
|
+
|
|
253
|
+
# Get Redis client
|
|
254
|
+
from control_plane_api.app.lib.redis_client import get_redis_client
|
|
255
|
+
|
|
256
|
+
redis_client = get_redis_client()
|
|
257
|
+
if not redis_client:
|
|
258
|
+
logger.warning("nats_event_redis_not_available")
|
|
259
|
+
return
|
|
260
|
+
|
|
261
|
+
# Build message for Redis
|
|
262
|
+
message = {
|
|
263
|
+
"event_type": event_type,
|
|
264
|
+
"data": data,
|
|
265
|
+
"timestamp": timestamp,
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
message_json = json.dumps(message)
|
|
269
|
+
|
|
270
|
+
# Redis keys
|
|
271
|
+
list_key = f"execution:{execution_id}:events"
|
|
272
|
+
channel = f"execution:{execution_id}:stream"
|
|
273
|
+
|
|
274
|
+
# Store in Redis list for replay
|
|
275
|
+
await redis_client.lpush(list_key, message_json)
|
|
276
|
+
await redis_client.ltrim(list_key, 0, 999) # Keep last 1000
|
|
277
|
+
await redis_client.expire(list_key, 3600) # 1 hour TTL
|
|
278
|
+
|
|
279
|
+
# Publish to Redis pub/sub for real-time UI
|
|
280
|
+
await redis_client.publish(channel, message_json)
|
|
281
|
+
|
|
282
|
+
logger.debug(
|
|
283
|
+
"nats_event_processed",
|
|
284
|
+
execution_id=execution_id,
|
|
285
|
+
event_type=event_type,
|
|
286
|
+
worker_id=worker_id[:8] if worker_id else None,
|
|
287
|
+
organization_id=organization_id,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
except Exception as e:
|
|
291
|
+
logger.error(
|
|
292
|
+
"nats_event_process_failed",
|
|
293
|
+
error=str(e),
|
|
294
|
+
event_data=event_data,
|
|
295
|
+
)
|
|
296
|
+
raise
|
|
297
|
+
|
|
298
|
+
async def stop(self) -> None:
|
|
299
|
+
"""Stop NATS listener and cleanup resources."""
|
|
300
|
+
if not self._running:
|
|
301
|
+
return
|
|
302
|
+
|
|
303
|
+
self._running = False
|
|
304
|
+
|
|
305
|
+
logger.info("nats_listener_stopping")
|
|
306
|
+
|
|
307
|
+
# Unsubscribe from all organizations
|
|
308
|
+
for org_id in list(self.subscriptions.keys()):
|
|
309
|
+
try:
|
|
310
|
+
await self.unsubscribe_organization(org_id)
|
|
311
|
+
except Exception as e:
|
|
312
|
+
logger.warning(
|
|
313
|
+
"nats_org_unsubscribe_on_stop_failed",
|
|
314
|
+
error=str(e),
|
|
315
|
+
organization_id=org_id,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
# Close NATS connection
|
|
319
|
+
if self.nc:
|
|
320
|
+
try:
|
|
321
|
+
await self.nc.drain()
|
|
322
|
+
await self.nc.close()
|
|
323
|
+
except Exception as e:
|
|
324
|
+
logger.warning("nats_connection_close_error", error=str(e))
|
|
325
|
+
|
|
326
|
+
logger.info("nats_listener_stopped")
|
|
327
|
+
|
|
328
|
+
def is_running(self) -> bool:
|
|
329
|
+
"""Check if listener is running."""
|
|
330
|
+
return self._running and self.nc is not None and self.nc.is_connected
|
|
331
|
+
|
|
332
|
+
def get_subscribed_organizations(self) -> Set[str]:
|
|
333
|
+
"""Get set of currently subscribed organization IDs."""
|
|
334
|
+
return set(self.subscriptions.keys())
|
|
335
|
+
|
|
336
|
+
async def health_check(self) -> Dict[str, Any]:
|
|
337
|
+
"""
|
|
338
|
+
Check NATS listener health.
|
|
339
|
+
|
|
340
|
+
Returns:
|
|
341
|
+
Dict with health status
|
|
342
|
+
"""
|
|
343
|
+
if not self.nc:
|
|
344
|
+
return {
|
|
345
|
+
"healthy": False,
|
|
346
|
+
"error": "nats_listener_not_initialized",
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
health = {
|
|
350
|
+
"healthy": self.nc.is_connected,
|
|
351
|
+
"running": self._running,
|
|
352
|
+
"nats_url": self.nats_url,
|
|
353
|
+
"jetstream_enabled": self.jetstream_enabled,
|
|
354
|
+
"subscribed_organizations": len(self.subscriptions),
|
|
355
|
+
"organizations": list(self.subscriptions.keys()),
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if self.nc.is_connected:
|
|
359
|
+
health["connected_url"] = (
|
|
360
|
+
self.nc.connected_url.netloc
|
|
361
|
+
if self.nc.connected_url
|
|
362
|
+
else None
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
# Add stats if available
|
|
366
|
+
if hasattr(self.nc, "stats"):
|
|
367
|
+
stats = self.nc.stats
|
|
368
|
+
health["stats"] = {
|
|
369
|
+
"in_msgs": stats.get("in_msgs", 0),
|
|
370
|
+
"out_msgs": stats.get("out_msgs", 0),
|
|
371
|
+
"reconnects": stats.get("reconnects", 0),
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return health
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Shared Planning Prompt Builder
|
|
3
|
+
|
|
4
|
+
Builds the rich, detailed planning prompt used by ALL strategies (Agno, Claude Code SDK, etc.)
|
|
5
|
+
This ensures 100% identical prompts across all implementations.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
from typing import List
|
|
10
|
+
from control_plane_api.app.models.task_planning import TaskPlanRequest, AgentInfo, TeamInfo
|
|
11
|
+
from control_plane_api.app.lib.task_planning.helpers import REFINEMENT_INSTRUCTIONS
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def build_planning_prompt(
|
|
15
|
+
request: TaskPlanRequest,
|
|
16
|
+
agents_to_use: List[dict],
|
|
17
|
+
teams_to_use: List[dict],
|
|
18
|
+
pricing_context: str,
|
|
19
|
+
) -> str:
|
|
20
|
+
"""
|
|
21
|
+
Build the complete planning prompt with full context.
|
|
22
|
+
|
|
23
|
+
This is the SAME prompt used by both Agno and Claude Code SDK to ensure
|
|
24
|
+
100% identical results.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
request: Task plan request
|
|
28
|
+
agents_to_use: Prepared agents data (JSON-serializable)
|
|
29
|
+
teams_to_use: Prepared teams data (JSON-serializable)
|
|
30
|
+
pricing_context: Model pricing information
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Complete planning prompt string
|
|
34
|
+
"""
|
|
35
|
+
# Build environments context
|
|
36
|
+
environments_context = (
|
|
37
|
+
"\n".join(
|
|
38
|
+
[
|
|
39
|
+
f"- **{e.name}** (ID: `{e.id}`)\n"
|
|
40
|
+
f" - **Type**: {e.type}\n"
|
|
41
|
+
f" - **Status**: {e.status}"
|
|
42
|
+
for e in request.environments
|
|
43
|
+
]
|
|
44
|
+
)
|
|
45
|
+
if request.environments
|
|
46
|
+
else "No execution environments specified"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Build worker queues context
|
|
50
|
+
worker_queues_context = (
|
|
51
|
+
"\n".join(
|
|
52
|
+
[
|
|
53
|
+
f"- **{q.name}** (ID: `{q.id}`)\n"
|
|
54
|
+
f" - **Environment**: {q.environment_id or 'Not specified'}\n"
|
|
55
|
+
f" - **Active Workers**: {q.active_workers}\n"
|
|
56
|
+
f" - **Status**: {q.status}\n"
|
|
57
|
+
f" - **Capacity**: {'Available' if q.active_workers > 0 and q.status == 'active' else 'Limited or Inactive'}"
|
|
58
|
+
for q in request.worker_queues
|
|
59
|
+
]
|
|
60
|
+
)
|
|
61
|
+
if request.worker_queues
|
|
62
|
+
else "No worker queues specified"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# System capabilities (condensed)
|
|
66
|
+
system_capabilities = "**System**: Code execution (Python/Bash/JS), Cloud (AWS/Azure/GCP), APIs, Kubernetes, Docker, Databases, Monitoring, Security, DevOps/IaC"
|
|
67
|
+
|
|
68
|
+
# Check conversation context
|
|
69
|
+
has_conversation_history = bool(request.conversation_context and request.conversation_context.strip())
|
|
70
|
+
should_be_decisive = request.iteration > 1 or has_conversation_history
|
|
71
|
+
|
|
72
|
+
# Build the complete prompt
|
|
73
|
+
planning_prompt = f"""
|
|
74
|
+
# Task Planning Request - Iteration #{request.iteration}
|
|
75
|
+
|
|
76
|
+
## Task Description
|
|
77
|
+
{request.description}
|
|
78
|
+
|
|
79
|
+
## Priority
|
|
80
|
+
{request.priority.upper()}
|
|
81
|
+
|
|
82
|
+
{"## Previous Conversation (USE THIS CONTEXT)" if has_conversation_history else ""}
|
|
83
|
+
{request.conversation_context if has_conversation_history else ""}
|
|
84
|
+
|
|
85
|
+
{"## User Feedback for Refinement" if request.refinement_feedback else ""}
|
|
86
|
+
{request.refinement_feedback if request.refinement_feedback else ""}
|
|
87
|
+
|
|
88
|
+
{"## Previous Plan (to be refined)" if request.previous_plan else ""}
|
|
89
|
+
{json.dumps(request.previous_plan, indent=2) if request.previous_plan else ""}
|
|
90
|
+
|
|
91
|
+
{REFINEMENT_INSTRUCTIONS.format(iteration=request.iteration) if request.previous_plan and request.refinement_feedback else ""}
|
|
92
|
+
|
|
93
|
+
## Available Resources
|
|
94
|
+
|
|
95
|
+
**IMPORTANT**: Agent and team data below is provided as complete JSON with ALL details including:
|
|
96
|
+
- execution_environment (secrets, env_vars, integration_ids)
|
|
97
|
+
- skills (with full configuration)
|
|
98
|
+
- projects and environments
|
|
99
|
+
- capabilities and runtime info
|
|
100
|
+
|
|
101
|
+
Use this rich data to make informed decisions about agent/team selection and task planning.
|
|
102
|
+
|
|
103
|
+
### Agents
|
|
104
|
+
{json.dumps(agents_to_use, indent=2) if agents_to_use else "No agents available"}
|
|
105
|
+
|
|
106
|
+
### Teams
|
|
107
|
+
{json.dumps(teams_to_use, indent=2) if teams_to_use else "No teams available"}
|
|
108
|
+
|
|
109
|
+
### Execution Environments
|
|
110
|
+
{environments_context}
|
|
111
|
+
|
|
112
|
+
### Worker Queues
|
|
113
|
+
{worker_queues_context}
|
|
114
|
+
|
|
115
|
+
{system_capabilities}
|
|
116
|
+
|
|
117
|
+
{pricing_context}
|
|
118
|
+
|
|
119
|
+
## Your Task
|
|
120
|
+
|
|
121
|
+
{'**BE DECISIVE**: You have conversation history showing the user has already provided context. DO NOT ask more questions. Use the information provided in the conversation history above to create a reasonable plan. Make sensible assumptions where needed and proceed with planning.' if should_be_decisive else '**FIRST ITERATION**: Review if you have enough context. ONLY ask questions if you are missing CRITICAL information that makes planning impossible (like completely unknown technology stack or domain). If the task is reasonably clear, proceed with planning and make reasonable assumptions.'}
|
|
122
|
+
|
|
123
|
+
{'**IMPORTANT**: DO NOT ask questions. The user wants a plan now. Use the conversation history above and create a comprehensive plan.' if should_be_decisive else 'If you need CRITICAL information to proceed, set has_questions=true and provide 1-2 critical questions in the questions array. Otherwise, proceed with planning.'}
|
|
124
|
+
|
|
125
|
+
Analyze this task and provide a comprehensive plan.
|
|
126
|
+
|
|
127
|
+
**Key Planning Guidelines:**
|
|
128
|
+
|
|
129
|
+
1. **Agent/Team Selection**: Choose the most capable entity from the lists above based on:
|
|
130
|
+
- Task complexity and requirements → Agent/team capabilities
|
|
131
|
+
- Single agent sufficient? Use agent. Multi-domain? Use team.
|
|
132
|
+
- Match agent model (from model_id) to task complexity
|
|
133
|
+
|
|
134
|
+
2. **Environment & Queue**: Select environment matching task needs (prod/staging/dev). Choose worker queue with capacity (active_workers > 0, status='active'). Match queue to environment when possible.
|
|
135
|
+
|
|
136
|
+
3. **Cost Breakdown** (use pricing above):
|
|
137
|
+
- **Token estimates** by complexity: Simple (1-3 pts): 2-5K in/1-2K out. Medium (5-8): 5-10K in/2-5K out. Complex (13-21): 10-20K in/5-10K out
|
|
138
|
+
- **Model costs**: Calculate from token estimates × pricing (Sonnet 4: $0.003/1K in, $0.015/1K out)
|
|
139
|
+
- **Tool costs**: AWS APIs $0.0004-0.001/call, DB queries $0.0001/call, Free tools $0
|
|
140
|
+
- **Runtime**: Time estimate × $0.10/hr
|
|
141
|
+
- **agent_cost** per agent: model_cost + tool_costs
|
|
142
|
+
- **estimated_cost_usd**: Sum all costs
|
|
143
|
+
|
|
144
|
+
4. **Realized Savings**:
|
|
145
|
+
- **Manual**: Use realistic hourly rates (Senior: $120-200/hr, Mid: $80-120/hr, Jr: $50-80/hr) × estimated manual time
|
|
146
|
+
- **AI**: Use calculated estimated_cost_usd and time
|
|
147
|
+
- **Savings**: money_saved, time_saved_hours, time_saved_percentage
|
|
148
|
+
- **Summary**: Compelling narrative showing concrete savings
|
|
149
|
+
|
|
150
|
+
5. Use exact IDs from lists. Be specific and actionable. Output valid JSON only.
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
return planning_prompt
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Planning Tools - Modular tools for the task planning agent
|
|
3
|
+
|
|
4
|
+
This package provides decoupled, maintainable tools organized by category:
|
|
5
|
+
- agents: Agent-related context and operations
|
|
6
|
+
- teams: Team-related context and operations
|
|
7
|
+
- environments: Environment and infrastructure context
|
|
8
|
+
- resources: General resource and capability queries
|
|
9
|
+
- models: Pydantic models for type-safe data structures
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from control_plane_api.app.lib.planning_tools.agents import AgentsContextTools
|
|
13
|
+
from control_plane_api.app.lib.planning_tools.teams import TeamsContextTools
|
|
14
|
+
from control_plane_api.app.lib.planning_tools.environments import EnvironmentsContextTools
|
|
15
|
+
from control_plane_api.app.lib.planning_tools.resources import ResourcesContextTools
|
|
16
|
+
from control_plane_api.app.lib.planning_tools.knowledge import KnowledgeContextTools
|
|
17
|
+
from control_plane_api.app.lib.planning_tools.models import (
|
|
18
|
+
AgentModel,
|
|
19
|
+
TeamModel,
|
|
20
|
+
TeamMemberModel,
|
|
21
|
+
EnvironmentModel,
|
|
22
|
+
WorkerQueueModel,
|
|
23
|
+
ExecutionHistoryModel,
|
|
24
|
+
SkillModel,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"AgentsContextTools",
|
|
29
|
+
"TeamsContextTools",
|
|
30
|
+
"EnvironmentsContextTools",
|
|
31
|
+
"ResourcesContextTools",
|
|
32
|
+
"KnowledgeContextTools",
|
|
33
|
+
# Models
|
|
34
|
+
"AgentModel",
|
|
35
|
+
"TeamModel",
|
|
36
|
+
"TeamMemberModel",
|
|
37
|
+
"EnvironmentModel",
|
|
38
|
+
"WorkerQueueModel",
|
|
39
|
+
"ExecutionHistoryModel",
|
|
40
|
+
"SkillModel",
|
|
41
|
+
]
|