Spaces:
Paused
Paused
Mirrowel
commited on
Commit
Β·
aeb8eaf
1
Parent(s):
1ce8eba
fix(provider): π add automatic ID repair for mismatched tool call responses
Browse filesImplements a recovery mechanism to handle cases where proxies or clients mutate tool call IDs (e.g., transforming "toolu_" prefix to "call_" prefix), which previously caused response grouping failures.
- Enhanced pending group handling to attempt orphan response matching when expected IDs are missing
- Automatically repairs response IDs to match their corresponding tool calls
- Maintains response order by using first available orphan for each unmatched call
- Added warning logs for ID mismatch repairs and partial group satisfaction
- Integrated tool response grouping fix into the main message transformation pipeline
This prevents tool call conversation corruption when intermediary services modify request/response identifiers.
src/rotator_library/providers/antigravity_provider.py
CHANGED
|
@@ -1307,16 +1307,38 @@ class AntigravityProvider(AntigravityAuthBase, ProviderInterface):
|
|
| 1307 |
new_contents.append(content)
|
| 1308 |
|
| 1309 |
# Handle remaining groups (shouldn't happen in well-formed conversations)
|
|
|
|
| 1310 |
for group in pending_groups:
|
| 1311 |
group_ids = group["ids"]
|
| 1312 |
-
|
| 1313 |
-
|
| 1314 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1315 |
new_contents.append({"parts": group_responses, "role": "user"})
|
| 1316 |
-
|
| 1317 |
-
|
| 1318 |
-
|
| 1319 |
-
|
|
|
|
|
|
|
| 1320 |
|
| 1321 |
# Warn about unmatched responses
|
| 1322 |
if collected_responses:
|
|
@@ -2305,6 +2327,7 @@ class AntigravityProvider(AntigravityAuthBase, ProviderInterface):
|
|
| 2305 |
internal_model = self._alias_to_internal(model)
|
| 2306 |
|
| 2307 |
system_instruction, contents = self._transform_messages(messages, internal_model)
|
|
|
|
| 2308 |
|
| 2309 |
gemini_payload = {"contents": contents}
|
| 2310 |
if system_instruction:
|
|
|
|
| 1307 |
new_contents.append(content)
|
| 1308 |
|
| 1309 |
# Handle remaining groups (shouldn't happen in well-formed conversations)
|
| 1310 |
+
# Attempt recovery by matching orphans to unsatisfied calls
|
| 1311 |
for group in pending_groups:
|
| 1312 |
group_ids = group["ids"]
|
| 1313 |
+
group_responses = []
|
| 1314 |
+
|
| 1315 |
+
for expected_id in group_ids:
|
| 1316 |
+
if expected_id in collected_responses:
|
| 1317 |
+
group_responses.append(collected_responses.pop(expected_id))
|
| 1318 |
+
elif collected_responses:
|
| 1319 |
+
# Recovery: Match with an orphan response
|
| 1320 |
+
# This handles cases where client/proxy mutates IDs (e.g. toolu_ -> call_)
|
| 1321 |
+
# Get the first available orphan ID to maintain order
|
| 1322 |
+
orphan_id = next(iter(collected_responses))
|
| 1323 |
+
orphan_resp = collected_responses.pop(orphan_id)
|
| 1324 |
+
|
| 1325 |
+
# Fix the ID in the response to match the call
|
| 1326 |
+
orphan_resp["functionResponse"]["id"] = expected_id
|
| 1327 |
+
|
| 1328 |
+
lib_logger.warning(
|
| 1329 |
+
f"[Grouping] Auto-repaired ID mismatch: mapped response '{orphan_id}' "
|
| 1330 |
+
f"to call '{expected_id}'"
|
| 1331 |
+
)
|
| 1332 |
+
group_responses.append(orphan_resp)
|
| 1333 |
+
|
| 1334 |
+
if group_responses:
|
| 1335 |
new_contents.append({"parts": group_responses, "role": "user"})
|
| 1336 |
+
|
| 1337 |
+
if len(group_responses) != len(group_ids):
|
| 1338 |
+
lib_logger.warning(
|
| 1339 |
+
f"[Grouping] Partial group satisfaction after repair: "
|
| 1340 |
+
f"expected {len(group_ids)}, got {len(group_responses)} responses"
|
| 1341 |
+
)
|
| 1342 |
|
| 1343 |
# Warn about unmatched responses
|
| 1344 |
if collected_responses:
|
|
|
|
| 2327 |
internal_model = self._alias_to_internal(model)
|
| 2328 |
|
| 2329 |
system_instruction, contents = self._transform_messages(messages, internal_model)
|
| 2330 |
+
contents = self._fix_tool_response_grouping(contents)
|
| 2331 |
|
| 2332 |
gemini_payload = {"contents": contents}
|
| 2333 |
if system_instruction:
|