release: 1.22.0 - #182
Conversation
PR SummaryMedium Risk Overview HTTP client behavior adds optional default headers from the Multipart / file uploads gain configurable array field naming in Pydantic v2 adds an CI and dev tooling: Stainless SDK repos use Reviewed by Cursor Bugbot for commit 937bd8e. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
🧪 Testing To try out this version of the SDK: Expires at: Sat, 19 Sep 2026 04:57:47 GMT |
daa341f to
c1c63c6
Compare
c1c63c6 to
c267c54
Compare
c267c54 to
e979d10
Compare
e979d10 to
9c43dac
Compare
9c43dac to
6c0aed9
Compare
6c0aed9 to
081e108
Compare
081e108 to
8e32391
Compare
8e32391 to
4643c9e
Compare
4643c9e to
0e0ddb8
Compare
0e0ddb8 to
9e2ce51
Compare
9e2ce51 to
4929b7c
Compare
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.
4929b7c to
215a2ab
Compare
…t in workflow templates
215a2ab to
ab9d80a
Compare
ab9d80a to
937bd8e
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Array file paths drop non-lists
- extract_files now pops leftover path segments only when the value is actually a list, so a single file or other non-list stays in the request body instead of being discarded.
Or push these changes by commenting:
@cursor push b7dac59259
Preview (b7dac59259)
diff --git a/src/lumaai/_utils/_utils.py b/src/lumaai/_utils/_utils.py
--- a/src/lumaai/_utils/_utils.py
+++ b/src/lumaai/_utils/_utils.py
@@ -109,8 +109,10 @@
if is_dict(obj):
try:
# Remove the field if there are no more dict keys in the path,
- # only "<array>" traversal markers or end.
- if all(p == "<array>" for p in path[index:]):
+ # only "<array>" traversal markers or end. Only pop leftover
+ # "<array>" segments when the value is actually a list.
+ remaining = path[index:]
+ if not remaining or (all(p == "<array>" for p in remaining) and is_list(obj.get(key))):
item = obj.pop(key)
else:
item = obj[key]
diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py
--- a/tests/test_extract_files.py
+++ b/tests/test_extract_files.py
@@ -41,6 +41,20 @@
assert query == {"title": "hello"}
+def test_array_path_does_not_drop_non_list() -> None:
+ query = {"files": b"single file", "title": "hello"}
+ assert extract_files(query, paths=[["files", "<array>"]]) == []
+ assert query == {"files": b"single file", "title": "hello"}
+
+ nested = {"foo": {"files": b"single file"}, "keep": 1}
+ assert extract_files(nested, paths=[["foo", "files", "<array>"]]) == []
+ assert nested == {"foo": {"files": b"single file"}, "keep": 1}
+
+ query2 = {"files": {"not": "a list"}}
+ assert extract_files(query2, paths=[["files", "<array>"]]) == []
+ assert query2 == {"files": {"not": "a list"}}
+
+
@pytest.mark.parametrize(
"query,paths,expected",
[You can send follow-ups to the cloud agent here.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 937bd8e. Configure here.
| if (len(path)) == index: | ||
| # Remove the field if there are no more dict keys in the path, | ||
| # only "<array>" traversal markers or end. | ||
| if all(p == "<array>" for p in path[index:]): |
There was a problem hiding this comment.
Array file paths drop non-lists
Medium Severity
extract_files now pops a field whenever the remaining path is only <array> markers, before confirming the value is a list. A single file (or other non-list) is removed from the body and never emitted as a multipart part, so that input is dropped from the request entirely.
Reviewed by Cursor Bugbot for commit 937bd8e. Configure here.



Automated Release PR
1.22.0 (2026-08-20)
Full Changelog: v1.21.0...v1.22.0
Features
Bug Fixes
Performance Improvements
Chores
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