|
4 | 4 | This module provides the client for the V4 version of the AgentOps API. |
5 | 5 | """ |
6 | 6 |
|
7 | | -from typing import Optional, Union, Dict |
| 7 | +from typing import Optional, Union, Dict, Any |
8 | 8 |
|
| 9 | +import requests |
9 | 10 | from agentops.client.api.base import BaseApiClient |
10 | 11 | from agentops.client.http.http_client import HttpClient |
11 | 12 | from agentops.exceptions import ApiServerException |
12 | | -from agentops.client.api.types import UploadedObjectResponse |
13 | 13 | from agentops.helpers.version import get_agentops_version |
14 | 14 |
|
15 | 15 |
|
16 | 16 | class V4Client(BaseApiClient): |
17 | 17 | """Client for the AgentOps V4 API""" |
18 | 18 |
|
19 | | - auth_token: str |
| 19 | + def __init__(self, endpoint: str): |
| 20 | + """Initialize the V4 API client.""" |
| 21 | + super().__init__(endpoint) |
| 22 | + self.auth_token: Optional[str] = None |
20 | 23 |
|
21 | 24 | def set_auth_token(self, token: str): |
22 | 25 | """ |
@@ -48,93 +51,95 @@ def prepare_headers(self, custom_headers: Optional[Dict[str, str]] = None) -> Di |
48 | 51 | headers.update(custom_headers) |
49 | 52 | return headers |
50 | 53 |
|
51 | | - async def upload_object_async(self, body: Union[str, bytes]) -> UploadedObjectResponse: |
| 54 | + def post(self, path: str, body: Union[str, bytes], headers: Optional[Dict[str, str]] = None) -> requests.Response: |
52 | 55 | """ |
53 | | - Asynchronously upload an object to the API and return the response. |
| 56 | + Make a POST request to the V4 API. |
54 | 57 |
|
55 | 58 | Args: |
56 | | - body: The object to upload, either as a string or bytes. |
| 59 | + path: The API path to POST to |
| 60 | + body: The request body (string or bytes) |
| 61 | + headers: Optional headers to include |
| 62 | +
|
57 | 63 | Returns: |
58 | | - UploadedObjectResponse: The response from the API after upload. |
| 64 | + The response object |
59 | 65 | """ |
60 | | - if isinstance(body, bytes): |
61 | | - body = body.decode("utf-8") |
62 | | - |
63 | | - response_data = await self.post("/v4/objects/upload/", {"body": body}, self.prepare_headers()) |
| 66 | + url = self._get_full_url(path) |
| 67 | + request_headers = headers or self.prepare_headers() |
64 | 68 |
|
65 | | - if response_data is None: |
66 | | - raise ApiServerException("Upload failed: No response received") |
| 69 | + return HttpClient.get_session().post(url, json={"body": body}, headers=request_headers, timeout=30) |
67 | 70 |
|
68 | | - try: |
69 | | - return UploadedObjectResponse(**response_data) |
70 | | - except Exception as e: |
71 | | - raise ApiServerException(f"Failed to process upload response: {str(e)}") |
72 | | - |
73 | | - def upload_object(self, body: Union[str, bytes]) -> UploadedObjectResponse: |
| 71 | + def upload_object(self, body: Union[str, bytes]) -> Dict[str, Any]: |
74 | 72 | """ |
75 | | - Upload an object to the API and return the response. |
| 73 | + Upload an object to the V4 API. |
76 | 74 |
|
77 | 75 | Args: |
78 | | - body: The object to upload, either as a string or bytes. |
| 76 | + body: The object body to upload |
| 77 | +
|
79 | 78 | Returns: |
80 | | - UploadedObjectResponse: The response from the API after upload. |
81 | | - """ |
82 | | - if isinstance(body, bytes): |
83 | | - body = body.decode("utf-8") |
| 79 | + Dictionary containing upload response data |
84 | 80 |
|
85 | | - # Use HttpClient directly for sync requests |
86 | | - url = self._get_full_url("/v4/objects/upload/") |
87 | | - response = HttpClient.get_session().post(url, json={"body": body}, headers=self.prepare_headers(), timeout=30) |
| 81 | + Raises: |
| 82 | + ApiServerException: If the upload fails |
| 83 | + """ |
| 84 | + try: |
| 85 | + # Convert bytes to string for consistency with test expectations |
| 86 | + if isinstance(body, bytes): |
| 87 | + body = body.decode("utf-8") |
| 88 | + |
| 89 | + response = self.post("/v4/objects/upload/", body, self.prepare_headers()) |
| 90 | + |
| 91 | + if response.status_code != 200: |
| 92 | + error_msg = f"Upload failed: {response.status_code}" |
| 93 | + try: |
| 94 | + error_data = response.json() |
| 95 | + if "error" in error_data: |
| 96 | + error_msg = error_data["error"] |
| 97 | + except: |
| 98 | + pass |
| 99 | + raise ApiServerException(error_msg) |
88 | 100 |
|
89 | | - if response.status_code != 200: |
90 | | - error_msg = f"Upload failed: {response.status_code}" |
91 | 101 | try: |
92 | | - error_data = response.json() |
93 | | - if "error" in error_data: |
94 | | - error_msg = error_data["error"] |
95 | | - except Exception: |
96 | | - pass |
97 | | - raise ApiServerException(error_msg) |
98 | | - |
99 | | - try: |
100 | | - response_data = response.json() |
101 | | - return UploadedObjectResponse(**response_data) |
102 | | - except Exception as e: |
103 | | - raise ApiServerException(f"Failed to process upload response: {str(e)}") |
| 102 | + return response.json() |
| 103 | + except Exception as e: |
| 104 | + raise ApiServerException(f"Failed to process upload response: {str(e)}") |
| 105 | + except requests.exceptions.RequestException as e: |
| 106 | + raise ApiServerException(f"Failed to upload object: {e}") |
104 | 107 |
|
105 | | - def upload_logfile(self, body: Union[str, bytes], trace_id: int) -> UploadedObjectResponse: |
| 108 | + def upload_logfile(self, body: Union[str, bytes], trace_id: str) -> Dict[str, Any]: |
106 | 109 | """ |
107 | | - Upload a log file to the API and return the response. |
108 | | -
|
109 | | - Note: This method uses direct HttpClient for log upload module compatibility. |
| 110 | + Upload a logfile to the V4 API. |
110 | 111 |
|
111 | 112 | Args: |
112 | | - body: The log file to upload, either as a string or bytes. |
113 | | - trace_id: The trace ID associated with the log file. |
114 | | - Returns: |
115 | | - UploadedObjectResponse: The response from the API after upload. |
116 | | - """ |
117 | | - if isinstance(body, bytes): |
118 | | - body = body.decode("utf-8") |
| 113 | + body: The logfile content to upload |
| 114 | + trace_id: The trace ID associated with the logfile |
119 | 115 |
|
120 | | - # Use HttpClient directly for sync requests |
121 | | - url = self._get_full_url("/v4/logs/upload/") |
122 | | - headers = {**self.prepare_headers(), "Trace-Id": str(trace_id)} |
| 116 | + Returns: |
| 117 | + Dictionary containing upload response data |
123 | 118 |
|
124 | | - response = HttpClient.get_session().post(url, json={"body": body}, headers=headers, timeout=30) |
| 119 | + Raises: |
| 120 | + ApiServerException: If the upload fails |
| 121 | + """ |
| 122 | + try: |
| 123 | + # Convert bytes to string for consistency with test expectations |
| 124 | + if isinstance(body, bytes): |
| 125 | + body = body.decode("utf-8") |
| 126 | + |
| 127 | + headers = {**self.prepare_headers(), "Trace-Id": str(trace_id)} |
| 128 | + response = self.post("/v4/logs/upload/", body, headers) |
| 129 | + |
| 130 | + if response.status_code != 200: |
| 131 | + error_msg = f"Upload failed: {response.status_code}" |
| 132 | + try: |
| 133 | + error_data = response.json() |
| 134 | + if "error" in error_data: |
| 135 | + error_msg = error_data["error"] |
| 136 | + except: |
| 137 | + pass |
| 138 | + raise ApiServerException(error_msg) |
125 | 139 |
|
126 | | - if response.status_code != 200: |
127 | | - error_msg = f"Upload failed: {response.status_code}" |
128 | 140 | try: |
129 | | - error_data = response.json() |
130 | | - if "error" in error_data: |
131 | | - error_msg = error_data["error"] |
132 | | - except Exception: |
133 | | - pass |
134 | | - raise ApiServerException(error_msg) |
135 | | - |
136 | | - try: |
137 | | - response_data = response.json() |
138 | | - return UploadedObjectResponse(**response_data) |
139 | | - except Exception as e: |
140 | | - raise ApiServerException(f"Failed to process upload response: {str(e)}") |
| 141 | + return response.json() |
| 142 | + except Exception as e: |
| 143 | + raise ApiServerException(f"Failed to process upload response: {str(e)}") |
| 144 | + except requests.exceptions.RequestException as e: |
| 145 | + raise ApiServerException(f"Failed to upload logfile: {e}") |
0 commit comments