fix: always fall back to non-streaming on ANY streaming error

Previously the fallback only triggered on specific error keywords like
'streaming is not supported'. Many third-party providers have partial
or broken streaming — rejecting stream=True, crashing on stream_options,
dropping connections mid-stream, returning malformed chunks, etc.

Now: any exception during the streaming API call triggers an automatic
fallback to the standard non-streaming request path. The error is logged
at INFO level for diagnostics but never surfaces to the user. If the
fallback also fails, THAT error propagates normally.

This ensures streaming is additive — it improves UX when it works but
never breaks providers that don't support it.

Tests: 2 new (any-error fallback, double-failure propagation), 15 total.
This commit is contained in:
teknium1 2026-03-16 06:15:09 -07:00
parent 5479bb0e0c
commit 99369b926c
2 changed files with 62 additions and 21 deletions

View file

@ -3208,23 +3208,17 @@ class AIAgent:
else:
result["response"] = _call_chat_completions()
except Exception as e:
err_text = str(e).lower()
# Fall back to non-streaming if provider doesn't support it.
# Be specific in matching — "stream" alone is too broad and
# catches unrelated errors like "stream_options" rejections.
stream_unsupported = any(
kw in err_text
for kw in ("streaming is not", "streaming not support",
"does not support stream", "not available")
)
if stream_unsupported:
logger.info("Streaming not supported by provider, falling back to non-streaming: %s", e)
try:
result["response"] = self._interruptible_api_call(api_kwargs)
except Exception as fallback_err:
result["error"] = fallback_err
else:
result["error"] = e
# Always fall back to non-streaming on ANY streaming error.
# Many third-party/extrinsic providers have partial or broken
# streaming support — rejecting stream=True, crashing on
# stream_options, dropping connections mid-stream, etc.
# A clean fallback to the standard request path ensures the
# agent still works even if streaming doesn't.
logger.info("Streaming failed, falling back to non-streaming: %s", e)
try:
result["response"] = self._interruptible_api_call(api_kwargs)
except Exception as fallback_err:
result["error"] = fallback_err
finally:
request_client = request_client_holder.get("client")
if request_client is not None: