archastro.platform.client

  1# Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License.
  2# This file is auto-generated by @archastro/sdk-generator. Do not edit.
  3# Content hash: f24da3972099
  4
  5from urllib.parse import urlparse, urlunparse
  6
  7from archastro.phx_channel import Socket
  8
  9from .auth import AsyncAuthClient, AuthClient
 10from .runtime.http_client import HttpClient, SyncHttpClient
 11from .v1 import V1, AsyncV1
 12
 13
 14class AsyncPlatformClient:
 15    def __init__(
 16        self,
 17        *,
 18        base_url: str = "https://platform.archastro.ai",
 19        access_token: str | None = None,
 20        get_access_token=None,
 21        on_refresh_token=None,
 22        path_prefix: str | None = None,
 23        default_headers: dict[str, str] | None = None,
 24    ):
 25        self._base_url = base_url
 26        self._access_token = access_token
 27        self._get_access_token = get_access_token
 28        self._default_headers = default_headers or {}
 29        self._http = HttpClient(
 30            base_url=base_url,
 31            access_token=access_token,
 32            get_access_token=get_access_token,
 33            on_refresh_token=on_refresh_token,
 34            path_prefix=path_prefix,
 35            default_headers=default_headers,
 36        )
 37        self.auth = AsyncAuthClient(self._http)
 38        self.v1 = AsyncV1(self._http)
 39        self.activity_feed = self.v1.activity_feed
 40        self.agent_computers = self.v1.agent_computers
 41        self.agent_env_vars = self.v1.agent_env_vars
 42        self.agent_health_actions = self.v1.agent_health_actions
 43        self.agent_installations = self.v1.agent_installations
 44        self.agent_routine_runs = self.v1.agent_routine_runs
 45        self.agent_routines = self.v1.agent_routines
 46        self.agent_sessions = self.v1.agent_sessions
 47        self.agent_skills = self.v1.agent_skills
 48        self.agent_tools = self.v1.agent_tools
 49        self.agents = self.v1.agents
 50        self.artifacts = self.v1.artifacts
 51        self.automation_runs = self.v1.automation_runs
 52        self.automations = self.v1.automations
 53        self.bug_reports = self.v1.bug_reports
 54        self.config = self.v1.config
 55        self.custom_objects = self.v1.custom_objects
 56        self.event_subscription_deliveries = self.v1.event_subscription_deliveries
 57        self.event_subscriptions = self.v1.event_subscriptions
 58        self.extractions = self.v1.extractions
 59        self.files = self.v1.files
 60        self.installation_sources = self.v1.installation_sources
 61        self.invites = self.v1.invites
 62        self.knowledge_documents = self.v1.knowledge_documents
 63        self.knowledge_ingestions = self.v1.knowledge_ingestions
 64        self.knowledge_sources = self.v1.knowledge_sources
 65        self.kv = self.v1.kv
 66        self.notification_preferences = self.v1.notification_preferences
 67        self.notifications = self.v1.notifications
 68        self.orgs = self.v1.orgs
 69        self.private_service_definitions = self.v1.private_service_definitions
 70        self.private_service_enrollments = self.v1.private_service_enrollments
 71        self.private_services = self.v1.private_services
 72        self.sandboxes = self.v1.sandboxes
 73        self.slack_channel_bindings = self.v1.slack_channel_bindings
 74        self.solution_categories = self.v1.solution_categories
 75        self.solution_instances = self.v1.solution_instances
 76        self.solution_tags = self.v1.solution_tags
 77        self.solutions = self.v1.solutions
 78        self.status = self.v1.status
 79        self.tasks = self.v1.tasks
 80        self.team_memberships = self.v1.team_memberships
 81        self.teams = self.v1.teams
 82        self.thread_messages = self.v1.thread_messages
 83        self.threads = self.v1.threads
 84        self.trajectories = self.v1.trajectories
 85        self.users = self.v1.users
 86        self.work_items = self.v1.work_items
 87        self.ai = self.v1.ai
 88        self.oauth = self.v1.oauth
 89        self._refresh_token: str | None = None
 90        self._extra_http_clients: list[HttpClient] = []
 91        self._sockets: list[Socket] = []
 92
 93    @property
 94    def refresh_token(self) -> str | None:
 95        return self._refresh_token
 96
 97    def set_access_token(self, token: str):
 98        self._access_token = token
 99        self._http.set_access_token(token)
100
101    def set_refresh_token(self, token: str):
102        self._refresh_token = token
103
104    async def __aenter__(self):
105        return self
106
107    async def __aexit__(self, exc_type, exc, tb):
108        await self.close()
109
110    async def close(self):
111        try:
112            try:
113                for socket in self._sockets:
114                    await socket.disconnect()
115            finally:
116                self._sockets.clear()
117            await self._http.close()
118        finally:
119            for http in self._extra_http_clients:
120                await http.close()
121            self._extra_http_clients.clear()
122
123    def _current_access_token(self) -> str | None:
124        if self._get_access_token:
125            return self._get_access_token()
126        return self._access_token
127
128    def _api_key(self) -> str | None:
129        for key, value in self._default_headers.items():
130            if key.lower() == "x-archastro-api-key".lower():
131                return value
132        return None
133
134    def _socket_params(self, params: dict[str, str] | None = None) -> dict[str, str]:
135        socket_params: dict[str, str] = {}
136        api_key = self._api_key()
137        if api_key:
138            socket_params["api_key"] = api_key
139        token = self._current_access_token()
140        if token:
141            socket_params["token"] = token
142        if params:
143            socket_params.update(params)
144        return socket_params
145
146    def _default_websocket_url(self) -> str:
147        parsed = urlparse(self._base_url)
148        scheme = (
149            "wss"
150            if parsed.scheme == "https"
151            else "ws"
152            if parsed.scheme == "http"
153            else parsed.scheme
154        )
155        path = parsed.path.rstrip("/") + "/socket/api/websocket"
156        return urlunparse(
157            parsed._replace(scheme=scheme, path=path, params="", query="", fragment="")
158        )
159
160    async def open_socket(
161        self,
162        *,
163        url: str | None = None,
164        params: dict[str, str] | None = None,
165        connect: bool = True,
166        heartbeat_interval: float = 30,
167        timeout: float = 10,
168        reconnect_backoff_ms: list[int] | None = None,
169        auto_reconnect: bool = True,
170    ) -> Socket:
171        socket_params = self._socket_params(params)
172        if connect and not socket_params.get("token"):
173            raise ValueError("AsyncPlatformClient.open_socket requires an access token")
174        socket = Socket(
175            url or self._default_websocket_url(),
176            params=socket_params,
177            heartbeat_interval=heartbeat_interval,
178            timeout=timeout,
179            reconnect_backoff_ms=reconnect_backoff_ms,
180            auto_reconnect=auto_reconnect,
181        )
182        if connect:
183            await socket.connect()
184            if not socket.is_connected:
185                raise ConnectionError("WebSocket connection failed")
186        self._sockets.append(socket)
187        return socket
188
189    # ─── Factory constructors (generated from auth schemes) ───
190
191    @classmethod
192    def with_secret_key(cls, key: str, base_url: str | None = None) -> "AsyncPlatformClient":
193        """Secret API key — full admin access, no user JWT required"""
194        kwargs = {}
195        if base_url:
196            kwargs["base_url"] = base_url
197        return cls(default_headers={"x-archastro-api-key": key}, **kwargs)
198
199    @classmethod
200    def with_token(
201        cls, api_key: str, access_token: str, base_url: str | None = None
202    ) -> "AsyncPlatformClient":
203        """Create a client with a publishable key and pre-existing access token."""
204        kwargs = {}
205        if base_url:
206            kwargs["base_url"] = base_url
207        return cls(
208            access_token=access_token, default_headers={"x-archastro-api-key": api_key}, **kwargs
209        )
210
211    @classmethod
212    async def with_credentials(
213        cls, api_key: str, email: str, password: str, base_url: str | None = None
214    ) -> "AsyncPlatformClient":
215        """Create a client by logging in with email/password"""
216        kwargs = {}
217        if base_url:
218            kwargs["base_url"] = base_url
219        client = cls(default_headers={"x-archastro-api-key": api_key}, **kwargs)
220        tokens = await client.auth.login(email, password)
221        if not tokens.access_token:
222            raise ValueError("Login did not return an access token")
223        client.set_access_token(tokens.access_token)
224        if tokens.refresh_token:
225            client.set_refresh_token(tokens.refresh_token)
226        refresh_http = HttpClient(
227            base_url=base_url or "https://platform.archastro.ai",
228            default_headers={"x-archastro-api-key": api_key},
229            refresh_only=True,
230        )
231        client._extra_http_clients.append(refresh_http)
232        refresh_auth = AsyncAuthClient(refresh_http)
233
234        async def _refresh() -> str:
235            rt = client.refresh_token
236            if not rt:
237                raise ValueError("No refresh token available")
238            refreshed = await refresh_auth.refresh(rt)
239            if not refreshed.access_token:
240                raise ValueError("Refresh did not return an access token")
241            client.set_access_token(refreshed.access_token)
242            if refreshed.refresh_token:
243                client.set_refresh_token(refreshed.refresh_token)
244            return refreshed.access_token
245
246        client._http.set_refresh_handler(_refresh)
247        return client
248
249
250class PlatformClient:
251    def __init__(
252        self,
253        *,
254        base_url: str = "https://platform.archastro.ai",
255        access_token: str | None = None,
256        get_access_token=None,
257        on_refresh_token=None,
258        path_prefix: str | None = None,
259        default_headers: dict[str, str] | None = None,
260    ):
261        self._closed = False
262        self._http = SyncHttpClient(
263            base_url=base_url,
264            access_token=access_token,
265            get_access_token=get_access_token,
266            on_refresh_token=on_refresh_token,
267            path_prefix=path_prefix,
268            default_headers=default_headers,
269        )
270        self.auth = AuthClient(self._http)
271        self.v1 = V1(self._http)
272        self.activity_feed = self.v1.activity_feed
273        self.agent_computers = self.v1.agent_computers
274        self.agent_env_vars = self.v1.agent_env_vars
275        self.agent_health_actions = self.v1.agent_health_actions
276        self.agent_installations = self.v1.agent_installations
277        self.agent_routine_runs = self.v1.agent_routine_runs
278        self.agent_routines = self.v1.agent_routines
279        self.agent_sessions = self.v1.agent_sessions
280        self.agent_skills = self.v1.agent_skills
281        self.agent_tools = self.v1.agent_tools
282        self.agents = self.v1.agents
283        self.artifacts = self.v1.artifacts
284        self.automation_runs = self.v1.automation_runs
285        self.automations = self.v1.automations
286        self.bug_reports = self.v1.bug_reports
287        self.config = self.v1.config
288        self.custom_objects = self.v1.custom_objects
289        self.event_subscription_deliveries = self.v1.event_subscription_deliveries
290        self.event_subscriptions = self.v1.event_subscriptions
291        self.extractions = self.v1.extractions
292        self.files = self.v1.files
293        self.installation_sources = self.v1.installation_sources
294        self.invites = self.v1.invites
295        self.knowledge_documents = self.v1.knowledge_documents
296        self.knowledge_ingestions = self.v1.knowledge_ingestions
297        self.knowledge_sources = self.v1.knowledge_sources
298        self.kv = self.v1.kv
299        self.notification_preferences = self.v1.notification_preferences
300        self.notifications = self.v1.notifications
301        self.orgs = self.v1.orgs
302        self.private_service_definitions = self.v1.private_service_definitions
303        self.private_service_enrollments = self.v1.private_service_enrollments
304        self.private_services = self.v1.private_services
305        self.sandboxes = self.v1.sandboxes
306        self.slack_channel_bindings = self.v1.slack_channel_bindings
307        self.solution_categories = self.v1.solution_categories
308        self.solution_instances = self.v1.solution_instances
309        self.solution_tags = self.v1.solution_tags
310        self.solutions = self.v1.solutions
311        self.status = self.v1.status
312        self.tasks = self.v1.tasks
313        self.team_memberships = self.v1.team_memberships
314        self.teams = self.v1.teams
315        self.thread_messages = self.v1.thread_messages
316        self.threads = self.v1.threads
317        self.trajectories = self.v1.trajectories
318        self.users = self.v1.users
319        self.work_items = self.v1.work_items
320        self.ai = self.v1.ai
321        self.oauth = self.v1.oauth
322        self._refresh_token: str | None = None
323        self._extra_http_clients: list[SyncHttpClient] = []
324
325    @property
326    def refresh_token(self) -> str | None:
327        return self._refresh_token
328
329    def set_access_token(self, token: str):
330        self._http.set_access_token(token)
331
332    def set_refresh_token(self, token: str):
333        self._refresh_token = token
334
335    def __enter__(self):
336        return self
337
338    def __exit__(self, exc_type, exc, tb):
339        self.close()
340
341    def close(self):
342        if self._closed:
343            return
344        self._closed = True
345        try:
346            self._http.close()
347        finally:
348            for http in self._extra_http_clients:
349                http.close()
350            self._extra_http_clients.clear()
351
352    # ─── Factory constructors (generated from auth schemes) ───
353
354    @classmethod
355    def with_secret_key(cls, key: str, base_url: str | None = None) -> "PlatformClient":
356        """Secret API key — full admin access, no user JWT required"""
357        kwargs = {}
358        if base_url:
359            kwargs["base_url"] = base_url
360        return cls(default_headers={"x-archastro-api-key": key}, **kwargs)
361
362    @classmethod
363    def with_token(
364        cls, api_key: str, access_token: str, base_url: str | None = None
365    ) -> "PlatformClient":
366        """Create a client with a publishable key and pre-existing access token."""
367        kwargs = {}
368        if base_url:
369            kwargs["base_url"] = base_url
370        return cls(
371            access_token=access_token, default_headers={"x-archastro-api-key": api_key}, **kwargs
372        )
373
374    @classmethod
375    def with_credentials(
376        cls, api_key: str, email: str, password: str, base_url: str | None = None
377    ) -> "PlatformClient":
378        kwargs = {}
379        if base_url:
380            kwargs["base_url"] = base_url
381        client = cls(default_headers={"x-archastro-api-key": api_key}, **kwargs)
382        tokens = client.auth.login(email, password)
383        if not tokens.access_token:
384            raise ValueError("Login did not return an access token")
385        client.set_access_token(tokens.access_token)
386        if tokens.refresh_token:
387            client.set_refresh_token(tokens.refresh_token)
388        refresh_http = SyncHttpClient(
389            base_url=base_url or "https://platform.archastro.ai",
390            default_headers={"x-archastro-api-key": api_key},
391            refresh_only=True,
392        )
393        client._extra_http_clients.append(refresh_http)
394        refresh_auth = AuthClient(refresh_http)
395
396        def _refresh() -> str:
397            rt = client.refresh_token
398            if not rt:
399                raise ValueError("No refresh token available")
400            refreshed = refresh_auth.refresh(rt)
401            if not refreshed.access_token:
402                raise ValueError("Refresh did not return an access token")
403            client.set_access_token(refreshed.access_token)
404            if refreshed.refresh_token:
405                client.set_refresh_token(refreshed.refresh_token)
406            return refreshed.access_token
407
408        client._http.set_refresh_handler(_refresh)
409        return client
class AsyncPlatformClient:
 15class AsyncPlatformClient:
 16    def __init__(
 17        self,
 18        *,
 19        base_url: str = "https://platform.archastro.ai",
 20        access_token: str | None = None,
 21        get_access_token=None,
 22        on_refresh_token=None,
 23        path_prefix: str | None = None,
 24        default_headers: dict[str, str] | None = None,
 25    ):
 26        self._base_url = base_url
 27        self._access_token = access_token
 28        self._get_access_token = get_access_token
 29        self._default_headers = default_headers or {}
 30        self._http = HttpClient(
 31            base_url=base_url,
 32            access_token=access_token,
 33            get_access_token=get_access_token,
 34            on_refresh_token=on_refresh_token,
 35            path_prefix=path_prefix,
 36            default_headers=default_headers,
 37        )
 38        self.auth = AsyncAuthClient(self._http)
 39        self.v1 = AsyncV1(self._http)
 40        self.activity_feed = self.v1.activity_feed
 41        self.agent_computers = self.v1.agent_computers
 42        self.agent_env_vars = self.v1.agent_env_vars
 43        self.agent_health_actions = self.v1.agent_health_actions
 44        self.agent_installations = self.v1.agent_installations
 45        self.agent_routine_runs = self.v1.agent_routine_runs
 46        self.agent_routines = self.v1.agent_routines
 47        self.agent_sessions = self.v1.agent_sessions
 48        self.agent_skills = self.v1.agent_skills
 49        self.agent_tools = self.v1.agent_tools
 50        self.agents = self.v1.agents
 51        self.artifacts = self.v1.artifacts
 52        self.automation_runs = self.v1.automation_runs
 53        self.automations = self.v1.automations
 54        self.bug_reports = self.v1.bug_reports
 55        self.config = self.v1.config
 56        self.custom_objects = self.v1.custom_objects
 57        self.event_subscription_deliveries = self.v1.event_subscription_deliveries
 58        self.event_subscriptions = self.v1.event_subscriptions
 59        self.extractions = self.v1.extractions
 60        self.files = self.v1.files
 61        self.installation_sources = self.v1.installation_sources
 62        self.invites = self.v1.invites
 63        self.knowledge_documents = self.v1.knowledge_documents
 64        self.knowledge_ingestions = self.v1.knowledge_ingestions
 65        self.knowledge_sources = self.v1.knowledge_sources
 66        self.kv = self.v1.kv
 67        self.notification_preferences = self.v1.notification_preferences
 68        self.notifications = self.v1.notifications
 69        self.orgs = self.v1.orgs
 70        self.private_service_definitions = self.v1.private_service_definitions
 71        self.private_service_enrollments = self.v1.private_service_enrollments
 72        self.private_services = self.v1.private_services
 73        self.sandboxes = self.v1.sandboxes
 74        self.slack_channel_bindings = self.v1.slack_channel_bindings
 75        self.solution_categories = self.v1.solution_categories
 76        self.solution_instances = self.v1.solution_instances
 77        self.solution_tags = self.v1.solution_tags
 78        self.solutions = self.v1.solutions
 79        self.status = self.v1.status
 80        self.tasks = self.v1.tasks
 81        self.team_memberships = self.v1.team_memberships
 82        self.teams = self.v1.teams
 83        self.thread_messages = self.v1.thread_messages
 84        self.threads = self.v1.threads
 85        self.trajectories = self.v1.trajectories
 86        self.users = self.v1.users
 87        self.work_items = self.v1.work_items
 88        self.ai = self.v1.ai
 89        self.oauth = self.v1.oauth
 90        self._refresh_token: str | None = None
 91        self._extra_http_clients: list[HttpClient] = []
 92        self._sockets: list[Socket] = []
 93
 94    @property
 95    def refresh_token(self) -> str | None:
 96        return self._refresh_token
 97
 98    def set_access_token(self, token: str):
 99        self._access_token = token
100        self._http.set_access_token(token)
101
102    def set_refresh_token(self, token: str):
103        self._refresh_token = token
104
105    async def __aenter__(self):
106        return self
107
108    async def __aexit__(self, exc_type, exc, tb):
109        await self.close()
110
111    async def close(self):
112        try:
113            try:
114                for socket in self._sockets:
115                    await socket.disconnect()
116            finally:
117                self._sockets.clear()
118            await self._http.close()
119        finally:
120            for http in self._extra_http_clients:
121                await http.close()
122            self._extra_http_clients.clear()
123
124    def _current_access_token(self) -> str | None:
125        if self._get_access_token:
126            return self._get_access_token()
127        return self._access_token
128
129    def _api_key(self) -> str | None:
130        for key, value in self._default_headers.items():
131            if key.lower() == "x-archastro-api-key".lower():
132                return value
133        return None
134
135    def _socket_params(self, params: dict[str, str] | None = None) -> dict[str, str]:
136        socket_params: dict[str, str] = {}
137        api_key = self._api_key()
138        if api_key:
139            socket_params["api_key"] = api_key
140        token = self._current_access_token()
141        if token:
142            socket_params["token"] = token
143        if params:
144            socket_params.update(params)
145        return socket_params
146
147    def _default_websocket_url(self) -> str:
148        parsed = urlparse(self._base_url)
149        scheme = (
150            "wss"
151            if parsed.scheme == "https"
152            else "ws"
153            if parsed.scheme == "http"
154            else parsed.scheme
155        )
156        path = parsed.path.rstrip("/") + "/socket/api/websocket"
157        return urlunparse(
158            parsed._replace(scheme=scheme, path=path, params="", query="", fragment="")
159        )
160
161    async def open_socket(
162        self,
163        *,
164        url: str | None = None,
165        params: dict[str, str] | None = None,
166        connect: bool = True,
167        heartbeat_interval: float = 30,
168        timeout: float = 10,
169        reconnect_backoff_ms: list[int] | None = None,
170        auto_reconnect: bool = True,
171    ) -> Socket:
172        socket_params = self._socket_params(params)
173        if connect and not socket_params.get("token"):
174            raise ValueError("AsyncPlatformClient.open_socket requires an access token")
175        socket = Socket(
176            url or self._default_websocket_url(),
177            params=socket_params,
178            heartbeat_interval=heartbeat_interval,
179            timeout=timeout,
180            reconnect_backoff_ms=reconnect_backoff_ms,
181            auto_reconnect=auto_reconnect,
182        )
183        if connect:
184            await socket.connect()
185            if not socket.is_connected:
186                raise ConnectionError("WebSocket connection failed")
187        self._sockets.append(socket)
188        return socket
189
190    # ─── Factory constructors (generated from auth schemes) ───
191
192    @classmethod
193    def with_secret_key(cls, key: str, base_url: str | None = None) -> "AsyncPlatformClient":
194        """Secret API key — full admin access, no user JWT required"""
195        kwargs = {}
196        if base_url:
197            kwargs["base_url"] = base_url
198        return cls(default_headers={"x-archastro-api-key": key}, **kwargs)
199
200    @classmethod
201    def with_token(
202        cls, api_key: str, access_token: str, base_url: str | None = None
203    ) -> "AsyncPlatformClient":
204        """Create a client with a publishable key and pre-existing access token."""
205        kwargs = {}
206        if base_url:
207            kwargs["base_url"] = base_url
208        return cls(
209            access_token=access_token, default_headers={"x-archastro-api-key": api_key}, **kwargs
210        )
211
212    @classmethod
213    async def with_credentials(
214        cls, api_key: str, email: str, password: str, base_url: str | None = None
215    ) -> "AsyncPlatformClient":
216        """Create a client by logging in with email/password"""
217        kwargs = {}
218        if base_url:
219            kwargs["base_url"] = base_url
220        client = cls(default_headers={"x-archastro-api-key": api_key}, **kwargs)
221        tokens = await client.auth.login(email, password)
222        if not tokens.access_token:
223            raise ValueError("Login did not return an access token")
224        client.set_access_token(tokens.access_token)
225        if tokens.refresh_token:
226            client.set_refresh_token(tokens.refresh_token)
227        refresh_http = HttpClient(
228            base_url=base_url or "https://platform.archastro.ai",
229            default_headers={"x-archastro-api-key": api_key},
230            refresh_only=True,
231        )
232        client._extra_http_clients.append(refresh_http)
233        refresh_auth = AsyncAuthClient(refresh_http)
234
235        async def _refresh() -> str:
236            rt = client.refresh_token
237            if not rt:
238                raise ValueError("No refresh token available")
239            refreshed = await refresh_auth.refresh(rt)
240            if not refreshed.access_token:
241                raise ValueError("Refresh did not return an access token")
242            client.set_access_token(refreshed.access_token)
243            if refreshed.refresh_token:
244                client.set_refresh_token(refreshed.refresh_token)
245            return refreshed.access_token
246
247        client._http.set_refresh_handler(_refresh)
248        return client
AsyncPlatformClient( *, base_url: str = 'https://platform.archastro.ai', access_token: str | None = None, get_access_token=None, on_refresh_token=None, path_prefix: str | None = None, default_headers: dict[str, str] | None = None)
16    def __init__(
17        self,
18        *,
19        base_url: str = "https://platform.archastro.ai",
20        access_token: str | None = None,
21        get_access_token=None,
22        on_refresh_token=None,
23        path_prefix: str | None = None,
24        default_headers: dict[str, str] | None = None,
25    ):
26        self._base_url = base_url
27        self._access_token = access_token
28        self._get_access_token = get_access_token
29        self._default_headers = default_headers or {}
30        self._http = HttpClient(
31            base_url=base_url,
32            access_token=access_token,
33            get_access_token=get_access_token,
34            on_refresh_token=on_refresh_token,
35            path_prefix=path_prefix,
36            default_headers=default_headers,
37        )
38        self.auth = AsyncAuthClient(self._http)
39        self.v1 = AsyncV1(self._http)
40        self.activity_feed = self.v1.activity_feed
41        self.agent_computers = self.v1.agent_computers
42        self.agent_env_vars = self.v1.agent_env_vars
43        self.agent_health_actions = self.v1.agent_health_actions
44        self.agent_installations = self.v1.agent_installations
45        self.agent_routine_runs = self.v1.agent_routine_runs
46        self.agent_routines = self.v1.agent_routines
47        self.agent_sessions = self.v1.agent_sessions
48        self.agent_skills = self.v1.agent_skills
49        self.agent_tools = self.v1.agent_tools
50        self.agents = self.v1.agents
51        self.artifacts = self.v1.artifacts
52        self.automation_runs = self.v1.automation_runs
53        self.automations = self.v1.automations
54        self.bug_reports = self.v1.bug_reports
55        self.config = self.v1.config
56        self.custom_objects = self.v1.custom_objects
57        self.event_subscription_deliveries = self.v1.event_subscription_deliveries
58        self.event_subscriptions = self.v1.event_subscriptions
59        self.extractions = self.v1.extractions
60        self.files = self.v1.files
61        self.installation_sources = self.v1.installation_sources
62        self.invites = self.v1.invites
63        self.knowledge_documents = self.v1.knowledge_documents
64        self.knowledge_ingestions = self.v1.knowledge_ingestions
65        self.knowledge_sources = self.v1.knowledge_sources
66        self.kv = self.v1.kv
67        self.notification_preferences = self.v1.notification_preferences
68        self.notifications = self.v1.notifications
69        self.orgs = self.v1.orgs
70        self.private_service_definitions = self.v1.private_service_definitions
71        self.private_service_enrollments = self.v1.private_service_enrollments
72        self.private_services = self.v1.private_services
73        self.sandboxes = self.v1.sandboxes
74        self.slack_channel_bindings = self.v1.slack_channel_bindings
75        self.solution_categories = self.v1.solution_categories
76        self.solution_instances = self.v1.solution_instances
77        self.solution_tags = self.v1.solution_tags
78        self.solutions = self.v1.solutions
79        self.status = self.v1.status
80        self.tasks = self.v1.tasks
81        self.team_memberships = self.v1.team_memberships
82        self.teams = self.v1.teams
83        self.thread_messages = self.v1.thread_messages
84        self.threads = self.v1.threads
85        self.trajectories = self.v1.trajectories
86        self.users = self.v1.users
87        self.work_items = self.v1.work_items
88        self.ai = self.v1.ai
89        self.oauth = self.v1.oauth
90        self._refresh_token: str | None = None
91        self._extra_http_clients: list[HttpClient] = []
92        self._sockets: list[Socket] = []
auth
v1
activity_feed
agent_computers
agent_env_vars
agent_health_actions
agent_installations
agent_routine_runs
agent_routines
agent_sessions
agent_skills
agent_tools
agents
artifacts
automation_runs
automations
bug_reports
config
custom_objects
event_subscription_deliveries
event_subscriptions
extractions
files
installation_sources
invites
knowledge_documents
knowledge_ingestions
knowledge_sources
kv
notification_preferences
notifications
orgs
private_service_definitions
private_service_enrollments
private_services
sandboxes
slack_channel_bindings
solution_categories
solution_instances
solution_tags
solutions
status
tasks
team_memberships
teams
thread_messages
threads
trajectories
users
work_items
ai
oauth
refresh_token: str | None
94    @property
95    def refresh_token(self) -> str | None:
96        return self._refresh_token
def set_access_token(self, token: str):
 98    def set_access_token(self, token: str):
 99        self._access_token = token
100        self._http.set_access_token(token)
def set_refresh_token(self, token: str):
102    def set_refresh_token(self, token: str):
103        self._refresh_token = token
async def close(self):
111    async def close(self):
112        try:
113            try:
114                for socket in self._sockets:
115                    await socket.disconnect()
116            finally:
117                self._sockets.clear()
118            await self._http.close()
119        finally:
120            for http in self._extra_http_clients:
121                await http.close()
122            self._extra_http_clients.clear()
async def open_socket( self, *, url: str | None = None, params: dict[str, str] | None = None, connect: bool = True, heartbeat_interval: float = 30, timeout: float = 10, reconnect_backoff_ms: list[int] | None = None, auto_reconnect: bool = True) -> archastro.phx_channel.Socket:
161    async def open_socket(
162        self,
163        *,
164        url: str | None = None,
165        params: dict[str, str] | None = None,
166        connect: bool = True,
167        heartbeat_interval: float = 30,
168        timeout: float = 10,
169        reconnect_backoff_ms: list[int] | None = None,
170        auto_reconnect: bool = True,
171    ) -> Socket:
172        socket_params = self._socket_params(params)
173        if connect and not socket_params.get("token"):
174            raise ValueError("AsyncPlatformClient.open_socket requires an access token")
175        socket = Socket(
176            url or self._default_websocket_url(),
177            params=socket_params,
178            heartbeat_interval=heartbeat_interval,
179            timeout=timeout,
180            reconnect_backoff_ms=reconnect_backoff_ms,
181            auto_reconnect=auto_reconnect,
182        )
183        if connect:
184            await socket.connect()
185            if not socket.is_connected:
186                raise ConnectionError("WebSocket connection failed")
187        self._sockets.append(socket)
188        return socket
@classmethod
def with_secret_key( cls, key: str, base_url: str | None = None) -> AsyncPlatformClient:
192    @classmethod
193    def with_secret_key(cls, key: str, base_url: str | None = None) -> "AsyncPlatformClient":
194        """Secret API key — full admin access, no user JWT required"""
195        kwargs = {}
196        if base_url:
197            kwargs["base_url"] = base_url
198        return cls(default_headers={"x-archastro-api-key": key}, **kwargs)

Secret API key — full admin access, no user JWT required

@classmethod
def with_token( cls, api_key: str, access_token: str, base_url: str | None = None) -> AsyncPlatformClient:
200    @classmethod
201    def with_token(
202        cls, api_key: str, access_token: str, base_url: str | None = None
203    ) -> "AsyncPlatformClient":
204        """Create a client with a publishable key and pre-existing access token."""
205        kwargs = {}
206        if base_url:
207            kwargs["base_url"] = base_url
208        return cls(
209            access_token=access_token, default_headers={"x-archastro-api-key": api_key}, **kwargs
210        )

Create a client with a publishable key and pre-existing access token.

@classmethod
async def with_credentials( cls, api_key: str, email: str, password: str, base_url: str | None = None) -> AsyncPlatformClient:
212    @classmethod
213    async def with_credentials(
214        cls, api_key: str, email: str, password: str, base_url: str | None = None
215    ) -> "AsyncPlatformClient":
216        """Create a client by logging in with email/password"""
217        kwargs = {}
218        if base_url:
219            kwargs["base_url"] = base_url
220        client = cls(default_headers={"x-archastro-api-key": api_key}, **kwargs)
221        tokens = await client.auth.login(email, password)
222        if not tokens.access_token:
223            raise ValueError("Login did not return an access token")
224        client.set_access_token(tokens.access_token)
225        if tokens.refresh_token:
226            client.set_refresh_token(tokens.refresh_token)
227        refresh_http = HttpClient(
228            base_url=base_url or "https://platform.archastro.ai",
229            default_headers={"x-archastro-api-key": api_key},
230            refresh_only=True,
231        )
232        client._extra_http_clients.append(refresh_http)
233        refresh_auth = AsyncAuthClient(refresh_http)
234
235        async def _refresh() -> str:
236            rt = client.refresh_token
237            if not rt:
238                raise ValueError("No refresh token available")
239            refreshed = await refresh_auth.refresh(rt)
240            if not refreshed.access_token:
241                raise ValueError("Refresh did not return an access token")
242            client.set_access_token(refreshed.access_token)
243            if refreshed.refresh_token:
244                client.set_refresh_token(refreshed.refresh_token)
245            return refreshed.access_token
246
247        client._http.set_refresh_handler(_refresh)
248        return client

Create a client by logging in with email/password

class PlatformClient:
251class PlatformClient:
252    def __init__(
253        self,
254        *,
255        base_url: str = "https://platform.archastro.ai",
256        access_token: str | None = None,
257        get_access_token=None,
258        on_refresh_token=None,
259        path_prefix: str | None = None,
260        default_headers: dict[str, str] | None = None,
261    ):
262        self._closed = False
263        self._http = SyncHttpClient(
264            base_url=base_url,
265            access_token=access_token,
266            get_access_token=get_access_token,
267            on_refresh_token=on_refresh_token,
268            path_prefix=path_prefix,
269            default_headers=default_headers,
270        )
271        self.auth = AuthClient(self._http)
272        self.v1 = V1(self._http)
273        self.activity_feed = self.v1.activity_feed
274        self.agent_computers = self.v1.agent_computers
275        self.agent_env_vars = self.v1.agent_env_vars
276        self.agent_health_actions = self.v1.agent_health_actions
277        self.agent_installations = self.v1.agent_installations
278        self.agent_routine_runs = self.v1.agent_routine_runs
279        self.agent_routines = self.v1.agent_routines
280        self.agent_sessions = self.v1.agent_sessions
281        self.agent_skills = self.v1.agent_skills
282        self.agent_tools = self.v1.agent_tools
283        self.agents = self.v1.agents
284        self.artifacts = self.v1.artifacts
285        self.automation_runs = self.v1.automation_runs
286        self.automations = self.v1.automations
287        self.bug_reports = self.v1.bug_reports
288        self.config = self.v1.config
289        self.custom_objects = self.v1.custom_objects
290        self.event_subscription_deliveries = self.v1.event_subscription_deliveries
291        self.event_subscriptions = self.v1.event_subscriptions
292        self.extractions = self.v1.extractions
293        self.files = self.v1.files
294        self.installation_sources = self.v1.installation_sources
295        self.invites = self.v1.invites
296        self.knowledge_documents = self.v1.knowledge_documents
297        self.knowledge_ingestions = self.v1.knowledge_ingestions
298        self.knowledge_sources = self.v1.knowledge_sources
299        self.kv = self.v1.kv
300        self.notification_preferences = self.v1.notification_preferences
301        self.notifications = self.v1.notifications
302        self.orgs = self.v1.orgs
303        self.private_service_definitions = self.v1.private_service_definitions
304        self.private_service_enrollments = self.v1.private_service_enrollments
305        self.private_services = self.v1.private_services
306        self.sandboxes = self.v1.sandboxes
307        self.slack_channel_bindings = self.v1.slack_channel_bindings
308        self.solution_categories = self.v1.solution_categories
309        self.solution_instances = self.v1.solution_instances
310        self.solution_tags = self.v1.solution_tags
311        self.solutions = self.v1.solutions
312        self.status = self.v1.status
313        self.tasks = self.v1.tasks
314        self.team_memberships = self.v1.team_memberships
315        self.teams = self.v1.teams
316        self.thread_messages = self.v1.thread_messages
317        self.threads = self.v1.threads
318        self.trajectories = self.v1.trajectories
319        self.users = self.v1.users
320        self.work_items = self.v1.work_items
321        self.ai = self.v1.ai
322        self.oauth = self.v1.oauth
323        self._refresh_token: str | None = None
324        self._extra_http_clients: list[SyncHttpClient] = []
325
326    @property
327    def refresh_token(self) -> str | None:
328        return self._refresh_token
329
330    def set_access_token(self, token: str):
331        self._http.set_access_token(token)
332
333    def set_refresh_token(self, token: str):
334        self._refresh_token = token
335
336    def __enter__(self):
337        return self
338
339    def __exit__(self, exc_type, exc, tb):
340        self.close()
341
342    def close(self):
343        if self._closed:
344            return
345        self._closed = True
346        try:
347            self._http.close()
348        finally:
349            for http in self._extra_http_clients:
350                http.close()
351            self._extra_http_clients.clear()
352
353    # ─── Factory constructors (generated from auth schemes) ───
354
355    @classmethod
356    def with_secret_key(cls, key: str, base_url: str | None = None) -> "PlatformClient":
357        """Secret API key — full admin access, no user JWT required"""
358        kwargs = {}
359        if base_url:
360            kwargs["base_url"] = base_url
361        return cls(default_headers={"x-archastro-api-key": key}, **kwargs)
362
363    @classmethod
364    def with_token(
365        cls, api_key: str, access_token: str, base_url: str | None = None
366    ) -> "PlatformClient":
367        """Create a client with a publishable key and pre-existing access token."""
368        kwargs = {}
369        if base_url:
370            kwargs["base_url"] = base_url
371        return cls(
372            access_token=access_token, default_headers={"x-archastro-api-key": api_key}, **kwargs
373        )
374
375    @classmethod
376    def with_credentials(
377        cls, api_key: str, email: str, password: str, base_url: str | None = None
378    ) -> "PlatformClient":
379        kwargs = {}
380        if base_url:
381            kwargs["base_url"] = base_url
382        client = cls(default_headers={"x-archastro-api-key": api_key}, **kwargs)
383        tokens = client.auth.login(email, password)
384        if not tokens.access_token:
385            raise ValueError("Login did not return an access token")
386        client.set_access_token(tokens.access_token)
387        if tokens.refresh_token:
388            client.set_refresh_token(tokens.refresh_token)
389        refresh_http = SyncHttpClient(
390            base_url=base_url or "https://platform.archastro.ai",
391            default_headers={"x-archastro-api-key": api_key},
392            refresh_only=True,
393        )
394        client._extra_http_clients.append(refresh_http)
395        refresh_auth = AuthClient(refresh_http)
396
397        def _refresh() -> str:
398            rt = client.refresh_token
399            if not rt:
400                raise ValueError("No refresh token available")
401            refreshed = refresh_auth.refresh(rt)
402            if not refreshed.access_token:
403                raise ValueError("Refresh did not return an access token")
404            client.set_access_token(refreshed.access_token)
405            if refreshed.refresh_token:
406                client.set_refresh_token(refreshed.refresh_token)
407            return refreshed.access_token
408
409        client._http.set_refresh_handler(_refresh)
410        return client
PlatformClient( *, base_url: str = 'https://platform.archastro.ai', access_token: str | None = None, get_access_token=None, on_refresh_token=None, path_prefix: str | None = None, default_headers: dict[str, str] | None = None)
252    def __init__(
253        self,
254        *,
255        base_url: str = "https://platform.archastro.ai",
256        access_token: str | None = None,
257        get_access_token=None,
258        on_refresh_token=None,
259        path_prefix: str | None = None,
260        default_headers: dict[str, str] | None = None,
261    ):
262        self._closed = False
263        self._http = SyncHttpClient(
264            base_url=base_url,
265            access_token=access_token,
266            get_access_token=get_access_token,
267            on_refresh_token=on_refresh_token,
268            path_prefix=path_prefix,
269            default_headers=default_headers,
270        )
271        self.auth = AuthClient(self._http)
272        self.v1 = V1(self._http)
273        self.activity_feed = self.v1.activity_feed
274        self.agent_computers = self.v1.agent_computers
275        self.agent_env_vars = self.v1.agent_env_vars
276        self.agent_health_actions = self.v1.agent_health_actions
277        self.agent_installations = self.v1.agent_installations
278        self.agent_routine_runs = self.v1.agent_routine_runs
279        self.agent_routines = self.v1.agent_routines
280        self.agent_sessions = self.v1.agent_sessions
281        self.agent_skills = self.v1.agent_skills
282        self.agent_tools = self.v1.agent_tools
283        self.agents = self.v1.agents
284        self.artifacts = self.v1.artifacts
285        self.automation_runs = self.v1.automation_runs
286        self.automations = self.v1.automations
287        self.bug_reports = self.v1.bug_reports
288        self.config = self.v1.config
289        self.custom_objects = self.v1.custom_objects
290        self.event_subscription_deliveries = self.v1.event_subscription_deliveries
291        self.event_subscriptions = self.v1.event_subscriptions
292        self.extractions = self.v1.extractions
293        self.files = self.v1.files
294        self.installation_sources = self.v1.installation_sources
295        self.invites = self.v1.invites
296        self.knowledge_documents = self.v1.knowledge_documents
297        self.knowledge_ingestions = self.v1.knowledge_ingestions
298        self.knowledge_sources = self.v1.knowledge_sources
299        self.kv = self.v1.kv
300        self.notification_preferences = self.v1.notification_preferences
301        self.notifications = self.v1.notifications
302        self.orgs = self.v1.orgs
303        self.private_service_definitions = self.v1.private_service_definitions
304        self.private_service_enrollments = self.v1.private_service_enrollments
305        self.private_services = self.v1.private_services
306        self.sandboxes = self.v1.sandboxes
307        self.slack_channel_bindings = self.v1.slack_channel_bindings
308        self.solution_categories = self.v1.solution_categories
309        self.solution_instances = self.v1.solution_instances
310        self.solution_tags = self.v1.solution_tags
311        self.solutions = self.v1.solutions
312        self.status = self.v1.status
313        self.tasks = self.v1.tasks
314        self.team_memberships = self.v1.team_memberships
315        self.teams = self.v1.teams
316        self.thread_messages = self.v1.thread_messages
317        self.threads = self.v1.threads
318        self.trajectories = self.v1.trajectories
319        self.users = self.v1.users
320        self.work_items = self.v1.work_items
321        self.ai = self.v1.ai
322        self.oauth = self.v1.oauth
323        self._refresh_token: str | None = None
324        self._extra_http_clients: list[SyncHttpClient] = []
auth
v1
activity_feed
agent_computers
agent_env_vars
agent_health_actions
agent_installations
agent_routine_runs
agent_routines
agent_sessions
agent_skills
agent_tools
agents
artifacts
automation_runs
automations
bug_reports
config
custom_objects
event_subscription_deliveries
event_subscriptions
extractions
files
installation_sources
invites
knowledge_documents
knowledge_ingestions
knowledge_sources
kv
notification_preferences
notifications
orgs
private_service_definitions
private_service_enrollments
private_services
sandboxes
slack_channel_bindings
solution_categories
solution_instances
solution_tags
solutions
status
tasks
team_memberships
teams
thread_messages
threads
trajectories
users
work_items
ai
oauth
refresh_token: str | None
326    @property
327    def refresh_token(self) -> str | None:
328        return self._refresh_token
def set_access_token(self, token: str):
330    def set_access_token(self, token: str):
331        self._http.set_access_token(token)
def set_refresh_token(self, token: str):
333    def set_refresh_token(self, token: str):
334        self._refresh_token = token
def close(self):
342    def close(self):
343        if self._closed:
344            return
345        self._closed = True
346        try:
347            self._http.close()
348        finally:
349            for http in self._extra_http_clients:
350                http.close()
351            self._extra_http_clients.clear()
@classmethod
def with_secret_key( cls, key: str, base_url: str | None = None) -> PlatformClient:
355    @classmethod
356    def with_secret_key(cls, key: str, base_url: str | None = None) -> "PlatformClient":
357        """Secret API key — full admin access, no user JWT required"""
358        kwargs = {}
359        if base_url:
360            kwargs["base_url"] = base_url
361        return cls(default_headers={"x-archastro-api-key": key}, **kwargs)

Secret API key — full admin access, no user JWT required

@classmethod
def with_token( cls, api_key: str, access_token: str, base_url: str | None = None) -> PlatformClient:
363    @classmethod
364    def with_token(
365        cls, api_key: str, access_token: str, base_url: str | None = None
366    ) -> "PlatformClient":
367        """Create a client with a publishable key and pre-existing access token."""
368        kwargs = {}
369        if base_url:
370            kwargs["base_url"] = base_url
371        return cls(
372            access_token=access_token, default_headers={"x-archastro-api-key": api_key}, **kwargs
373        )

Create a client with a publishable key and pre-existing access token.

@classmethod
def with_credentials( cls, api_key: str, email: str, password: str, base_url: str | None = None) -> PlatformClient:
375    @classmethod
376    def with_credentials(
377        cls, api_key: str, email: str, password: str, base_url: str | None = None
378    ) -> "PlatformClient":
379        kwargs = {}
380        if base_url:
381            kwargs["base_url"] = base_url
382        client = cls(default_headers={"x-archastro-api-key": api_key}, **kwargs)
383        tokens = client.auth.login(email, password)
384        if not tokens.access_token:
385            raise ValueError("Login did not return an access token")
386        client.set_access_token(tokens.access_token)
387        if tokens.refresh_token:
388            client.set_refresh_token(tokens.refresh_token)
389        refresh_http = SyncHttpClient(
390            base_url=base_url or "https://platform.archastro.ai",
391            default_headers={"x-archastro-api-key": api_key},
392            refresh_only=True,
393        )
394        client._extra_http_clients.append(refresh_http)
395        refresh_auth = AuthClient(refresh_http)
396
397        def _refresh() -> str:
398            rt = client.refresh_token
399            if not rt:
400                raise ValueError("No refresh token available")
401            refreshed = refresh_auth.refresh(rt)
402            if not refreshed.access_token:
403                raise ValueError("Refresh did not return an access token")
404            client.set_access_token(refreshed.access_token)
405            if refreshed.refresh_token:
406                client.set_refresh_token(refreshed.refresh_token)
407            return refreshed.access_token
408
409        client._http.set_refresh_handler(_refresh)
410        return client