unique_toolkit 1.18.0__py3-none-any.whl → 1.18.1__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.

Potentially problematic release.


This version of unique_toolkit might be problematic. Click here for more details.

@@ -95,17 +95,29 @@ class SubAgentResponsesPostprocessor(Postprocessor):
95
95
  "Main agent message is not set, the `run` method must be called first"
96
96
  )
97
97
 
98
+ _add_sub_agent_references_in_place(
99
+ loop_response=loop_response,
100
+ sub_agent_infos=list(self._assistant_id_to_tool_info.values()),
101
+ )
102
+
98
103
  existing_refs = {
99
104
  ref.source_id: ref.sequence_number
100
105
  for ref in loop_response.message.references
101
106
  }
102
107
 
108
+ displayed_sub_agent_infos = dict(
109
+ (assistant_id, sub_agent_info)
110
+ for assistant_id, sub_agent_info in self._assistant_id_to_tool_info.items()
111
+ if sub_agent_info["display_config"].mode
112
+ != SubAgentResponseDisplayMode.HIDDEN
113
+ )
114
+
103
115
  _consolidate_references_in_place(
104
- list(self._assistant_id_to_tool_info.values()), existing_refs, loop_response
116
+ list(displayed_sub_agent_infos.values()), existing_refs
105
117
  )
106
118
 
107
119
  answers = []
108
- for assistant_id in self._assistant_id_to_tool_info.keys():
120
+ for assistant_id in displayed_sub_agent_infos.keys():
109
121
  messages = self._assistant_id_to_tool_info[assistant_id]["responses"]
110
122
 
111
123
  for sequence_number in sorted(messages):
@@ -140,9 +152,12 @@ class SubAgentResponsesPostprocessor(Postprocessor):
140
152
  for ref in message["references"]
141
153
  )
142
154
 
143
- loop_response.message.text = (
144
- "<br>\n\n".join(answers) + "<br>\n\n" + loop_response.message.text.strip()
145
- )
155
+ if len(answers) > 0:
156
+ loop_response.message.text = (
157
+ "<br>\n\n".join(answers)
158
+ + "<br>\n\n"
159
+ + loop_response.message.text.strip()
160
+ )
146
161
 
147
162
  return True
148
163
 
@@ -163,13 +178,6 @@ class SubAgentResponsesPostprocessor(Postprocessor):
163
178
  def register_sub_agent_tool(
164
179
  self, tool: SubAgentTool, display_config: SubAgentDisplayConfig
165
180
  ) -> None:
166
- if display_config.mode == SubAgentResponseDisplayMode.HIDDEN:
167
- logger.info(
168
- "Sub agent tool %s has display mode `hidden`, responses will be ignored.",
169
- tool.config.assistant_id,
170
- )
171
- return
172
-
173
181
  if tool.config.assistant_id not in self._assistant_id_to_tool_info:
174
182
  tool.subscribe(self)
175
183
  self._assistant_id_to_tool_info[tool.config.assistant_id] = (
@@ -216,10 +224,73 @@ class SubAgentResponsesPostprocessor(Postprocessor):
216
224
  }
217
225
 
218
226
 
227
+ def _add_sub_agent_references_in_place(
228
+ loop_response: LanguageModelStreamResponse,
229
+ sub_agent_infos: list[_SubAgentToolInfo],
230
+ ) -> None:
231
+ message_text = loop_response.message.text
232
+
233
+ existing_refs = {
234
+ ref.source_id: ref.sequence_number
235
+ for ref in loop_response.message.references or []
236
+ }
237
+ start_index = max(existing_refs.values(), default=0) + 1
238
+
239
+ for sub_agent_info in sub_agent_infos:
240
+ sub_agent_name = sub_agent_info["name"]
241
+ for sequence_number in sorted(sub_agent_info["responses"]):
242
+ sub_agent_response = sub_agent_info["responses"][sequence_number]
243
+
244
+ for reference in sorted(
245
+ sub_agent_response["references"], key=lambda r: r["sequenceNumber"]
246
+ ):
247
+ ref_num = reference["sequenceNumber"]
248
+ source_id = reference["sourceId"]
249
+
250
+ reference_str = SubAgentTool.get_sub_agent_reference_format(
251
+ name=sub_agent_name,
252
+ sequence_number=sequence_number,
253
+ reference_number=ref_num,
254
+ )
255
+
256
+ if reference_str not in message_text:
257
+ # Reference not used
258
+ continue
259
+
260
+ if source_id in existing_refs:
261
+ new_ref_num = existing_refs[source_id]
262
+
263
+ else:
264
+ new_ref_num = start_index
265
+ existing_refs[source_id] = new_ref_num
266
+ start_index += 1
267
+
268
+ loop_response.message.references.append(
269
+ ContentReference(
270
+ name=reference["name"],
271
+ url=reference["url"] or "",
272
+ sequence_number=new_ref_num,
273
+ source_id=source_id,
274
+ source=reference["source"],
275
+ )
276
+ )
277
+
278
+ message_text = re.sub(
279
+ rf"\s*{re.escape(reference_str)}",
280
+ f" <sup>{new_ref_num}</sup>",
281
+ message_text,
282
+ )
283
+
284
+ loop_response.message.text = message_text
285
+ # Remove spaces between consecutive references
286
+ loop_response.message.text = re.sub(
287
+ r"</sup>\s*<sup>", "</sup><sup>", loop_response.message.text
288
+ )
289
+
290
+
219
291
  def _consolidate_references_in_place(
220
292
  messages: list[_SubAgentToolInfo],
221
293
  existing_refs: dict[str, int],
222
- loop_response: LanguageModelStreamResponse,
223
294
  ) -> None:
224
295
  start_index = max(existing_refs.values(), default=0) + 1
225
296
 
@@ -253,29 +324,5 @@ def _consolidate_references_in_place(
253
324
  ref_map[reference["sequenceNumber"]] = reference_num
254
325
  reference["sequenceNumber"] = reference_num
255
326
 
256
- loop_response.message.text = (
257
- _replace_sub_agent_references_in_main_agent_message(
258
- loop_response.message.text,
259
- assistant_tool_info["name"],
260
- sequence_number,
261
- ref_map,
262
- )
263
- )
264
327
  message["text"] = _replace_references_in_text(message["text"], ref_map)
265
328
  message["references"] = message_new_refs
266
-
267
-
268
- def _replace_sub_agent_references_in_main_agent_message(
269
- message: str, sub_agent_name: str, sequence_number: int, ref_map: dict[int, int]
270
- ) -> str:
271
- for old_seq_num, new_seq_num in ref_map.items():
272
- reference = SubAgentTool.get_sub_agent_reference_format(
273
- name=sub_agent_name,
274
- sequence_number=sequence_number,
275
- reference_number=old_seq_num,
276
- )
277
- message = re.sub(rf"\s*{reference}", f" <sup>{new_seq_num}</sup>", message)
278
-
279
- # Remove spaces between consecutive references
280
- message = re.sub(r"</sup>\s*<sup>", "</sup><sup>", message)
281
- return message
@@ -22,9 +22,8 @@ class TestConsolidateReferencesInPlace:
22
22
  """Test with empty messages list."""
23
23
  messages = []
24
24
  existing_refs = {}
25
- loop_response = self._create_mock_loop_response()
26
25
 
27
- _consolidate_references_in_place(messages, existing_refs, loop_response)
26
+ _consolidate_references_in_place(messages, existing_refs)
28
27
 
29
28
  assert existing_refs == {}
30
29
 
@@ -53,9 +52,8 @@ class TestConsolidateReferencesInPlace:
53
52
  }
54
53
  ]
55
54
  existing_refs = {}
56
- loop_response = self._create_mock_loop_response()
57
55
 
58
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
56
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
59
57
 
60
58
  # Should start from index 1 since existing_refs is empty
61
59
  assert existing_refs == {"source1": 1}
@@ -90,9 +88,8 @@ class TestConsolidateReferencesInPlace:
90
88
  }
91
89
  ]
92
90
  existing_refs = {"existing_source": 5}
93
- loop_response = self._create_mock_loop_response()
94
91
 
95
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
92
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
96
93
 
97
94
  # Should start from 6 (max existing + 1)
98
95
  assert existing_refs == {"existing_source": 5, "new_source": 6}
@@ -141,8 +138,7 @@ class TestConsolidateReferencesInPlace:
141
138
  ]
142
139
  existing_refs = {}
143
140
 
144
- loop_response = self._create_mock_loop_response()
145
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
141
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
146
142
 
147
143
  # Both should map to the same consolidated reference number
148
144
  assert existing_refs == {"shared_source": 1}
@@ -187,8 +183,7 @@ class TestConsolidateReferencesInPlace:
187
183
  ]
188
184
  existing_refs = {}
189
185
 
190
- loop_response = self._create_mock_loop_response()
191
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
186
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
192
187
 
193
188
  assert existing_refs == {"source1": 1, "source2": 2}
194
189
  # Both references should be in the message since they're unique
@@ -240,8 +235,7 @@ class TestConsolidateReferencesInPlace:
240
235
  ]
241
236
  existing_refs = {}
242
237
 
243
- loop_response = self._create_mock_loop_response()
244
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
238
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
245
239
 
246
240
  # Should be processed in order 1, 2, 3 and assigned consecutive numbers
247
241
  assert existing_refs == {"source1": 1, "source2": 2, "source3": 3}
@@ -262,8 +256,7 @@ class TestConsolidateReferencesInPlace:
262
256
  ]
263
257
  existing_refs = {}
264
258
 
265
- loop_response = self._create_mock_loop_response()
266
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
259
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
267
260
 
268
261
  assert existing_refs == {}
269
262
  assert messages[0]["responses"][1]["text"] == "Text with no references"
@@ -314,8 +307,7 @@ class TestConsolidateReferencesInPlace:
314
307
  ]
315
308
  existing_refs = {}
316
309
 
317
- loop_response = self._create_mock_loop_response()
318
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
310
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
319
311
 
320
312
  assert existing_refs == {"source1": 1, "source2": 2}
321
313
  assert messages[0]["responses"][1]["text"] == "Assistant 1 text <sup>1</sup>"
@@ -368,8 +360,7 @@ class TestConsolidateReferencesInPlace:
368
360
  ]
369
361
  existing_refs = {"existing": 10} # Start from 11
370
362
 
371
- loop_response = self._create_mock_loop_response()
372
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
363
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
373
364
 
374
365
  # sourceB gets 11 (first in sorted order), sourceA gets 12
375
366
  assert existing_refs == {"existing": 10, "sourceB": 11, "sourceA": 12}
@@ -416,8 +407,7 @@ class TestConsolidateReferencesInPlace:
416
407
  ]
417
408
  existing_refs = {}
418
409
 
419
- loop_response = self._create_mock_loop_response()
420
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
410
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
421
411
 
422
412
  # Should call _replace_references_in_text with the original text and ref mapping
423
413
  mock_replace.assert_called_once_with("Original text <sup>1</sup>", {1: 1})
@@ -446,8 +436,7 @@ class TestConsolidateReferencesInPlace:
446
436
  ]
447
437
  existing_refs = {}
448
438
 
449
- loop_response = self._create_mock_loop_response()
450
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
439
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
451
440
 
452
441
  # The original reference object should be modified in place
453
442
  assert original_ref["sequenceNumber"] == 1
@@ -488,8 +477,7 @@ class TestConsolidateReferencesInPlace:
488
477
  ]
489
478
 
490
479
  existing_refs_copy = existing_refs.copy()
491
- loop_response = self._create_mock_loop_response()
492
- _consolidate_references_in_place(messages, existing_refs_copy, loop_response) # type: ignore
480
+ _consolidate_references_in_place(messages, existing_refs_copy) # type: ignore
493
481
 
494
482
  assert existing_refs_copy["new_source"] == expected_start
495
483
 
@@ -505,8 +493,7 @@ class TestConsolidateReferencesInPlace:
505
493
  ]
506
494
  existing_refs = {}
507
495
 
508
- loop_response = self._create_mock_loop_response()
509
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
496
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
510
497
 
511
498
  assert existing_refs == {}
512
499
 
@@ -550,8 +537,7 @@ class TestConsolidateReferencesInPlace:
550
537
  ]
551
538
  existing_refs = {}
552
539
 
553
- loop_response = self._create_mock_loop_response()
554
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
540
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
555
541
 
556
542
  # Only valid messages should be processed
557
543
  assert existing_refs == {"source1": 1, "source3": 2}
@@ -611,8 +597,7 @@ class TestConsolidateReferencesInPlace:
611
597
  ]
612
598
  existing_refs = {}
613
599
 
614
- loop_response = self._create_mock_loop_response()
615
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
600
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
616
601
 
617
602
  # Should be processed in order 1, 2, 3 based on response sequence numbers
618
603
  assert existing_refs == {"source1": 1, "source2": 2, "source3": 3}
@@ -646,8 +631,7 @@ class TestConsolidateReferencesInPlace:
646
631
  ]
647
632
  existing_refs = {"existing_source": 99}
648
633
 
649
- loop_response = self._create_mock_loop_response()
650
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
634
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
651
635
 
652
636
  # Should use existing reference number and not add to new refs
653
637
  assert existing_refs == {"existing_source": 99}
@@ -685,8 +669,7 @@ class TestConsolidateReferencesInPlace:
685
669
  ]
686
670
  existing_refs = {"zero": 0, "negative": -5, "positive": 3}
687
671
 
688
- loop_response = self._create_mock_loop_response()
689
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
672
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
690
673
 
691
674
  # Should start from max(0, -5, 3) + 1 = 4
692
675
  assert existing_refs["new_source"] == 4
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_toolkit
3
- Version: 1.18.0
3
+ Version: 1.18.1
4
4
  Summary:
5
5
  License: Proprietary
6
6
  Author: Cedric Klinkert
@@ -118,6 +118,9 @@ All notable changes to this project will be documented in this file.
118
118
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
119
119
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
120
120
 
121
+ ## [1.18.1] - 2025-10-28
122
+ - Fix bug where sub agent references were not properly displayed in the main agent response when the sub agent response was hidden.
123
+
121
124
  ## [1.18.0] - 2025-10-27
122
125
  - Temporary fix to rendering of sub agent responses.
123
126
  - Add config option `stop_condition` to `SubAgentToolConfig`
@@ -68,8 +68,8 @@ unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py,sha256=R90CSecxJrKH7
68
68
  unique_toolkit/agentic/tools/a2a/postprocessing/_display.py,sha256=rdWk-6M6V27v7G3dqaaDj1vXcgsFvDrHswFuSKQfd2I,5186
69
69
  unique_toolkit/agentic/tools/a2a/postprocessing/_utils.py,sha256=JsWwylR2Ao_L0wk1UlhqeN2fTxPnrbhoi1klYHVBnLk,750
70
70
  unique_toolkit/agentic/tools/a2a/postprocessing/config.py,sha256=hqo3vQZX63yXoLT7wN13vf0rC7qKiozKKfdkicYCQno,1061
71
- unique_toolkit/agentic/tools/a2a/postprocessing/postprocessor.py,sha256=lEjJ1u-CTpoyDT7OFaBBOklONUCUU-CGsosHJRYUfkI,10335
72
- unique_toolkit/agentic/tools/a2a/postprocessing/test/test_consolidate_references.py,sha256=0hlTbtqClyMqHNnZRRxETgjVhYrtRu3xUnZx0JSE-uo,28030
71
+ unique_toolkit/agentic/tools/a2a/postprocessing/postprocessor.py,sha256=MMy3NeN4koHWmamaXvsEnrRbsh7XBaWhD0PRcr1i7C4,11931
72
+ unique_toolkit/agentic/tools/a2a/postprocessing/test/test_consolidate_references.py,sha256=HvisnbhPUwuR9uELGunxLjNHvCXheoD5eW52L0tvUXk,26789
73
73
  unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display.py,sha256=Hn2GOsVhpCkpFV9Asvy_IyiYvCd88rxDzi0E_zt2kWc,37553
74
74
  unique_toolkit/agentic/tools/a2a/postprocessing/test/test_postprocessor_reference_functions.py,sha256=GxSkkY-Xgd61Bk8sIRfEtkT9hqL1VgPLWrq-6XoB0rA,11360
75
75
  unique_toolkit/agentic/tools/a2a/prompts.py,sha256=0ILHL_RAcT04gFm2d470j4Gho7PoJXdCJy-bkZgf_wk,2401
@@ -165,7 +165,7 @@ unique_toolkit/short_term_memory/service.py,sha256=5PeVBu1ZCAfyDb2HLVvlmqSbyzBBu
165
165
  unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
166
166
  unique_toolkit/smart_rules/compile.py,sha256=Ozhh70qCn2yOzRWr9d8WmJeTo7AQurwd3tStgBMPFLA,1246
167
167
  unique_toolkit/test_utilities/events.py,sha256=_mwV2bs5iLjxS1ynDCjaIq-gjjKhXYCK-iy3dRfvO3g,6410
168
- unique_toolkit-1.18.0.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
169
- unique_toolkit-1.18.0.dist-info/METADATA,sha256=6XAUmwya1a8ILqkVKETFxYEaCF4p4Q3GfhRmgWO6tcI,38528
170
- unique_toolkit-1.18.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
171
- unique_toolkit-1.18.0.dist-info/RECORD,,
168
+ unique_toolkit-1.18.1.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
169
+ unique_toolkit-1.18.1.dist-info/METADATA,sha256=JM7lTRErEGHbrIrH_VsVvp4NC2snqXYAzq89D6qOrF8,38686
170
+ unique_toolkit-1.18.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
171
+ unique_toolkit-1.18.1.dist-info/RECORD,,