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,467 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MCP (Model Context Protocol) server builder for Claude Code runtime.
|
|
3
|
+
|
|
4
|
+
This module handles the creation and configuration of MCP servers from
|
|
5
|
+
both external sources and custom skills.
|
|
6
|
+
|
|
7
|
+
The Claude Code SDK automatically:
|
|
8
|
+
- Connects to MCP servers
|
|
9
|
+
- Discovers available tools
|
|
10
|
+
- Names them as mcp__<server_name>__<tool_name>
|
|
11
|
+
- Makes them available to Claude
|
|
12
|
+
|
|
13
|
+
We only need to:
|
|
14
|
+
1. Validate and format MCP server configs
|
|
15
|
+
2. Convert custom skills to SDK MCP servers (for custom tools)
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from typing import Dict, Any, List, Tuple, Optional
|
|
19
|
+
import structlog
|
|
20
|
+
import asyncio
|
|
21
|
+
|
|
22
|
+
logger = structlog.get_logger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _validate_and_normalize_mcp_config(server_name: str, config: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
26
|
+
"""
|
|
27
|
+
Validate and normalize MCP server configuration dict.
|
|
28
|
+
|
|
29
|
+
The Claude SDK expects TypedDict configs (McpStdioServerConfig or McpSSEServerConfig).
|
|
30
|
+
These are just dictionaries with specific required/optional fields.
|
|
31
|
+
|
|
32
|
+
Stdio format:
|
|
33
|
+
{
|
|
34
|
+
"command": str, # Required
|
|
35
|
+
"args": list[str], # Optional
|
|
36
|
+
"env": dict[str, str] # Optional
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
SSE format:
|
|
40
|
+
{
|
|
41
|
+
"type": "sse", # Required, must be "sse"
|
|
42
|
+
"url": str, # Required
|
|
43
|
+
"headers": dict[str, str] # Optional
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
server_name: Name of the MCP server
|
|
48
|
+
config: Configuration dict from execution environment
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Validated config dict, or None if invalid
|
|
52
|
+
"""
|
|
53
|
+
try:
|
|
54
|
+
# Check if it's stdio transport (has 'command' field)
|
|
55
|
+
if "command" in config:
|
|
56
|
+
command = config.get("command")
|
|
57
|
+
if not command:
|
|
58
|
+
logger.error(
|
|
59
|
+
"stdio_mcp_server_missing_command",
|
|
60
|
+
server_name=server_name,
|
|
61
|
+
config=config
|
|
62
|
+
)
|
|
63
|
+
return None
|
|
64
|
+
|
|
65
|
+
# Build normalized stdio config
|
|
66
|
+
normalized = {
|
|
67
|
+
"command": command,
|
|
68
|
+
}
|
|
69
|
+
if "args" in config:
|
|
70
|
+
normalized["args"] = config["args"]
|
|
71
|
+
if "env" in config:
|
|
72
|
+
normalized["env"] = config["env"]
|
|
73
|
+
|
|
74
|
+
logger.info(
|
|
75
|
+
"validated_stdio_mcp_server",
|
|
76
|
+
server_name=server_name,
|
|
77
|
+
command=command,
|
|
78
|
+
has_args="args" in normalized,
|
|
79
|
+
has_env="env" in normalized
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# Print detailed config for debugging
|
|
83
|
+
print(f"\n{'='*80}")
|
|
84
|
+
print(f"🔍 STDIO MCP SERVER FULL CONFIG (after template resolution)")
|
|
85
|
+
print(f"{'='*80}")
|
|
86
|
+
print(f"Server Name: {server_name}")
|
|
87
|
+
print(f"Command: {command}")
|
|
88
|
+
if "args" in normalized:
|
|
89
|
+
print(f"Args: {normalized['args']}")
|
|
90
|
+
if "env" in normalized:
|
|
91
|
+
print(f"\nEnvironment Variables:")
|
|
92
|
+
for env_name, env_value in normalized["env"].items():
|
|
93
|
+
# Mask sensitive values
|
|
94
|
+
if any(sensitive in env_name.lower() for sensitive in ["key", "token", "auth", "secret", "password"]):
|
|
95
|
+
masked_value = env_value[:20] + "..." if len(env_value) > 20 else "***"
|
|
96
|
+
print(f" {env_name}: {masked_value} (length: {len(env_value)})")
|
|
97
|
+
else:
|
|
98
|
+
print(f" {env_name}: {env_value}")
|
|
99
|
+
print(f"{'='*80}\n")
|
|
100
|
+
|
|
101
|
+
return normalized
|
|
102
|
+
|
|
103
|
+
# Check if it's HTTP/SSE transport (has 'type'/'transport_type' and 'url' fields)
|
|
104
|
+
# Support both 'type' and 'transport_type' for backward compatibility
|
|
105
|
+
elif ("type" in config or "transport_type" in config) and "url" in config:
|
|
106
|
+
transport_type = config.get("type") or config.get("transport_type")
|
|
107
|
+
url = config.get("url")
|
|
108
|
+
|
|
109
|
+
if not url:
|
|
110
|
+
logger.error(
|
|
111
|
+
"http_sse_mcp_server_missing_url",
|
|
112
|
+
server_name=server_name,
|
|
113
|
+
transport_type=transport_type,
|
|
114
|
+
config=config
|
|
115
|
+
)
|
|
116
|
+
return None
|
|
117
|
+
|
|
118
|
+
# Validate transport type
|
|
119
|
+
if transport_type not in ("sse", "http"):
|
|
120
|
+
logger.error(
|
|
121
|
+
"unsupported_mcp_transport_type",
|
|
122
|
+
server_name=server_name,
|
|
123
|
+
transport_type=transport_type,
|
|
124
|
+
supported=["sse", "http"]
|
|
125
|
+
)
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
# Build normalized config - preserve transport type!
|
|
129
|
+
# HTTP = recommended (native Claude SDK support, bidirectional)
|
|
130
|
+
# SSE = deprecated (requires workaround, unidirectional)
|
|
131
|
+
normalized = {
|
|
132
|
+
"type": transport_type, # Keep original: "http" or "sse"
|
|
133
|
+
"url": url,
|
|
134
|
+
}
|
|
135
|
+
if "headers" in config:
|
|
136
|
+
normalized["headers"] = config["headers"]
|
|
137
|
+
|
|
138
|
+
# Log full configuration including headers for debugging
|
|
139
|
+
logger.info(
|
|
140
|
+
"validated_http_mcp_server",
|
|
141
|
+
server_name=server_name,
|
|
142
|
+
transport=transport_type,
|
|
143
|
+
url=url,
|
|
144
|
+
has_headers="headers" in normalized,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# Print detailed config for debugging
|
|
148
|
+
transport_label = "HTTP" if transport_type == "http" else "SSE (DEPRECATED)"
|
|
149
|
+
print(f"\n{'='*80}")
|
|
150
|
+
print(f"🔍 {transport_label} MCP SERVER FULL CONFIG (after template resolution)")
|
|
151
|
+
print(f"{'='*80}")
|
|
152
|
+
print(f"Server Name: {server_name}")
|
|
153
|
+
print(f"Transport: {transport_type}")
|
|
154
|
+
print(f"URL: {url}")
|
|
155
|
+
if "headers" in normalized:
|
|
156
|
+
print(f"\nHeaders:")
|
|
157
|
+
for header_name, header_value in normalized["headers"].items():
|
|
158
|
+
# Mask sensitive values but show structure
|
|
159
|
+
if any(sensitive in header_name.lower() for sensitive in ["key", "token", "auth", "secret"]):
|
|
160
|
+
masked_value = header_value[:20] + "..." if len(header_value) > 20 else "***"
|
|
161
|
+
print(f" {header_name}: {masked_value} (length: {len(header_value)})")
|
|
162
|
+
else:
|
|
163
|
+
print(f" {header_name}: {header_value}")
|
|
164
|
+
else:
|
|
165
|
+
print(f"\nHeaders: (none)")
|
|
166
|
+
print(f"{'='*80}\n")
|
|
167
|
+
|
|
168
|
+
return normalized
|
|
169
|
+
|
|
170
|
+
else:
|
|
171
|
+
logger.error(
|
|
172
|
+
"invalid_mcp_server_config_format",
|
|
173
|
+
server_name=server_name,
|
|
174
|
+
config=config,
|
|
175
|
+
error="Must have either 'command' (stdio) or 'type'+'url' (SSE/HTTP)"
|
|
176
|
+
)
|
|
177
|
+
return None
|
|
178
|
+
|
|
179
|
+
except Exception as e:
|
|
180
|
+
logger.error(
|
|
181
|
+
"mcp_config_validation_error",
|
|
182
|
+
server_name=server_name,
|
|
183
|
+
error=str(e),
|
|
184
|
+
exc_info=True
|
|
185
|
+
)
|
|
186
|
+
return None
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def extract_mcp_tool_names(
|
|
190
|
+
server_name: str,
|
|
191
|
+
server_obj: Any,
|
|
192
|
+
explicit_tools: Optional[List[str]] = None
|
|
193
|
+
) -> List[str]:
|
|
194
|
+
"""
|
|
195
|
+
Extract MCP tool names from server object.
|
|
196
|
+
|
|
197
|
+
⚠️ Note: This function is kept for backward compatibility but isn't used
|
|
198
|
+
in the main flow. Tool discovery is handled by discover_all_mcp_resources()
|
|
199
|
+
in mcp_discovery.py as a workaround for Claude SDK bug #3426.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
server_name: Name of the MCP server
|
|
203
|
+
server_obj: MCP server object
|
|
204
|
+
explicit_tools: Optional list of tool names
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
Empty list (discovery handled in mcp_discovery.py)
|
|
208
|
+
"""
|
|
209
|
+
logger.debug(
|
|
210
|
+
"extract_mcp_tool_names_skipped",
|
|
211
|
+
server_name=server_name,
|
|
212
|
+
message="Tool extraction handled by mcp_discovery.py pre-discovery"
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# Return empty list - discovery handled elsewhere
|
|
216
|
+
return []
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def build_mcp_servers(
|
|
220
|
+
skills: List[Any],
|
|
221
|
+
context_mcp_servers: Dict[str, Any] = None,
|
|
222
|
+
mcp_tools_config: Optional[Dict[str, List[str]]] = None
|
|
223
|
+
) -> Tuple[Dict[str, Any], List[str]]:
|
|
224
|
+
"""
|
|
225
|
+
Build MCP server configurations from context and custom skills.
|
|
226
|
+
|
|
227
|
+
This function:
|
|
228
|
+
1. Validates and formats external MCP server configs (stdio/SSE)
|
|
229
|
+
2. Converts custom skills to SDK MCP servers (for custom tools)
|
|
230
|
+
|
|
231
|
+
⚠️ Note about tool discovery:
|
|
232
|
+
The Claude SDK has a bug (#3426) where it doesn't properly expose SSE MCP tools.
|
|
233
|
+
Tool discovery is handled separately in config.py via discover_all_mcp_resources()
|
|
234
|
+
which pre-discovers tools and adds them to allowedTools as a workaround.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
skills: List of skill objects to convert to MCP servers
|
|
238
|
+
context_mcp_servers: Optional MCP servers from execution context (as config dicts)
|
|
239
|
+
mcp_tools_config: Optional dict mapping server_name -> list of tool names (not used)
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
Tuple of (MCP server configurations dict, empty list)
|
|
243
|
+
Note: Second return value is always empty - tool discovery handled in config.py
|
|
244
|
+
"""
|
|
245
|
+
if mcp_tools_config is None:
|
|
246
|
+
mcp_tools_config = {}
|
|
247
|
+
from claude_agent_sdk import create_sdk_mcp_server, tool as mcp_tool
|
|
248
|
+
|
|
249
|
+
# DEBUG: Log what we received
|
|
250
|
+
print(f"\n🔍 DEBUG: build_mcp_servers() INPUTS:")
|
|
251
|
+
print(f" context_mcp_servers type: {type(context_mcp_servers)}")
|
|
252
|
+
print(f" context_mcp_servers value: {context_mcp_servers}")
|
|
253
|
+
print(f" context_mcp_servers count: {len(context_mcp_servers) if context_mcp_servers else 0}")
|
|
254
|
+
if context_mcp_servers:
|
|
255
|
+
print(f" Server names from context: {list(context_mcp_servers.keys())}")
|
|
256
|
+
print()
|
|
257
|
+
|
|
258
|
+
mcp_servers = {}
|
|
259
|
+
|
|
260
|
+
# Include MCP servers from context (if any)
|
|
261
|
+
if context_mcp_servers:
|
|
262
|
+
logger.info(
|
|
263
|
+
"processing_mcp_servers_from_context",
|
|
264
|
+
server_count=len(context_mcp_servers),
|
|
265
|
+
server_names=list(context_mcp_servers.keys()),
|
|
266
|
+
note="SDK will discover tools automatically from these servers"
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
for server_name, server_config in context_mcp_servers.items():
|
|
270
|
+
logger.debug(
|
|
271
|
+
"processing_mcp_server_from_context",
|
|
272
|
+
server_name=server_name,
|
|
273
|
+
config_keys=list(server_config.keys()) if isinstance(server_config, dict) else "not_dict",
|
|
274
|
+
has_command="command" in server_config if isinstance(server_config, dict) else False,
|
|
275
|
+
has_type="type" in server_config if isinstance(server_config, dict) else False,
|
|
276
|
+
has_url="url" in server_config if isinstance(server_config, dict) else False,
|
|
277
|
+
)
|
|
278
|
+
# Validate and normalize config dict (already in Claude SDK TypedDict format)
|
|
279
|
+
normalized_config = _validate_and_normalize_mcp_config(server_name, server_config)
|
|
280
|
+
if normalized_config:
|
|
281
|
+
mcp_servers[server_name] = normalized_config
|
|
282
|
+
transport = normalized_config.get("type", "stdio") if "type" in normalized_config else "stdio"
|
|
283
|
+
logger.info(
|
|
284
|
+
"mcp_server_configured",
|
|
285
|
+
server_name=server_name,
|
|
286
|
+
transport=transport,
|
|
287
|
+
note="SDK will connect and discover tools automatically" if transport == "http"
|
|
288
|
+
else "SDK will connect (pre-discovery may be needed for SSE)" if transport == "sse"
|
|
289
|
+
else "SDK will connect and discover tools automatically"
|
|
290
|
+
)
|
|
291
|
+
else:
|
|
292
|
+
logger.warning(
|
|
293
|
+
"skipping_mcp_server_invalid_config",
|
|
294
|
+
server_name=server_name,
|
|
295
|
+
config=server_config
|
|
296
|
+
)
|
|
297
|
+
continue
|
|
298
|
+
|
|
299
|
+
# Convert custom skills to MCP servers
|
|
300
|
+
for skill in skills:
|
|
301
|
+
tools_list = []
|
|
302
|
+
registered_tool_names = [] # Track tool names for logging
|
|
303
|
+
skill_name = getattr(skill, "name", "custom_skill")
|
|
304
|
+
|
|
305
|
+
# Check for Toolkit pattern (has .functions attribute)
|
|
306
|
+
if hasattr(skill, "functions") and hasattr(skill.functions, "items"):
|
|
307
|
+
logger.info(
|
|
308
|
+
"found_skill_with_registered_functions",
|
|
309
|
+
skill_name=skill_name,
|
|
310
|
+
function_count=len(skill.functions),
|
|
311
|
+
function_names=list(skill.functions.keys()),
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
# Extract tools from functions registry
|
|
315
|
+
for func_name, func_obj in skill.functions.items():
|
|
316
|
+
# Skip helper tools for workflow_executor skills to avoid confusion
|
|
317
|
+
if func_name in ["list_all_workflows", "get_workflow_info"]:
|
|
318
|
+
logger.debug(
|
|
319
|
+
"skipping_helper_tool_for_workflow_executor",
|
|
320
|
+
skill_name=skill_name,
|
|
321
|
+
tool_name=func_name,
|
|
322
|
+
)
|
|
323
|
+
continue
|
|
324
|
+
|
|
325
|
+
# Get entrypoint (the actual callable)
|
|
326
|
+
entrypoint = getattr(func_obj, "entrypoint", None)
|
|
327
|
+
if not entrypoint:
|
|
328
|
+
logger.warning(
|
|
329
|
+
"function_missing_entrypoint",
|
|
330
|
+
skill_name=skill_name,
|
|
331
|
+
function_name=func_name,
|
|
332
|
+
)
|
|
333
|
+
continue
|
|
334
|
+
|
|
335
|
+
# Get function metadata - use function name as-is
|
|
336
|
+
tool_name = func_name
|
|
337
|
+
tool_description = (
|
|
338
|
+
getattr(func_obj, "description", None)
|
|
339
|
+
or entrypoint.__doc__
|
|
340
|
+
or f"{tool_name} tool"
|
|
341
|
+
)
|
|
342
|
+
tool_parameters = getattr(func_obj, "parameters", {})
|
|
343
|
+
|
|
344
|
+
# Create a closure that captures the entrypoint with proper variable scope
|
|
345
|
+
def make_tool_wrapper(
|
|
346
|
+
tool_entrypoint,
|
|
347
|
+
tool_func_name,
|
|
348
|
+
tool_func_description,
|
|
349
|
+
tool_func_parameters,
|
|
350
|
+
):
|
|
351
|
+
"""Factory to create tool wrappers with proper closure"""
|
|
352
|
+
|
|
353
|
+
@mcp_tool(tool_func_name, tool_func_description, tool_func_parameters)
|
|
354
|
+
async def wrapped_tool(args: dict) -> dict:
|
|
355
|
+
try:
|
|
356
|
+
logger.debug(
|
|
357
|
+
"executing_builtin_skill_tool",
|
|
358
|
+
tool_name=tool_func_name,
|
|
359
|
+
args=args,
|
|
360
|
+
)
|
|
361
|
+
# Call the entrypoint with unpacked args
|
|
362
|
+
if asyncio.iscoroutinefunction(tool_entrypoint):
|
|
363
|
+
result = (
|
|
364
|
+
await tool_entrypoint(**args)
|
|
365
|
+
if args
|
|
366
|
+
else await tool_entrypoint()
|
|
367
|
+
)
|
|
368
|
+
else:
|
|
369
|
+
# Run synchronous tools in thread pool to avoid blocking
|
|
370
|
+
result = await asyncio.to_thread(
|
|
371
|
+
lambda: tool_entrypoint(**args)
|
|
372
|
+
if args
|
|
373
|
+
else tool_entrypoint()
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
logger.info(
|
|
377
|
+
"builtin_skill_tool_completed",
|
|
378
|
+
tool_name=tool_func_name,
|
|
379
|
+
result_length=len(str(result)),
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
return {
|
|
383
|
+
"content": [{"type": "text", "text": str(result)}]
|
|
384
|
+
}
|
|
385
|
+
except Exception as e:
|
|
386
|
+
logger.error(
|
|
387
|
+
"builtin_skill_tool_execution_failed",
|
|
388
|
+
tool_name=tool_func_name,
|
|
389
|
+
error=str(e),
|
|
390
|
+
exc_info=True,
|
|
391
|
+
)
|
|
392
|
+
return {
|
|
393
|
+
"content": [
|
|
394
|
+
{
|
|
395
|
+
"type": "text",
|
|
396
|
+
"text": f"Error executing {tool_func_name}: {str(e)}",
|
|
397
|
+
}
|
|
398
|
+
],
|
|
399
|
+
"isError": True,
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
return wrapped_tool
|
|
403
|
+
|
|
404
|
+
wrapped_tool = make_tool_wrapper(
|
|
405
|
+
entrypoint, tool_name, tool_description, tool_parameters
|
|
406
|
+
)
|
|
407
|
+
tools_list.append(wrapped_tool)
|
|
408
|
+
registered_tool_names.append(tool_name)
|
|
409
|
+
|
|
410
|
+
logger.info(
|
|
411
|
+
"registered_mcp_tool_from_skill_function",
|
|
412
|
+
skill_name=skill_name,
|
|
413
|
+
tool_name=tool_name,
|
|
414
|
+
full_mcp_tool_name=f"mcp__{skill_name}__{tool_name}",
|
|
415
|
+
note="SDK will make this available automatically"
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
# Legacy: Check if skill has get_tools() method
|
|
419
|
+
elif hasattr(skill, "get_tools"):
|
|
420
|
+
for tool_func in skill.get_tools():
|
|
421
|
+
# Wrap each tool function with MCP tool decorator
|
|
422
|
+
tool_name = getattr(tool_func, "__name__", "custom_tool")
|
|
423
|
+
tool_description = getattr(tool_func, "__doc__", f"{tool_name} tool")
|
|
424
|
+
|
|
425
|
+
# Create MCP tool wrapper
|
|
426
|
+
@mcp_tool(tool_name, tool_description, {})
|
|
427
|
+
async def wrapped_tool(args: dict) -> dict:
|
|
428
|
+
# Run synchronous tools in thread pool to avoid blocking
|
|
429
|
+
if asyncio.iscoroutinefunction(tool_func):
|
|
430
|
+
result = (
|
|
431
|
+
await tool_func(**args) if args else await tool_func()
|
|
432
|
+
)
|
|
433
|
+
else:
|
|
434
|
+
result = await asyncio.to_thread(
|
|
435
|
+
lambda: tool_func(**args) if args else tool_func()
|
|
436
|
+
)
|
|
437
|
+
return {"content": [{"type": "text", "text": str(result)}]}
|
|
438
|
+
|
|
439
|
+
tools_list.append(wrapped_tool)
|
|
440
|
+
registered_tool_names.append(tool_name)
|
|
441
|
+
|
|
442
|
+
# Create MCP server for this skill if it has tools
|
|
443
|
+
if tools_list:
|
|
444
|
+
server_name = skill_name
|
|
445
|
+
|
|
446
|
+
mcp_servers[server_name] = create_sdk_mcp_server(
|
|
447
|
+
name=server_name, version="1.0.0", tools=tools_list
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
logger.info(
|
|
451
|
+
"created_mcp_server_for_skill",
|
|
452
|
+
skill_name=skill_name,
|
|
453
|
+
server_name=server_name,
|
|
454
|
+
tool_count=len(tools_list),
|
|
455
|
+
tool_names=registered_tool_names,
|
|
456
|
+
note="SDK will make these tools available as mcp__<server>__<tool>"
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
logger.info(
|
|
460
|
+
"built_mcp_servers",
|
|
461
|
+
server_count=len(mcp_servers),
|
|
462
|
+
servers=list(mcp_servers.keys()),
|
|
463
|
+
note="SDK will discover and provide all tools automatically - no manual intervention needed"
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
# Return empty list for tool names - SDK discovers them automatically
|
|
467
|
+
return mcp_servers, []
|