Commit graph

105 commits

Author SHA1 Message Date
yassin
6d5a3ab42c merge: litellm_internal_staging into litellm_headroom_ccr_streaming_responses
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-03 00:24:17 +00:00
mateo-berri
d7ee215c57 fix(responses): keep namespace tools intact when a guardrail returns them unchanged
Any pre_call guardrail on /v1/responses flattened Codex namespace tools
into ns__member functions and wrote the flattened list back to the
request, so the model called mcp__server__tool with no namespace and
Codex rejected the call as unsupported.

The handler now keeps the client's original tools, hands the guardrail a
deep copy of the flattened ones, and rebuilds data["tools"] by matching
the guardrail's output to the originals by type and name. Unchanged
tools go back as the original objects, a dropped or edited namespace
member changes only that member, and tools the guardrail injects are
still appended.

Fixes #39183
2026-09-02 11:32:04 -07:00
mateo-berri
4a5d0b8163 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_headroom_ccr_streaming_responses
# Conflicts:
#	litellm/llms/openai/responses/guardrail_translation/handler.py
#	tests/test_litellm/llms/openai/responses/test_openai_responses_guardrail_handler.py
2026-09-01 22:25:59 -07:00
mateo-berri
98ea5eaab4 fix(responses): correlate streamed tool call events on normalized item ids 2026-09-01 12:08:22 -07:00
mateo-berri
c01ef712a2 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_headroom_ccr_streaming_responses
# Conflicts:
#	tests/test_litellm/responses/litellm_completion_transformation/test_streaming_iterator_transformation.py
2026-09-01 11:27:03 -07:00
mateo-berri
ab2c9aed0f fix(responses): normalize tool call id shapes across the anthropic bridge and openai replay
The chat-completions bridge emitted Responses output items whose item ids
were raw Anthropic tool ids (toolu_/srvtoolu_), which OpenAI rejects on
replay with "Expected an ID that begins with 'fc'", breaking router
fallback conversations from gpt-5 to claude models.

Four fixes, composable and independently useful:
- emission: bridge output items get fc_/ctc_-prefixed item ids while
  call_id stays raw so tool_result pairing keeps working (streaming and
  non-streaming share the same helpers)
- openai replay: request transformation drops tool call item ids that do
  not match OpenAI's own shapes instead of forwarding them, gated to
  OpenAI and Azure, since the API accepts the items with no id at all
- anthropic replay: a replayed srvtoolu_ call whose paired server tool
  result is unavailable degrades to a plain client tool_use instead of a
  dangling server_tool_use that 400s the client's tool_result
- tool-only turns no longer emit a message output item with output_text
  text null, matching native OpenAI output
2026-09-01 11:12:24 -07:00
Mateo Wang
30bf592aaf
Merge pull request #35417 from BerriAI/litellm_fix_responses_bridge_tool_call_arguments_json
fix(responses): json-encode object tool call arguments in the chat completions bridge
2026-09-01 10:08:12 -07:00
mateo-berri
c9908ffabb fix(responses): count input_file tokens instead of silently dropping the file
The Responses-to-chat transform dropped the filename OpenAI requires next to
file_data, so a request carrying an inline PDF counted 13 tokens instead of 36
and a real completion through the chat bridge got a 400.
2026-08-31 13:17:43 -07:00
milan
9125a5b7a0 fix(responses): json-encode object tool call arguments in the chat completions bridge
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-31 18:43:36 +00:00
mateo-berri
6bd3699d43 fix(responses): keep guardrailed input items and bridge stream usage intact
- _write_back_structured_messages now patches only the rewritten rows back
  into the original input items, so reasoning items (encrypted_content),
  function_call ids, and web_search_call items survive a guardrail rewrite
  verbatim; rewrites that cannot be row-mapped fall back to the previous
  full conversion
- the responses bridge stream snapshot restores usage hidden in
  _hidden_params when stream_options is unset, so converted fake streams
  report real input_tokens instead of 0
2026-08-29 16:39:14 -07:00
yucheng-berri
ba8d8b6e14
fix(logging): redact tool call arguments to valid JSON and preserve null content (#38182)
* fix(logging): redact tool call arguments to valid JSON and preserve null content

Resolves LIT-6102

* refactor(logging): centralize redacted tool-call arguments constant and satisfy test-quality gate

* fix(responses): drop Final annotations on loop-assigned locals flagged by basedpyright

* fix(responses): skip custom tool calls in redacted-arguments normalizer

* fix(logging): keep the redaction sentinel in stored tool-call arguments and preserve null output text
2026-08-25 16:38:18 -07:00
Mateo Wang
ddf4c8e58b
Merge pull request #37953 from BerriAI/litellm_fix_24985_thinking_roundtrip
fix(anthropic): round-trip thinking blocks to OpenAI backends on /v1/messages
2026-08-24 10:57:23 -07:00
mateo-berri
71d6f5f0be Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_fix_24985_thinking_roundtrip 2026-08-22 15:14:16 -07:00
mateo-berri
d6d25ed310 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_fix_26167_bridged_session_lookup 2026-08-22 15:10:26 -07:00
Mateo Wang
11cbe472ac
Merge pull request #36355 from harryzhou2000/fix/responses-bridge-preserve-reasoning-input-items
fix(responses-bridge): preserve reasoning input items and signed thinking blocks
2026-08-22 15:07:02 -07:00
mateo-berri
5317a5ab50 test: cover the reverse bridge on an assistant message that precedes its function_call 2026-08-22 14:53:18 -07:00
mateo-berri
19a3fe1b66 fix(responses-bridge): fall back to summary text when content carries none
An empty content list, or one holding only opaque blocks, still lets the
provider-bound branch replay the summary text. The inspection path treated
any non-None content as final, so that replayed text stayed invisible to
guardrails and token counting.
2026-08-22 14:51:38 -07:00
mateo-berri
d2b5034fea test(responses): fold the bridged streaming regressions into the mapped test file 2026-08-22 14:33:23 -07:00
mateo-berri
3d69ec3603 fix(responses-bridge): keep summary-only reasoning text scannable
A reasoning input item that carries only summary text is replayed to the
provider as reasoning_content, so inspection-only callers must see that
text too. They used to fall through to the generic content branch, which
reads content and drops a summary-only item, leaving guardrails and token
counters blind to text the model still receives.
2026-08-22 14:30:52 -07:00
mateo-berri
9d22acab11 fix(responses): skip the session lookup retry when spend logs are off 2026-08-22 14:22:10 -07:00
mateo-berri
6a55683cd0 refactor: drop the unused response argument from the image item extractor
The image generation item ID no longer comes from the chat completion
response, so the extractor does not need it.
2026-08-22 14:22:08 -07:00
mateo-berri
f89a3693ba fix(responses): resolve previous_response_id for a just-written turn
The session lookup reads spend logs straight out of the database, so a
follow-up sent seconds after the turn it chains off found nothing while the
row was still queued in the worker that served it, and the conversation was
dropped without an error. Responses calls now ask the spend-log writer to
flush on its next pass instead of waiting out its poll interval, and the
lookup gives a just-finished turn a short second chance.

Replaying a session also accepted `input` only as a string or a single dict,
so the standard list shape dropped every user turn and left the model with
assistant messages alone.
2026-08-22 11:46:24 -07:00
mateo-berri
6d2b7db2fb fix: keep one reasoning item id across a bridged stream
Write the fallback reasoning item id back to the cache so the
reasoning-done path and the completed snapshot cannot drift apart, and
cover the shared delta id and the snapshot alignment with tests.
2026-08-22 11:42:59 -07:00
Mateo Wang
ae25da3d54 fix(responses-bridge): keep reasoning text visible to inspection-only callers
Guardrails, token counting and rate limiting share the input transform with
the provider path, so moving reasoning onto reasoning_content hid it from
them. Provider-bound callers opt in with replay_reasoning.
2026-08-22 11:39:10 -07:00
mateo-berri
05ee5756e7 refactor(responses): rebuild the streaming snapshot output instead of mutating items
Align the response.completed item IDs by copying each output item rather than
writing to it in place, and move the regression cases into the existing
completion-response and image-generation test modules.
2026-08-22 11:17:02 -07:00
mateo-berri
70e4273ba1 fix(responses): make previous_response_id resolve on the bridged path
Streaming /v1/responses over the completion bridge minted a fresh resp_{uuid4}
for every response, while spend tracking stored the inner chat completion id as
request_id. The session lookup queries on request_id, so a follow-up sent with
that response id matched no rows and the prior conversation was silently
dropped. The iterator now pulls the first upstream chunk before emitting
response.created, so created, in_progress and completed all carry the same
encoded chat completion id.

Two more ways the same history went missing:

- The session lookup only read spend logs already written to the DB, so a
  follow-up sent inside the batch writer's window found nothing. It now also
  reads the rows still queued in memory.
- Input was only accepted as a string or a single dict, so the list shape the
  Responses API actually sends dropped every user turn from the reconstructed
  history.
2026-08-22 11:12:17 -07:00
mateo-berri
a7afe986e3 fix(responses): replay signed thinking blocks through the completion bridge
encrypted_content on a reasoning input item is written by LiteLLM's own
_encode_thinking_blocks as a JSON array of Anthropic/Bedrock thinking
blocks, so decode it back and replay the signed blocks on the assistant
message instead of dropping them. Providers without a native
ResponsesAPIConfig now keep the verifiable chain-of-thought across turns,
and prior-turn reasoning stops reaching the provider as visible
assistant text.
2026-08-22 10:51:40 -07:00
mateo-berri
005f04edb6 fix(responses): mint Responses API item IDs in the completion bridge
The Chat Completions -> Responses bridge stamped the upstream chatcmpl-*
ID onto message output items, so replaying bridged history into native
OpenAI Responses failed with "Expected an ID that begins with 'msg'".
Image generation calls were minted as chatcmpl-*_img_N instead of ig_*,
and reasoning items used a salted hash() that is not stable across
processes.

Streaming minted msg_* for its incremental events but rebuilt the
response.completed snapshot through the same broken transform, so the
snapshot contradicted the events it had just sent and streaming clients
hit the same 400. The snapshot now reuses the IDs already streamed.

Fixes #27333
2026-08-22 10:39:31 -07:00
mateo-berri
840b0318bf Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_lit6007_pr36355 2026-08-22 10:24:37 -07:00
yuneng-jiang
6a0d03914c
test: drop the cwd-relative sys.path.insert calls from the test suite (#37802)
* test: drop the cwd-relative sys.path.insert calls from the test suite

TQ003 stands at 1,077 across 1,058 files, and 1,015 of them are the same shape:
sys.path.insert(0, os.path.abspath("../..")) and its deeper siblings. The
argument resolves against the working directory rather than the file, so from
the repo root, where every job runs pytest, it inserts the directory two levels
above the checkout. It has never pointed at litellm. The package is installed
into the environment anyway, which is what actually makes the import work, and
what the rule's message has said all along.

Removing them leaves 1,634 imports of sys and os with no remaining reference,
and those go too, except where another test module imports the name back out of
the file. The rest of TQ003 is 62 call sites that resolve against __file__ or a
variable, which are a different question and are left alone.

Collection is identical either way: 45,871 tests and the same 51 pre-existing
collection errors before and after, and ruff reports no new undefined name.

* test: drop the duplicate imports the sys.path sweep exposed to F811

* test(pre-call-utils): restore the os import the new bedrock tests need
2026-08-22 09:25:58 -07:00
ryan-crabbe-berri
e9d40a8f73 test: enforce F811 so a duplicate definition cannot silently replace the first
A name bound twice keeps only the second binding. In `tests/` that is nearly
always a repeated import, harmless but misleading, and the same rule is what
catches the cases that are not harmless: a local that shadows an import the
module still calls, and a second `def test_x` that quietly replaces the first.

311 of the 344 sites were repeated imports and came out with ruff's own fix.
The remaining 33 needed a decision. Four modules imported a name they never
used because a local definition below already shadowed it. Two comprehensions
bound `call` over `unittest.mock.call`, which those modules import and use.
One test rebound the two module handles its nested reload closure had captured.
One class attribute shadowed an unused `status` import.

The load-test fixtures move to a conftest, which is how pytest is meant to share
them, so the test module no longer imports three fixture names it never calls.
The nine `prisma_client` parameters keep a narrow `noqa`: pytest resolves that
fixture by name before the body runs, so the parameter never shadows anything.
2026-08-21 12:06:19 -07:00
mateo-berri
710ef81a80 fix(usage): keep responses usage SDK-parseable and complete streamed reasoning splits
An unknown reasoning split now falls back to reasoning_tokens=0 in the
chat-to-responses usage translation, since the OpenAI SDK requires
output_tokens_details with an int reasoning_tokens, and the streaming
chunk builder caps the tokenized reasoning estimate at completion_tokens
and fills text_tokens with the remainder
2026-08-19 14:57:19 -07:00
mateo-berri
46a4eda19e Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_fix_bedrock_adaptive_thinking_token_accounting
# Conflicts:
#	litellm/llms/bedrock/chat/invoke_handler.py
#	litellm/responses/litellm_completion_transformation/transformation.py
#	tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py
#	tests/test_litellm/responses/litellm_completion_transformation/test_reasoning_content_transformation.py
2026-08-19 14:10:53 -07:00
HarryZhou
3a77556dc1 fix(responses-bridge): preserve reasoning merge order when assistant already has reasoning_content 2026-08-19 12:57:43 +08:00
HarryZhou
b6ee13803d fix(responses-bridge): preserve reasoning input items as reasoning_content 2026-08-19 12:57:42 +08:00
Emerson Gomes
4ea5749642
feat(azure-ai): add Grok 4.3 model metadata (#27932)
* Add Azure AI Grok 4.3 metadata

* Address Azure Grok 4.3 test feedback

* Drop empty tool choice in responses bridge

* style(azure-ai): update Grok metadata tests
2026-08-13 17:25:17 -07:00
yuneng-jiang
16ce5031f0
Merge branch 'litellm_internal_staging' into litellm_/remove-no-guard-mirror-tests 2026-08-12 10:38:24 -07:00
Mateo Wang
cfcd0cda8a fix(responses): leave namespace unset on non-namespace tool calls 2026-08-12 00:28:15 -07:00
Mateo Wang
a64a83bf36 fix(responses): keep custom_tool_call echoes on their advertised short name 2026-08-12 00:19:08 -07:00
Mateo Wang
ca14e52b08 fix(responses): requalify echoed namespace tool calls with their flattened name 2026-08-12 00:01:34 -07:00
Mateo Wang
397fcd0e6b fix(responses): serialize flattened namespace tools and keep tool results adjacent to tool_calls 2026-08-11 23:41:44 -07:00
Daniel Cadenas
08d4a39f23
fix(responses): harden namespace tool mapping 2026-08-06 21:25:57 -03:00
Daniel Cadenas
bd1478e4ad
fix(responses): preserve Codex namespace tool calls 2026-08-06 20:53:05 -03:00
Devin AI
aadfa89ff6 Merge branch 'litellm_internal_staging' into litellm_fix_bedrock_adaptive_thinking_token_accounting
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-05 21:13:36 +00:00
Devin AI
af2246c5b8 fix(anthropic,bedrock): report provider thinking tokens instead of classifying them as text
Resolves LIT-5244

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-05 20:47:05 +00:00
mateo-berri
7288247682 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_fix_openai_cache_token_details_loss
# Conflicts:
#	litellm/litellm_core_utils/llm_cost_calc/utils.py
#	litellm/litellm_core_utils/streaming_chunk_builder_utils.py
#	litellm/litellm_core_utils/streaming_handler.py
#	tests/test_litellm/litellm_core_utils/test_streaming_chunk_builder_utils.py
2026-08-05 01:23:54 -07:00
Tin Chi Lo
b79b01e38a fix(proxy): translate custom tool grammar formats and tool_choice across API surfaces
Cursor's ApplyPatch is a grammar-constrained custom tool; the Responses
surface carries the grammar flat while chat completions wraps the same
fields in a grammar object, so the nested envelope from the previous
commit still 400d at OpenAI (tools[N].custom.format.grammar). Adds a
shared flat to nested format helper pair in prompt_templates/common_utils
used by the cursor messages arm and the chat-to-responses bridge, nests
flat Responses-style tool_choice objects on the cursor arm, flattens chat
custom tool_choice on the chat-to-responses bridge, and maps custom
tool_choice to function tool_choice on the responses-to-chat bridge to
match that bridge's custom-to-function tool downgrade
2026-08-01 11:26:09 -07:00
Devin AI
c429a0e4a7 fix(cost_tracking): keep OpenAI prompt cache token details through usage reassembly 2026-07-27 18:36:26 +00:00
Yuneng Jiang
e4a0475263
test: remove four mirror test files that exercise none of their module
A second mutation batch scored the previously unmapped mirror files on
current staging. These four generate mutants for the module they are
named after, yet no test in the file executes any of them; their
test-context coverage lands on generic shared machinery or, for the
guardrail translation handler remainder, on no litellm line at all.
Eight sibling findings that do exercise a different real module are
kept for retargeting instead of removal.
2026-07-25 10:57:19 -07:00
Mateo Wang
ee6e8077ae
fix(responses): preserve reasoning_tokens through chat->responses usage translation (#32837)
* fix(responses): preserve reasoning_tokens through chat->responses usage translation

Remove the unconditional else-branch that wrote reasoning_tokens=0 whenever
completion_tokens_details.reasoning_tokens was None or absent. Also change
OutputTokensDetails.reasoning_tokens from int=0 to Optional[int]=None so that
re-instantiation without explicit reasoning_tokens no longer silently zeroes out
the field, and remove the same hardcoded zero from the mock_responses_api_response
initializer.

* test(responses): update assertions to match Optional[int] reasoning_tokens default

* fix(responses): preserve explicit reasoning_tokens=0 in usage translation

Align the reasoning_tokens guard with the is-not-None guards used for
text_tokens and image_tokens: a provider-reported zero passes through
while an absent value stays omitted.

---------

Co-authored-by: Deepanshu <deepanshu.lulla@alpha-sense.com>
2026-07-10 20:15:49 -07:00