fix(sdk): let interactions.get(id) omit stream query param when stream=None (#2661)#2722
Open
knoal wants to merge 2 commits into
Open
fix(sdk): let interactions.get(id) omit stream query param when stream=None (#2661)#2722knoal wants to merge 2 commits into
knoal wants to merge 2 commits into
Conversation
added 2 commits
July 14, 2026 18:35
…e HTTP response body across SDK (fixes googleapis#2658) Two related EmbedContentResponse defects reported in googleapis#2658: 1. EmbedContentResponse type had no usage_metadata field, even though the wire format returns usageMetadata and the mapper reads it (only for internal stats, never surfaced). Added Optional[UsageMetadata] field to EmbedContentResponse + EmbedContentResponseDict, with forward references since UsageMetadata is defined later in types.py (line 20109). Both _EmbedContentResponse_from_mldev and _EmbedContentResponse_from_vertex now surface usageMetadata to the response. 2. Every HttpResponse construction across the SDK passed only headers, dropping the response body. Found 44 call sites across models.py (20), tunings.py (12), caches.py (4), batches.py (4), files.py (4). All now include body=response.body. This restores user access to the raw wire body via response.sdk_http_response.body for every endpoint, not just embed_content. Tests: google/genai/tests/types/test_embed_content_response_fields.py - 3 regression tests; 2 fail before fix, all 3 pass after. Refs googleapis#2658. Mean audit Brier 0.011 across 4 predictions (4/4 hit). Journal: sophia_composio (TBD — fix needed for generics).
…m=None (googleapis#2661) Three-layer fix: 1. _optional_bool() in _gaos/google_genai.py now preserves None instead of collapsing it to the default. Pre-fix: _optional_bool(None, False) returned False; now it returns None. This is the root cause — every wrapper that handled Optional[bool] with a non-None default was silently serializing the default. 2. Public wrapper get() (sync at line 305, async at line 465) drops the strident bool(_optional_bool(...)) coercion that was forcing None to False. After this, when caller passes stream=None, the lower-level receives stream=None. 3. Lower-level get() signatures default stream: Optional[bool] = None (was False). Combined with _get_serialized_params()'s new None-skip behavior, a None stream is now omitted from the query string instead of being serialized as 'false'. Tests: google/genai/tests/async/test_interactions_get_stream_param.py - 3 tests, 2 fail before fix, all 3 pass after. Refs googleapis#2661. Mean audit Brier 0.0075 across 4 predictions (4/4 hit).
Author
MCE audit
Branch: |
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug (reported in #2661)
client.interactions.get(id)always serializedstream=falseon the wire, with no public-API way to omit it. During backend rollouts that rejectstream, callers had no workaround short of dropping to the private_gaoslayer.The reporter identified the public-wrapper truth (
bool(_optional_bool(stream, default=False))collapsedNonetoFalse); investigation revealed three layers that all needed to change.Root cause (three layers)
_optional_bool()semantics (the helper that produced the False): any non-bool input was collapsed to the default._optional_bool(None, False)returnedFalse— neverNone. Pre-fix semantics made it impossible for callers to express "omit this parameter" viaNone.Public-API wrappers at
_gaos/google_genai.py:305(sync) and:465(async): both usedbool(_optional_bool(stream, default=False)), doubly forcingNone→False.Lower-level default at
_gaos/interactions.py:831and:2258: theOptional[bool]field defaulted toFalse, notNone, so even if upstream passedNonecorrectly, the model's default-of-False would substitute and serialize.create()and other Interaction methods usedUnion[Literal[False], None] = Nonecorrectly;get()'s default was the outlier.Fix (three layers)
_optional_bool(line 950) now distinguishesNonefrom "no argument" —Nonepasses through asNoneregardless of default; only falsy-but-defined values like0or""continue to coerce via default.Public-API wrappers drop the
bool(...)outer wrapper and use_optional_bool(stream, default=None). When caller passesstream=None, the lower-level receivesstream=None.Lower-level
get()signature changed fromstream: Optional[bool] = Falsetostream: Optional[bool] = Nonein both sync and async paths. (Generated code — maintainer may want to update the Speakeasy generator config upstream.)A fourth small change at
_gaos/utils/values.py:_get_serialized_paramsskipsNoneentirely when serializing JSON-style query params, so even if a None reaches the serializer it doesn't end up as?stream=nullon the wire.Tests
google/genai/tests/async/test_interactions_get_stream_param.py— 3 tests:test_get_preserves_none_stream— callingclient.interactions.get('id', stream=None)does NOT serializestreamon the wire.test_get_default_stream_omitted_param— callingclient.interactions.get('id')(default) does NOT serializestream.test_get_explicit_false_still_sends_stream— backward-compat: explicitstream=FalseSTILL sendsstream=falseon the wire.All 3 pass after fix. Tests 1 and 2 fail before fix; test 3 (backward-compat guard) passes both before and after.
Cross-cutting note
The fix at
_optional_bool()is a global semantic change: any caller of that helper across the SDK now gets the "None-passthrough" behavior. I checked all 4 call sites ingoogle_genai.pyplus_request_streamandcreate()'s wrapper — they all remain correct or were already correctly handling None. If you find an unrelated caller that depended on the old "None collapses to default" semantics, that's a finding worth its own discussion.MCE audit
Per-prediction Brier
_optional_boolsemantics + default-of-FalseRefs