release: 4.1.0 - #89
Open
stainless-app[bot] wants to merge 140 commits into
Open
Conversation
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.
…t in workflow templates
Comment on lines
+72
to
+77
| else: | ||
| parts[i] = quoter(str(values[name])) | ||
|
|
||
| return "".join(parts) | ||
|
|
||
|
|
There was a problem hiding this comment.
None path parameter silently becomes "null"
When a placeholder value is None, _interpolate inserts the literal string "null" into the URL (e.g. path_template("/api/workers/{id}", id=None) → /api/workers/null). In practice the callers all guard against empty strings before reaching this function, so the path is never triggered, but the behaviour is surprising enough to warrant either a docstring note or a TypeError raise for None inputs instead of a silent sentinel substitution.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/brainbase/_utils/_path.py
Line: 72-77
Comment:
**`None` path parameter silently becomes `"null"`**
When a placeholder value is `None`, `_interpolate` inserts the literal string `"null"` into the URL (e.g. `path_template("/api/workers/{id}", id=None)` → `/api/workers/null`). In practice the callers all guard against empty strings before reaching this function, so the path is never triggered, but the behaviour is surprising enough to warrant either a docstring note or a `TypeError` raise for `None` inputs instead of a silent sentinel substitution.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
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.
Automated Release PR
4.1.0 (2026-08-05)
Full Changelog: v4.0.0...v4.1.0
Features
NotGivenfor body (#67) (3ad7f25)X-Stainless-Read-Timeoutheader (#63) (a594c75)Bug Fixes
model_dumpandmodel_dump_jsonfor Pydantic v1 (898ca7b)by_aliasunless set (887a8ec)Performance Improvements
Chores
httpx-aiohttpversion to 0.1.9 (7aeb4c8)actions/github-script(bdad5ed)api.mdfiles (034e708)--fixargument to lint script (0b1e68e)test_proxy_environment_variablesmore resilient (f79d30c)test_proxy_environment_variablesmore resilient to env (08e33e4)pyproject.tomlfile (f87b268)actions/checkoutversion (54d6bd9)get_platformtest (ef07d85)Documentation
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 is the automated Stainless-generated release PR bumping the Brainbase Python SDK from v4.0.0 to v4.1.0. The release contains a substantial set of infrastructure improvements alongside a small API surface update.
VoiceCreateResponse,VoiceUpdateResponse,VoiceRetrieveResponse) are consolidated into a singleVoiceDeploymentmodel; f-string URL construction is replaced with a newpath_templateutility that properly percent-encodes path parameters per RFC 3986 and rejects dot-segment traversal.cached_property, the deprecatedtransport/proxies/limitsconstructor arguments are removed, and new features are added including aiohttp support, binary request streaming,follow_redirects,X-Stainless-Read-Timeoutheader, andBRAINBASE_CUSTOM_HEADERSenv-var-driven header injection.PYDANTIC_V1flag, supporting v1/v2/v3 without thepydantic.v1shim;SequenceNotStr,BinaryTypes/AsyncBinaryTypes, and module-levelnot_given/omitsingletons are added to_types.py.Confidence Score: 4/5
Safe to merge — the changes are auto-generated, well-structured, and the core request/retry logic refactoring is internally consistent.
The retry refactoring (recursion → loop) is the most load-bearing change; reviewing it carefully shows the idempotency key is correctly set once before retries start, and remaining_retries arithmetic is correct. The two findings — VoiceDeployment missing a name field and path_template's silent None→null conversion — are worth confirming against the API spec but neither causes a runtime failure in the current call sites. The Pydantic compatibility overhaul is broad but follows a clean PYDANTIC_V1 flag pattern.
Files Needing Attention: src/brainbase/types/workers/deployments/voice_deployment.py (confirm name field against API spec) and src/brainbase/_utils/_path.py (None parameter behaviour).
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[Client.workers.voice.create / update / retrieve / list] --> B[path_template\nPercent-encode path params\nReject dot-segments] B --> C[_build_request\nSet idempotency key once\nAdd X-Stainless-Read-Timeout\nStrip Content-Type on GET] C --> D{Retry loop\nmax_retries+1 iterations} D --> E[httpx.send / aiohttp.send] E -->|TimeoutException| F{remaining_retries > 0?} E -->|ConnectionError| F E -->|HTTP 4xx/5xx + should_retry| F F -->|Yes| G[_sleep_for_retry\ncontinue loop] G --> D F -->|No| H[Raise APIError] E -->|Success| I[_process_response\ncast_to VoiceDeployment\nor other model]Comments Outside Diff (1)
src/brainbase/types/workers/deployments/voice_deployment.py, line 12-21 (link)namefieldThe
nameparameter is required in bothVoiceCreateParamsandVoiceUpdateParams, butVoiceDeployment— the unified response model for create, retrieve, update, and list — has nonamefield. If the API returns anamein its response, callers cannot access it as a typed attribute. It will still be stored in the model's extra fields (becauseBaseModelhasextra="allow"), but there's no IDE-visible accessor. Worth confirming the API spec intentionally omitsnamefrom responses.Prompt To Fix With AI
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "release: 4.1.0" | Re-trigger Greptile