feat: add standalone ops ai workspace setup

This commit is contained in:
DCCONSTRUCTIONS
2026-06-09 13:23:02 +03:00
parent 6c119aae04
commit 71979526cf
6 changed files with 810 additions and 63 deletions
@@ -8,6 +8,7 @@ from plane.app.views import (
AIWorkspaceExecutorDetailEndpoint,
AIWorkspaceExecutorListEndpoint,
AIWorkspaceExecutorSelectEndpoint,
AIWorkspaceExecutorWindowsAgentEndpoint,
AIWorkspaceThreadDetailEndpoint,
AIWorkspaceThreadListEndpoint,
AIWorkspaceThreadMessagesEndpoint,
@@ -30,6 +31,11 @@ urlpatterns = [
AIWorkspaceExecutorSelectEndpoint.as_view(),
name="ai-workspace-executor-select",
),
path(
"workspaces/<str:slug>/ai-workspace/executors/<uuid:executor_id>/agent/windows.ps1",
AIWorkspaceExecutorWindowsAgentEndpoint.as_view(),
name="ai-workspace-executor-windows-agent",
),
path(
"workspaces/<str:slug>/ai-workspace/threads/",
AIWorkspaceThreadListEndpoint.as_view(),
@@ -178,6 +178,7 @@ from .ai_workspace import (
AIWorkspaceExecutorDetailEndpoint,
AIWorkspaceExecutorListEndpoint,
AIWorkspaceExecutorSelectEndpoint,
AIWorkspaceExecutorWindowsAgentEndpoint,
AIWorkspaceThreadDetailEndpoint,
AIWorkspaceThreadListEndpoint,
AIWorkspaceThreadMessagesEndpoint,
@@ -3,6 +3,7 @@ import os
# Third party imports
import requests
from django.http import HttpResponse
from rest_framework import status
from rest_framework.response import Response
@@ -138,6 +139,48 @@ class AIWorkspaceExecutorSelectEndpoint(BaseAPIView):
return ai_workspace_request(request, "POST", f"/executors/{executor_id}/select")
class AIWorkspaceExecutorWindowsAgentEndpoint(BaseAPIView):
@allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
def get(self, request, slug, executor_id):
config, error_response = require_ai_workspace_config()
if error_response is not None:
return error_response
base_url, token, timeout = config
params = {}
if request.query_params.get("port"):
params["port"] = request.query_params.get("port")
try:
response = requests.get(
f"{base_url}/api/ai-workspace/assistant/v1/executors/{executor_id}/agent/windows.ps1",
headers={
"Authorization": f"Bearer {token}",
"Accept": "application/octet-stream, text/plain, */*",
**user_headers(request.user),
},
params=params,
timeout=timeout,
)
except requests.RequestException:
return Response(
{
"ok": False,
"error": "ai_workspace_assistant_unavailable",
"message": "NODE.DC AI Workspace Assistant is unavailable.",
},
status=status.HTTP_502_BAD_GATEWAY,
)
if response.status_code >= 400:
return HttpResponse(response.content, status=response.status_code, content_type=response.headers.get("Content-Type", "text/plain"))
output = HttpResponse(response.content, status=response.status_code, content_type=response.headers.get("Content-Type", "application/octet-stream"))
for header in ("Content-Disposition", "Cache-Control", "Pragma", "Expires", "Surrogate-Control", "X-AI-Workspace-Installer-SHA256"):
if response.headers.get(header):
output[header] = response.headers[header]
return output
class AIWorkspaceThreadListEndpoint(BaseAPIView):
@allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
def get(self, request, slug):