feat: add Ops AI Workspace npm setup command
This commit is contained in:
@@ -10,6 +10,7 @@ from plane.app.views import (
|
||||
AIWorkspaceExecutorEventsEndpoint,
|
||||
AIWorkspaceExecutorListEndpoint,
|
||||
AIWorkspaceExecutorSelectEndpoint,
|
||||
AIWorkspaceExecutorSetupCommandEndpoint,
|
||||
AIWorkspaceExecutorWindowsAgentEndpoint,
|
||||
AIWorkspaceSettingsEndpoint,
|
||||
AIWorkspaceThreadDispatchEndpoint,
|
||||
@@ -55,6 +56,11 @@ urlpatterns = [
|
||||
AIWorkspaceExecutorWindowsAgentEndpoint.as_view(),
|
||||
name="ai-workspace-executor-windows-agent",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/ai-workspace/executors/<uuid:executor_id>/agent/setup-command/",
|
||||
AIWorkspaceExecutorSetupCommandEndpoint.as_view(),
|
||||
name="ai-workspace-executor-setup-command",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/ai-workspace/threads/",
|
||||
AIWorkspaceThreadListEndpoint.as_view(),
|
||||
|
||||
@@ -180,6 +180,7 @@ from .ai_workspace import (
|
||||
AIWorkspaceExecutorEventsEndpoint,
|
||||
AIWorkspaceExecutorListEndpoint,
|
||||
AIWorkspaceExecutorSelectEndpoint,
|
||||
AIWorkspaceExecutorSetupCommandEndpoint,
|
||||
AIWorkspaceExecutorWindowsAgentEndpoint,
|
||||
AIWorkspaceSettingsEndpoint,
|
||||
AIWorkspaceThreadDispatchEndpoint,
|
||||
|
||||
@@ -505,6 +505,51 @@ def ops_settings_payload(raw_payload, slug):
|
||||
return payload
|
||||
|
||||
|
||||
def sync_ops_installer_context(request, slug, source):
|
||||
request_data = request.data if isinstance(request.data, dict) else {}
|
||||
ops_project_id = str(
|
||||
request_data.get("opsProjectId")
|
||||
or request_data.get("ops_project_id")
|
||||
or request.query_params.get("ops_project_id")
|
||||
or ""
|
||||
).strip()
|
||||
if not ops_project_id:
|
||||
return None
|
||||
|
||||
ops_workspace_slug = str(
|
||||
request_data.get("opsWorkspaceSlug")
|
||||
or request_data.get("ops_workspace_slug")
|
||||
or request.query_params.get("ops_workspace_slug")
|
||||
or slug
|
||||
or ""
|
||||
).strip()
|
||||
active_context = {
|
||||
"surface": "ops",
|
||||
"workspaceSlug": ops_workspace_slug,
|
||||
"opsWorkspaceSlug": ops_workspace_slug,
|
||||
"opsRouteWorkspaceSlug": slug,
|
||||
"opsProjectId": ops_project_id,
|
||||
}
|
||||
sync_payload = ops_settings_payload(
|
||||
{
|
||||
"activeContext": active_context,
|
||||
"enabledToolPacks": ["ops", "engine"],
|
||||
"metadata": {
|
||||
"source": source,
|
||||
"updatedAt": timezone.now().isoformat(),
|
||||
},
|
||||
},
|
||||
slug,
|
||||
)
|
||||
sync_payload, ops_grant_error = attach_ops_grant_for_active_context(request, slug, sync_payload)
|
||||
if ops_grant_error is not None:
|
||||
return ops_grant_error
|
||||
sync_response = ai_workspace_request(request, "PATCH", "/settings", sync_payload)
|
||||
if sync_response.status_code >= 400:
|
||||
return sync_response
|
||||
return None
|
||||
|
||||
|
||||
class AIWorkspaceSettingsEndpoint(BaseAPIView):
|
||||
@allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
|
||||
def get(self, request, slug):
|
||||
@@ -584,33 +629,9 @@ class AIWorkspaceExecutorWindowsAgentEndpoint(BaseAPIView):
|
||||
params = {}
|
||||
if request.query_params.get("port"):
|
||||
params["port"] = request.query_params.get("port")
|
||||
ops_project_id = (request.query_params.get("ops_project_id") or "").strip()
|
||||
if ops_project_id:
|
||||
ops_workspace_slug = (request.query_params.get("ops_workspace_slug") or slug or "").strip()
|
||||
active_context = {
|
||||
"surface": "ops",
|
||||
"workspaceSlug": ops_workspace_slug,
|
||||
"opsWorkspaceSlug": ops_workspace_slug,
|
||||
"opsRouteWorkspaceSlug": slug,
|
||||
"opsProjectId": ops_project_id,
|
||||
}
|
||||
sync_payload = ops_settings_payload(
|
||||
{
|
||||
"activeContext": active_context,
|
||||
"enabledToolPacks": ["ops", "engine"],
|
||||
"metadata": {
|
||||
"source": "ops-ai-workspace-installer",
|
||||
"updatedAt": timezone.now().isoformat(),
|
||||
},
|
||||
},
|
||||
slug,
|
||||
)
|
||||
sync_payload, ops_grant_error = attach_ops_grant_for_active_context(request, slug, sync_payload)
|
||||
if ops_grant_error is not None:
|
||||
return ops_grant_error
|
||||
sync_response = ai_workspace_request(request, "PATCH", "/settings", sync_payload)
|
||||
if sync_response.status_code >= 400:
|
||||
return sync_response
|
||||
sync_error = sync_ops_installer_context(request, slug, "ops-ai-workspace-installer")
|
||||
if sync_error is not None:
|
||||
return sync_error
|
||||
|
||||
try:
|
||||
response = requests.get(
|
||||
@@ -643,6 +664,27 @@ class AIWorkspaceExecutorWindowsAgentEndpoint(BaseAPIView):
|
||||
return output
|
||||
|
||||
|
||||
class AIWorkspaceExecutorSetupCommandEndpoint(BaseAPIView):
|
||||
@allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
|
||||
def post(self, request, slug, executor_id):
|
||||
sync_error = sync_ops_installer_context(request, slug, "ops-ai-workspace-npm-setup")
|
||||
if sync_error is not None:
|
||||
return sync_error
|
||||
|
||||
request_data = request.data if isinstance(request.data, dict) else {}
|
||||
payload = {}
|
||||
port = request_data.get("port") or request.query_params.get("port")
|
||||
if port:
|
||||
payload["port"] = port
|
||||
return ai_workspace_request(
|
||||
request,
|
||||
"POST",
|
||||
f"/executors/{executor_id}/agent/setup-command",
|
||||
payload,
|
||||
timeout_override=15,
|
||||
)
|
||||
|
||||
|
||||
class AIWorkspaceThreadListEndpoint(BaseAPIView):
|
||||
@allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
|
||||
def get(self, request, slug):
|
||||
|
||||
Reference in New Issue
Block a user