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,242 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Resources Context Tools - Fetch general resource and capability information
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from sqlalchemy.orm import Session
|
|
7
|
+
from control_plane_api.app.lib.planning_tools.base import BasePlanningTools
|
|
8
|
+
from control_plane_api.app.lib.supabase import get_supabase
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ResourcesContextTools(BasePlanningTools):
|
|
12
|
+
"""
|
|
13
|
+
Tools for fetching general resource and capability context
|
|
14
|
+
|
|
15
|
+
Provides methods to:
|
|
16
|
+
- List available tools and skills
|
|
17
|
+
- Query project information
|
|
18
|
+
- Get integration capabilities
|
|
19
|
+
- Check system-wide resources
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, db: Optional[Session] = None, organization_id: Optional[str] = None):
|
|
23
|
+
super().__init__(db=db, organization_id=organization_id)
|
|
24
|
+
self.name = "resources_context_tools"
|
|
25
|
+
|
|
26
|
+
async def list_available_skills(self) -> str:
|
|
27
|
+
"""
|
|
28
|
+
List all available skills that agents can use
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Formatted list of skills including:
|
|
32
|
+
- Skill name and category
|
|
33
|
+
- Available tools within each skill
|
|
34
|
+
- Usage descriptions
|
|
35
|
+
- Cost implications
|
|
36
|
+
"""
|
|
37
|
+
try:
|
|
38
|
+
response = await self._make_request("GET", "/skills")
|
|
39
|
+
|
|
40
|
+
skills = response if isinstance(response, list) else response.get("skills", [])
|
|
41
|
+
|
|
42
|
+
output = [f"Available Skills ({len(skills)} total):"]
|
|
43
|
+
|
|
44
|
+
for idx, skill in enumerate(skills, 1):
|
|
45
|
+
name = skill.get("name", "Unknown")
|
|
46
|
+
category = skill.get("category", "General")
|
|
47
|
+
tools = skill.get("tools", [])
|
|
48
|
+
|
|
49
|
+
output.append(f"\n{idx}. {name} (Category: {category})")
|
|
50
|
+
output.append(f" Description: {skill.get('description', 'No description')}")
|
|
51
|
+
|
|
52
|
+
if tools:
|
|
53
|
+
output.append(f" Tools ({len(tools)}):")
|
|
54
|
+
for tool in tools[:5]: # Show first 5 tools
|
|
55
|
+
tool_name = tool.get("name", "unknown")
|
|
56
|
+
output.append(f" - {tool_name}")
|
|
57
|
+
if len(tools) > 5:
|
|
58
|
+
output.append(f" ... and {len(tools) - 5} more")
|
|
59
|
+
|
|
60
|
+
return "\n".join(output)
|
|
61
|
+
|
|
62
|
+
except Exception as e:
|
|
63
|
+
return f"Error listing skills: {str(e)}"
|
|
64
|
+
|
|
65
|
+
async def get_skill_details(self, skill_name: str) -> str:
|
|
66
|
+
"""
|
|
67
|
+
Get detailed information about a specific skill
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
skill_name: Name of the skill to fetch
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Detailed skill information including all available tools
|
|
74
|
+
"""
|
|
75
|
+
try:
|
|
76
|
+
response = await self._make_request("GET", f"/skills/{skill_name}")
|
|
77
|
+
|
|
78
|
+
return self._format_detail_response(
|
|
79
|
+
item=response,
|
|
80
|
+
title=f"Skill Details: {skill_name}",
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
except Exception as e:
|
|
84
|
+
return f"Error fetching skill {skill_name}: {str(e)}"
|
|
85
|
+
|
|
86
|
+
async def list_projects(self, limit: int = 50) -> str:
|
|
87
|
+
"""
|
|
88
|
+
List all available projects
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
limit: Maximum number of projects to return
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
List of projects with basic information
|
|
95
|
+
"""
|
|
96
|
+
try:
|
|
97
|
+
params = {"limit": limit}
|
|
98
|
+
if self.organization_id:
|
|
99
|
+
params["organization_id"] = self.organization_id
|
|
100
|
+
|
|
101
|
+
response = await self._make_request("GET", "/projects", params=params)
|
|
102
|
+
|
|
103
|
+
projects = response if isinstance(response, list) else response.get("projects", [])
|
|
104
|
+
|
|
105
|
+
return self._format_list_response(
|
|
106
|
+
items=projects,
|
|
107
|
+
title="Available Projects",
|
|
108
|
+
key_fields=["description", "status", "owner"],
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
except Exception as e:
|
|
112
|
+
return f"Error listing projects: {str(e)}"
|
|
113
|
+
|
|
114
|
+
async def get_project_details(self, project_id: str) -> str:
|
|
115
|
+
"""
|
|
116
|
+
Get detailed information about a specific project
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
project_id: ID of the project
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
Detailed project information
|
|
123
|
+
"""
|
|
124
|
+
try:
|
|
125
|
+
response = await self._make_request("GET", f"/projects/{project_id}")
|
|
126
|
+
|
|
127
|
+
return self._format_detail_response(
|
|
128
|
+
item=response,
|
|
129
|
+
title=f"Project Details: {response.get('name', 'Unknown')}",
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
except Exception as e:
|
|
133
|
+
return f"Error fetching project {project_id}: {str(e)}"
|
|
134
|
+
|
|
135
|
+
async def list_integrations(self) -> str:
|
|
136
|
+
"""
|
|
137
|
+
List all available integrations
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
List of available integrations (Slack, Jira, GitHub, AWS, etc.)
|
|
141
|
+
"""
|
|
142
|
+
try:
|
|
143
|
+
response = await self._make_request("GET", "/integrations")
|
|
144
|
+
|
|
145
|
+
integrations = response if isinstance(response, list) else response.get("integrations", [])
|
|
146
|
+
|
|
147
|
+
return self._format_list_response(
|
|
148
|
+
items=integrations,
|
|
149
|
+
title="Available Integrations",
|
|
150
|
+
key_fields=["type", "status", "capabilities"],
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
except Exception as e:
|
|
154
|
+
return f"Error listing integrations: {str(e)}"
|
|
155
|
+
|
|
156
|
+
async def get_organization_info(self) -> str:
|
|
157
|
+
"""
|
|
158
|
+
Get information about the current organization
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
Organization information including:
|
|
162
|
+
- Resource limits
|
|
163
|
+
- Active agents/teams count
|
|
164
|
+
- Usage statistics
|
|
165
|
+
"""
|
|
166
|
+
try:
|
|
167
|
+
if not self.organization_id:
|
|
168
|
+
return "Organization ID not provided"
|
|
169
|
+
|
|
170
|
+
response = await self._make_request("GET", f"/organizations/{self.organization_id}")
|
|
171
|
+
|
|
172
|
+
# Get additional statistics
|
|
173
|
+
agents = await self._make_request("GET", "/agents", params={"organization_id": self.organization_id})
|
|
174
|
+
teams = await self._make_request("GET", "/teams", params={"organization_id": self.organization_id})
|
|
175
|
+
|
|
176
|
+
agent_count = len(agents) if isinstance(agents, list) else agents.get("count", 0)
|
|
177
|
+
team_count = len(teams) if isinstance(teams, list) else teams.get("count", 0)
|
|
178
|
+
|
|
179
|
+
output = [
|
|
180
|
+
f"Organization: {response.get('name', 'Unknown')}",
|
|
181
|
+
f" ID: {self.organization_id}",
|
|
182
|
+
f" Status: {response.get('status', 'unknown')}",
|
|
183
|
+
f" Active Agents: {agent_count}",
|
|
184
|
+
f" Active Teams: {team_count}",
|
|
185
|
+
]
|
|
186
|
+
|
|
187
|
+
if "resource_limits" in response:
|
|
188
|
+
output.append("\n Resource Limits:")
|
|
189
|
+
for key, value in response["resource_limits"].items():
|
|
190
|
+
output.append(f" {key}: {value}")
|
|
191
|
+
|
|
192
|
+
return "\n".join(output)
|
|
193
|
+
|
|
194
|
+
except Exception as e:
|
|
195
|
+
return f"Error fetching organization info: {str(e)}"
|
|
196
|
+
|
|
197
|
+
async def search_tools_by_capability(self, capability: str) -> str:
|
|
198
|
+
"""
|
|
199
|
+
Search for tools that provide a specific capability
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
capability: Capability to search for (e.g., "aws", "kubernetes", "database")
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
List of tools/skills that provide the capability
|
|
206
|
+
"""
|
|
207
|
+
try:
|
|
208
|
+
response = await self._make_request("GET", "/skills")
|
|
209
|
+
skills = response if isinstance(response, list) else response.get("skills", [])
|
|
210
|
+
|
|
211
|
+
matching_tools = []
|
|
212
|
+
for skill in skills:
|
|
213
|
+
skill_text = f"{skill.get('name', '')} {skill.get('description', '')}".lower()
|
|
214
|
+
tools = skill.get("tools", [])
|
|
215
|
+
|
|
216
|
+
if capability.lower() in skill_text:
|
|
217
|
+
matching_tools.append({
|
|
218
|
+
"name": skill.get("name"),
|
|
219
|
+
"category": skill.get("category"),
|
|
220
|
+
"description": skill.get("description"),
|
|
221
|
+
"tool_count": len(tools),
|
|
222
|
+
})
|
|
223
|
+
else:
|
|
224
|
+
# Check individual tools
|
|
225
|
+
for tool in tools:
|
|
226
|
+
tool_text = f"{tool.get('name', '')} {tool.get('description', '')}".lower()
|
|
227
|
+
if capability.lower() in tool_text:
|
|
228
|
+
matching_tools.append({
|
|
229
|
+
"name": f"{skill.get('name')}/{tool.get('name')}",
|
|
230
|
+
"category": skill.get("category"),
|
|
231
|
+
"description": tool.get("description"),
|
|
232
|
+
"tool_count": 1,
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
return self._format_list_response(
|
|
236
|
+
items=matching_tools,
|
|
237
|
+
title=f"Tools/Skills with '{capability}' capability",
|
|
238
|
+
key_fields=["category", "description"],
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
except Exception as e:
|
|
242
|
+
return f"Error searching tools: {str(e)}"
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Team Context Tools - Fetch team information for task planning
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional, List
|
|
6
|
+
from sqlalchemy.orm import Session
|
|
7
|
+
import structlog
|
|
8
|
+
from control_plane_api.app.lib.planning_tools.base import BasePlanningTools
|
|
9
|
+
from control_plane_api.app.lib.planning_tools.models import TeamModel, TeamMemberModel
|
|
10
|
+
from control_plane_api.app.models.team import Team
|
|
11
|
+
from control_plane_api.app.models.agent import Agent
|
|
12
|
+
from control_plane_api.app.lib.supabase import get_supabase
|
|
13
|
+
|
|
14
|
+
logger = structlog.get_logger()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TeamsContextTools(BasePlanningTools):
|
|
18
|
+
"""
|
|
19
|
+
Tools for fetching team context and composition
|
|
20
|
+
|
|
21
|
+
Provides methods to:
|
|
22
|
+
- List all available teams
|
|
23
|
+
- Get detailed team information
|
|
24
|
+
- Query team member capabilities
|
|
25
|
+
- Check team availability
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, db: Optional[Session] = None, organization_id: Optional[str] = None):
|
|
29
|
+
super().__init__(db=db, organization_id=organization_id)
|
|
30
|
+
self.name = "team_context_tools"
|
|
31
|
+
|
|
32
|
+
async def list_teams(self, limit: int = 50, status_filter: Optional[str] = None) -> List[dict]:
|
|
33
|
+
"""
|
|
34
|
+
List all available teams with their full information
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
limit: Maximum number of teams to return
|
|
38
|
+
status_filter: Optional status filter (e.g., 'active', 'inactive')
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
List of team dictionaries with complete data including:
|
|
42
|
+
- Team name, ID, description, status
|
|
43
|
+
- Full agent details for each team member
|
|
44
|
+
- Agent execution environments, skills, capabilities
|
|
45
|
+
- Team configuration
|
|
46
|
+
"""
|
|
47
|
+
try:
|
|
48
|
+
# CRITICAL SECURITY: organization_id MUST be set to prevent cross-org data leakage
|
|
49
|
+
if not self.organization_id:
|
|
50
|
+
logger.error("list_teams_called_without_organization_id",
|
|
51
|
+
message="SECURITY: Refusing to list teams without organization_id filter")
|
|
52
|
+
return []
|
|
53
|
+
|
|
54
|
+
db = self._get_db()
|
|
55
|
+
|
|
56
|
+
# Build query - ALWAYS filter by organization
|
|
57
|
+
query = db.query(Team).filter(Team.organization_id == self.organization_id)
|
|
58
|
+
if status_filter:
|
|
59
|
+
query = query.filter(Team.status == status_filter)
|
|
60
|
+
|
|
61
|
+
teams = query.limit(limit).all()
|
|
62
|
+
|
|
63
|
+
# Convert to Pydantic models
|
|
64
|
+
team_models = []
|
|
65
|
+
for team in teams:
|
|
66
|
+
# Get agent count from configuration
|
|
67
|
+
member_ids = team.configuration.get("member_ids", []) if team.configuration else []
|
|
68
|
+
team_models.append(
|
|
69
|
+
TeamModel(
|
|
70
|
+
id=str(team.id),
|
|
71
|
+
name=team.name,
|
|
72
|
+
description=team.description,
|
|
73
|
+
status=team.status,
|
|
74
|
+
agent_count=len(member_ids),
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Convert to dict for formatting - but we need more data!
|
|
79
|
+
# Fetch full agent details for each team to include in context
|
|
80
|
+
team_dicts = []
|
|
81
|
+
for team in teams:
|
|
82
|
+
member_ids = team.configuration.get("member_ids", []) if team.configuration else []
|
|
83
|
+
|
|
84
|
+
# Fetch full agent data for team members - SECURITY: Filter by organization!
|
|
85
|
+
agents_data = []
|
|
86
|
+
if member_ids:
|
|
87
|
+
agent_objs = db.query(Agent).filter(
|
|
88
|
+
Agent.id.in_(member_ids),
|
|
89
|
+
Agent.organization_id == self.organization_id # SECURITY: Always filter
|
|
90
|
+
).all()
|
|
91
|
+
for agent in agent_objs:
|
|
92
|
+
agents_data.append({
|
|
93
|
+
"id": str(agent.id),
|
|
94
|
+
"name": agent.name,
|
|
95
|
+
"model_id": getattr(agent, 'model_id', None) or "default",
|
|
96
|
+
"description": getattr(agent, 'description', None),
|
|
97
|
+
"status": getattr(agent, 'status', 'unknown'),
|
|
98
|
+
"capabilities": getattr(agent, 'capabilities', None) or [],
|
|
99
|
+
"execution_environment": getattr(agent, 'execution_environment', None),
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
team_dicts.append({
|
|
103
|
+
"id": str(team.id),
|
|
104
|
+
"name": team.name,
|
|
105
|
+
"description": team.description,
|
|
106
|
+
"status": team.status,
|
|
107
|
+
"agent_count": len(member_ids),
|
|
108
|
+
"agents": agents_data, # Include full agent data
|
|
109
|
+
"configuration": team.configuration,
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
# Return structured data directly instead of formatted string
|
|
113
|
+
return team_dicts
|
|
114
|
+
|
|
115
|
+
except Exception as e:
|
|
116
|
+
logger.error("error_listing_teams", error=str(e))
|
|
117
|
+
return []
|
|
118
|
+
|
|
119
|
+
async def get_team_details(self, team_id: str) -> str:
|
|
120
|
+
"""
|
|
121
|
+
Get detailed information about a specific team
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
team_id: ID of the team to fetch
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
Detailed team information including:
|
|
128
|
+
- Full team configuration
|
|
129
|
+
- List of all team members with their roles
|
|
130
|
+
- Team capabilities (aggregate of member capabilities)
|
|
131
|
+
- Coordination strategy
|
|
132
|
+
"""
|
|
133
|
+
try:
|
|
134
|
+
db = self._get_db()
|
|
135
|
+
|
|
136
|
+
team = db.query(Team).filter(Team.id == team_id)
|
|
137
|
+
if self.organization_id:
|
|
138
|
+
team = team.filter(Team.organization_id == self.organization_id)
|
|
139
|
+
team = team.first()
|
|
140
|
+
|
|
141
|
+
if not team:
|
|
142
|
+
return f"Team {team_id} not found"
|
|
143
|
+
|
|
144
|
+
# Get member IDs from configuration
|
|
145
|
+
member_ids = team.configuration.get("member_ids", []) if team.configuration else []
|
|
146
|
+
|
|
147
|
+
# Fetch agents and convert to Pydantic models
|
|
148
|
+
agent_models = []
|
|
149
|
+
if member_ids:
|
|
150
|
+
agent_objs = db.query(Agent).filter(Agent.id.in_(member_ids)).all()
|
|
151
|
+
agent_models = [
|
|
152
|
+
TeamMemberModel(
|
|
153
|
+
id=str(agent.id),
|
|
154
|
+
name=agent.name,
|
|
155
|
+
model_id=agent.model_id or "default",
|
|
156
|
+
description=agent.description,
|
|
157
|
+
)
|
|
158
|
+
for agent in agent_objs
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
# Convert to dict for output formatting
|
|
162
|
+
agents = [model.model_dump() for model in agent_models]
|
|
163
|
+
|
|
164
|
+
output = [
|
|
165
|
+
f"Team Details: {team.name}",
|
|
166
|
+
f" ID: {str(team.id)}",
|
|
167
|
+
f" Description: {team.description or 'No description'}",
|
|
168
|
+
f" Agent Count: {len(agents)}",
|
|
169
|
+
"",
|
|
170
|
+
"Team Members:",
|
|
171
|
+
]
|
|
172
|
+
|
|
173
|
+
for idx, agent in enumerate(agents, 1):
|
|
174
|
+
output.append(f" {idx}. {agent.get('name', 'Unnamed')} (ID: {agent.get('id')})")
|
|
175
|
+
if "model_id" in agent:
|
|
176
|
+
output.append(f" Model: {agent['model_id']}")
|
|
177
|
+
if "description" in agent:
|
|
178
|
+
output.append(f" Capabilities: {agent['description'][:100]}")
|
|
179
|
+
|
|
180
|
+
return "\n".join(output)
|
|
181
|
+
|
|
182
|
+
except Exception as e:
|
|
183
|
+
return f"Error fetching team {team_id}: {str(e)}"
|
|
184
|
+
|
|
185
|
+
async def get_team_members(self, team_id: str) -> str:
|
|
186
|
+
"""
|
|
187
|
+
Get list of agents in a specific team
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
team_id: ID of the team
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
List of team members with their capabilities
|
|
194
|
+
"""
|
|
195
|
+
try:
|
|
196
|
+
db = self._get_db()
|
|
197
|
+
|
|
198
|
+
team = db.query(Team).filter(Team.id == team_id)
|
|
199
|
+
if self.organization_id:
|
|
200
|
+
team = team.filter(Team.organization_id == self.organization_id)
|
|
201
|
+
team = team.first()
|
|
202
|
+
|
|
203
|
+
if not team:
|
|
204
|
+
return f"Team {team_id} not found"
|
|
205
|
+
|
|
206
|
+
# Get member IDs from configuration
|
|
207
|
+
member_ids = team.configuration.get("member_ids", []) if team.configuration else []
|
|
208
|
+
|
|
209
|
+
if not member_ids:
|
|
210
|
+
return f"Team {team_id} has no members"
|
|
211
|
+
|
|
212
|
+
# Fetch agents and convert to Pydantic models
|
|
213
|
+
agent_objs = db.query(Agent).filter(Agent.id.in_(member_ids)).all()
|
|
214
|
+
agent_models = [
|
|
215
|
+
TeamMemberModel(
|
|
216
|
+
id=str(agent.id),
|
|
217
|
+
name=agent.name,
|
|
218
|
+
model_id=agent.model_id or "default",
|
|
219
|
+
description=agent.description,
|
|
220
|
+
)
|
|
221
|
+
for agent in agent_objs
|
|
222
|
+
]
|
|
223
|
+
|
|
224
|
+
# Convert to dict for formatting
|
|
225
|
+
agent_dicts = [model.model_dump() for model in agent_models]
|
|
226
|
+
|
|
227
|
+
return self._format_list_response(
|
|
228
|
+
items=agent_dicts,
|
|
229
|
+
title=f"Team Members ({len(agent_dicts)} total)",
|
|
230
|
+
key_fields=["model_id", "description"],
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
except Exception as e:
|
|
234
|
+
return f"Error fetching team members: {str(e)}"
|
|
235
|
+
|
|
236
|
+
async def search_teams_by_capability(self, capability: str) -> str:
|
|
237
|
+
"""
|
|
238
|
+
Search for teams that have agents with a specific capability
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
capability: Capability to search for (e.g., "devops", "security", "data")
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
List of teams with members having the capability
|
|
245
|
+
"""
|
|
246
|
+
try:
|
|
247
|
+
db = self._get_db()
|
|
248
|
+
|
|
249
|
+
query = db.query(Team)
|
|
250
|
+
if self.organization_id:
|
|
251
|
+
query = query.filter(Team.organization_id == self.organization_id)
|
|
252
|
+
|
|
253
|
+
teams = query.all()
|
|
254
|
+
|
|
255
|
+
matching_teams = []
|
|
256
|
+
for team in teams:
|
|
257
|
+
# Search in team name and description
|
|
258
|
+
team_text = f"{team.name} {team.description or ''}".lower()
|
|
259
|
+
|
|
260
|
+
# Also search in team members' descriptions
|
|
261
|
+
member_ids = team.configuration.get("member_ids", []) if team.configuration else []
|
|
262
|
+
if member_ids:
|
|
263
|
+
agents = db.query(Agent).filter(Agent.id.in_(member_ids)).all()
|
|
264
|
+
agent_text = " ".join([agent.description or "" for agent in agents]).lower()
|
|
265
|
+
else:
|
|
266
|
+
agent_text = ""
|
|
267
|
+
|
|
268
|
+
if capability.lower() in team_text or capability.lower() in agent_text:
|
|
269
|
+
matching_teams.append(
|
|
270
|
+
TeamModel(
|
|
271
|
+
id=str(team.id),
|
|
272
|
+
name=team.name,
|
|
273
|
+
description=team.description,
|
|
274
|
+
status=team.status,
|
|
275
|
+
agent_count=len(member_ids),
|
|
276
|
+
)
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
# Convert to dict for formatting
|
|
280
|
+
matching_dicts = [model.model_dump() for model in matching_teams]
|
|
281
|
+
|
|
282
|
+
return self._format_list_response(
|
|
283
|
+
items=matching_dicts,
|
|
284
|
+
title=f"Teams with '{capability}' capability",
|
|
285
|
+
key_fields=["description", "agent_count"],
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
except Exception as e:
|
|
289
|
+
return f"Error searching teams: {str(e)}"
|
|
290
|
+
|
|
291
|
+
async def get_team_execution_history(self, team_id: str, limit: int = 10) -> str:
|
|
292
|
+
"""
|
|
293
|
+
Get recent execution history for a team
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
team_id: ID of the team
|
|
297
|
+
limit: Number of recent executions to fetch
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
Recent execution history with success rates
|
|
301
|
+
"""
|
|
302
|
+
try:
|
|
303
|
+
# Use Supabase for execution history
|
|
304
|
+
client = get_supabase()
|
|
305
|
+
|
|
306
|
+
query = client.table("executions").select("*").eq("entity_id", team_id).eq("execution_type", "TEAM")
|
|
307
|
+
if self.organization_id:
|
|
308
|
+
query = query.eq("organization_id", self.organization_id)
|
|
309
|
+
|
|
310
|
+
result = query.order("created_at", desc=True).limit(limit).execute()
|
|
311
|
+
executions = result.data or []
|
|
312
|
+
|
|
313
|
+
if not executions:
|
|
314
|
+
return f"No execution history found for team {team_id}"
|
|
315
|
+
|
|
316
|
+
completed = sum(1 for e in executions if e.get("status") == "completed")
|
|
317
|
+
total = len(executions)
|
|
318
|
+
success_rate = (completed / total * 100) if total > 0 else 0
|
|
319
|
+
|
|
320
|
+
output = [
|
|
321
|
+
f"Execution History for Team (Last {total} runs):",
|
|
322
|
+
f"Success Rate: {success_rate:.1f}% ({completed}/{total})",
|
|
323
|
+
"\nRecent Executions:",
|
|
324
|
+
]
|
|
325
|
+
|
|
326
|
+
for idx, execution in enumerate(executions[:5], 1):
|
|
327
|
+
status = execution.get("status", "unknown")
|
|
328
|
+
prompt = execution.get("prompt", "No description")[:50]
|
|
329
|
+
output.append(f"{idx}. Status: {status} | Task: {prompt}...")
|
|
330
|
+
|
|
331
|
+
return "\n".join(output)
|
|
332
|
+
|
|
333
|
+
except Exception as e:
|
|
334
|
+
return f"Error fetching execution history: {str(e)}"
|