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] = []
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] = []
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