Skip to content

fix: emit additionalProperties as query params on streaming connect#86

Merged
GregHolmes merged 1 commit into
mainfrom
fix/streaming-additional-properties-query-params
Jul 24, 2026
Merged

fix: emit additionalProperties as query params on streaming connect#86
GregHolmes merged 1 commit into
mainfrom
fix/streaming-additional-properties-query-params

Conversation

@GregHolmes

Copy link
Copy Markdown
Collaborator

Summary

Fixes #83. On the streaming connect builders, the upgrade URL is built only from the typed options and additionalProperties is never emitted. So unmodeled query params set via the builder escape hatch -- for example no_delay -- were silently dropped:

  • Before: setting no_delay via additionalProperty yielded model=nova-3 only
  • After: yields model=nova-3&no_delay=true

connect also accepts no RequestOptions, and RequestOptions.queryParameters is the REST world's mechanism for arbitrary query params -- so before this change there was no working way to send an unmodeled query param on a streaming connection at all.

Root cause

A generator gap, not a spec issue. The WebSocket connect template serializes only the typed options and ignores additionalProperties. The builder still exposes additionalProperty, so the escape hatch looks available but does nothing on the wire.

Fix

Emit additionalProperties as query params in connect, routed through QueryStringMapper with arraysAsRepeats enabled, so boolean, numeric, and list values serialize exactly as the REST path does. ConnectOptions is request-only and never deserialized, so the map only ever holds what the caller set via the builder.

Applied to all four connect clients: listen v1, listen v2, speak v1, speak v2. speak v1 was not previously frozen and is added to .fernignore.

Tests

New StreamingAdditionalPropertiesWireTest with MockWebServer coverage on all four clients: a no_delay boolean plus a custom string reach the captured upgrade URL and coexist with the typed model param. Also verified with a throwaway showing boolean, numeric, and list-valued escape-hatch params all serialize correctly -- multi=x&multi=y for a list. ./gradlew spotlessJavaCheck test is green.

Upstream / follow-ups

  • Generator: the WebSocket connect template should emit additionalProperties on the connect path so all four clients can be un-frozen. Added to the Fern-upgrade defect list.
  • Spec: no_delay is a real listen param and arguably should be modeled as a typed option, which would remove the need for the escape hatch for that param.

Note: overlaps with #85 in speak v2 connect -- both touch the same method at different points, so whichever merges second needs a trivial rebase.

@dg-coreylweathers dg-coreylweathers left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified: escape hatch reaches the wire on all four connect clients, REST-parity serialization, null-guarded, all four frozen in .fernignore, gate green. Merge #85 first, then rebase this so speak v2's tag fix + .fernignore comment stay honest.

Fixes #83. The streaming connect() builders build the upgrade URL only from
the typed options and never emit additionalProperties, so unmodeled query
params set via the builder's additionalProperty escape hatch -- e.g.
no_delay -- were silently dropped. connect() also accepts no RequestOptions,
so there was no working way to send an unmodeled query param on a streaming
connection at all.

Emit additionalProperties as query params in connect(), routed through
QueryStringMapper with repeats enabled so non-string values and lists
serialize the same way the REST path does. ConnectOptions is request-only
and never deserialized, so the map only ever holds what the caller set.

Applied to all four connect clients -- listen v1, listen v2, speak v1,
speak v2. speak v1 was not previously frozen, so it is added to .fernignore.
The durable fix belongs upstream in the Fern generator WebSocket template,
which should emit additionalProperties on the connect path.
@GregHolmes
GregHolmes force-pushed the fix/streaming-additional-properties-query-params branch from 161599f to 85b5cf7 Compare July 24, 2026 12:16
@GregHolmes
GregHolmes merged commit 28229fc into main Jul 24, 2026
8 checks passed
GregHolmes pushed a commit that referenced this pull request Jul 24, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.7.1](v0.7.0...v0.7.1)
(2026-07-24)


### Bug Fixes

* emit additionalProperties as query params on streaming connect
([#86](#86))
([28229fc](28229fc))
* emit repeated query params for all multi-value streaming options
([#82](#82))
([746be15](746be15)),
closes [#77](#77)
* emit repeated tag query params for multi-value speak v2 streaming
([#85](#85))
([e748619](e748619))

#### What's in this release

Three related fixes to streaming (WebSocket) query-parameter
serialization on `listen` and `speak`. All are bug fixes — no API
changes.

**Multi-keyterm streaming fix**
- Streaming connections mis-serialized a multi-value `keyterm` (and
other array-valued params): a `List<String>` was stringified into a
single param (`keyterm=[a, b]`) instead of repeated params
(`keyterm=a&keyterm=b`). The server treats the stringified list as one
nonsense term, so multiple key terms were not boosted — recognition of
them was actually degraded.
- Now fixed for every array-valued streaming query param — `listen`:
`keyterm`, `keywords`, `replace`, `search`, `tag`, `extra`,
`language_hint`; `speak`: `tag` — by routing them through the same
repeated-param serialization the REST path already uses (#81, #82, #85;
closes #77).
- **If you worked around this by hand-joining terms into a single
string, drop that workaround** — pass a real `List<String>` (e.g.
`ListenV1Keyterm.of(List.of("a", "b"))`) and each term is now sent as
its own `keyterm=` param.

**Unmodeled streaming query params now work (e.g. `no_delay`)**
- The streaming `connect(...)` builders dropped `additionalProperties`,
so unmodeled params set via `.additionalProperty("no_delay", true)`
never reached the URL — it was impossible to set `no_delay` on a
streaming connection.
- Now fixed on all four connect clients (`listen` v1/v2, `speak` v1/v2):
`additionalProperties` are emitted as query params, so any
not-yet-modeled param can be passed through until it gains a typed
option (#86; closes #83).

_All four streaming clients remain frozen in `.fernignore`; the durable
fix belongs in the Fern generator's WebSocket template, tracked for the
next generator upgrade._

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

Its impossible to set the no_delay=true

2 participants