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,203 @@
|
|
|
1
|
+
"""Temporal credentials service with caching and fallback.
|
|
2
|
+
|
|
3
|
+
This service orchestrates fetching organization-specific Temporal credentials
|
|
4
|
+
from the Kubiya API, with Redis caching and fallback to environment variables.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from typing import Optional, Dict
|
|
9
|
+
import structlog
|
|
10
|
+
|
|
11
|
+
from control_plane_api.app.lib.kubiya_client import get_kubiya_client
|
|
12
|
+
from control_plane_api.app.lib.temporal_credentials_cache import (
|
|
13
|
+
get_cached_temporal_credentials,
|
|
14
|
+
cache_temporal_credentials,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
logger = structlog.get_logger()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def is_local_temporal() -> bool:
|
|
21
|
+
"""
|
|
22
|
+
Check if running against local Temporal server.
|
|
23
|
+
|
|
24
|
+
Detects local Temporal by checking if TEMPORAL_HOST contains
|
|
25
|
+
localhost, 127.0.0.1, or temporal: (Docker Compose service name).
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
True if local Temporal, False if Temporal Cloud
|
|
29
|
+
"""
|
|
30
|
+
temporal_host = os.getenv("TEMPORAL_HOST", "us-east-1.aws.api.temporal.io:7233")
|
|
31
|
+
return (
|
|
32
|
+
"localhost" in temporal_host or
|
|
33
|
+
"127.0.0.1" in temporal_host or
|
|
34
|
+
temporal_host.startswith("temporal:")
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
async def get_temporal_credentials_for_org(
|
|
39
|
+
org_id: str,
|
|
40
|
+
token: str,
|
|
41
|
+
use_fallback: bool = True
|
|
42
|
+
) -> Dict:
|
|
43
|
+
"""
|
|
44
|
+
Get Temporal credentials for organization with caching and fallback.
|
|
45
|
+
|
|
46
|
+
This is the main entry point for fetching Temporal credentials.
|
|
47
|
+
|
|
48
|
+
Flow:
|
|
49
|
+
1. Check if local Temporal (auto-detect from TEMPORAL_HOST)
|
|
50
|
+
- If local: Return env var credentials immediately
|
|
51
|
+
2. Check Redis cache
|
|
52
|
+
3. If not cached, call Kubiya API
|
|
53
|
+
4. Cache the result
|
|
54
|
+
5. On failure, optionally fallback to env vars (backwards compatibility)
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
org_id: Organization ID (slug or UUID)
|
|
58
|
+
token: Authentication token
|
|
59
|
+
use_fallback: If True, fallback to env vars on API failure (default: True)
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Dict with keys:
|
|
63
|
+
{
|
|
64
|
+
"namespace": "org-slug.lpagu",
|
|
65
|
+
"api_key": "...",
|
|
66
|
+
"host": "us-east-1.aws.api.temporal.io:7233",
|
|
67
|
+
"org": "org-slug",
|
|
68
|
+
"ttl": "2026-01-07T14:38:20Z"
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
Raises:
|
|
72
|
+
ValueError: If credentials cannot be obtained and fallback is disabled
|
|
73
|
+
|
|
74
|
+
Example:
|
|
75
|
+
credentials = await get_temporal_credentials_for_org(
|
|
76
|
+
org_id="kubiya-ai",
|
|
77
|
+
token=request.state.kubiya_token,
|
|
78
|
+
use_fallback=True
|
|
79
|
+
)
|
|
80
|
+
"""
|
|
81
|
+
# Check if running against local Temporal
|
|
82
|
+
if is_local_temporal():
|
|
83
|
+
logger.debug("using_local_temporal_credentials", org_id=org_id)
|
|
84
|
+
return _get_local_temporal_credentials()
|
|
85
|
+
|
|
86
|
+
# PRIORITY: Check if explicit Temporal credentials are set in environment variables
|
|
87
|
+
# This allows overriding Kubiya API with admin credentials
|
|
88
|
+
if os.getenv("TEMPORAL_API_KEY") or os.getenv("TEMPORAL_NAMESPACE"):
|
|
89
|
+
logger.info(
|
|
90
|
+
"using_explicit_env_temporal_credentials",
|
|
91
|
+
org_id=org_id,
|
|
92
|
+
namespace=os.getenv("TEMPORAL_NAMESPACE", "not_set"),
|
|
93
|
+
has_api_key=bool(os.getenv("TEMPORAL_API_KEY"))
|
|
94
|
+
)
|
|
95
|
+
return _get_fallback_credentials()
|
|
96
|
+
|
|
97
|
+
# Check cache first
|
|
98
|
+
cached_creds = await get_cached_temporal_credentials(org_id)
|
|
99
|
+
if cached_creds:
|
|
100
|
+
logger.debug("using_cached_temporal_credentials", org_id=org_id)
|
|
101
|
+
return _normalize_credentials(cached_creds)
|
|
102
|
+
|
|
103
|
+
# Fetch from Kubiya API
|
|
104
|
+
kubiya_client = get_kubiya_client()
|
|
105
|
+
api_creds = await kubiya_client.get_temporal_credentials(token)
|
|
106
|
+
|
|
107
|
+
if api_creds:
|
|
108
|
+
# Cache the credentials
|
|
109
|
+
await cache_temporal_credentials(org_id, api_creds)
|
|
110
|
+
|
|
111
|
+
logger.info(
|
|
112
|
+
"temporal_credentials_fetched_from_api",
|
|
113
|
+
org_id=org_id,
|
|
114
|
+
namespace=api_creds.get("namespace"),
|
|
115
|
+
source="kubiya_api"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
return _normalize_credentials(api_creds)
|
|
119
|
+
|
|
120
|
+
# API fetch failed
|
|
121
|
+
if use_fallback:
|
|
122
|
+
logger.warning(
|
|
123
|
+
"temporal_credentials_api_failed_using_fallback",
|
|
124
|
+
org_id=org_id,
|
|
125
|
+
fallback_enabled=use_fallback
|
|
126
|
+
)
|
|
127
|
+
return _get_fallback_credentials()
|
|
128
|
+
else:
|
|
129
|
+
raise ValueError(
|
|
130
|
+
f"Failed to fetch Temporal credentials for org {org_id} "
|
|
131
|
+
"and fallback is disabled"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _normalize_credentials(api_response: Dict) -> Dict:
|
|
136
|
+
"""
|
|
137
|
+
Normalize API response to standard format.
|
|
138
|
+
|
|
139
|
+
Converts the Kubiya API response format to the internal format
|
|
140
|
+
used by the control plane.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
api_response: Response from Kubiya API with keys like 'apiKey', 'namespace'
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
Normalized credentials dict with keys like 'api_key', 'namespace'
|
|
147
|
+
"""
|
|
148
|
+
# Get host from env or use default
|
|
149
|
+
host = os.getenv("TEMPORAL_HOST", "us-east-1.aws.api.temporal.io:7233")
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
"namespace": api_response.get("namespace"),
|
|
153
|
+
"api_key": api_response.get("apiKey"),
|
|
154
|
+
"host": host,
|
|
155
|
+
"org": api_response.get("org"),
|
|
156
|
+
"ttl": api_response.get("ttl"),
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _get_local_temporal_credentials() -> Dict:
|
|
161
|
+
"""
|
|
162
|
+
Get local Temporal credentials from environment variables.
|
|
163
|
+
|
|
164
|
+
Used when running against a local Temporal server (development).
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Credentials dict with env var values
|
|
168
|
+
"""
|
|
169
|
+
logger.info("using_local_temporal_credentials", source="env_vars")
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
"namespace": os.getenv("TEMPORAL_NAMESPACE", "default").strip(),
|
|
173
|
+
"api_key": "", # No API key for local Temporal
|
|
174
|
+
"host": os.getenv("TEMPORAL_HOST", "localhost:7233").strip(),
|
|
175
|
+
"org": "local",
|
|
176
|
+
"ttl": None,
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _get_fallback_credentials() -> Dict:
|
|
181
|
+
"""
|
|
182
|
+
Get fallback credentials from environment variables.
|
|
183
|
+
|
|
184
|
+
Used for backwards compatibility during migration when the
|
|
185
|
+
Kubiya API is unavailable.
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
Credentials dict with env var values
|
|
189
|
+
"""
|
|
190
|
+
logger.warning("using_fallback_temporal_credentials", source="env_vars")
|
|
191
|
+
|
|
192
|
+
# Strip whitespace/newlines from env vars to handle malformed .env files
|
|
193
|
+
namespace = os.getenv("TEMPORAL_NAMESPACE", "agent-control-plane.lpagu").strip()
|
|
194
|
+
api_key = (os.getenv("TEMPORAL_API_KEY") or os.getenv("TEMPORAL_CLOUD_ADMIN_TOKEN", "")).strip()
|
|
195
|
+
host = os.getenv("TEMPORAL_HOST", "us-east-1.aws.api.temporal.io:7233").strip()
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
"namespace": namespace,
|
|
199
|
+
"api_key": api_key,
|
|
200
|
+
"host": host,
|
|
201
|
+
"org": "fallback",
|
|
202
|
+
"ttl": None,
|
|
203
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Shared validation module for runtime and model validation.
|
|
3
|
+
|
|
4
|
+
This module is shared between the API and worker to avoid circular dependencies.
|
|
5
|
+
It provides validation logic without depending on worker-specific types.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .runtime_validation import (
|
|
9
|
+
validate_agent_for_runtime,
|
|
10
|
+
validate_agent_for_runtime_with_litellm,
|
|
11
|
+
validate_model_against_litellm,
|
|
12
|
+
get_runtime_requirements_info,
|
|
13
|
+
list_all_runtime_requirements,
|
|
14
|
+
RUNTIME_REQUIREMENTS,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"validate_agent_for_runtime",
|
|
19
|
+
"validate_agent_for_runtime_with_litellm",
|
|
20
|
+
"validate_model_against_litellm",
|
|
21
|
+
"get_runtime_requirements_info",
|
|
22
|
+
"list_all_runtime_requirements",
|
|
23
|
+
"RUNTIME_REQUIREMENTS",
|
|
24
|
+
]
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Runtime validation logic shared between API and worker.
|
|
3
|
+
|
|
4
|
+
This module provides validation without depending on worker-specific types,
|
|
5
|
+
making it safe to import from both the API layer and worker layer.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import List, Optional, Dict, Any, Set
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
import re
|
|
11
|
+
import structlog
|
|
12
|
+
|
|
13
|
+
logger = structlog.get_logger()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class ModelRequirement:
|
|
18
|
+
"""Model requirement specification for a runtime."""
|
|
19
|
+
|
|
20
|
+
# Patterns that model IDs must match (any match is valid)
|
|
21
|
+
model_id_patterns: List[str]
|
|
22
|
+
|
|
23
|
+
# Model providers that are supported (e.g., "anthropic", "openai")
|
|
24
|
+
supported_providers: Set[str]
|
|
25
|
+
|
|
26
|
+
# Specific model families supported (e.g., "claude", "gpt")
|
|
27
|
+
supported_families: Set[str]
|
|
28
|
+
|
|
29
|
+
# Human-readable description
|
|
30
|
+
description: str = ""
|
|
31
|
+
|
|
32
|
+
# Examples of valid model IDs
|
|
33
|
+
examples: List[str] = None
|
|
34
|
+
|
|
35
|
+
def __post_init__(self):
|
|
36
|
+
if self.examples is None:
|
|
37
|
+
self.examples = []
|
|
38
|
+
|
|
39
|
+
def validate(self, model_id: Optional[str]) -> tuple[bool, Optional[str]]:
|
|
40
|
+
"""
|
|
41
|
+
Validate a model ID against this requirement.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
model_id: Model ID to validate
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Tuple of (is_valid, error_message)
|
|
48
|
+
"""
|
|
49
|
+
if not model_id:
|
|
50
|
+
return False, "Model ID is required for this runtime"
|
|
51
|
+
|
|
52
|
+
# Check pattern matching
|
|
53
|
+
for pattern in self.model_id_patterns:
|
|
54
|
+
if re.search(pattern, model_id, re.IGNORECASE):
|
|
55
|
+
return True, None
|
|
56
|
+
|
|
57
|
+
# Check provider/family
|
|
58
|
+
model_lower = model_id.lower()
|
|
59
|
+
|
|
60
|
+
# Check if any supported family is in the model ID
|
|
61
|
+
for family in self.supported_families:
|
|
62
|
+
if family.lower() in model_lower:
|
|
63
|
+
return True, None
|
|
64
|
+
|
|
65
|
+
# Provide helpful error message
|
|
66
|
+
examples_str = ", ".join(self.examples) if self.examples else "N/A"
|
|
67
|
+
return False, (
|
|
68
|
+
f"Model '{model_id}' is not compatible with this runtime. "
|
|
69
|
+
f"Expected models matching: {', '.join(self.model_id_patterns)}. "
|
|
70
|
+
f"Supported families: {', '.join(self.supported_families)}. "
|
|
71
|
+
f"Examples: {examples_str}"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass
|
|
76
|
+
class RuntimeRequirements:
|
|
77
|
+
"""Requirements specification for a runtime."""
|
|
78
|
+
|
|
79
|
+
runtime_type: str
|
|
80
|
+
|
|
81
|
+
# Model requirements
|
|
82
|
+
model_requirement: ModelRequirement
|
|
83
|
+
|
|
84
|
+
# Required fields in agent/team config
|
|
85
|
+
required_config_fields: List[str] = None
|
|
86
|
+
|
|
87
|
+
# Optional but recommended fields
|
|
88
|
+
recommended_config_fields: List[str] = None
|
|
89
|
+
|
|
90
|
+
# Maximum conversation history length
|
|
91
|
+
max_history_length: Optional[int] = None
|
|
92
|
+
|
|
93
|
+
# Whether system prompt is required
|
|
94
|
+
requires_system_prompt: bool = False
|
|
95
|
+
|
|
96
|
+
# Whether tools/skills are required
|
|
97
|
+
requires_tools: bool = False
|
|
98
|
+
|
|
99
|
+
def __post_init__(self):
|
|
100
|
+
if self.required_config_fields is None:
|
|
101
|
+
self.required_config_fields = []
|
|
102
|
+
if self.recommended_config_fields is None:
|
|
103
|
+
self.recommended_config_fields = []
|
|
104
|
+
|
|
105
|
+
def validate_model(self, model_id: Optional[str]) -> tuple[bool, Optional[str]]:
|
|
106
|
+
"""Validate model compatibility."""
|
|
107
|
+
return self.model_requirement.validate(model_id)
|
|
108
|
+
|
|
109
|
+
def validate_config(self, config: Optional[Dict[str, Any]]) -> List[str]:
|
|
110
|
+
"""
|
|
111
|
+
Validate agent/team configuration.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
List of validation errors (empty if valid)
|
|
115
|
+
"""
|
|
116
|
+
errors = []
|
|
117
|
+
|
|
118
|
+
if not config:
|
|
119
|
+
if self.required_config_fields:
|
|
120
|
+
errors.append(
|
|
121
|
+
f"Configuration is required for this runtime. "
|
|
122
|
+
f"Required fields: {', '.join(self.required_config_fields)}"
|
|
123
|
+
)
|
|
124
|
+
return errors
|
|
125
|
+
|
|
126
|
+
# Check required fields
|
|
127
|
+
for field in self.required_config_fields:
|
|
128
|
+
if field not in config or config[field] is None:
|
|
129
|
+
errors.append(f"Required field '{field}' is missing in configuration")
|
|
130
|
+
|
|
131
|
+
return errors
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# ==================== Runtime Requirements Definitions ====================
|
|
135
|
+
|
|
136
|
+
# Agno/Default Runtime - Flexible, supports most models
|
|
137
|
+
DEFAULT_RUNTIME_REQUIREMENTS = RuntimeRequirements(
|
|
138
|
+
runtime_type="default",
|
|
139
|
+
model_requirement=ModelRequirement(
|
|
140
|
+
model_id_patterns=[
|
|
141
|
+
r".*", # Accept all models
|
|
142
|
+
],
|
|
143
|
+
supported_providers={"openai", "anthropic", "azure", "google", "mistral", "cohere"},
|
|
144
|
+
supported_families={"gpt", "claude", "gemini", "mistral", "command"},
|
|
145
|
+
description="Default runtime supports most LiteLLM-compatible models",
|
|
146
|
+
examples=[
|
|
147
|
+
"gpt-4",
|
|
148
|
+
"gpt-4-turbo",
|
|
149
|
+
"gpt-3.5-turbo",
|
|
150
|
+
"claude-3-opus",
|
|
151
|
+
"claude-3-sonnet",
|
|
152
|
+
"claude-sonnet-4",
|
|
153
|
+
"gemini-pro",
|
|
154
|
+
"mistral-large",
|
|
155
|
+
],
|
|
156
|
+
),
|
|
157
|
+
max_history_length=100, # Reasonable default
|
|
158
|
+
requires_system_prompt=False,
|
|
159
|
+
requires_tools=False,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# Claude Code Runtime - Requires Claude models
|
|
163
|
+
CLAUDE_CODE_RUNTIME_REQUIREMENTS = RuntimeRequirements(
|
|
164
|
+
runtime_type="claude_code",
|
|
165
|
+
model_requirement=ModelRequirement(
|
|
166
|
+
model_id_patterns=[
|
|
167
|
+
r"claude", # Must contain "claude"
|
|
168
|
+
r"kubiya/claude", # LiteLLM proxy format
|
|
169
|
+
r"anthropic\.claude", # Alternative format
|
|
170
|
+
],
|
|
171
|
+
supported_providers={"anthropic"},
|
|
172
|
+
supported_families={"claude"},
|
|
173
|
+
description=(
|
|
174
|
+
"Claude Code runtime requires Anthropic Claude models. "
|
|
175
|
+
"This runtime leverages Claude's advanced capabilities including "
|
|
176
|
+
"extended context, tool use, and code understanding."
|
|
177
|
+
),
|
|
178
|
+
examples=[
|
|
179
|
+
"claude-3-opus-20240229",
|
|
180
|
+
"claude-3-sonnet-20240229",
|
|
181
|
+
"claude-3-5-sonnet-20241022",
|
|
182
|
+
"claude-3-haiku-20240307",
|
|
183
|
+
"claude-sonnet-4",
|
|
184
|
+
"claude-opus-4",
|
|
185
|
+
"kubiya/claude-sonnet-4",
|
|
186
|
+
"kubiya/claude-opus-4",
|
|
187
|
+
],
|
|
188
|
+
),
|
|
189
|
+
max_history_length=200, # Claude handles longer contexts well
|
|
190
|
+
requires_system_prompt=False, # Optional but recommended
|
|
191
|
+
requires_tools=False, # Claude Code adds tools automatically
|
|
192
|
+
recommended_config_fields=["timeout", "max_tokens"],
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
# Registry of runtime requirements
|
|
197
|
+
RUNTIME_REQUIREMENTS: Dict[str, RuntimeRequirements] = {
|
|
198
|
+
"default": DEFAULT_RUNTIME_REQUIREMENTS,
|
|
199
|
+
"claude_code": CLAUDE_CODE_RUNTIME_REQUIREMENTS,
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# ==================== Validation Functions ====================
|
|
204
|
+
|
|
205
|
+
def validate_agent_for_runtime(
|
|
206
|
+
runtime_type: str,
|
|
207
|
+
model_id: Optional[str],
|
|
208
|
+
agent_config: Optional[Dict[str, Any]] = None,
|
|
209
|
+
system_prompt: Optional[str] = None,
|
|
210
|
+
) -> tuple[bool, List[str]]:
|
|
211
|
+
"""
|
|
212
|
+
Validate agent configuration for a runtime.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
runtime_type: Runtime type string (e.g., "default", "claude_code")
|
|
216
|
+
model_id: Model ID to validate
|
|
217
|
+
agent_config: Agent configuration dict
|
|
218
|
+
system_prompt: System prompt
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
Tuple of (is_valid, error_messages)
|
|
222
|
+
"""
|
|
223
|
+
requirements = RUNTIME_REQUIREMENTS.get(runtime_type)
|
|
224
|
+
if not requirements:
|
|
225
|
+
# No requirements registered - allow by default
|
|
226
|
+
return True, []
|
|
227
|
+
|
|
228
|
+
errors = []
|
|
229
|
+
|
|
230
|
+
# Validate model
|
|
231
|
+
is_valid, error = requirements.validate_model(model_id)
|
|
232
|
+
if not is_valid:
|
|
233
|
+
errors.append(error)
|
|
234
|
+
|
|
235
|
+
# Validate config
|
|
236
|
+
config_errors = requirements.validate_config(agent_config)
|
|
237
|
+
errors.extend(config_errors)
|
|
238
|
+
|
|
239
|
+
# Validate system prompt if required
|
|
240
|
+
if requirements.requires_system_prompt and not system_prompt:
|
|
241
|
+
errors.append("System prompt is required for this runtime")
|
|
242
|
+
|
|
243
|
+
return len(errors) == 0, errors
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def get_runtime_requirements_info(runtime_type: str) -> Dict[str, Any]:
|
|
247
|
+
"""
|
|
248
|
+
Get human-readable requirements info for a runtime.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
runtime_type: Runtime type string
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
Dict with requirements information
|
|
255
|
+
"""
|
|
256
|
+
requirements = RUNTIME_REQUIREMENTS.get(runtime_type)
|
|
257
|
+
if not requirements:
|
|
258
|
+
return {
|
|
259
|
+
"runtime_type": runtime_type,
|
|
260
|
+
"model_requirement": "No specific requirements",
|
|
261
|
+
"flexible": True,
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
"runtime_type": runtime_type,
|
|
266
|
+
"model_requirement": {
|
|
267
|
+
"description": requirements.model_requirement.description,
|
|
268
|
+
"supported_providers": list(requirements.model_requirement.supported_providers),
|
|
269
|
+
"supported_families": list(requirements.model_requirement.supported_families),
|
|
270
|
+
"examples": requirements.model_requirement.examples,
|
|
271
|
+
},
|
|
272
|
+
"required_config_fields": requirements.required_config_fields,
|
|
273
|
+
"recommended_config_fields": requirements.recommended_config_fields,
|
|
274
|
+
"max_history_length": requirements.max_history_length,
|
|
275
|
+
"requires_system_prompt": requirements.requires_system_prompt,
|
|
276
|
+
"requires_tools": requirements.requires_tools,
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def list_all_runtime_requirements() -> Dict[str, Dict[str, Any]]:
|
|
281
|
+
"""
|
|
282
|
+
Get requirements for all registered runtimes.
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
Dict mapping runtime type to requirements info
|
|
286
|
+
"""
|
|
287
|
+
return {
|
|
288
|
+
runtime_type: get_runtime_requirements_info(runtime_type)
|
|
289
|
+
for runtime_type in RUNTIME_REQUIREMENTS.keys()
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
async def validate_model_against_litellm(model_id: str) -> tuple[bool, Optional[str]]:
|
|
294
|
+
"""
|
|
295
|
+
Validate a model ID against the LiteLLM server.
|
|
296
|
+
|
|
297
|
+
This function dynamically checks if the model is available in the LiteLLM server.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
model_id: Model ID to validate
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
Tuple of (is_valid, error_message)
|
|
304
|
+
"""
|
|
305
|
+
try:
|
|
306
|
+
# Import here to avoid circular dependencies
|
|
307
|
+
from control_plane_api.app.services.litellm_service import litellm_service
|
|
308
|
+
|
|
309
|
+
# Fetch available models from LiteLLM server
|
|
310
|
+
available_models = await litellm_service.fetch_available_models()
|
|
311
|
+
|
|
312
|
+
# Extract model IDs from the response
|
|
313
|
+
available_model_ids = [model.get("id") for model in available_models if model.get("id")]
|
|
314
|
+
|
|
315
|
+
# Check if the model_id is in the available models
|
|
316
|
+
if model_id in available_model_ids:
|
|
317
|
+
return True, None
|
|
318
|
+
|
|
319
|
+
# Check if any model ID contains the requested model (for prefix matching)
|
|
320
|
+
# e.g., "claude-sonnet-4" might match "kubiya/claude-sonnet-4"
|
|
321
|
+
for available_id in available_model_ids:
|
|
322
|
+
if model_id in available_id or available_id in model_id:
|
|
323
|
+
logger.info(
|
|
324
|
+
"model_validation_fuzzy_match",
|
|
325
|
+
requested=model_id,
|
|
326
|
+
matched=available_id
|
|
327
|
+
)
|
|
328
|
+
return True, None
|
|
329
|
+
|
|
330
|
+
return False, (
|
|
331
|
+
f"Model '{model_id}' is not available in the LiteLLM server. "
|
|
332
|
+
f"Available models: {', '.join(available_model_ids[:10])}"
|
|
333
|
+
+ ("..." if len(available_model_ids) > 10 else "")
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
except Exception as e:
|
|
337
|
+
logger.warning(
|
|
338
|
+
"litellm_validation_failed",
|
|
339
|
+
model_id=model_id,
|
|
340
|
+
error=str(e),
|
|
341
|
+
msg="Falling back to pattern-based validation"
|
|
342
|
+
)
|
|
343
|
+
# If LiteLLM validation fails, fall back to pattern-based validation
|
|
344
|
+
# Accept any model with provider/model format
|
|
345
|
+
if "/" in model_id:
|
|
346
|
+
return True, None
|
|
347
|
+
return False, f"Model '{model_id}' has invalid format (expected 'provider/model')"
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
async def validate_agent_for_runtime_with_litellm(
|
|
351
|
+
runtime_type: str,
|
|
352
|
+
model_id: Optional[str],
|
|
353
|
+
agent_config: Optional[Dict[str, Any]] = None,
|
|
354
|
+
system_prompt: Optional[str] = None,
|
|
355
|
+
check_litellm: bool = True,
|
|
356
|
+
) -> tuple[bool, List[str]]:
|
|
357
|
+
"""
|
|
358
|
+
Enhanced validation that checks both runtime requirements and LiteLLM availability.
|
|
359
|
+
|
|
360
|
+
Args:
|
|
361
|
+
runtime_type: Runtime type string (e.g., "default", "claude_code")
|
|
362
|
+
model_id: Model ID to validate
|
|
363
|
+
agent_config: Agent configuration dict
|
|
364
|
+
system_prompt: System prompt
|
|
365
|
+
check_litellm: Whether to check model availability in LiteLLM server
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
Tuple of (is_valid, error_messages)
|
|
369
|
+
"""
|
|
370
|
+
# First, run standard runtime validation
|
|
371
|
+
is_valid, errors = validate_agent_for_runtime(
|
|
372
|
+
runtime_type=runtime_type,
|
|
373
|
+
model_id=model_id,
|
|
374
|
+
agent_config=agent_config,
|
|
375
|
+
system_prompt=system_prompt
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
# If basic validation failed, return immediately
|
|
379
|
+
if not is_valid:
|
|
380
|
+
return is_valid, errors
|
|
381
|
+
|
|
382
|
+
# Optionally check against LiteLLM server
|
|
383
|
+
if check_litellm and model_id:
|
|
384
|
+
litellm_valid, litellm_error = await validate_model_against_litellm(model_id)
|
|
385
|
+
if not litellm_valid and litellm_error:
|
|
386
|
+
errors.append(litellm_error)
|
|
387
|
+
|
|
388
|
+
return len(errors) == 0, errors
|