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
This commit is contained in:
Sameer Kankute 2026-04-07 18:24:00 +05:30
parent 4d677386b6
commit 91cb235401
No known key found for this signature in database
2 changed files with 71 additions and 4 deletions

View file

@ -279,7 +279,7 @@ def create_container(
# Set the correct call type for container creation
litellm_logging_obj.call_type = CallTypes.create_container.value
return base_llm_http_handler.container_create_handler(
container_obj = base_llm_http_handler.container_create_handler(
name=name,
container_create_request_params=container_create_request_params,
container_provider_config=container_provider_config,
@ -289,6 +289,17 @@ def create_container(
timeout=timeout or DEFAULT_REQUEST_TIMEOUT,
_is_async=_is_async,
)
# Encode container_id with provider/model metadata for routing
if isinstance(container_obj, ContainerObject):
model_id = kwargs.get("litellm_metadata", {}).get("model_info", {}).get("id")
container_obj = ContainerRequestUtils.encode_container_id_in_response(
response_obj=container_obj,
custom_llm_provider=custom_llm_provider,
model_id=model_id,
)
return container_obj
except Exception as e:
raise litellm.exception_type(
@ -683,7 +694,7 @@ def retrieve_container(
# Set the correct call type
litellm_logging_obj.call_type = CallTypes.retrieve_container.value
return base_llm_http_handler.container_retrieve_handler(
container_obj = base_llm_http_handler.container_retrieve_handler(
container_id=original_container_id, # Use decoded original ID
container_provider_config=container_provider_config,
litellm_params=litellm_params,
@ -693,6 +704,17 @@ def retrieve_container(
timeout=timeout or DEFAULT_REQUEST_TIMEOUT,
_is_async=_is_async,
)
# Encode container_id with provider/model metadata for routing
if isinstance(container_obj, ContainerObject):
model_id = kwargs.get("litellm_metadata", {}).get("model_info", {}).get("id")
container_obj = ContainerRequestUtils.encode_container_id_in_response(
response_obj=container_obj,
custom_llm_provider=custom_llm_provider,
model_id=model_id,
)
return container_obj
except Exception as e:
raise litellm.exception_type(
@ -879,7 +901,7 @@ def delete_container(
# Set the correct call type
litellm_logging_obj.call_type = CallTypes.delete_container.value
return base_llm_http_handler.container_delete_handler(
delete_result = base_llm_http_handler.container_delete_handler(
container_id=original_container_id, # Use decoded original ID
container_provider_config=container_provider_config,
litellm_params=litellm_params,
@ -889,6 +911,17 @@ def delete_container(
timeout=timeout or DEFAULT_REQUEST_TIMEOUT,
_is_async=_is_async,
)
# Encode container_id in response with provider/model metadata for routing
if isinstance(delete_result, DeleteContainerResult):
model_id = kwargs.get("litellm_metadata", {}).get("model_info", {}).get("id")
delete_result = ContainerRequestUtils.encode_container_id_in_response(
response_obj=delete_result,
custom_llm_provider=custom_llm_provider,
model_id=model_id,
)
return delete_result
except Exception as e:
raise litellm.exception_type(

View file

@ -1,4 +1,4 @@
from typing import Dict
from typing import Any, Dict, Optional, TypeVar
from litellm.llms.base_llm.containers.transformation import BaseContainerConfig
from litellm.types.containers.main import (
@ -6,6 +6,8 @@ from litellm.types.containers.main import (
ContainerListOptionalRequestParams,
)
T = TypeVar("T")
class ContainerRequestUtils:
@staticmethod
@ -68,3 +70,35 @@ class ContainerRequestUtils:
container_list_optional_params[param] = passed_params[param] # type: ignore
return container_list_optional_params
@staticmethod
def encode_container_id_in_response(
response_obj: T,
custom_llm_provider: Optional[str],
model_id: Optional[str],
) -> T:
"""
Encode container_id in response object with provider/model metadata for routing.
This mirrors the responses API pattern where response IDs are encoded with
routing metadata so follow-up calls can route to the correct provider.
Args:
response_obj: Response object with an `id` attribute (ContainerObject, DeleteContainerResult, etc.)
custom_llm_provider: Provider name (e.g., "azure", "openai")
model_id: Model ID from litellm_metadata
Returns:
The same response object with encoded container_id
"""
if response_obj and hasattr(response_obj, "id"):
from litellm.responses.utils import ResponsesAPIRequestUtils
encoded_id = ResponsesAPIRequestUtils._build_container_id(
custom_llm_provider=custom_llm_provider,
model_id=model_id,
container_id=response_obj.id,
)
response_obj.id = encoded_id
return response_obj