hivetrace 1.3.8__py3-none-any.whl → 1.3.9__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.
- hivetrace/client/async_client.py +66 -4
- hivetrace/client/base.py +53 -1
- hivetrace/client/sync_client.py +68 -3
- hivetrace/models/responses.py +4 -0
- {hivetrace-1.3.8.dist-info → hivetrace-1.3.9.dist-info}/METADATA +78 -5
- {hivetrace-1.3.8.dist-info → hivetrace-1.3.9.dist-info}/RECORD +9 -9
- {hivetrace-1.3.8.dist-info → hivetrace-1.3.9.dist-info}/LICENSE +0 -0
- {hivetrace-1.3.8.dist-info → hivetrace-1.3.9.dist-info}/WHEEL +0 -0
- {hivetrace-1.3.8.dist-info → hivetrace-1.3.9.dist-info}/top_level.txt +0 -0
hivetrace/client/async_client.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import warnings
|
|
2
|
-
from typing import Any, Dict, Optional, Union
|
|
2
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
3
3
|
|
|
4
4
|
import httpx
|
|
5
5
|
|
|
@@ -22,7 +22,6 @@ class AsyncHivetraceSDK(BaseHivetraceSDK):
|
|
|
22
22
|
def __init__(self, config: Optional[Dict[str, Any]] = None) -> None:
|
|
23
23
|
super().__init__(config)
|
|
24
24
|
self.session = httpx.AsyncClient()
|
|
25
|
-
# SDK асинхронный, задаем флаг для адаптеров
|
|
26
25
|
self.async_mode = True
|
|
27
26
|
|
|
28
27
|
async def __aenter__(self):
|
|
@@ -55,27 +54,90 @@ class AsyncHivetraceSDK(BaseHivetraceSDK):
|
|
|
55
54
|
except Exception as e:
|
|
56
55
|
return ErrorHandler.handle_unexpected_error(e)
|
|
57
56
|
|
|
57
|
+
async def _send_files(
|
|
58
|
+
self, endpoint: str, files: List[Tuple[str, bytes, str]]
|
|
59
|
+
) -> HivetraceResponse:
|
|
60
|
+
request_args = self._build_files_request_args(endpoint, files)
|
|
61
|
+
try:
|
|
62
|
+
response = await self.session.post(**request_args)
|
|
63
|
+
response.raise_for_status()
|
|
64
|
+
api_data = response.json()
|
|
65
|
+
return ResponseBuilder.build_response_from_api(api_data)
|
|
66
|
+
except httpx.HTTPStatusError as e:
|
|
67
|
+
return ErrorHandler.handle_http_error(e)
|
|
68
|
+
except httpx.ConnectError as e:
|
|
69
|
+
return ErrorHandler.handle_connection_error(e)
|
|
70
|
+
except httpx.TimeoutException as e:
|
|
71
|
+
return ErrorHandler.handle_timeout_error(e)
|
|
72
|
+
except httpx.RequestError as e:
|
|
73
|
+
return ErrorHandler.handle_request_error(e)
|
|
74
|
+
except ValueError as e:
|
|
75
|
+
return ErrorHandler.handle_json_decode_error(e)
|
|
76
|
+
except Exception as e:
|
|
77
|
+
return ErrorHandler.handle_unexpected_error(e)
|
|
78
|
+
|
|
79
|
+
async def _get_blocking_status(self, endpoint: str) -> Optional[bool]:
|
|
80
|
+
url = f"{self.hivetrace_url}/{endpoint.lstrip('/')}"
|
|
81
|
+
headers = {"Authorization": f"Bearer {self.hivetrace_access_token}"}
|
|
82
|
+
try:
|
|
83
|
+
response = await self.session.get(
|
|
84
|
+
url, headers=headers, timeout=self._DEFAULT_TIMEOUT
|
|
85
|
+
)
|
|
86
|
+
response.raise_for_status()
|
|
87
|
+
data = response.json()
|
|
88
|
+
return data.get("blocked")
|
|
89
|
+
except Exception:
|
|
90
|
+
return None
|
|
91
|
+
|
|
58
92
|
async def input(
|
|
59
93
|
self,
|
|
60
94
|
application_id: str,
|
|
61
95
|
message: str,
|
|
62
96
|
additional_parameters: Optional[Dict[str, Any]] = None,
|
|
97
|
+
files: Optional[List[Tuple[str, bytes, str]]] = None,
|
|
63
98
|
) -> HivetraceResponse:
|
|
64
99
|
payload = self._build_message_payload(
|
|
65
100
|
application_id, message, additional_parameters
|
|
66
101
|
)
|
|
67
|
-
|
|
102
|
+
process_response = await self._send_request("/process_request/", payload)
|
|
103
|
+
if files:
|
|
104
|
+
analysis_id = self._extract_analysis_id(process_response)
|
|
105
|
+
if analysis_id:
|
|
106
|
+
await self._send_files(
|
|
107
|
+
f"/user_prompt_analysis/{analysis_id}/attach_files", files
|
|
108
|
+
)
|
|
109
|
+
analysis_id = self._extract_analysis_id(process_response)
|
|
110
|
+
if analysis_id:
|
|
111
|
+
blocked = await self._get_blocking_status(
|
|
112
|
+
f"/user_prompt_analysis/{analysis_id}/check_blocking"
|
|
113
|
+
)
|
|
114
|
+
self._set_blocked(process_response, blocked)
|
|
115
|
+
return process_response
|
|
68
116
|
|
|
69
117
|
async def output(
|
|
70
118
|
self,
|
|
71
119
|
application_id: str,
|
|
72
120
|
message: str,
|
|
73
121
|
additional_parameters: Optional[Dict[str, Any]] = None,
|
|
122
|
+
files: Optional[List[Tuple[str, bytes, str]]] = None,
|
|
74
123
|
) -> HivetraceResponse:
|
|
75
124
|
payload = self._build_message_payload(
|
|
76
125
|
application_id, message, additional_parameters
|
|
77
126
|
)
|
|
78
|
-
|
|
127
|
+
process_response = await self._send_request("/process_response/", payload)
|
|
128
|
+
if files:
|
|
129
|
+
analysis_id = self._extract_analysis_id(process_response)
|
|
130
|
+
if analysis_id:
|
|
131
|
+
await self._send_files(
|
|
132
|
+
f"/llm_response_analysis/{analysis_id}/attach_files", files
|
|
133
|
+
)
|
|
134
|
+
analysis_id = self._extract_analysis_id(process_response)
|
|
135
|
+
if analysis_id:
|
|
136
|
+
blocked = await self._get_blocking_status(
|
|
137
|
+
f"/llm_response_analysis/{analysis_id}/check_blocking"
|
|
138
|
+
)
|
|
139
|
+
self._set_blocked(process_response, blocked)
|
|
140
|
+
return process_response
|
|
79
141
|
|
|
80
142
|
async def function_call(
|
|
81
143
|
self,
|
hivetrace/client/base.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import uuid
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
|
-
from typing import Any, Dict, Optional, Union
|
|
4
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
5
5
|
|
|
6
6
|
import httpx
|
|
7
7
|
from pydantic import ValidationError
|
|
@@ -94,6 +94,58 @@ class BaseHivetraceSDK(ABC):
|
|
|
94
94
|
"timeout": self._DEFAULT_TIMEOUT,
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
def _build_files_request_args(
|
|
98
|
+
self,
|
|
99
|
+
endpoint: str,
|
|
100
|
+
files: List[Tuple[str, bytes, str]],
|
|
101
|
+
files_field_name: str = "attached_files",
|
|
102
|
+
) -> Dict[str, Any]:
|
|
103
|
+
"""Builds request args for multipart file upload."""
|
|
104
|
+
url = f"{self.hivetrace_url}/{endpoint.lstrip('/')}"
|
|
105
|
+
headers = {"Authorization": f"Bearer {self.hivetrace_access_token}"}
|
|
106
|
+
return {
|
|
107
|
+
"url": url,
|
|
108
|
+
"files": self._prepare_files_param(files, files_field_name),
|
|
109
|
+
"headers": headers,
|
|
110
|
+
"timeout": self._DEFAULT_TIMEOUT,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@staticmethod
|
|
114
|
+
def _prepare_files_param(
|
|
115
|
+
files: List[Tuple[str, bytes, str]],
|
|
116
|
+
files_field_name: str = "attached_files",
|
|
117
|
+
) -> List[Tuple[str, Tuple[str, bytes, str]]]:
|
|
118
|
+
files_param: List[Tuple[str, Tuple[str, bytes, str]]] = []
|
|
119
|
+
for file_tuple in files:
|
|
120
|
+
files_param.append((files_field_name, file_tuple))
|
|
121
|
+
return files_param
|
|
122
|
+
|
|
123
|
+
@staticmethod
|
|
124
|
+
def _extract_analysis_id(response: Any) -> Optional[str]:
|
|
125
|
+
"""Extracts analysis id from API response if present."""
|
|
126
|
+
try:
|
|
127
|
+
if isinstance(response, dict):
|
|
128
|
+
monitoring_result = response.get("monitoring_result", {})
|
|
129
|
+
analysis_id = monitoring_result.get("id")
|
|
130
|
+
return str(analysis_id) if analysis_id is not None else None
|
|
131
|
+
except Exception:
|
|
132
|
+
return None
|
|
133
|
+
return None
|
|
134
|
+
|
|
135
|
+
@staticmethod
|
|
136
|
+
def _set_blocked(response: Any, blocked: Optional[bool]) -> Any:
|
|
137
|
+
"""Sets 'blocked' flag on response when possible."""
|
|
138
|
+
try:
|
|
139
|
+
if isinstance(response, dict):
|
|
140
|
+
response["blocked"] = blocked
|
|
141
|
+
return response
|
|
142
|
+
if hasattr(response, "blocked"):
|
|
143
|
+
setattr(response, "blocked", blocked)
|
|
144
|
+
return response
|
|
145
|
+
except Exception:
|
|
146
|
+
return response
|
|
147
|
+
return response
|
|
148
|
+
|
|
97
149
|
def _handle_http_error(self, error: httpx.HTTPStatusError) -> HivetraceResponse:
|
|
98
150
|
return ErrorHandler.handle_http_error(error)
|
|
99
151
|
|
hivetrace/client/sync_client.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import weakref
|
|
2
|
-
from typing import Any, Dict, Optional, Union
|
|
2
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
3
3
|
|
|
4
4
|
import httpx
|
|
5
5
|
|
|
@@ -67,27 +67,92 @@ class SyncHivetraceSDK(BaseHivetraceSDK):
|
|
|
67
67
|
except Exception as e:
|
|
68
68
|
return ErrorHandler.handle_unexpected_error(e)
|
|
69
69
|
|
|
70
|
+
def _send_files(
|
|
71
|
+
self, endpoint: str, files: List[Tuple[str, bytes, str]]
|
|
72
|
+
) -> HivetraceResponse:
|
|
73
|
+
request_args = self._build_files_request_args(endpoint, files)
|
|
74
|
+
try:
|
|
75
|
+
response = self.session.post(**request_args)
|
|
76
|
+
response.raise_for_status()
|
|
77
|
+
|
|
78
|
+
api_data = response.json()
|
|
79
|
+
return ResponseBuilder.build_response_from_api(api_data)
|
|
80
|
+
|
|
81
|
+
except httpx.HTTPStatusError as e:
|
|
82
|
+
return ErrorHandler.handle_http_error(e)
|
|
83
|
+
except httpx.ConnectError as e:
|
|
84
|
+
return ErrorHandler.handle_connection_error(e)
|
|
85
|
+
except httpx.TimeoutException as e:
|
|
86
|
+
return ErrorHandler.handle_timeout_error(e)
|
|
87
|
+
except httpx.RequestError as e:
|
|
88
|
+
return ErrorHandler.handle_request_error(e)
|
|
89
|
+
except ValueError as e:
|
|
90
|
+
return ErrorHandler.handle_json_decode_error(e)
|
|
91
|
+
except Exception as e:
|
|
92
|
+
return ErrorHandler.handle_unexpected_error(e)
|
|
93
|
+
|
|
94
|
+
def _get_blocking_status(self, endpoint: str) -> Optional[bool]:
|
|
95
|
+
url = f"{self.hivetrace_url}/{endpoint.lstrip('/')}"
|
|
96
|
+
headers = {"Authorization": f"Bearer {self.hivetrace_access_token}"}
|
|
97
|
+
try:
|
|
98
|
+
response = self.session.get(
|
|
99
|
+
url, headers=headers, timeout=self._DEFAULT_TIMEOUT
|
|
100
|
+
)
|
|
101
|
+
response.raise_for_status()
|
|
102
|
+
data = response.json()
|
|
103
|
+
return data.get("blocked")
|
|
104
|
+
except Exception:
|
|
105
|
+
return None
|
|
106
|
+
|
|
70
107
|
def input(
|
|
71
108
|
self,
|
|
72
109
|
application_id: str,
|
|
73
110
|
message: str,
|
|
74
111
|
additional_parameters: Optional[Dict[str, Any]] = None,
|
|
112
|
+
files: Optional[List[Tuple[str, bytes, str]]] = None,
|
|
75
113
|
) -> HivetraceResponse:
|
|
76
114
|
payload = self._build_message_payload(
|
|
77
115
|
application_id, message, additional_parameters
|
|
78
116
|
)
|
|
79
|
-
|
|
117
|
+
process_response = self._send_request("/process_request/", payload)
|
|
118
|
+
if files:
|
|
119
|
+
analysis_id = self._extract_analysis_id(process_response)
|
|
120
|
+
if analysis_id:
|
|
121
|
+
self._send_files(
|
|
122
|
+
f"/user_prompt_analysis/{analysis_id}/attach_files", files
|
|
123
|
+
)
|
|
124
|
+
analysis_id = self._extract_analysis_id(process_response)
|
|
125
|
+
if analysis_id:
|
|
126
|
+
blocked = self._get_blocking_status(
|
|
127
|
+
f"/user_prompt_analysis/{analysis_id}/check_blocking"
|
|
128
|
+
)
|
|
129
|
+
self._set_blocked(process_response, blocked)
|
|
130
|
+
return process_response
|
|
80
131
|
|
|
81
132
|
def output(
|
|
82
133
|
self,
|
|
83
134
|
application_id: str,
|
|
84
135
|
message: str,
|
|
85
136
|
additional_parameters: Optional[Dict[str, Any]] = None,
|
|
137
|
+
files: Optional[List[Tuple[str, bytes, str]]] = None,
|
|
86
138
|
) -> HivetraceResponse:
|
|
87
139
|
payload = self._build_message_payload(
|
|
88
140
|
application_id, message, additional_parameters
|
|
89
141
|
)
|
|
90
|
-
|
|
142
|
+
process_response = self._send_request("/process_response/", payload)
|
|
143
|
+
if files:
|
|
144
|
+
analysis_id = self._extract_analysis_id(process_response)
|
|
145
|
+
if analysis_id:
|
|
146
|
+
self._send_files(
|
|
147
|
+
f"/llm_response_analysis/{analysis_id}/attach_files", files
|
|
148
|
+
)
|
|
149
|
+
analysis_id = self._extract_analysis_id(process_response)
|
|
150
|
+
if analysis_id:
|
|
151
|
+
blocked = self._get_blocking_status(
|
|
152
|
+
f"/llm_response_analysis/{analysis_id}/check_blocking"
|
|
153
|
+
)
|
|
154
|
+
self._set_blocked(process_response, blocked)
|
|
155
|
+
return process_response
|
|
91
156
|
|
|
92
157
|
def function_call(
|
|
93
158
|
self,
|
hivetrace/models/responses.py
CHANGED
|
@@ -24,6 +24,10 @@ class ProcessResponse(SuccessResponse):
|
|
|
24
24
|
|
|
25
25
|
message_id: Optional[str] = Field(None, description="ID of processed message")
|
|
26
26
|
trace_id: Optional[str] = Field(None, description="Trace ID")
|
|
27
|
+
blocked: Optional[bool] = Field(
|
|
28
|
+
None,
|
|
29
|
+
description="Role restriction flag. True if message/response is blocked by policy.",
|
|
30
|
+
)
|
|
27
31
|
|
|
28
32
|
|
|
29
33
|
class ErrorResponse(BaseResponse):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hivetrace
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.9
|
|
4
4
|
Summary: Hivetrace SDK for monitoring LLM applications
|
|
5
5
|
Home-page: http://hivetrace.ai
|
|
6
6
|
Author: Raft
|
|
@@ -11,6 +11,7 @@ Requires-Python: >=3.8
|
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
13
|
Requires-Dist: httpx >=0.28.1
|
|
14
|
+
Requires-Dist: pydantic >=2.11.7
|
|
14
15
|
Requires-Dist: python-dotenv >=1.0.1
|
|
15
16
|
Provides-Extra: all
|
|
16
17
|
Requires-Dist: crewai >=0.95.0 ; extra == 'all'
|
|
@@ -20,9 +21,11 @@ Requires-Dist: langchain-openai ==0.2.5 ; extra == 'all'
|
|
|
20
21
|
Requires-Dist: langchain ==0.3.19 ; extra == 'all'
|
|
21
22
|
Requires-Dist: langchain-experimental ==0.3.4 ; extra == 'all'
|
|
22
23
|
Requires-Dist: openai-agents >=0.1.0 ; extra == 'all'
|
|
24
|
+
Requires-Dist: pydantic >=2.11.7 ; extra == 'all'
|
|
23
25
|
Requires-Dist: python-dotenv >=1.0.1 ; extra == 'all'
|
|
24
26
|
Provides-Extra: base
|
|
25
27
|
Requires-Dist: httpx >=0.28.1 ; extra == 'base'
|
|
28
|
+
Requires-Dist: pydantic >=2.11.7 ; extra == 'base'
|
|
26
29
|
Requires-Dist: python-dotenv >=1.0.1 ; extra == 'base'
|
|
27
30
|
Provides-Extra: crewai
|
|
28
31
|
Requires-Dist: crewai >=0.95.0 ; extra == 'crewai'
|
|
@@ -78,6 +81,16 @@ response = client.input(
|
|
|
78
81
|
application_id="your-application-id", # Obtained after registering the application in the UI
|
|
79
82
|
message="User prompt here",
|
|
80
83
|
)
|
|
84
|
+
|
|
85
|
+
# Optionally attach files (filename, bytes, mime_type)
|
|
86
|
+
files = [
|
|
87
|
+
("doc1.txt", open("doc1.txt", "rb"), "text/plain"),
|
|
88
|
+
]
|
|
89
|
+
response_with_files = client.input(
|
|
90
|
+
application_id="your-application-id",
|
|
91
|
+
message="User prompt with files",
|
|
92
|
+
files=files,
|
|
93
|
+
)
|
|
81
94
|
```
|
|
82
95
|
|
|
83
96
|
### Send an LLM response (output)
|
|
@@ -87,6 +100,16 @@ response = client.output(
|
|
|
87
100
|
application_id="your-application-id",
|
|
88
101
|
message="LLM response here",
|
|
89
102
|
)
|
|
103
|
+
|
|
104
|
+
# With files
|
|
105
|
+
files = [
|
|
106
|
+
("doc1.txt", open("doc1.txt", "rb"), "text/plain"),
|
|
107
|
+
]
|
|
108
|
+
response_with_files = client.output(
|
|
109
|
+
application_id="your-application-id",
|
|
110
|
+
message="LLM response with files",
|
|
111
|
+
files=files,
|
|
112
|
+
)
|
|
90
113
|
```
|
|
91
114
|
|
|
92
115
|
---
|
|
@@ -107,6 +130,16 @@ response = await client.input(
|
|
|
107
130
|
application_id="your-application-id",
|
|
108
131
|
message="User prompt here",
|
|
109
132
|
)
|
|
133
|
+
|
|
134
|
+
# With files (filename, bytes, mime_type)
|
|
135
|
+
files = [
|
|
136
|
+
("doc1.txt", open("doc1.txt", "rb"), "text/plain"),
|
|
137
|
+
]
|
|
138
|
+
response_with_files = await client.input(
|
|
139
|
+
application_id="your-application-id",
|
|
140
|
+
message="User prompt with files",
|
|
141
|
+
files=files,
|
|
142
|
+
)
|
|
110
143
|
```
|
|
111
144
|
|
|
112
145
|
### Send an LLM response (output)
|
|
@@ -116,6 +149,16 @@ response = await client.output(
|
|
|
116
149
|
application_id="your-application-id",
|
|
117
150
|
message="LLM response here",
|
|
118
151
|
)
|
|
152
|
+
|
|
153
|
+
# With files
|
|
154
|
+
files = [
|
|
155
|
+
("doc1.txt", open("doc1.txt", "rb"), "text/plain"),
|
|
156
|
+
]
|
|
157
|
+
response_with_files = await client.output(
|
|
158
|
+
application_id="your-application-id",
|
|
159
|
+
message="LLM response with files",
|
|
160
|
+
files=files,
|
|
161
|
+
)
|
|
119
162
|
```
|
|
120
163
|
|
|
121
164
|
---
|
|
@@ -148,10 +191,20 @@ response = client.input(
|
|
|
148
191
|
|
|
149
192
|
```python
|
|
150
193
|
# Sync
|
|
151
|
-
def input(
|
|
194
|
+
def input(
|
|
195
|
+
application_id: str,
|
|
196
|
+
message: str,
|
|
197
|
+
additional_parameters: dict | None = None,
|
|
198
|
+
files: list[tuple[str, bytes, str]] | None = None,
|
|
199
|
+
) -> dict: ...
|
|
152
200
|
|
|
153
201
|
# Async
|
|
154
|
-
async def input(
|
|
202
|
+
async def input(
|
|
203
|
+
application_id: str,
|
|
204
|
+
message: str,
|
|
205
|
+
additional_parameters: dict | None = None,
|
|
206
|
+
files: list[tuple[str, bytes, str]] | None = None,
|
|
207
|
+
) -> dict: ...
|
|
155
208
|
```
|
|
156
209
|
|
|
157
210
|
Sends a **user prompt** to Hivetrace.
|
|
@@ -159,11 +212,15 @@ Sends a **user prompt** to Hivetrace.
|
|
|
159
212
|
* `application_id` — Application identifier (must be a valid UUID, created in the UI)
|
|
160
213
|
* `message` — The user prompt
|
|
161
214
|
* `additional_parameters` — Optional dictionary with extra context (session, user, agents, etc.)
|
|
215
|
+
* `files` — Optional list of tuples `(filename: str, content: bytes, mime_type: str)`; files are attached to the created analysis record
|
|
216
|
+
|
|
217
|
+
Response contains a `blocked` flag that indicates role restrictions.
|
|
162
218
|
|
|
163
219
|
**Response example:**
|
|
164
220
|
|
|
165
221
|
```json
|
|
166
222
|
{
|
|
223
|
+
"blocked": false,
|
|
167
224
|
"status": "processed",
|
|
168
225
|
"monitoring_result": {
|
|
169
226
|
"is_toxic": false,
|
|
@@ -181,10 +238,20 @@ Sends a **user prompt** to Hivetrace.
|
|
|
181
238
|
|
|
182
239
|
```python
|
|
183
240
|
# Sync
|
|
184
|
-
def output(
|
|
241
|
+
def output(
|
|
242
|
+
application_id: str,
|
|
243
|
+
message: str,
|
|
244
|
+
additional_parameters: dict | None = None,
|
|
245
|
+
files: list[tuple[str, bytes, str]] | None = None,
|
|
246
|
+
) -> dict: ...
|
|
185
247
|
|
|
186
248
|
# Async
|
|
187
|
-
async def output(
|
|
249
|
+
async def output(
|
|
250
|
+
application_id: str,
|
|
251
|
+
message: str,
|
|
252
|
+
additional_parameters: dict | None = None,
|
|
253
|
+
files: list[tuple[str, bytes, str]] | None = None,
|
|
254
|
+
) -> dict: ...
|
|
188
255
|
```
|
|
189
256
|
|
|
190
257
|
Sends an **LLM response** to Hivetrace.
|
|
@@ -192,11 +259,17 @@ Sends an **LLM response** to Hivetrace.
|
|
|
192
259
|
* `application_id` — Application identifier (must be a valid UUID, created in the UI)
|
|
193
260
|
* `message` — The LLM response
|
|
194
261
|
* `additional_parameters` — Optional dictionary with extra context (session, user, agents, etc.)
|
|
262
|
+
* `files` — Optional list of tuples `(filename: str, content: bytes, mime_type: str)`
|
|
263
|
+
|
|
264
|
+
> Files are uploaded after the main request completes and an analysis ID is available.
|
|
265
|
+
|
|
266
|
+
Response contains a `blocked` flag that indicates role restrictions.
|
|
195
267
|
|
|
196
268
|
**Response example:**
|
|
197
269
|
|
|
198
270
|
```json
|
|
199
271
|
{
|
|
272
|
+
"blocked": false,
|
|
200
273
|
"status": "processed",
|
|
201
274
|
"monitoring_result": {
|
|
202
275
|
"is_toxic": false,
|
|
@@ -21,9 +21,9 @@ hivetrace/adapters/openai_agents/tracing.py,sha256=aOmJV2PT77x0bKZHXy46GRsExFmGw
|
|
|
21
21
|
hivetrace/adapters/utils/__init__.py,sha256=AkdJzecQlhT3hHFOIO5zWbAIEXvbgH_5vmzlPViedt0,142
|
|
22
22
|
hivetrace/adapters/utils/logging.py,sha256=UxCMFvlpP6vJfzRwMYhhJIi7RTWdgVK2sWtCeEB67_w,1126
|
|
23
23
|
hivetrace/client/__init__.py,sha256=Daz_KxOMzGSBKUpv48tTooGZrmzk0wzDq8QUTHuBZBU,313
|
|
24
|
-
hivetrace/client/async_client.py,sha256=
|
|
25
|
-
hivetrace/client/base.py,sha256=
|
|
26
|
-
hivetrace/client/sync_client.py,sha256=
|
|
24
|
+
hivetrace/client/async_client.py,sha256=9uvimxP-Q7vY-bbZW5RiTEYQd8_uP3wyqR3s92kPGUs,6518
|
|
25
|
+
hivetrace/client/base.py,sha256=JSVL60S7jaGNCovkTP9MPZGzSPPe7FcgMJne0QKCs1U,7960
|
|
26
|
+
hivetrace/client/sync_client.py,sha256=J3nKDVfVtfYL3NjlMtj5l7EpZKXupJnI1bpHy-tWgyE,6347
|
|
27
27
|
hivetrace/errors/__init__.py,sha256=3Sqr2Pz4NwE_u8CgTzVbzoNj-B52cwzdsHINnpWO3Yg,1006
|
|
28
28
|
hivetrace/errors/api.py,sha256=ThIoH8akPWuSqF6bqnex5f25p8ZBnRFsz2IrcivAHgc,1029
|
|
29
29
|
hivetrace/errors/base.py,sha256=_2o8TbvlPzJEzKGl4T3u1XbTAJgP5fO19T6XQSfH3pI,686
|
|
@@ -34,12 +34,12 @@ hivetrace/handlers/error_handler.py,sha256=aWLL--HKBm4h8AO4oQSpsFObq2TjHXntYXBDX
|
|
|
34
34
|
hivetrace/handlers/response_builder.py,sha256=J3qDWxvi_jxiZ7AgmYscHfukbz4rmnSwBF2UaWkqzb4,2558
|
|
35
35
|
hivetrace/models/__init__.py,sha256=qQvtDkI0Awlch6c_kedH5Jq8aWn3XhDXbxbch5nf-RI,1020
|
|
36
36
|
hivetrace/models/requests.py,sha256=dMKUMOqerDmZj4CcQ3AF-N4HSl_csv9lafA2bpggNVc,2640
|
|
37
|
-
hivetrace/models/responses.py,sha256=
|
|
37
|
+
hivetrace/models/responses.py,sha256=U06Gc4ZU2WmaPxjy1Dg5BtTDad6MOBURiDPTeLyDtcE,3209
|
|
38
38
|
hivetrace/utils/__init__.py,sha256=BNYbeSuUbrZL7RradjE_OFAxam3L6eexbL2IMfjImv0,747
|
|
39
39
|
hivetrace/utils/error_helpers.py,sha256=egVQpENputLR8exNpV1cui2LSHqbf8pI6SHRbLdxOX8,2661
|
|
40
40
|
hivetrace/utils/uuid_generator.py,sha256=W4i2tUSyClNKNgm4O-bk_Qkkmw3cWIuf29DjwXftx0c,344
|
|
41
|
-
hivetrace-1.3.
|
|
42
|
-
hivetrace-1.3.
|
|
43
|
-
hivetrace-1.3.
|
|
44
|
-
hivetrace-1.3.
|
|
45
|
-
hivetrace-1.3.
|
|
41
|
+
hivetrace-1.3.9.dist-info/LICENSE,sha256=8d3g3prbWPDLQ5AV0dtyWfYTj5QPl8MJ_wlr2l8pjEU,11333
|
|
42
|
+
hivetrace-1.3.9.dist-info/METADATA,sha256=WMOawn28WE9xSOozoUgigYH2UkRCMCtcreYj7r_ccuY,27727
|
|
43
|
+
hivetrace-1.3.9.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
44
|
+
hivetrace-1.3.9.dist-info/top_level.txt,sha256=F6mZCzZ5CSftMc-M0NeOYWbwyTzjybR72P4qSBMyZZM,10
|
|
45
|
+
hivetrace-1.3.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|