unique_toolkit 2026.30.0.dev12__py3-none-any.whl → 2026.30.0.dev13__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.
@@ -6,7 +6,7 @@ import mimetypes
6
6
  from datetime import datetime
7
7
  from enum import StrEnum
8
8
  from itertools import groupby
9
- from typing import TYPE_CHECKING, Iterator
9
+ from typing import TYPE_CHECKING, Callable, Iterator
10
10
 
11
11
  if TYPE_CHECKING:
12
12
  from unique_toolkit.content.schemas import ContentChunk
@@ -200,9 +200,7 @@ async def download_encoded_images_async(
200
200
  return base64_encoded_images
201
201
 
202
202
 
203
- class FileContentSerialization(StrEnum):
204
- NONE = "none"
205
- FILE_NAME = "file_name"
203
+ FileContentSerializer = Callable[[Content], str | None]
206
204
 
207
205
 
208
206
  class ImageContentInclusion(StrEnum):
@@ -210,23 +208,17 @@ class ImageContentInclusion(StrEnum):
210
208
  ALL = "all"
211
209
 
212
210
 
213
- def file_content_serialization(
211
+ def _serialize_file_contents(
212
+ text: str,
214
213
  file_contents: list[Content],
215
- file_content_serialization: FileContentSerialization,
214
+ file_content_serializer: FileContentSerializer | None,
216
215
  ) -> str:
217
- match file_content_serialization:
218
- case FileContentSerialization.NONE:
219
- return ""
220
- case FileContentSerialization.FILE_NAME:
221
- file_names = [
222
- f"- Uploaded file: {f.key} at {f.created_at}" for f in file_contents
223
- ]
224
- return "\n".join(
225
- [
226
- "Files Uploaded to Chat can be accessed by internal search tool if available:\n",
227
- ]
228
- + file_names,
229
- )
216
+ serialized_files: list[str] = []
217
+ if file_content_serializer is not None:
218
+ for file_content in file_contents:
219
+ if serialized_file := file_content_serializer(file_content):
220
+ serialized_files.append(serialized_file)
221
+ return (text + "\n\n" + "\n".join(serialized_files)).strip()
230
222
 
231
223
 
232
224
  def _append_element_to_builder(
@@ -234,9 +226,9 @@ def _append_element_to_builder(
234
226
  c: ChatMessageWithContents,
235
227
  text: str,
236
228
  include_images: ImageContentInclusion,
237
- file_content_serialization_type: FileContentSerialization,
238
229
  content_service: ContentService,
239
230
  chat_id: str,
231
+ file_content_serializer: FileContentSerializer | None = None,
240
232
  selected_content_ids: set[str] | None = None,
241
233
  ) -> None:
242
234
  if len(c.contents) > 0:
@@ -249,15 +241,12 @@ def _append_element_to_builder(
249
241
  image_contents = [
250
242
  co for co in image_contents if co.id in selected_content_ids
251
243
  ]
252
- content = (
253
- text
254
- + "\n\n"
255
- + file_content_serialization(
256
- file_contents,
257
- file_content_serialization_type,
258
- )
259
- ).strip()
260
- if include_images and len(image_contents) > 0:
244
+ content = _serialize_file_contents(
245
+ text,
246
+ file_contents,
247
+ file_content_serializer,
248
+ )
249
+ if include_images and image_contents:
261
250
  builder.image_message_append(
262
251
  content=content,
263
252
  images=download_encoded_images(
@@ -285,9 +274,9 @@ async def _append_element_to_builder_async(
285
274
  c: ChatMessageWithContents,
286
275
  text: str,
287
276
  include_images: ImageContentInclusion,
288
- file_content_serialization_type: FileContentSerialization,
289
277
  content_service: ContentService,
290
278
  chat_id: str,
279
+ file_content_serializer: FileContentSerializer | None = None,
291
280
  selected_content_ids: set[str] | None = None,
292
281
  ) -> None:
293
282
  if len(c.contents) > 0:
@@ -300,15 +289,12 @@ async def _append_element_to_builder_async(
300
289
  image_contents = [
301
290
  co for co in image_contents if co.id in selected_content_ids
302
291
  ]
303
- content = (
304
- text
305
- + "\n\n"
306
- + file_content_serialization(
307
- file_contents,
308
- file_content_serialization_type,
309
- )
310
- ).strip()
311
- if include_images and len(image_contents) > 0:
292
+ content = _serialize_file_contents(
293
+ text,
294
+ file_contents,
295
+ file_content_serializer,
296
+ )
297
+ if include_images and image_contents:
312
298
  builder.image_message_append(
313
299
  content=content,
314
300
  images=await download_encoded_images_async(
@@ -336,7 +322,7 @@ def get_full_history_with_contents(
336
322
  chat_service: ChatService,
337
323
  content_service: ContentService,
338
324
  include_images: ImageContentInclusion = ImageContentInclusion.ALL,
339
- file_content_serialization_type: FileContentSerialization = FileContentSerialization.FILE_NAME,
325
+ file_content_serializer: FileContentSerializer | None = None,
340
326
  selected_content_ids: set[str] | None = None,
341
327
  ) -> LanguageModelMessages:
342
328
  grouped_elements = get_chat_history_with_contents(
@@ -361,7 +347,7 @@ def get_full_history_with_contents(
361
347
  c=c,
362
348
  text=text,
363
349
  include_images=include_images,
364
- file_content_serialization_type=file_content_serialization_type,
350
+ file_content_serializer=file_content_serializer,
365
351
  content_service=content_service,
366
352
  chat_id=chat_id,
367
353
  selected_content_ids=selected_content_ids,
@@ -376,7 +362,7 @@ async def get_full_history_with_contents_async(
376
362
  chat_service: ChatService,
377
363
  content_service: ContentService,
378
364
  include_images: ImageContentInclusion = ImageContentInclusion.ALL,
379
- file_content_serialization_type: FileContentSerialization = FileContentSerialization.FILE_NAME,
365
+ file_content_serializer: FileContentSerializer | None = None,
380
366
  selected_content_ids: set[str] | None = None,
381
367
  ) -> LanguageModelMessages:
382
368
  grouped_elements = await get_chat_history_with_contents_async(
@@ -400,7 +386,7 @@ async def get_full_history_with_contents_async(
400
386
  c=c,
401
387
  text=text,
402
388
  include_images=include_images,
403
- file_content_serialization_type=file_content_serialization_type,
389
+ file_content_serializer=file_content_serializer,
404
390
  content_service=content_service,
405
391
  chat_id=chat_id,
406
392
  selected_content_ids=selected_content_ids,
@@ -415,7 +401,7 @@ def get_full_history_with_contents_and_tool_calls(
415
401
  chat_service: ChatService,
416
402
  content_service: ContentService,
417
403
  include_images: ImageContentInclusion = ImageContentInclusion.ALL,
418
- file_content_serialization_type: FileContentSerialization = FileContentSerialization.FILE_NAME,
404
+ file_content_serializer: FileContentSerializer | None = None,
419
405
  selected_content_ids: set[str] | None = None,
420
406
  ) -> tuple[LanguageModelMessages, int, dict[int, "ContentChunk"]]:
421
407
  """Build the full LLM message history, including persisted tool call rounds.
@@ -544,7 +530,7 @@ def get_full_history_with_contents_and_tool_calls(
544
530
  c=c,
545
531
  text=text,
546
532
  include_images=include_images,
547
- file_content_serialization_type=file_content_serialization_type,
533
+ file_content_serializer=file_content_serializer,
548
534
  content_service=content_service,
549
535
  chat_id=chat_id,
550
536
  selected_content_ids=selected_content_ids,
@@ -559,7 +545,7 @@ async def get_full_history_with_contents_and_tool_calls_async(
559
545
  chat_service: ChatService,
560
546
  content_service: ContentService,
561
547
  include_images: ImageContentInclusion = ImageContentInclusion.ALL,
562
- file_content_serialization_type: FileContentSerialization = FileContentSerialization.FILE_NAME,
548
+ file_content_serializer: FileContentSerializer | None = None,
563
549
  selected_content_ids: set[str] | None = None,
564
550
  ) -> tuple[LanguageModelMessages, int, dict[int, "ContentChunk"]]:
565
551
  """Async version of get_full_history_with_contents_and_tool_calls."""
@@ -662,7 +648,7 @@ async def get_full_history_with_contents_and_tool_calls_async(
662
648
  c=c,
663
649
  text=text,
664
650
  include_images=include_images,
665
- file_content_serialization_type=file_content_serialization_type,
651
+ file_content_serializer=file_content_serializer,
666
652
  content_service=content_service,
667
653
  chat_id=chat_id,
668
654
  selected_content_ids=selected_content_ids,
@@ -10,6 +10,9 @@ from unique_toolkit._common.feature_flags.schema import (
10
10
  )
11
11
  from unique_toolkit._common.pydantic_helpers import DeactivatedNone
12
12
  from unique_toolkit._common.validators import LMI
13
+ from unique_toolkit.agentic.history_manager.history_construction_with_contents import (
14
+ FileContentSerializer,
15
+ )
13
16
  from unique_toolkit.agentic.history_manager.loop_token_reducer import LoopTokenReducer
14
17
  from unique_toolkit.agentic.history_manager.utils import (
15
18
  serialize_tool_content_json,
@@ -115,6 +118,7 @@ class HistoryManager:
115
118
  config: HistoryManagerConfig,
116
119
  language_model: LMI,
117
120
  reference_manager: ReferenceManager,
121
+ file_content_serializer: FileContentSerializer | None = None,
118
122
  ):
119
123
  self._config = config
120
124
  self._logger = logger
@@ -123,10 +127,10 @@ class HistoryManager:
123
127
  logger=self._logger,
124
128
  event=event,
125
129
  max_history_tokens=self._config.max_history_tokens,
126
- has_uploaded_content_config=bool(self._config.uploaded_content_config),
127
130
  language_model=self._language_model,
128
131
  reference_manager=reference_manager,
129
132
  enable_tool_call_persistence=self._config.enable_tool_call_persistence,
133
+ file_content_serializer=file_content_serializer,
130
134
  )
131
135
  self._reference_manager = reference_manager
132
136
  self._tool_call_result_history: list[ToolCallResponse] = []
@@ -9,7 +9,7 @@ from unique_toolkit._common.token.token_counting import (
9
9
  )
10
10
  from unique_toolkit._common.validators import LMI
11
11
  from unique_toolkit.agentic.history_manager.history_construction_with_contents import (
12
- FileContentSerialization,
12
+ FileContentSerializer,
13
13
  get_full_history_with_contents_and_tool_calls_async,
14
14
  get_full_history_with_contents_async,
15
15
  )
@@ -54,13 +54,13 @@ class LoopTokenReducer:
54
54
  logger: Logger,
55
55
  event: ChatEvent,
56
56
  max_history_tokens: int,
57
- has_uploaded_content_config: bool,
58
57
  reference_manager: ReferenceManager,
59
58
  language_model: LMI,
60
59
  enable_tool_call_persistence: bool = False,
60
+ file_content_serializer: FileContentSerializer | None = None,
61
61
  ):
62
62
  self._max_history_tokens = max_history_tokens
63
- self._has_uploaded_content_config = has_uploaded_content_config
63
+ self._file_content_serializer = file_content_serializer
64
64
  self._logger = logger
65
65
  self._reference_manager = reference_manager
66
66
  self._language_model = language_model
@@ -309,11 +309,6 @@ class LoopTokenReducer:
309
309
  Returns:
310
310
  list[LanguageModelMessage]: The history
311
311
  """
312
- file_content_serialization_type = (
313
- FileContentSerialization.NONE
314
- if self._has_uploaded_content_config
315
- else FileContentSerialization.FILE_NAME
316
- )
317
312
  if self._enable_tool_call_persistence:
318
313
  (
319
314
  full_history,
@@ -324,7 +319,7 @@ class LoopTokenReducer:
324
319
  chat_id=self._chat_id,
325
320
  chat_service=self._chat_service,
326
321
  content_service=self._content_service,
327
- file_content_serialization_type=file_content_serialization_type,
322
+ file_content_serializer=self._file_content_serializer,
328
323
  selected_content_ids=self._selected_content_ids,
329
324
  )
330
325
  self._max_db_source_number = max_src
@@ -335,7 +330,7 @@ class LoopTokenReducer:
335
330
  chat_id=self._chat_id,
336
331
  chat_service=self._chat_service,
337
332
  content_service=self._content_service,
338
- file_content_serialization_type=file_content_serialization_type,
333
+ file_content_serializer=self._file_content_serializer,
339
334
  selected_content_ids=self._selected_content_ids,
340
335
  )
341
336
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: unique-toolkit
3
- Version: 2026.30.0.dev12
3
+ Version: 2026.30.0.dev13
4
4
  Summary:
5
5
  Author: Cedric Klinkert, Martin Fadler, Sadique Sheik, Fabian Schläpfer, Pascal Hauri, Ejiroghene Oki-Peter, Rami Azouz, Ricardo Visini, Sanzio Monti
6
6
  Author-email: Cedric Klinkert <cedric.klinkert@unique.ch>, Martin Fadler <martin.fadler@unique.ch>, Sadique Sheik <sadique@unique.ch>, Fabian Schläpfer <fabian@unique.ch>, Pascal Hauri <pascal@unique.ch>, Ejiroghene Oki-Peter <oki-peter.ejiroghene@unique.ai>, Rami Azouz <rami.ext@unique.ch>, Ricardo Visini <ricardo.visini@unique.ch>, Sanzio Monti <sanzio.monti@unique.ai>
@@ -113,9 +113,9 @@ unique_toolkit/agentic/evaluation/tests/test_prompt_loaders.py,sha256=zBREdlKf5t
113
113
  unique_toolkit/agentic/evaluation/utils.py,sha256=HmyPaDV8wdW-_gOjjW-wDaMKgdrsP5-SHP7OqTmGI_A,264
114
114
  unique_toolkit/agentic/feature_flags/__init__.py,sha256=LhE2cHoa9AYBOR7TjiIToOn46sttm9paKcrzE7gnDPM,149
115
115
  unique_toolkit/agentic/feature_flags/feature_flags.py,sha256=ul9-StpKO-4Kzq0GxTR4UlM-fRQsOD4BGr5aNmAiyBo,5315
116
- unique_toolkit/agentic/history_manager/history_construction_with_contents.py,sha256=yqaG_tqyijgW6DEpfulg1zKtzQLewgWEegWnvZvE4P4,25849
117
- unique_toolkit/agentic/history_manager/history_manager.py,sha256=1W9908BoKzBRwxaLx_AVQE4QsMHj4mq3rdeNunTpHfY,15739
118
- unique_toolkit/agentic/history_manager/loop_token_reducer.py,sha256=egXlsiN6QxoWM3R4DAjsuhSap7RU3DqBJeDGfw9Ndc0,26846
116
+ unique_toolkit/agentic/history_manager/history_construction_with_contents.py,sha256=70lm8pYmQpb0HRpqzPTb4ikh8vVbvhfGR5S-D4Ftbbc,25306
117
+ unique_toolkit/agentic/history_manager/history_manager.py,sha256=RIVeQxlCq25JwUY6WWQzz5zoOCouAK7shbxUztpgZPs,15903
118
+ unique_toolkit/agentic/history_manager/loop_token_reducer.py,sha256=v9K4TbEVK9HBLgbvax9KZmAqkCkowk6v391AJeZdVts,26645
119
119
  unique_toolkit/agentic/history_manager/settings.py,sha256=Lrx3a8yXeU0MXrWlV6RZSHsgYWF9Zrs8LyR96OpqQ_k,1216
120
120
  unique_toolkit/agentic/history_manager/utils.py,sha256=hYgaahQq9gKm7V2Q5qnyZtqw5opO-MKH7wTGq9-iEgE,6455
121
121
  unique_toolkit/agentic/loop_runner/__init__.py,sha256=KPZLJ9fCzR9mwnvAgrA_dPsDJlcQS8o0r0amNdmBljY,1352
@@ -407,6 +407,6 @@ unique_toolkit/short_term_memory/service.py,sha256=2JMBEBn6GoyK-a0xvdcWpPft-3C74
407
407
  unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
408
408
  unique_toolkit/smart_rules/compile.py,sha256=vRe0aMJWuVIK-VsqomgxQImzke7MDmwgSxxJfYCa7zw,1386
409
409
  unique_toolkit/test_utilities/events.py,sha256=FLrhMh0A_mQutAUjoD0FdMcVQ4Gq31r35OVGzRjvLro,6760
410
- unique_toolkit-2026.30.0.dev12.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
411
- unique_toolkit-2026.30.0.dev12.dist-info/METADATA,sha256=XpaKCUPzzdREkJVfO1q4QF-G5BBdQkh2DG8_NTupKGY,7460
412
- unique_toolkit-2026.30.0.dev12.dist-info/RECORD,,
410
+ unique_toolkit-2026.30.0.dev13.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
411
+ unique_toolkit-2026.30.0.dev13.dist-info/METADATA,sha256=ySP5zJPYH87Q1z_K649-D8vyfa7Xg1lma3hVMblb4qg,7460
412
+ unique_toolkit-2026.30.0.dev13.dist-info/RECORD,,