mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-23 05:34:41 +00:00
fix(types): strip is_error in the existing cache_control pass for the pyright ceiling
The previous in-place strip left two basedpyright breaches over the merge-base ceiling (base8683f1418e): the bare second `filter_value_from_dict(message, "is_error")` call added a reportArgumentType (AllMessageValues is not assignable to the bare-dict parameter), and `message.get("role")` on the AllMessageValues union added two reportUnknownMemberType. Fold is_error into the existing cache_control pass via a new `*extra_keys` parameter on filter_value_from_dict (no new call site, so no new diagnostic); the unconditional strip is behavior-equivalent because is_error only ever exists as the litellm-internal carrier on tool messages, which real OpenAI would reject as an unknown field anyway. The adapter side reads is_error through a membership guard instead of a second unknown-typed `.get`. Verification: type_check_gate OK (every rule within ceiling, base8683f1418e), type_discipline_gate OK, targeted per-file basedpyright delta vs merge-base zero on all four touched files, adapter + gpt transformation test suites 316 passed. Generated-by: GLM-5.3-Flash (ZCode)
This commit is contained in:
parent
016348c6c2
commit
328866c020
3 changed files with 11 additions and 14 deletions
|
|
@ -1807,11 +1807,11 @@ def strip_litellm_internal_message_fields(message: AllMessageValues) -> AllMessa
|
|||
)
|
||||
|
||||
|
||||
def filter_value_from_dict(dictionary: dict, key: str, depth: int = 0) -> Any:
|
||||
def filter_value_from_dict(dictionary: dict, key: str, *extra_keys: str, depth: int = 0) -> Any:
|
||||
"""
|
||||
Filters a value from a dictionary
|
||||
|
||||
Goes through the nested dict and removes the key if it exists
|
||||
Goes through the nested dict and removes the key (plus any extra keys) if it exists
|
||||
"""
|
||||
from litellm.constants import DEFAULT_MAX_RECURSE_DEPTH
|
||||
|
||||
|
|
@ -1822,14 +1822,14 @@ def filter_value_from_dict(dictionary: dict, key: str, depth: int = 0) -> Any:
|
|||
keys: Final = list(dictionary.keys())
|
||||
for k in keys:
|
||||
v = dictionary[k]
|
||||
if k == key:
|
||||
if k == key or k in extra_keys:
|
||||
del dictionary[k]
|
||||
elif isinstance(v, dict):
|
||||
filter_value_from_dict(v, key, depth + 1)
|
||||
filter_value_from_dict(v, key, *extra_keys, depth=depth + 1)
|
||||
elif isinstance(v, list):
|
||||
for item in v:
|
||||
if isinstance(item, dict):
|
||||
filter_value_from_dict(item, key, depth + 1)
|
||||
filter_value_from_dict(item, key, *extra_keys, depth=depth + 1)
|
||||
return dictionary
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -529,7 +529,7 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
role="tool",
|
||||
tool_call_id=content.get("tool_use_id", ""),
|
||||
content=self._tool_result_content(content.get("content")),
|
||||
**({"is_error": True} if content.get("is_error") is True else {}),
|
||||
**({"is_error": True} if "is_error" in content and content["is_error"] is True else {}),
|
||||
)
|
||||
self._add_cache_control_if_applicable(content, tool_result, model)
|
||||
tool_message_list.append(tool_result)
|
||||
|
|
|
|||
|
|
@ -410,17 +410,14 @@ class OpenAIGPTConfig(BaseLLMModelInfo, BaseConfig):
|
|||
from litellm.types.llms.openai import ChatCompletionToolParam
|
||||
|
||||
for i, message in enumerate(messages):
|
||||
# is_error: litellm's anthropic adapter carries tool_result.is_error
|
||||
# on the intermediate tool message so error-aware translations can
|
||||
# restore it; real OpenAI has no such field (#44979). Stripped in
|
||||
# the same in-place pass as cache_control.
|
||||
messages[i] = cast(
|
||||
AllMessageValues,
|
||||
filter_value_from_dict(message, "cache_control"),
|
||||
filter_value_from_dict(message, "cache_control", "is_error"),
|
||||
)
|
||||
if message.get("role") == "tool":
|
||||
# litellm's anthropic adapter carries tool_result.is_error on
|
||||
# the intermediate tool message so error-aware translations
|
||||
# can restore it; real OpenAI has no such field (#44979).
|
||||
# filter_value_from_dict mutates the message dict in place, so
|
||||
# the list slot keeps referencing the updated message.
|
||||
filter_value_from_dict(message, "is_error")
|
||||
if tools is not None:
|
||||
for i, tool in enumerate(tools):
|
||||
tools[i] = cast(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue