unique_toolkit 1.33.3__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.
@@ -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._config = config
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
- content = await self._content_service.upload_content_from_bytes_async(
203
- content=file_content.content,
204
- content_name=container_file.filename,
205
- skip_ingestion=True,
206
- mime_type=guess_type(container_file.filename)[0] or "text/plain",
207
- scope_id=self._config.upload_scope_id,
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
 
@@ -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.33.3
3
+ Version: 1.34.0
4
4
  Summary:
5
5
  License: Proprietary
6
6
  Author: Cedric Klinkert
@@ -121,6 +121,9 @@ 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
+
124
127
  ## [1.33.3] - 2025-12-02
125
128
  - Fix serialization of ToolBuildConfig `configuration` field.
126
129
 
@@ -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=9KfuLdhRvsW4K7dO6Q1fkdpyzKUqmMbIwVCO5eu3fDw,10732
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
@@ -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=vA97DO4iiXMeTNuwS-bYeskX0DnqO_8vL4yzJAfsGtw,60111
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.33.3.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
203
- unique_toolkit-1.33.3.dist-info/METADATA,sha256=X_ddHgP_CSpLGtfeB9_wRZ-ZO6ESULNu_oRPRj2Xpog,45428
204
- unique_toolkit-1.33.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
205
- unique_toolkit-1.33.3.dist-info/RECORD,,
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,,