agentrun-inner-test 0.0.62__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of agentrun-inner-test might be problematic. Click here for more details.

Files changed (154) hide show
  1. agentrun/__init__.py +358 -0
  2. agentrun/agent_runtime/__client_async_template.py +466 -0
  3. agentrun/agent_runtime/__endpoint_async_template.py +345 -0
  4. agentrun/agent_runtime/__init__.py +53 -0
  5. agentrun/agent_runtime/__runtime_async_template.py +477 -0
  6. agentrun/agent_runtime/api/__data_async_template.py +58 -0
  7. agentrun/agent_runtime/api/__init__.py +6 -0
  8. agentrun/agent_runtime/api/control.py +1362 -0
  9. agentrun/agent_runtime/api/data.py +98 -0
  10. agentrun/agent_runtime/client.py +868 -0
  11. agentrun/agent_runtime/endpoint.py +649 -0
  12. agentrun/agent_runtime/model.py +362 -0
  13. agentrun/agent_runtime/runtime.py +904 -0
  14. agentrun/credential/__client_async_template.py +177 -0
  15. agentrun/credential/__credential_async_template.py +216 -0
  16. agentrun/credential/__init__.py +28 -0
  17. agentrun/credential/api/__init__.py +5 -0
  18. agentrun/credential/api/control.py +606 -0
  19. agentrun/credential/client.py +319 -0
  20. agentrun/credential/credential.py +381 -0
  21. agentrun/credential/model.py +248 -0
  22. agentrun/integration/__init__.py +21 -0
  23. agentrun/integration/agentscope/__init__.py +13 -0
  24. agentrun/integration/agentscope/adapter.py +17 -0
  25. agentrun/integration/agentscope/builtin.py +88 -0
  26. agentrun/integration/agentscope/message_adapter.py +185 -0
  27. agentrun/integration/agentscope/model_adapter.py +60 -0
  28. agentrun/integration/agentscope/tool_adapter.py +59 -0
  29. agentrun/integration/builtin/__init__.py +18 -0
  30. agentrun/integration/builtin/knowledgebase.py +137 -0
  31. agentrun/integration/builtin/model.py +93 -0
  32. agentrun/integration/builtin/sandbox.py +1234 -0
  33. agentrun/integration/builtin/toolset.py +47 -0
  34. agentrun/integration/crewai/__init__.py +13 -0
  35. agentrun/integration/crewai/adapter.py +9 -0
  36. agentrun/integration/crewai/builtin.py +88 -0
  37. agentrun/integration/crewai/model_adapter.py +31 -0
  38. agentrun/integration/crewai/tool_adapter.py +26 -0
  39. agentrun/integration/google_adk/__init__.py +13 -0
  40. agentrun/integration/google_adk/adapter.py +15 -0
  41. agentrun/integration/google_adk/builtin.py +88 -0
  42. agentrun/integration/google_adk/message_adapter.py +144 -0
  43. agentrun/integration/google_adk/model_adapter.py +46 -0
  44. agentrun/integration/google_adk/tool_adapter.py +235 -0
  45. agentrun/integration/langchain/__init__.py +31 -0
  46. agentrun/integration/langchain/adapter.py +15 -0
  47. agentrun/integration/langchain/builtin.py +94 -0
  48. agentrun/integration/langchain/message_adapter.py +141 -0
  49. agentrun/integration/langchain/model_adapter.py +37 -0
  50. agentrun/integration/langchain/tool_adapter.py +50 -0
  51. agentrun/integration/langgraph/__init__.py +36 -0
  52. agentrun/integration/langgraph/adapter.py +20 -0
  53. agentrun/integration/langgraph/agent_converter.py +1073 -0
  54. agentrun/integration/langgraph/builtin.py +88 -0
  55. agentrun/integration/pydantic_ai/__init__.py +13 -0
  56. agentrun/integration/pydantic_ai/adapter.py +13 -0
  57. agentrun/integration/pydantic_ai/builtin.py +88 -0
  58. agentrun/integration/pydantic_ai/model_adapter.py +44 -0
  59. agentrun/integration/pydantic_ai/tool_adapter.py +19 -0
  60. agentrun/integration/utils/__init__.py +112 -0
  61. agentrun/integration/utils/adapter.py +560 -0
  62. agentrun/integration/utils/canonical.py +164 -0
  63. agentrun/integration/utils/converter.py +134 -0
  64. agentrun/integration/utils/model.py +110 -0
  65. agentrun/integration/utils/tool.py +1759 -0
  66. agentrun/knowledgebase/__client_async_template.py +173 -0
  67. agentrun/knowledgebase/__init__.py +53 -0
  68. agentrun/knowledgebase/__knowledgebase_async_template.py +438 -0
  69. agentrun/knowledgebase/api/__data_async_template.py +414 -0
  70. agentrun/knowledgebase/api/__init__.py +19 -0
  71. agentrun/knowledgebase/api/control.py +606 -0
  72. agentrun/knowledgebase/api/data.py +624 -0
  73. agentrun/knowledgebase/client.py +311 -0
  74. agentrun/knowledgebase/knowledgebase.py +748 -0
  75. agentrun/knowledgebase/model.py +270 -0
  76. agentrun/memory_collection/__client_async_template.py +178 -0
  77. agentrun/memory_collection/__init__.py +37 -0
  78. agentrun/memory_collection/__memory_collection_async_template.py +457 -0
  79. agentrun/memory_collection/api/__init__.py +5 -0
  80. agentrun/memory_collection/api/control.py +610 -0
  81. agentrun/memory_collection/client.py +323 -0
  82. agentrun/memory_collection/memory_collection.py +844 -0
  83. agentrun/memory_collection/model.py +162 -0
  84. agentrun/model/__client_async_template.py +357 -0
  85. agentrun/model/__init__.py +57 -0
  86. agentrun/model/__model_proxy_async_template.py +270 -0
  87. agentrun/model/__model_service_async_template.py +267 -0
  88. agentrun/model/api/__init__.py +6 -0
  89. agentrun/model/api/control.py +1173 -0
  90. agentrun/model/api/data.py +196 -0
  91. agentrun/model/client.py +674 -0
  92. agentrun/model/model.py +235 -0
  93. agentrun/model/model_proxy.py +439 -0
  94. agentrun/model/model_service.py +438 -0
  95. agentrun/sandbox/__aio_sandbox_async_template.py +523 -0
  96. agentrun/sandbox/__browser_sandbox_async_template.py +110 -0
  97. agentrun/sandbox/__client_async_template.py +491 -0
  98. agentrun/sandbox/__code_interpreter_sandbox_async_template.py +463 -0
  99. agentrun/sandbox/__init__.py +69 -0
  100. agentrun/sandbox/__sandbox_async_template.py +463 -0
  101. agentrun/sandbox/__template_async_template.py +152 -0
  102. agentrun/sandbox/aio_sandbox.py +912 -0
  103. agentrun/sandbox/api/__aio_data_async_template.py +335 -0
  104. agentrun/sandbox/api/__browser_data_async_template.py +140 -0
  105. agentrun/sandbox/api/__code_interpreter_data_async_template.py +206 -0
  106. agentrun/sandbox/api/__init__.py +19 -0
  107. agentrun/sandbox/api/__sandbox_data_async_template.py +107 -0
  108. agentrun/sandbox/api/aio_data.py +551 -0
  109. agentrun/sandbox/api/browser_data.py +172 -0
  110. agentrun/sandbox/api/code_interpreter_data.py +396 -0
  111. agentrun/sandbox/api/control.py +1051 -0
  112. agentrun/sandbox/api/playwright_async.py +492 -0
  113. agentrun/sandbox/api/playwright_sync.py +492 -0
  114. agentrun/sandbox/api/sandbox_data.py +154 -0
  115. agentrun/sandbox/browser_sandbox.py +185 -0
  116. agentrun/sandbox/client.py +925 -0
  117. agentrun/sandbox/code_interpreter_sandbox.py +823 -0
  118. agentrun/sandbox/model.py +384 -0
  119. agentrun/sandbox/sandbox.py +848 -0
  120. agentrun/sandbox/template.py +217 -0
  121. agentrun/server/__init__.py +191 -0
  122. agentrun/server/agui_normalizer.py +180 -0
  123. agentrun/server/agui_protocol.py +797 -0
  124. agentrun/server/invoker.py +309 -0
  125. agentrun/server/model.py +427 -0
  126. agentrun/server/openai_protocol.py +535 -0
  127. agentrun/server/protocol.py +140 -0
  128. agentrun/server/server.py +208 -0
  129. agentrun/toolset/__client_async_template.py +62 -0
  130. agentrun/toolset/__init__.py +51 -0
  131. agentrun/toolset/__toolset_async_template.py +204 -0
  132. agentrun/toolset/api/__init__.py +17 -0
  133. agentrun/toolset/api/control.py +262 -0
  134. agentrun/toolset/api/mcp.py +100 -0
  135. agentrun/toolset/api/openapi.py +1251 -0
  136. agentrun/toolset/client.py +102 -0
  137. agentrun/toolset/model.py +321 -0
  138. agentrun/toolset/toolset.py +271 -0
  139. agentrun/utils/__data_api_async_template.py +721 -0
  140. agentrun/utils/__init__.py +5 -0
  141. agentrun/utils/__resource_async_template.py +158 -0
  142. agentrun/utils/config.py +270 -0
  143. agentrun/utils/control_api.py +105 -0
  144. agentrun/utils/data_api.py +1121 -0
  145. agentrun/utils/exception.py +151 -0
  146. agentrun/utils/helper.py +108 -0
  147. agentrun/utils/log.py +77 -0
  148. agentrun/utils/model.py +168 -0
  149. agentrun/utils/resource.py +291 -0
  150. agentrun_inner_test-0.0.62.dist-info/METADATA +265 -0
  151. agentrun_inner_test-0.0.62.dist-info/RECORD +154 -0
  152. agentrun_inner_test-0.0.62.dist-info/WHEEL +5 -0
  153. agentrun_inner_test-0.0.62.dist-info/licenses/LICENSE +201 -0
  154. agentrun_inner_test-0.0.62.dist-info/top_level.txt +1 -0
@@ -0,0 +1,721 @@
1
+ """AgentRun Data Client SDK / AgentRun 数据客户端 SDK
2
+
3
+ This module provides an async HTTP client for interacting with the AgentRun Data API.
4
+ 此模块提供用于与 AgentRun Data API 交互的异步 HTTP 客户端。
5
+
6
+ It supports standard HTTP methods (GET, POST, PUT, PATCH, DELETE) with proper
7
+ error handling, type hints, and JSON serialization.
8
+ """
9
+
10
+ from enum import Enum
11
+ from typing import Any, Dict, Optional, Union
12
+ from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
13
+
14
+ import httpx
15
+
16
+ from agentrun.utils.config import Config
17
+ from agentrun.utils.exception import ClientError
18
+ from agentrun.utils.helper import mask_password
19
+ from agentrun.utils.log import logger
20
+
21
+
22
+ class ResourceType(Enum):
23
+ Runtime = "runtime"
24
+ LiteLLM = "litellm"
25
+ Tool = "tool"
26
+ Template = "template"
27
+ Sandbox = "sandbox"
28
+ KnowledgeBase = "knowledgebase"
29
+
30
+
31
+ class DataAPI:
32
+ """
33
+ Async HTTP client for AgentRun Data API.
34
+
35
+ This client provides async methods for making HTTP requests to the AgentRun Data API
36
+ with automatic URL construction, JSON handling, and error management.
37
+
38
+ The client automatically manages HTTP sessions - no need for manual session management
39
+ or context managers in simple use cases.
40
+ """
41
+
42
+ def __init__(
43
+ self,
44
+ resource_name: str,
45
+ resource_type: ResourceType,
46
+ config: Optional[Config] = None,
47
+ namespace: str = "agents",
48
+ ):
49
+ """
50
+ Initialize the AgentRun Data Client.
51
+
52
+ Args:
53
+ region: Aliyun region (default: "cn-hangzhou")
54
+ protocol: Protocol to use (default: "https")
55
+ account_id: Aliyun account ID
56
+ version: API version (default: "2025-09-10")
57
+ namespace: API namespace (default: "agents")
58
+ timeout: Request timeout in seconds (default: 600)
59
+ headers: Default headers to include in all requests
60
+ auto_manage_session: Whether to automatically manage sessions (default: True)
61
+
62
+ Raises:
63
+ ValueError: If account_id is not provided or protocol is invalid
64
+ """
65
+
66
+ self.resource_name = resource_name
67
+ self.resource_type = resource_type
68
+ self.access_token = None
69
+
70
+ self.config = Config.with_configs(config)
71
+ self.namespace = namespace
72
+
73
+ if self.config.get_token():
74
+ logger.debug(
75
+ "using provided access token from config, %s",
76
+ mask_password(self.config.get_token() or ""),
77
+ )
78
+ self.access_token = self.config.get_token()
79
+
80
+ def get_base_url(self) -> str:
81
+ """
82
+ Get the base URL for API requests.
83
+
84
+ Returns:
85
+ The base URL string
86
+ """
87
+ return self.config.get_data_endpoint()
88
+
89
+ def with_path(
90
+ self, path: str, query: Optional[Dict[str, Any]] = None
91
+ ) -> str:
92
+ """
93
+ Construct full URL with the given path and query parameters.
94
+
95
+ Args:
96
+ path: API path (may include query string)
97
+ query: Query parameters to add/merge
98
+
99
+ Returns:
100
+ Complete URL string with query parameters
101
+
102
+ Examples:
103
+ >>> client.with_path("resources")
104
+ "http://account.agentrun-data.cn-hangzhou.aliyuncs.com/2025-09-10/agents/resources"
105
+
106
+ >>> client.with_path("resources", {"limit": 10})
107
+ "http://account.agentrun-data.cn-hangzhou.aliyuncs.com/2025-09-10/agents/resources?limit=10"
108
+
109
+ >>> client.with_path("resources?page=1", {"limit": 10})
110
+ "http://account.agentrun-data.cn-hangzhou.aliyuncs.com/2025-09-10/agents/resources?page=1&limit=10"
111
+ """
112
+ # Remove leading slash if present
113
+ path = path.lstrip("/")
114
+ base_url = "/".join([
115
+ part.strip("/")
116
+ for part in [
117
+ self.get_base_url(),
118
+ self.namespace,
119
+ path,
120
+ ]
121
+ if part
122
+ ])
123
+
124
+ # If no query parameters, return the base URL
125
+ if not query:
126
+ return base_url
127
+
128
+ # Parse the URL to handle existing query parameters
129
+ parsed = urlparse(base_url)
130
+
131
+ # Parse existing query parameters
132
+ existing_params = parse_qs(parsed.query, keep_blank_values=True)
133
+
134
+ # Merge with new query parameters
135
+ # Convert new query dict to the same format as parse_qs (values as lists)
136
+ for key, value in query.items():
137
+ if isinstance(value, list):
138
+ existing_params[key] = value
139
+ else:
140
+ existing_params[key] = [str(value)]
141
+
142
+ # Flatten the parameters (convert lists to single values where appropriate)
143
+ flattened_params = {}
144
+ for key, value_list in existing_params.items():
145
+ if len(value_list) == 1:
146
+ flattened_params[key] = value_list[0]
147
+ else:
148
+ flattened_params[key] = value_list
149
+
150
+ # Encode query string
151
+ new_query = urlencode(flattened_params, doseq=True)
152
+
153
+ # Reconstruct URL with new query string
154
+ return urlunparse((
155
+ parsed.scheme,
156
+ parsed.netloc,
157
+ parsed.path,
158
+ parsed.params,
159
+ new_query,
160
+ parsed.fragment,
161
+ ))
162
+
163
+ def auth(
164
+ self,
165
+ url: str = "",
166
+ headers: Optional[Dict[str, str]] = None,
167
+ query: Optional[Dict[str, Any]] = None,
168
+ config: Optional[Config] = None,
169
+ ) -> tuple[str, Dict[str, str], Optional[Dict[str, Any]]]:
170
+ """
171
+ Authentication hook for modifying requests before sending.
172
+
173
+ This method can be overridden in subclasses to implement custom
174
+ authentication logic (e.g., signing requests, adding auth tokens).
175
+
176
+ Args:
177
+ url: The request URL
178
+ headers: The request headers
179
+ query: The query parameters
180
+
181
+ Returns:
182
+ Tuple of (modified_url, modified_headers, modified_query)
183
+
184
+ Examples:
185
+ Override this method to add custom authentication:
186
+
187
+ >>> class AuthedClient(AgentRunDataClient):
188
+ ... def auth(self, url, headers, query):
189
+ ... # Add auth token to headers
190
+ ... headers["Authorization"] = "Bearer token123"
191
+ ... # Or add signature to query
192
+ ... query = query or {}
193
+ ... query["signature"] = self._sign_request(url)
194
+ ... return url, headers, query
195
+ """
196
+ cfg = Config.with_configs(self.config, config)
197
+
198
+ if (
199
+ self.access_token is None
200
+ and self.resource_name
201
+ and self.resource_type
202
+ and not cfg.get_token()
203
+ ):
204
+ try:
205
+ from alibabacloud_agentrun20250910.models import (
206
+ GetAccessTokenRequest,
207
+ )
208
+
209
+ from .control_api import ControlAPI
210
+
211
+ cli = ControlAPI(self.config)._get_client()
212
+ input = (
213
+ GetAccessTokenRequest(
214
+ resource_id=self.resource_name,
215
+ resource_type=self.resource_type.value,
216
+ )
217
+ if self.resource_type == ResourceType.Sandbox
218
+ else GetAccessTokenRequest(
219
+ resource_name=self.resource_name,
220
+ resource_type=self.resource_type.value,
221
+ )
222
+ )
223
+
224
+ resp = cli.get_access_token(input)
225
+ self.access_token = resp.body.data.access_token
226
+
227
+ except Exception as e:
228
+ logger.warning(
229
+ "Failed to get access token for"
230
+ f" {self.resource_type}({self.resource_name}): {e}"
231
+ )
232
+
233
+ logger.debug(
234
+ "fetching access token for resource %s of type %s, %s",
235
+ self.resource_name,
236
+ self.resource_type,
237
+ mask_password(self.access_token or ""),
238
+ )
239
+ headers = {
240
+ "Agentrun-Access-Token": cfg.get_token() or self.access_token or "",
241
+ **cfg.get_headers(),
242
+ **(headers or {}),
243
+ }
244
+
245
+ return url, headers, query
246
+
247
+ def _prepare_request(
248
+ self,
249
+ method: str,
250
+ url: str,
251
+ data: Optional[Union[Dict[str, Any], str]] = None,
252
+ headers: Optional[Dict[str, str]] = None,
253
+ query: Optional[Dict[str, Any]] = None,
254
+ config: Optional[Config] = None,
255
+ ):
256
+ req_headers = {
257
+ "Content-Type": "application/json",
258
+ "User-Agent": "AgentRunDataClient/1.0",
259
+ }
260
+
261
+ # Merge with instance default headers
262
+ cfg = Config.with_configs(self.config, config)
263
+
264
+ req_headers.update(cfg.get_headers())
265
+
266
+ # Merge request-specific headers
267
+ if headers:
268
+ req_headers.update(headers)
269
+
270
+ # Apply authentication (may modify URL, headers, and query)
271
+ url, req_headers, query = self.auth(url, req_headers, query, config=cfg)
272
+
273
+ # Add query parameters to URL if provided
274
+ if query:
275
+ parsed = urlparse(url)
276
+ existing_params = parse_qs(parsed.query, keep_blank_values=True)
277
+
278
+ # Merge query parameters
279
+ for key, value in query.items():
280
+ if isinstance(value, list):
281
+ existing_params[key] = value
282
+ else:
283
+ existing_params[key] = [str(value)]
284
+
285
+ # Flatten and encode
286
+ flattened_params = {}
287
+ for key, value_list in existing_params.items():
288
+ if len(value_list) == 1:
289
+ flattened_params[key] = value_list[0]
290
+ else:
291
+ flattened_params[key] = value_list
292
+
293
+ new_query = urlencode(flattened_params, doseq=True)
294
+ url = urlunparse((
295
+ parsed.scheme,
296
+ parsed.netloc,
297
+ parsed.path,
298
+ parsed.params,
299
+ new_query,
300
+ parsed.fragment,
301
+ ))
302
+
303
+ # Prepare request body
304
+ req_json = None
305
+ req_content = None
306
+
307
+ if data is not None:
308
+ if isinstance(data, dict):
309
+ req_json = data
310
+ elif isinstance(data, str):
311
+ req_content = data
312
+ else:
313
+ req_content = str(data)
314
+
315
+ logger.debug(
316
+ "%s %s headers=%s, json=%s, content=%s",
317
+ method,
318
+ url,
319
+ req_headers,
320
+ req_json,
321
+ req_content,
322
+ )
323
+ return method, url, req_headers, req_json, req_content
324
+
325
+ async def _make_request_async(
326
+ self,
327
+ method: str,
328
+ url: str,
329
+ data: Optional[Union[Dict[str, Any], str]] = None,
330
+ headers: Optional[Dict[str, str]] = None,
331
+ query: Optional[Dict[str, Any]] = None,
332
+ config: Optional[Config] = None,
333
+ ) -> Dict[str, Any]:
334
+ """
335
+ Make a sync HTTP request using httpx.
336
+
337
+ Args:
338
+ method: HTTP method (GET, POST, PUT, PATCH, DELETE)
339
+ url: Full URL to request
340
+ data: Request body (dict or string)
341
+ headers: Additional headers to include
342
+ query: Query parameters to add to URL
343
+
344
+ Returns:
345
+ Response body as dictionary
346
+
347
+ Raises:
348
+ AgentRunClientError: If the request fails
349
+ """
350
+ method, url, req_headers, req_json, req_content = self._prepare_request(
351
+ method, url, data, headers, query, config=config
352
+ )
353
+
354
+ try:
355
+ async with httpx.AsyncClient(
356
+ timeout=self.config.get_timeout()
357
+ ) as client:
358
+ response = await client.request(
359
+ method,
360
+ url,
361
+ headers=req_headers,
362
+ json=req_json,
363
+ content=req_content,
364
+ )
365
+
366
+ # # Raise for HTTP error status codes
367
+ # response.raise_for_status()
368
+
369
+ response_text = response.text
370
+ logger.debug(f"Response: {response_text}")
371
+
372
+ # Parse JSON response
373
+ if response_text:
374
+ try:
375
+ return response.json()
376
+ except ValueError as e:
377
+ error_msg = f"Failed to parse JSON response: {e}"
378
+ bad_gateway_error_message = "502 Bad Gateway"
379
+ if response.status_code == 502 and (
380
+ bad_gateway_error_message in response_text
381
+ ):
382
+ error_msg = bad_gateway_error_message
383
+ logger.error(error_msg)
384
+ raise ClientError(
385
+ status_code=response.status_code, message=error_msg
386
+ ) from e
387
+
388
+ return {}
389
+
390
+ except httpx.HTTPStatusError as e:
391
+ # HTTP error response
392
+ error_text = ""
393
+ try:
394
+ error_text = e.response.text
395
+ except Exception:
396
+ error_text = str(e)
397
+
398
+ error_msg = (
399
+ f"HTTP {e.response.status_code} error:"
400
+ f" {error_text or e.response.reason_phrase}"
401
+ )
402
+ raise ClientError(
403
+ status_code=e.response.status_code, message=error_msg
404
+ ) from e
405
+
406
+ except httpx.RequestError as e:
407
+ error_msg = f"Request error: {e!s}"
408
+ raise ClientError(status_code=0, message=error_msg) from e
409
+
410
+ async def get_async(
411
+ self,
412
+ path: str,
413
+ query: Optional[Dict[str, Any]] = None,
414
+ headers: Optional[Dict[str, str]] = None,
415
+ config: Optional[Config] = None,
416
+ ) -> Dict[str, Any]:
417
+ """
418
+ Make an async GET request.
419
+
420
+ Args:
421
+ path: API path (may include query string)
422
+ query: Query parameters to add/merge
423
+ headers: Additional headers
424
+
425
+ Returns:
426
+ Response body as dictionary
427
+
428
+ Raises:
429
+ AgentRunClientError: If the request fails
430
+
431
+ Examples:
432
+ >>> await client.get("resources")
433
+ >>> await client.get("resources", query={"limit": 10, "page": 1})
434
+ >>> await client.get("resources?status=active", query={"limit": 10})
435
+ """
436
+ return await self._make_request_async(
437
+ "GET",
438
+ self.with_path(path, query=query),
439
+ headers=headers,
440
+ config=config,
441
+ )
442
+
443
+ async def post_async(
444
+ self,
445
+ path: str,
446
+ data: Optional[Union[Dict[str, Any], str]] = None,
447
+ query: Optional[Dict[str, Any]] = None,
448
+ headers: Optional[Dict[str, str]] = None,
449
+ config: Optional[Config] = None,
450
+ ) -> Dict[str, Any]:
451
+ """
452
+ Make an async POST request.
453
+
454
+ Args:
455
+ path: API path (may include query string)
456
+ data: Request body
457
+ query: Query parameters to add/merge
458
+ headers: Additional headers
459
+
460
+ Returns:
461
+ Response body as dictionary
462
+
463
+ Raises:
464
+ AgentRunClientError: If the request fails
465
+
466
+ Examples:
467
+ >>> await client.post("resources", data={"name": "test"})
468
+ >>> await client.post("resources", data={"name": "test"}, query={"async": "true"})
469
+ """
470
+
471
+ return await self._make_request_async(
472
+ "POST",
473
+ self.with_path(path, query=query),
474
+ data=data,
475
+ headers=headers,
476
+ config=config,
477
+ )
478
+
479
+ async def put_async(
480
+ self,
481
+ path: str,
482
+ data: Optional[Union[Dict[str, Any], str]] = None,
483
+ query: Optional[Dict[str, Any]] = None,
484
+ headers: Optional[Dict[str, str]] = None,
485
+ config: Optional[Config] = None,
486
+ ) -> Dict[str, Any]:
487
+ """
488
+ Make an async PUT request.
489
+
490
+ Args:
491
+ path: API path (may include query string)
492
+ data: Request body
493
+ query: Query parameters to add/merge
494
+ headers: Additional headers
495
+
496
+ Returns:
497
+ Response body as dictionary
498
+
499
+ Raises:
500
+ AgentRunClientError: If the request fails
501
+ """
502
+ return await self._make_request_async(
503
+ "PUT",
504
+ self.with_path(path, query=query),
505
+ data=data,
506
+ headers=headers,
507
+ config=config,
508
+ )
509
+
510
+ async def patch_async(
511
+ self,
512
+ path: str,
513
+ data: Optional[Union[Dict[str, Any], str]] = None,
514
+ query: Optional[Dict[str, Any]] = None,
515
+ headers: Optional[Dict[str, str]] = None,
516
+ config: Optional[Config] = None,
517
+ ) -> Dict[str, Any]:
518
+ """
519
+ Make an async PATCH request.
520
+
521
+ Args:
522
+ path: API path (may include query string)
523
+ data: Request body
524
+ query: Query parameters to add/merge
525
+ headers: Additional headers
526
+
527
+ Returns:
528
+ Response body as dictionary
529
+
530
+ Raises:
531
+ AgentRunClientError: If the request fails
532
+ """
533
+ return await self._make_request_async(
534
+ "PATCH",
535
+ self.with_path(path, query=query),
536
+ data=data,
537
+ headers=headers,
538
+ config=config,
539
+ )
540
+
541
+ async def delete_async(
542
+ self,
543
+ path: str,
544
+ query: Optional[Dict[str, Any]] = None,
545
+ headers: Optional[Dict[str, str]] = None,
546
+ config: Optional[Config] = None,
547
+ ) -> Dict[str, Any]:
548
+ """
549
+ Make an async DELETE request.
550
+
551
+ Args:
552
+ path: API path (may include query string)
553
+ query: Query parameters to add/merge
554
+ headers: Additional headers
555
+
556
+ Returns:
557
+ Response body as dictionary
558
+
559
+ Raises:
560
+ AgentRunClientError: If the request fails
561
+ """
562
+ return await self._make_request_async(
563
+ "DELETE",
564
+ self.with_path(path, query=query),
565
+ headers=headers,
566
+ config=config,
567
+ )
568
+
569
+ async def post_file_async(
570
+ self,
571
+ path: str,
572
+ local_file_path: str,
573
+ target_file_path: str,
574
+ form_data: Optional[Dict[str, Any]] = None,
575
+ query: Optional[Dict[str, Any]] = None,
576
+ headers: Optional[Dict[str, str]] = None,
577
+ config: Optional[Config] = None,
578
+ ) -> Dict[str, Any]:
579
+ """
580
+ Asynchronously upload a file using multipart/form-data (POST request).
581
+
582
+ Args:
583
+ path: API path (may include query string)
584
+ local_file_path: Local file path to upload
585
+ target_file_path: Target file path on the server
586
+ form_data: Additional form data fields
587
+ query: Query parameters to add/merge
588
+ headers: Additional headers
589
+
590
+ Returns:
591
+ Response body as dictionary
592
+
593
+ Raises:
594
+ AgentRunClientError: If the request fails
595
+
596
+ Examples:
597
+ >>> await client.post_file_async("/files", local_file_path="/local/data.csv", target_file_path="/remote/data.csv")
598
+ >>> await client.post_file_async("/files", local_file_path="/local/data.csv", target_file_path="/remote/input.csv")
599
+ """
600
+ import os
601
+
602
+ filename = os.path.basename(local_file_path)
603
+
604
+ url = self.with_path(path, query=query)
605
+ req_headers = self.config.get_headers()
606
+ req_headers.update(headers or {})
607
+
608
+ try:
609
+ with open(local_file_path, "rb") as f:
610
+ file_content = f.read()
611
+ files = {"file": (filename, file_content)}
612
+ data = form_data or {}
613
+ data["path"] = target_file_path
614
+
615
+ async with httpx.AsyncClient(
616
+ timeout=self.config.get_timeout()
617
+ ) as client:
618
+ response = await client.post(
619
+ url, files=files, data=data, headers=req_headers
620
+ )
621
+ response.raise_for_status()
622
+ return response.json()
623
+ except httpx.HTTPStatusError as e:
624
+ raise ClientError(
625
+ status_code=e.response.status_code, message=e.response.text
626
+ ) from e
627
+
628
+ async def get_file_async(
629
+ self,
630
+ path: str,
631
+ save_path: str,
632
+ query: Optional[Dict[str, Any]] = None,
633
+ headers: Optional[Dict[str, str]] = None,
634
+ config: Optional[Config] = None,
635
+ ) -> Dict[str, Any]:
636
+ """
637
+ Asynchronously download a file and save it to local path (GET request).
638
+
639
+ Args:
640
+ path: API path (may include query string)
641
+ save_path: Local file path to save the downloaded file
642
+ query: Query parameters to add/merge
643
+ headers: Additional headers
644
+
645
+ Returns:
646
+ Dictionary with 'saved_path' and 'size' keys
647
+
648
+ Raises:
649
+ AgentRunClientError: If the request fails
650
+
651
+ Examples:
652
+ >>> await client.get_file_async("/files", save_path="/local/data.csv", query={"path": "/remote/file.csv"})
653
+ """
654
+ url = self.with_path(path, query=query)
655
+ req_headers = self.config.get_headers()
656
+ req_headers.update(headers or {})
657
+
658
+ try:
659
+ async with httpx.AsyncClient(
660
+ timeout=self.config.get_timeout()
661
+ ) as client:
662
+ response = await client.get(url, headers=req_headers)
663
+ response.raise_for_status()
664
+
665
+ with open(save_path, "wb") as f:
666
+ f.write(response.content)
667
+
668
+ return {"saved_path": save_path, "size": len(response.content)}
669
+ except httpx.HTTPStatusError as e:
670
+ raise ClientError(
671
+ status_code=e.response.status_code, message=e.response.text
672
+ ) from e
673
+
674
+ async def get_video_async(
675
+ self,
676
+ path: str,
677
+ save_path: str,
678
+ query: Optional[Dict[str, Any]] = None,
679
+ headers: Optional[Dict[str, str]] = None,
680
+ config: Optional[Config] = None,
681
+ ) -> Dict[str, Any]:
682
+ """
683
+ Asynchronously download a video file and save it to local path (GET request).
684
+
685
+ Args:
686
+ path: API path (may include query string)
687
+ save_path: Local file path to save the downloaded video file (.mkv)
688
+ query: Query parameters to add/merge
689
+ headers: Additional headers
690
+
691
+ Returns:
692
+ Dictionary with 'saved_path' and 'size' keys
693
+
694
+ Raises:
695
+ AgentRunClientError: If the request fails
696
+
697
+ Examples:
698
+ >>> await client.get_video_async("/videos", save_path="/local/video.mkv", query={"path": "/remote/video.mp4"})
699
+ """
700
+ url = self.with_path(path, query=query)
701
+ req_headers = self.config.get_headers()
702
+ req_headers.update(headers or {})
703
+ # Apply authentication (may modify URL, headers, and query)
704
+ cfg = Config.with_configs(self.config, config)
705
+ url, req_headers, query = self.auth(url, req_headers, query, config=cfg)
706
+
707
+ try:
708
+ async with httpx.AsyncClient(
709
+ timeout=self.config.get_timeout()
710
+ ) as client:
711
+ response = await client.get(url, headers=req_headers)
712
+ response.raise_for_status()
713
+
714
+ with open(save_path, "wb") as f:
715
+ f.write(response.content)
716
+
717
+ return {"saved_path": save_path, "size": len(response.content)}
718
+ except httpx.HTTPStatusError as e:
719
+ raise ClientError(
720
+ status_code=e.response.status_code, message=e.response.text
721
+ ) from e