litellm/tests/unit/proxy/hooks
devin-ai-integration[bot] 7a7d27c550
fix(guardrails): run the end-of-stream post_call scan when the client disconnects mid-stream (#43839)
* fix(guardrails): run end-of-stream post_call scan when the client disconnects mid-stream

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): close the guardrail stream chain in async_data_generator on client disconnect

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): leave the raw upstream response to the shielded finalizer on client disconnect

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): keep disconnect cleanup going when a streaming callback cleanup raises

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(proxy): assert the refund through a recorder instead of the mock

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(guardrails): inspect tool calls released before a disconnect under incremental_diff and record a failed scan marker

The incremental_diff transform stream now scans tool calls it already released when the client disconnects, and a disconnect scan whose translation raises after the guardrail recorded success also records guardrail_failed_to_respond

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(guardrails): pin that a text-only disconnect scan is not handed a tool_calls finish

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(guardrails): cover disconnect scans on every streaming endpoint and client, plus outage, worker-kill and cache-hit cells

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(guardrails): prove the cache-hit twin is served from the cache

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(guardrails): type the disconnect-close streams so basedpyright stops reporting unknown arguments

* fix(guardrails): give the guardrail metadata cast a reason so the type discipline gate accepts it

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(guardrails): scan released Messages and Responses tool calls on disconnect

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* style(guardrails): format the disconnect scan unit tests

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* chore(guardrails): drop mutable-ok markers that no longer suppress a rule

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(guardrails): scan released Responses output after a finished item and end only in-flight Chat choices

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(guardrails): type the disconnect scan test helpers

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* refactor(guardrails): type request_data in the disconnect scan helpers

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(guardrails): type request_data in the disconnect scan test doubles

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(guardrails): pin that chat streams with no tool call in flight end as released

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(guardrails): scan only released chunks on disconnect and skip it once a block owns the verdict

The disconnect scan now uses the chunks actually yielded to the client, copies them before scanning,
skips when a mid-stream block or HTTP error already settled the verdict, and the iterator wrapper
only closes hooks that are async generators so plain async iterator hooks keep working

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(guardrails): pin that a delivered guardrail error or final chunk settles the disconnect verdict

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(guardrails): close any hook iterator that exposes aclose when the stream ends early

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): accept a synchronous aclose on custom streaming hook iterators

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): swallow callback aclose errors at end of stream

A custom callback whose async_post_call_streaming_iterator_hook returns a
non-generator async iterator with a raising aclose() failed the finished
stream: content plus usage reached the client and then the stream surfaced
an error SSE with no [DONE], or aborted a post_call pipeline's buffering
loop into a 500 with an empty body. Wrap the aclose invocation in
_wrap_streaming_iterator_with_enrichment in try/except and log a warning
naming the callback and the cleanup error, matching close_guarded_stream
and _close_guarded_layers. Iteration-time hook exceptions still propagate.

* fix(proxy): log only the error type when a callback aclose raises

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: yucheng <yucheng@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-05 01:44:43 -07:00
..
litellm_skills test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
__init__.py ci: move tests/proxy_unit_tests to tests/unit/proxy and run the proxy-db shards from litellm-tests (#42903) 2026-09-24 22:59:11 +00:00
test_async_post_call_streaming_iterator_hook.py fix(guardrails): run the end-of-stream post_call scan when the client disconnects mid-stream (#43839) 2026-10-05 01:44:43 -07:00
test_autorouter_baseline_cache.py chore(lint): remove the LIT002 mutable-construction rule (#43971) 2026-10-01 12:24:02 -07:00
test_banned_keyword_list.py ci: move tests/proxy_unit_tests to tests/unit/proxy and run the proxy-db shards from litellm-tests (#42903) 2026-09-24 22:59:11 +00:00
test_batch_enqueued_tokens.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_batch_file_validation.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_batch_rate_limiter.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_dynamic_rate_limiter.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_dynamic_rate_limiter_v3.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_image_generation_guardrails.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_key_management_event_hooks.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_max_budget_per_session_limiter.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_max_iterations_limiter.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_model_max_budget_limiter.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_parallel_request_limiter.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_parallel_request_limiter_v3.py feat(mcp): hand listed-tool description and input schema to pre-call hooks per caller (#41162) 2026-10-04 00:53:58 -07:00
test_post_call_failure_hook_integration.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_post_call_response_headers_hook.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_post_call_streaming_hook_integration.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_post_call_success_hook_integration.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_prompt_cache_observer.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_prompt_injection_detection.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_proxy_hooks_init.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_proxy_rate_limit_provider_field.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_proxy_track_cost_callback.py fix(otel): name postgres service spans by operation and table (#44240) 2026-10-03 09:20:28 -07:00
test_rate_limiter_toctou.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_send_invite_email.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_sensitive_data_routing.py fix(otel): nest cache spans under their operation and name service spans by purpose (#44150) 2026-10-03 09:20:27 -07:00
test_tpm_concurrent.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_unit_test_max_model_budget_limiter.py fix(router): await budget redis pipeline before sync reads (internal copy of #32618) (#43125) 2026-09-24 22:27:13 -07:00
test_user_management_event_hooks.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00