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,203 @@
1
+ """Temporal credentials service with caching and fallback.
2
+
3
+ This service orchestrates fetching organization-specific Temporal credentials
4
+ from the Kubiya API, with Redis caching and fallback to environment variables.
5
+ """
6
+
7
+ import os
8
+ from typing import Optional, Dict
9
+ import structlog
10
+
11
+ from control_plane_api.app.lib.kubiya_client import get_kubiya_client
12
+ from control_plane_api.app.lib.temporal_credentials_cache import (
13
+ get_cached_temporal_credentials,
14
+ cache_temporal_credentials,
15
+ )
16
+
17
+ logger = structlog.get_logger()
18
+
19
+
20
+ def is_local_temporal() -> bool:
21
+ """
22
+ Check if running against local Temporal server.
23
+
24
+ Detects local Temporal by checking if TEMPORAL_HOST contains
25
+ localhost, 127.0.0.1, or temporal: (Docker Compose service name).
26
+
27
+ Returns:
28
+ True if local Temporal, False if Temporal Cloud
29
+ """
30
+ temporal_host = os.getenv("TEMPORAL_HOST", "us-east-1.aws.api.temporal.io:7233")
31
+ return (
32
+ "localhost" in temporal_host or
33
+ "127.0.0.1" in temporal_host or
34
+ temporal_host.startswith("temporal:")
35
+ )
36
+
37
+
38
+ async def get_temporal_credentials_for_org(
39
+ org_id: str,
40
+ token: str,
41
+ use_fallback: bool = True
42
+ ) -> Dict:
43
+ """
44
+ Get Temporal credentials for organization with caching and fallback.
45
+
46
+ This is the main entry point for fetching Temporal credentials.
47
+
48
+ Flow:
49
+ 1. Check if local Temporal (auto-detect from TEMPORAL_HOST)
50
+ - If local: Return env var credentials immediately
51
+ 2. Check Redis cache
52
+ 3. If not cached, call Kubiya API
53
+ 4. Cache the result
54
+ 5. On failure, optionally fallback to env vars (backwards compatibility)
55
+
56
+ Args:
57
+ org_id: Organization ID (slug or UUID)
58
+ token: Authentication token
59
+ use_fallback: If True, fallback to env vars on API failure (default: True)
60
+
61
+ Returns:
62
+ Dict with keys:
63
+ {
64
+ "namespace": "org-slug.lpagu",
65
+ "api_key": "...",
66
+ "host": "us-east-1.aws.api.temporal.io:7233",
67
+ "org": "org-slug",
68
+ "ttl": "2026-01-07T14:38:20Z"
69
+ }
70
+
71
+ Raises:
72
+ ValueError: If credentials cannot be obtained and fallback is disabled
73
+
74
+ Example:
75
+ credentials = await get_temporal_credentials_for_org(
76
+ org_id="kubiya-ai",
77
+ token=request.state.kubiya_token,
78
+ use_fallback=True
79
+ )
80
+ """
81
+ # Check if running against local Temporal
82
+ if is_local_temporal():
83
+ logger.debug("using_local_temporal_credentials", org_id=org_id)
84
+ return _get_local_temporal_credentials()
85
+
86
+ # PRIORITY: Check if explicit Temporal credentials are set in environment variables
87
+ # This allows overriding Kubiya API with admin credentials
88
+ if os.getenv("TEMPORAL_API_KEY") or os.getenv("TEMPORAL_NAMESPACE"):
89
+ logger.info(
90
+ "using_explicit_env_temporal_credentials",
91
+ org_id=org_id,
92
+ namespace=os.getenv("TEMPORAL_NAMESPACE", "not_set"),
93
+ has_api_key=bool(os.getenv("TEMPORAL_API_KEY"))
94
+ )
95
+ return _get_fallback_credentials()
96
+
97
+ # Check cache first
98
+ cached_creds = await get_cached_temporal_credentials(org_id)
99
+ if cached_creds:
100
+ logger.debug("using_cached_temporal_credentials", org_id=org_id)
101
+ return _normalize_credentials(cached_creds)
102
+
103
+ # Fetch from Kubiya API
104
+ kubiya_client = get_kubiya_client()
105
+ api_creds = await kubiya_client.get_temporal_credentials(token)
106
+
107
+ if api_creds:
108
+ # Cache the credentials
109
+ await cache_temporal_credentials(org_id, api_creds)
110
+
111
+ logger.info(
112
+ "temporal_credentials_fetched_from_api",
113
+ org_id=org_id,
114
+ namespace=api_creds.get("namespace"),
115
+ source="kubiya_api"
116
+ )
117
+
118
+ return _normalize_credentials(api_creds)
119
+
120
+ # API fetch failed
121
+ if use_fallback:
122
+ logger.warning(
123
+ "temporal_credentials_api_failed_using_fallback",
124
+ org_id=org_id,
125
+ fallback_enabled=use_fallback
126
+ )
127
+ return _get_fallback_credentials()
128
+ else:
129
+ raise ValueError(
130
+ f"Failed to fetch Temporal credentials for org {org_id} "
131
+ "and fallback is disabled"
132
+ )
133
+
134
+
135
+ def _normalize_credentials(api_response: Dict) -> Dict:
136
+ """
137
+ Normalize API response to standard format.
138
+
139
+ Converts the Kubiya API response format to the internal format
140
+ used by the control plane.
141
+
142
+ Args:
143
+ api_response: Response from Kubiya API with keys like 'apiKey', 'namespace'
144
+
145
+ Returns:
146
+ Normalized credentials dict with keys like 'api_key', 'namespace'
147
+ """
148
+ # Get host from env or use default
149
+ host = os.getenv("TEMPORAL_HOST", "us-east-1.aws.api.temporal.io:7233")
150
+
151
+ return {
152
+ "namespace": api_response.get("namespace"),
153
+ "api_key": api_response.get("apiKey"),
154
+ "host": host,
155
+ "org": api_response.get("org"),
156
+ "ttl": api_response.get("ttl"),
157
+ }
158
+
159
+
160
+ def _get_local_temporal_credentials() -> Dict:
161
+ """
162
+ Get local Temporal credentials from environment variables.
163
+
164
+ Used when running against a local Temporal server (development).
165
+
166
+ Returns:
167
+ Credentials dict with env var values
168
+ """
169
+ logger.info("using_local_temporal_credentials", source="env_vars")
170
+
171
+ return {
172
+ "namespace": os.getenv("TEMPORAL_NAMESPACE", "default").strip(),
173
+ "api_key": "", # No API key for local Temporal
174
+ "host": os.getenv("TEMPORAL_HOST", "localhost:7233").strip(),
175
+ "org": "local",
176
+ "ttl": None,
177
+ }
178
+
179
+
180
+ def _get_fallback_credentials() -> Dict:
181
+ """
182
+ Get fallback credentials from environment variables.
183
+
184
+ Used for backwards compatibility during migration when the
185
+ Kubiya API is unavailable.
186
+
187
+ Returns:
188
+ Credentials dict with env var values
189
+ """
190
+ logger.warning("using_fallback_temporal_credentials", source="env_vars")
191
+
192
+ # Strip whitespace/newlines from env vars to handle malformed .env files
193
+ namespace = os.getenv("TEMPORAL_NAMESPACE", "agent-control-plane.lpagu").strip()
194
+ api_key = (os.getenv("TEMPORAL_API_KEY") or os.getenv("TEMPORAL_CLOUD_ADMIN_TOKEN", "")).strip()
195
+ host = os.getenv("TEMPORAL_HOST", "us-east-1.aws.api.temporal.io:7233").strip()
196
+
197
+ return {
198
+ "namespace": namespace,
199
+ "api_key": api_key,
200
+ "host": host,
201
+ "org": "fallback",
202
+ "ttl": None,
203
+ }
@@ -0,0 +1,24 @@
1
+ """
2
+ Shared validation module for runtime and model validation.
3
+
4
+ This module is shared between the API and worker to avoid circular dependencies.
5
+ It provides validation logic without depending on worker-specific types.
6
+ """
7
+
8
+ from .runtime_validation import (
9
+ validate_agent_for_runtime,
10
+ validate_agent_for_runtime_with_litellm,
11
+ validate_model_against_litellm,
12
+ get_runtime_requirements_info,
13
+ list_all_runtime_requirements,
14
+ RUNTIME_REQUIREMENTS,
15
+ )
16
+
17
+ __all__ = [
18
+ "validate_agent_for_runtime",
19
+ "validate_agent_for_runtime_with_litellm",
20
+ "validate_model_against_litellm",
21
+ "get_runtime_requirements_info",
22
+ "list_all_runtime_requirements",
23
+ "RUNTIME_REQUIREMENTS",
24
+ ]
@@ -0,0 +1,388 @@
1
+ """
2
+ Runtime validation logic shared between API and worker.
3
+
4
+ This module provides validation without depending on worker-specific types,
5
+ making it safe to import from both the API layer and worker layer.
6
+ """
7
+
8
+ from typing import List, Optional, Dict, Any, Set
9
+ from dataclasses import dataclass
10
+ import re
11
+ import structlog
12
+
13
+ logger = structlog.get_logger()
14
+
15
+
16
+ @dataclass
17
+ class ModelRequirement:
18
+ """Model requirement specification for a runtime."""
19
+
20
+ # Patterns that model IDs must match (any match is valid)
21
+ model_id_patterns: List[str]
22
+
23
+ # Model providers that are supported (e.g., "anthropic", "openai")
24
+ supported_providers: Set[str]
25
+
26
+ # Specific model families supported (e.g., "claude", "gpt")
27
+ supported_families: Set[str]
28
+
29
+ # Human-readable description
30
+ description: str = ""
31
+
32
+ # Examples of valid model IDs
33
+ examples: List[str] = None
34
+
35
+ def __post_init__(self):
36
+ if self.examples is None:
37
+ self.examples = []
38
+
39
+ def validate(self, model_id: Optional[str]) -> tuple[bool, Optional[str]]:
40
+ """
41
+ Validate a model ID against this requirement.
42
+
43
+ Args:
44
+ model_id: Model ID to validate
45
+
46
+ Returns:
47
+ Tuple of (is_valid, error_message)
48
+ """
49
+ if not model_id:
50
+ return False, "Model ID is required for this runtime"
51
+
52
+ # Check pattern matching
53
+ for pattern in self.model_id_patterns:
54
+ if re.search(pattern, model_id, re.IGNORECASE):
55
+ return True, None
56
+
57
+ # Check provider/family
58
+ model_lower = model_id.lower()
59
+
60
+ # Check if any supported family is in the model ID
61
+ for family in self.supported_families:
62
+ if family.lower() in model_lower:
63
+ return True, None
64
+
65
+ # Provide helpful error message
66
+ examples_str = ", ".join(self.examples) if self.examples else "N/A"
67
+ return False, (
68
+ f"Model '{model_id}' is not compatible with this runtime. "
69
+ f"Expected models matching: {', '.join(self.model_id_patterns)}. "
70
+ f"Supported families: {', '.join(self.supported_families)}. "
71
+ f"Examples: {examples_str}"
72
+ )
73
+
74
+
75
+ @dataclass
76
+ class RuntimeRequirements:
77
+ """Requirements specification for a runtime."""
78
+
79
+ runtime_type: str
80
+
81
+ # Model requirements
82
+ model_requirement: ModelRequirement
83
+
84
+ # Required fields in agent/team config
85
+ required_config_fields: List[str] = None
86
+
87
+ # Optional but recommended fields
88
+ recommended_config_fields: List[str] = None
89
+
90
+ # Maximum conversation history length
91
+ max_history_length: Optional[int] = None
92
+
93
+ # Whether system prompt is required
94
+ requires_system_prompt: bool = False
95
+
96
+ # Whether tools/skills are required
97
+ requires_tools: bool = False
98
+
99
+ def __post_init__(self):
100
+ if self.required_config_fields is None:
101
+ self.required_config_fields = []
102
+ if self.recommended_config_fields is None:
103
+ self.recommended_config_fields = []
104
+
105
+ def validate_model(self, model_id: Optional[str]) -> tuple[bool, Optional[str]]:
106
+ """Validate model compatibility."""
107
+ return self.model_requirement.validate(model_id)
108
+
109
+ def validate_config(self, config: Optional[Dict[str, Any]]) -> List[str]:
110
+ """
111
+ Validate agent/team configuration.
112
+
113
+ Returns:
114
+ List of validation errors (empty if valid)
115
+ """
116
+ errors = []
117
+
118
+ if not config:
119
+ if self.required_config_fields:
120
+ errors.append(
121
+ f"Configuration is required for this runtime. "
122
+ f"Required fields: {', '.join(self.required_config_fields)}"
123
+ )
124
+ return errors
125
+
126
+ # Check required fields
127
+ for field in self.required_config_fields:
128
+ if field not in config or config[field] is None:
129
+ errors.append(f"Required field '{field}' is missing in configuration")
130
+
131
+ return errors
132
+
133
+
134
+ # ==================== Runtime Requirements Definitions ====================
135
+
136
+ # Agno/Default Runtime - Flexible, supports most models
137
+ DEFAULT_RUNTIME_REQUIREMENTS = RuntimeRequirements(
138
+ runtime_type="default",
139
+ model_requirement=ModelRequirement(
140
+ model_id_patterns=[
141
+ r".*", # Accept all models
142
+ ],
143
+ supported_providers={"openai", "anthropic", "azure", "google", "mistral", "cohere"},
144
+ supported_families={"gpt", "claude", "gemini", "mistral", "command"},
145
+ description="Default runtime supports most LiteLLM-compatible models",
146
+ examples=[
147
+ "gpt-4",
148
+ "gpt-4-turbo",
149
+ "gpt-3.5-turbo",
150
+ "claude-3-opus",
151
+ "claude-3-sonnet",
152
+ "claude-sonnet-4",
153
+ "gemini-pro",
154
+ "mistral-large",
155
+ ],
156
+ ),
157
+ max_history_length=100, # Reasonable default
158
+ requires_system_prompt=False,
159
+ requires_tools=False,
160
+ )
161
+
162
+ # Claude Code Runtime - Requires Claude models
163
+ CLAUDE_CODE_RUNTIME_REQUIREMENTS = RuntimeRequirements(
164
+ runtime_type="claude_code",
165
+ model_requirement=ModelRequirement(
166
+ model_id_patterns=[
167
+ r"claude", # Must contain "claude"
168
+ r"kubiya/claude", # LiteLLM proxy format
169
+ r"anthropic\.claude", # Alternative format
170
+ ],
171
+ supported_providers={"anthropic"},
172
+ supported_families={"claude"},
173
+ description=(
174
+ "Claude Code runtime requires Anthropic Claude models. "
175
+ "This runtime leverages Claude's advanced capabilities including "
176
+ "extended context, tool use, and code understanding."
177
+ ),
178
+ examples=[
179
+ "claude-3-opus-20240229",
180
+ "claude-3-sonnet-20240229",
181
+ "claude-3-5-sonnet-20241022",
182
+ "claude-3-haiku-20240307",
183
+ "claude-sonnet-4",
184
+ "claude-opus-4",
185
+ "kubiya/claude-sonnet-4",
186
+ "kubiya/claude-opus-4",
187
+ ],
188
+ ),
189
+ max_history_length=200, # Claude handles longer contexts well
190
+ requires_system_prompt=False, # Optional but recommended
191
+ requires_tools=False, # Claude Code adds tools automatically
192
+ recommended_config_fields=["timeout", "max_tokens"],
193
+ )
194
+
195
+
196
+ # Registry of runtime requirements
197
+ RUNTIME_REQUIREMENTS: Dict[str, RuntimeRequirements] = {
198
+ "default": DEFAULT_RUNTIME_REQUIREMENTS,
199
+ "claude_code": CLAUDE_CODE_RUNTIME_REQUIREMENTS,
200
+ }
201
+
202
+
203
+ # ==================== Validation Functions ====================
204
+
205
+ def validate_agent_for_runtime(
206
+ runtime_type: str,
207
+ model_id: Optional[str],
208
+ agent_config: Optional[Dict[str, Any]] = None,
209
+ system_prompt: Optional[str] = None,
210
+ ) -> tuple[bool, List[str]]:
211
+ """
212
+ Validate agent configuration for a runtime.
213
+
214
+ Args:
215
+ runtime_type: Runtime type string (e.g., "default", "claude_code")
216
+ model_id: Model ID to validate
217
+ agent_config: Agent configuration dict
218
+ system_prompt: System prompt
219
+
220
+ Returns:
221
+ Tuple of (is_valid, error_messages)
222
+ """
223
+ requirements = RUNTIME_REQUIREMENTS.get(runtime_type)
224
+ if not requirements:
225
+ # No requirements registered - allow by default
226
+ return True, []
227
+
228
+ errors = []
229
+
230
+ # Validate model
231
+ is_valid, error = requirements.validate_model(model_id)
232
+ if not is_valid:
233
+ errors.append(error)
234
+
235
+ # Validate config
236
+ config_errors = requirements.validate_config(agent_config)
237
+ errors.extend(config_errors)
238
+
239
+ # Validate system prompt if required
240
+ if requirements.requires_system_prompt and not system_prompt:
241
+ errors.append("System prompt is required for this runtime")
242
+
243
+ return len(errors) == 0, errors
244
+
245
+
246
+ def get_runtime_requirements_info(runtime_type: str) -> Dict[str, Any]:
247
+ """
248
+ Get human-readable requirements info for a runtime.
249
+
250
+ Args:
251
+ runtime_type: Runtime type string
252
+
253
+ Returns:
254
+ Dict with requirements information
255
+ """
256
+ requirements = RUNTIME_REQUIREMENTS.get(runtime_type)
257
+ if not requirements:
258
+ return {
259
+ "runtime_type": runtime_type,
260
+ "model_requirement": "No specific requirements",
261
+ "flexible": True,
262
+ }
263
+
264
+ return {
265
+ "runtime_type": runtime_type,
266
+ "model_requirement": {
267
+ "description": requirements.model_requirement.description,
268
+ "supported_providers": list(requirements.model_requirement.supported_providers),
269
+ "supported_families": list(requirements.model_requirement.supported_families),
270
+ "examples": requirements.model_requirement.examples,
271
+ },
272
+ "required_config_fields": requirements.required_config_fields,
273
+ "recommended_config_fields": requirements.recommended_config_fields,
274
+ "max_history_length": requirements.max_history_length,
275
+ "requires_system_prompt": requirements.requires_system_prompt,
276
+ "requires_tools": requirements.requires_tools,
277
+ }
278
+
279
+
280
+ def list_all_runtime_requirements() -> Dict[str, Dict[str, Any]]:
281
+ """
282
+ Get requirements for all registered runtimes.
283
+
284
+ Returns:
285
+ Dict mapping runtime type to requirements info
286
+ """
287
+ return {
288
+ runtime_type: get_runtime_requirements_info(runtime_type)
289
+ for runtime_type in RUNTIME_REQUIREMENTS.keys()
290
+ }
291
+
292
+
293
+ async def validate_model_against_litellm(model_id: str) -> tuple[bool, Optional[str]]:
294
+ """
295
+ Validate a model ID against the LiteLLM server.
296
+
297
+ This function dynamically checks if the model is available in the LiteLLM server.
298
+
299
+ Args:
300
+ model_id: Model ID to validate
301
+
302
+ Returns:
303
+ Tuple of (is_valid, error_message)
304
+ """
305
+ try:
306
+ # Import here to avoid circular dependencies
307
+ from control_plane_api.app.services.litellm_service import litellm_service
308
+
309
+ # Fetch available models from LiteLLM server
310
+ available_models = await litellm_service.fetch_available_models()
311
+
312
+ # Extract model IDs from the response
313
+ available_model_ids = [model.get("id") for model in available_models if model.get("id")]
314
+
315
+ # Check if the model_id is in the available models
316
+ if model_id in available_model_ids:
317
+ return True, None
318
+
319
+ # Check if any model ID contains the requested model (for prefix matching)
320
+ # e.g., "claude-sonnet-4" might match "kubiya/claude-sonnet-4"
321
+ for available_id in available_model_ids:
322
+ if model_id in available_id or available_id in model_id:
323
+ logger.info(
324
+ "model_validation_fuzzy_match",
325
+ requested=model_id,
326
+ matched=available_id
327
+ )
328
+ return True, None
329
+
330
+ return False, (
331
+ f"Model '{model_id}' is not available in the LiteLLM server. "
332
+ f"Available models: {', '.join(available_model_ids[:10])}"
333
+ + ("..." if len(available_model_ids) > 10 else "")
334
+ )
335
+
336
+ except Exception as e:
337
+ logger.warning(
338
+ "litellm_validation_failed",
339
+ model_id=model_id,
340
+ error=str(e),
341
+ msg="Falling back to pattern-based validation"
342
+ )
343
+ # If LiteLLM validation fails, fall back to pattern-based validation
344
+ # Accept any model with provider/model format
345
+ if "/" in model_id:
346
+ return True, None
347
+ return False, f"Model '{model_id}' has invalid format (expected 'provider/model')"
348
+
349
+
350
+ async def validate_agent_for_runtime_with_litellm(
351
+ runtime_type: str,
352
+ model_id: Optional[str],
353
+ agent_config: Optional[Dict[str, Any]] = None,
354
+ system_prompt: Optional[str] = None,
355
+ check_litellm: bool = True,
356
+ ) -> tuple[bool, List[str]]:
357
+ """
358
+ Enhanced validation that checks both runtime requirements and LiteLLM availability.
359
+
360
+ Args:
361
+ runtime_type: Runtime type string (e.g., "default", "claude_code")
362
+ model_id: Model ID to validate
363
+ agent_config: Agent configuration dict
364
+ system_prompt: System prompt
365
+ check_litellm: Whether to check model availability in LiteLLM server
366
+
367
+ Returns:
368
+ Tuple of (is_valid, error_messages)
369
+ """
370
+ # First, run standard runtime validation
371
+ is_valid, errors = validate_agent_for_runtime(
372
+ runtime_type=runtime_type,
373
+ model_id=model_id,
374
+ agent_config=agent_config,
375
+ system_prompt=system_prompt
376
+ )
377
+
378
+ # If basic validation failed, return immediately
379
+ if not is_valid:
380
+ return is_valid, errors
381
+
382
+ # Optionally check against LiteLLM server
383
+ if check_litellm and model_id:
384
+ litellm_valid, litellm_error = await validate_model_against_litellm(model_id)
385
+ if not litellm_valid and litellm_error:
386
+ errors.append(litellm_error)
387
+
388
+ return len(errors) == 0, errors