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,588 @@
1
+ """Temporal Cloud provisioning activities using tcld CLI"""
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Optional
5
+ from datetime import datetime, timezone
6
+ from temporalio import activity
7
+ import structlog
8
+ import subprocess
9
+ import json
10
+ import os
11
+ import time
12
+ import secrets
13
+
14
+ from control_plane_api.app.database import get_session_local
15
+ from control_plane_api.app.models.orchestration import Namespace
16
+ from control_plane_api.app.models.environment import Environment
17
+
18
+ logger = structlog.get_logger()
19
+
20
+
21
+ @dataclass
22
+ class CheckNamespaceInput:
23
+ """Input for check_namespace_exists activity"""
24
+ organization_id: str
25
+ namespace_name: str
26
+
27
+
28
+ @dataclass
29
+ class CreateNamespaceInput:
30
+ """Input for create_namespace activity"""
31
+ organization_id: str
32
+ namespace_name: str
33
+ account_id: str
34
+ region: str = "aws-us-east-1"
35
+ retention_days: int = 30
36
+
37
+
38
+ @dataclass
39
+ class PollNamespaceStatusInput:
40
+ """Input for poll_namespace_status activity"""
41
+ namespace_name: str
42
+ max_attempts: int = 60 # 60 attempts * 5 seconds = 5 minutes max
43
+ poll_interval_seconds: int = 5
44
+
45
+
46
+ @dataclass
47
+ class GenerateApiKeyInput:
48
+ """Input for generate_namespace_api_key activity"""
49
+ namespace_name: str
50
+ key_description: str = "Control Plane API Key"
51
+
52
+
53
+ @dataclass
54
+ class StoreNamespaceCredentialsInput:
55
+ """Input for store_namespace_credentials activity"""
56
+ organization_id: str
57
+ namespace_name: str
58
+ api_key: str
59
+ status: str = "ready"
60
+
61
+
62
+ def run_tcld_command(cmd: list[str], capture_output: bool = True) -> dict:
63
+ """
64
+ Execute tcld CLI command and return result.
65
+
66
+ Args:
67
+ cmd: Command list (e.g., ["tcld", "namespace", "get", "--namespace", "my-ns"])
68
+ capture_output: Whether to capture stdout/stderr
69
+
70
+ Returns:
71
+ Dict with success, stdout, stderr, returncode
72
+ """
73
+ try:
74
+ # Get admin token from environment
75
+ admin_token = os.getenv("TEMPORAL_CLOUD_ADMIN_TOKEN")
76
+ if not admin_token:
77
+ raise ValueError("TEMPORAL_CLOUD_ADMIN_TOKEN environment variable is not set")
78
+
79
+ # Add API key to command if not already present
80
+ # tcld expects --api-key flag for authentication
81
+ enhanced_cmd = cmd.copy()
82
+ if "--api-key" not in enhanced_cmd:
83
+ # Insert API key right after tcld command
84
+ enhanced_cmd.insert(1, "--api-key")
85
+ enhanced_cmd.insert(2, admin_token)
86
+
87
+ activity.logger.info(f"Running tcld command: {' '.join(enhanced_cmd[:3])}... [credentials hidden]")
88
+
89
+ # Prepare environment (tcld might also check env vars)
90
+ env = os.environ.copy()
91
+ env["TEMPORAL_CLOUD_API_KEY"] = admin_token # Backup: env var
92
+
93
+ result = subprocess.run(
94
+ enhanced_cmd,
95
+ capture_output=capture_output,
96
+ text=True,
97
+ timeout=60, # 60 second timeout (namespace operations can take longer)
98
+ env=env,
99
+ )
100
+
101
+ return {
102
+ "success": result.returncode == 0,
103
+ "stdout": result.stdout,
104
+ "stderr": result.stderr,
105
+ "returncode": result.returncode,
106
+ }
107
+ except subprocess.TimeoutExpired:
108
+ return {
109
+ "success": False,
110
+ "error": "Command timed out after 60 seconds",
111
+ "returncode": -1,
112
+ }
113
+ except Exception as e:
114
+ return {
115
+ "success": False,
116
+ "error": str(e),
117
+ "returncode": -1,
118
+ }
119
+
120
+
121
+ @activity.defn
122
+ async def check_namespace_exists(input: CheckNamespaceInput) -> dict:
123
+ """
124
+ Check if a Temporal Cloud namespace already exists.
125
+
126
+ Uses: tcld namespace get --namespace <namespace_name>
127
+
128
+ Returns:
129
+ Dict with exists (bool) and details if found
130
+ """
131
+ activity.logger.info(
132
+ f"Checking if namespace exists",
133
+ extra={
134
+ "organization_id": input.organization_id,
135
+ "namespace_name": input.namespace_name,
136
+ }
137
+ )
138
+
139
+ try:
140
+ # First check our database
141
+ SessionLocal = get_session_local()
142
+ db = SessionLocal()
143
+
144
+ try:
145
+ namespace = db.query(Namespace).filter(
146
+ Namespace.organization_id == input.organization_id,
147
+ Namespace.namespace_name == input.namespace_name
148
+ ).first()
149
+
150
+ if namespace:
151
+ activity.logger.info(
152
+ f"Namespace found in database",
153
+ extra={
154
+ "namespace_name": input.namespace_name,
155
+ "status": namespace.status,
156
+ }
157
+ )
158
+ return {
159
+ "exists": True,
160
+ "in_database": True,
161
+ "status": namespace.status,
162
+ "details": {
163
+ "id": str(namespace.id),
164
+ "organization_id": namespace.organization_id,
165
+ "namespace_name": namespace.namespace_name,
166
+ "status": namespace.status,
167
+ "temporal_host": namespace.temporal_host,
168
+ "created_at": namespace.created_at.isoformat() if namespace.created_at else None,
169
+ "updated_at": namespace.updated_at.isoformat() if namespace.updated_at else None,
170
+ },
171
+ }
172
+ finally:
173
+ db.close()
174
+
175
+ # Check Temporal Cloud using tcld
176
+ result = run_tcld_command([
177
+ "tcld", "namespace", "get",
178
+ "--namespace", input.namespace_name,
179
+ "--output", "json"
180
+ ])
181
+
182
+ if result["success"]:
183
+ # Parse JSON output
184
+ try:
185
+ namespace_data = json.loads(result["stdout"])
186
+ activity.logger.info(
187
+ f"Namespace exists in Temporal Cloud",
188
+ extra={"namespace_name": input.namespace_name}
189
+ )
190
+ return {
191
+ "exists": True,
192
+ "in_temporal_cloud": True,
193
+ "details": namespace_data,
194
+ }
195
+ except json.JSONDecodeError:
196
+ return {"exists": True, "in_temporal_cloud": True}
197
+ else:
198
+ # Namespace doesn't exist
199
+ activity.logger.info(
200
+ f"Namespace does not exist",
201
+ extra={"namespace_name": input.namespace_name}
202
+ )
203
+ return {"exists": False}
204
+
205
+ except Exception as e:
206
+ activity.logger.error(
207
+ f"Failed to check namespace existence",
208
+ extra={"error": str(e), "namespace_name": input.namespace_name}
209
+ )
210
+ raise
211
+
212
+
213
+ @activity.defn
214
+ async def create_namespace(input: CreateNamespaceInput) -> dict:
215
+ """
216
+ Create a new Temporal Cloud namespace using tcld CLI.
217
+
218
+ Uses: tcld namespace create --namespace <name> --region <region> --retention-days <days>
219
+
220
+ Returns:
221
+ Dict with success flag and namespace details
222
+ """
223
+ activity.logger.info(
224
+ f"Creating Temporal Cloud namespace",
225
+ extra={
226
+ "organization_id": input.organization_id,
227
+ "namespace_name": input.namespace_name,
228
+ "region": input.region,
229
+ }
230
+ )
231
+
232
+ # Create namespace record in database first (status: provisioning)
233
+ SessionLocal = get_session_local()
234
+ db = SessionLocal()
235
+
236
+ try:
237
+ # Check if already exists in DB
238
+ existing = db.query(Namespace).filter(
239
+ Namespace.organization_id == input.organization_id
240
+ ).first()
241
+
242
+ if existing:
243
+ namespace_id = existing.id
244
+ # Update to provisioning
245
+ existing.status = "provisioning"
246
+ existing.updated_at = datetime.now(timezone.utc)
247
+ db.commit()
248
+ else:
249
+ # Create new record
250
+ new_namespace = Namespace(
251
+ organization_id=input.organization_id,
252
+ namespace_name=input.namespace_name,
253
+ status="provisioning",
254
+ temporal_host=None,
255
+ created_at=datetime.now(timezone.utc),
256
+ updated_at=datetime.now(timezone.utc),
257
+ )
258
+ db.add(new_namespace)
259
+ db.commit()
260
+ db.refresh(new_namespace)
261
+ namespace_id = new_namespace.id
262
+
263
+ # Execute tcld namespace create
264
+ cmd = [
265
+ "tcld", "namespace", "create",
266
+ "--namespace", input.namespace_name,
267
+ "--region", input.region,
268
+ "--retention-days", str(input.retention_days),
269
+ "--output", "json"
270
+ ]
271
+
272
+ result = run_tcld_command(cmd)
273
+
274
+ if result["success"]:
275
+ activity.logger.info(
276
+ f"Namespace creation initiated",
277
+ extra={"namespace_name": input.namespace_name}
278
+ )
279
+ return {
280
+ "success": True,
281
+ "namespace_id": namespace_id,
282
+ "namespace_name": input.namespace_name,
283
+ "message": "Namespace creation initiated",
284
+ }
285
+ else:
286
+ error_msg = result.get("stderr", result.get("error", "Unknown error"))
287
+ activity.logger.error(
288
+ f"Failed to create namespace",
289
+ extra={
290
+ "namespace_name": input.namespace_name,
291
+ "error": error_msg,
292
+ }
293
+ )
294
+
295
+ # Update database with error
296
+ if namespace_id:
297
+ namespace_to_update = db.query(Namespace).filter(Namespace.id == namespace_id).first()
298
+ if namespace_to_update:
299
+ namespace_to_update.status = "error"
300
+ namespace_to_update.updated_at = datetime.now(timezone.utc)
301
+ db.commit()
302
+
303
+ return {
304
+ "success": False,
305
+ "error": error_msg,
306
+ }
307
+
308
+ except Exception as e:
309
+ activity.logger.error(
310
+ f"Failed to create namespace",
311
+ extra={"error": str(e), "namespace_name": input.namespace_name}
312
+ )
313
+ raise
314
+ finally:
315
+ db.close()
316
+
317
+ @activity.defn
318
+ async def poll_namespace_status(input: PollNamespaceStatusInput) -> dict:
319
+ """
320
+ Poll Temporal Cloud namespace status until it's ready.
321
+
322
+ Uses: tcld namespace get --namespace <name>
323
+
324
+ Returns:
325
+ Dict with ready (bool), status, and details
326
+ """
327
+ activity.logger.info(
328
+ f"Polling namespace status",
329
+ extra={
330
+ "namespace_name": input.namespace_name,
331
+ "max_attempts": input.max_attempts,
332
+ }
333
+ )
334
+
335
+ attempt = 0
336
+ while attempt < input.max_attempts:
337
+ attempt += 1
338
+
339
+ try:
340
+ result = run_tcld_command([
341
+ "tcld", "namespace", "get",
342
+ "--namespace", input.namespace_name,
343
+ "--output", "json"
344
+ ])
345
+
346
+ if result["success"]:
347
+ try:
348
+ namespace_data = json.loads(result["stdout"])
349
+ status = namespace_data.get("state", "unknown")
350
+
351
+ activity.logger.info(
352
+ f"Namespace status check",
353
+ extra={
354
+ "namespace_name": input.namespace_name,
355
+ "attempt": attempt,
356
+ "status": status,
357
+ }
358
+ )
359
+
360
+ # Check if namespace is ready (status might be "active" or "running")
361
+ if status.lower() in ["active", "running", "ready"]:
362
+ return {
363
+ "ready": True,
364
+ "status": status,
365
+ "attempts": attempt,
366
+ "details": namespace_data,
367
+ }
368
+ except json.JSONDecodeError:
369
+ activity.logger.warning(
370
+ f"Failed to parse namespace status JSON",
371
+ extra={"attempt": attempt}
372
+ )
373
+
374
+ # Wait before next attempt
375
+ if attempt < input.max_attempts:
376
+ time.sleep(input.poll_interval_seconds)
377
+
378
+ except Exception as e:
379
+ activity.logger.warning(
380
+ f"Error polling namespace status",
381
+ extra={"attempt": attempt, "error": str(e)}
382
+ )
383
+ if attempt < input.max_attempts:
384
+ time.sleep(input.poll_interval_seconds)
385
+
386
+ # Timed out
387
+ activity.logger.error(
388
+ f"Namespace provisioning timed out",
389
+ extra={
390
+ "namespace_name": input.namespace_name,
391
+ "attempts": attempt,
392
+ }
393
+ )
394
+ return {
395
+ "ready": False,
396
+ "status": "timeout",
397
+ "attempts": attempt,
398
+ "error": f"Namespace not ready after {attempt} attempts"
399
+ }
400
+
401
+
402
+ @activity.defn
403
+ async def generate_namespace_api_key(input: GenerateApiKeyInput) -> dict:
404
+ """
405
+ Generate an API key for the Temporal Cloud namespace.
406
+
407
+ Uses: tcld apikey create --namespace <name> --description <desc>
408
+
409
+ Returns:
410
+ Dict with success flag and api_key
411
+ """
412
+ activity.logger.info(
413
+ f"Generating API key for namespace",
414
+ extra={"namespace_name": input.namespace_name}
415
+ )
416
+
417
+ try:
418
+ result = run_tcld_command([
419
+ "tcld", "apikey", "create",
420
+ "--namespace", input.namespace_name,
421
+ "--description", input.key_description,
422
+ "--output", "json"
423
+ ])
424
+
425
+ if result["success"]:
426
+ try:
427
+ key_data = json.loads(result["stdout"])
428
+ api_key = key_data.get("key") or key_data.get("apiKey")
429
+
430
+ if api_key:
431
+ activity.logger.info(
432
+ f"API key generated successfully",
433
+ extra={"namespace_name": input.namespace_name}
434
+ )
435
+ return {
436
+ "success": True,
437
+ "api_key": api_key,
438
+ "key_id": key_data.get("id"),
439
+ }
440
+ else:
441
+ return {
442
+ "success": False,
443
+ "error": "API key not found in response",
444
+ }
445
+ except json.JSONDecodeError:
446
+ return {
447
+ "success": False,
448
+ "error": "Failed to parse API key response",
449
+ }
450
+ else:
451
+ error_msg = result.get("stderr", result.get("error", "Unknown error"))
452
+ activity.logger.error(
453
+ f"Failed to generate API key",
454
+ extra={"namespace_name": input.namespace_name, "error": error_msg}
455
+ )
456
+ return {
457
+ "success": False,
458
+ "error": error_msg,
459
+ }
460
+
461
+ except Exception as e:
462
+ activity.logger.error(
463
+ f"Failed to generate API key",
464
+ extra={"error": str(e), "namespace_name": input.namespace_name}
465
+ )
466
+ raise
467
+
468
+
469
+ @activity.defn
470
+ async def store_namespace_credentials(input: StoreNamespaceCredentialsInput) -> dict:
471
+ """
472
+ Store namespace credentials in database.
473
+
474
+ TODO: Encrypt API key before storing (use something like Fernet or AWS KMS)
475
+
476
+ Returns:
477
+ Dict with success flag
478
+ """
479
+ activity.logger.info(
480
+ f"Storing namespace credentials",
481
+ extra={
482
+ "organization_id": input.organization_id,
483
+ "namespace_name": input.namespace_name,
484
+ }
485
+ )
486
+
487
+ try:
488
+ SessionLocal = get_session_local()
489
+ db = SessionLocal()
490
+
491
+ try:
492
+ # TODO: Encrypt API key properly
493
+ # For now, we'll store it as-is (NOT RECOMMENDED FOR PRODUCTION)
494
+ # In production, use:
495
+ # - AWS KMS
496
+ # - Vault
497
+ # - Supabase Vault (vault.encrypt)
498
+ # - cryptography.Fernet
499
+ api_key_encrypted = input.api_key # Should be encrypted!
500
+
501
+ # Find and update namespace record
502
+ namespace = db.query(Namespace).filter(
503
+ Namespace.organization_id == input.organization_id,
504
+ Namespace.namespace_name == input.namespace_name
505
+ ).first()
506
+
507
+ if namespace:
508
+ namespace.api_key_encrypted = api_key_encrypted
509
+ namespace.status = input.status
510
+ namespace.updated_at = datetime.now(timezone.utc)
511
+ db.commit()
512
+
513
+ activity.logger.info(
514
+ f"Namespace credentials stored",
515
+ extra={"namespace_name": input.namespace_name}
516
+ )
517
+ return {"success": True, "namespace_id": str(namespace.id)}
518
+ else:
519
+ raise Exception("Failed to update namespace credentials - namespace not found")
520
+ finally:
521
+ db.close()
522
+
523
+ except Exception as e:
524
+ activity.logger.error(
525
+ f"Failed to store namespace credentials",
526
+ extra={"error": str(e), "namespace_name": input.namespace_name}
527
+ )
528
+ raise
529
+
530
+
531
+ @activity.defn
532
+ async def update_task_queue_status(
533
+ task_queue_id: str,
534
+ status: str,
535
+ error_message: Optional[str] = None,
536
+ temporal_namespace_id: Optional[str] = None,
537
+ ) -> dict:
538
+ """
539
+ Update task queue status after provisioning.
540
+
541
+ Returns:
542
+ Dict with success flag
543
+ """
544
+ activity.logger.info(
545
+ f"Updating task queue status",
546
+ extra={"task_queue_id": task_queue_id, "status": status}
547
+ )
548
+
549
+ try:
550
+ SessionLocal = get_session_local()
551
+ db = SessionLocal()
552
+
553
+ try:
554
+ # Find and update environment (task queue)
555
+ environment = db.query(Environment).filter(
556
+ Environment.id == task_queue_id
557
+ ).first()
558
+
559
+ if environment:
560
+ environment.status = status
561
+ environment.updated_at = datetime.now(timezone.utc)
562
+
563
+ if error_message:
564
+ environment.error_message = error_message
565
+
566
+ # Note: temporal_namespace_id field may not exist in Environment model
567
+ # This might need schema update if it's required
568
+ if temporal_namespace_id and hasattr(environment, 'temporal_namespace_id'):
569
+ environment.temporal_namespace_id = temporal_namespace_id
570
+
571
+ db.commit()
572
+
573
+ activity.logger.info(
574
+ f"Task queue status updated",
575
+ extra={"task_queue_id": task_queue_id, "status": status}
576
+ )
577
+ return {"success": True}
578
+ else:
579
+ raise Exception("Failed to update task queue status - environment not found")
580
+ finally:
581
+ db.close()
582
+
583
+ except Exception as e:
584
+ activity.logger.error(
585
+ f"Failed to update task queue status",
586
+ extra={"error": str(e), "task_queue_id": task_queue_id}
587
+ )
588
+ raise
@@ -0,0 +1,35 @@
1
+ """
2
+ Configuration module for Control Plane API.
3
+
4
+ This module provides separate configuration classes for API and shared settings.
5
+ """
6
+
7
+ from .api_config import APIConfig
8
+
9
+ # Create singleton instance
10
+ _api_config = None
11
+
12
+
13
+ def get_api_config() -> APIConfig:
14
+ """
15
+ Get or create the API configuration singleton.
16
+
17
+ Returns:
18
+ APIConfig instance
19
+ """
20
+ global _api_config
21
+
22
+ if _api_config is None:
23
+ _api_config = APIConfig()
24
+
25
+ return _api_config
26
+
27
+
28
+ # For backward compatibility with existing code
29
+ settings = get_api_config()
30
+
31
+ __all__ = [
32
+ "APIConfig",
33
+ "get_api_config",
34
+ "settings",
35
+ ]