Commit graph

6832 commits

Author SHA1 Message Date
Chesars
0c28b47057 fix(vertex): streaming finish_reason="stop" instead of "tool_calls" for gemini-3.1-flash-lite-preview
Models like gemini-3.1-flash-lite-preview send the final streaming chunk
with empty content (text:"") alongside finishReason:"STOP", instead of
omitting content entirely. The existing fix (PR #21577) only handled
chunks without content, so this case was missed.

Now, after processing candidates, if tool_calls were seen in earlier
chunks and a choice has finish_reason="stop", it is overridden to
"tool_calls" to match the OpenAI spec.

Fixes #22900
2026-03-17 17:47:01 -03:00
voidborne-d
ca8f5cffa0 style: apply black formatting to fix CI lint check 2026-03-17 18:52:57 +00:00
d 🔹
ef22144854 address P2 feedback: add lock docstring warning, remove redundant mock write
- Add WARNING docstring to _get_shared_session_lock() about not resetting
  the lock to None while coroutines may be in the recovery path
- Remove redundant proxy_server_module.shared_aiohttp_session assignment
  in mock_init (add_shared_session_to_data overwrites it synchronously)
2026-03-17 18:07:15 +00:00
Sameer Kankute
1b91e1656a Add support for gpt-5.4 mini and nano 2026-03-17 23:20:59 +05:30
rstar327
b0db75df1f
fix(proxy): convert max_budget to float when set from environment variable (#23855)
Fixes #23843
2026-03-17 23:05:07 +05:30
ryan-crabbe
ef9cc33ee3
Merge pull request #23822 from BerriAI/litellm_ryan_march_16
Litellm ryan's daily branch march 16
2026-03-17 10:03:01 -07:00
yuneng-jiang
a622a1fa35
Merge pull request #23827 from BerriAI/litellm_internal_dev_03_16_2026
[Infra] Merge daily dev branch with main
2026-03-17 09:58:06 -07:00
cohml
3eeb14bf1a
fix(cache): Fix Redis cluster caching (#23480)
* fix redis cluster startup_nodes check order

* add tests for redis cluster startup_nodes fix
2026-03-17 08:32:01 -07:00
d
32ecd24116 fix: address P2 review feedback - exception handling and warning accuracy
- Add try/except around _initialize_shared_aiohttp_session call to catch
  and log exceptions (instead of letting them bubble to outer handler)
- Fix warning message when re-checked session is None (was incorrectly
  logging closed session ID on a None session)
- Add debug logging to outer except handler instead of bare pass
- Add test for _initialize_shared_aiohttp_session raising exception
2026-03-17 13:09:26 +00:00
Sameer Kankute
5692db8123 fix(file_search): address latest greptile feedback
Strip internal logging ids from emulated sub-calls, dedupe included search_results by file_id, clean unused imports, and add unit coverage for dedupe behavior.

Made-with: Cursor
2026-03-17 15:33:11 +05:30
d 🔹
9e09bbc1df fix: reset _shared_session_lock in all tests for event loop isolation
Address Greptile P1 review: tests that exercise the closed-session code
path need to reset the module-level lock to avoid RuntimeError on
Python < 3.10 when asyncio.Lock is reused across different event loops.
2026-03-17 09:54:01 +00:00
Sameer Kankute
729f7d48eb fix(file_search): address greptile review on follow-up calls and tests
Include all function_call items when building emulated follow-up input and update tests to assert real emulated routing + Responses-format function tool structure.

Made-with: Cursor
2026-03-17 15:10:46 +05:30
voidborne-d
ab4fda2eeb fix: add asyncio.Lock to prevent session/connector leak on concurrent recreation
When multiple requests detect a closed shared session simultaneously,
they would each create a new aiohttp.ClientSession, leaking intermediate
sessions and their TCP connectors. Added double-checked locking pattern
with asyncio.Lock to ensure only one coroutine recreates the session.

Added concurrent recreation test case.
2026-03-17 08:08:44 +00:00
yuneng-jiang
dcbaa0512b
Merge pull request #23826 from BerriAI/litellm_yj_march_16_2026
[Infra] Merge personal dev branch with daily dev branch
2026-03-16 23:47:50 -07:00
Sameer Kankute
c735251570 feat(responses): file_search support — Phase 1 native passthrough + Phase 2 emulated fallback
Phase 1 (native passthrough):
- _decode_vector_store_ids_in_tools(): decode LiteLLM-managed unified
  vector_store_ids to provider-native IDs in file_search tools
- Split update_responses_tools_with_model_file_ids() into decode pass
  (always runs) + code_interpreter mapping pass (guarded)
- BaseResponsesAPIConfig.supports_native_file_search() → False by default;
  OpenAIResponsesAPIConfig overrides to True
- ManagedFiles.async_pre_call_hook(): batch team-level access check for
  unified vector_store_ids in file_search tools (no N+1)
- Docs: file_search section in response_api.md

Phase 2 (emulated fallback for non-native providers):
- litellm/responses/file_search/emulated_handler.py: converts file_search
  tool → function tool, intercepts tool call, runs asearch(), makes
  follow-up call, synthesizes OpenAI-format output (file_search_call +
  message + file_citation annotations)
- responses/main.py: routes to emulated handler when provider doesn't
  support file_search natively

Tests: 41 unit tests across 8 families (A-H) in test_file_search_responses.py

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 11:41:44 +05:30
Sameer Kankute
0bc609affd fix(vertex-ai): support batch cancel via Vertex API
Add Vertex batch cancellation support in LiteLLM batch APIs, route proxy cancel fallback using request provider headers, and return post-cancel batch state via retrieve to keep response shape compatible.

Made-with: Cursor
2026-03-17 11:23:47 +05:30
Ryan Crabbe
302292c805 Merge remote-tracking branch 'origin/main' into litellm_ryan_march_16 2026-03-16 22:51:45 -07:00
Awais Qureshi
186c2adb32
fix(gemini): support images in tool_results for /v1/messages routing (#23724)
* fix(gemini): support images in tool_results for /v1/messages routing

convert_to_gemini_tool_call_result() dropped images in two cases:
- data-URL strings (data:image/...;base64,...) treated as plain text
- Anthropic image blocks in list content skipped

Add detection and convert both to Gemini inline_data BlobType so image
bytes are preserved.

Fixes #23712.

* fix(gemini): support images in tool_results for /v1/messages routing

convert_to_gemini_tool_call_result() dropped images in two cases:
- data-URL strings (data:image/...;base64,...) treated as plain text
- Anthropic image blocks in list content skipped

Add detection and convert both to Gemini inline_data BlobType so image
bytes are preserved.

Fixes #23712.

* fix(gemini): support images in tool_results for /v1/messages routing

convert_to_gemini_tool_call_result() dropped images in two cases:
- data-URL strings (data:image/...;base64,...) treated as plain text
- Anthropic image blocks in list content skipped

Add detection and convert both to Gemini inline_data BlobType so image
bytes are preserved.

Fixes #23712.

* fix(fireworks): skip #transform=inline for base64 data URLs

  Closes #23583
2026-03-16 22:38:16 -07:00
Miguel Miranda Dias
e9291a97c3
fix(langsmith): avoid no running event loop during sync init (#23727)
* fix(langsmith): skip periodic flush task without event loop

* fix(langsmith): lazily start periodic flush task

* test(langsmith): tighten flush task coverage

* test(langsmith): cover lazy failure flush startup

* refactor(langsmith): keep flush startup private
2026-03-16 22:34:15 -07:00
Awais Qureshi
84b4af40fa
fix(fireworks): skip #transform=inline for base64 data URLs (#23729)
* fix(fireworks): skip #transform=inline for base64 data URLs

Closes #23583

Appending #transform=inline to a data: URL corrupted the base64 payload,
causing binascii.Error (Incorrect padding) when Fireworks AI attempted to
decode the image. Data URLs are already inlined so the fragment is a no-op
anyway — guard both the str and dict image_url branches to skip the suffix
when the URL starts with "data:".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(fireworks): skip #transform=inline for base64 data URLs

  Closes #23583

* fix(fireworks): skip #transform=inline for base64 data URLs

  Closes #23583

* fix(fireworks): skip #transform=inline for base64 data URLs

  Closes #23583

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
2026-03-16 22:30:18 -07:00
Harshit Jain
d15c2d546e
fix: Register DynamoAI guardrail initializer and enum entry (#23752)
* fix: Register DynamoAI guardrail initializer and enum entry

Fix the "Unsupported guardrail: dynamoai" error by:
1. Adding DYNAMOAI to SupportedGuardrailIntegrations enum
2. Implementing initialize_guardrail() and registries in dynamoai/__init__.py

The DynamoAI guardrail was added in PR #15920 but never properly registered
in the initialization system. The __init__.py was missing the
guardrail_initializer_registry and guardrail_class_registry dictionaries
that the dynamic discovery mechanism looks for at module load time.

Fixes #22773

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* Update litellm/proxy/guardrails/guardrail_hooks/dynamoai/__init__.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Update litellm/proxy/guardrails/guardrail_hooks/dynamoai/__init__.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* test: Add tests for DynamoAI guardrail registration

Verifies enum entry, initializer registry, class registry,
instance creation, and global registry discovery.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-16 22:24:29 -07:00
yuneng-jiang
53d96c8353 [Feature] Disable custom API key values via UI setting
Add disable_custom_api_keys UI setting that prevents users from specifying
custom key values during key generation and regeneration. When enabled, all
keys must be auto-generated, eliminating the risk of key hash collisions
in multi-tenant environments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 21:35:21 -07:00
voidborne-d
7b66c970e9 fix: auto-recover shared aiohttp session when closed (#23806)
When the shared aiohttp session closes (due to network interruption,
idle timeout, or Redis failover side effects), the proxy permanently
falls back to creating a new HTTPS connection per request, losing the
benefit of connection pooling for the entire pod lifetime.

Fix: make add_shared_session_to_data() async and recreate the session
when it is found closed, restoring connection pooling automatically.

Fixes #23806
2026-03-17 03:11:58 +00:00
yuneng-jiang
4a92db8da1 [Fix] Skip key_alias re-validation on update/regenerate when alias unchanged
When updating or regenerating a key without changing its key_alias, the
existing alias was being re-validated against current format rules. This
caused keys with legacy aliases (created before stricter validation) to
become uneditable. Now validation only runs when the alias actually changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 18:09:00 -07:00
yuneng-jiang
208740a87c [Fix] Remove duplicate get_team_object call in _validate_update_key_data
Move the non-admin team validation into the existing get_team_object call
site to avoid an extra DB round-trip. The existing call already fetches
the team for limits checking — we now add the LIT-1884 guard there when
team_obj is None for non-admin callers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 17:40:42 -07:00
yuneng-jiang
bc752fb109 [Fix] Prevent internal users from creating invalid keys via key/generate and key/update
Internal users could exploit key/generate and key/update to create unbound
keys (no user_id, no budget) or attach keys to non-existent teams. This
adds validation for non-admin callers: auto-assign user_id on generate,
reject invalid team_ids, and prevent removing user_id on update.

Closes LIT-1884

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 17:27:12 -07:00
yuneng-jiang
2ebea084c9 Merge remote-tracking branch 'origin/main' into litellm_internal_dev_03_16_2026 2026-03-16 16:33:40 -07:00
yuneng-jiang
31a677e357
Merge pull request #23792 from BerriAI/litellm_ui_logs_filter_2
[Fix] UI - Logs: Empty Filter Results Show Stale Data
2026-03-16 16:33:24 -07:00
Ryan Crabbe
67482db49d feat: fetch blog posts from docs RSS feed instead of static JSON on GitHub 2026-03-16 15:55:16 -07:00
yuneng-jiang
278c9babc6
[Infra] Merging RC Branch with Main (#23786)
* fix(test): add missing mocks for test_streamable_http_mcp_handler_mock

The test was missing mocks for extract_mcp_auth_context and set_auth_context,
causing the handler to fail silently in the except block instead of reaching
session_manager.handle_request. This mirrors the fix already applied to the
sibling test_sse_mcp_handler_mock.

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* fix(ci): route OpenAI models through chat completions in pass-through tests

The test_anthropic_messages_openai_model_streaming_cost_injection test fails
because the OpenAI Responses API returns 400 for requests routed through the
Anthropic Messages endpoint. Setting LITELLM_USE_CHAT_COMPLETIONS_URL_FOR_ANTHROPIC_MESSAGES=true
routes OpenAI models through the stable chat completions path instead.
Cost injection still works since it happens at the proxy level.

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* fix(ci): fix assemblyai custom auth and router wildcard test flakiness

1. custom_auth_basic.py: Add user_role='proxy_admin' so the custom auth
   user can access management endpoints like /key/generate. The test
   test_assemblyai_transcribe_with_non_admin_key was hidden behind an
   earlier -x failure and was never reached before.

2. test_router_utils.py: Add flaky(retries=3) and increase sleep from 1s
   to 2s for test_router_get_model_group_usage_wildcard_routes. The async
   callback needs time to write usage to cache, and 1s is insufficient on
   slower CI hardware.

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* ci: retrigger CI pipeline

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* fix(mypy): use LitellmUserRoles enum instead of raw string in custom_auth_basic

Fixes mypy error: Argument 'user_role' has incompatible type 'str'; expected 'LitellmUserRoles | None'

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* fix: don't close HTTP/SDK clients on LLMClientCache eviction (#22926)

* fix: don't close HTTP/SDK clients on LLMClientCache eviction

Removing the _remove_key override that eagerly called aclose()/close()
on evicted clients. Evicted clients may still be held by in-flight
streaming requests; closing them causes:

  RuntimeError: Cannot send a request, as the client has been closed.

This is a regression from commit fb72979432. Clients that are no longer
referenced will be garbage-collected naturally. Explicit shutdown cleanup
happens via close_litellm_async_clients().

Fixes production crashes after the 1-hour cache TTL expires.

* test: update LLMClientCache unit tests for no-close-on-eviction behavior

Flip the assertions: evicted clients must NOT be closed. Replace
test_remove_key_closes_async_client → test_remove_key_does_not_close_async_client
and equivalents for sync/eviction paths.

Add test_remove_key_removes_plain_values for non-client cache entries.
Remove test_background_tasks_cleaned_up_after_completion (no more _background_tasks).
Remove test_remove_key_no_event_loop variant that depended on old behavior.

* test: add e2e tests for OpenAI SDK client surviving cache eviction

Add two new e2e tests using real AsyncOpenAI clients:
- test_evicted_openai_sdk_client_stays_usable: verifies size-based eviction
  doesn't close the client
- test_ttl_expired_openai_sdk_client_stays_usable: verifies TTL expiry
  eviction doesn't close the client

Both tests sleep after eviction so any create_task()-based close would
have time to run, making the regression detectable.

Also expand the module docstring to explain why the sleep is required.

* docs(AGENTS.md): add rule — never close HTTP/SDK clients on cache eviction

* docs(CLAUDE.md): add HTTP client cache safety guideline

* [Fix] Install bsdmainutils for column command in security scans

The security_scans.sh script uses `column` to format vulnerability
output, but the package wasn't installed in the CI environment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: handle string callback values in prometheus multiproc setup

When callbacks are configured as a plain string (e.g., `callbacks: "my_callback"`)
instead of a list, the proxy crashes on startup with:
  TypeError: can only concatenate str (not "list") to str

Normalize each callback setting to a list before concatenating.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* bump: version 1.82.2 → 1.82.3

* fix(test): update test_startup_fails_when_db_setup_fails for opt-in enforcement

The --enforce_prisma_migration_check flag is now required to trigger
sys.exit(1) on DB migration failure, after #23675 flipped the default
behavior to warn-and-continue.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(cost_calculator): use model name for per-request custom pricing when router_model_id has no pricing

When custom pricing is passed as per-request kwargs (input_cost_per_token/output_cost_per_token),
completion() registers pricing under the model name, but _select_model_name_for_cost_calc was
selecting the router deployment hash (which has no pricing data), causing response_cost to be 0.0.

Now checks whether the router_model_id entry actually has pricing before preferring it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 15:32:20 -07:00
yuneng-jiang
bc810f99e4 [Fix] Privilege escalation: restrict /key/block, /key/unblock, and max_budget updates to admins
Non-admin users (INTERNAL_USER) could call /key/block and /key/unblock on
arbitrary keys, and modify max_budget on their own keys via /key/update.
These endpoints are now restricted to proxy admins, team admins, or org admins.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 14:46:50 -07:00
joereyna
0c1739390b fix: remove skip decorators from m2m tests now that oauth2_flow is set 2026-03-16 13:17:27 -07:00
michelligabriele
b0c317e6d0 test: use __file__-relative sys.path for stable test imports
Address Greptile review — resolve sys.path relative to the test file
location instead of the process working directory.
2026-03-16 21:07:07 +01:00
michelligabriele
23b69eea62 fix(proxy): model-level guardrails not executing for non-streaming post_call
Model-level guardrails (litellm_params.guardrails on a deployment) were
only merged into request metadata in the streaming post_call path
(async_post_call_streaming_hook) but not in the non-streaming path
(post_call_success_hook). This caused should_run_guardrail to skip the
guardrail because the guardrail name was never added to metadata.guardrails.

Add the same _check_and_merge_model_level_guardrails call to
post_call_success_hook before the guardrail callback loop, mirroring the
streaming path.

Fixes model-level guardrails silently not firing for non-streaming
post_call requests.
2026-03-16 20:55:22 +01:00
ryan-crabbe
4f2fe3378f
Merge pull request #23666 from BerriAI/litellm_fix-default-user-perms-not-synced-with-ui
fix: align DefaultInternalUserParams Pydantic default with runtime fallback
2026-03-16 11:58:30 -07:00
Sameer Kankute
3dccdde9c8
Merge pull request #23686 from BerriAI/litellm_oss_staging_03_14_2026
Litellm oss staging 03 14 2026
2026-03-16 20:00:17 +05:30
Sameer Kankute
71dfd0115c
Merge pull request #23737 from BerriAI/litellm_create-character-endpoint-fixes
[Feat] Add create character endpoints and other new videos Endpoints
2026-03-16 19:53:35 +05:30
Sameer Kankute
ee24abe86e fix(test): skip new video character endpoints in Azure SDK initialization test
Add avideo_create_character, avideo_get_character, avideo_edit, and avideo_extension
to the skip condition since Azure video calls don't use initialize_azure_sdk_client.

Tests now properly skip with expected behavior instead of failing:
- test_ensure_initialize_azure_sdk_client_always_used[avideo_create_character] ✓
- test_ensure_initialize_azure_sdk_client_always_used[avideo_get_character] ✓
- test_ensure_initialize_azure_sdk_client_always_used[avideo_edit] ✓
- test_ensure_initialize_azure_sdk_client_always_used[avideo_extension] ✓

Made-with: Cursor
2026-03-16 19:45:57 +05:30
Sameer Kankute
b796ee9f03
Merge pull request #23530 from Sameerlite/litellm_preserve-final-streaming-attributes
fix(streaming): preserve custom attributes on final stream chunk
2026-03-16 19:12:41 +05:30
Sameer Kankute
0bbdd2a249
Merge pull request #23715 from BerriAI/litellm_anthropic_beta_header_order
Refactor: Filtering beta header after transformation
2026-03-16 19:07:08 +05:30
Sameer Kankute
ab377f396e
Merge pull request #23718 from BerriAI/litellm_fix_vertex_ai_batch
Fix: Vertex ai Batch Output File Download Fails with 500
2026-03-16 19:05:49 +05:30
Sameer Kankute
9beec825d4
Merge branch 'main' into litellm_create-character-endpoint-fixes 2026-03-16 17:58:16 +05:30
Sameer Kankute
14a691ffd5 Add new videos transformation 2026-03-16 17:56:21 +05:30
yuneng-jiang
8f56ddb9c6 Merge remote main into litellm_ci_optimize
Resolved conflict in test_claude_agent_sdk.py by keeping main's additions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 00:50:22 -07:00
Sameer Kankute
22b333cae6 Fix downloading vertex ai files 2026-03-16 12:08:06 +05:30
Krish Dholakia
ca4329aeb9
Root cause fix - migrate all logging update to use 1 function - for centralized kwarg updates (#23659)
* fix: Fixes https://github.com/BerriAI/litellm/issues/23185

* fix(responses/main.py): ensure litellm metadata custom cost works

* refactor: move all logging updates to a common function, to have just 1 place to update logging kwarg updates
2026-03-15 23:21:01 -07:00
Sameer Kankute
1a8f8c6d52 Refactor: Filtering beta header after transformation 2026-03-16 10:47:15 +05:30
yuneng-jiang
40edb16fb9 Fix test isolation: run eager tiktoken tests in subprocesses
The eager tiktoken tests were clearing all litellm modules from
sys.modules and re-importing, creating new module objects with different
class identities. This broke unittest.mock.patch for all subsequent
tests on the same xdist worker. Running these tests in subprocesses
provides perfect isolation.

Fixes: test_metadata_passed_to_custom_callback_codex_models,
test_oidc_github_success, test_oidc_google_cached,
test_oidc_google_failure,
test_encrypted_content_affinity_bypasses_rpm_limits, and 5 others.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 17:32:31 -07:00
yuneng-jiang
a81a1968ed Fix test isolation: clear litellm.callbacks and model_fallbacks between tests
The isolate_litellm_state conftest fixture saved/restored litellm.callbacks
but never cleared it before each test, unlike the other callback lists. It
also didn't handle litellm.model_fallbacks. Leaked callbacks and fallback
config caused mocked tests to route through Router/fallback paths, hitting
real APIs with mock keys.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 16:43:15 -07:00
yuneng-jiang
1092c17468 Fix flaky encrypted_content_affinity tests: mock at handler level
The 4 integration tests were flaky in CI because the AsyncHTTPHandler.post
mock was bypassed when aiohttp transport is used. Mock at the higher
BaseLLMHTTPHandler.async_response_api_handler level instead, which
bypasses the HTTP layer entirely while still exercising router deployment
selection, pre-call checks, and response post-processing (item ID rewriting).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 15:39:25 -07:00