Mirrowel commited on
Commit
8a839ed
·
1 Parent(s): 8d69bcd

refactor(antigravity): 🔨 remove thinking mode toggling feature

Browse files

This commit removes the thinking mode toggling functionality that was previously used to handle model switches mid-conversation when tool use loops were incomplete.

- Removed `_detect_incomplete_tool_turn`, `_inject_turn_completion`, and `_handle_thinking_mode_toggle` helper methods
- Removed environment variable configuration for turn completion behavior (`ANTIGRAVITY_AUTO_INJECT_TURN_COMPLETION`, `ANTIGRAVITY_AUTO_SUPPRESS_THINKING`, `ANTIGRAVITY_TURN_COMPLETION_TEXT`)
- Removed thinking mode toggle logic from `acompletion` method
- Added provider prefix to JSON auto-correction warning log for better debugging

The removed feature was designed to automatically handle incomplete tool use loops when switching to Claude models with thinking mode enabled, but was buggy as hell.

src/rotator_library/providers/antigravity_provider.py CHANGED
@@ -199,7 +199,7 @@ def _recursively_parse_json_strings(obj: Any) -> Any:
199
  cleaned = stripped[:last_bracket+1]
200
  parsed = json.loads(cleaned)
201
  lib_logger.warning(
202
- f"Auto-corrected malformed JSON string: "
203
  f"truncated {len(stripped) - len(cleaned)} extra chars"
204
  )
205
  return _recursively_parse_json_strings(parsed)
@@ -370,11 +370,6 @@ class AntigravityProvider(AntigravityAuthBase, ProviderInterface):
370
  self._enable_dynamic_models = _env_bool("ANTIGRAVITY_ENABLE_DYNAMIC_MODELS", False)
371
  self._enable_gemini3_tool_fix = _env_bool("ANTIGRAVITY_GEMINI3_TOOL_FIX", True)
372
 
373
- # Thinking mode toggling behavior
374
- self._auto_inject_turn_completion = _env_bool("ANTIGRAVITY_AUTO_INJECT_TURN_COMPLETION", True)
375
- self._auto_suppress_thinking = _env_bool("ANTIGRAVITY_AUTO_SUPPRESS_THINKING", False)
376
- self._turn_completion_placeholder = os.getenv("ANTIGRAVITY_TURN_COMPLETION_TEXT", "...")
377
-
378
  # Gemini 3 tool fix configuration
379
  self._gemini3_tool_prefix = os.getenv("ANTIGRAVITY_GEMINI3_TOOL_PREFIX", "gemini3_")
380
  self._gemini3_description_prompt = os.getenv(
@@ -1368,142 +1363,6 @@ class AntigravityProvider(AntigravityAuthBase, ProviderInterface):
1368
 
1369
  return [f"antigravity/{m}" for m in AVAILABLE_MODELS]
1370
 
1371
- # =========================================================================
1372
- # THINKING MODE TOGGLING HELPERS
1373
- # =========================================================================
1374
-
1375
- def _detect_incomplete_tool_turn(self, messages: List[Dict[str, Any]]) -> Optional[int]:
1376
- """
1377
- Detect if messages end with an incomplete tool use loop.
1378
-
1379
- An incomplete tool turn is when:
1380
- - Last message is a tool result
1381
- - The assistant message that made the tool call hasn't been completed
1382
- with a final text response
1383
-
1384
- Returns:
1385
- Index of the assistant message with tool_calls if incomplete turn detected,
1386
- None otherwise
1387
- """
1388
- if len(messages) < 2:
1389
- return None
1390
-
1391
- # Last message must be tool result
1392
- if messages[-1].get("role") != "tool":
1393
- return None
1394
-
1395
- # Find the assistant message that made the tool call
1396
- for i in range(len(messages) - 2, -1, -1):
1397
- msg = messages[i]
1398
- if msg.get("role") == "assistant":
1399
- if msg.get("tool_calls"):
1400
- # Check if turn was completed by a subsequent assistant message
1401
- for j in range(i + 1, len(messages)):
1402
- if messages[j].get("role") == "assistant" and not messages[j].get("tool_calls"):
1403
- return None # Turn completed
1404
-
1405
- # Incomplete turn found
1406
- lib_logger.debug(
1407
- f"Detected incomplete tool turn: assistant message at index {i} "
1408
- f"has tool_calls, but no completing text response found"
1409
- )
1410
- return i
1411
- else:
1412
- # Found completing assistant message
1413
- return None
1414
-
1415
- return None
1416
-
1417
- def _inject_turn_completion(
1418
- self,
1419
- messages: List[Dict[str, Any]],
1420
- incomplete_turn_index: int
1421
- ) -> List[Dict[str, Any]]:
1422
- """
1423
- Inject a completing assistant message to close an incomplete tool use turn.
1424
-
1425
- Args:
1426
- messages: Original message list
1427
- incomplete_turn_index: Index of the assistant message with tool_calls
1428
-
1429
- Returns:
1430
- Modified message list with injected completion
1431
- """
1432
- completion_msg = {
1433
- "role": "assistant",
1434
- "content": self._turn_completion_placeholder
1435
- }
1436
-
1437
- # Append to close the turn
1438
- modified_messages = messages.copy()
1439
- modified_messages.append(completion_msg)
1440
-
1441
- lib_logger.info(
1442
- f"Injected turn-completing assistant message ('{self._turn_completion_placeholder}') "
1443
- f"to enable thinking mode. Original tool use started at message index {incomplete_turn_index}."
1444
- )
1445
-
1446
- return modified_messages
1447
-
1448
- def _handle_thinking_mode_toggle(
1449
- self,
1450
- messages: List[Dict[str, Any]],
1451
- model: str,
1452
- reasoning_effort: Optional[str]
1453
- ) -> Tuple[List[Dict[str, Any]], Optional[str]]:
1454
- """
1455
- Handle thinking mode toggling when switching models mid-conversation.
1456
-
1457
- When switching to Claude with thinking enabled, but the conversation has
1458
- an incomplete tool use loop from another model, either:
1459
- 1. Inject a completing message to close the turn (if auto_inject enabled)
1460
- 2. Suppress thinking mode (if auto_suppress enabled)
1461
- 3. Let it fail with API error (if both disabled)
1462
-
1463
- Args:
1464
- messages: Original message list
1465
- model: Target model
1466
- reasoning_effort: Requested reasoning effort level
1467
-
1468
- Returns:
1469
- (modified_messages, modified_reasoning_effort)
1470
- """
1471
- # Only applies when trying to enable thinking on Claude
1472
- if not self._is_claude(model) or not reasoning_effort:
1473
- return messages, reasoning_effort
1474
-
1475
- incomplete_turn_index = self._detect_incomplete_tool_turn(messages)
1476
- if incomplete_turn_index is None:
1477
- # No incomplete turn - proceed normally
1478
- return messages, reasoning_effort
1479
-
1480
- # Strategy 1: Auto-inject turn completion (preferred)
1481
- if self._auto_inject_turn_completion:
1482
- lib_logger.info(
1483
- "Model switch to Claude with thinking detected mid-tool-use-loop. "
1484
- "Injecting turn completion to enable thinking mode."
1485
- )
1486
- modified_messages = self._inject_turn_completion(messages, incomplete_turn_index)
1487
- return modified_messages, reasoning_effort
1488
-
1489
- # Strategy 2: Auto-suppress thinking
1490
- if self._auto_suppress_thinking:
1491
- lib_logger.warning(
1492
- f"Model switch to Claude with thinking detected mid-tool-use-loop. "
1493
- f"Suppressing reasoning_effort={reasoning_effort} to avoid API error. "
1494
- f"Set ANTIGRAVITY_AUTO_INJECT_TURN_COMPLETION=true to inject completion instead."
1495
- )
1496
- return messages, None
1497
-
1498
- # Strategy 3: Let it fail (user wants to handle it themselves)
1499
- lib_logger.warning(
1500
- "Model switch to Claude with thinking detected mid-tool-use-loop. "
1501
- "Both auto-injection and auto-suppression are disabled. "
1502
- "Request will likely fail with API error. "
1503
- f"Enable ANTIGRAVITY_AUTO_INJECT_TURN_COMPLETION or ANTIGRAVITY_AUTO_SUPPRESS_THINKING."
1504
- )
1505
- return messages, reasoning_effort
1506
-
1507
  async def acompletion(
1508
  self,
1509
  client: httpx.AsyncClient,
@@ -1533,13 +1392,6 @@ class AntigravityProvider(AntigravityAuthBase, ProviderInterface):
1533
  # Create logger
1534
  file_logger = AntigravityFileLogger(model, enable_logging)
1535
 
1536
- # Handle thinking mode toggling for model switches
1537
- messages, reasoning_effort = self._handle_thinking_mode_toggle(messages, model, reasoning_effort)
1538
- if reasoning_effort != kwargs.get("reasoning_effort"):
1539
- kwargs["reasoning_effort"] = reasoning_effort
1540
- if messages != kwargs.get("messages"):
1541
- kwargs["messages"] = messages
1542
-
1543
  # Transform messages
1544
  system_instruction, gemini_contents = self._transform_messages(messages, model)
1545
  gemini_contents = self._fix_tool_response_grouping(gemini_contents)
 
199
  cleaned = stripped[:last_bracket+1]
200
  parsed = json.loads(cleaned)
201
  lib_logger.warning(
202
+ f"[Antigravity] Auto-corrected malformed JSON string: "
203
  f"truncated {len(stripped) - len(cleaned)} extra chars"
204
  )
205
  return _recursively_parse_json_strings(parsed)
 
370
  self._enable_dynamic_models = _env_bool("ANTIGRAVITY_ENABLE_DYNAMIC_MODELS", False)
371
  self._enable_gemini3_tool_fix = _env_bool("ANTIGRAVITY_GEMINI3_TOOL_FIX", True)
372
 
 
 
 
 
 
373
  # Gemini 3 tool fix configuration
374
  self._gemini3_tool_prefix = os.getenv("ANTIGRAVITY_GEMINI3_TOOL_PREFIX", "gemini3_")
375
  self._gemini3_description_prompt = os.getenv(
 
1363
 
1364
  return [f"antigravity/{m}" for m in AVAILABLE_MODELS]
1365
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1366
  async def acompletion(
1367
  self,
1368
  client: httpx.AsyncClient,
 
1392
  # Create logger
1393
  file_logger = AntigravityFileLogger(model, enable_logging)
1394
 
 
 
 
 
 
 
 
1395
  # Transform messages
1396
  system_instruction, gemini_contents = self._transform_messages(messages, model)
1397
  gemini_contents = self._fix_tool_response_grouping(gemini_contents)