unique_toolkit 1.7.0__py3-none-any.whl → 1.8.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.
Files changed (26) hide show
  1. unique_toolkit/agentic/tools/a2a/__init__.py +19 -3
  2. unique_toolkit/agentic/tools/a2a/config.py +12 -52
  3. unique_toolkit/agentic/tools/a2a/evaluation/__init__.py +10 -3
  4. unique_toolkit/agentic/tools/a2a/evaluation/_utils.py +66 -0
  5. unique_toolkit/agentic/tools/a2a/evaluation/config.py +13 -2
  6. unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py +82 -89
  7. unique_toolkit/agentic/tools/a2a/manager.py +2 -2
  8. unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py +9 -1
  9. unique_toolkit/agentic/tools/a2a/postprocessing/{display.py → _display.py} +16 -7
  10. unique_toolkit/agentic/tools/a2a/postprocessing/_utils.py +19 -0
  11. unique_toolkit/agentic/tools/a2a/postprocessing/config.py +24 -0
  12. unique_toolkit/agentic/tools/a2a/postprocessing/postprocessor.py +109 -110
  13. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_consolidate_references.py +665 -0
  14. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display.py +54 -75
  15. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_postprocessor_reference_functions.py +53 -45
  16. unique_toolkit/agentic/tools/a2a/tool/__init__.py +4 -0
  17. unique_toolkit/agentic/tools/a2a/{memory.py → tool/_memory.py} +1 -1
  18. unique_toolkit/agentic/tools/a2a/{schema.py → tool/_schema.py} +0 -6
  19. unique_toolkit/agentic/tools/a2a/tool/config.py +63 -0
  20. unique_toolkit/agentic/tools/a2a/{service.py → tool/service.py} +108 -65
  21. unique_toolkit/agentic/tools/config.py +2 -2
  22. unique_toolkit/agentic/tools/tool_manager.py +1 -2
  23. {unique_toolkit-1.7.0.dist-info → unique_toolkit-1.8.0.dist-info}/METADATA +5 -1
  24. {unique_toolkit-1.7.0.dist-info → unique_toolkit-1.8.0.dist-info}/RECORD +26 -20
  25. {unique_toolkit-1.7.0.dist-info → unique_toolkit-1.8.0.dist-info}/LICENSE +0 -0
  26. {unique_toolkit-1.7.0.dist-info → unique_toolkit-1.8.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,665 @@
1
+ from unittest.mock import patch
2
+
3
+ import pytest
4
+
5
+ from unique_toolkit.agentic.tools.a2a.postprocessing.postprocessor import (
6
+ _consolidate_references_in_place,
7
+ )
8
+
9
+
10
+ class TestConsolidateReferencesInPlace:
11
+ """Test cases for _consolidate_references_in_place function."""
12
+
13
+ def test_empty_messages_list(self):
14
+ """Test with empty messages list."""
15
+ messages = []
16
+ existing_refs = {}
17
+
18
+ _consolidate_references_in_place(messages, existing_refs)
19
+
20
+ assert existing_refs == {}
21
+
22
+ def test_empty_existing_refs(self):
23
+ """Test with empty existing references."""
24
+ messages = [
25
+ {
26
+ "display_name": "Assistant1",
27
+ "display_config": {"mode": "expanded"},
28
+ "responses": {
29
+ 1: {
30
+ "text": "Test text with reference <sup>1</sup>",
31
+ "references": [
32
+ {
33
+ "sourceId": "source1",
34
+ "sequenceNumber": 1,
35
+ "name": "Test Source",
36
+ "url": "http://test.com",
37
+ "source": "test",
38
+ "originalIndex": [],
39
+ }
40
+ ],
41
+ }
42
+ },
43
+ }
44
+ ]
45
+ existing_refs = {}
46
+
47
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
48
+
49
+ # Should start from index 1 since existing_refs is empty
50
+ assert existing_refs == {"source1": 1}
51
+ assert messages[0]["responses"][1]["references"][0]["sequenceNumber"] == 1
52
+ assert (
53
+ messages[0]["responses"][1]["text"]
54
+ == "Test text with reference <sup>1</sup>"
55
+ )
56
+
57
+ def test_with_existing_refs(self):
58
+ """Test with existing references."""
59
+ messages = [
60
+ {
61
+ "display_name": "Assistant1",
62
+ "display_config": {"mode": "expanded"},
63
+ "responses": {
64
+ 1: {
65
+ "text": "New text with reference <sup>1</sup>",
66
+ "references": [
67
+ {
68
+ "sourceId": "new_source",
69
+ "sequenceNumber": 1,
70
+ "name": "New Source",
71
+ "url": "http://new.com",
72
+ "source": "new",
73
+ "originalIndex": [],
74
+ }
75
+ ],
76
+ }
77
+ },
78
+ }
79
+ ]
80
+ existing_refs = {"existing_source": 5}
81
+
82
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
83
+
84
+ # Should start from 6 (max existing + 1)
85
+ assert existing_refs == {"existing_source": 5, "new_source": 6}
86
+ assert messages[0]["responses"][1]["references"][0]["sequenceNumber"] == 6
87
+ assert (
88
+ messages[0]["responses"][1]["text"]
89
+ == "New text with reference <sup>6</sup>"
90
+ )
91
+
92
+ def test_duplicate_source_ids(self):
93
+ """Test with duplicate source IDs across different messages."""
94
+ messages = [
95
+ {
96
+ "display_name": "Assistant1",
97
+ "display_config": {"mode": "expanded"},
98
+ "responses": {
99
+ 1: {
100
+ "text": "First reference <sup>1</sup>",
101
+ "references": [
102
+ {
103
+ "sourceId": "shared_source",
104
+ "sequenceNumber": 1,
105
+ "name": "Shared Source",
106
+ "url": "http://shared.com",
107
+ "source": "shared",
108
+ "originalIndex": [],
109
+ }
110
+ ],
111
+ },
112
+ 2: {
113
+ "text": "Second reference <sup>2</sup>",
114
+ "references": [
115
+ {
116
+ "sourceId": "shared_source",
117
+ "sequenceNumber": 2,
118
+ "name": "Shared Source",
119
+ "url": "http://shared.com",
120
+ "source": "shared",
121
+ "originalIndex": [],
122
+ }
123
+ ],
124
+ },
125
+ },
126
+ }
127
+ ]
128
+ existing_refs = {}
129
+
130
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
131
+
132
+ # Both should map to the same consolidated reference number
133
+ assert existing_refs == {"shared_source": 1}
134
+ assert messages[0]["responses"][1]["references"][0]["sequenceNumber"] == 1
135
+ assert (
136
+ messages[0]["responses"][2]["references"] == []
137
+ ) # Should be empty for duplicate
138
+ assert messages[0]["responses"][1]["text"] == "First reference <sup>1</sup>"
139
+ assert messages[0]["responses"][2]["text"] == "Second reference <sup>1</sup>"
140
+
141
+ def test_multiple_references_in_single_message(self):
142
+ """Test with multiple references in a single message."""
143
+ messages = [
144
+ {
145
+ "display_name": "Assistant1",
146
+ "display_config": {"mode": "expanded"},
147
+ "responses": {
148
+ 1: {
149
+ "text": "Text with <sup>1</sup> and <sup>2</sup> references",
150
+ "references": [
151
+ {
152
+ "sourceId": "source1",
153
+ "sequenceNumber": 1,
154
+ "name": "Source 1",
155
+ "url": "http://source1.com",
156
+ "source": "src1",
157
+ "originalIndex": [],
158
+ },
159
+ {
160
+ "sourceId": "source2",
161
+ "sequenceNumber": 2,
162
+ "name": "Source 2",
163
+ "url": "http://source2.com",
164
+ "source": "src2",
165
+ "originalIndex": [],
166
+ },
167
+ ],
168
+ }
169
+ },
170
+ }
171
+ ]
172
+ existing_refs = {}
173
+
174
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
175
+
176
+ assert existing_refs == {"source1": 1, "source2": 2}
177
+ # Both references should be in the message since they're unique
178
+ assert len(messages[0]["responses"][1]["references"]) == 2
179
+ assert (
180
+ messages[0]["responses"][1]["text"]
181
+ == "Text with <sup>1</sup> and <sup>2</sup> references"
182
+ )
183
+
184
+ def test_references_sorted_by_sequence_number(self):
185
+ """Test that references are sorted by sequence number before processing."""
186
+ messages = [
187
+ {
188
+ "display_name": "Assistant1",
189
+ "display_config": {"mode": "expanded"},
190
+ "responses": {
191
+ 1: {
192
+ "text": "Text with <sup>3</sup> and <sup>1</sup> and <sup>2</sup>",
193
+ "references": [
194
+ {
195
+ "sourceId": "source3",
196
+ "sequenceNumber": 3,
197
+ "name": "Source 3",
198
+ "url": "http://source3.com",
199
+ "source": "src3",
200
+ "originalIndex": [],
201
+ },
202
+ {
203
+ "sourceId": "source1",
204
+ "sequenceNumber": 1,
205
+ "name": "Source 1",
206
+ "url": "http://source1.com",
207
+ "source": "src1",
208
+ "originalIndex": [],
209
+ },
210
+ {
211
+ "sourceId": "source2",
212
+ "sequenceNumber": 2,
213
+ "name": "Source 2",
214
+ "url": "http://source2.com",
215
+ "source": "src2",
216
+ "originalIndex": [],
217
+ },
218
+ ],
219
+ }
220
+ },
221
+ }
222
+ ]
223
+ existing_refs = {}
224
+
225
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
226
+
227
+ # Should be processed in order 1, 2, 3 and assigned consecutive numbers
228
+ assert existing_refs == {"source1": 1, "source2": 2, "source3": 3}
229
+ assert (
230
+ messages[0]["responses"][1]["text"]
231
+ == "Text with <sup>3</sup> and <sup>1</sup> and <sup>2</sup>"
232
+ )
233
+
234
+ def test_empty_references_list(self):
235
+ """Test with empty references list."""
236
+ messages = [
237
+ {
238
+ "display_name": "Assistant1",
239
+ "display_config": {"mode": "expanded"},
240
+ "responses": {1: {"text": "Text with no references", "references": []}},
241
+ }
242
+ ]
243
+ existing_refs = {}
244
+
245
+ with patch(
246
+ "unique_toolkit.agentic.tools.a2a.postprocessing.postprocessor.logger"
247
+ ) as mock_logger:
248
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
249
+
250
+ # Should log debug message about no references
251
+ mock_logger.debug.assert_called_once()
252
+ assert (
253
+ "does not contain any references" in mock_logger.debug.call_args[0][0]
254
+ )
255
+
256
+ assert existing_refs == {}
257
+ assert messages[0]["responses"][1]["text"] == "Text with no references"
258
+
259
+ def test_multiple_assistants(self):
260
+ """Test with multiple assistants."""
261
+ messages = [
262
+ {
263
+ "display_name": "Assistant1",
264
+ "display_config": {"mode": "expanded"},
265
+ "responses": {
266
+ 1: {
267
+ "text": "Assistant 1 text <sup>1</sup>",
268
+ "references": [
269
+ {
270
+ "sourceId": "source1",
271
+ "sequenceNumber": 1,
272
+ "name": "Source 1",
273
+ "url": "http://source1.com",
274
+ "source": "src1",
275
+ "originalIndex": [],
276
+ }
277
+ ],
278
+ }
279
+ },
280
+ },
281
+ {
282
+ "display_name": "Assistant2",
283
+ "display_config": {"mode": "expanded"},
284
+ "responses": {
285
+ 1: {
286
+ "text": "Assistant 2 text <sup>1</sup>",
287
+ "references": [
288
+ {
289
+ "sourceId": "source2",
290
+ "sequenceNumber": 1,
291
+ "name": "Source 2",
292
+ "url": "http://source2.com",
293
+ "source": "src2",
294
+ "originalIndex": [],
295
+ }
296
+ ],
297
+ }
298
+ },
299
+ },
300
+ ]
301
+ existing_refs = {}
302
+
303
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
304
+
305
+ assert existing_refs == {"source1": 1, "source2": 2}
306
+ assert messages[0]["responses"][1]["text"] == "Assistant 1 text <sup>1</sup>"
307
+ assert messages[1]["responses"][1]["text"] == "Assistant 2 text <sup>2</sup>"
308
+
309
+ def test_complex_reference_mapping(self):
310
+ """Test complex scenario with overlapping sequence numbers and mixed source IDs."""
311
+ messages = [
312
+ {
313
+ "display_name": "Assistant1",
314
+ "display_config": {"mode": "expanded"},
315
+ "responses": {
316
+ 1: {
317
+ "text": "Text with <sup>2</sup> and <sup>1</sup>",
318
+ "references": [
319
+ {
320
+ "sourceId": "sourceA",
321
+ "sequenceNumber": 2,
322
+ "name": "Source A",
323
+ "url": "http://sourceA.com",
324
+ "source": "srcA",
325
+ "originalIndex": [],
326
+ },
327
+ {
328
+ "sourceId": "sourceB",
329
+ "sequenceNumber": 1,
330
+ "name": "Source B",
331
+ "url": "http://sourceB.com",
332
+ "source": "srcB",
333
+ "originalIndex": [],
334
+ },
335
+ ],
336
+ },
337
+ 2: {
338
+ "text": "Another text with <sup>1</sup>",
339
+ "references": [
340
+ {
341
+ "sourceId": "sourceA", # Same source as above
342
+ "sequenceNumber": 1,
343
+ "name": "Source A",
344
+ "url": "http://sourceA.com",
345
+ "source": "srcA",
346
+ "originalIndex": [],
347
+ }
348
+ ],
349
+ },
350
+ },
351
+ }
352
+ ]
353
+ existing_refs = {"existing": 10} # Start from 11
354
+
355
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
356
+
357
+ # sourceB gets 11 (first in sorted order), sourceA gets 12
358
+ assert existing_refs == {"existing": 10, "sourceB": 11, "sourceA": 12}
359
+
360
+ # First message should have both references updated
361
+ assert (
362
+ messages[0]["responses"][1]["text"]
363
+ == "Text with <sup>12</sup> and <sup>11</sup>"
364
+ )
365
+ assert len(messages[0]["responses"][1]["references"]) == 2
366
+
367
+ # Second message should have empty references (duplicate sourceA) but updated text
368
+ assert messages[0]["responses"][2]["text"] == "Another text with <sup>12</sup>"
369
+ assert messages[0]["responses"][2]["references"] == []
370
+
371
+ @patch(
372
+ "unique_toolkit.agentic.tools.a2a.postprocessing.postprocessor._replace_references_in_text"
373
+ )
374
+ def test_replace_references_called_correctly(self, mock_replace):
375
+ """Test that _replace_references_in_text is called with correct parameters."""
376
+ mock_replace.return_value = "Updated text"
377
+
378
+ messages = [
379
+ {
380
+ "display_name": "Assistant1",
381
+ "display_config": {"mode": "expanded"},
382
+ "responses": {
383
+ 1: {
384
+ "text": "Original text <sup>1</sup>",
385
+ "references": [
386
+ {
387
+ "sourceId": "source1",
388
+ "sequenceNumber": 1,
389
+ "name": "Source 1",
390
+ "url": "http://source1.com",
391
+ "source": "src1",
392
+ "originalIndex": [],
393
+ }
394
+ ],
395
+ }
396
+ },
397
+ }
398
+ ]
399
+ existing_refs = {}
400
+
401
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
402
+
403
+ # Should call _replace_references_in_text with the original text and ref mapping
404
+ mock_replace.assert_called_once_with("Original text <sup>1</sup>", {1: 1})
405
+ assert messages[0]["responses"][1]["text"] == "Updated text"
406
+
407
+ def test_reference_sequence_number_modification(self):
408
+ """Test that reference sequence numbers are correctly modified in place."""
409
+ original_ref = {
410
+ "sourceId": "source1",
411
+ "sequenceNumber": 5,
412
+ "name": "Source 1",
413
+ "url": "http://source1.com",
414
+ "source": "src1",
415
+ "originalIndex": [],
416
+ }
417
+
418
+ messages = [
419
+ {
420
+ "display_name": "Assistant1",
421
+ "display_config": {"mode": "expanded"},
422
+ "responses": {
423
+ 1: {"text": "Text <sup>5</sup>", "references": [original_ref]}
424
+ },
425
+ }
426
+ ]
427
+ existing_refs = {}
428
+
429
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
430
+
431
+ # The original reference object should be modified in place
432
+ assert original_ref["sequenceNumber"] == 1
433
+ assert messages[0]["responses"][1]["references"][0]["sequenceNumber"] == 1
434
+
435
+ @pytest.mark.parametrize(
436
+ "existing_refs,expected_start",
437
+ [
438
+ ({}, 1), # Empty -> start from 1
439
+ ({"a": 1}, 2), # Max 1 -> start from 2
440
+ ({"a": 5, "b": 3, "c": 10}, 11), # Max 10 -> start from 11
441
+ ({"a": 0}, 1), # Max 0 -> start from 1
442
+ ],
443
+ )
444
+ def test_start_index_calculation(self, existing_refs, expected_start):
445
+ """Test that start_index is calculated correctly from existing_refs."""
446
+ messages = [
447
+ {
448
+ "display_name": "Assistant1",
449
+ "display_config": {"mode": "expanded"},
450
+ "responses": {
451
+ 1: {
452
+ "text": "Text <sup>1</sup>",
453
+ "references": [
454
+ {
455
+ "sourceId": "new_source",
456
+ "sequenceNumber": 1,
457
+ "name": "New Source",
458
+ "url": "http://new.com",
459
+ "source": "new",
460
+ "originalIndex": [],
461
+ }
462
+ ],
463
+ }
464
+ },
465
+ }
466
+ ]
467
+
468
+ existing_refs_copy = existing_refs.copy()
469
+ _consolidate_references_in_place(messages, existing_refs_copy) # type: ignore
470
+
471
+ assert existing_refs_copy["new_source"] == expected_start
472
+
473
+ def test_no_responses_in_assistant(self):
474
+ """Test with assistant that has no responses."""
475
+ messages = [
476
+ {
477
+ "display_name": "Assistant1",
478
+ "display_config": {"mode": "expanded"},
479
+ "responses": {},
480
+ }
481
+ ]
482
+ existing_refs = {}
483
+
484
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
485
+
486
+ assert existing_refs == {}
487
+
488
+ def test_mixed_valid_and_invalid_messages(self):
489
+ """Test with mix of valid messages and messages with no references."""
490
+ messages = [
491
+ {
492
+ "display_name": "Assistant1",
493
+ "display_config": {"mode": "expanded"},
494
+ "responses": {
495
+ 1: {
496
+ "text": "Valid text <sup>1</sup>",
497
+ "references": [
498
+ {
499
+ "sourceId": "source1",
500
+ "sequenceNumber": 1,
501
+ "name": "Source 1",
502
+ "url": "http://source1.com",
503
+ "source": "src1",
504
+ "originalIndex": [],
505
+ }
506
+ ],
507
+ },
508
+ 2: {"text": "No references", "references": []},
509
+ 3: {
510
+ "text": "Another valid <sup>1</sup>",
511
+ "references": [
512
+ {
513
+ "sourceId": "source3",
514
+ "sequenceNumber": 1,
515
+ "name": "Source 3",
516
+ "url": "http://source3.com",
517
+ "source": "src3",
518
+ "originalIndex": [],
519
+ }
520
+ ],
521
+ },
522
+ },
523
+ }
524
+ ]
525
+ existing_refs = {}
526
+
527
+ with patch(
528
+ "unique_toolkit.agentic.tools.a2a.postprocessing.postprocessor.logger"
529
+ ) as mock_logger:
530
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
531
+
532
+ # Should log once for message 2
533
+ mock_logger.debug.assert_called_once()
534
+
535
+ # Only valid messages should be processed
536
+ assert existing_refs == {"source1": 1, "source3": 2}
537
+ assert messages[0]["responses"][1]["text"] == "Valid text <sup>1</sup>"
538
+ assert messages[0]["responses"][2]["text"] == "No references"
539
+ assert messages[0]["responses"][3]["text"] == "Another valid <sup>2</sup>"
540
+
541
+ def test_sequence_number_sorting_within_responses(self):
542
+ """Test that responses are processed in sorted sequence number order."""
543
+ messages = [
544
+ {
545
+ "display_name": "Assistant1",
546
+ "display_config": {"mode": "expanded"},
547
+ "responses": {
548
+ 3: {
549
+ "text": "Third message <sup>1</sup>",
550
+ "references": [
551
+ {
552
+ "sourceId": "source3",
553
+ "sequenceNumber": 1,
554
+ "name": "Source 3",
555
+ "url": "http://source3.com",
556
+ "source": "src3",
557
+ "originalIndex": [],
558
+ }
559
+ ],
560
+ },
561
+ 1: {
562
+ "text": "First message <sup>1</sup>",
563
+ "references": [
564
+ {
565
+ "sourceId": "source1",
566
+ "sequenceNumber": 1,
567
+ "name": "Source 1",
568
+ "url": "http://source1.com",
569
+ "source": "src1",
570
+ "originalIndex": [],
571
+ }
572
+ ],
573
+ },
574
+ 2: {
575
+ "text": "Second message <sup>1</sup>",
576
+ "references": [
577
+ {
578
+ "sourceId": "source2",
579
+ "sequenceNumber": 1,
580
+ "name": "Source 2",
581
+ "url": "http://source2.com",
582
+ "source": "src2",
583
+ "originalIndex": [],
584
+ }
585
+ ],
586
+ },
587
+ },
588
+ }
589
+ ]
590
+ existing_refs = {}
591
+
592
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
593
+
594
+ # Should be processed in order 1, 2, 3 based on response sequence numbers
595
+ assert existing_refs == {"source1": 1, "source2": 2, "source3": 3}
596
+ assert messages[0]["responses"][1]["text"] == "First message <sup>1</sup>"
597
+ assert messages[0]["responses"][2]["text"] == "Second message <sup>2</sup>"
598
+ assert messages[0]["responses"][3]["text"] == "Third message <sup>3</sup>"
599
+
600
+ def test_source_id_already_exists_in_existing_refs(self):
601
+ """Test when source ID already exists in existing_refs."""
602
+ messages = [
603
+ {
604
+ "display_name": "Assistant1",
605
+ "display_config": {"mode": "expanded"},
606
+ "responses": {
607
+ 1: {
608
+ "text": "Message <sup>1</sup> with existing source",
609
+ "references": [
610
+ {
611
+ "sourceId": "existing_source",
612
+ "sequenceNumber": 1,
613
+ "name": "Existing Source",
614
+ "url": "http://existing.com",
615
+ "source": "existing",
616
+ "originalIndex": [],
617
+ }
618
+ ],
619
+ }
620
+ },
621
+ }
622
+ ]
623
+ existing_refs = {"existing_source": 99}
624
+
625
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
626
+
627
+ # Should use existing reference number and not add to new refs
628
+ assert existing_refs == {"existing_source": 99}
629
+ assert (
630
+ messages[0]["responses"][1]["text"]
631
+ == "Message <sup>99</sup> with existing source"
632
+ )
633
+ assert (
634
+ messages[0]["responses"][1]["references"] == []
635
+ ) # Should be empty since it's not new
636
+
637
+ def test_edge_case_zero_and_negative_existing_refs(self):
638
+ """Test edge case with zero and negative values in existing_refs."""
639
+ messages = [
640
+ {
641
+ "display_name": "Assistant1",
642
+ "display_config": {"mode": "expanded"},
643
+ "responses": {
644
+ 1: {
645
+ "text": "Text <sup>1</sup>",
646
+ "references": [
647
+ {
648
+ "sourceId": "new_source",
649
+ "sequenceNumber": 1,
650
+ "name": "New Source",
651
+ "url": "http://new.com",
652
+ "source": "new",
653
+ "originalIndex": [],
654
+ }
655
+ ],
656
+ }
657
+ },
658
+ }
659
+ ]
660
+ existing_refs = {"zero": 0, "negative": -5, "positive": 3}
661
+
662
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
663
+
664
+ # Should start from max(0, -5, 3) + 1 = 4
665
+ assert existing_refs["new_source"] == 4