unique_toolkit 1.33.2__py3-none-any.whl → 1.34.0__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.
- unique_toolkit/agentic/responses_api/postprocessors/generated_files.py +30 -9
- unique_toolkit/agentic/tools/config.py +5 -45
- unique_toolkit/services/chat_service.py +25 -0
- {unique_toolkit-1.33.2.dist-info → unique_toolkit-1.34.0.dist-info}/METADATA +7 -1
- {unique_toolkit-1.33.2.dist-info → unique_toolkit-1.34.0.dist-info}/RECORD +7 -7
- {unique_toolkit-1.33.2.dist-info → unique_toolkit-1.34.0.dist-info}/LICENSE +0 -0
- {unique_toolkit-1.33.2.dist-info → unique_toolkit-1.34.0.dist-info}/WHEEL +0 -0
|
@@ -8,6 +8,7 @@ from openai import AsyncOpenAI
|
|
|
8
8
|
from openai.types.responses.response_output_text import AnnotationContainerFileCitation
|
|
9
9
|
from pydantic import BaseModel, Field, RootModel
|
|
10
10
|
|
|
11
|
+
from unique_toolkit import ChatService
|
|
11
12
|
from unique_toolkit.agentic.postprocessor.postprocessor_manager import (
|
|
12
13
|
ResponsesApiPostprocessor,
|
|
13
14
|
)
|
|
@@ -27,9 +28,13 @@ logger = logging.getLogger(__name__)
|
|
|
27
28
|
|
|
28
29
|
class DisplayCodeInterpreterFilesPostProcessorConfig(BaseModel):
|
|
29
30
|
model_config = get_configuration_dict()
|
|
31
|
+
upload_to_chat: bool = Field(
|
|
32
|
+
default=False,
|
|
33
|
+
description="Whether to upload the generated files to the chat.",
|
|
34
|
+
)
|
|
30
35
|
upload_scope_id: str = Field(
|
|
31
36
|
default="<SCOPE_ID_PLACEHOLDER>",
|
|
32
|
-
description="The scope ID where the generated files will be uploaded.",
|
|
37
|
+
description="The scope ID where the generated files will be uploaded. Ignored if `uploadToChat` is set.",
|
|
33
38
|
)
|
|
34
39
|
|
|
35
40
|
file_download_failed_message: str = Field(
|
|
@@ -75,6 +80,7 @@ class DisplayCodeInterpreterFilesPostProcessor(
|
|
|
75
80
|
client: AsyncOpenAI,
|
|
76
81
|
content_service: ContentService | KnowledgeBaseService,
|
|
77
82
|
config: DisplayCodeInterpreterFilesPostProcessorConfig,
|
|
83
|
+
chat_service: ChatService | None = None,
|
|
78
84
|
# Short term memory arguments, we prefer to explicitely pass the required auth variables
|
|
79
85
|
# as it is crucial that we use chat-level short term memory not to leak user files to other chats.
|
|
80
86
|
# Technically, short term memory can be scoped company-level, we would like to ensure this case is avoided.
|
|
@@ -83,9 +89,14 @@ class DisplayCodeInterpreterFilesPostProcessor(
|
|
|
83
89
|
chat_id: str | None = None,
|
|
84
90
|
) -> None:
|
|
85
91
|
super().__init__(self.__class__.__name__)
|
|
92
|
+
|
|
86
93
|
self._content_service = content_service
|
|
87
|
-
self.
|
|
94
|
+
self._chat_service = chat_service
|
|
88
95
|
self._client = client
|
|
96
|
+
self._config = config
|
|
97
|
+
|
|
98
|
+
if self._config.upload_to_chat and self._chat_service is None:
|
|
99
|
+
raise ValueError("ChatService is required if uploadToChat is True")
|
|
89
100
|
|
|
90
101
|
self._short_term_memory_manager = None
|
|
91
102
|
if chat_id is not None and user_id is not None and company_id is not None:
|
|
@@ -199,13 +210,23 @@ class DisplayCodeInterpreterFilesPostProcessor(
|
|
|
199
210
|
"Uploading file content for %s to knowledge base",
|
|
200
211
|
container_file.filename,
|
|
201
212
|
)
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
213
|
+
|
|
214
|
+
if self._config.upload_to_chat:
|
|
215
|
+
assert self._chat_service is not None # Checked in __init__
|
|
216
|
+
content = await self._chat_service.upload_to_chat_from_bytes_async(
|
|
217
|
+
content=file_content.content,
|
|
218
|
+
content_name=container_file.filename,
|
|
219
|
+
mime_type=guess_type(container_file.filename)[0] or "text/plain",
|
|
220
|
+
skip_ingestion=True,
|
|
221
|
+
)
|
|
222
|
+
else:
|
|
223
|
+
content = await self._content_service.upload_content_from_bytes_async(
|
|
224
|
+
content=file_content.content,
|
|
225
|
+
content_name=container_file.filename,
|
|
226
|
+
mime_type=guess_type(container_file.filename)[0] or "text/plain",
|
|
227
|
+
scope_id=self._config.upload_scope_id,
|
|
228
|
+
skip_ingestion=True,
|
|
229
|
+
)
|
|
209
230
|
|
|
210
231
|
return _ContentInfo(filename=container_file.filename, content_id=content.id)
|
|
211
232
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import json
|
|
2
1
|
from enum import StrEnum
|
|
3
|
-
from typing import Annotated, Any
|
|
2
|
+
from typing import Annotated, Any
|
|
4
3
|
|
|
5
4
|
from pydantic import (
|
|
6
5
|
BaseModel,
|
|
7
6
|
BeforeValidator,
|
|
8
7
|
Field,
|
|
9
8
|
ValidationInfo,
|
|
9
|
+
field_serializer,
|
|
10
10
|
model_validator,
|
|
11
11
|
)
|
|
12
12
|
|
|
@@ -123,46 +123,6 @@ class ToolBuildConfig(BaseModel):
|
|
|
123
123
|
value["configuration"] = config
|
|
124
124
|
return value
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
subclass fields from `configuration` by delegating to its own
|
|
130
|
-
model_dump. This prevents `{}` when `configuration` is typed
|
|
131
|
-
as `BaseToolConfig` but holds a subclass instance.
|
|
132
|
-
"""
|
|
133
|
-
data: Dict[str, Any] = {
|
|
134
|
-
"name": self.name,
|
|
135
|
-
"configuration": self.configuration.model_dump()
|
|
136
|
-
if self.configuration
|
|
137
|
-
else None,
|
|
138
|
-
"display_name": self.display_name,
|
|
139
|
-
"icon": self.icon,
|
|
140
|
-
"selection_policy": self.selection_policy,
|
|
141
|
-
"is_exclusive": self.is_exclusive,
|
|
142
|
-
"is_sub_agent": self.is_sub_agent,
|
|
143
|
-
"is_enabled": self.is_enabled,
|
|
144
|
-
}
|
|
145
|
-
return data
|
|
146
|
-
|
|
147
|
-
def model_dump_json(self) -> str:
|
|
148
|
-
"""
|
|
149
|
-
Returns a JSON string representation of the tool config.
|
|
150
|
-
Ensures `configuration` is fully serialized by using the
|
|
151
|
-
subclass's `model_dump_json()` when available.
|
|
152
|
-
"""
|
|
153
|
-
config_json = (
|
|
154
|
-
self.configuration.model_dump_json() if self.configuration else None
|
|
155
|
-
)
|
|
156
|
-
config = json.loads(config_json) if config_json else None
|
|
157
|
-
|
|
158
|
-
data: Dict[str, Any] = {
|
|
159
|
-
"name": self.name,
|
|
160
|
-
"configuration": config,
|
|
161
|
-
"display_name": self.display_name,
|
|
162
|
-
"icon": self.icon,
|
|
163
|
-
"selection_policy": self.selection_policy,
|
|
164
|
-
"is_exclusive": self.is_exclusive,
|
|
165
|
-
"is_sub_agent": self.is_sub_agent,
|
|
166
|
-
"is_enabled": self.is_enabled,
|
|
167
|
-
}
|
|
168
|
-
return json.dumps(data)
|
|
126
|
+
@field_serializer("configuration")
|
|
127
|
+
def serialize_config(self, value: BaseToolConfig) -> dict[str, Any]:
|
|
128
|
+
return value.__class__.model_dump(value)
|
|
@@ -70,6 +70,7 @@ from unique_toolkit.content.functions import (
|
|
|
70
70
|
download_content_to_bytes,
|
|
71
71
|
search_contents,
|
|
72
72
|
upload_content_from_bytes,
|
|
73
|
+
upload_content_from_bytes_async,
|
|
73
74
|
)
|
|
74
75
|
from unique_toolkit.content.schemas import (
|
|
75
76
|
Content,
|
|
@@ -1607,6 +1608,30 @@ class ChatService(ChatServiceDeprecated):
|
|
|
1607
1608
|
metadata=metadata,
|
|
1608
1609
|
)
|
|
1609
1610
|
|
|
1611
|
+
async def upload_to_chat_from_bytes_async(
|
|
1612
|
+
self,
|
|
1613
|
+
*,
|
|
1614
|
+
content: bytes,
|
|
1615
|
+
content_name: str,
|
|
1616
|
+
mime_type: str,
|
|
1617
|
+
scope_id: str | None = None,
|
|
1618
|
+
skip_ingestion: bool = False,
|
|
1619
|
+
ingestion_config: unique_sdk.Content.IngestionConfig | None = None,
|
|
1620
|
+
metadata: dict[str, Any] | None = None,
|
|
1621
|
+
) -> Content:
|
|
1622
|
+
return await upload_content_from_bytes_async(
|
|
1623
|
+
user_id=self._user_id,
|
|
1624
|
+
company_id=self._company_id,
|
|
1625
|
+
content=content,
|
|
1626
|
+
content_name=content_name,
|
|
1627
|
+
mime_type=mime_type,
|
|
1628
|
+
scope_id=scope_id,
|
|
1629
|
+
chat_id=self._chat_id,
|
|
1630
|
+
skip_ingestion=skip_ingestion,
|
|
1631
|
+
ingestion_config=ingestion_config,
|
|
1632
|
+
metadata=metadata,
|
|
1633
|
+
)
|
|
1634
|
+
|
|
1610
1635
|
def download_chat_content_to_bytes(self, *, content_id: str) -> bytes:
|
|
1611
1636
|
return download_content_to_bytes(
|
|
1612
1637
|
user_id=self._user_id,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: unique_toolkit
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.34.0
|
|
4
4
|
Summary:
|
|
5
5
|
License: Proprietary
|
|
6
6
|
Author: Cedric Klinkert
|
|
@@ -121,6 +121,12 @@ All notable changes to this project will be documented in this file.
|
|
|
121
121
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
122
122
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
123
123
|
|
|
124
|
+
## [1.34.0] - 2025-12-02
|
|
125
|
+
- Add option to upload code interpreter generated files to the chat.
|
|
126
|
+
|
|
127
|
+
## [1.33.3] - 2025-12-02
|
|
128
|
+
- Fix serialization of ToolBuildConfig `configuration` field.
|
|
129
|
+
|
|
124
130
|
## [1.33.2] - 2025-12-01
|
|
125
131
|
- Upgrade numpy to >2.1.0 to ensure compatibility with langchain library
|
|
126
132
|
|
|
@@ -68,7 +68,7 @@ unique_toolkit/agentic/postprocessor/postprocessor_manager.py,sha256=s6HFhA61TE0
|
|
|
68
68
|
unique_toolkit/agentic/reference_manager/reference_manager.py,sha256=x51CT0D8HHu2LzgXdHGy0leOYpjnsxVbPZ2nc28G9mA,4005
|
|
69
69
|
unique_toolkit/agentic/responses_api/__init__.py,sha256=9WTO-ef7fGE9Y1QtZJFm8Q_jkwK8Srtl-HWvpAD2Wxs,668
|
|
70
70
|
unique_toolkit/agentic/responses_api/postprocessors/code_display.py,sha256=h6ZqPR0kPQnxM0ynshYQTa1BrcN8XGbUz9p03m8rOj0,2339
|
|
71
|
-
unique_toolkit/agentic/responses_api/postprocessors/generated_files.py,sha256=
|
|
71
|
+
unique_toolkit/agentic/responses_api/postprocessors/generated_files.py,sha256=ZdxJQQlD5K2Arn_NJVQNzIUwp-q5SmIE17o-UquTa0A,11691
|
|
72
72
|
unique_toolkit/agentic/responses_api/stream_handler.py,sha256=Y1IM0uiPBdlab5UuOTCsHTaVX-fd9MxfS3xkwhdFie4,647
|
|
73
73
|
unique_toolkit/agentic/short_term_memory_manager/persistent_short_term_memory_manager.py,sha256=uF3HSoZF0hBfuNhIE9N8KRtuwDfpoeXUFVrv_cyZ3Sw,5839
|
|
74
74
|
unique_toolkit/agentic/thinking_manager/thinking_manager.py,sha256=41QWFsdRrbWlQHBfYCFv726UDom4WbcvaRfjCmoUOQI,4183
|
|
@@ -99,7 +99,7 @@ unique_toolkit/agentic/tools/a2a/tool/_schema.py,sha256=wMwyunViTnxaURvenkATEvyf
|
|
|
99
99
|
unique_toolkit/agentic/tools/a2a/tool/config.py,sha256=zK9onAMYlYrPc0MCz0gBocd22jm0H5ar1ihNJ7CyjJU,5780
|
|
100
100
|
unique_toolkit/agentic/tools/a2a/tool/service.py,sha256=OJx1zc1roPgt4aa1fDw4XTF9VOCCF72dhEJaNMEMOSU,13865
|
|
101
101
|
unique_toolkit/agentic/tools/agent_chunks_hanlder.py,sha256=x32Dp1Z8cVW5i-XzXbaMwX2KHPcNGmqEU-FB4AV9ZGo,1909
|
|
102
|
-
unique_toolkit/agentic/tools/config.py,sha256=
|
|
102
|
+
unique_toolkit/agentic/tools/config.py,sha256=71PSq8LoR80irk2iJfy_AgXOPi4Nh3luW5z5cDvY8i0,3920
|
|
103
103
|
unique_toolkit/agentic/tools/factory.py,sha256=A1Aliwx037UAk9ADiDsg0zjCWWnvzV_PxwJNoPTvW6c,1434
|
|
104
104
|
unique_toolkit/agentic/tools/mcp/__init__.py,sha256=RLF_p-LDRC7GhiB3fdCi4u3bh6V9PY_w26fg61BLyco,122
|
|
105
105
|
unique_toolkit/agentic/tools/mcp/manager.py,sha256=DPYwwDe6RSZyuPaxn-je49fP_qOOs0ZV46EM6GZcV4c,2748
|
|
@@ -189,7 +189,7 @@ unique_toolkit/language_model/service.py,sha256=rt5LoQnDifIa5TnykGkJNl03lj0QhCMd
|
|
|
189
189
|
unique_toolkit/language_model/utils.py,sha256=bPQ4l6_YO71w-zaIPanUUmtbXC1_hCvLK0tAFc3VCRc,1902
|
|
190
190
|
unique_toolkit/protocols/support.py,sha256=ZEnbQL5w2-T_1AeM8OHycZJ3qbdfVI1nXe0nL9esQEw,5544
|
|
191
191
|
unique_toolkit/services/__init__.py,sha256=90-IT5FjMcnlqxjp5kme9Fqgp_on46rggctIqHMdqsw,195
|
|
192
|
-
unique_toolkit/services/chat_service.py,sha256=
|
|
192
|
+
unique_toolkit/services/chat_service.py,sha256=tHFmpbDiooYIvM5vZePsnwHdYUEcIBeD3db4lcsMJ_s,60941
|
|
193
193
|
unique_toolkit/services/knowledge_base.py,sha256=uc89GL_NZXeFkJKkdHSSh2y1Wx0tmgasWk6uyGi4G_M,36210
|
|
194
194
|
unique_toolkit/short_term_memory/__init__.py,sha256=2mI3AUrffgH7Yt-xS57EGqnHf7jnn6xquoKEhJqk3Wg,185
|
|
195
195
|
unique_toolkit/short_term_memory/constants.py,sha256=698CL6-wjup2MvU19RxSmQk3gX7aqW_OOpZB7sbz_Xg,34
|
|
@@ -199,7 +199,7 @@ unique_toolkit/short_term_memory/service.py,sha256=5PeVBu1ZCAfyDb2HLVvlmqSbyzBBu
|
|
|
199
199
|
unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
200
200
|
unique_toolkit/smart_rules/compile.py,sha256=Ozhh70qCn2yOzRWr9d8WmJeTo7AQurwd3tStgBMPFLA,1246
|
|
201
201
|
unique_toolkit/test_utilities/events.py,sha256=_mwV2bs5iLjxS1ynDCjaIq-gjjKhXYCK-iy3dRfvO3g,6410
|
|
202
|
-
unique_toolkit-1.
|
|
203
|
-
unique_toolkit-1.
|
|
204
|
-
unique_toolkit-1.
|
|
205
|
-
unique_toolkit-1.
|
|
202
|
+
unique_toolkit-1.34.0.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
|
|
203
|
+
unique_toolkit-1.34.0.dist-info/METADATA,sha256=DNDLgni0ur55-wGblbTjZqzJpFMKfx_IsWIfwWD5Lvk,45523
|
|
204
|
+
unique_toolkit-1.34.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
205
|
+
unique_toolkit-1.34.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|