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,403 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tool mapping module for Claude Code runtime.
|
|
3
|
+
|
|
4
|
+
This module handles the translation of generic skill types to specific
|
|
5
|
+
Claude Code SDK tool names, with validation and error handling.
|
|
6
|
+
|
|
7
|
+
BUG FIX #6: Added tool name validation before adding to allowed_tools.
|
|
8
|
+
Issue #4 Fix: Externalized tool mappings to configuration file.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import List, Tuple, Set, Dict, Optional
|
|
12
|
+
import structlog
|
|
13
|
+
import yaml
|
|
14
|
+
import os
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
logger = structlog.get_logger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Known builtin Claude Code tools from SDK documentation
|
|
21
|
+
# This registry is the source of truth for validating builtin tool existence
|
|
22
|
+
CLAUDE_CODE_BUILTIN_TOOLS: Set[str] = {
|
|
23
|
+
"Read",
|
|
24
|
+
"Write",
|
|
25
|
+
"Edit",
|
|
26
|
+
"Glob",
|
|
27
|
+
"Grep",
|
|
28
|
+
"Bash",
|
|
29
|
+
"BashOutput",
|
|
30
|
+
"KillShell",
|
|
31
|
+
"WebFetch",
|
|
32
|
+
"WebSearch",
|
|
33
|
+
"Task",
|
|
34
|
+
"NotebookEdit",
|
|
35
|
+
"TodoWrite",
|
|
36
|
+
"ExitPlanMode",
|
|
37
|
+
"AskUserQuestion",
|
|
38
|
+
"Skill",
|
|
39
|
+
"SlashCommand",
|
|
40
|
+
# MCP resource tools (both naming conventions)
|
|
41
|
+
"ListMcpResources",
|
|
42
|
+
"ReadMcpResource",
|
|
43
|
+
"mcp__list_resources",
|
|
44
|
+
"mcp__read_resource",
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# Backward compatibility alias
|
|
48
|
+
KNOWN_BUILTIN_TOOLS: Set[str] = CLAUDE_CODE_BUILTIN_TOOLS
|
|
49
|
+
|
|
50
|
+
# DEPRECATED: Hardcoded mapping (kept for backward compatibility)
|
|
51
|
+
# Use ToolMappingRegistry instead
|
|
52
|
+
SKILL_TO_TOOL_MAPPING = {
|
|
53
|
+
"shell": ["Bash", "BashOutput", "KillShell"],
|
|
54
|
+
"file_system": ["Read", "Write", "Edit", "Glob", "Grep"],
|
|
55
|
+
"web": ["WebFetch", "WebSearch"],
|
|
56
|
+
"docker": ["Bash"], # Docker commands via Bash
|
|
57
|
+
"kubernetes": ["Bash"], # kubectl via Bash
|
|
58
|
+
"git": ["Bash"], # git commands via Bash
|
|
59
|
+
"task": ["Task"], # Subagent tasks
|
|
60
|
+
"notebook": ["NotebookEdit"],
|
|
61
|
+
"planning": ["TodoWrite", "ExitPlanMode"],
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class ToolMappingRegistry:
|
|
66
|
+
"""
|
|
67
|
+
Issue #4 Fix: Dynamic tool mapping registry with configuration file support.
|
|
68
|
+
|
|
69
|
+
This class loads tool mappings from a YAML configuration file instead of
|
|
70
|
+
hardcoding them, making the system more maintainable and extensible.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
def __init__(self, config_path: Optional[Path] = None):
|
|
74
|
+
"""
|
|
75
|
+
Initialize the tool mapping registry.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
config_path: Optional path to configuration file.
|
|
79
|
+
Defaults to tool_mapping_config.yaml in this directory.
|
|
80
|
+
"""
|
|
81
|
+
self.config_path = config_path or self._get_default_config_path()
|
|
82
|
+
self.mappings: Dict[str, List[str]] = {}
|
|
83
|
+
self.default_tools: List[str] = []
|
|
84
|
+
self.overrides: Dict[str, Dict[str, List[str]]] = {}
|
|
85
|
+
self._load_config()
|
|
86
|
+
|
|
87
|
+
def _get_default_config_path(self) -> Path:
|
|
88
|
+
"""Get path to default configuration file."""
|
|
89
|
+
return Path(__file__).parent / "tool_mapping_config.yaml"
|
|
90
|
+
|
|
91
|
+
def _load_config(self):
|
|
92
|
+
"""Load mappings from configuration file."""
|
|
93
|
+
try:
|
|
94
|
+
# Check for environment variable override
|
|
95
|
+
env_config_path = os.environ.get("CLAUDE_CODE_TOOL_MAPPING_CONFIG")
|
|
96
|
+
if env_config_path:
|
|
97
|
+
config_path = Path(env_config_path)
|
|
98
|
+
logger.info(
|
|
99
|
+
"using_tool_mapping_config_from_env",
|
|
100
|
+
path=str(config_path),
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
config_path = self.config_path
|
|
104
|
+
|
|
105
|
+
if not config_path.exists():
|
|
106
|
+
logger.warning(
|
|
107
|
+
"tool_mapping_config_not_found",
|
|
108
|
+
path=str(config_path),
|
|
109
|
+
fallback="using hardcoded mappings",
|
|
110
|
+
)
|
|
111
|
+
self._load_fallback_mappings()
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
with open(config_path) as f:
|
|
115
|
+
config = yaml.safe_load(f)
|
|
116
|
+
|
|
117
|
+
self.mappings = config.get("skill_type_mappings", {})
|
|
118
|
+
self.default_tools = config.get("default_tools", ["Read", "Write", "Bash"])
|
|
119
|
+
self.overrides = config.get("overrides", {})
|
|
120
|
+
|
|
121
|
+
logger.info(
|
|
122
|
+
"tool_mapping_config_loaded",
|
|
123
|
+
path=str(config_path),
|
|
124
|
+
skill_types=list(self.mappings.keys()),
|
|
125
|
+
default_tools=self.default_tools,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
except Exception as e:
|
|
129
|
+
logger.error(
|
|
130
|
+
"failed_to_load_tool_mapping_config",
|
|
131
|
+
path=str(self.config_path),
|
|
132
|
+
error=str(e),
|
|
133
|
+
fallback="using hardcoded mappings",
|
|
134
|
+
exc_info=True,
|
|
135
|
+
)
|
|
136
|
+
self._load_fallback_mappings()
|
|
137
|
+
|
|
138
|
+
def _load_fallback_mappings(self):
|
|
139
|
+
"""Load fallback hardcoded mappings."""
|
|
140
|
+
self.mappings = SKILL_TO_TOOL_MAPPING.copy()
|
|
141
|
+
self.default_tools = ["Read", "Write", "Bash"]
|
|
142
|
+
logger.debug("using_fallback_hardcoded_mappings")
|
|
143
|
+
|
|
144
|
+
def get_tools_for_skill_type(self, skill_type: str) -> List[str]:
|
|
145
|
+
"""
|
|
146
|
+
Get Claude Code tools for a skill type.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
skill_type: Generic skill type (e.g., "file_system", "shell")
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
List of Claude Code tool names
|
|
153
|
+
"""
|
|
154
|
+
# Check for environment variable override first
|
|
155
|
+
env_key = f"CLAUDE_CODE_MAPPING_{skill_type.upper()}"
|
|
156
|
+
env_override = os.environ.get(env_key)
|
|
157
|
+
if env_override:
|
|
158
|
+
tools = [t.strip() for t in env_override.split(",")]
|
|
159
|
+
logger.debug(
|
|
160
|
+
"using_env_override_for_skill_type",
|
|
161
|
+
skill_type=skill_type,
|
|
162
|
+
tools=tools,
|
|
163
|
+
env_key=env_key,
|
|
164
|
+
)
|
|
165
|
+
return tools
|
|
166
|
+
|
|
167
|
+
# Check configuration
|
|
168
|
+
tools = self.mappings.get(skill_type, [])
|
|
169
|
+
if not tools:
|
|
170
|
+
logger.warning(
|
|
171
|
+
"no_mapping_for_skill_type",
|
|
172
|
+
skill_type=skill_type,
|
|
173
|
+
available_types=list(self.mappings.keys()),
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
return tools
|
|
177
|
+
|
|
178
|
+
def get_default_tools(self) -> List[str]:
|
|
179
|
+
"""Get default tools when no specific skill types are provided."""
|
|
180
|
+
# Check for environment variable override
|
|
181
|
+
env_default = os.environ.get("CLAUDE_CODE_DEFAULT_TOOLS")
|
|
182
|
+
if env_default:
|
|
183
|
+
tools = [t.strip() for t in env_default.split(",")]
|
|
184
|
+
logger.debug("using_env_override_for_default_tools", tools=tools)
|
|
185
|
+
return tools
|
|
186
|
+
|
|
187
|
+
return self.default_tools
|
|
188
|
+
|
|
189
|
+
def validate_mapping(self, skill_type: str, tools: List[str]) -> bool:
|
|
190
|
+
"""
|
|
191
|
+
Validate that all tools in a mapping exist in CLAUDE_CODE_BUILTIN_TOOLS.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
skill_type: Skill type being validated
|
|
195
|
+
tools: List of tool names
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
True if all tools are valid, False otherwise
|
|
199
|
+
"""
|
|
200
|
+
invalid_tools = [t for t in tools if t not in CLAUDE_CODE_BUILTIN_TOOLS]
|
|
201
|
+
if invalid_tools:
|
|
202
|
+
logger.error(
|
|
203
|
+
"invalid_tools_in_mapping",
|
|
204
|
+
skill_type=skill_type,
|
|
205
|
+
invalid_tools=invalid_tools,
|
|
206
|
+
valid_tools=sorted(CLAUDE_CODE_BUILTIN_TOOLS),
|
|
207
|
+
)
|
|
208
|
+
return False
|
|
209
|
+
return True
|
|
210
|
+
|
|
211
|
+
def reload_config(self):
|
|
212
|
+
"""Reload configuration from file."""
|
|
213
|
+
logger.info("reloading_tool_mapping_config")
|
|
214
|
+
self._load_config()
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# Global registry instance
|
|
218
|
+
_tool_mapping_registry: Optional[ToolMappingRegistry] = None
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def get_tool_mapping_registry() -> ToolMappingRegistry:
|
|
222
|
+
"""
|
|
223
|
+
Get the global tool mapping registry instance.
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
ToolMappingRegistry instance
|
|
227
|
+
"""
|
|
228
|
+
global _tool_mapping_registry
|
|
229
|
+
if _tool_mapping_registry is None:
|
|
230
|
+
_tool_mapping_registry = ToolMappingRegistry()
|
|
231
|
+
return _tool_mapping_registry
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def map_skills_to_tools(skills: list) -> List[str]:
|
|
235
|
+
"""
|
|
236
|
+
Map skills to Claude Code tool names.
|
|
237
|
+
|
|
238
|
+
This function translates generic skill types to the specific
|
|
239
|
+
tool names that Claude Code SDK understands.
|
|
240
|
+
|
|
241
|
+
Issue #4 Fix: Now uses ToolMappingRegistry instead of hardcoded mappings.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
skills: List of skill objects
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
List of Claude Code tool names (deduplicated)
|
|
248
|
+
"""
|
|
249
|
+
registry = get_tool_mapping_registry()
|
|
250
|
+
tools = []
|
|
251
|
+
|
|
252
|
+
for skill in skills:
|
|
253
|
+
# Get skill type
|
|
254
|
+
skill_type = None
|
|
255
|
+
if hasattr(skill, "type"):
|
|
256
|
+
skill_type = skill.type
|
|
257
|
+
elif isinstance(skill, dict):
|
|
258
|
+
skill_type = skill.get("type")
|
|
259
|
+
|
|
260
|
+
# Map to Claude Code tools using registry
|
|
261
|
+
if skill_type:
|
|
262
|
+
mapped_tools = registry.get_tools_for_skill_type(skill_type)
|
|
263
|
+
if mapped_tools:
|
|
264
|
+
tools.extend(mapped_tools)
|
|
265
|
+
|
|
266
|
+
# Deduplicate and add default tools if none specified
|
|
267
|
+
if tools:
|
|
268
|
+
unique_tools = list(set(tools))
|
|
269
|
+
else:
|
|
270
|
+
unique_tools = registry.get_default_tools()
|
|
271
|
+
|
|
272
|
+
logger.info(
|
|
273
|
+
"mapped_skills_to_claude_code_tools",
|
|
274
|
+
skill_count=len(skills),
|
|
275
|
+
tool_count=len(unique_tools),
|
|
276
|
+
tools=unique_tools,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
return unique_tools
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def validate_builtin_tools(tool_names: List[str]) -> Tuple[List[str], List[str]]:
|
|
283
|
+
"""
|
|
284
|
+
Validate that builtin tool names exist in Claude Code SDK.
|
|
285
|
+
|
|
286
|
+
Issue #2 Fix: This function ensures Claude Code builtin tools are validated
|
|
287
|
+
before being used, preventing runtime errors.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
tool_names: List of builtin tool names to validate
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
Tuple of (valid_tools, invalid_tools)
|
|
294
|
+
|
|
295
|
+
Raises:
|
|
296
|
+
ValueError: If any builtin tool doesn't exist in CLAUDE_CODE_BUILTIN_TOOLS
|
|
297
|
+
"""
|
|
298
|
+
valid = []
|
|
299
|
+
invalid = []
|
|
300
|
+
|
|
301
|
+
for tool_name in tool_names:
|
|
302
|
+
if tool_name in CLAUDE_CODE_BUILTIN_TOOLS:
|
|
303
|
+
valid.append(tool_name)
|
|
304
|
+
else:
|
|
305
|
+
invalid.append(tool_name)
|
|
306
|
+
|
|
307
|
+
if invalid:
|
|
308
|
+
error_msg = (
|
|
309
|
+
f"Invalid builtin tool names detected: {invalid}. "
|
|
310
|
+
f"These tools don't exist in Claude Code SDK. "
|
|
311
|
+
f"Valid builtin tools are: {sorted(CLAUDE_CODE_BUILTIN_TOOLS)}"
|
|
312
|
+
)
|
|
313
|
+
logger.error(
|
|
314
|
+
"invalid_builtin_tools_detected",
|
|
315
|
+
invalid_tools=invalid,
|
|
316
|
+
valid_tools=valid,
|
|
317
|
+
available_tools=sorted(CLAUDE_CODE_BUILTIN_TOOLS),
|
|
318
|
+
)
|
|
319
|
+
raise ValueError(error_msg)
|
|
320
|
+
|
|
321
|
+
logger.debug(
|
|
322
|
+
"builtin_tools_validated",
|
|
323
|
+
tool_count=len(valid),
|
|
324
|
+
tools=valid,
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
return valid, invalid
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def validate_tool_names(tool_names: List[str]) -> Tuple[List[str], List[str]]:
|
|
331
|
+
"""
|
|
332
|
+
Validate tool names before adding to allowed_tools.
|
|
333
|
+
|
|
334
|
+
BUG FIX #6: This function ensures only valid tool names are used.
|
|
335
|
+
|
|
336
|
+
Args:
|
|
337
|
+
tool_names: List of tool names to validate
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
Tuple of (valid_tools, invalid_tools)
|
|
341
|
+
"""
|
|
342
|
+
valid = []
|
|
343
|
+
invalid = []
|
|
344
|
+
|
|
345
|
+
for tool_name in tool_names:
|
|
346
|
+
# Builtin tools or MCP tools (mcp__ prefix) are valid
|
|
347
|
+
if tool_name in KNOWN_BUILTIN_TOOLS or tool_name.startswith("mcp__"):
|
|
348
|
+
valid.append(tool_name)
|
|
349
|
+
else:
|
|
350
|
+
invalid.append(tool_name)
|
|
351
|
+
|
|
352
|
+
if invalid:
|
|
353
|
+
logger.warning(
|
|
354
|
+
"invalid_tool_names_filtered",
|
|
355
|
+
invalid_tools=invalid,
|
|
356
|
+
valid_count=len(valid),
|
|
357
|
+
invalid_count=len(invalid),
|
|
358
|
+
message="These tools will be filtered out as they're not recognized",
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
return valid, invalid
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def sanitize_tool_name(name: str) -> str:
|
|
365
|
+
"""
|
|
366
|
+
Sanitize a tool name to meet universal LLM provider requirements.
|
|
367
|
+
|
|
368
|
+
Uses the universal validator to ensure compatibility across all providers.
|
|
369
|
+
|
|
370
|
+
Args:
|
|
371
|
+
name: Tool name to sanitize
|
|
372
|
+
|
|
373
|
+
Returns:
|
|
374
|
+
Sanitized tool name that works for all LLM providers
|
|
375
|
+
"""
|
|
376
|
+
from control_plane_api.worker.utils.tool_validation import sanitize_tool_name as universal_sanitize
|
|
377
|
+
return universal_sanitize(name)
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def construct_mcp_tool_name(server_name: str, tool_name: str = None) -> str:
|
|
381
|
+
"""
|
|
382
|
+
Construct a full MCP tool name following the naming convention.
|
|
383
|
+
|
|
384
|
+
Convention: mcp__<server_name>__<tool_name>
|
|
385
|
+
|
|
386
|
+
Args:
|
|
387
|
+
server_name: Name of the MCP server
|
|
388
|
+
tool_name: Optional tool name. If omitted, only server name is used.
|
|
389
|
+
|
|
390
|
+
Returns:
|
|
391
|
+
Full MCP tool name (sanitized)
|
|
392
|
+
"""
|
|
393
|
+
sanitized_server = sanitize_tool_name(server_name)
|
|
394
|
+
|
|
395
|
+
if tool_name:
|
|
396
|
+
sanitized_tool = sanitize_tool_name(tool_name)
|
|
397
|
+
# Avoid duplication: mcp__run_ado_test not mcp__run_ado_test__run_ado_test
|
|
398
|
+
if sanitized_tool == sanitized_server:
|
|
399
|
+
return f"mcp__{sanitized_server}"
|
|
400
|
+
else:
|
|
401
|
+
return f"mcp__{sanitized_server}__{sanitized_tool}"
|
|
402
|
+
else:
|
|
403
|
+
return f"mcp__{sanitized_server}"
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility functions for Claude Code runtime.
|
|
3
|
+
|
|
4
|
+
This module provides helper functions for prompt building, session management,
|
|
5
|
+
and SDK version checking.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Optional
|
|
9
|
+
import structlog
|
|
10
|
+
|
|
11
|
+
logger = structlog.get_logger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def build_prompt_with_history(context: any) -> str:
|
|
15
|
+
"""
|
|
16
|
+
Build prompt with conversation history.
|
|
17
|
+
|
|
18
|
+
Since ClaudeSDKClient maintains session continuity, we include
|
|
19
|
+
the conversation history as context in the prompt.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
context: RuntimeExecutionContext
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Prompt string with history context
|
|
26
|
+
"""
|
|
27
|
+
if not context.conversation_history:
|
|
28
|
+
return context.prompt
|
|
29
|
+
|
|
30
|
+
# Build context from history
|
|
31
|
+
history_context = "Previous conversation:\n"
|
|
32
|
+
for msg in context.conversation_history[-10:]: # Last 10 messages
|
|
33
|
+
role = msg.get("role", "unknown")
|
|
34
|
+
content = msg.get("content", "")
|
|
35
|
+
if len(content) > 200:
|
|
36
|
+
history_context += f"{role.capitalize()}: {content[:200]}...\n"
|
|
37
|
+
else:
|
|
38
|
+
history_context += f"{role.capitalize()}: {content}\n"
|
|
39
|
+
|
|
40
|
+
return f"{history_context}\n\nCurrent request:\n{context.prompt}"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_sdk_version() -> str:
|
|
44
|
+
"""
|
|
45
|
+
Get Claude Code SDK version.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
SDK version string or "unknown"
|
|
49
|
+
"""
|
|
50
|
+
try:
|
|
51
|
+
import claude_agent_sdk
|
|
52
|
+
|
|
53
|
+
return getattr(claude_agent_sdk, "__version__", "unknown")
|
|
54
|
+
except Exception:
|
|
55
|
+
return "unknown"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def extract_usage_from_result_message(message: any) -> dict:
|
|
59
|
+
"""
|
|
60
|
+
Extract usage metrics from ResultMessage.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
message: ResultMessage object
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Usage dict with token counts
|
|
67
|
+
"""
|
|
68
|
+
if not hasattr(message, "usage") or not message.usage:
|
|
69
|
+
logger.warning("result_message_has_no_usage")
|
|
70
|
+
return {}
|
|
71
|
+
|
|
72
|
+
# ResultMessage.usage is a dict, not an object - use .get() instead of getattr()
|
|
73
|
+
usage_dict = message.usage
|
|
74
|
+
|
|
75
|
+
# Handle both dict and object usage formats
|
|
76
|
+
if isinstance(usage_dict, dict):
|
|
77
|
+
input_tokens = usage_dict.get("input_tokens", 0)
|
|
78
|
+
output_tokens = usage_dict.get("output_tokens", 0)
|
|
79
|
+
cache_read_tokens = usage_dict.get("cache_read_input_tokens", 0)
|
|
80
|
+
cache_creation_tokens = usage_dict.get("cache_creation_input_tokens", 0)
|
|
81
|
+
else:
|
|
82
|
+
# Fallback for object-style usage
|
|
83
|
+
input_tokens = getattr(usage_dict, "input_tokens", 0)
|
|
84
|
+
output_tokens = getattr(usage_dict, "output_tokens", 0)
|
|
85
|
+
cache_read_tokens = getattr(usage_dict, "cache_read_input_tokens", 0)
|
|
86
|
+
cache_creation_tokens = getattr(usage_dict, "cache_creation_input_tokens", 0)
|
|
87
|
+
|
|
88
|
+
# Use Anthropic field names for consistency with analytics
|
|
89
|
+
usage = {
|
|
90
|
+
"input_tokens": input_tokens,
|
|
91
|
+
"output_tokens": output_tokens,
|
|
92
|
+
"total_tokens": input_tokens + output_tokens,
|
|
93
|
+
"cache_read_tokens": cache_read_tokens,
|
|
94
|
+
"cache_creation_tokens": cache_creation_tokens,
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
logger.info(
|
|
98
|
+
"usage_extracted_from_claude_code",
|
|
99
|
+
input_tokens=input_tokens,
|
|
100
|
+
output_tokens=output_tokens,
|
|
101
|
+
total_tokens=usage["total_tokens"],
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
return usage
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def extract_session_id_from_result_message(
|
|
108
|
+
message: any, execution_id: str
|
|
109
|
+
) -> Optional[str]:
|
|
110
|
+
"""
|
|
111
|
+
Extract and validate session_id from ResultMessage.
|
|
112
|
+
|
|
113
|
+
BUG FIX #4: Validates session_id before returning.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
message: ResultMessage object
|
|
117
|
+
execution_id: Execution ID for logging
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
Valid session_id or None
|
|
121
|
+
"""
|
|
122
|
+
session_id = getattr(message, "session_id", None)
|
|
123
|
+
|
|
124
|
+
if not session_id:
|
|
125
|
+
logger.warning(
|
|
126
|
+
"no_session_id_in_result_message",
|
|
127
|
+
execution_id=execution_id[:8],
|
|
128
|
+
message="Multi-turn conversations may not work without session_id",
|
|
129
|
+
)
|
|
130
|
+
return None
|
|
131
|
+
|
|
132
|
+
# Validate format
|
|
133
|
+
if not isinstance(session_id, str) or len(session_id) < 10:
|
|
134
|
+
logger.warning(
|
|
135
|
+
"invalid_session_id_format_in_result_message",
|
|
136
|
+
execution_id=execution_id[:8],
|
|
137
|
+
session_id_type=type(session_id).__name__,
|
|
138
|
+
session_id_length=len(session_id) if isinstance(session_id, str) else 0,
|
|
139
|
+
)
|
|
140
|
+
return None
|
|
141
|
+
|
|
142
|
+
logger.info(
|
|
143
|
+
"session_id_captured_for_conversation_continuity",
|
|
144
|
+
execution_id=execution_id[:8],
|
|
145
|
+
session_id_prefix=session_id[:16],
|
|
146
|
+
message="This session_id will enable multi-turn conversations",
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
return session_id
|