Skip to content

feat(containers): Azure routing, managed container IDs, delete response parsing - #25287

Merged
krrish-berri-2 merged 7 commits into
litellm_internal_staging_04_11_2026from
litellm_azure-containers-delete-response-and-routing
Apr 11, 2026
Merged

feat(containers): Azure routing, managed container IDs, delete response parsing#25287
krrish-berri-2 merged 7 commits into
litellm_internal_staging_04_11_2026from
litellm_azure-containers-delete-response-and-routing

Conversation

@Sameerlite

@Sameerlite Sameerlite commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add AzureContainerConfig and register it for Azure / Azure Text in ProviderConfigManager.
  • Join container API paths with httpx.URL so api-version stays in the query string (fixes malformed Azure URLs).
  • Managed cntr_ IDs: encode on responses/streaming output; decode in proxy container handlers and container SDK helpers so upstream sees the original provider container id.
  • DeleteContainerFileResponse: accept OpenAI/Azure wire value container.file.deleted (was rejecting and surfacing 500s after successful DELETE).
image

…sponse wire format

- Add AzureContainerConfig and safe URL joining for paths with api-version query
- Encode/decode managed container IDs in responses, streaming, and proxy handlers
- Accept OpenAI delete response object literal container.file.deleted
- Tests for Azure URL regression and DeleteContainerFileResponse parsing

Made-with: Cursor
@vercel

vercel Bot commented Apr 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Apr 7, 2026 4:11pm

Request Review

@codspeed-hq

codspeed-hq Bot commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 16 untouched benchmarks


Comparing litellm_azure-containers-delete-response-and-routing (6843a93) with main (2bb7387)

Open in CodSpeed

Delta stream events do not include a response body; Mock-based tests
(and any truthy synthetic .response on transforms) must not trigger
_update_responses_api_response_id_with_model_id. Fixes
test_stop_async_iteration_not_logged_as_failure (TypeError: Mock not iterable).

Made-with: Cursor
Comment thread litellm/proxy/container_endpoints/handler_factory.py Fixed
Comment thread litellm/proxy/container_endpoints/handler_factory.py Fixed
Comment thread litellm/proxy/container_endpoints/handler_factory.py Fixed
- Add ContainerRequestUtils.encode_container_id_in_response utility
- Encode container_id in create/retrieve/delete responses (SDK path)
- Fix streaming iterator: gate response ID update on parsed_chunk key
- Follows responses API pattern (encode after handler, not in handler)

Made-with: Cursor
Comment thread litellm/containers/utils.py Fixed
@greptile-apps

greptile-apps Bot commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR extends LiteLLM's container API with four improvements: Azure routing (AzureContainerConfig registered for azure/azure_text providers), managed container IDs (containers created via proxy/router are now encoded as cntr_{base64(...)} embedding provider/model affinity metadata, with decode logic stripping them before upstream calls), URL fix (join_container_api_base_path using httpx.URL ensures Azure's ?api-version=v1 always appears after path segments like /cntr_.../files), and DeleteContainerFileResponse wire-format fix (now accepts both container.file.deleted and container_file.deleted, eliminating 500s after successful DELETE).

  • Style: Three inline imports in container_handler.py violate CLAUDE.md's module-level import rule (BaseLLMException in _sync_handle/_async_handle, and extract_file_data in _prepare_multipart_file_upload).
  • Performance: _load_endpoints_config() in container_handler.py opens endpoints.json on every container file API call with no caching.
  • Affinity edge case: encode_container_id_in_response uses target_model_names[0] as the model affinity anchor when model_info.id is absent; with multiple targets and round-robin, the encoded model may not match the deployment that actually created the container.

Confidence Score: 5/5

Safe to merge; all remaining findings are P2 style and performance suggestions

Core logic is correct and well-tested: AzureContainerConfig registration, managed ID encode/decode (None-guard fix applied), httpx.URL path joining, and DeleteContainerFileResponse wire-format fix all work correctly. The two P2 findings (inline imports, uncached JSON read) are non-blocking.

litellm/llms/custom_httpx/container_handler.py (inline imports + uncached JSON read); litellm/containers/utils.py (target_model_names affinity edge case)

Important Files Changed

Filename Overview
litellm/llms/azure/containers/transformation.py New AzureContainerConfig inheriting OpenAIContainerConfig; delegates auth/URL to BaseAzureLLM — clean and minimal
litellm/llms/openai/containers/utils.py New join_container_api_base_path helper using httpx.URL to preserve query-string when appending paths — fixes Azure api-version placement bug
litellm/llms/custom_httpx/container_handler.py New GenericContainerHandler; _load_endpoints_config() re-reads endpoints.json without caching on every request; three inline imports
litellm/containers/utils.py decode_managed_container_id_for_request and encode_container_id_in_response added; target_model_names[0] affinity may not match actual deployment
litellm/responses/utils.py _build_container_id/_decode_container_id helpers with correct None-guard; robust regex-based decoding with safe fallback
litellm/types/containers/main.py DeleteContainerFileResponse now accepts container.file.deleted (OpenAI/Azure wire) and container_file.deleted (legacy)
litellm/proxy/container_endpoints/handler_factory.py Proxy handlers decode managed container IDs; decode pattern duplicated across three functions; inline imports remain
litellm/containers/main.py All container functions accept azure/azure_text and call decode_managed_container_id_for_request before provider config lookup
litellm/containers/endpoint_factory.py Endpoint factory updated for azure/azure_text; decode_managed_container_id_for_request called before dispatching
tests/test_litellm/containers/test_azure_container_transformation.py Comprehensive unit tests for AzureContainerConfig including URL construction and api-version regression tests
tests/test_litellm/containers/test_container_utils.py Tests for decode_managed_container_id_for_request roundtrip and DeleteContainerFileResponse wire format
tests/test_litellm/containers/test_container_api.py Container API tests covering encode/decode roundtrip at the API layer
tests/test_litellm/responses/test_responses_utils.py ResponsesAPIRequestUtils tests including container ID encode/decode roundtrip
litellm/responses/streaming_iterator.py Streaming iterator now calls _encode_container_id_on_output_item for output_item events so managed IDs appear incrementally in streaming
litellm/utils.py ProviderConfigManager.get_provider_container_config now returns AzureContainerConfig for AZURE/AZURE_TEXT providers
litellm/llms/azure/containers/init.py New empty init.py for the azure containers module
litellm/llms/openai/containers/transformation.py All URL-building methods now use join_container_api_base_path instead of f-string concatenation

Sequence Diagram

sequenceDiagram
    participant Client
    participant Proxy as LiteLLM Proxy
    participant Handler as handler_factory.py
    participant SDK as containers/main.py
    participant Azure as Azure OpenAI

    Note over Client,Azure: Container Create (encoding)
    Client->>Proxy: POST /v1/containers {name}
    Proxy->>SDK: create_container(provider=azure)
    SDK->>Azure: POST /openai/v1/containers
    Azure-->>SDK: {id: "cntr_abc"}
    SDK->>SDK: encode_container_id_in_response()<br/>id -> cntr_{b64(litellm:azure;model_id:X;cntr_abc)}
    SDK-->>Proxy: ContainerObject(id=cntr_{b64...})
    Proxy-->>Client: {id: "cntr_{b64...}"}

    Note over Client,Azure: Follow-up (decoding)
    Client->>Proxy: GET /v1/containers/cntr_{b64...}/files
    Proxy->>Handler: _process_request(container_id=cntr_{b64...})
    Handler->>Handler: _decode_container_id()<br/>-> original=cntr_abc, provider=azure
    Handler->>SDK: list_container_files(cntr_abc, azure)
    SDK->>Azure: GET /openai/v1/containers/cntr_abc/files?api-version=v1
    Azure-->>SDK: ContainerFileListResponse
    SDK-->>Proxy: ContainerFileListResponse
    Proxy-->>Client: file list
Loading

Reviews (3): Last reviewed commit: "Fix p1 concern" | Re-trigger Greptile

Comment thread litellm/responses/utils.py Outdated
Comment thread litellm/containers/utils.py Outdated
- Move ResponsesAPIRequestUtils imports to module scope (utils, main, handler_factory).
- Serialize absent model_id as empty segment instead of literal None; decode empty
  and legacy "None" segments as missing for router affinity.
- Add unit tests for build/decode round-trip and legacy IDs.

Made-with: Cursor
@Sameerlite
Sameerlite had a problem deploying to integration-postgres April 7, 2026 13:58 — with GitHub Actions Error
@Sameerlite
Sameerlite had a problem deploying to integration-postgres April 7, 2026 13:58 — with GitHub Actions Error
@Sameerlite
Sameerlite temporarily deployed to integration-redis-postgres April 7, 2026 13:58 — with GitHub Actions Inactive
@Sameerlite
Sameerlite temporarily deployed to integration-postgres April 7, 2026 13:58 — with GitHub Actions Inactive
@Sameerlite
Sameerlite temporarily deployed to integration-postgres April 7, 2026 13:58 — with GitHub Actions Inactive
@Sameerlite

Copy link
Copy Markdown
Contributor Author

@greptile-apps will raise another PR for P1 as this is not an issue introduced by this feat but an already existing issue

@greptile-apps

greptile-apps Bot commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

That makes sense. Addressing pre-existing issues in a separate PR keeps this one focused and makes the changes easier to review. Just make sure to link the P1 PR here when you open it so we can track the fix.

Tip: You can customize Greptile's behavior for this repo with .greptile/rules and .greptile/config.

Comment thread litellm/proxy/container_endpoints/handler_factory.py Dismissed
- Add decode_managed_container_id_for_request in containers/utils and reuse from main.
- Strip LiteLLM cntr_ wrappers before generic_container_handler (64-char API limit).
- Resolve provider for logging/errors; add unit test for decode helper.
- Use resolved_custom_llm_provider after decode for mypy-safe provider typing.

Made-with: Cursor
@Sameerlite
Sameerlite temporarily deployed to integration-postgres April 7, 2026 16:09 — with GitHub Actions Inactive
@Sameerlite
Sameerlite temporarily deployed to integration-redis-postgres April 7, 2026 16:09 — with GitHub Actions Inactive
@Sameerlite
Sameerlite temporarily deployed to integration-postgres April 7, 2026 16:09 — with GitHub Actions Inactive
@Sameerlite
Sameerlite temporarily deployed to integration-postgres April 7, 2026 16:09 — with GitHub Actions Inactive
@Sameerlite
Sameerlite had a problem deploying to integration-postgres April 7, 2026 16:09 — with GitHub Actions Error
@krrish-berri-2
krrish-berri-2 changed the base branch from main to litellm_internal_staging_04_11_2026 April 11, 2026 16:20
@krrish-berri-2
krrish-berri-2 merged commit d03eced into litellm_internal_staging_04_11_2026 Apr 11, 2026
103 of 108 checks passed
@krrish-berri-2
krrish-berri-2 deleted the litellm_azure-containers-delete-response-and-routing branch April 11, 2026 16:21
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…se parsing (BerriAI#25287)

* feat(containers): Azure container routing, managed IDs, and delete response wire format

- Add AzureContainerConfig and safe URL joining for paths with api-version query
- Encode/decode managed container IDs in responses, streaming, and proxy handlers
- Accept OpenAI delete response object literal container.file.deleted
- Tests for Azure URL regression and DeleteContainerFileResponse parsing

Made-with: Cursor

* fix(responses): gate response id update on parsed_chunk having response

Delta stream events do not include a response body; Mock-based tests
(and any truthy synthetic .response on transforms) must not trigger
_update_responses_api_response_id_with_model_id. Fixes
test_stop_async_iteration_not_logged_as_failure (TypeError: Mock not iterable).

Made-with: Cursor

* feat(containers): encode container IDs in SDK responses for routing

- Add ContainerRequestUtils.encode_container_id_in_response utility
- Encode container_id in create/retrieve/delete responses (SDK path)
- Fix streaming iterator: gate response ID update on parsed_chunk key
- Follows responses API pattern (encode after handler, not in handler)

Made-with: Cursor

* fix(containers): module-level imports and managed cntr_ ID encoding

- Move ResponsesAPIRequestUtils imports to module scope (utils, main, handler_factory).
- Serialize absent model_id as empty segment instead of literal None; decode empty
  and legacy "None" segments as missing for router affinity.
- Add unit tests for build/decode round-trip and legacy IDs.

Made-with: Cursor

* fix(containers): decode managed IDs in endpoint_factory SDK path

- Add decode_managed_container_id_for_request in containers/utils and reuse from main.
- Strip LiteLLM cntr_ wrappers before generic_container_handler (64-char API limit).
- Resolve provider for logging/errors; add unit test for decode helper.
- Use resolved_custom_llm_provider after decode for mypy-safe provider typing.

Made-with: Cursor

* Fix p1 concern

* Fix p1 concern
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants