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.
Files changed (479) hide show
  1. control_plane_api/LICENSE +676 -0
  2. control_plane_api/README.md +350 -0
  3. control_plane_api/__init__.py +4 -0
  4. control_plane_api/__version__.py +8 -0
  5. control_plane_api/alembic/README +1 -0
  6. control_plane_api/alembic/env.py +121 -0
  7. control_plane_api/alembic/script.py.mako +28 -0
  8. control_plane_api/alembic/versions/2613c65c3dbe_initial_database_setup.py +32 -0
  9. control_plane_api/alembic/versions/2df520d4927d_merge_heads.py +28 -0
  10. control_plane_api/alembic/versions/43abf98d6a01_add_paused_status_to_executions.py +73 -0
  11. control_plane_api/alembic/versions/6289854264cb_merge_multiple_heads.py +28 -0
  12. control_plane_api/alembic/versions/6a4d4dc3d8dc_generate_execution_transitions.py +50 -0
  13. control_plane_api/alembic/versions/87d11cf0a783_add_disconnected_status_to_worker_.py +44 -0
  14. control_plane_api/alembic/versions/add_ephemeral_queue_support.py +85 -0
  15. control_plane_api/alembic/versions/add_model_type_to_llm_models.py +31 -0
  16. control_plane_api/alembic/versions/add_plan_executions_table.py +114 -0
  17. control_plane_api/alembic/versions/add_trace_span_tables.py +154 -0
  18. control_plane_api/alembic/versions/add_user_info_to_traces.py +36 -0
  19. control_plane_api/alembic/versions/adjusting_foreign_keys.py +32 -0
  20. control_plane_api/alembic/versions/b4983d976db2_initial_tables.py +1128 -0
  21. control_plane_api/alembic/versions/d181a3b40e71_rename_custom_metadata_to_metadata_in_.py +50 -0
  22. control_plane_api/alembic/versions/df9117888e82_add_missing_columns.py +82 -0
  23. control_plane_api/alembic/versions/f25de6ad895a_missing_migrations.py +34 -0
  24. control_plane_api/alembic/versions/f71305fb69b9_fix_ephemeral_queue_deletion_foreign_key.py +54 -0
  25. control_plane_api/alembic/versions/mark_local_exec_queues_as_ephemeral.py +68 -0
  26. control_plane_api/alembic.ini +148 -0
  27. control_plane_api/api/index.py +12 -0
  28. control_plane_api/app/__init__.py +11 -0
  29. control_plane_api/app/activities/__init__.py +20 -0
  30. control_plane_api/app/activities/agent_activities.py +384 -0
  31. control_plane_api/app/activities/plan_generation_activities.py +499 -0
  32. control_plane_api/app/activities/team_activities.py +424 -0
  33. control_plane_api/app/activities/temporal_cloud_activities.py +588 -0
  34. control_plane_api/app/config/__init__.py +35 -0
  35. control_plane_api/app/config/api_config.py +469 -0
  36. control_plane_api/app/config/config_loader.py +224 -0
  37. control_plane_api/app/config/model_pricing.py +323 -0
  38. control_plane_api/app/config/storage_config.py +159 -0
  39. control_plane_api/app/config.py +115 -0
  40. control_plane_api/app/controllers/__init__.py +0 -0
  41. control_plane_api/app/controllers/execution_environment_controller.py +1315 -0
  42. control_plane_api/app/database.py +135 -0
  43. control_plane_api/app/exceptions.py +408 -0
  44. control_plane_api/app/lib/__init__.py +11 -0
  45. control_plane_api/app/lib/environment.py +65 -0
  46. control_plane_api/app/lib/event_bus/__init__.py +17 -0
  47. control_plane_api/app/lib/event_bus/base.py +136 -0
  48. control_plane_api/app/lib/event_bus/manager.py +335 -0
  49. control_plane_api/app/lib/event_bus/providers/__init__.py +6 -0
  50. control_plane_api/app/lib/event_bus/providers/http_provider.py +166 -0
  51. control_plane_api/app/lib/event_bus/providers/nats_provider.py +324 -0
  52. control_plane_api/app/lib/event_bus/providers/redis_provider.py +233 -0
  53. control_plane_api/app/lib/event_bus/providers/websocket_provider.py +497 -0
  54. control_plane_api/app/lib/job_executor.py +330 -0
  55. control_plane_api/app/lib/kubiya_client.py +293 -0
  56. control_plane_api/app/lib/litellm_pricing.py +166 -0
  57. control_plane_api/app/lib/mcp_validation.py +163 -0
  58. control_plane_api/app/lib/nats/__init__.py +13 -0
  59. control_plane_api/app/lib/nats/credentials_manager.py +288 -0
  60. control_plane_api/app/lib/nats/listener.py +374 -0
  61. control_plane_api/app/lib/planning_prompt_builder.py +153 -0
  62. control_plane_api/app/lib/planning_tools/__init__.py +41 -0
  63. control_plane_api/app/lib/planning_tools/agents.py +409 -0
  64. control_plane_api/app/lib/planning_tools/agno_toolkit.py +836 -0
  65. control_plane_api/app/lib/planning_tools/base.py +119 -0
  66. control_plane_api/app/lib/planning_tools/cognitive_memory_tools.py +403 -0
  67. control_plane_api/app/lib/planning_tools/context_graph_tools.py +545 -0
  68. control_plane_api/app/lib/planning_tools/environments.py +218 -0
  69. control_plane_api/app/lib/planning_tools/knowledge.py +204 -0
  70. control_plane_api/app/lib/planning_tools/models.py +93 -0
  71. control_plane_api/app/lib/planning_tools/planning_service.py +646 -0
  72. control_plane_api/app/lib/planning_tools/resources.py +242 -0
  73. control_plane_api/app/lib/planning_tools/teams.py +334 -0
  74. control_plane_api/app/lib/policy_enforcer_client.py +1016 -0
  75. control_plane_api/app/lib/redis_client.py +803 -0
  76. control_plane_api/app/lib/sqlalchemy_utils.py +486 -0
  77. control_plane_api/app/lib/state_transition_tools/__init__.py +7 -0
  78. control_plane_api/app/lib/state_transition_tools/execution_context.py +388 -0
  79. control_plane_api/app/lib/storage/__init__.py +20 -0
  80. control_plane_api/app/lib/storage/base_provider.py +274 -0
  81. control_plane_api/app/lib/storage/provider_factory.py +157 -0
  82. control_plane_api/app/lib/storage/vercel_blob_provider.py +468 -0
  83. control_plane_api/app/lib/supabase.py +71 -0
  84. control_plane_api/app/lib/supabase_utils.py +138 -0
  85. control_plane_api/app/lib/task_planning/__init__.py +138 -0
  86. control_plane_api/app/lib/task_planning/agent_factory.py +308 -0
  87. control_plane_api/app/lib/task_planning/agents.py +389 -0
  88. control_plane_api/app/lib/task_planning/cache.py +218 -0
  89. control_plane_api/app/lib/task_planning/entity_resolver.py +273 -0
  90. control_plane_api/app/lib/task_planning/helpers.py +293 -0
  91. control_plane_api/app/lib/task_planning/hooks.py +474 -0
  92. control_plane_api/app/lib/task_planning/models.py +503 -0
  93. control_plane_api/app/lib/task_planning/plan_validator.py +166 -0
  94. control_plane_api/app/lib/task_planning/planning_workflow.py +2911 -0
  95. control_plane_api/app/lib/task_planning/runner.py +656 -0
  96. control_plane_api/app/lib/task_planning/streaming_hook.py +213 -0
  97. control_plane_api/app/lib/task_planning/workflow.py +424 -0
  98. control_plane_api/app/lib/templating/__init__.py +88 -0
  99. control_plane_api/app/lib/templating/compiler.py +278 -0
  100. control_plane_api/app/lib/templating/engine.py +178 -0
  101. control_plane_api/app/lib/templating/parsers/__init__.py +29 -0
  102. control_plane_api/app/lib/templating/parsers/base.py +96 -0
  103. control_plane_api/app/lib/templating/parsers/env.py +85 -0
  104. control_plane_api/app/lib/templating/parsers/graph.py +112 -0
  105. control_plane_api/app/lib/templating/parsers/secret.py +87 -0
  106. control_plane_api/app/lib/templating/parsers/simple.py +81 -0
  107. control_plane_api/app/lib/templating/resolver.py +366 -0
  108. control_plane_api/app/lib/templating/types.py +214 -0
  109. control_plane_api/app/lib/templating/validator.py +201 -0
  110. control_plane_api/app/lib/temporal_client.py +232 -0
  111. control_plane_api/app/lib/temporal_credentials_cache.py +178 -0
  112. control_plane_api/app/lib/temporal_credentials_service.py +203 -0
  113. control_plane_api/app/lib/validation/__init__.py +24 -0
  114. control_plane_api/app/lib/validation/runtime_validation.py +388 -0
  115. control_plane_api/app/main.py +531 -0
  116. control_plane_api/app/middleware/__init__.py +10 -0
  117. control_plane_api/app/middleware/auth.py +645 -0
  118. control_plane_api/app/middleware/exception_handler.py +267 -0
  119. control_plane_api/app/middleware/prometheus_middleware.py +173 -0
  120. control_plane_api/app/middleware/rate_limiting.py +384 -0
  121. control_plane_api/app/middleware/request_id.py +202 -0
  122. control_plane_api/app/models/__init__.py +40 -0
  123. control_plane_api/app/models/agent.py +90 -0
  124. control_plane_api/app/models/analytics.py +206 -0
  125. control_plane_api/app/models/associations.py +107 -0
  126. control_plane_api/app/models/auth_user.py +73 -0
  127. control_plane_api/app/models/context.py +161 -0
  128. control_plane_api/app/models/custom_integration.py +99 -0
  129. control_plane_api/app/models/environment.py +64 -0
  130. control_plane_api/app/models/execution.py +125 -0
  131. control_plane_api/app/models/execution_transition.py +50 -0
  132. control_plane_api/app/models/job.py +159 -0
  133. control_plane_api/app/models/llm_model.py +78 -0
  134. control_plane_api/app/models/orchestration.py +66 -0
  135. control_plane_api/app/models/plan_execution.py +102 -0
  136. control_plane_api/app/models/presence.py +49 -0
  137. control_plane_api/app/models/project.py +61 -0
  138. control_plane_api/app/models/project_management.py +85 -0
  139. control_plane_api/app/models/session.py +29 -0
  140. control_plane_api/app/models/skill.py +155 -0
  141. control_plane_api/app/models/system_tables.py +43 -0
  142. control_plane_api/app/models/task_planning.py +372 -0
  143. control_plane_api/app/models/team.py +86 -0
  144. control_plane_api/app/models/trace.py +257 -0
  145. control_plane_api/app/models/user_profile.py +54 -0
  146. control_plane_api/app/models/worker.py +221 -0
  147. control_plane_api/app/models/workflow.py +161 -0
  148. control_plane_api/app/models/workspace.py +50 -0
  149. control_plane_api/app/observability/__init__.py +177 -0
  150. control_plane_api/app/observability/context_logging.py +475 -0
  151. control_plane_api/app/observability/decorators.py +337 -0
  152. control_plane_api/app/observability/local_span_processor.py +702 -0
  153. control_plane_api/app/observability/metrics.py +303 -0
  154. control_plane_api/app/observability/middleware.py +246 -0
  155. control_plane_api/app/observability/optional.py +115 -0
  156. control_plane_api/app/observability/tracing.py +382 -0
  157. control_plane_api/app/policies/README.md +149 -0
  158. control_plane_api/app/policies/approved_users.rego +62 -0
  159. control_plane_api/app/policies/business_hours.rego +51 -0
  160. control_plane_api/app/policies/rate_limiting.rego +100 -0
  161. control_plane_api/app/policies/tool_enforcement/README.md +336 -0
  162. control_plane_api/app/policies/tool_enforcement/bash_command_validation.rego +71 -0
  163. control_plane_api/app/policies/tool_enforcement/business_hours_enforcement.rego +82 -0
  164. control_plane_api/app/policies/tool_enforcement/mcp_tool_allowlist.rego +58 -0
  165. control_plane_api/app/policies/tool_enforcement/production_safeguards.rego +80 -0
  166. control_plane_api/app/policies/tool_enforcement/role_based_tool_access.rego +44 -0
  167. control_plane_api/app/policies/tool_restrictions.rego +86 -0
  168. control_plane_api/app/routers/__init__.py +4 -0
  169. control_plane_api/app/routers/agents.py +382 -0
  170. control_plane_api/app/routers/agents_v2.py +1598 -0
  171. control_plane_api/app/routers/analytics.py +1310 -0
  172. control_plane_api/app/routers/auth.py +59 -0
  173. control_plane_api/app/routers/client_config.py +57 -0
  174. control_plane_api/app/routers/context_graph.py +561 -0
  175. control_plane_api/app/routers/context_manager.py +577 -0
  176. control_plane_api/app/routers/custom_integrations.py +490 -0
  177. control_plane_api/app/routers/enforcer.py +132 -0
  178. control_plane_api/app/routers/environment_context.py +252 -0
  179. control_plane_api/app/routers/environments.py +761 -0
  180. control_plane_api/app/routers/execution_environment.py +847 -0
  181. control_plane_api/app/routers/executions/__init__.py +28 -0
  182. control_plane_api/app/routers/executions/router.py +286 -0
  183. control_plane_api/app/routers/executions/services/__init__.py +22 -0
  184. control_plane_api/app/routers/executions/services/demo_worker_health.py +156 -0
  185. control_plane_api/app/routers/executions/services/status_service.py +420 -0
  186. control_plane_api/app/routers/executions/services/test_worker_health.py +480 -0
  187. control_plane_api/app/routers/executions/services/worker_health.py +514 -0
  188. control_plane_api/app/routers/executions/streaming/__init__.py +22 -0
  189. control_plane_api/app/routers/executions/streaming/deduplication.py +352 -0
  190. control_plane_api/app/routers/executions/streaming/event_buffer.py +353 -0
  191. control_plane_api/app/routers/executions/streaming/event_formatter.py +964 -0
  192. control_plane_api/app/routers/executions/streaming/history_loader.py +588 -0
  193. control_plane_api/app/routers/executions/streaming/live_source.py +693 -0
  194. control_plane_api/app/routers/executions/streaming/streamer.py +849 -0
  195. control_plane_api/app/routers/executions.py +4888 -0
  196. control_plane_api/app/routers/health.py +165 -0
  197. control_plane_api/app/routers/health_v2.py +394 -0
  198. control_plane_api/app/routers/integration_templates.py +496 -0
  199. control_plane_api/app/routers/integrations.py +287 -0
  200. control_plane_api/app/routers/jobs.py +1809 -0
  201. control_plane_api/app/routers/metrics.py +517 -0
  202. control_plane_api/app/routers/models.py +82 -0
  203. control_plane_api/app/routers/models_v2.py +628 -0
  204. control_plane_api/app/routers/plan_executions.py +1481 -0
  205. control_plane_api/app/routers/plan_generation_async.py +304 -0
  206. control_plane_api/app/routers/policies.py +669 -0
  207. control_plane_api/app/routers/presence.py +234 -0
  208. control_plane_api/app/routers/projects.py +987 -0
  209. control_plane_api/app/routers/runners.py +379 -0
  210. control_plane_api/app/routers/runtimes.py +172 -0
  211. control_plane_api/app/routers/secrets.py +171 -0
  212. control_plane_api/app/routers/skills.py +1010 -0
  213. control_plane_api/app/routers/skills_definitions.py +140 -0
  214. control_plane_api/app/routers/storage.py +456 -0
  215. control_plane_api/app/routers/task_planning.py +611 -0
  216. control_plane_api/app/routers/task_queues.py +650 -0
  217. control_plane_api/app/routers/team_context.py +274 -0
  218. control_plane_api/app/routers/teams.py +1747 -0
  219. control_plane_api/app/routers/templates.py +248 -0
  220. control_plane_api/app/routers/traces.py +571 -0
  221. control_plane_api/app/routers/websocket_client.py +479 -0
  222. control_plane_api/app/routers/websocket_executions_status.py +437 -0
  223. control_plane_api/app/routers/websocket_gateway.py +323 -0
  224. control_plane_api/app/routers/websocket_traces.py +576 -0
  225. control_plane_api/app/routers/worker_queues.py +2555 -0
  226. control_plane_api/app/routers/worker_websocket.py +419 -0
  227. control_plane_api/app/routers/workers.py +1004 -0
  228. control_plane_api/app/routers/workflows.py +204 -0
  229. control_plane_api/app/runtimes/__init__.py +6 -0
  230. control_plane_api/app/runtimes/validation.py +344 -0
  231. control_plane_api/app/schemas/__init__.py +1 -0
  232. control_plane_api/app/schemas/job_schemas.py +302 -0
  233. control_plane_api/app/schemas/mcp_schemas.py +311 -0
  234. control_plane_api/app/schemas/template_schemas.py +133 -0
  235. control_plane_api/app/schemas/trace_schemas.py +168 -0
  236. control_plane_api/app/schemas/worker_queue_observability_schemas.py +165 -0
  237. control_plane_api/app/services/__init__.py +1 -0
  238. control_plane_api/app/services/agno_planning_strategy.py +233 -0
  239. control_plane_api/app/services/agno_service.py +838 -0
  240. control_plane_api/app/services/claude_code_planning_service.py +203 -0
  241. control_plane_api/app/services/context_graph_client.py +224 -0
  242. control_plane_api/app/services/custom_integration_service.py +415 -0
  243. control_plane_api/app/services/integration_resolution_service.py +345 -0
  244. control_plane_api/app/services/litellm_service.py +394 -0
  245. control_plane_api/app/services/plan_generator.py +79 -0
  246. control_plane_api/app/services/planning_strategy.py +66 -0
  247. control_plane_api/app/services/planning_strategy_factory.py +118 -0
  248. control_plane_api/app/services/policy_service.py +615 -0
  249. control_plane_api/app/services/state_transition_service.py +755 -0
  250. control_plane_api/app/services/storage_service.py +593 -0
  251. control_plane_api/app/services/temporal_cloud_provisioning.py +150 -0
  252. control_plane_api/app/services/toolsets/context_graph_skill.py +432 -0
  253. control_plane_api/app/services/trace_retention.py +354 -0
  254. control_plane_api/app/services/worker_queue_metrics_service.py +190 -0
  255. control_plane_api/app/services/workflow_cancellation_manager.py +135 -0
  256. control_plane_api/app/services/workflow_operations_service.py +611 -0
  257. control_plane_api/app/skills/__init__.py +100 -0
  258. control_plane_api/app/skills/base.py +239 -0
  259. control_plane_api/app/skills/builtin/__init__.py +37 -0
  260. control_plane_api/app/skills/builtin/agent_communication/__init__.py +8 -0
  261. control_plane_api/app/skills/builtin/agent_communication/skill.py +246 -0
  262. control_plane_api/app/skills/builtin/code_ingestion/__init__.py +4 -0
  263. control_plane_api/app/skills/builtin/code_ingestion/skill.py +267 -0
  264. control_plane_api/app/skills/builtin/cognitive_memory/__init__.py +4 -0
  265. control_plane_api/app/skills/builtin/cognitive_memory/skill.py +174 -0
  266. control_plane_api/app/skills/builtin/contextual_awareness/__init__.py +4 -0
  267. control_plane_api/app/skills/builtin/contextual_awareness/skill.py +387 -0
  268. control_plane_api/app/skills/builtin/data_visualization/__init__.py +4 -0
  269. control_plane_api/app/skills/builtin/data_visualization/skill.py +154 -0
  270. control_plane_api/app/skills/builtin/docker/__init__.py +4 -0
  271. control_plane_api/app/skills/builtin/docker/skill.py +104 -0
  272. control_plane_api/app/skills/builtin/file_generation/__init__.py +4 -0
  273. control_plane_api/app/skills/builtin/file_generation/skill.py +94 -0
  274. control_plane_api/app/skills/builtin/file_system/__init__.py +4 -0
  275. control_plane_api/app/skills/builtin/file_system/skill.py +110 -0
  276. control_plane_api/app/skills/builtin/knowledge_api/__init__.py +5 -0
  277. control_plane_api/app/skills/builtin/knowledge_api/skill.py +124 -0
  278. control_plane_api/app/skills/builtin/python/__init__.py +4 -0
  279. control_plane_api/app/skills/builtin/python/skill.py +92 -0
  280. control_plane_api/app/skills/builtin/remote_filesystem/__init__.py +5 -0
  281. control_plane_api/app/skills/builtin/remote_filesystem/skill.py +170 -0
  282. control_plane_api/app/skills/builtin/shell/__init__.py +4 -0
  283. control_plane_api/app/skills/builtin/shell/skill.py +161 -0
  284. control_plane_api/app/skills/builtin/slack/__init__.py +3 -0
  285. control_plane_api/app/skills/builtin/slack/skill.py +302 -0
  286. control_plane_api/app/skills/builtin/workflow_executor/__init__.py +4 -0
  287. control_plane_api/app/skills/builtin/workflow_executor/skill.py +469 -0
  288. control_plane_api/app/skills/business_intelligence.py +189 -0
  289. control_plane_api/app/skills/config.py +63 -0
  290. control_plane_api/app/skills/loaders/__init__.py +14 -0
  291. control_plane_api/app/skills/loaders/base.py +73 -0
  292. control_plane_api/app/skills/loaders/filesystem_loader.py +199 -0
  293. control_plane_api/app/skills/registry.py +125 -0
  294. control_plane_api/app/utils/helpers.py +12 -0
  295. control_plane_api/app/utils/workflow_executor.py +354 -0
  296. control_plane_api/app/workflows/__init__.py +11 -0
  297. control_plane_api/app/workflows/agent_execution.py +520 -0
  298. control_plane_api/app/workflows/agent_execution_with_skills.py +223 -0
  299. control_plane_api/app/workflows/namespace_provisioning.py +326 -0
  300. control_plane_api/app/workflows/plan_generation.py +254 -0
  301. control_plane_api/app/workflows/team_execution.py +442 -0
  302. control_plane_api/scripts/seed_models.py +240 -0
  303. control_plane_api/scripts/validate_existing_tool_names.py +492 -0
  304. control_plane_api/shared/__init__.py +8 -0
  305. control_plane_api/shared/version.py +17 -0
  306. control_plane_api/test_deduplication.py +274 -0
  307. control_plane_api/test_executor_deduplication_e2e.py +309 -0
  308. control_plane_api/test_job_execution_e2e.py +283 -0
  309. control_plane_api/test_real_integration.py +193 -0
  310. control_plane_api/version.py +38 -0
  311. control_plane_api/worker/__init__.py +0 -0
  312. control_plane_api/worker/activities/__init__.py +0 -0
  313. control_plane_api/worker/activities/agent_activities.py +1585 -0
  314. control_plane_api/worker/activities/approval_activities.py +234 -0
  315. control_plane_api/worker/activities/job_activities.py +199 -0
  316. control_plane_api/worker/activities/runtime_activities.py +1167 -0
  317. control_plane_api/worker/activities/skill_activities.py +282 -0
  318. control_plane_api/worker/activities/team_activities.py +479 -0
  319. control_plane_api/worker/agent_runtime_server.py +370 -0
  320. control_plane_api/worker/binary_manager.py +333 -0
  321. control_plane_api/worker/config/__init__.py +31 -0
  322. control_plane_api/worker/config/worker_config.py +273 -0
  323. control_plane_api/worker/control_plane_client.py +1491 -0
  324. control_plane_api/worker/examples/analytics_integration_example.py +362 -0
  325. control_plane_api/worker/health_monitor.py +159 -0
  326. control_plane_api/worker/metrics.py +237 -0
  327. control_plane_api/worker/models/__init__.py +1 -0
  328. control_plane_api/worker/models/error_events.py +105 -0
  329. control_plane_api/worker/models/inputs.py +89 -0
  330. control_plane_api/worker/runtimes/__init__.py +35 -0
  331. control_plane_api/worker/runtimes/agent_runtime/runtime.py +485 -0
  332. control_plane_api/worker/runtimes/agno/__init__.py +34 -0
  333. control_plane_api/worker/runtimes/agno/config.py +248 -0
  334. control_plane_api/worker/runtimes/agno/hooks.py +385 -0
  335. control_plane_api/worker/runtimes/agno/mcp_builder.py +195 -0
  336. control_plane_api/worker/runtimes/agno/runtime.py +1063 -0
  337. control_plane_api/worker/runtimes/agno/utils.py +163 -0
  338. control_plane_api/worker/runtimes/base.py +979 -0
  339. control_plane_api/worker/runtimes/claude_code/__init__.py +38 -0
  340. control_plane_api/worker/runtimes/claude_code/cleanup.py +184 -0
  341. control_plane_api/worker/runtimes/claude_code/client_pool.py +529 -0
  342. control_plane_api/worker/runtimes/claude_code/config.py +829 -0
  343. control_plane_api/worker/runtimes/claude_code/hooks.py +482 -0
  344. control_plane_api/worker/runtimes/claude_code/litellm_proxy.py +1702 -0
  345. control_plane_api/worker/runtimes/claude_code/mcp_builder.py +467 -0
  346. control_plane_api/worker/runtimes/claude_code/mcp_discovery.py +558 -0
  347. control_plane_api/worker/runtimes/claude_code/runtime.py +1546 -0
  348. control_plane_api/worker/runtimes/claude_code/tool_mapper.py +403 -0
  349. control_plane_api/worker/runtimes/claude_code/utils.py +149 -0
  350. control_plane_api/worker/runtimes/factory.py +173 -0
  351. control_plane_api/worker/runtimes/model_utils.py +107 -0
  352. control_plane_api/worker/runtimes/validation.py +93 -0
  353. control_plane_api/worker/services/__init__.py +1 -0
  354. control_plane_api/worker/services/agent_communication_tools.py +908 -0
  355. control_plane_api/worker/services/agent_executor.py +485 -0
  356. control_plane_api/worker/services/agent_executor_v2.py +793 -0
  357. control_plane_api/worker/services/analytics_collector.py +457 -0
  358. control_plane_api/worker/services/analytics_service.py +464 -0
  359. control_plane_api/worker/services/approval_tools.py +310 -0
  360. control_plane_api/worker/services/approval_tools_agno.py +207 -0
  361. control_plane_api/worker/services/cancellation_manager.py +177 -0
  362. control_plane_api/worker/services/code_ingestion_tools.py +465 -0
  363. control_plane_api/worker/services/contextual_awareness_tools.py +405 -0
  364. control_plane_api/worker/services/data_visualization.py +834 -0
  365. control_plane_api/worker/services/event_publisher.py +531 -0
  366. control_plane_api/worker/services/jira_tools.py +257 -0
  367. control_plane_api/worker/services/remote_filesystem_tools.py +498 -0
  368. control_plane_api/worker/services/runtime_analytics.py +328 -0
  369. control_plane_api/worker/services/session_service.py +365 -0
  370. control_plane_api/worker/services/skill_context_enhancement.py +181 -0
  371. control_plane_api/worker/services/skill_factory.py +471 -0
  372. control_plane_api/worker/services/system_prompt_enhancement.py +410 -0
  373. control_plane_api/worker/services/team_executor.py +715 -0
  374. control_plane_api/worker/services/team_executor_v2.py +1866 -0
  375. control_plane_api/worker/services/tool_enforcement.py +254 -0
  376. control_plane_api/worker/services/workflow_executor/__init__.py +52 -0
  377. control_plane_api/worker/services/workflow_executor/event_processor.py +287 -0
  378. control_plane_api/worker/services/workflow_executor/event_publisher.py +210 -0
  379. control_plane_api/worker/services/workflow_executor/executors/__init__.py +15 -0
  380. control_plane_api/worker/services/workflow_executor/executors/base.py +270 -0
  381. control_plane_api/worker/services/workflow_executor/executors/json_executor.py +50 -0
  382. control_plane_api/worker/services/workflow_executor/executors/python_executor.py +50 -0
  383. control_plane_api/worker/services/workflow_executor/models.py +142 -0
  384. control_plane_api/worker/services/workflow_executor_tools.py +1748 -0
  385. control_plane_api/worker/skills/__init__.py +12 -0
  386. control_plane_api/worker/skills/builtin/context_graph_search/README.md +213 -0
  387. control_plane_api/worker/skills/builtin/context_graph_search/__init__.py +5 -0
  388. control_plane_api/worker/skills/builtin/context_graph_search/agno_impl.py +808 -0
  389. control_plane_api/worker/skills/builtin/context_graph_search/skill.yaml +67 -0
  390. control_plane_api/worker/skills/builtin/contextual_awareness/__init__.py +4 -0
  391. control_plane_api/worker/skills/builtin/contextual_awareness/agno_impl.py +62 -0
  392. control_plane_api/worker/skills/builtin/data_visualization/agno_impl.py +18 -0
  393. control_plane_api/worker/skills/builtin/data_visualization/skill.yaml +84 -0
  394. control_plane_api/worker/skills/builtin/docker/agno_impl.py +65 -0
  395. control_plane_api/worker/skills/builtin/docker/skill.yaml +60 -0
  396. control_plane_api/worker/skills/builtin/file_generation/agno_impl.py +47 -0
  397. control_plane_api/worker/skills/builtin/file_generation/skill.yaml +64 -0
  398. control_plane_api/worker/skills/builtin/file_system/agno_impl.py +32 -0
  399. control_plane_api/worker/skills/builtin/file_system/skill.yaml +54 -0
  400. control_plane_api/worker/skills/builtin/knowledge_api/__init__.py +4 -0
  401. control_plane_api/worker/skills/builtin/knowledge_api/agno_impl.py +50 -0
  402. control_plane_api/worker/skills/builtin/knowledge_api/skill.yaml +66 -0
  403. control_plane_api/worker/skills/builtin/python/agno_impl.py +25 -0
  404. control_plane_api/worker/skills/builtin/python/skill.yaml +60 -0
  405. control_plane_api/worker/skills/builtin/schema_fix_mixin.py +260 -0
  406. control_plane_api/worker/skills/builtin/shell/agno_impl.py +31 -0
  407. control_plane_api/worker/skills/builtin/shell/skill.yaml +60 -0
  408. control_plane_api/worker/skills/builtin/slack/__init__.py +3 -0
  409. control_plane_api/worker/skills/builtin/slack/agno_impl.py +1282 -0
  410. control_plane_api/worker/skills/builtin/slack/skill.yaml +276 -0
  411. control_plane_api/worker/skills/builtin/workflow_executor/agno_impl.py +62 -0
  412. control_plane_api/worker/skills/builtin/workflow_executor/skill.yaml +79 -0
  413. control_plane_api/worker/skills/loaders/__init__.py +5 -0
  414. control_plane_api/worker/skills/loaders/base.py +23 -0
  415. control_plane_api/worker/skills/loaders/filesystem_loader.py +357 -0
  416. control_plane_api/worker/skills/registry.py +208 -0
  417. control_plane_api/worker/tests/__init__.py +1 -0
  418. control_plane_api/worker/tests/conftest.py +12 -0
  419. control_plane_api/worker/tests/e2e/__init__.py +0 -0
  420. control_plane_api/worker/tests/e2e/test_context_graph_real_api.py +338 -0
  421. control_plane_api/worker/tests/e2e/test_context_graph_templates_e2e.py +523 -0
  422. control_plane_api/worker/tests/e2e/test_enforcement_e2e.py +344 -0
  423. control_plane_api/worker/tests/e2e/test_execution_flow.py +571 -0
  424. control_plane_api/worker/tests/e2e/test_single_execution_mode.py +656 -0
  425. control_plane_api/worker/tests/integration/__init__.py +0 -0
  426. control_plane_api/worker/tests/integration/test_builtin_skills_fixes.py +245 -0
  427. control_plane_api/worker/tests/integration/test_context_graph_search_integration.py +365 -0
  428. control_plane_api/worker/tests/integration/test_control_plane_integration.py +308 -0
  429. control_plane_api/worker/tests/integration/test_hook_enforcement_integration.py +579 -0
  430. control_plane_api/worker/tests/integration/test_scheduled_job_workflow.py +237 -0
  431. control_plane_api/worker/tests/integration/test_system_prompt_enhancement_integration.py +343 -0
  432. control_plane_api/worker/tests/unit/__init__.py +0 -0
  433. control_plane_api/worker/tests/unit/test_builtin_skill_autoload.py +396 -0
  434. control_plane_api/worker/tests/unit/test_context_graph_search.py +450 -0
  435. control_plane_api/worker/tests/unit/test_context_graph_templates.py +403 -0
  436. control_plane_api/worker/tests/unit/test_control_plane_client.py +401 -0
  437. control_plane_api/worker/tests/unit/test_control_plane_client_jobs.py +345 -0
  438. control_plane_api/worker/tests/unit/test_job_activities.py +353 -0
  439. control_plane_api/worker/tests/unit/test_skill_context_enhancement.py +321 -0
  440. control_plane_api/worker/tests/unit/test_system_prompt_enhancement.py +415 -0
  441. control_plane_api/worker/tests/unit/test_tool_enforcement.py +324 -0
  442. control_plane_api/worker/utils/__init__.py +1 -0
  443. control_plane_api/worker/utils/chunk_batcher.py +330 -0
  444. control_plane_api/worker/utils/environment.py +65 -0
  445. control_plane_api/worker/utils/error_publisher.py +260 -0
  446. control_plane_api/worker/utils/event_batcher.py +256 -0
  447. control_plane_api/worker/utils/logging_config.py +335 -0
  448. control_plane_api/worker/utils/logging_helper.py +326 -0
  449. control_plane_api/worker/utils/parameter_validator.py +120 -0
  450. control_plane_api/worker/utils/retry_utils.py +60 -0
  451. control_plane_api/worker/utils/streaming_utils.py +665 -0
  452. control_plane_api/worker/utils/tool_validation.py +332 -0
  453. control_plane_api/worker/utils/workspace_manager.py +163 -0
  454. control_plane_api/worker/websocket_client.py +393 -0
  455. control_plane_api/worker/worker.py +1297 -0
  456. control_plane_api/worker/workflows/__init__.py +0 -0
  457. control_plane_api/worker/workflows/agent_execution.py +909 -0
  458. control_plane_api/worker/workflows/scheduled_job_wrapper.py +332 -0
  459. control_plane_api/worker/workflows/team_execution.py +611 -0
  460. kubiya_control_plane_api-0.9.15.dist-info/METADATA +354 -0
  461. kubiya_control_plane_api-0.9.15.dist-info/RECORD +479 -0
  462. kubiya_control_plane_api-0.9.15.dist-info/WHEEL +5 -0
  463. kubiya_control_plane_api-0.9.15.dist-info/entry_points.txt +5 -0
  464. kubiya_control_plane_api-0.9.15.dist-info/licenses/LICENSE +676 -0
  465. kubiya_control_plane_api-0.9.15.dist-info/top_level.txt +3 -0
  466. scripts/__init__.py +1 -0
  467. scripts/migrations.py +39 -0
  468. scripts/seed_worker_queues.py +128 -0
  469. scripts/setup_agent_runtime.py +142 -0
  470. worker_internal/__init__.py +1 -0
  471. worker_internal/planner/__init__.py +1 -0
  472. worker_internal/planner/activities.py +1499 -0
  473. worker_internal/planner/agent_tools.py +197 -0
  474. worker_internal/planner/event_models.py +148 -0
  475. worker_internal/planner/event_publisher.py +67 -0
  476. worker_internal/planner/models.py +199 -0
  477. worker_internal/planner/retry_logic.py +134 -0
  478. worker_internal/planner/worker.py +300 -0
  479. 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)}"