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.
- control_plane_api/README.md +266 -0
- control_plane_api/__init__.py +0 -0
- control_plane_api/__version__.py +1 -0
- control_plane_api/alembic/README +1 -0
- control_plane_api/alembic/env.py +98 -0
- control_plane_api/alembic/script.py.mako +28 -0
- control_plane_api/alembic/versions/1382bec74309_initial_migration_with_all_models.py +251 -0
- control_plane_api/alembic/versions/1f54bc2a37e3_add_analytics_tables.py +162 -0
- control_plane_api/alembic/versions/2e4cb136dc10_rename_toolset_ids_to_skill_ids_in_teams.py +30 -0
- control_plane_api/alembic/versions/31cd69a644ce_add_skill_templates_table.py +28 -0
- control_plane_api/alembic/versions/89e127caa47d_add_jobs_and_job_executions_tables.py +161 -0
- control_plane_api/alembic/versions/add_llm_models_table.py +51 -0
- control_plane_api/alembic/versions/b0e10697f212_add_runtime_column_to_teams_simple.py +42 -0
- control_plane_api/alembic/versions/ce43b24b63bf_add_execution_trigger_source_and_fix_.py +155 -0
- control_plane_api/alembic/versions/d4eaf16e3f8d_rename_toolsets_to_skills.py +84 -0
- control_plane_api/alembic/versions/efa2dc427da1_rename_metadata_to_custom_metadata.py +32 -0
- control_plane_api/alembic/versions/f973b431d1ce_add_workflow_executor_to_skill_types.py +44 -0
- control_plane_api/alembic.ini +148 -0
- control_plane_api/api/index.py +12 -0
- control_plane_api/app/__init__.py +11 -0
- control_plane_api/app/activities/__init__.py +20 -0
- control_plane_api/app/activities/agent_activities.py +379 -0
- control_plane_api/app/activities/team_activities.py +410 -0
- control_plane_api/app/activities/temporal_cloud_activities.py +577 -0
- control_plane_api/app/config/__init__.py +35 -0
- control_plane_api/app/config/api_config.py +354 -0
- control_plane_api/app/config/model_pricing.py +318 -0
- control_plane_api/app/config.py +95 -0
- control_plane_api/app/database.py +135 -0
- control_plane_api/app/exceptions.py +408 -0
- control_plane_api/app/lib/__init__.py +11 -0
- control_plane_api/app/lib/job_executor.py +312 -0
- control_plane_api/app/lib/kubiya_client.py +235 -0
- control_plane_api/app/lib/litellm_pricing.py +166 -0
- control_plane_api/app/lib/planning_tools/__init__.py +22 -0
- control_plane_api/app/lib/planning_tools/agents.py +155 -0
- control_plane_api/app/lib/planning_tools/base.py +189 -0
- control_plane_api/app/lib/planning_tools/environments.py +214 -0
- control_plane_api/app/lib/planning_tools/resources.py +240 -0
- control_plane_api/app/lib/planning_tools/teams.py +198 -0
- control_plane_api/app/lib/policy_enforcer_client.py +939 -0
- control_plane_api/app/lib/redis_client.py +436 -0
- control_plane_api/app/lib/supabase.py +71 -0
- control_plane_api/app/lib/temporal_client.py +138 -0
- control_plane_api/app/lib/validation/__init__.py +20 -0
- control_plane_api/app/lib/validation/runtime_validation.py +287 -0
- control_plane_api/app/main.py +128 -0
- control_plane_api/app/middleware/__init__.py +8 -0
- control_plane_api/app/middleware/auth.py +513 -0
- control_plane_api/app/middleware/exception_handler.py +267 -0
- control_plane_api/app/middleware/rate_limiting.py +384 -0
- control_plane_api/app/middleware/request_id.py +202 -0
- control_plane_api/app/models/__init__.py +27 -0
- control_plane_api/app/models/agent.py +79 -0
- control_plane_api/app/models/analytics.py +206 -0
- control_plane_api/app/models/associations.py +81 -0
- control_plane_api/app/models/environment.py +63 -0
- control_plane_api/app/models/execution.py +93 -0
- control_plane_api/app/models/job.py +179 -0
- control_plane_api/app/models/llm_model.py +75 -0
- control_plane_api/app/models/presence.py +49 -0
- control_plane_api/app/models/project.py +47 -0
- control_plane_api/app/models/session.py +38 -0
- control_plane_api/app/models/team.py +66 -0
- control_plane_api/app/models/workflow.py +55 -0
- control_plane_api/app/policies/README.md +121 -0
- control_plane_api/app/policies/approved_users.rego +62 -0
- control_plane_api/app/policies/business_hours.rego +51 -0
- control_plane_api/app/policies/rate_limiting.rego +100 -0
- control_plane_api/app/policies/tool_restrictions.rego +86 -0
- control_plane_api/app/routers/__init__.py +4 -0
- control_plane_api/app/routers/agents.py +364 -0
- control_plane_api/app/routers/agents_v2.py +1260 -0
- control_plane_api/app/routers/analytics.py +1014 -0
- control_plane_api/app/routers/context_manager.py +562 -0
- control_plane_api/app/routers/environment_context.py +270 -0
- control_plane_api/app/routers/environments.py +715 -0
- control_plane_api/app/routers/execution_environment.py +517 -0
- control_plane_api/app/routers/executions.py +1911 -0
- control_plane_api/app/routers/health.py +92 -0
- control_plane_api/app/routers/health_v2.py +326 -0
- control_plane_api/app/routers/integrations.py +274 -0
- control_plane_api/app/routers/jobs.py +1344 -0
- control_plane_api/app/routers/models.py +82 -0
- control_plane_api/app/routers/models_v2.py +361 -0
- control_plane_api/app/routers/policies.py +639 -0
- control_plane_api/app/routers/presence.py +234 -0
- control_plane_api/app/routers/projects.py +902 -0
- control_plane_api/app/routers/runners.py +379 -0
- control_plane_api/app/routers/runtimes.py +172 -0
- control_plane_api/app/routers/secrets.py +155 -0
- control_plane_api/app/routers/skills.py +1001 -0
- control_plane_api/app/routers/skills_definitions.py +140 -0
- control_plane_api/app/routers/task_planning.py +1256 -0
- control_plane_api/app/routers/task_queues.py +654 -0
- control_plane_api/app/routers/team_context.py +270 -0
- control_plane_api/app/routers/teams.py +1400 -0
- control_plane_api/app/routers/worker_queues.py +1545 -0
- control_plane_api/app/routers/workers.py +935 -0
- control_plane_api/app/routers/workflows.py +204 -0
- control_plane_api/app/runtimes/__init__.py +6 -0
- control_plane_api/app/runtimes/validation.py +344 -0
- control_plane_api/app/schemas/job_schemas.py +295 -0
- control_plane_api/app/services/__init__.py +1 -0
- control_plane_api/app/services/agno_service.py +619 -0
- control_plane_api/app/services/litellm_service.py +190 -0
- control_plane_api/app/services/policy_service.py +525 -0
- control_plane_api/app/services/temporal_cloud_provisioning.py +150 -0
- control_plane_api/app/skills/__init__.py +44 -0
- control_plane_api/app/skills/base.py +229 -0
- control_plane_api/app/skills/business_intelligence.py +189 -0
- control_plane_api/app/skills/data_visualization.py +154 -0
- control_plane_api/app/skills/docker.py +104 -0
- control_plane_api/app/skills/file_generation.py +94 -0
- control_plane_api/app/skills/file_system.py +110 -0
- control_plane_api/app/skills/python.py +92 -0
- control_plane_api/app/skills/registry.py +65 -0
- control_plane_api/app/skills/shell.py +102 -0
- control_plane_api/app/skills/workflow_executor.py +469 -0
- control_plane_api/app/utils/workflow_executor.py +354 -0
- control_plane_api/app/workflows/__init__.py +11 -0
- control_plane_api/app/workflows/agent_execution.py +507 -0
- control_plane_api/app/workflows/agent_execution_with_skills.py +222 -0
- control_plane_api/app/workflows/namespace_provisioning.py +326 -0
- control_plane_api/app/workflows/team_execution.py +399 -0
- control_plane_api/scripts/seed_models.py +239 -0
- control_plane_api/worker/__init__.py +0 -0
- control_plane_api/worker/activities/__init__.py +0 -0
- control_plane_api/worker/activities/agent_activities.py +1241 -0
- control_plane_api/worker/activities/approval_activities.py +234 -0
- control_plane_api/worker/activities/runtime_activities.py +388 -0
- control_plane_api/worker/activities/skill_activities.py +267 -0
- control_plane_api/worker/activities/team_activities.py +1217 -0
- control_plane_api/worker/config/__init__.py +31 -0
- control_plane_api/worker/config/worker_config.py +275 -0
- control_plane_api/worker/control_plane_client.py +529 -0
- control_plane_api/worker/examples/analytics_integration_example.py +362 -0
- control_plane_api/worker/models/__init__.py +1 -0
- control_plane_api/worker/models/inputs.py +89 -0
- control_plane_api/worker/runtimes/__init__.py +31 -0
- control_plane_api/worker/runtimes/base.py +789 -0
- control_plane_api/worker/runtimes/claude_code_runtime.py +1443 -0
- control_plane_api/worker/runtimes/default_runtime.py +617 -0
- control_plane_api/worker/runtimes/factory.py +173 -0
- control_plane_api/worker/runtimes/validation.py +93 -0
- control_plane_api/worker/services/__init__.py +1 -0
- control_plane_api/worker/services/agent_executor.py +422 -0
- control_plane_api/worker/services/agent_executor_v2.py +383 -0
- control_plane_api/worker/services/analytics_collector.py +457 -0
- control_plane_api/worker/services/analytics_service.py +464 -0
- control_plane_api/worker/services/approval_tools.py +310 -0
- control_plane_api/worker/services/approval_tools_agno.py +207 -0
- control_plane_api/worker/services/cancellation_manager.py +177 -0
- control_plane_api/worker/services/data_visualization.py +827 -0
- control_plane_api/worker/services/jira_tools.py +257 -0
- control_plane_api/worker/services/runtime_analytics.py +328 -0
- control_plane_api/worker/services/session_service.py +194 -0
- control_plane_api/worker/services/skill_factory.py +175 -0
- control_plane_api/worker/services/team_executor.py +574 -0
- control_plane_api/worker/services/team_executor_v2.py +465 -0
- control_plane_api/worker/services/workflow_executor_tools.py +1418 -0
- control_plane_api/worker/tests/__init__.py +1 -0
- control_plane_api/worker/tests/e2e/__init__.py +0 -0
- control_plane_api/worker/tests/e2e/test_execution_flow.py +571 -0
- control_plane_api/worker/tests/integration/__init__.py +0 -0
- control_plane_api/worker/tests/integration/test_control_plane_integration.py +308 -0
- control_plane_api/worker/tests/unit/__init__.py +0 -0
- control_plane_api/worker/tests/unit/test_control_plane_client.py +401 -0
- control_plane_api/worker/utils/__init__.py +1 -0
- control_plane_api/worker/utils/chunk_batcher.py +305 -0
- control_plane_api/worker/utils/retry_utils.py +60 -0
- control_plane_api/worker/utils/streaming_utils.py +373 -0
- control_plane_api/worker/worker.py +753 -0
- control_plane_api/worker/workflows/__init__.py +0 -0
- control_plane_api/worker/workflows/agent_execution.py +589 -0
- control_plane_api/worker/workflows/team_execution.py +429 -0
- kubiya_control_plane_api-0.3.4.dist-info/METADATA +229 -0
- kubiya_control_plane_api-0.3.4.dist-info/RECORD +182 -0
- kubiya_control_plane_api-0.3.4.dist-info/entry_points.txt +2 -0
- kubiya_control_plane_api-0.3.4.dist-info/top_level.txt +1 -0
- kubiya_control_plane_api-0.1.0.dist-info/METADATA +0 -66
- kubiya_control_plane_api-0.1.0.dist-info/RECORD +0 -5
- kubiya_control_plane_api-0.1.0.dist-info/top_level.txt +0 -1
- {kubiya_control_plane_api-0.1.0.dist-info/licenses → control_plane_api}/LICENSE +0 -0
- {kubiya_control_plane_api-0.1.0.dist-info → kubiya_control_plane_api-0.3.4.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Environment Context router - Manage contextual settings for environments.
|
|
3
|
+
|
|
4
|
+
Allows attaching knowledge and resources to environments for agent execution context.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from fastapi import APIRouter, Depends, HTTPException, status, Request
|
|
8
|
+
from typing import List
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from pydantic import BaseModel, Field
|
|
11
|
+
import structlog
|
|
12
|
+
import uuid
|
|
13
|
+
|
|
14
|
+
from control_plane_api.app.middleware.auth import get_current_organization
|
|
15
|
+
from control_plane_api.app.lib.supabase import get_supabase
|
|
16
|
+
|
|
17
|
+
logger = structlog.get_logger()
|
|
18
|
+
|
|
19
|
+
router = APIRouter()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Pydantic schemas
|
|
23
|
+
class UpdateEnvironmentContextRequest(BaseModel):
|
|
24
|
+
knowledge_uuids: List[str] = Field(default_factory=list, description="Array of knowledge UUIDs")
|
|
25
|
+
resource_ids: List[str] = Field(default_factory=list, description="Array of resource IDs from Meilisearch")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class EnvironmentContextResponse(BaseModel):
|
|
29
|
+
id: str
|
|
30
|
+
environment_id: str
|
|
31
|
+
organization_id: str
|
|
32
|
+
knowledge_uuids: List[str]
|
|
33
|
+
resource_ids: List[str]
|
|
34
|
+
created_at: str
|
|
35
|
+
updated_at: str
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@router.get("/environments/{environment_id}/context", response_model=EnvironmentContextResponse)
|
|
39
|
+
async def get_environment_context(
|
|
40
|
+
environment_id: str,
|
|
41
|
+
request: Request,
|
|
42
|
+
organization: dict = Depends(get_current_organization),
|
|
43
|
+
):
|
|
44
|
+
"""Get context configuration for an environment"""
|
|
45
|
+
try:
|
|
46
|
+
client = get_supabase()
|
|
47
|
+
org_id = organization["id"]
|
|
48
|
+
|
|
49
|
+
# Verify environment exists
|
|
50
|
+
env_result = (
|
|
51
|
+
client.table("environments")
|
|
52
|
+
.select("id")
|
|
53
|
+
.eq("id", environment_id)
|
|
54
|
+
.eq("organization_id", org_id)
|
|
55
|
+
.single()
|
|
56
|
+
.execute()
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
if not env_result.data:
|
|
60
|
+
raise HTTPException(
|
|
61
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
62
|
+
detail="Environment not found"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Get or create context
|
|
66
|
+
context_result = (
|
|
67
|
+
client.table("environment_contexts")
|
|
68
|
+
.select("*")
|
|
69
|
+
.eq("environment_id", environment_id)
|
|
70
|
+
.eq("organization_id", org_id)
|
|
71
|
+
.single()
|
|
72
|
+
.execute()
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
if context_result.data:
|
|
76
|
+
return EnvironmentContextResponse(**context_result.data)
|
|
77
|
+
|
|
78
|
+
# Create default context if it doesn't exist
|
|
79
|
+
context_id = str(uuid.uuid4())
|
|
80
|
+
now = datetime.utcnow().isoformat()
|
|
81
|
+
|
|
82
|
+
default_context = {
|
|
83
|
+
"id": context_id,
|
|
84
|
+
"environment_id": environment_id,
|
|
85
|
+
"organization_id": org_id,
|
|
86
|
+
"knowledge_uuids": [],
|
|
87
|
+
"resource_ids": [],
|
|
88
|
+
"created_at": now,
|
|
89
|
+
"updated_at": now,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
result = client.table("environment_contexts").insert(default_context).execute()
|
|
93
|
+
|
|
94
|
+
if not result.data:
|
|
95
|
+
raise HTTPException(
|
|
96
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
97
|
+
detail="Failed to create environment context"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
logger.info(
|
|
101
|
+
"environment_context_created",
|
|
102
|
+
environment_id=environment_id,
|
|
103
|
+
org_id=org_id,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
return EnvironmentContextResponse(**result.data[0])
|
|
107
|
+
|
|
108
|
+
except HTTPException:
|
|
109
|
+
raise
|
|
110
|
+
except Exception as e:
|
|
111
|
+
logger.error("get_environment_context_failed", error=str(e), environment_id=environment_id)
|
|
112
|
+
raise HTTPException(
|
|
113
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
114
|
+
detail=f"Failed to get environment context: {str(e)}"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@router.put("/environments/{environment_id}/context", response_model=EnvironmentContextResponse)
|
|
119
|
+
async def update_environment_context(
|
|
120
|
+
environment_id: str,
|
|
121
|
+
context_data: UpdateEnvironmentContextRequest,
|
|
122
|
+
request: Request,
|
|
123
|
+
organization: dict = Depends(get_current_organization),
|
|
124
|
+
):
|
|
125
|
+
"""Update context configuration for an environment"""
|
|
126
|
+
try:
|
|
127
|
+
client = get_supabase()
|
|
128
|
+
org_id = organization["id"]
|
|
129
|
+
|
|
130
|
+
# Verify environment exists
|
|
131
|
+
env_result = (
|
|
132
|
+
client.table("environments")
|
|
133
|
+
.select("id")
|
|
134
|
+
.eq("id", environment_id)
|
|
135
|
+
.eq("organization_id", org_id)
|
|
136
|
+
.single()
|
|
137
|
+
.execute()
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
if not env_result.data:
|
|
141
|
+
raise HTTPException(
|
|
142
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
143
|
+
detail="Environment not found"
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# Check if context exists
|
|
147
|
+
existing_context = (
|
|
148
|
+
client.table("environment_contexts")
|
|
149
|
+
.select("id")
|
|
150
|
+
.eq("environment_id", environment_id)
|
|
151
|
+
.eq("organization_id", org_id)
|
|
152
|
+
.single()
|
|
153
|
+
.execute()
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
now = datetime.utcnow().isoformat()
|
|
157
|
+
|
|
158
|
+
if existing_context.data:
|
|
159
|
+
# Update existing context
|
|
160
|
+
update_data = {
|
|
161
|
+
"knowledge_uuids": context_data.knowledge_uuids,
|
|
162
|
+
"resource_ids": context_data.resource_ids,
|
|
163
|
+
"updated_at": now,
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
result = (
|
|
167
|
+
client.table("environment_contexts")
|
|
168
|
+
.update(update_data)
|
|
169
|
+
.eq("id", existing_context.data["id"])
|
|
170
|
+
.execute()
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
if not result.data:
|
|
174
|
+
raise HTTPException(
|
|
175
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
176
|
+
detail="Failed to update environment context"
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
logger.info(
|
|
180
|
+
"environment_context_updated",
|
|
181
|
+
environment_id=environment_id,
|
|
182
|
+
knowledge_count=len(context_data.knowledge_uuids),
|
|
183
|
+
resource_count=len(context_data.resource_ids),
|
|
184
|
+
org_id=org_id,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
return EnvironmentContextResponse(**result.data[0])
|
|
188
|
+
else:
|
|
189
|
+
# Create new context
|
|
190
|
+
context_id = str(uuid.uuid4())
|
|
191
|
+
|
|
192
|
+
new_context = {
|
|
193
|
+
"id": context_id,
|
|
194
|
+
"environment_id": environment_id,
|
|
195
|
+
"organization_id": org_id,
|
|
196
|
+
"knowledge_uuids": context_data.knowledge_uuids,
|
|
197
|
+
"resource_ids": context_data.resource_ids,
|
|
198
|
+
"created_at": now,
|
|
199
|
+
"updated_at": now,
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
result = client.table("environment_contexts").insert(new_context).execute()
|
|
203
|
+
|
|
204
|
+
if not result.data:
|
|
205
|
+
raise HTTPException(
|
|
206
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
207
|
+
detail="Failed to create environment context"
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
logger.info(
|
|
211
|
+
"environment_context_created",
|
|
212
|
+
environment_id=environment_id,
|
|
213
|
+
knowledge_count=len(context_data.knowledge_uuids),
|
|
214
|
+
resource_count=len(context_data.resource_ids),
|
|
215
|
+
org_id=org_id,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
return EnvironmentContextResponse(**result.data[0])
|
|
219
|
+
|
|
220
|
+
except HTTPException:
|
|
221
|
+
raise
|
|
222
|
+
except Exception as e:
|
|
223
|
+
logger.error("update_environment_context_failed", error=str(e), environment_id=environment_id)
|
|
224
|
+
raise HTTPException(
|
|
225
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
226
|
+
detail=f"Failed to update environment context: {str(e)}"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
@router.delete("/environments/{environment_id}/context", status_code=status.HTTP_204_NO_CONTENT)
|
|
231
|
+
async def clear_environment_context(
|
|
232
|
+
environment_id: str,
|
|
233
|
+
request: Request,
|
|
234
|
+
organization: dict = Depends(get_current_organization),
|
|
235
|
+
):
|
|
236
|
+
"""Clear all context for an environment (reset to empty arrays)"""
|
|
237
|
+
try:
|
|
238
|
+
client = get_supabase()
|
|
239
|
+
org_id = organization["id"]
|
|
240
|
+
|
|
241
|
+
# Update context to empty arrays
|
|
242
|
+
now = datetime.utcnow().isoformat()
|
|
243
|
+
update_data = {
|
|
244
|
+
"knowledge_uuids": [],
|
|
245
|
+
"resource_ids": [],
|
|
246
|
+
"updated_at": now,
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
result = (
|
|
250
|
+
client.table("environment_contexts")
|
|
251
|
+
.update(update_data)
|
|
252
|
+
.eq("environment_id", environment_id)
|
|
253
|
+
.eq("organization_id", org_id)
|
|
254
|
+
.execute()
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
logger.info(
|
|
258
|
+
"environment_context_cleared",
|
|
259
|
+
environment_id=environment_id,
|
|
260
|
+
org_id=org_id,
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
return None
|
|
264
|
+
|
|
265
|
+
except Exception as e:
|
|
266
|
+
logger.error("clear_environment_context_failed", error=str(e), environment_id=environment_id)
|
|
267
|
+
raise HTTPException(
|
|
268
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
269
|
+
detail=f"Failed to clear environment context: {str(e)}"
|
|
270
|
+
)
|