Skip to content

release: 4.1.0 - #93

Closed
stainless-app[bot] wants to merge 140 commits into
mainfrom
release-please--branches--main--changes--next
Closed

stainless-app[bot] wants to merge 140 commits into
mainfrom
release-please--branches--main--changes--next

Conversation

@stainless-app

@stainless-app stainless-app Bot commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

Automated Release PR

4.1.0 (2026-09-14)

Full Changelog: v4.0.0...v4.1.0

Features

  • api: update via SDK Studio (#61) (9c0c551)
  • clean up environment call outs (696f18b)
  • client: add custom JSON encoder for extended type support (87eaded)
  • client: add follow_redirects request option (6eb41c9)
  • client: add support for aiohttp (6f6ddd9)
  • client: add support for binary request streaming (41c399b)
  • client: allow passing NotGiven for body (#67) (3ad7f25)
  • client: send X-Stainless-Read-Timeout header (#63) (a594c75)
  • client: support file upload requests (fde965a)
  • improve future compat with pydantic v3 (bccbddf)
  • internal/types: support eagerly validating pydantic iterators (8e8ca68)
  • internal: implement indices array format for query and form serialization (c601950)
  • stlc: configurable CI runner and private-production-repo support in workflow templates (2da8c4d)
  • support setting headers via env (20336c3)
  • types: replace List[str] with SequenceNotStr in params (0578887)

Bug Fixes

  • asyncify on non-asyncio runtimes (#66) (ca310cd)
  • avoid newer type syntax (db10820)
  • ci: correct conditional (66eb0ef)
  • ci: ensure pip is always available (#78) (d3d295a)
  • ci: release-doctor — report correct token name (65cdccf)
  • ci: remove publishing patch (#79) (493f504)
  • client: add missing f-string prefix in file type error message (8026d49)
  • client: close streams without requiring full consumption (e783145)
  • client: correctly parse binary response | stream (3924997)
  • client: don't send Content-Type header on GET requests (6bcbc4e)
  • client: mark some request bodies as optional (3ad7f25)
  • client: preserve hardcoded query params when merging with user params (12d00c8)
  • compat with Python 3.14 (f7d6103)
  • compat: update signatures of model_dump and model_dump_json for Pydantic v1 (898ca7b)
  • deps: bump minimum typing-extensions version (323a703)
  • ensure file data are only sent as 1 parameter (2a24f49)
  • ensure streams are always closed (f89af68)
  • package: support direct resource imports (ad2d130)
  • parsing: correctly handle nested discriminated unions (cd511d2)
  • parsing: ignore empty metadata (bdd8ead)
  • parsing: parse extra field types (470d8a8)
  • perf: optimize some hot paths (7cc4937)
  • perf: skip traversing types for NotGiven values (38509ba)
  • pydantic v1: more robust ModelField.annotation check (3dc3480)
  • pydantic: do not pass by_alias unless set (887a8ec)
  • sanitize endpoint path params (40f9b7b)
  • tests: fix: tests which call HTTP endpoints directly with the example parameters (539215f)
  • types: allow pyright to infer TypedDict types within SequenceNotStr (84b4806)
  • types: handle more discriminated union shapes (#77) (8b6dcf0)
  • use async_to_httpx_files in patch method (6bfd0c0)
  • use correct field name format for multipart file arrays (0f7a6a4)

Performance Improvements

  • client: optimize file structure copying in multipart requests (639db35)

Chores

  • add Python 3.14 classifier and testing (c172e9c)
  • broadly detect json family of content-type headers (febefbc)
  • bump httpx-aiohttp version to 0.1.9 (7aeb4c8)
  • ci: add timeout thresholds for CI jobs (d5cbcd0)
  • ci: change upload type (d7e4405)
  • ci: enable for pull requests (1ea6fbc)
  • ci: fix installation instructions (6291f4a)
  • ci: only run for pushes and fork pull requests (5d00f3e)
  • ci: only use depot for staging repos (19ee773)
  • ci: skip lint on metadata-only changes (287d210)
  • ci: skip uploading artifacts on stainless-internal branches (d12f89a)
  • ci: upgrade actions/github-script (bdad5ed)
  • ci: upload sdks to package manager (598ec7e)
  • client: minor internal fixes (1e29d3b)
  • deps: mypy 1.18.1 has a regression, pin to 1.17 (fd940b6)
  • do not install brew dependencies in ./scripts/bootstrap by default (67c48f0)
  • docs: grammar improvements (540e711)
  • docs: remove reference to rye shell (ec32daa)
  • docs: update client docstring (#71) (b41543a)
  • docs: use environment variables for authentication in code snippets (ff7f0ef)
  • fix typos (#80) (c1576cc)
  • format all api.md files (034e708)
  • internal/tests: avoid race condition with implicit client cleanup (d3a5435)
  • internal: add --fix argument to lint script (0b1e68e)
  • internal: add missing files argument to base client (5547d1b)
  • internal: add request options to SSE classes (931a27e)
  • internal: add Sequence related utils (5f815ef)
  • internal: avoid errors for isinstance checks on proxies (5dc0949)
  • internal: base client updates (0ac179a)
  • internal: bump dependencies (5c298f6)
  • internal: bump pinned h11 dep (6cafe07)
  • internal: bump pyright version (81c2baf)
  • internal: bump rye to 0.44.0 (#76) (21a20b3)
  • internal: change ci workflow machines (656643d)
  • internal: codegen related update (0b4efb7)
  • internal: codegen related update (2f8fbc4)
  • internal: codegen related update (d6d5a1d)
  • internal: codegen related update (a145cee)
  • internal: codegen related update (#75) (db19786)
  • internal: detect missing future annotations with ruff (23b94ed)
  • internal: expand CI branch coverage (7fd1145)
  • internal: fix devcontainers setup (#68) (97b7254)
  • internal: fix lint error on Python 3.14 (1d9c80a)
  • internal: fix list file params (1b5e333)
  • internal: fix ruff target version (1437b86)
  • internal: fix type traversing dictionary params (#64) (1322c80)
  • internal: grammar fix (it's -> its) (8b1cdb7)
  • internal: import reformatting (8a3f6f0)
  • internal: make test_proxy_environment_variables more resilient (f79d30c)
  • internal: make test_proxy_environment_variables more resilient to env (08e33e4)
  • internal: minor type handling changes (#65) (7e69125)
  • internal: more robust bootstrap script (449a9c3)
  • internal: move mypy configurations to pyproject.toml file (f87b268)
  • internal: properly set pydantic_private (#69) (bc25b84)
  • internal: reduce CI branch coverage (2492996)
  • internal: refactor retries to not use recursion (055e329)
  • internal: reformat pyproject.toml (5b57987)
  • internal: remove extra empty newlines (#74) (3d90dff)
  • internal: remove mock server code (cb06a16)
  • internal: remove trailing character (#81) (4cfa80b)
  • internal: remove unused http client options forwarding (#72) (69a44e3)
  • internal: slight transform perf improvement (#82) (5498eaf)
  • internal: tweak CI branches (2372dd8)
  • internal: update actions/checkout version (54d6bd9)
  • internal: update comment in script (103820e)
  • internal: update conftest.py (83531b4)
  • internal: update gitignore (15b9637)
  • internal: update models test (421a2b5)
  • internal: update pydantic dependency (5dd09a4)
  • internal: update pyright exclude list (f306088)
  • internal: update pyright settings (2d267e1)
  • package: drop Python 3.8 support (95ca18d)
  • package: mark python 3.13 as supported (06ad64f)
  • project: add settings file for vscode (6754b39)
  • readme: fix version rendering on pypi (b1e9e51)
  • readme: update badges (f3f214f)
  • speedup initial import (3b3f4e6)
  • tests: add tests for httpx client instantiation & proxies (5e172cd)
  • tests: run tests in parallel (497b381)
  • tests: simplify get_platform test (ef07d85)
  • tests: skip some failing tests on the latest python versions (39d037c)
  • types: change optional parameter type from NotGiven to Omit (14cb9a9)
  • update @stainless-api/prism-cli to v5.15.0 (d766a01)
  • update github action (d0f9d9e)
  • update lockfile (77726a0)
  • update mock server docs (1241c00)

Documentation

  • client: fix httpx.Timeout documentation reference (3341b85)
  • update URLs from stainlessapi.com to stainless.com (#70) (08062c4)

This pull request is managed by Stainless's GitHub App.

The semver version number is based on included commit messages. Alternatively, you can manually set the version number in the title of this pull request.

For a better experience, it is recommended to use either rebase-merge or squash-merge when merging this pull request.

🔗 Stainless website
📚 Read the docs
🙋 Reach out for help or questions

Greptile Summary

This release updates the generated SDK and core HTTP client, adds aiohttp and binary-body support, revises serialization, parsing, retries, streaming cleanup, and path handling, consolidates voice deployment response models, drops Python 3.8, and modernizes CI and development tooling.

  • Adds aiohttp-backed asynchronous clients, per-request redirect control, binary streaming uploads, custom JSON encoding, and environment-provided headers.
  • Refactors retry and stream lifecycles while expanding Pydantic compatibility and type transformation.
  • Consolidates voice response models under VoiceDeployment.
  • Updates package metadata to 4.1.0 and refreshes workflows, dependencies, tests, and documentation.
  • Requires corrections for credential logging, two minor-release compatibility breaks, and synchronous recursion in async dictionary transformation.

Confidence Score: 1/5

The PR is not safe to merge until credential-bearing CI output is protected and the minor-release compatibility breaks are resolved.

The artifact uploader exposes live authorization material in CI logs, while the 4.1.0 package removes documented response imports and Python 3.8 installability; async dictionary transformation also performs potentially blocking synchronous file reads.

Files Needing Attention: scripts/utils/upload-artifact.sh, src/brainbase/types/workers/deployments/init.py, pyproject.toml, src/brainbase/_utils/_transform.py

Security Review

The new CI artifact-upload path exposes its GitHub OIDC bearer token and signed upload URL through Bash command tracing and verbose request output. Tracing and verbose URL logging must be disabled around credential-bearing commands.

Important Files Changed

Filename Overview
scripts/utils/upload-artifact.sh Adds package artifact upload handling but traces the OIDC bearer token and signed upload URL into CI logs.
src/brainbase/types/workers/deployments/init.py Replaces three documented voice response exports with VoiceDeployment without compatibility aliases.
pyproject.toml Releases version 4.1.0, adds aiohttp dependencies, updates tooling, and raises the Python runtime floor from 3.8 to 3.9.
src/brainbase/_utils/_transform.py Expands and optimizes recursive transformations, but async generic-dictionary traversal incorrectly uses the synchronous transformer.
src/brainbase/_base_client.py Adds binary content, redirect options, iterative retries, custom JSON encoding, and revised request/response lifecycle handling.
src/brainbase/_models.py Expands Pydantic compatibility, discriminated-union parsing, extra-field handling, and eager iterable validation.
src/brainbase/resources/workers/deployments/voice.py Adds path sanitization and changes voice endpoint return types to the consolidated deployment model.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  User[SDK caller] --> Resource[Generated resource method]
  Resource --> Transform[Request transformation]
  Transform --> Client[Sync or async base client]
  Client --> Retry[Request and retry loop]
  Retry --> HTTPX[HTTPX transport]
  HTTPX --> API[Brainbase API]
  API --> Parse[Response parsing]
  Parse --> Model[Pydantic response model]
  CI[GitHub Actions build] --> Build[Build wheel]
  Build --> Upload[Artifact upload script]
  Upload --> Storage[Stainless package storage]
Loading
Prompt To Fix All With AI
### Issue 1
scripts/utils/upload-artifact.sh:2
**Credentials Leak Into Logs**

The artifact uploader enables shell tracing while inserting the GitHub OIDC token into an `Authorization` header and the signed upload URL into `curl`. GitHub Actions captures this stderr output, so users with access to the build log can obtain reusable credentials. Disable tracing before handling credentials and avoid verbose output containing signed URLs.

**How this was verified:** The workflow passes an OIDC token as `AUTH`, and Bash expands that value and the signed URL into traced commands written to stderr.

### Issue 2
src/brainbase/types/workers/deployments/__init__.py:5-8
**Public Response Imports Removed**

This minor release removes the documented `VoiceCreateResponse`, `VoiceRetrieveResponse`, and `VoiceUpdateResponse` exports and their importable modules without compatibility aliases. Applications upgrading from 4.0.0 that retain these public imports will fail during import with `ImportError` or `ModuleNotFoundError`. Preserve aliases and modules for the 4.x series, or make this a major release.

### Issue 3
pyproject.toml:20
**Minor Release Drops Python**

Raising `requires-python` from 3.8 to 3.9 makes version 4.1.0 uninstallable in an environment supported by 4.0.0. Python 3.8 consumers therefore cannot take an otherwise compatible 4.x upgrade. Retain Python 3.8 support or publish the support removal as a major release.

### Issue 4
src/brainbase/_utils/_transform.py:348-350
**Async Transform Blocks Loop**

The asynchronous dictionary branch calls `_transform_recursive` instead of `_async_transform_recursive`. For dictionary values containing base64-formatted `PathLike` inputs, this reads files synchronously on the event-loop thread rather than using the existing awaited AnyIO path. Large file transformations can therefore delay unrelated asynchronous work.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "release: 4.1.0" | Re-trigger Greptile

Greptile also left 4 inline comments on this PR.

fix(client): mark some request bodies as optional
Note that we still want to run tests, as these depend on the metadata.
Pin all GitHub Actions referenced in generated workflows (both
first-party `actions/*` and third-party) to immutable commit SHAs.
Updating pinned actions is now a deliberate codegen-side bump rather
than implicit on every workflow run.
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -exuo pipefail

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 security Credentials Leak Into Logs

The artifact uploader enables shell tracing while inserting the GitHub OIDC token into an Authorization header and the signed upload URL into curl. GitHub Actions captures this stderr output, so users with access to the build log can obtain reusable credentials. Disable tracing before handling credentials and avoid verbose output containing signed URLs.

How this was verified: The workflow passes an OIDC token as AUTH, and Bash expands that value and the signed URL into traced commands written to stderr.

Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/utils/upload-artifact.sh
Line: 2

Comment:
**Credentials Leak Into Logs**

The artifact uploader enables shell tracing while inserting the GitHub OIDC token into an `Authorization` header and the signed upload URL into `curl`. GitHub Actions captures this stderr output, so users with access to the build log can obtain reusable credentials. Disable tracing before handling credentials and avoid verbose output containing signed URLs.

**How this was verified:** The workflow passes an OIDC token as `AUTH`, and Bash expands that value and the signed URL into traced commands written to stderr.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +5 to 8
from .voice_deployment import VoiceDeployment as VoiceDeployment
from .voice_create_params import VoiceCreateParams as VoiceCreateParams
from .voice_list_response import VoiceListResponse as VoiceListResponse
from .voice_update_params import VoiceUpdateParams as VoiceUpdateParams

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Public Response Imports Removed

This minor release removes the documented VoiceCreateResponse, VoiceRetrieveResponse, and VoiceUpdateResponse exports and their importable modules without compatibility aliases. Applications upgrading from 4.0.0 that retain these public imports will fail during import with ImportError or ModuleNotFoundError. Preserve aliases and modules for the 4.x series, or make this a major release.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/brainbase/types/workers/deployments/__init__.py
Line: 5-8

Comment:
**Public Response Imports Removed**

This minor release removes the documented `VoiceCreateResponse`, `VoiceRetrieveResponse`, and `VoiceUpdateResponse` exports and their importable modules without compatibility aliases. Applications upgrading from 4.0.0 that retain these public imports will fail during import with `ImportError` or `ModuleNotFoundError`. Preserve aliases and modules for the 4.x series, or make this a major release.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment thread pyproject.toml
]
requires-python = ">= 3.8"

requires-python = ">= 3.9"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Minor Release Drops Python

Raising requires-python from 3.8 to 3.9 makes version 4.1.0 uninstallable in an environment supported by 4.0.0. Python 3.8 consumers therefore cannot take an otherwise compatible 4.x upgrade. Retain Python 3.8 support or publish the support removal as a major release.

Prompt To Fix With AI
This is a comment left during a code review.
Path: pyproject.toml
Line: 20

Comment:
**Minor Release Drops Python**

Raising `requires-python` from 3.8 to 3.9 makes version 4.1.0 uninstallable in an environment supported by 4.0.0. Python 3.8 consumers therefore cannot take an otherwise compatible 4.x upgrade. Retain Python 3.8 support or publish the support removal as a major release.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +348 to +350
if origin == dict and is_mapping(data):
items_type = get_args(stripped_type)[1]
return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Async Transform Blocks Loop

The asynchronous dictionary branch calls _transform_recursive instead of _async_transform_recursive. For dictionary values containing base64-formatted PathLike inputs, this reads files synchronously on the event-loop thread rather than using the existing awaited AnyIO path. Large file transformations can therefore delay unrelated asynchronous work.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/brainbase/_utils/_transform.py
Line: 348-350

Comment:
**Async Transform Blocks Loop**

The asynchronous dictionary branch calls `_transform_recursive` instead of `_async_transform_recursive`. For dictionary values containing base64-formatted `PathLike` inputs, this reads files synchronously on the event-loop thread rather than using the existing awaited AnyIO path. Large file transformations can therefore delay unrelated asynchronous work.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

@Nauxie Nauxie closed this Sep 22, 2026
@Nauxie

Nauxie commented Sep 22, 2026

Copy link
Copy Markdown
Member

Auto-closed by PR Janitor after 7 days of inactivity. Reopen anytime if this is still relevant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant