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,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Template engine package for variable substitution in MCP configurations.
|
|
3
|
+
|
|
4
|
+
This package provides a flexible, extensible template engine that supports
|
|
5
|
+
multiple template syntaxes through a plugin-based parser system.
|
|
6
|
+
|
|
7
|
+
Supported template syntaxes:
|
|
8
|
+
- {{variable}} - Simple variable substitution
|
|
9
|
+
- {{.secret.name}} - Secret from vault
|
|
10
|
+
- {{.env.VAR}} - Environment variable
|
|
11
|
+
|
|
12
|
+
Example usage:
|
|
13
|
+
from control_plane_api.app.lib.templating import TemplateEngine, TemplateContext, TemplateCompiler
|
|
14
|
+
|
|
15
|
+
# Parse and compile a template
|
|
16
|
+
engine = TemplateEngine()
|
|
17
|
+
context = TemplateContext(
|
|
18
|
+
secrets={"api_key": "secret-value"},
|
|
19
|
+
env_vars={"PORT": "8080"}
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
compiler = TemplateCompiler(engine)
|
|
23
|
+
result = compiler.compile("http://api.example.com:{{.env.PORT}}/{{.secret.api_key}}", context)
|
|
24
|
+
print(result.compiled) # "http://api.example.com:8080/secret-value"
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
# Core types
|
|
28
|
+
from control_plane_api.app.lib.templating.types import (
|
|
29
|
+
TemplateVariableType,
|
|
30
|
+
TemplateVariable,
|
|
31
|
+
ValidationError,
|
|
32
|
+
ParseResult,
|
|
33
|
+
TemplateContext,
|
|
34
|
+
ValidationResult,
|
|
35
|
+
CompileResult,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Main engine components
|
|
39
|
+
from control_plane_api.app.lib.templating.engine import TemplateEngine, get_default_engine
|
|
40
|
+
from control_plane_api.app.lib.templating.validator import TemplateValidator
|
|
41
|
+
from control_plane_api.app.lib.templating.compiler import TemplateCompiler
|
|
42
|
+
from control_plane_api.app.lib.templating.resolver import (
|
|
43
|
+
TemplateResolver,
|
|
44
|
+
TemplateResolutionError,
|
|
45
|
+
resolve_templates,
|
|
46
|
+
has_templates,
|
|
47
|
+
extract_all_variables,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Parser infrastructure (for advanced usage)
|
|
51
|
+
from control_plane_api.app.lib.templating.parsers import (
|
|
52
|
+
BaseParser,
|
|
53
|
+
SimpleVariableParser,
|
|
54
|
+
SecretVariableParser,
|
|
55
|
+
EnvVariableParser,
|
|
56
|
+
DEFAULT_PARSERS,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
__all__ = [
|
|
60
|
+
# Types
|
|
61
|
+
"TemplateVariableType",
|
|
62
|
+
"TemplateVariable",
|
|
63
|
+
"ValidationError",
|
|
64
|
+
"ParseResult",
|
|
65
|
+
"TemplateContext",
|
|
66
|
+
"ValidationResult",
|
|
67
|
+
"CompileResult",
|
|
68
|
+
# Main components
|
|
69
|
+
"TemplateEngine",
|
|
70
|
+
"get_default_engine",
|
|
71
|
+
"TemplateValidator",
|
|
72
|
+
"TemplateCompiler",
|
|
73
|
+
"TemplateResolver",
|
|
74
|
+
"TemplateResolutionError",
|
|
75
|
+
# Convenience functions
|
|
76
|
+
"resolve_templates",
|
|
77
|
+
"has_templates",
|
|
78
|
+
"extract_all_variables",
|
|
79
|
+
# Parsers (advanced)
|
|
80
|
+
"BaseParser",
|
|
81
|
+
"SimpleVariableParser",
|
|
82
|
+
"SecretVariableParser",
|
|
83
|
+
"EnvVariableParser",
|
|
84
|
+
"DEFAULT_PARSERS",
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
# Version
|
|
88
|
+
__version__ = "1.0.0"
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Template compilation logic.
|
|
3
|
+
|
|
4
|
+
Compiles templates by substituting variables with their values from a context.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import os
|
|
9
|
+
import structlog
|
|
10
|
+
import httpx
|
|
11
|
+
from typing import Any, Dict, Optional
|
|
12
|
+
from control_plane_api.app.lib.templating.types import (
|
|
13
|
+
TemplateContext,
|
|
14
|
+
TemplateVariableType,
|
|
15
|
+
CompileResult,
|
|
16
|
+
)
|
|
17
|
+
from control_plane_api.app.lib.templating.engine import TemplateEngine, get_default_engine
|
|
18
|
+
from control_plane_api.app.lib.templating.validator import TemplateValidator
|
|
19
|
+
|
|
20
|
+
logger = structlog.get_logger()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TemplateCompiler:
|
|
24
|
+
"""
|
|
25
|
+
Compiles templates by substituting variables with values from a context.
|
|
26
|
+
|
|
27
|
+
The compiler:
|
|
28
|
+
1. Validates the template
|
|
29
|
+
2. Substitutes variables with their values
|
|
30
|
+
3. Returns the compiled string
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, engine: TemplateEngine = None):
|
|
34
|
+
"""
|
|
35
|
+
Initialize the compiler with a template engine.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
engine: Template engine to use. If None, uses default engine.
|
|
39
|
+
"""
|
|
40
|
+
self.engine = engine if engine is not None else get_default_engine()
|
|
41
|
+
self.validator = TemplateValidator(self.engine)
|
|
42
|
+
|
|
43
|
+
def compile(self, template: str, context: TemplateContext) -> CompileResult:
|
|
44
|
+
"""
|
|
45
|
+
Compile a template by substituting all variables with their values.
|
|
46
|
+
|
|
47
|
+
Process:
|
|
48
|
+
1. Parse the template to extract variables
|
|
49
|
+
2. Validate that all variables exist in context
|
|
50
|
+
3. Substitute variables with their values (in reverse order to preserve positions)
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
template: Template string to compile
|
|
54
|
+
context: Template context with variable values
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
CompileResult with compiled string or error
|
|
58
|
+
"""
|
|
59
|
+
try:
|
|
60
|
+
# Parse the template
|
|
61
|
+
parse_result = self.engine.parse(template)
|
|
62
|
+
|
|
63
|
+
# Check for syntax errors
|
|
64
|
+
if not parse_result.is_valid:
|
|
65
|
+
error_messages = [err.message for err in parse_result.errors]
|
|
66
|
+
error_str = "; ".join(error_messages)
|
|
67
|
+
logger.warning("template_syntax_errors", errors=error_messages)
|
|
68
|
+
return CompileResult(
|
|
69
|
+
compiled="",
|
|
70
|
+
success=False,
|
|
71
|
+
error=f"Template syntax errors: {error_str}"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Validate against context
|
|
75
|
+
validation_result = self.validator.validate(template, context)
|
|
76
|
+
if not validation_result.valid:
|
|
77
|
+
error_messages = [err.message for err in validation_result.errors]
|
|
78
|
+
error_str = "; ".join(error_messages)
|
|
79
|
+
logger.warning("template_validation_errors", errors=error_messages)
|
|
80
|
+
return CompileResult(
|
|
81
|
+
compiled="",
|
|
82
|
+
success=False,
|
|
83
|
+
error=f"Template validation errors: {error_str}"
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Substitute variables (process in reverse order to preserve positions)
|
|
87
|
+
result = template
|
|
88
|
+
for var in sorted(parse_result.variables, key=lambda v: v.start, reverse=True):
|
|
89
|
+
try:
|
|
90
|
+
# Get the value based on variable type
|
|
91
|
+
value = self._get_variable_value(var.type, var, context)
|
|
92
|
+
|
|
93
|
+
# Convert to string
|
|
94
|
+
value_str = str(value) if value is not None else ""
|
|
95
|
+
|
|
96
|
+
# Substitute
|
|
97
|
+
result = result[:var.start] + value_str + result[var.end:]
|
|
98
|
+
|
|
99
|
+
logger.debug(
|
|
100
|
+
"variable_substituted",
|
|
101
|
+
variable_name=var.name,
|
|
102
|
+
variable_type=var.type.value,
|
|
103
|
+
has_value=bool(value),
|
|
104
|
+
value_length=len(value_str)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
except KeyError as e:
|
|
108
|
+
# This shouldn't happen if validation passed, but handle it gracefully
|
|
109
|
+
logger.error(
|
|
110
|
+
"variable_not_found_during_compilation",
|
|
111
|
+
variable_name=var.name,
|
|
112
|
+
error=str(e)
|
|
113
|
+
)
|
|
114
|
+
# Preserve the original error message (especially for graph node API errors)
|
|
115
|
+
error_msg = str(e) if str(e) else f"Variable '{var.name}' not found in context"
|
|
116
|
+
return CompileResult(
|
|
117
|
+
compiled="",
|
|
118
|
+
success=False,
|
|
119
|
+
error=error_msg
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
logger.info(
|
|
123
|
+
"template_compiled_successfully",
|
|
124
|
+
original_length=len(template),
|
|
125
|
+
compiled_length=len(result),
|
|
126
|
+
variable_count=len(parse_result.variables)
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
return CompileResult(
|
|
130
|
+
compiled=result,
|
|
131
|
+
success=True
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
except Exception as e:
|
|
135
|
+
logger.error("template_compilation_failed", error=str(e), exc_info=True)
|
|
136
|
+
return CompileResult(
|
|
137
|
+
compiled="",
|
|
138
|
+
success=False,
|
|
139
|
+
error=f"Compilation failed: {str(e)}"
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
def _get_variable_value(
|
|
143
|
+
self,
|
|
144
|
+
var_type: TemplateVariableType,
|
|
145
|
+
var,
|
|
146
|
+
context: TemplateContext
|
|
147
|
+
) -> Any:
|
|
148
|
+
"""
|
|
149
|
+
Get the value for a variable from the context.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
var_type: Type of variable
|
|
153
|
+
var: TemplateVariable object
|
|
154
|
+
context: Template context
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
Variable value
|
|
158
|
+
|
|
159
|
+
Raises:
|
|
160
|
+
KeyError: If variable not found in context
|
|
161
|
+
"""
|
|
162
|
+
if var_type == TemplateVariableType.SECRET:
|
|
163
|
+
return context.secrets[var.display_name]
|
|
164
|
+
elif var_type == TemplateVariableType.ENV:
|
|
165
|
+
return context.env_vars[var.display_name]
|
|
166
|
+
elif var_type == TemplateVariableType.GRAPH:
|
|
167
|
+
return self._get_graph_node_value(var.display_name, context)
|
|
168
|
+
else: # SIMPLE
|
|
169
|
+
return context.variables[var.name]
|
|
170
|
+
|
|
171
|
+
def _get_graph_node_value(
|
|
172
|
+
self,
|
|
173
|
+
node_id: str,
|
|
174
|
+
context: TemplateContext
|
|
175
|
+
) -> str:
|
|
176
|
+
"""
|
|
177
|
+
Get graph node data from context or fetch from API.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
node_id: The node ID to fetch
|
|
181
|
+
context: Template context with graph configuration
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
Formatted node data as JSON string
|
|
185
|
+
|
|
186
|
+
Raises:
|
|
187
|
+
KeyError: If node not found or API configuration missing
|
|
188
|
+
"""
|
|
189
|
+
# Check if node is already in context
|
|
190
|
+
if context.graph_nodes and node_id in context.graph_nodes:
|
|
191
|
+
node_data = context.graph_nodes[node_id]
|
|
192
|
+
return json.dumps(node_data, indent=2)
|
|
193
|
+
|
|
194
|
+
# Need to fetch from API - validate configuration
|
|
195
|
+
if not context.graph_api_base:
|
|
196
|
+
raise KeyError(
|
|
197
|
+
f"Context graph API base URL not configured for node '{node_id}'"
|
|
198
|
+
)
|
|
199
|
+
if not context.graph_api_key:
|
|
200
|
+
raise KeyError(
|
|
201
|
+
f"Context graph API key not configured for node '{node_id}'"
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Fetch node from API
|
|
205
|
+
try:
|
|
206
|
+
node_data = self._fetch_graph_node(
|
|
207
|
+
node_id=node_id,
|
|
208
|
+
api_base=context.graph_api_base,
|
|
209
|
+
api_key=context.graph_api_key,
|
|
210
|
+
org_id=context.graph_org_id
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
# Cache in context for subsequent requests
|
|
214
|
+
if context.graph_nodes is None:
|
|
215
|
+
context.graph_nodes = {}
|
|
216
|
+
context.graph_nodes[node_id] = node_data
|
|
217
|
+
|
|
218
|
+
return json.dumps(node_data, indent=2)
|
|
219
|
+
|
|
220
|
+
except httpx.HTTPStatusError as e:
|
|
221
|
+
if e.response.status_code == 404:
|
|
222
|
+
raise KeyError(f"Graph node '{node_id}' not found")
|
|
223
|
+
else:
|
|
224
|
+
raise KeyError(
|
|
225
|
+
f"Failed to fetch graph node '{node_id}': "
|
|
226
|
+
f"HTTP {e.response.status_code}"
|
|
227
|
+
)
|
|
228
|
+
except Exception as e:
|
|
229
|
+
raise KeyError(f"Failed to fetch graph node '{node_id}': {str(e)}")
|
|
230
|
+
|
|
231
|
+
def _fetch_graph_node(
|
|
232
|
+
self,
|
|
233
|
+
node_id: str,
|
|
234
|
+
api_base: str,
|
|
235
|
+
api_key: str,
|
|
236
|
+
org_id: Optional[str] = None,
|
|
237
|
+
timeout: int = 30
|
|
238
|
+
) -> Dict[str, Any]:
|
|
239
|
+
"""
|
|
240
|
+
Fetch a node from the context graph API.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
node_id: The node ID to fetch
|
|
244
|
+
api_base: Context graph API base URL
|
|
245
|
+
api_key: API key for authentication
|
|
246
|
+
org_id: Optional organization ID
|
|
247
|
+
timeout: Request timeout in seconds
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
Node data dictionary
|
|
251
|
+
|
|
252
|
+
Raises:
|
|
253
|
+
httpx.HTTPStatusError: If request fails (including 404)
|
|
254
|
+
Exception: If request fails for other reasons
|
|
255
|
+
"""
|
|
256
|
+
url = f"{api_base.rstrip('/')}/api/v1/graph/nodes/{node_id}"
|
|
257
|
+
|
|
258
|
+
headers = {
|
|
259
|
+
"Authorization": f"UserKey {api_key}",
|
|
260
|
+
"Accept": "application/json",
|
|
261
|
+
"Content-Type": "application/json",
|
|
262
|
+
"X-Kubiya-Client": "agent-runtime-template-compiler",
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if org_id:
|
|
266
|
+
headers["X-Organization-ID"] = org_id
|
|
267
|
+
|
|
268
|
+
logger.debug(
|
|
269
|
+
"fetching_graph_node",
|
|
270
|
+
node_id=node_id,
|
|
271
|
+
api_base=api_base,
|
|
272
|
+
has_org_id=bool(org_id)
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
with httpx.Client(timeout=timeout) as client:
|
|
276
|
+
response = client.get(url, headers=headers)
|
|
277
|
+
response.raise_for_status()
|
|
278
|
+
return response.json()
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Main template engine orchestrator.
|
|
3
|
+
|
|
4
|
+
Coordinates multiple parsers to extract, validate, and compile templates.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import structlog
|
|
8
|
+
from typing import List, Set
|
|
9
|
+
from control_plane_api.app.lib.templating.types import (
|
|
10
|
+
TemplateVariable,
|
|
11
|
+
ParseResult,
|
|
12
|
+
ValidationError,
|
|
13
|
+
)
|
|
14
|
+
from control_plane_api.app.lib.templating.parsers import BaseParser, DEFAULT_PARSERS
|
|
15
|
+
|
|
16
|
+
logger = structlog.get_logger()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TemplateEngine:
|
|
20
|
+
"""
|
|
21
|
+
Main template engine that coordinates multiple parsers.
|
|
22
|
+
|
|
23
|
+
This engine uses a plugin-based architecture where different parsers
|
|
24
|
+
can be registered to handle different template syntaxes.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, parsers: List[BaseParser] = None):
|
|
28
|
+
"""
|
|
29
|
+
Initialize the template engine with a list of parsers.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
parsers: List of parsers to use. If None, uses DEFAULT_PARSERS.
|
|
33
|
+
"""
|
|
34
|
+
self.parsers = parsers if parsers is not None else DEFAULT_PARSERS.copy()
|
|
35
|
+
logger.debug("template_engine_initialized", parser_count=len(self.parsers))
|
|
36
|
+
|
|
37
|
+
def parse(self, template: str) -> ParseResult:
|
|
38
|
+
"""
|
|
39
|
+
Parse a template string using all registered parsers.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
template: Template string to parse
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
ParseResult with all variables found and any syntax errors
|
|
46
|
+
"""
|
|
47
|
+
if not template:
|
|
48
|
+
return ParseResult(template="", variables=[], errors=[])
|
|
49
|
+
|
|
50
|
+
variables: List[TemplateVariable] = []
|
|
51
|
+
errors: List[ValidationError] = []
|
|
52
|
+
processed_positions: Set[int] = set()
|
|
53
|
+
|
|
54
|
+
# Run each parser
|
|
55
|
+
for parser in self.parsers:
|
|
56
|
+
try:
|
|
57
|
+
parser_variables = parser.parse(template)
|
|
58
|
+
|
|
59
|
+
# Filter out variables at already-processed positions
|
|
60
|
+
# This prevents conflicts between parsers (e.g., {{var}} matching as both simple and secret)
|
|
61
|
+
for var in parser_variables:
|
|
62
|
+
if var.start not in processed_positions:
|
|
63
|
+
variables.append(var)
|
|
64
|
+
processed_positions.add(var.start)
|
|
65
|
+
logger.debug(
|
|
66
|
+
"variable_parsed",
|
|
67
|
+
variable_name=var.name,
|
|
68
|
+
variable_type=var.type.value,
|
|
69
|
+
position=var.start
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
except Exception as e:
|
|
73
|
+
logger.error(
|
|
74
|
+
"parser_error",
|
|
75
|
+
parser=parser.__class__.__name__,
|
|
76
|
+
error=str(e)
|
|
77
|
+
)
|
|
78
|
+
errors.append(ValidationError(
|
|
79
|
+
message=f"Parser error ({parser.__class__.__name__}): {str(e)}",
|
|
80
|
+
code="PARSER_ERROR"
|
|
81
|
+
))
|
|
82
|
+
|
|
83
|
+
# Check for unrecognized template patterns
|
|
84
|
+
# Find all {{ }} that weren't matched by any parser
|
|
85
|
+
import re
|
|
86
|
+
all_braces = re.finditer(r"\{\{([^}]+)\}\}", template)
|
|
87
|
+
for match in all_braces:
|
|
88
|
+
start = match.start()
|
|
89
|
+
if start not in processed_positions:
|
|
90
|
+
raw = match.group(0)
|
|
91
|
+
errors.append(ValidationError(
|
|
92
|
+
message=f"Unrecognized template syntax: '{raw}'. Expected {{{{variable}}}}, {{{{.secret.name}}}}, or {{{{.env.VAR}}}}",
|
|
93
|
+
position=start,
|
|
94
|
+
code="INVALID_SYNTAX"
|
|
95
|
+
))
|
|
96
|
+
logger.warning(
|
|
97
|
+
"unrecognized_template_syntax",
|
|
98
|
+
raw=raw,
|
|
99
|
+
position=start
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Sort variables by position for consistent ordering
|
|
103
|
+
variables.sort(key=lambda v: v.start)
|
|
104
|
+
|
|
105
|
+
return ParseResult(
|
|
106
|
+
template=template,
|
|
107
|
+
variables=variables,
|
|
108
|
+
errors=errors
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def extract_variables(self, template: str) -> List[TemplateVariable]:
|
|
112
|
+
"""
|
|
113
|
+
Extract all variables from a template without full parsing.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
template: Template string
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
List of TemplateVariable objects
|
|
120
|
+
"""
|
|
121
|
+
parse_result = self.parse(template)
|
|
122
|
+
return parse_result.variables
|
|
123
|
+
|
|
124
|
+
def get_required_secrets(self, template: str) -> List[str]:
|
|
125
|
+
"""
|
|
126
|
+
Get list of required secret names from a template.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
template: Template string
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
List of secret names (without .secret prefix)
|
|
133
|
+
"""
|
|
134
|
+
parse_result = self.parse(template)
|
|
135
|
+
return [var.display_name for var in parse_result.secret_variables]
|
|
136
|
+
|
|
137
|
+
def get_required_env_vars(self, template: str) -> List[str]:
|
|
138
|
+
"""
|
|
139
|
+
Get list of required environment variable names from a template.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
template: Template string
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
List of environment variable names (without .env prefix)
|
|
146
|
+
"""
|
|
147
|
+
parse_result = self.parse(template)
|
|
148
|
+
return [var.display_name for var in parse_result.env_variables]
|
|
149
|
+
|
|
150
|
+
def get_required_simple_vars(self, template: str) -> List[str]:
|
|
151
|
+
"""
|
|
152
|
+
Get list of required simple variable names from a template.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
template: Template string
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
List of simple variable names
|
|
159
|
+
"""
|
|
160
|
+
parse_result = self.parse(template)
|
|
161
|
+
return [var.name for var in parse_result.simple_variables]
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
# Global default engine instance
|
|
165
|
+
_default_engine = None
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def get_default_engine() -> TemplateEngine:
|
|
169
|
+
"""
|
|
170
|
+
Get the default global template engine instance.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
TemplateEngine instance
|
|
174
|
+
"""
|
|
175
|
+
global _default_engine
|
|
176
|
+
if _default_engine is None:
|
|
177
|
+
_default_engine = TemplateEngine()
|
|
178
|
+
return _default_engine
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Template parsers package.
|
|
3
|
+
|
|
4
|
+
Exports all available template variable parsers.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from control_plane_api.app.lib.templating.parsers.base import BaseParser
|
|
8
|
+
from control_plane_api.app.lib.templating.parsers.simple import SimpleVariableParser
|
|
9
|
+
from control_plane_api.app.lib.templating.parsers.secret import SecretVariableParser
|
|
10
|
+
from control_plane_api.app.lib.templating.parsers.env import EnvVariableParser
|
|
11
|
+
from control_plane_api.app.lib.templating.parsers.graph import GraphNodeParser
|
|
12
|
+
|
|
13
|
+
# Default list of parsers to use in the template engine
|
|
14
|
+
# Order matters: more specific patterns should come first to avoid conflicts
|
|
15
|
+
DEFAULT_PARSERS = [
|
|
16
|
+
SecretVariableParser(), # {{.secret.name}} - most specific
|
|
17
|
+
EnvVariableParser(), # {{.env.VAR}} - specific
|
|
18
|
+
GraphNodeParser(), # {{.graph.node-id}} - specific
|
|
19
|
+
SimpleVariableParser(), # {{variable}} - most general (must be last)
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"BaseParser",
|
|
24
|
+
"SimpleVariableParser",
|
|
25
|
+
"SecretVariableParser",
|
|
26
|
+
"EnvVariableParser",
|
|
27
|
+
"GraphNodeParser",
|
|
28
|
+
"DEFAULT_PARSERS",
|
|
29
|
+
]
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base parser interface for template variable parsers.
|
|
3
|
+
|
|
4
|
+
This module defines the abstract base class that all template parsers must implement.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import re
|
|
8
|
+
from abc import ABC, abstractmethod
|
|
9
|
+
from typing import List, Optional
|
|
10
|
+
from control_plane_api.app.lib.templating.types import TemplateVariable, TemplateVariableType
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BaseParser(ABC):
|
|
14
|
+
"""
|
|
15
|
+
Abstract base class for template variable parsers.
|
|
16
|
+
|
|
17
|
+
Each parser is responsible for:
|
|
18
|
+
- Defining a regex pattern to match its template syntax
|
|
19
|
+
- Parsing matches into TemplateVariable objects
|
|
20
|
+
- Validating variable names according to its rules
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
@abstractmethod
|
|
25
|
+
def pattern(self) -> re.Pattern:
|
|
26
|
+
"""
|
|
27
|
+
Regular expression pattern to match this parser's template syntax.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
Compiled regex pattern
|
|
31
|
+
"""
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def variable_type(self) -> TemplateVariableType:
|
|
37
|
+
"""
|
|
38
|
+
Type of variables this parser handles.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
TemplateVariableType enum value
|
|
42
|
+
"""
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
@abstractmethod
|
|
46
|
+
def parse_match(self, match: re.Match, template: str) -> Optional[TemplateVariable]:
|
|
47
|
+
"""
|
|
48
|
+
Parse a regex match into a TemplateVariable.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
match: Regex match object
|
|
52
|
+
template: Full template string (for context)
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
TemplateVariable if valid, None if invalid
|
|
56
|
+
"""
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
@abstractmethod
|
|
60
|
+
def validate_name(self, name: str) -> bool:
|
|
61
|
+
"""
|
|
62
|
+
Validate that a variable name follows this parser's rules.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
name: Variable name to validate
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
True if valid, False otherwise
|
|
69
|
+
"""
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
def parse(self, template: str) -> List[TemplateVariable]:
|
|
73
|
+
"""
|
|
74
|
+
Parse a template string and extract all variables of this parser's type.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
template: Template string to parse
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
List of TemplateVariable objects found
|
|
81
|
+
"""
|
|
82
|
+
if not template:
|
|
83
|
+
return []
|
|
84
|
+
|
|
85
|
+
variables: List[TemplateVariable] = []
|
|
86
|
+
|
|
87
|
+
for match in self.pattern.finditer(template):
|
|
88
|
+
variable = self.parse_match(match, template)
|
|
89
|
+
if variable:
|
|
90
|
+
variables.append(variable)
|
|
91
|
+
|
|
92
|
+
return variables
|
|
93
|
+
|
|
94
|
+
def __repr__(self) -> str:
|
|
95
|
+
"""String representation for debugging."""
|
|
96
|
+
return f"{self.__class__.__name__}(type={self.variable_type.value})"
|