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,204 @@
1
+ from fastapi import APIRouter, Depends, HTTPException, status
2
+ from sqlalchemy.orm import Session
3
+ from typing import List
4
+ from datetime import datetime
5
+
6
+ from control_plane_api.app.database import get_db
7
+ from control_plane_api.app.models.workflow import Workflow, WorkflowStatus
8
+ from pydantic import BaseModel, Field
9
+
10
+ router = APIRouter()
11
+
12
+
13
+ # Pydantic schemas
14
+ class WorkflowCreate(BaseModel):
15
+ name: str = Field(..., description="Workflow name")
16
+ description: str | None = Field(None, description="Workflow description")
17
+ steps: list = Field(default_factory=list, description="Workflow steps")
18
+ configuration: dict = Field(default_factory=dict, description="Workflow configuration")
19
+ team_id: str | None = Field(None, description="Team ID")
20
+
21
+
22
+ class WorkflowUpdate(BaseModel):
23
+ name: str | None = None
24
+ description: str | None = None
25
+ status: WorkflowStatus | None = None
26
+ steps: list | None = None
27
+ current_step: str | None = None
28
+ configuration: dict | None = None
29
+ state: dict | None = None
30
+
31
+
32
+ class WorkflowResponse(BaseModel):
33
+ id: str
34
+ name: str
35
+ description: str | None
36
+ status: WorkflowStatus
37
+ steps: list
38
+ current_step: str | None
39
+ configuration: dict
40
+ team_id: str | None
41
+ created_at: datetime
42
+ updated_at: datetime
43
+ started_at: datetime | None
44
+ completed_at: datetime | None
45
+ state: dict
46
+ error_message: str | None
47
+
48
+ class Config:
49
+ from_attributes = True
50
+
51
+
52
+ @router.post("", response_model=WorkflowResponse, status_code=status.HTTP_201_CREATED)
53
+ def create_workflow(workflow_data: WorkflowCreate, db: Session = Depends(get_db)):
54
+ """Create a new workflow"""
55
+ workflow = Workflow(
56
+ name=workflow_data.name,
57
+ description=workflow_data.description,
58
+ steps=workflow_data.steps,
59
+ configuration=workflow_data.configuration,
60
+ team_id=workflow_data.team_id,
61
+ )
62
+ db.add(workflow)
63
+ db.commit()
64
+ db.refresh(workflow)
65
+ return workflow
66
+
67
+
68
+ @router.get("", response_model=List[WorkflowResponse])
69
+ def list_workflows(
70
+ skip: int = 0,
71
+ limit: int = 100,
72
+ status_filter: WorkflowStatus | None = None,
73
+ team_id: str | None = None,
74
+ db: Session = Depends(get_db),
75
+ ):
76
+ """List all workflows"""
77
+ query = db.query(Workflow)
78
+ if status_filter:
79
+ query = query.filter(Workflow.status == status_filter)
80
+ if team_id:
81
+ query = query.filter(Workflow.team_id == team_id)
82
+ workflows = query.offset(skip).limit(limit).all()
83
+ return workflows
84
+
85
+
86
+ @router.get("/{workflow_id}", response_model=WorkflowResponse)
87
+ def get_workflow(workflow_id: str, db: Session = Depends(get_db)):
88
+ """Get a specific workflow by ID"""
89
+ workflow = db.query(Workflow).filter(Workflow.id == workflow_id).first()
90
+ if not workflow:
91
+ raise HTTPException(status_code=404, detail="Workflow not found")
92
+ return workflow
93
+
94
+
95
+ @router.patch("/{workflow_id}", response_model=WorkflowResponse)
96
+ def update_workflow(workflow_id: str, workflow_data: WorkflowUpdate, db: Session = Depends(get_db)):
97
+ """Update a workflow"""
98
+ workflow = db.query(Workflow).filter(Workflow.id == workflow_id).first()
99
+ if not workflow:
100
+ raise HTTPException(status_code=404, detail="Workflow not found")
101
+
102
+ update_data = workflow_data.model_dump(exclude_unset=True)
103
+ for field, value in update_data.items():
104
+ setattr(workflow, field, value)
105
+
106
+ workflow.updated_at = datetime.utcnow()
107
+ db.commit()
108
+ db.refresh(workflow)
109
+ return workflow
110
+
111
+
112
+ @router.delete("/{workflow_id}", status_code=status.HTTP_204_NO_CONTENT)
113
+ def delete_workflow(workflow_id: str, db: Session = Depends(get_db)):
114
+ """Delete a workflow"""
115
+ workflow = db.query(Workflow).filter(Workflow.id == workflow_id).first()
116
+ if not workflow:
117
+ raise HTTPException(status_code=404, detail="Workflow not found")
118
+
119
+ db.delete(workflow)
120
+ db.commit()
121
+ return None
122
+
123
+
124
+ @router.post("/{workflow_id}/start", response_model=WorkflowResponse)
125
+ def start_workflow(workflow_id: str, db: Session = Depends(get_db)):
126
+ """Start a workflow"""
127
+ workflow = db.query(Workflow).filter(Workflow.id == workflow_id).first()
128
+ if not workflow:
129
+ raise HTTPException(status_code=404, detail="Workflow not found")
130
+
131
+ if workflow.status == WorkflowStatus.RUNNING:
132
+ raise HTTPException(status_code=400, detail="Workflow is already running")
133
+
134
+ workflow.status = WorkflowStatus.RUNNING
135
+ workflow.started_at = datetime.utcnow()
136
+ workflow.error_message = None
137
+ if workflow.steps and len(workflow.steps) > 0:
138
+ workflow.current_step = workflow.steps[0].get("id", workflow.steps[0].get("name"))
139
+ db.commit()
140
+ db.refresh(workflow)
141
+ return workflow
142
+
143
+
144
+ @router.post("/{workflow_id}/pause", response_model=WorkflowResponse)
145
+ def pause_workflow(workflow_id: str, db: Session = Depends(get_db)):
146
+ """Pause a workflow"""
147
+ workflow = db.query(Workflow).filter(Workflow.id == workflow_id).first()
148
+ if not workflow:
149
+ raise HTTPException(status_code=404, detail="Workflow not found")
150
+
151
+ if workflow.status != WorkflowStatus.RUNNING:
152
+ raise HTTPException(status_code=400, detail="Can only pause running workflows")
153
+
154
+ workflow.status = WorkflowStatus.PAUSED
155
+ db.commit()
156
+ db.refresh(workflow)
157
+ return workflow
158
+
159
+
160
+ @router.post("/{workflow_id}/resume", response_model=WorkflowResponse)
161
+ def resume_workflow(workflow_id: str, db: Session = Depends(get_db)):
162
+ """Resume a paused workflow"""
163
+ workflow = db.query(Workflow).filter(Workflow.id == workflow_id).first()
164
+ if not workflow:
165
+ raise HTTPException(status_code=404, detail="Workflow not found")
166
+
167
+ if workflow.status != WorkflowStatus.PAUSED:
168
+ raise HTTPException(status_code=400, detail="Can only resume paused workflows")
169
+
170
+ workflow.status = WorkflowStatus.RUNNING
171
+ db.commit()
172
+ db.refresh(workflow)
173
+ return workflow
174
+
175
+
176
+ @router.post("/{workflow_id}/cancel", response_model=WorkflowResponse)
177
+ def cancel_workflow(workflow_id: str, db: Session = Depends(get_db)):
178
+ """Cancel a workflow"""
179
+ workflow = db.query(Workflow).filter(Workflow.id == workflow_id).first()
180
+ if not workflow:
181
+ raise HTTPException(status_code=404, detail="Workflow not found")
182
+
183
+ if workflow.status in [WorkflowStatus.COMPLETED, WorkflowStatus.CANCELLED]:
184
+ raise HTTPException(status_code=400, detail="Workflow is already completed or cancelled")
185
+
186
+ workflow.status = WorkflowStatus.CANCELLED
187
+ workflow.completed_at = datetime.utcnow()
188
+ db.commit()
189
+ db.refresh(workflow)
190
+ return workflow
191
+
192
+
193
+ @router.post("/{workflow_id}/complete", response_model=WorkflowResponse)
194
+ def complete_workflow(workflow_id: str, db: Session = Depends(get_db)):
195
+ """Mark a workflow as completed"""
196
+ workflow = db.query(Workflow).filter(Workflow.id == workflow_id).first()
197
+ if not workflow:
198
+ raise HTTPException(status_code=404, detail="Workflow not found")
199
+
200
+ workflow.status = WorkflowStatus.COMPLETED
201
+ workflow.completed_at = datetime.utcnow()
202
+ db.commit()
203
+ db.refresh(workflow)
204
+ return workflow
@@ -0,0 +1,6 @@
1
+ """
2
+ Shared runtime validation and configuration.
3
+
4
+ This module is shared between the API and worker to ensure consistent
5
+ validation logic across both components.
6
+ """
@@ -0,0 +1,344 @@
1
+ """
2
+ Runtime validation system with model compatibility and requirements checking.
3
+
4
+ This module provides:
5
+ - Model compatibility validation per runtime
6
+ - Runtime requirements specification
7
+ - Agent/Team configuration validation
8
+ - End-to-end validation before execution
9
+
10
+ This is shared between the API and worker for consistent validation.
11
+ """
12
+
13
+ from typing import List, Optional, Dict, Any, Set
14
+ from dataclasses import dataclass
15
+ from enum import Enum
16
+ import re
17
+
18
+
19
+ class RuntimeType(str, Enum):
20
+ """Agent runtime type enumeration"""
21
+ DEFAULT = "default" # Agno-based runtime
22
+ CLAUDE_CODE = "claude_code" # Claude Code SDK runtime
23
+
24
+
25
+ class ValidationError(Exception):
26
+ """Raised when validation fails."""
27
+
28
+ def __init__(self, message: str, field: Optional[str] = None, details: Optional[Dict[str, Any]] = None):
29
+ self.message = message
30
+ self.field = field
31
+ self.details = details or {}
32
+ super().__init__(message)
33
+
34
+ def to_dict(self) -> Dict[str, Any]:
35
+ """Convert to dict for API responses."""
36
+ result = {"error": self.message}
37
+ if self.field:
38
+ result["field"] = self.field
39
+ if self.details:
40
+ result["details"] = self.details
41
+ return result
42
+
43
+
44
+ @dataclass
45
+ class ModelRequirement:
46
+ """Model requirement specification for a runtime."""
47
+
48
+ # Patterns that model IDs must match (any match is valid)
49
+ model_id_patterns: List[str]
50
+
51
+ # Model providers that are supported (e.g., "anthropic", "openai")
52
+ supported_providers: Set[str]
53
+
54
+ # Specific model families supported (e.g., "claude", "gpt")
55
+ supported_families: Set[str]
56
+
57
+ # Minimum model version (if applicable)
58
+ min_version: Optional[str] = None
59
+
60
+ # Human-readable description
61
+ description: str = ""
62
+
63
+ # Examples of valid model IDs
64
+ examples: List[str] = None
65
+
66
+ def __post_init__(self):
67
+ if self.examples is None:
68
+ self.examples = []
69
+
70
+ def validate(self, model_id: Optional[str]) -> tuple[bool, Optional[str]]:
71
+ """
72
+ Validate a model ID against this requirement.
73
+
74
+ Args:
75
+ model_id: Model ID to validate
76
+
77
+ Returns:
78
+ Tuple of (is_valid, error_message)
79
+ """
80
+ if not model_id:
81
+ return False, "Model ID is required for this runtime"
82
+
83
+ # Check pattern matching
84
+ for pattern in self.model_id_patterns:
85
+ if re.search(pattern, model_id, re.IGNORECASE):
86
+ return True, None
87
+
88
+ # Check provider/family
89
+ model_lower = model_id.lower()
90
+
91
+ # Check if any supported family is in the model ID
92
+ for family in self.supported_families:
93
+ if family.lower() in model_lower:
94
+ return True, None
95
+
96
+ # Provide helpful error message
97
+ examples_str = ", ".join(self.examples) if self.examples else "N/A"
98
+ return False, (
99
+ f"Model '{model_id}' is not compatible with this runtime. "
100
+ f"Expected models matching: {', '.join(self.model_id_patterns)}. "
101
+ f"Supported families: {', '.join(self.supported_families)}. "
102
+ f"Examples: {examples_str}"
103
+ )
104
+
105
+
106
+ @dataclass
107
+ class RuntimeRequirements:
108
+ """Requirements specification for a runtime."""
109
+
110
+ runtime_type: RuntimeType
111
+
112
+ # Model requirements
113
+ model_requirement: ModelRequirement
114
+
115
+ # Required fields in agent/team config
116
+ required_config_fields: List[str] = None
117
+
118
+ # Optional but recommended fields
119
+ recommended_config_fields: List[str] = None
120
+
121
+ # Maximum conversation history length
122
+ max_history_length: Optional[int] = None
123
+
124
+ # Whether system prompt is required
125
+ requires_system_prompt: bool = False
126
+
127
+ # Whether tools/skills are required
128
+ requires_tools: bool = False
129
+
130
+ def __post_init__(self):
131
+ if self.required_config_fields is None:
132
+ self.required_config_fields = []
133
+ if self.recommended_config_fields is None:
134
+ self.recommended_config_fields = []
135
+
136
+ def validate_model(self, model_id: Optional[str]) -> tuple[bool, Optional[str]]:
137
+ """Validate model compatibility."""
138
+ return self.model_requirement.validate(model_id)
139
+
140
+ def validate_config(self, config: Optional[Dict[str, Any]]) -> List[str]:
141
+ """
142
+ Validate agent/team configuration.
143
+
144
+ Returns:
145
+ List of validation errors (empty if valid)
146
+ """
147
+ errors = []
148
+
149
+ if not config:
150
+ if self.required_config_fields:
151
+ errors.append(
152
+ f"Configuration is required for this runtime. "
153
+ f"Required fields: {', '.join(self.required_config_fields)}"
154
+ )
155
+ return errors
156
+
157
+ # Check required fields
158
+ for field in self.required_config_fields:
159
+ if field not in config or config[field] is None:
160
+ errors.append(f"Required field '{field}' is missing in configuration")
161
+
162
+ return errors
163
+
164
+
165
+ class RuntimeRequirementsRegistry:
166
+ """Registry of runtime requirements for validation."""
167
+
168
+ _requirements: Dict[RuntimeType, RuntimeRequirements] = {}
169
+
170
+ @classmethod
171
+ def register(cls, requirements: RuntimeRequirements):
172
+ """Register requirements for a runtime type."""
173
+ cls._requirements[requirements.runtime_type] = requirements
174
+
175
+ @classmethod
176
+ def get(cls, runtime_type: RuntimeType) -> Optional[RuntimeRequirements]:
177
+ """Get requirements for a runtime type."""
178
+ return cls._requirements.get(runtime_type)
179
+
180
+
181
+ # ==================== Default Runtime Requirements ====================
182
+
183
+ # Agno/Default Runtime - Flexible, supports most models
184
+ DEFAULT_RUNTIME_REQUIREMENTS = RuntimeRequirements(
185
+ runtime_type=RuntimeType.DEFAULT,
186
+ model_requirement=ModelRequirement(
187
+ model_id_patterns=[
188
+ r".*", # Accept all models
189
+ ],
190
+ supported_providers={"openai", "anthropic", "azure", "google", "mistral", "cohere"},
191
+ supported_families={"gpt", "claude", "gemini", "mistral", "command"},
192
+ description="Default runtime supports most LiteLLM-compatible models",
193
+ examples=[
194
+ "gpt-4",
195
+ "gpt-4-turbo",
196
+ "gpt-3.5-turbo",
197
+ "claude-3-opus",
198
+ "claude-3-sonnet",
199
+ "gemini-pro",
200
+ "mistral-large",
201
+ ],
202
+ ),
203
+ max_history_length=100, # Reasonable default
204
+ requires_system_prompt=False,
205
+ requires_tools=False,
206
+ )
207
+
208
+ # Claude Code Runtime - Requires Claude models
209
+ CLAUDE_CODE_RUNTIME_REQUIREMENTS = RuntimeRequirements(
210
+ runtime_type=RuntimeType.CLAUDE_CODE,
211
+ model_requirement=ModelRequirement(
212
+ model_id_patterns=[
213
+ r"claude", # Must contain "claude"
214
+ r"kubiya/claude", # LiteLLM proxy format
215
+ r"anthropic\.claude", # Alternative format
216
+ ],
217
+ supported_providers={"anthropic"},
218
+ supported_families={"claude"},
219
+ description=(
220
+ "Claude Code runtime requires Anthropic Claude models. "
221
+ "This runtime leverages Claude's advanced capabilities including "
222
+ "extended context, tool use, and code understanding."
223
+ ),
224
+ examples=[
225
+ "claude-3-opus-20240229",
226
+ "claude-3-sonnet-20240229",
227
+ "claude-3-5-sonnet-20241022",
228
+ "claude-3-haiku-20240307",
229
+ "claude-sonnet-4",
230
+ "claude-opus-4",
231
+ "kubiya/claude-sonnet-4",
232
+ "kubiya/claude-opus-4",
233
+ ],
234
+ ),
235
+ max_history_length=200, # Claude handles longer contexts well
236
+ requires_system_prompt=False, # Optional but recommended
237
+ requires_tools=False, # Claude Code adds tools automatically
238
+ recommended_config_fields=["timeout", "max_tokens"],
239
+ )
240
+
241
+
242
+ # Register default requirements
243
+ RuntimeRequirementsRegistry.register(DEFAULT_RUNTIME_REQUIREMENTS)
244
+ RuntimeRequirementsRegistry.register(CLAUDE_CODE_RUNTIME_REQUIREMENTS)
245
+
246
+
247
+ # ==================== Validation Helpers ====================
248
+
249
+ def validate_agent_for_runtime(
250
+ runtime_type: str,
251
+ model_id: Optional[str],
252
+ agent_config: Optional[Dict[str, Any]] = None,
253
+ system_prompt: Optional[str] = None,
254
+ ) -> tuple[bool, List[str]]:
255
+ """
256
+ Validate agent configuration for a runtime (for API validation).
257
+
258
+ Args:
259
+ runtime_type: Runtime type string
260
+ model_id: Model ID to validate
261
+ agent_config: Agent configuration dict
262
+ system_prompt: System prompt
263
+
264
+ Returns:
265
+ Tuple of (is_valid, error_messages)
266
+ """
267
+ try:
268
+ rt = RuntimeType(runtime_type)
269
+ except ValueError:
270
+ return False, [f"Invalid runtime type: {runtime_type}"]
271
+
272
+ requirements = RuntimeRequirementsRegistry.get(rt)
273
+ if not requirements:
274
+ # No requirements - allow
275
+ return True, []
276
+
277
+ errors = []
278
+
279
+ # Validate model
280
+ is_valid, error = requirements.validate_model(model_id)
281
+ if not is_valid:
282
+ errors.append(error)
283
+
284
+ # Validate config
285
+ config_errors = requirements.validate_config(agent_config)
286
+ errors.extend(config_errors)
287
+
288
+ # Validate system prompt if required
289
+ if requirements.requires_system_prompt and not system_prompt:
290
+ errors.append("System prompt is required for this runtime")
291
+
292
+ return len(errors) == 0, errors
293
+
294
+
295
+ def get_runtime_requirements_info(runtime_type: str) -> Dict[str, Any]:
296
+ """
297
+ Get human-readable requirements info for a runtime.
298
+
299
+ Args:
300
+ runtime_type: Runtime type string
301
+
302
+ Returns:
303
+ Dict with requirements information
304
+ """
305
+ try:
306
+ rt = RuntimeType(runtime_type)
307
+ except ValueError:
308
+ return {"error": f"Invalid runtime type: {runtime_type}"}
309
+
310
+ requirements = RuntimeRequirementsRegistry.get(rt)
311
+ if not requirements:
312
+ return {
313
+ "runtime_type": runtime_type,
314
+ "model_requirement": "No specific requirements",
315
+ "flexible": True,
316
+ }
317
+
318
+ return {
319
+ "runtime_type": runtime_type,
320
+ "model_requirement": {
321
+ "description": requirements.model_requirement.description,
322
+ "supported_providers": list(requirements.model_requirement.supported_providers),
323
+ "supported_families": list(requirements.model_requirement.supported_families),
324
+ "examples": requirements.model_requirement.examples,
325
+ },
326
+ "required_config_fields": requirements.required_config_fields,
327
+ "recommended_config_fields": requirements.recommended_config_fields,
328
+ "max_history_length": requirements.max_history_length,
329
+ "requires_system_prompt": requirements.requires_system_prompt,
330
+ "requires_tools": requirements.requires_tools,
331
+ }
332
+
333
+
334
+ def list_all_runtime_requirements() -> Dict[str, Dict[str, Any]]:
335
+ """
336
+ Get requirements for all registered runtimes.
337
+
338
+ Returns:
339
+ Dict mapping runtime type to requirements info
340
+ """
341
+ return {
342
+ rt.value: get_runtime_requirements_info(rt.value)
343
+ for rt in RuntimeRequirementsRegistry._requirements.keys()
344
+ }
@@ -0,0 +1 @@
1
+ """Pydantic schemas for API request/response models."""