kubiya-control-plane-api 0.1.0__py3-none-any.whl → 0.3.4__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.

Potentially problematic release.


This version of kubiya-control-plane-api might be problematic. Click here for more details.

Files changed (185) hide show
  1. control_plane_api/README.md +266 -0
  2. control_plane_api/__init__.py +0 -0
  3. control_plane_api/__version__.py +1 -0
  4. control_plane_api/alembic/README +1 -0
  5. control_plane_api/alembic/env.py +98 -0
  6. control_plane_api/alembic/script.py.mako +28 -0
  7. control_plane_api/alembic/versions/1382bec74309_initial_migration_with_all_models.py +251 -0
  8. control_plane_api/alembic/versions/1f54bc2a37e3_add_analytics_tables.py +162 -0
  9. control_plane_api/alembic/versions/2e4cb136dc10_rename_toolset_ids_to_skill_ids_in_teams.py +30 -0
  10. control_plane_api/alembic/versions/31cd69a644ce_add_skill_templates_table.py +28 -0
  11. control_plane_api/alembic/versions/89e127caa47d_add_jobs_and_job_executions_tables.py +161 -0
  12. control_plane_api/alembic/versions/add_llm_models_table.py +51 -0
  13. control_plane_api/alembic/versions/b0e10697f212_add_runtime_column_to_teams_simple.py +42 -0
  14. control_plane_api/alembic/versions/ce43b24b63bf_add_execution_trigger_source_and_fix_.py +155 -0
  15. control_plane_api/alembic/versions/d4eaf16e3f8d_rename_toolsets_to_skills.py +84 -0
  16. control_plane_api/alembic/versions/efa2dc427da1_rename_metadata_to_custom_metadata.py +32 -0
  17. control_plane_api/alembic/versions/f973b431d1ce_add_workflow_executor_to_skill_types.py +44 -0
  18. control_plane_api/alembic.ini +148 -0
  19. control_plane_api/api/index.py +12 -0
  20. control_plane_api/app/__init__.py +11 -0
  21. control_plane_api/app/activities/__init__.py +20 -0
  22. control_plane_api/app/activities/agent_activities.py +379 -0
  23. control_plane_api/app/activities/team_activities.py +410 -0
  24. control_plane_api/app/activities/temporal_cloud_activities.py +577 -0
  25. control_plane_api/app/config/__init__.py +35 -0
  26. control_plane_api/app/config/api_config.py +354 -0
  27. control_plane_api/app/config/model_pricing.py +318 -0
  28. control_plane_api/app/config.py +95 -0
  29. control_plane_api/app/database.py +135 -0
  30. control_plane_api/app/exceptions.py +408 -0
  31. control_plane_api/app/lib/__init__.py +11 -0
  32. control_plane_api/app/lib/job_executor.py +312 -0
  33. control_plane_api/app/lib/kubiya_client.py +235 -0
  34. control_plane_api/app/lib/litellm_pricing.py +166 -0
  35. control_plane_api/app/lib/planning_tools/__init__.py +22 -0
  36. control_plane_api/app/lib/planning_tools/agents.py +155 -0
  37. control_plane_api/app/lib/planning_tools/base.py +189 -0
  38. control_plane_api/app/lib/planning_tools/environments.py +214 -0
  39. control_plane_api/app/lib/planning_tools/resources.py +240 -0
  40. control_plane_api/app/lib/planning_tools/teams.py +198 -0
  41. control_plane_api/app/lib/policy_enforcer_client.py +939 -0
  42. control_plane_api/app/lib/redis_client.py +436 -0
  43. control_plane_api/app/lib/supabase.py +71 -0
  44. control_plane_api/app/lib/temporal_client.py +138 -0
  45. control_plane_api/app/lib/validation/__init__.py +20 -0
  46. control_plane_api/app/lib/validation/runtime_validation.py +287 -0
  47. control_plane_api/app/main.py +128 -0
  48. control_plane_api/app/middleware/__init__.py +8 -0
  49. control_plane_api/app/middleware/auth.py +513 -0
  50. control_plane_api/app/middleware/exception_handler.py +267 -0
  51. control_plane_api/app/middleware/rate_limiting.py +384 -0
  52. control_plane_api/app/middleware/request_id.py +202 -0
  53. control_plane_api/app/models/__init__.py +27 -0
  54. control_plane_api/app/models/agent.py +79 -0
  55. control_plane_api/app/models/analytics.py +206 -0
  56. control_plane_api/app/models/associations.py +81 -0
  57. control_plane_api/app/models/environment.py +63 -0
  58. control_plane_api/app/models/execution.py +93 -0
  59. control_plane_api/app/models/job.py +179 -0
  60. control_plane_api/app/models/llm_model.py +75 -0
  61. control_plane_api/app/models/presence.py +49 -0
  62. control_plane_api/app/models/project.py +47 -0
  63. control_plane_api/app/models/session.py +38 -0
  64. control_plane_api/app/models/team.py +66 -0
  65. control_plane_api/app/models/workflow.py +55 -0
  66. control_plane_api/app/policies/README.md +121 -0
  67. control_plane_api/app/policies/approved_users.rego +62 -0
  68. control_plane_api/app/policies/business_hours.rego +51 -0
  69. control_plane_api/app/policies/rate_limiting.rego +100 -0
  70. control_plane_api/app/policies/tool_restrictions.rego +86 -0
  71. control_plane_api/app/routers/__init__.py +4 -0
  72. control_plane_api/app/routers/agents.py +364 -0
  73. control_plane_api/app/routers/agents_v2.py +1260 -0
  74. control_plane_api/app/routers/analytics.py +1014 -0
  75. control_plane_api/app/routers/context_manager.py +562 -0
  76. control_plane_api/app/routers/environment_context.py +270 -0
  77. control_plane_api/app/routers/environments.py +715 -0
  78. control_plane_api/app/routers/execution_environment.py +517 -0
  79. control_plane_api/app/routers/executions.py +1911 -0
  80. control_plane_api/app/routers/health.py +92 -0
  81. control_plane_api/app/routers/health_v2.py +326 -0
  82. control_plane_api/app/routers/integrations.py +274 -0
  83. control_plane_api/app/routers/jobs.py +1344 -0
  84. control_plane_api/app/routers/models.py +82 -0
  85. control_plane_api/app/routers/models_v2.py +361 -0
  86. control_plane_api/app/routers/policies.py +639 -0
  87. control_plane_api/app/routers/presence.py +234 -0
  88. control_plane_api/app/routers/projects.py +902 -0
  89. control_plane_api/app/routers/runners.py +379 -0
  90. control_plane_api/app/routers/runtimes.py +172 -0
  91. control_plane_api/app/routers/secrets.py +155 -0
  92. control_plane_api/app/routers/skills.py +1001 -0
  93. control_plane_api/app/routers/skills_definitions.py +140 -0
  94. control_plane_api/app/routers/task_planning.py +1256 -0
  95. control_plane_api/app/routers/task_queues.py +654 -0
  96. control_plane_api/app/routers/team_context.py +270 -0
  97. control_plane_api/app/routers/teams.py +1400 -0
  98. control_plane_api/app/routers/worker_queues.py +1545 -0
  99. control_plane_api/app/routers/workers.py +935 -0
  100. control_plane_api/app/routers/workflows.py +204 -0
  101. control_plane_api/app/runtimes/__init__.py +6 -0
  102. control_plane_api/app/runtimes/validation.py +344 -0
  103. control_plane_api/app/schemas/job_schemas.py +295 -0
  104. control_plane_api/app/services/__init__.py +1 -0
  105. control_plane_api/app/services/agno_service.py +619 -0
  106. control_plane_api/app/services/litellm_service.py +190 -0
  107. control_plane_api/app/services/policy_service.py +525 -0
  108. control_plane_api/app/services/temporal_cloud_provisioning.py +150 -0
  109. control_plane_api/app/skills/__init__.py +44 -0
  110. control_plane_api/app/skills/base.py +229 -0
  111. control_plane_api/app/skills/business_intelligence.py +189 -0
  112. control_plane_api/app/skills/data_visualization.py +154 -0
  113. control_plane_api/app/skills/docker.py +104 -0
  114. control_plane_api/app/skills/file_generation.py +94 -0
  115. control_plane_api/app/skills/file_system.py +110 -0
  116. control_plane_api/app/skills/python.py +92 -0
  117. control_plane_api/app/skills/registry.py +65 -0
  118. control_plane_api/app/skills/shell.py +102 -0
  119. control_plane_api/app/skills/workflow_executor.py +469 -0
  120. control_plane_api/app/utils/workflow_executor.py +354 -0
  121. control_plane_api/app/workflows/__init__.py +11 -0
  122. control_plane_api/app/workflows/agent_execution.py +507 -0
  123. control_plane_api/app/workflows/agent_execution_with_skills.py +222 -0
  124. control_plane_api/app/workflows/namespace_provisioning.py +326 -0
  125. control_plane_api/app/workflows/team_execution.py +399 -0
  126. control_plane_api/scripts/seed_models.py +239 -0
  127. control_plane_api/worker/__init__.py +0 -0
  128. control_plane_api/worker/activities/__init__.py +0 -0
  129. control_plane_api/worker/activities/agent_activities.py +1241 -0
  130. control_plane_api/worker/activities/approval_activities.py +234 -0
  131. control_plane_api/worker/activities/runtime_activities.py +388 -0
  132. control_plane_api/worker/activities/skill_activities.py +267 -0
  133. control_plane_api/worker/activities/team_activities.py +1217 -0
  134. control_plane_api/worker/config/__init__.py +31 -0
  135. control_plane_api/worker/config/worker_config.py +275 -0
  136. control_plane_api/worker/control_plane_client.py +529 -0
  137. control_plane_api/worker/examples/analytics_integration_example.py +362 -0
  138. control_plane_api/worker/models/__init__.py +1 -0
  139. control_plane_api/worker/models/inputs.py +89 -0
  140. control_plane_api/worker/runtimes/__init__.py +31 -0
  141. control_plane_api/worker/runtimes/base.py +789 -0
  142. control_plane_api/worker/runtimes/claude_code_runtime.py +1443 -0
  143. control_plane_api/worker/runtimes/default_runtime.py +617 -0
  144. control_plane_api/worker/runtimes/factory.py +173 -0
  145. control_plane_api/worker/runtimes/validation.py +93 -0
  146. control_plane_api/worker/services/__init__.py +1 -0
  147. control_plane_api/worker/services/agent_executor.py +422 -0
  148. control_plane_api/worker/services/agent_executor_v2.py +383 -0
  149. control_plane_api/worker/services/analytics_collector.py +457 -0
  150. control_plane_api/worker/services/analytics_service.py +464 -0
  151. control_plane_api/worker/services/approval_tools.py +310 -0
  152. control_plane_api/worker/services/approval_tools_agno.py +207 -0
  153. control_plane_api/worker/services/cancellation_manager.py +177 -0
  154. control_plane_api/worker/services/data_visualization.py +827 -0
  155. control_plane_api/worker/services/jira_tools.py +257 -0
  156. control_plane_api/worker/services/runtime_analytics.py +328 -0
  157. control_plane_api/worker/services/session_service.py +194 -0
  158. control_plane_api/worker/services/skill_factory.py +175 -0
  159. control_plane_api/worker/services/team_executor.py +574 -0
  160. control_plane_api/worker/services/team_executor_v2.py +465 -0
  161. control_plane_api/worker/services/workflow_executor_tools.py +1418 -0
  162. control_plane_api/worker/tests/__init__.py +1 -0
  163. control_plane_api/worker/tests/e2e/__init__.py +0 -0
  164. control_plane_api/worker/tests/e2e/test_execution_flow.py +571 -0
  165. control_plane_api/worker/tests/integration/__init__.py +0 -0
  166. control_plane_api/worker/tests/integration/test_control_plane_integration.py +308 -0
  167. control_plane_api/worker/tests/unit/__init__.py +0 -0
  168. control_plane_api/worker/tests/unit/test_control_plane_client.py +401 -0
  169. control_plane_api/worker/utils/__init__.py +1 -0
  170. control_plane_api/worker/utils/chunk_batcher.py +305 -0
  171. control_plane_api/worker/utils/retry_utils.py +60 -0
  172. control_plane_api/worker/utils/streaming_utils.py +373 -0
  173. control_plane_api/worker/worker.py +753 -0
  174. control_plane_api/worker/workflows/__init__.py +0 -0
  175. control_plane_api/worker/workflows/agent_execution.py +589 -0
  176. control_plane_api/worker/workflows/team_execution.py +429 -0
  177. kubiya_control_plane_api-0.3.4.dist-info/METADATA +229 -0
  178. kubiya_control_plane_api-0.3.4.dist-info/RECORD +182 -0
  179. kubiya_control_plane_api-0.3.4.dist-info/entry_points.txt +2 -0
  180. kubiya_control_plane_api-0.3.4.dist-info/top_level.txt +1 -0
  181. kubiya_control_plane_api-0.1.0.dist-info/METADATA +0 -66
  182. kubiya_control_plane_api-0.1.0.dist-info/RECORD +0 -5
  183. kubiya_control_plane_api-0.1.0.dist-info/top_level.txt +0 -1
  184. {kubiya_control_plane_api-0.1.0.dist-info/licenses → control_plane_api}/LICENSE +0 -0
  185. {kubiya_control_plane_api-0.1.0.dist-info → kubiya_control_plane_api-0.3.4.dist-info}/WHEEL +0 -0
@@ -0,0 +1,287 @@
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
+
12
+
13
+ @dataclass
14
+ class ModelRequirement:
15
+ """Model requirement specification for a runtime."""
16
+
17
+ # Patterns that model IDs must match (any match is valid)
18
+ model_id_patterns: List[str]
19
+
20
+ # Model providers that are supported (e.g., "anthropic", "openai")
21
+ supported_providers: Set[str]
22
+
23
+ # Specific model families supported (e.g., "claude", "gpt")
24
+ supported_families: Set[str]
25
+
26
+ # Human-readable description
27
+ description: str = ""
28
+
29
+ # Examples of valid model IDs
30
+ examples: List[str] = None
31
+
32
+ def __post_init__(self):
33
+ if self.examples is None:
34
+ self.examples = []
35
+
36
+ def validate(self, model_id: Optional[str]) -> tuple[bool, Optional[str]]:
37
+ """
38
+ Validate a model ID against this requirement.
39
+
40
+ Args:
41
+ model_id: Model ID to validate
42
+
43
+ Returns:
44
+ Tuple of (is_valid, error_message)
45
+ """
46
+ if not model_id:
47
+ return False, "Model ID is required for this runtime"
48
+
49
+ # Check pattern matching
50
+ for pattern in self.model_id_patterns:
51
+ if re.search(pattern, model_id, re.IGNORECASE):
52
+ return True, None
53
+
54
+ # Check provider/family
55
+ model_lower = model_id.lower()
56
+
57
+ # Check if any supported family is in the model ID
58
+ for family in self.supported_families:
59
+ if family.lower() in model_lower:
60
+ return True, None
61
+
62
+ # Provide helpful error message
63
+ examples_str = ", ".join(self.examples) if self.examples else "N/A"
64
+ return False, (
65
+ f"Model '{model_id}' is not compatible with this runtime. "
66
+ f"Expected models matching: {', '.join(self.model_id_patterns)}. "
67
+ f"Supported families: {', '.join(self.supported_families)}. "
68
+ f"Examples: {examples_str}"
69
+ )
70
+
71
+
72
+ @dataclass
73
+ class RuntimeRequirements:
74
+ """Requirements specification for a runtime."""
75
+
76
+ runtime_type: str
77
+
78
+ # Model requirements
79
+ model_requirement: ModelRequirement
80
+
81
+ # Required fields in agent/team config
82
+ required_config_fields: List[str] = None
83
+
84
+ # Optional but recommended fields
85
+ recommended_config_fields: List[str] = None
86
+
87
+ # Maximum conversation history length
88
+ max_history_length: Optional[int] = None
89
+
90
+ # Whether system prompt is required
91
+ requires_system_prompt: bool = False
92
+
93
+ # Whether tools/skills are required
94
+ requires_tools: bool = False
95
+
96
+ def __post_init__(self):
97
+ if self.required_config_fields is None:
98
+ self.required_config_fields = []
99
+ if self.recommended_config_fields is None:
100
+ self.recommended_config_fields = []
101
+
102
+ def validate_model(self, model_id: Optional[str]) -> tuple[bool, Optional[str]]:
103
+ """Validate model compatibility."""
104
+ return self.model_requirement.validate(model_id)
105
+
106
+ def validate_config(self, config: Optional[Dict[str, Any]]) -> List[str]:
107
+ """
108
+ Validate agent/team configuration.
109
+
110
+ Returns:
111
+ List of validation errors (empty if valid)
112
+ """
113
+ errors = []
114
+
115
+ if not config:
116
+ if self.required_config_fields:
117
+ errors.append(
118
+ f"Configuration is required for this runtime. "
119
+ f"Required fields: {', '.join(self.required_config_fields)}"
120
+ )
121
+ return errors
122
+
123
+ # Check required fields
124
+ for field in self.required_config_fields:
125
+ if field not in config or config[field] is None:
126
+ errors.append(f"Required field '{field}' is missing in configuration")
127
+
128
+ return errors
129
+
130
+
131
+ # ==================== Runtime Requirements Definitions ====================
132
+
133
+ # Agno/Default Runtime - Flexible, supports most models
134
+ DEFAULT_RUNTIME_REQUIREMENTS = RuntimeRequirements(
135
+ runtime_type="default",
136
+ model_requirement=ModelRequirement(
137
+ model_id_patterns=[
138
+ r".*", # Accept all models
139
+ ],
140
+ supported_providers={"openai", "anthropic", "azure", "google", "mistral", "cohere"},
141
+ supported_families={"gpt", "claude", "gemini", "mistral", "command"},
142
+ description="Default runtime supports most LiteLLM-compatible models",
143
+ examples=[
144
+ "gpt-4",
145
+ "gpt-4-turbo",
146
+ "gpt-3.5-turbo",
147
+ "claude-3-opus",
148
+ "claude-3-sonnet",
149
+ "claude-sonnet-4",
150
+ "gemini-pro",
151
+ "mistral-large",
152
+ ],
153
+ ),
154
+ max_history_length=100, # Reasonable default
155
+ requires_system_prompt=False,
156
+ requires_tools=False,
157
+ )
158
+
159
+ # Claude Code Runtime - Requires Claude models
160
+ CLAUDE_CODE_RUNTIME_REQUIREMENTS = RuntimeRequirements(
161
+ runtime_type="claude_code",
162
+ model_requirement=ModelRequirement(
163
+ model_id_patterns=[
164
+ r"claude", # Must contain "claude"
165
+ r"kubiya/claude", # LiteLLM proxy format
166
+ r"anthropic\.claude", # Alternative format
167
+ ],
168
+ supported_providers={"anthropic"},
169
+ supported_families={"claude"},
170
+ description=(
171
+ "Claude Code runtime requires Anthropic Claude models. "
172
+ "This runtime leverages Claude's advanced capabilities including "
173
+ "extended context, tool use, and code understanding."
174
+ ),
175
+ examples=[
176
+ "claude-3-opus-20240229",
177
+ "claude-3-sonnet-20240229",
178
+ "claude-3-5-sonnet-20241022",
179
+ "claude-3-haiku-20240307",
180
+ "claude-sonnet-4",
181
+ "claude-opus-4",
182
+ "kubiya/claude-sonnet-4",
183
+ "kubiya/claude-opus-4",
184
+ ],
185
+ ),
186
+ max_history_length=200, # Claude handles longer contexts well
187
+ requires_system_prompt=False, # Optional but recommended
188
+ requires_tools=False, # Claude Code adds tools automatically
189
+ recommended_config_fields=["timeout", "max_tokens"],
190
+ )
191
+
192
+
193
+ # Registry of runtime requirements
194
+ RUNTIME_REQUIREMENTS: Dict[str, RuntimeRequirements] = {
195
+ "default": DEFAULT_RUNTIME_REQUIREMENTS,
196
+ "claude_code": CLAUDE_CODE_RUNTIME_REQUIREMENTS,
197
+ }
198
+
199
+
200
+ # ==================== Validation Functions ====================
201
+
202
+ def validate_agent_for_runtime(
203
+ runtime_type: str,
204
+ model_id: Optional[str],
205
+ agent_config: Optional[Dict[str, Any]] = None,
206
+ system_prompt: Optional[str] = None,
207
+ ) -> tuple[bool, List[str]]:
208
+ """
209
+ Validate agent configuration for a runtime.
210
+
211
+ Args:
212
+ runtime_type: Runtime type string (e.g., "default", "claude_code")
213
+ model_id: Model ID to validate
214
+ agent_config: Agent configuration dict
215
+ system_prompt: System prompt
216
+
217
+ Returns:
218
+ Tuple of (is_valid, error_messages)
219
+ """
220
+ requirements = RUNTIME_REQUIREMENTS.get(runtime_type)
221
+ if not requirements:
222
+ # No requirements registered - allow by default
223
+ return True, []
224
+
225
+ errors = []
226
+
227
+ # Validate model
228
+ is_valid, error = requirements.validate_model(model_id)
229
+ if not is_valid:
230
+ errors.append(error)
231
+
232
+ # Validate config
233
+ config_errors = requirements.validate_config(agent_config)
234
+ errors.extend(config_errors)
235
+
236
+ # Validate system prompt if required
237
+ if requirements.requires_system_prompt and not system_prompt:
238
+ errors.append("System prompt is required for this runtime")
239
+
240
+ return len(errors) == 0, errors
241
+
242
+
243
+ def get_runtime_requirements_info(runtime_type: str) -> Dict[str, Any]:
244
+ """
245
+ Get human-readable requirements info for a runtime.
246
+
247
+ Args:
248
+ runtime_type: Runtime type string
249
+
250
+ Returns:
251
+ Dict with requirements information
252
+ """
253
+ requirements = RUNTIME_REQUIREMENTS.get(runtime_type)
254
+ if not requirements:
255
+ return {
256
+ "runtime_type": runtime_type,
257
+ "model_requirement": "No specific requirements",
258
+ "flexible": True,
259
+ }
260
+
261
+ return {
262
+ "runtime_type": runtime_type,
263
+ "model_requirement": {
264
+ "description": requirements.model_requirement.description,
265
+ "supported_providers": list(requirements.model_requirement.supported_providers),
266
+ "supported_families": list(requirements.model_requirement.supported_families),
267
+ "examples": requirements.model_requirement.examples,
268
+ },
269
+ "required_config_fields": requirements.required_config_fields,
270
+ "recommended_config_fields": requirements.recommended_config_fields,
271
+ "max_history_length": requirements.max_history_length,
272
+ "requires_system_prompt": requirements.requires_system_prompt,
273
+ "requires_tools": requirements.requires_tools,
274
+ }
275
+
276
+
277
+ def list_all_runtime_requirements() -> Dict[str, Dict[str, Any]]:
278
+ """
279
+ Get requirements for all registered runtimes.
280
+
281
+ Returns:
282
+ Dict mapping runtime type to requirements info
283
+ """
284
+ return {
285
+ runtime_type: get_runtime_requirements_info(runtime_type)
286
+ for runtime_type in RUNTIME_REQUIREMENTS.keys()
287
+ }
@@ -0,0 +1,128 @@
1
+ from fastapi import FastAPI
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from contextlib import asynccontextmanager
4
+ import structlog
5
+
6
+ from control_plane_api.app.config import settings
7
+ from control_plane_api.app.routers import agents, teams, workflows, health, executions, presence, runners, workers, projects, models, models_v2, task_queues, worker_queues, environment_context, team_context, context_manager, skills, skills_definitions, environments, runtimes, secrets, integrations, execution_environment, policies, task_planning, jobs, analytics
8
+ from control_plane_api.app.routers import agents_v2 # New multi-tenant agent router
9
+
10
+ # Configure structured logging
11
+ import logging
12
+
13
+ structlog.configure(
14
+ processors=[
15
+ structlog.contextvars.merge_contextvars,
16
+ structlog.processors.add_log_level,
17
+ structlog.processors.TimeStamper(fmt="iso"),
18
+ structlog.processors.JSONRenderer(),
19
+ ],
20
+ wrapper_class=structlog.make_filtering_bound_logger(
21
+ getattr(logging, settings.log_level.upper(), logging.INFO)
22
+ ),
23
+ logger_factory=structlog.PrintLoggerFactory(),
24
+ )
25
+
26
+ logger = structlog.get_logger()
27
+
28
+
29
+ @asynccontextmanager
30
+ async def lifespan(app: FastAPI):
31
+ """Application lifespan manager for serverless"""
32
+ logger.info(
33
+ "agent_control_plane_starting",
34
+ version=settings.api_version,
35
+ environment=settings.environment
36
+ )
37
+ # No database initialization needed for serverless
38
+ # Supabase client is initialized on-demand
39
+ yield
40
+ logger.info("agent_control_plane_shutting_down")
41
+
42
+
43
+ # Create FastAPI application
44
+ app = FastAPI(
45
+ title=settings.api_title,
46
+ version=settings.api_version,
47
+ description=settings.api_description,
48
+ lifespan=lifespan,
49
+ # Disable lifespan for Vercel (will be "off" via Mangum)
50
+ openapi_url="/api/openapi.json" if settings.environment != "production" else None,
51
+ docs_url="/api/docs" if settings.environment != "production" else None,
52
+ redoc_url="/api/redoc" if settings.environment != "production" else None,
53
+ )
54
+
55
+ # Add CORS middleware
56
+ app.add_middleware(
57
+ CORSMiddleware,
58
+ allow_origins=settings.cors_origins,
59
+ allow_credentials=True,
60
+ allow_methods=["*"],
61
+ allow_headers=["*"],
62
+ )
63
+
64
+ # Include routers (all routes under /api/v1)
65
+ app.include_router(health.router, prefix="/api", tags=["Health"])
66
+ app.include_router(models_v2.router, prefix="/api/v1/models", tags=["Models"]) # LLM models CRUD (database-backed)
67
+ app.include_router(runtimes.router, prefix="/api/v1", tags=["Runtimes"]) # Agent runtime types
68
+ app.include_router(secrets.router, prefix="/api/v1", tags=["Secrets"]) # Kubiya secrets proxy
69
+ app.include_router(integrations.router, prefix="/api/v1", tags=["Integrations"]) # Kubiya integrations proxy
70
+ app.include_router(execution_environment.router, prefix="/api/v1", tags=["Execution Environment"]) # Resolved execution environment for workers
71
+ app.include_router(projects.router, prefix="/api/v1/projects", tags=["Projects"]) # Multi-project management
72
+ app.include_router(environments.router, prefix="/api/v1/environments", tags=["Environments"]) # Environment management
73
+ app.include_router(task_queues.router, prefix="/api/v1/task-queues", tags=["Task Queues"]) # Legacy endpoint (use /environments)
74
+ app.include_router(worker_queues.router, prefix="/api/v1", tags=["Worker Queues"]) # Worker queue management per environment
75
+ app.include_router(environment_context.router, prefix="/api/v1", tags=["Environment Context"]) # Environment context management
76
+ app.include_router(team_context.router, prefix="/api/v1", tags=["Team Context"]) # Team context management
77
+ app.include_router(context_manager.router, prefix="/api/v1", tags=["Context Manager"]) # Unified context management
78
+ app.include_router(skills_definitions.router, prefix="/api/v1/skills", tags=["Tool Sets"]) # Skill definitions and templates (must be before skills.router)
79
+ app.include_router(skills.router, prefix="/api/v1/skills", tags=["Tool Sets"]) # Tool sets management
80
+ app.include_router(policies.router, prefix="/api/v1/policies", tags=["Policies"]) # Policy management and enforcement
81
+ app.include_router(task_planning.router, prefix="/api/v1", tags=["Task Planning"]) # AI-powered task planning
82
+ app.include_router(agents_v2.router, prefix="/api/v1/agents", tags=["Agents"]) # Use new multi-tenant router
83
+ app.include_router(runners.router, prefix="/api/v1/runners", tags=["Runners"]) # Proxy to Kubiya API
84
+ app.include_router(workers.router, prefix="/api/v1/workers", tags=["Workers"]) # Worker registration and heartbeats
85
+ app.include_router(teams.router, prefix="/api/v1/teams", tags=["Teams"])
86
+ app.include_router(workflows.router, prefix="/api/v1/workflows", tags=["Workflows"])
87
+ app.include_router(executions.router, prefix="/api/v1/executions", tags=["Executions"])
88
+ app.include_router(presence.router, prefix="/api/v1/presence", tags=["Presence"])
89
+ app.include_router(jobs.router, prefix="/api/v1/jobs", tags=["Jobs"]) # Scheduled and webhook-triggered jobs
90
+ app.include_router(analytics.router, prefix="/api/v1/analytics", tags=["Analytics"]) # Execution metrics and reporting
91
+
92
+
93
+ @app.get("/")
94
+ async def root():
95
+ """Root endpoint"""
96
+ return {
97
+ "message": "Welcome to Agent Control Plane",
98
+ "version": settings.api_version,
99
+ "environment": settings.environment,
100
+ "docs": "/api/docs" if settings.environment != "production" else None,
101
+ }
102
+
103
+
104
+ @app.get("/api")
105
+ async def api_root():
106
+ """API root endpoint"""
107
+ return {
108
+ "message": "Agent Control Plane API",
109
+ "version": settings.api_version,
110
+ "endpoints": {
111
+ "projects": "/api/v1/projects",
112
+ "task_queues": "/api/v1/task-queues",
113
+ "agents": "/api/v1/agents",
114
+ "teams": "/api/v1/teams",
115
+ "skills": "/api/v1/skills",
116
+ "policies": "/api/v1/policies",
117
+ "workflows": "/api/v1/workflows",
118
+ "executions": "/api/v1/executions",
119
+ "presence": "/api/v1/presence",
120
+ "runners": "/api/v1/runners",
121
+ "workers": "/api/v1/workers",
122
+ "models": "/api/v1/models",
123
+ "runtimes": "/api/v1/runtimes",
124
+ "secrets": "/api/v1/secrets",
125
+ "integrations": "/api/v1/integrations",
126
+ "health": "/api/health",
127
+ }
128
+ }
@@ -0,0 +1,8 @@
1
+ """Middleware modules"""
2
+
3
+ from control_plane_api.app.middleware.auth import get_current_organization, extract_token_from_headers
4
+
5
+ __all__ = [
6
+ "get_current_organization",
7
+ "extract_token_from_headers",
8
+ ]