跳到导航

5.40.0

(feat): Support inferred bearer auth with type: refresh-token. The generated InferredAuthTokenProvider always sends grant_type="refresh_token" to the get-token endpoint, and grant_type is no longer a client constructor parameter. Users pass only the refresh token (and any other non-literal token endpoint parameters).

(feat): Inferred auth now works next to other auth schemes (auth: any and endpoint-security) when it has credentials of its own, e.g. a type: refresh-token scheme next to OAuth client credentials. The client takes the inferred credentials as optional constructor parameters (shared ones such as client_id are added once) and uses the inferred token provider when they are passed, so Client(refresh_token=...) and Client(client_id=..., client_secret=...) both work.

(feat): With type: refresh-token, inferred auth only exposes and sends the token endpoint parameters used by the OAuth refresh token grant (refresh_token, scope, client_id, client_secret) plus any required ones. Optional parameters of other grants on a shared token endpoint, such as code, code_verifier and redirect_uri, are no longer client constructor parameters.

(feat): Add the omit_unset_inferred_auth_params config option (default false). When enabled, the inferred auth token provider leaves unset optional token request parameters out of the get-token request instead of sending them as null (JSON) or empty values (form-encoded).

(feat): Inferred auth with type: refresh-token now rotates the refresh token. When the token response returns a new refresh_token, the provider uses it for the next refresh, and the client calls the optional on_refresh_token_rotated callback with it so it can be persisted.

(fix): Fix wire test setup for inferred auth. tests/wire/conftest.py now passes a test value for each required token endpoint parameter (e.g. client_id, client_secret) instead of always passing api_key, which raised TypeError when the client had no api_key parameter.

5.39.5

(fix): Fix the root client docstring example for global headers and root path parameters that have a client-default. The example now passes the default as a keyword argument (e.g. version="2024-01-01") instead of a bare positional value, which was a SyntaxError when it followed another keyword argument.

5.39.4

(fix): SSE unions discriminated by the event: line (x-fern-discriminator-context: protocol) now parse both variant styles: envelope variants ({event, data: Payload}) are built from the data: JSON, and payload variants (the data: JSON itself) get the event: value injected as the discriminant. The event name no longer has to be repeated inside the data: JSON.

5.39.3

(fix): Stop automatically replaying requests after server disconnects or incomplete responses (httpx.RemoteProtocolError), which could duplicate non-idempotent POST/PATCH operations, even after a 200 status was received. Connection-establishment failures and HTTP-status retries are unchanged. Set request_options={"retry_remote_protocol_errors": True} only when replaying the request is safe to explicitly restore the previous behavior.

(fix): With pydantic_config.skip_validation: true, a union value that matches no known member is now returned as its original data (the raw dict) instead of None. Previously a response carrying a union variant added after the SDK was generated (e.g. a new product on a discriminated union), or one missing its discriminant, silently decoded to None and its fields were lost. Known variants still decode to their classes.

5.39.2

(fix): Generated core/pydantic_utilities.py now type-checks under pydantic 2.14, which made mypy report var-annotated on the module-level TypeAdapter instances.

5.39.1

(fix): XML (TwiML) fluent child methods (response.say(...), gather.play(...), …) keep document order on Python 3.12+. The ordered content list is a pydantic private attribute, and the runtime_checkable Protocol used to find it stopped matching on 3.12 (where isinstance uses inspect.getattr_static), so children appended by the fluent methods were ordered after text and add_child(...) elements, e.g. r.say("a"); r.add_child(XmlElement("Custom")); r.say("b") rendered <Custom/><Say>a</Say><Say>b</Say>.