unique_toolkit 2026.30.0.dev22__py3-none-any.whl → 2026.30.0.dev23__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.
@@ -48,6 +48,9 @@ class Analytics(TypedDict):
48
48
  language_model: AnalyticsLanguageModel
49
49
  loop_iteration_count: int
50
50
  mcp_tool_names_used: list[AnalyticsToolName]
51
+ # Total size of artifacts/files created this turn, in MiB. None when Code
52
+ # Interpreter did not run; 0.0 when it ran but produced nothing.
53
+ output_size: float | None
51
54
  references_count: int
52
55
  skills_used: list[AnalyticsSkill]
53
56
  subagent_names_used: list[AnalyticsToolName]
@@ -129,8 +132,8 @@ class DebugInfoManager:
129
132
  ]
130
133
  # Artifacts are recorded at the postprocessor seam (Code Interpreter's
131
134
  # DisplayCodeInterpreterFilesPostProcessor) into debug_info["artifacts"].
132
- # Absent when no Code Interpreter ran this turn → both fields stay None,
133
- # preserving the always-present, null-when-unknown contract.
135
+ # Absent when no Code Interpreter ran this turn → artifact fields stay
136
+ # None, preserving the always-present, null-when-unknown contract.
134
137
  analytics = Analytics(
135
138
  tools_used=analytics_tools,
136
139
  tool_call_count=len(analytics_tools),
@@ -152,6 +155,7 @@ class DebugInfoManager:
152
155
  total_time_to_answer_ms=total_time_to_answer_ms,
153
156
  artifacts_created_count=artifacts["count"] if artifacts else None,
154
157
  artifacts_created_filetype=artifacts["filetypes"] if artifacts else None,
158
+ output_size=artifacts["output_size"] if artifacts else None,
155
159
  # None when the user-memory postprocessor is not activated for this
156
160
  # turn; True/False when it ran and did/didn't update the profile.
157
161
  context_memory_updated=context_memory_updated,
@@ -46,16 +46,22 @@ from unique_toolkit.short_term_memory.service import ShortTermMemoryService
46
46
  logger = logging.getLogger(__name__)
47
47
 
48
48
 
49
+ _BYTES_PER_MB = 1024 * 1024
50
+
51
+
49
52
  class ArtifactsDebugInfo(TypedDict):
50
53
  """This turn's successfully-created artifacts, for analytics.
51
54
 
52
- Feeds analytics.artifacts_created_count / artifacts_created_filetype. The
53
- postprocessor returns this to the orchestrator, which owns the
54
- ``DebugInfoManager`` and records it.
55
+ Feeds analytics.artifacts_created_count / artifacts_created_filetype /
56
+ output_size. The postprocessor returns this to the orchestrator, which
57
+ owns the ``DebugInfoManager`` and records it.
55
58
  """
56
59
 
57
60
  count: int
58
61
  filetypes: list[str]
62
+ # Total size of this turn's successfully-created artifacts, in MiB
63
+ # (bytes / 1024**2). 0.0 when the interpreter ran but produced nothing.
64
+ output_size: float
59
65
 
60
66
 
61
67
  class _ChatLoggerAdapter(logging.LoggerAdapter[logging.Logger]):
@@ -380,6 +386,9 @@ class DisplayCodeInterpreterFilesPostProcessor(
380
386
  chat_id=chat_id,
381
387
  )
382
388
 
389
+ # Cleared at the start of each run(); holds this-turn download sizes.
390
+ self._file_size_map: dict[str, int] = {}
391
+
383
392
  def _build_retry(self) -> AsyncRetrying:
384
393
  """Build a tenacity retry policy from the current config.
385
394
 
@@ -407,6 +416,10 @@ class DisplayCodeInterpreterFilesPostProcessor(
407
416
  [cf.filename for cf in container_files],
408
417
  )
409
418
 
419
+ # Per-turn byte sizes of successfully uploaded files. Not persisted to
420
+ # short-term memory — only feeds this turn's analytics.output_size.
421
+ self._file_size_map = {}
422
+
410
423
  phase_t0 = time.monotonic()
411
424
  try:
412
425
  self._content_map: dict[str, str | None] = await self._load_previous_files() # pyright: ignore[reportAttributeAccessIssue]
@@ -501,17 +514,19 @@ class DisplayCodeInterpreterFilesPostProcessor(
501
514
  ) -> ArtifactsDebugInfo | None:
502
515
  """Compute this turn's successfully-created artifacts.
503
516
 
504
- Feeds analytics.artifacts_created_count / artifacts_created_filetype.
517
+ Feeds analytics.artifacts_created_count / artifacts_created_filetype /
518
+ output_size.
505
519
 
506
520
  Returns ``None`` when the Code Interpreter did not execute this turn
507
521
  (``code_interpreter_calls`` empty). The postprocessor is registered
508
522
  whenever the tool is *enabled*, so ``run()`` also fires on turns where the
509
523
  model never invoked it — returning ``None`` there keeps analytics.artifacts_*
510
- as null ("did not run") rather than 0/[] ("ran, created nothing"). When it
511
- did run, count is scoped to this response's ``container_files`` (not
512
- ``self._content_map``, which also holds prior-message files from short-term
513
- memory), successful uploads only, with a deduped, sorted set of file
514
- extensions.
524
+ / output_size as null ("did not run") rather than 0/[]/0.0 ("ran, created
525
+ nothing"). When it did run, metrics are scoped to this response's
526
+ ``container_files`` (not ``self._content_map``, which also holds
527
+ prior-message files from short-term memory), successful uploads only, with
528
+ a deduped, sorted set of file extensions and total size in MiB from
529
+ ``self._file_size_map`` (populated at download time).
515
530
  """
516
531
  # Interpreter did not run this turn → leave artifacts null, not 0/[].
517
532
  if not loop_response.code_interpreter_calls:
@@ -522,9 +537,13 @@ class DisplayCodeInterpreterFilesPostProcessor(
522
537
  for cf in loop_response.container_files
523
538
  if self._content_map.get(cf.filename) is not None
524
539
  }
540
+ total_bytes = sum(
541
+ self._file_size_map.get(name, 0) for name in created_filenames
542
+ )
525
543
  return ArtifactsDebugInfo(
526
544
  count=len(created_filenames),
527
545
  filetypes=sorted({_artifact_filetype(name) for name in created_filenames}),
546
+ output_size=total_bytes / _BYTES_PER_MB,
528
547
  )
529
548
 
530
549
  @override
@@ -763,6 +782,9 @@ class DisplayCodeInterpreterFilesPostProcessor(
763
782
  upload_ms,
764
783
  pipeline_ms,
765
784
  )
785
+ # Record size only on successful upload so failed downloads don't
786
+ # inflate analytics.output_size (mirrors content_map success gating).
787
+ self._file_size_map[container_file.filename] = len(file_bytes)
766
788
  return _ContentInfo(filename=container_file.filename, content_id=content.id)
767
789
 
768
790
  async def _download_file_bytes_with_progress(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: unique-toolkit
3
- Version: 2026.30.0.dev22
3
+ Version: 2026.30.0.dev23
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>
@@ -83,7 +83,7 @@ unique_toolkit/_common/utils/write_configuration.py,sha256=fzvr4C-XBL3OSM3Od9Tbq
83
83
  unique_toolkit/_common/validate_required_values.py,sha256=cA8GPwkV1EPsG6ffIkmAn3Dx4LRRMC1EAURmT7PyuCg,551
84
84
  unique_toolkit/_common/validators.py,sha256=ElnkMsyEY24TfzfTVHvireyT39EnZgW5N40T0P4b6gE,2638
85
85
  unique_toolkit/agentic/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
86
- unique_toolkit/agentic/debug_info_manager/debug_info_manager.py,sha256=MoLHxJSK5yYb_MIzQEx0DICPfzHYZi04ofLbVEvcNso,8666
86
+ unique_toolkit/agentic/debug_info_manager/debug_info_manager.py,sha256=qbQp-e9BO-vGLb6IDbYAM8q8xt2iXMRoC5PX-SjlsRk,8920
87
87
  unique_toolkit/agentic/debug_info_manager/test/test_debug_info_manager.py,sha256=bDjrHLqfwtd7ewdIdyTFHabG-15t3iXvs34ywoYXcik,11888
88
88
  unique_toolkit/agentic/evaluation/config.py,sha256=u5-iuT-4mfA2_9UZjZ-TN3YutVf35aR4EsF9l61Odnk,1696
89
89
  unique_toolkit/agentic/evaluation/context_relevancy/prompts/__init__.py,sha256=IKGvHW2viBylTUjEJNKvIXO4YrYwdJXBHSxA9rKtiRI,355
@@ -218,7 +218,7 @@ unique_toolkit/agentic/tools/openai_builtin/code_interpreter/config.py,sha256=C4
218
218
  unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/__init__.py,sha256=SzEiUqxIw8D4_51SvTt-8oTOYTGirYkmH4J6SgojzME,634
219
219
  unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/artifacts.py,sha256=wAgDrcXZbCdDbNWNpbMigBUXySzbKQXSfg3KsZfAWfs,3115
220
220
  unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/code_display.py,sha256=Q4crOkYG-C_uTSc7rW14cP1H4IWxsKpfuftafDHbjEo,2897
221
- unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/generated_files.py,sha256=YZ3AWE97RaGREO3bO6r9c5CYvKeVVvOlIGwwuRvyYuU,61797
221
+ unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/generated_files.py,sha256=OIbaRhjorsNe6LhVJYVvLxxMKwphc6ot13vi58axnnM,62861
222
222
  unique_toolkit/agentic/tools/openai_builtin/code_interpreter/schemas.py,sha256=W7egCmYrPrzic0aXsu9wY5fvQ8y_cl4Tzq_cjVs0mZs,542
223
223
  unique_toolkit/agentic/tools/openai_builtin/code_interpreter/tool/__init__.py,sha256=r6yXmGTLJzXNq5laHOlre9veu--VbCQVlDRVm2QUGzI,326
224
224
  unique_toolkit/agentic/tools/openai_builtin/code_interpreter/tool/config.py,sha256=sbLV-fYt_veBAdonqAHY9sm-eHxpjIZgc1KVbm03pZY,19042
@@ -418,6 +418,6 @@ unique_toolkit/short_term_memory/service.py,sha256=2JMBEBn6GoyK-a0xvdcWpPft-3C74
418
418
  unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
419
419
  unique_toolkit/smart_rules/compile.py,sha256=vRe0aMJWuVIK-VsqomgxQImzke7MDmwgSxxJfYCa7zw,1386
420
420
  unique_toolkit/test_utilities/events.py,sha256=FLrhMh0A_mQutAUjoD0FdMcVQ4Gq31r35OVGzRjvLro,6760
421
- unique_toolkit-2026.30.0.dev22.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
422
- unique_toolkit-2026.30.0.dev22.dist-info/METADATA,sha256=g3QbTNdj0uJ646TdRxg3L2XegUywt3EVUp5vYpGHrCs,7460
423
- unique_toolkit-2026.30.0.dev22.dist-info/RECORD,,
421
+ unique_toolkit-2026.30.0.dev23.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
422
+ unique_toolkit-2026.30.0.dev23.dist-info/METADATA,sha256=utPGYgyaIlzKn9GzqkzYKL5hcp5de76B_N0AoVQSFLc,7460
423
+ unique_toolkit-2026.30.0.dev23.dist-info/RECORD,,