archastro.platform.client

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

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:
198    @classmethod
199    async def with_credentials(
200        cls, api_key: str, email: str, password: str, base_url: str | None = None
201    ) -> "AsyncPlatformClient":
202        """Create a client by logging in with email/password"""
203        kwargs = {}
204        if base_url:
205            kwargs["base_url"] = base_url
206        client = cls(default_headers={"x-archastro-api-key": api_key}, **kwargs)
207        tokens = await client.auth.login(email, password)
208        if not tokens.access_token:
209            raise ValueError("Login did not return an access token")
210        client.set_access_token(tokens.access_token)
211        if tokens.refresh_token:
212            client.set_refresh_token(tokens.refresh_token)
213        refresh_http = HttpClient(
214            base_url=base_url or "https://platform.archastro.ai",
215            default_headers={"x-archastro-api-key": api_key},
216            refresh_only=True,
217        )
218        client._extra_http_clients.append(refresh_http)
219        refresh_auth = AsyncAuthClient(refresh_http)
220
221        async def _refresh() -> str:
222            rt = client.refresh_token
223            if not rt:
224                raise ValueError("No refresh token available")
225            refreshed = await refresh_auth.refresh(rt)
226            if not refreshed.access_token:
227                raise ValueError("Refresh did not return an access token")
228            client.set_access_token(refreshed.access_token)
229            if refreshed.refresh_token:
230                client.set_refresh_token(refreshed.refresh_token)
231            return refreshed.access_token
232
233        client._http.set_refresh_handler(_refresh)
234        return client

Create a client by logging in with email/password

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

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:
347    @classmethod
348    def with_credentials(
349        cls, api_key: str, email: str, password: str, base_url: str | None = None
350    ) -> "PlatformClient":
351        kwargs = {}
352        if base_url:
353            kwargs["base_url"] = base_url
354        client = cls(default_headers={"x-archastro-api-key": api_key}, **kwargs)
355        tokens = client.auth.login(email, password)
356        if not tokens.access_token:
357            raise ValueError("Login did not return an access token")
358        client.set_access_token(tokens.access_token)
359        if tokens.refresh_token:
360            client.set_refresh_token(tokens.refresh_token)
361        refresh_http = SyncHttpClient(
362            base_url=base_url or "https://platform.archastro.ai",
363            default_headers={"x-archastro-api-key": api_key},
364            refresh_only=True,
365        )
366        client._extra_http_clients.append(refresh_http)
367        refresh_auth = AuthClient(refresh_http)
368
369        def _refresh() -> str:
370            rt = client.refresh_token
371            if not rt:
372                raise ValueError("No refresh token available")
373            refreshed = refresh_auth.refresh(rt)
374            if not refreshed.access_token:
375                raise ValueError("Refresh did not return an access token")
376            client.set_access_token(refreshed.access_token)
377            if refreshed.refresh_token:
378                client.set_refresh_token(refreshed.refresh_token)
379            return refreshed.access_token
380
381        client._http.set_refresh_handler(_refresh)
382        return client