83 lines
2.5 KiB
Python
83 lines
2.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Control-plane client for workspace, agent, and guard operations."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import httpx
|
|
|
|
|
|
class ControlPlaneClient:
|
|
"""Async client for the agent control-plane API surface."""
|
|
|
|
def __init__(self, base_url: str = "http://localhost:8000/api"):
|
|
self.base_url = base_url.rstrip("/")
|
|
self._client: httpx.AsyncClient | None = None
|
|
|
|
async def __aenter__(self) -> "ControlPlaneClient":
|
|
self._client = httpx.AsyncClient(base_url=self.base_url, timeout=30.0)
|
|
return self
|
|
|
|
async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
if self._client:
|
|
await self._client.aclose()
|
|
|
|
async def list_workspaces(self) -> dict:
|
|
response = await self._client.get("/workspaces")
|
|
response.raise_for_status()
|
|
return response.json()
|
|
|
|
async def get_workspace(self, workspace_id: str) -> dict:
|
|
response = await self._client.get(f"/workspaces/{workspace_id}")
|
|
response.raise_for_status()
|
|
return response.json()
|
|
|
|
async def list_agents(self, workspace_id: str) -> dict:
|
|
response = await self._client.get(
|
|
f"/workspaces/{workspace_id}/agents",
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
|
|
async def get_agent(self, workspace_id: str, agent_id: str) -> dict:
|
|
response = await self._client.get(
|
|
f"/workspaces/{workspace_id}/agents/{agent_id}",
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
|
|
async def fetch_pending_approvals(self) -> dict:
|
|
response = await self._client.get("/guard/pending")
|
|
response.raise_for_status()
|
|
return response.json()
|
|
|
|
async def approve_pending_approval(
|
|
self,
|
|
approval_id: str,
|
|
*,
|
|
one_time: bool = True,
|
|
expires_in_minutes: int = 30,
|
|
) -> dict:
|
|
response = await self._client.post(
|
|
"/guard/approve",
|
|
json={
|
|
"approval_id": approval_id,
|
|
"one_time": one_time,
|
|
"expires_in_minutes": expires_in_minutes,
|
|
},
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
|
|
async def deny_pending_approval(
|
|
self,
|
|
approval_id: str,
|
|
*,
|
|
reason: str = "Denied by client",
|
|
) -> dict:
|
|
response = await self._client.post(
|
|
"/guard/deny",
|
|
json={"approval_id": approval_id, "reason": reason},
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|