fix(api_server): coerce stringified booleans in request payloads
This commit is contained in:
@@ -71,6 +71,35 @@ def _coerce_port(value: Any, default: int = DEFAULT_PORT) -> int:
|
||||
return default
|
||||
|
||||
|
||||
_TRUE_REQUEST_BOOL_STRINGS = frozenset({"1", "true", "yes", "on"})
|
||||
_FALSE_REQUEST_BOOL_STRINGS = frozenset({"0", "false", "no", "off"})
|
||||
|
||||
|
||||
def _coerce_request_bool(value: Any, default: bool = False) -> bool:
|
||||
"""Normalize boolean-like API payload values.
|
||||
|
||||
External clients should send real JSON booleans, but some OpenAI-compatible
|
||||
frontends and middleware serialize flags like ``stream`` as strings. Using
|
||||
Python truthiness on those values misroutes requests because ``"false"`` is
|
||||
still truthy. Treat only explicit bool-ish scalars as booleans; everything
|
||||
else falls back to the caller's default.
|
||||
"""
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
if value is None:
|
||||
return default
|
||||
if isinstance(value, str):
|
||||
normalized = value.strip().lower()
|
||||
if normalized in _TRUE_REQUEST_BOOL_STRINGS:
|
||||
return True
|
||||
if normalized in _FALSE_REQUEST_BOOL_STRINGS:
|
||||
return False
|
||||
return default
|
||||
if isinstance(value, (int, float)):
|
||||
return bool(value)
|
||||
return default
|
||||
|
||||
|
||||
def _normalize_chat_content(
|
||||
content: Any, *, _max_depth: int = 10, _depth: int = 0,
|
||||
) -> str:
|
||||
@@ -1005,7 +1034,7 @@ class APIServerAdapter(BasePlatformAdapter):
|
||||
status=400,
|
||||
)
|
||||
|
||||
stream = body.get("stream", False)
|
||||
stream = _coerce_request_bool(body.get("stream"), default=False)
|
||||
|
||||
# Extract system message (becomes ephemeral system prompt layered ON TOP of core)
|
||||
system_prompt = None
|
||||
@@ -2082,7 +2111,7 @@ class APIServerAdapter(BasePlatformAdapter):
|
||||
instructions = body.get("instructions")
|
||||
previous_response_id = body.get("previous_response_id")
|
||||
conversation = body.get("conversation")
|
||||
store = body.get("store", True)
|
||||
store = _coerce_request_bool(body.get("store"), default=True)
|
||||
|
||||
# conversation and previous_response_id are mutually exclusive
|
||||
if conversation and previous_response_id:
|
||||
@@ -2165,7 +2194,7 @@ class APIServerAdapter(BasePlatformAdapter):
|
||||
# groups the entire conversation under one session entry.
|
||||
session_id = stored_session_id or str(uuid.uuid4())
|
||||
|
||||
stream = bool(body.get("stream", False))
|
||||
stream = _coerce_request_bool(body.get("stream"), default=False)
|
||||
if stream:
|
||||
# Streaming branch — emit OpenAI Responses SSE events as the
|
||||
# agent runs so frontends can render text deltas and tool
|
||||
@@ -3228,7 +3257,10 @@ class APIServerAdapter(BasePlatformAdapter):
|
||||
status=409,
|
||||
)
|
||||
|
||||
resolve_all = bool(body.get("all") or body.get("resolve_all"))
|
||||
resolve_all = (
|
||||
_coerce_request_bool(body.get("all"), default=False)
|
||||
or _coerce_request_bool(body.get("resolve_all"), default=False)
|
||||
)
|
||||
try:
|
||||
from tools.approval import resolve_gateway_approval
|
||||
|
||||
|
||||
Reference in New Issue
Block a user