From 9731e382e9891fff3a429f5c3bc265b8ecf41d13 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 29 Mar 2026 07:12:40 +0000 Subject: [PATCH 001/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d5bade16..6c587a05 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-9dcbb133ea8d4e419314a5fddc878258610a80acfe82604b328a7eb3cb4f8f5f.yml -openapi_spec_hash: 10479661e623fc6063eafbba3f2b5dff +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-a84151f6a38bf7bf51ba18b5f89953041d0fa0d55e20e0963e7a6e4e879d7f92.yml +openapi_spec_hash: b7b27b00a0ba1db2bf4ead8d99e169c8 config_hash: 14efe98ee80f1e66ef35443e52f02953 From c9a79d6a8c96716ea565ac7c97aed396b9737a4d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 29 Mar 2026 22:12:45 +0000 Subject: [PATCH 002/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6c587a05..20caf862 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-a84151f6a38bf7bf51ba18b5f89953041d0fa0d55e20e0963e7a6e4e879d7f92.yml -openapi_spec_hash: b7b27b00a0ba1db2bf4ead8d99e169c8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-5725f0597f674c6e948d7eeea4a7083a5961701f1ab41a4925ee8e7ec0c51e29.yml +openapi_spec_hash: bead409a858bc21c2f9d8c48747a6109 config_hash: 14efe98ee80f1e66ef35443e52f02953 From f4c1aa4a3dc8afe17accb3b942daf00a9b6753f4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 18:12:53 +0000 Subject: [PATCH 003/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 20caf862..00e9a54d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-5725f0597f674c6e948d7eeea4a7083a5961701f1ab41a4925ee8e7ec0c51e29.yml -openapi_spec_hash: bead409a858bc21c2f9d8c48747a6109 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-aa7a5b73db1eaec68233c620991a8534ec0d1d2bfa2cac7c19c8c6afe45b4885.yml +openapi_spec_hash: 2278aecc02ea9ce18c0e4aac3a19b3d8 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 7317096babe5e45e97eeeed0031353e103bf9a65 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:12:52 +0000 Subject: [PATCH 004/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 00e9a54d..e9ee073d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-aa7a5b73db1eaec68233c620991a8534ec0d1d2bfa2cac7c19c8c6afe45b4885.yml -openapi_spec_hash: 2278aecc02ea9ce18c0e4aac3a19b3d8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-9785c1c79da8b3aa66bbd477b412199aef228ba5d6c76e22c42c2b86486e99b0.yml +openapi_spec_hash: 225134420d5dc6505a3a3070b4630e7f config_hash: 14efe98ee80f1e66ef35443e52f02953 From 9344c8c84df96bfd8a34067eee5c0711d5f365f0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 20:12:55 +0000 Subject: [PATCH 005/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e9ee073d..04504ec3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-9785c1c79da8b3aa66bbd477b412199aef228ba5d6c76e22c42c2b86486e99b0.yml -openapi_spec_hash: 225134420d5dc6505a3a3070b4630e7f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-f6578cd4a0fb47032d22aef27e037ffccc5f867c389009734a2d664fadfa2edf.yml +openapi_spec_hash: f39d514ea25d9971f63ccba74c385055 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 9110fcb2a4f90818e826127d353a04ca0a7c3f99 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 21:12:51 +0000 Subject: [PATCH 006/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 04504ec3..c495bdb5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-f6578cd4a0fb47032d22aef27e037ffccc5f867c389009734a2d664fadfa2edf.yml -openapi_spec_hash: f39d514ea25d9971f63ccba74c385055 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-a013b4b2d7a191deb744e270c9e36671a56755aa1e4947aa1a6c47bb0bd74522.yml +openapi_spec_hash: 8ababe03f384d092c5087af336a04397 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 68580e616d0743c04631a6a03f8f0c230dae9393 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 22:13:08 +0000 Subject: [PATCH 007/103] feat(api): api update --- .stats.yml | 4 ++-- .../types/split_table_options_param.py | 6 ++++++ tests/api_resources/test_split.py | 20 +++++++++++++++---- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index c495bdb5..ff2fb865 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-a013b4b2d7a191deb744e270c9e36671a56755aa1e4947aa1a6c47bb0bd74522.yml -openapi_spec_hash: 8ababe03f384d092c5087af336a04397 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-8a67a4230c9d972fa26ce75b3202346c05c8ebbf8500d2f9cff1a9d3ae737139.yml +openapi_spec_hash: b10a686101cb072711c7ed18078d7061 config_hash: 14efe98ee80f1e66ef35443e52f02953 diff --git a/src/reducto/types/split_table_options_param.py b/src/reducto/types/split_table_options_param.py index 740e863c..a4c29707 100644 --- a/src/reducto/types/split_table_options_param.py +++ b/src/reducto/types/split_table_options_param.py @@ -8,6 +8,12 @@ class SplitTableOptionsParam(TypedDict, total=False): + allow_page_overlap: bool + """If True, a page can belong to multiple categories/partitions. + + If False, each page must belong to exactly one category. Defaults to True. + """ + table_cutoff: Literal["truncate", "preserve"] """ If tables should be truncated to the first few rows or if all content should be diff --git a/tests/api_resources/test_split.py b/tests/api_resources/test_split.py index 2de2376f..af41c588 100644 --- a/tests/api_resources/test_split.py +++ b/tests/api_resources/test_split.py @@ -95,7 +95,10 @@ def test_method_run_with_all_params(self, client: Reducto) -> None: }, }, }, - settings={"table_cutoff": "truncate"}, + settings={ + "allow_page_overlap": True, + "table_cutoff": "truncate", + }, split_rules="split_rules", ) assert_matches_type(SplitResponse, split, path=["response"]) @@ -224,7 +227,10 @@ def test_method_run_job_with_all_params(self, client: Reducto) -> None: }, }, }, - settings={"table_cutoff": "truncate"}, + settings={ + "allow_page_overlap": True, + "table_cutoff": "truncate", + }, split_rules="split_rules", ) assert_matches_type(AsyncSplitResponse, split, path=["response"]) @@ -351,7 +357,10 @@ async def test_method_run_with_all_params(self, async_client: AsyncReducto) -> N }, }, }, - settings={"table_cutoff": "truncate"}, + settings={ + "allow_page_overlap": True, + "table_cutoff": "truncate", + }, split_rules="split_rules", ) assert_matches_type(SplitResponse, split, path=["response"]) @@ -480,7 +489,10 @@ async def test_method_run_job_with_all_params(self, async_client: AsyncReducto) }, }, }, - settings={"table_cutoff": "truncate"}, + settings={ + "allow_page_overlap": True, + "table_cutoff": "truncate", + }, split_rules="split_rules", ) assert_matches_type(AsyncSplitResponse, split, path=["response"]) From 3774aa0c535656c190cfbc5377815ff91774dc09 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 23:12:58 +0000 Subject: [PATCH 008/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index ff2fb865..551ff3a5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-8a67a4230c9d972fa26ce75b3202346c05c8ebbf8500d2f9cff1a9d3ae737139.yml -openapi_spec_hash: b10a686101cb072711c7ed18078d7061 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-55e59e8321d55efeca390c786a15d7b5c15f3447a353e77a33692ff96ed3c7e5.yml +openapi_spec_hash: 3f0d45f30cbecb1af0376e6df4457ef6 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 117ec654884ac13bdbd9e86e40441d7a5169aeda Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 00:12:55 +0000 Subject: [PATCH 009/103] feat(api): api update --- .stats.yml | 4 ++-- src/reducto/types/parse_usage.py | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 551ff3a5..6874716d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-55e59e8321d55efeca390c786a15d7b5c15f3447a353e77a33692ff96ed3c7e5.yml -openapi_spec_hash: 3f0d45f30cbecb1af0376e6df4457ef6 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-6f920cbb7dfd371cb4c975f617ab7b24917ef45be5dbc2e188b84999ba99ae2a.yml +openapi_spec_hash: 7135c104dfc28ece87fa04705fe5634c config_hash: 14efe98ee80f1e66ef35443e52f02953 diff --git a/src/reducto/types/parse_usage.py b/src/reducto/types/parse_usage.py index 74abb42d..a67ffc45 100644 --- a/src/reducto/types/parse_usage.py +++ b/src/reducto/types/parse_usage.py @@ -1,6 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, Optional +from typing import Dict, List, Optional +from typing_extensions import Literal from .._models import BaseModel @@ -13,3 +14,19 @@ class ParseUsage(BaseModel): credit_breakdown: Optional[Dict[str, float]] = None credits: Optional[float] = None + + page_billing_breakdown: Optional[ + Dict[ + str, + List[ + Literal[ + "page", "html_page", "docx_native_page", "agentic", "complex", "chart_agent", "spreadsheet_cells" + ] + ], + ] + ] = None + """Per-page breakdown of features used. + + Maps 1-indexed page numbers (as strings) to the list of billing features applied + on that page (e.g. 'page', 'complex', 'chart_agent'). + """ From c73a6717e2aaf48273a2bccfc3e8074ae6591589 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 17:12:46 +0000 Subject: [PATCH 010/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6874716d..a779492b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-6f920cbb7dfd371cb4c975f617ab7b24917ef45be5dbc2e188b84999ba99ae2a.yml -openapi_spec_hash: 7135c104dfc28ece87fa04705fe5634c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-72b0bcabddc0f5047bfe24ace69b39850c2bc33dde97db1879d2623c7b785158.yml +openapi_spec_hash: 974d8580e1e20098c8d1e78759b04161 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 0b87d9d46cee610611e9f14c4de6d85531015971 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 18:12:42 +0000 Subject: [PATCH 011/103] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index a779492b..1a06425c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-72b0bcabddc0f5047bfe24ace69b39850c2bc33dde97db1879d2623c7b785158.yml -openapi_spec_hash: 974d8580e1e20098c8d1e78759b04161 +openapi_spec_hash: fb344cd27b1109b60ef6f07f2e66a3df config_hash: 14efe98ee80f1e66ef35443e52f02953 From f17d871317d1617951918a505191023e4a9acd00 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 19:12:38 +0000 Subject: [PATCH 012/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1a06425c..19fc7470 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-72b0bcabddc0f5047bfe24ace69b39850c2bc33dde97db1879d2623c7b785158.yml -openapi_spec_hash: fb344cd27b1109b60ef6f07f2e66a3df +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-7c9e2128f7b792b0fcb1388ff190536e566ff57bb4ecdc85e109c5b87afd7aad.yml +openapi_spec_hash: 790b761c5f52d643ad4d7319a27d1d78 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 8374c19840d17f5b037773cd60083bff743f945f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 00:12:33 +0000 Subject: [PATCH 013/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 19fc7470..809e905a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-7c9e2128f7b792b0fcb1388ff190536e566ff57bb4ecdc85e109c5b87afd7aad.yml -openapi_spec_hash: 790b761c5f52d643ad4d7319a27d1d78 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-eb0239565433f1be5464872d144a39c6fddfba871d37953e610ae4b3bcf84765.yml +openapi_spec_hash: 64160bb7ceb786d6b693520e3c6136ed config_hash: 14efe98ee80f1e66ef35443e52f02953 From fc5d1fa8c5cef2b75a621d7fa142aa398b312a0e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 01:12:33 +0000 Subject: [PATCH 014/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 809e905a..a1453de6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-eb0239565433f1be5464872d144a39c6fddfba871d37953e610ae4b3bcf84765.yml -openapi_spec_hash: 64160bb7ceb786d6b693520e3c6136ed +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-f4850dffc0de034cdf31637d73868dcb6902178d9bc2d65637881203f0916a9b.yml +openapi_spec_hash: 1ec001354c7be267d736ea5bf78d252e config_hash: 14efe98ee80f1e66ef35443e52f02953 From b76548427ff7e4bea915db6dbbb1fb22c7471310 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 02:12:30 +0000 Subject: [PATCH 015/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index a1453de6..d540a74f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-f4850dffc0de034cdf31637d73868dcb6902178d9bc2d65637881203f0916a9b.yml -openapi_spec_hash: 1ec001354c7be267d736ea5bf78d252e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-7767033068b42cda48fd3e40e12aba82d51de6ce344c2e872674a1398603ea9c.yml +openapi_spec_hash: 61c87e5f6031ee998935fe8d5f984090 config_hash: 14efe98ee80f1e66ef35443e52f02953 From b8fdce2055dc6f7448e108f2029ec81a9704200d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 05:12:39 +0000 Subject: [PATCH 016/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d540a74f..93ee2e21 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-7767033068b42cda48fd3e40e12aba82d51de6ce344c2e872674a1398603ea9c.yml -openapi_spec_hash: 61c87e5f6031ee998935fe8d5f984090 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-291a8e226cee138c003d0803686f3f4a801be4d75d11708b8daf4f4cf2320522.yml +openapi_spec_hash: 6d642d25fe63e0e652b55111cdfc3971 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 9cfb3b5f3e19c0df72deb5c066f1fbbd2d24d77a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 06:12:40 +0000 Subject: [PATCH 017/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 93ee2e21..42949bd7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-291a8e226cee138c003d0803686f3f4a801be4d75d11708b8daf4f4cf2320522.yml -openapi_spec_hash: 6d642d25fe63e0e652b55111cdfc3971 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-795b6cf3510ca1a816f22b3bc37a74fdbb14d0278aa9fd3a5a11c70f6c51e8bd.yml +openapi_spec_hash: f6372c128d75f8ab00e345ed79eb6695 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 224996d84edbc74ef4c259a7fa5d4f5baa54d219 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:12:33 +0000 Subject: [PATCH 018/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 42949bd7..b78233ae 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-795b6cf3510ca1a816f22b3bc37a74fdbb14d0278aa9fd3a5a11c70f6c51e8bd.yml -openapi_spec_hash: f6372c128d75f8ab00e345ed79eb6695 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-37a0b358a1cdedb9e9a70fae2fc0eca28eb26abeab2ac8d58d6a845934b0a82d.yml +openapi_spec_hash: 62cdb8d681367c86cc3e01d2622468a7 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 04514db20c61c22828cebd1960eb74b28bc7ac43 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 19:12:43 +0000 Subject: [PATCH 019/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index b78233ae..4065a839 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-37a0b358a1cdedb9e9a70fae2fc0eca28eb26abeab2ac8d58d6a845934b0a82d.yml -openapi_spec_hash: 62cdb8d681367c86cc3e01d2622468a7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-9dcf831bd3aa27c3150266a1ada9ea0a048d9f7abfccb7112e975066a49d2efd.yml +openapi_spec_hash: ac7d7b08600bce9ba341654a6d19ceb8 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 1f00043e2751f1aedd5279d02a9979bf0aa475bc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 21:12:38 +0000 Subject: [PATCH 020/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4065a839..4535e1cf 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-9dcf831bd3aa27c3150266a1ada9ea0a048d9f7abfccb7112e975066a49d2efd.yml -openapi_spec_hash: ac7d7b08600bce9ba341654a6d19ceb8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ad80ccea986db3c204b07467500db29d32b665029f1a420bc7bcbbe5d494e8b9.yml +openapi_spec_hash: 68352a6b9b020bdb9e1f0ead92bffb3d config_hash: 14efe98ee80f1e66ef35443e52f02953 From 71929956801ec48a9c202a2cc48de3b0f6654f43 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 02:12:34 +0000 Subject: [PATCH 021/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4535e1cf..81f11e4b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ad80ccea986db3c204b07467500db29d32b665029f1a420bc7bcbbe5d494e8b9.yml -openapi_spec_hash: 68352a6b9b020bdb9e1f0ead92bffb3d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-1cc5b0f12365973a1a8b6b1891180c844cf80c60516643be09cf6680a76186c4.yml +openapi_spec_hash: 33199663f44acd70776fa2449945d930 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 604578fc82a9e0e9cd1c96140b288d5f7e9cfc96 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 03:12:31 +0000 Subject: [PATCH 022/103] feat(api): api update --- .stats.yml | 4 ++-- src/reducto/types/parse_usage.py | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 81f11e4b..551eaac4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-1cc5b0f12365973a1a8b6b1891180c844cf80c60516643be09cf6680a76186c4.yml -openapi_spec_hash: 33199663f44acd70776fa2449945d930 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-e2cdf83446e5a5681f9d8ab7fc7be09e2fb817249b89024500c9824d89bf62d3.yml +openapi_spec_hash: cfa97fc221b56c4a2fa1e41ab74ef856 config_hash: 14efe98ee80f1e66ef35443e52f02953 diff --git a/src/reducto/types/parse_usage.py b/src/reducto/types/parse_usage.py index a67ffc45..17b20133 100644 --- a/src/reducto/types/parse_usage.py +++ b/src/reducto/types/parse_usage.py @@ -20,7 +20,14 @@ class ParseUsage(BaseModel): str, List[ Literal[ - "page", "html_page", "docx_native_page", "agentic", "complex", "chart_agent", "spreadsheet_cells" + "page", + "html_page", + "docx_native_page", + "agentic", + "complex", + "chart_agent", + "spreadsheet_cells", + "billable_spreadsheet_pages", ] ], ] From 274ca16d5208e97a4950c301824b8cae09f86c12 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 16:12:38 +0000 Subject: [PATCH 023/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 551eaac4..968358c7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-e2cdf83446e5a5681f9d8ab7fc7be09e2fb817249b89024500c9824d89bf62d3.yml -openapi_spec_hash: cfa97fc221b56c4a2fa1e41ab74ef856 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-f0165cc85ea814378d85886f8f4ddf68320aee2a3aa51d0fdd6d091ae18b250a.yml +openapi_spec_hash: a045e701dae4fbd90dfcfe0a4ad50f9a config_hash: 14efe98ee80f1e66ef35443e52f02953 From 5bacc3120c92f8c834158f0e23f22d7823ed1b88 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 19:12:48 +0000 Subject: [PATCH 024/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 968358c7..4f1e8bf3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-f0165cc85ea814378d85886f8f4ddf68320aee2a3aa51d0fdd6d091ae18b250a.yml -openapi_spec_hash: a045e701dae4fbd90dfcfe0a4ad50f9a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-c5c5783a3605356c2ff578e37a0493f25b4fee6c089f0c334f2732f2d44847af.yml +openapi_spec_hash: 7c38f13abeceda217fefbffd57b2ef17 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 8fe48032b27113b09c6aaee1a417c59b8a245805 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 20:12:33 +0000 Subject: [PATCH 025/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4f1e8bf3..f911c6fe 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-c5c5783a3605356c2ff578e37a0493f25b4fee6c089f0c334f2732f2d44847af.yml -openapi_spec_hash: 7c38f13abeceda217fefbffd57b2ef17 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-96d58e98621d6df2c489729df5fa38f206d83c8f424ccec5b6d27ff375ae3a53.yml +openapi_spec_hash: 8a18f6a4b9e62d6822dd4896af1ba4b5 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 5abb2f90cbd2e73c770bc6d5aa2be6a52af141b6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 22:12:32 +0000 Subject: [PATCH 026/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f911c6fe..6efca889 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-96d58e98621d6df2c489729df5fa38f206d83c8f424ccec5b6d27ff375ae3a53.yml -openapi_spec_hash: 8a18f6a4b9e62d6822dd4896af1ba4b5 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-fcb9575685c61204f6fd0380384057e425fbd50f0c6ac5ca3f9172140093cd4f.yml +openapi_spec_hash: 7e4178eb5f23b9653f797f21accc3f50 config_hash: 14efe98ee80f1e66ef35443e52f02953 From deb2b31b9914481fad3e2e95bcc9433abd8c6462 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 00:12:38 +0000 Subject: [PATCH 027/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6efca889..0c1752e7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-fcb9575685c61204f6fd0380384057e425fbd50f0c6ac5ca3f9172140093cd4f.yml -openapi_spec_hash: 7e4178eb5f23b9653f797f21accc3f50 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-cd060f7f0fa6ddbdd5ee1fe96f0a8b99d1fa5e2c7f161cc0894fa060cfff4cbe.yml +openapi_spec_hash: 0ad486eb5857c7025b2c3d50f08c0fff config_hash: 14efe98ee80f1e66ef35443e52f02953 From 173baec86db42b5c1ee8fd72d50eff3cd2b7e807 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 18:12:41 +0000 Subject: [PATCH 028/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0c1752e7..9aa41462 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-cd060f7f0fa6ddbdd5ee1fe96f0a8b99d1fa5e2c7f161cc0894fa060cfff4cbe.yml -openapi_spec_hash: 0ad486eb5857c7025b2c3d50f08c0fff +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ea359bf0e80dd8ae215cb2842fc973f27427d836e4fd4e445a5c2579ef55238b.yml +openapi_spec_hash: fdb4a30b3b2e0291c49b8afe842a708c config_hash: 14efe98ee80f1e66ef35443e52f02953 From 50e757b9bdf58c9071fdd66fb98ddc062fd24e9d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 20:12:32 +0000 Subject: [PATCH 029/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9aa41462..50ae468b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ea359bf0e80dd8ae215cb2842fc973f27427d836e4fd4e445a5c2579ef55238b.yml -openapi_spec_hash: fdb4a30b3b2e0291c49b8afe842a708c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-d2e33e7e9c06e2964894d501d1697545bd363664f457bb54aac567e2d9c04fd5.yml +openapi_spec_hash: 774e8e086308bda721c7a923a2adee7e config_hash: 14efe98ee80f1e66ef35443e52f02953 From 7b291172b293ad4b8c8bd5c7af5f1557bd1bca91 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 21:12:33 +0000 Subject: [PATCH 030/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 50ae468b..56b40b5c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-d2e33e7e9c06e2964894d501d1697545bd363664f457bb54aac567e2d9c04fd5.yml -openapi_spec_hash: 774e8e086308bda721c7a923a2adee7e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-97829cbf4403d0ccd099bf9a5e5e8be6006bca8afa602de02a2523db580e5f8b.yml +openapi_spec_hash: bb373a25261bbe17512f0887e920f75b config_hash: 14efe98ee80f1e66ef35443e52f02953 From 690aa83b1224a698fe30fe2140d329031f7d23c5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 22:12:31 +0000 Subject: [PATCH 031/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 56b40b5c..ab035b21 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-97829cbf4403d0ccd099bf9a5e5e8be6006bca8afa602de02a2523db580e5f8b.yml -openapi_spec_hash: bb373a25261bbe17512f0887e920f75b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-47096a2028691753abd34906de25dd2fe82cfa92c01e312a83a39add624a1eb8.yml +openapi_spec_hash: d23db7e8b2cab2fa8fa7261e81df683f config_hash: 14efe98ee80f1e66ef35443e52f02953 From d6b60594501d0239bb598bcf91c60a1a63a05d0e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 23:12:30 +0000 Subject: [PATCH 032/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index ab035b21..e9f96426 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-47096a2028691753abd34906de25dd2fe82cfa92c01e312a83a39add624a1eb8.yml -openapi_spec_hash: d23db7e8b2cab2fa8fa7261e81df683f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-80908169ab6840ad4486b00af46b14d2928e5b15e9b1decee167d9903f155b67.yml +openapi_spec_hash: 98535b9fdf88f1a983f610b0e5b63e67 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 713ddf0bff488f4a97f84b3fa9d8851c30ce1d47 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:12:32 +0000 Subject: [PATCH 033/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e9f96426..d6e3d041 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-80908169ab6840ad4486b00af46b14d2928e5b15e9b1decee167d9903f155b67.yml -openapi_spec_hash: 98535b9fdf88f1a983f610b0e5b63e67 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-d5027be46fb8d1a7ad62983642862fb2d131058ba1a874d1defe4ecad0d7a556.yml +openapi_spec_hash: add5b3c740887d70a85bb09999d49e28 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 97ba85fd6709facfa76da94891c521fed8397436 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 18:12:33 +0000 Subject: [PATCH 034/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d6e3d041..2c90e2bd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-d5027be46fb8d1a7ad62983642862fb2d131058ba1a874d1defe4ecad0d7a556.yml -openapi_spec_hash: add5b3c740887d70a85bb09999d49e28 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-e7ba7639173bb705eeb83622c6311fca0409131ac7d2d5aee1ee3d409fcc6ac1.yml +openapi_spec_hash: 42dd6959f8443e6def3dd260d713bc0e config_hash: 14efe98ee80f1e66ef35443e52f02953 From 93c89fe6418217d6b48b5797c368f99b2eaba7ad Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 20:12:35 +0000 Subject: [PATCH 035/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2c90e2bd..a5b06f76 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-e7ba7639173bb705eeb83622c6311fca0409131ac7d2d5aee1ee3d409fcc6ac1.yml -openapi_spec_hash: 42dd6959f8443e6def3dd260d713bc0e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-b30a7a55fea0136bbe9eb0c7d870e6028aeee0a5efc9d759a2beea9607e7e706.yml +openapi_spec_hash: 2590388059734b0f921eea37b986ab1a config_hash: 14efe98ee80f1e66ef35443e52f02953 From b76a4d27b965cb5a84bd1ed59382895e6222de00 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 22:12:35 +0000 Subject: [PATCH 036/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index a5b06f76..4c07ea7a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-b30a7a55fea0136bbe9eb0c7d870e6028aeee0a5efc9d759a2beea9607e7e706.yml -openapi_spec_hash: 2590388059734b0f921eea37b986ab1a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-72d69e27a3f79d04afad20e779cf142051a4d981ac69105c6591b4c4ceebf12c.yml +openapi_spec_hash: 1cd45cf29c741bb38041252cb0f71b04 config_hash: 14efe98ee80f1e66ef35443e52f02953 From 9594ccc337b96a9ebad0599548fba02dd5f5a36f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 01:12:38 +0000 Subject: [PATCH 037/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4c07ea7a..6272f155 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-72d69e27a3f79d04afad20e779cf142051a4d981ac69105c6591b4c4ceebf12c.yml -openapi_spec_hash: 1cd45cf29c741bb38041252cb0f71b04 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-909015e871edecb3ae245c7bcebf6ac51030151866722c240e49c75e4d7a9bfe.yml +openapi_spec_hash: f3de44db5aa996b24d01eaac32b95f21 config_hash: 14efe98ee80f1e66ef35443e52f02953 From a54762b2a40c2da5e5b7e8dee56717bde8c94e61 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 21:14:53 +0000 Subject: [PATCH 038/103] chore: configure new SDK language --- .stats.yml | 2 +- README.md | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 6272f155..e4c43fdc 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-909015e871edecb3ae245c7bcebf6ac51030151866722c240e49c75e4d7a9bfe.yml openapi_spec_hash: f3de44db5aa996b24d01eaac32b95f21 -config_hash: 14efe98ee80f1e66ef35443e52f02953 +config_hash: 9fa10baf03f994be027bf73b29ac8572 diff --git a/README.md b/README.md index f0fc57fd..055265b1 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,15 @@ and offers both synchronous and asynchronous clients powered by [httpx](https:// It is generated with [Stainless](https://www.stainless.com/). +## MCP Server + +Use the Reducto MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application. + +[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=reductoai-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsInJlZHVjdG9haS1tY3AiXSwiZW52Ijp7IlJFRFVDVE9fQVBJX0tFWSI6Ik15IEFQSSBLZXkifX0) +[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22reductoai-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22reductoai-mcp%22%5D%2C%22env%22%3A%7B%22REDUCTO_API_KEY%22%3A%22My%20API%20Key%22%7D%7D) + +> Note: You may need to set environment variables in your MCP client. + ## Documentation The REST API documentation can be found on [docs.reductoai.com](https://docs.reductoai.com). The full API of this library can be found in [api.md](api.md). From 72d4eac3b2514c35b26fdafeecb1e64cc067ea80 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 02:07:55 +0000 Subject: [PATCH 039/103] fix(client): preserve hardcoded query params when merging with user params --- src/reducto/_base_client.py | 4 ++++ tests/test_client.py | 48 +++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/reducto/_base_client.py b/src/reducto/_base_client.py index 1e31cb4d..ee1f4314 100644 --- a/src/reducto/_base_client.py +++ b/src/reducto/_base_client.py @@ -558,6 +558,10 @@ def _build_request( files = cast(HttpxRequestFiles, ForceMultipartDict()) prepared_url = self._prepare_url(options.url) + # preserve hard-coded query params from the url + if params and prepared_url.query: + params = {**dict(prepared_url.params.items()), **params} + prepared_url = prepared_url.copy_with(raw_path=prepared_url.raw_path.split(b"?", 1)[0]) if "_" in prepared_url.host: # work around https://github.com/encode/httpx/discussions/2880 kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")} diff --git a/tests/test_client.py b/tests/test_client.py index 157a4300..95bc33e2 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -427,6 +427,30 @@ def test_default_query_option(self) -> None: client.close() + def test_hardcoded_query_params_in_url(self, client: Reducto) -> None: + request = client._build_request(FinalRequestOptions(method="get", url="/foo?beta=true")) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true"} + + request = client._build_request( + FinalRequestOptions( + method="get", + url="/foo?beta=true", + params={"limit": "10", "page": "abc"}, + ) + ) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true", "limit": "10", "page": "abc"} + + request = client._build_request( + FinalRequestOptions( + method="get", + url="/files/a%2Fb?beta=true", + params={"limit": "10"}, + ) + ) + assert request.url.raw_path == b"/files/a%2Fb?beta=true&limit=10" + def test_request_extra_json(self, client: Reducto) -> None: request = client._build_request( FinalRequestOptions( @@ -1328,6 +1352,30 @@ async def test_default_query_option(self) -> None: await client.close() + async def test_hardcoded_query_params_in_url(self, async_client: AsyncReducto) -> None: + request = async_client._build_request(FinalRequestOptions(method="get", url="/foo?beta=true")) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true"} + + request = async_client._build_request( + FinalRequestOptions( + method="get", + url="/foo?beta=true", + params={"limit": "10", "page": "abc"}, + ) + ) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true", "limit": "10", "page": "abc"} + + request = async_client._build_request( + FinalRequestOptions( + method="get", + url="/files/a%2Fb?beta=true", + params={"limit": "10"}, + ) + ) + assert request.url.raw_path == b"/files/a%2Fb?beta=true&limit=10" + def test_request_extra_json(self, client: Reducto) -> None: request = client._build_request( FinalRequestOptions( From 1aa9d1ae27a708c8658fc77e4cefe66e12995db8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 03:12:43 +0000 Subject: [PATCH 040/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e4c43fdc..957945df 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-909015e871edecb3ae245c7bcebf6ac51030151866722c240e49c75e4d7a9bfe.yml -openapi_spec_hash: f3de44db5aa996b24d01eaac32b95f21 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-6027f973a6f6048c223a46f1eb6e202034fd879b5dc66457ba53383340de206d.yml +openapi_spec_hash: 15ba253c0b9229186e50c20f43a4c6a4 config_hash: 9fa10baf03f994be027bf73b29ac8572 From dc09cfcdf0b276a3e0aaa5fbfb8cab983e109de4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 04:12:41 +0000 Subject: [PATCH 041/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 957945df..e4c43fdc 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-6027f973a6f6048c223a46f1eb6e202034fd879b5dc66457ba53383340de206d.yml -openapi_spec_hash: 15ba253c0b9229186e50c20f43a4c6a4 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-909015e871edecb3ae245c7bcebf6ac51030151866722c240e49c75e4d7a9bfe.yml +openapi_spec_hash: f3de44db5aa996b24d01eaac32b95f21 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 4a5c70781f1d48691b0eeabff944489ea075f631 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 21:12:33 +0000 Subject: [PATCH 042/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e4c43fdc..e57a6c7e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-909015e871edecb3ae245c7bcebf6ac51030151866722c240e49c75e4d7a9bfe.yml -openapi_spec_hash: f3de44db5aa996b24d01eaac32b95f21 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-7f583b0abe8f0d1373ba420e60d7dce079a34e4011cd6563391d55cfea38904e.yml +openapi_spec_hash: 1f85c7e745c2d4cd06d8941b7b698224 config_hash: 9fa10baf03f994be027bf73b29ac8572 From ae568c96084b78d24355d2183d06bfb8951b995e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 23:12:36 +0000 Subject: [PATCH 043/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e57a6c7e..92e7dde3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-7f583b0abe8f0d1373ba420e60d7dce079a34e4011cd6563391d55cfea38904e.yml -openapi_spec_hash: 1f85c7e745c2d4cd06d8941b7b698224 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ac7b0ea2f39a481f0ddc8db9061bf9cb47d5ed1016aece28e33e49e1a24c752c.yml +openapi_spec_hash: 485d53a2036d10457aa78e5aa2c45028 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 49c50b447c51da6dd566ef016be72a65bd6a69f3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 01:12:33 +0000 Subject: [PATCH 044/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 92e7dde3..a37a6991 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ac7b0ea2f39a481f0ddc8db9061bf9cb47d5ed1016aece28e33e49e1a24c752c.yml -openapi_spec_hash: 485d53a2036d10457aa78e5aa2c45028 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-44cd0e03741ed12f4a77a1c52e1c223d204c9db59524088cf8f3fdafd05b9a4b.yml +openapi_spec_hash: d5df075740321207fe2347f95de0683a config_hash: 9fa10baf03f994be027bf73b29ac8572 From 5f410d2da121c5074d70e7a6d4156641b3ca0905 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 21:12:33 +0000 Subject: [PATCH 045/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index a37a6991..36a9ba39 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-44cd0e03741ed12f4a77a1c52e1c223d204c9db59524088cf8f3fdafd05b9a4b.yml -openapi_spec_hash: d5df075740321207fe2347f95de0683a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-00fd6801264dbae6636cbff4adf786219dd5b8f6eeb393199a459145971e9731.yml +openapi_spec_hash: 7383c3202c3118c5c0b792ec759d9a35 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 5eb5782d4d9681a31e037ad682a542876bdb2efa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 22:12:37 +0000 Subject: [PATCH 046/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 36a9ba39..0575f04f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-00fd6801264dbae6636cbff4adf786219dd5b8f6eeb393199a459145971e9731.yml -openapi_spec_hash: 7383c3202c3118c5c0b792ec759d9a35 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-fd81681679afcd2c4b67e17acf6e1931bddce71a040433a55656e5aedd9c3ca5.yml +openapi_spec_hash: 9e418826f20acb29130fc3fd97e7eb16 config_hash: 9fa10baf03f994be027bf73b29ac8572 From aae74574a5324dc56fa21cd4ec455dee62cae162 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 03:12:33 +0000 Subject: [PATCH 047/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0575f04f..71b0a926 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-fd81681679afcd2c4b67e17acf6e1931bddce71a040433a55656e5aedd9c3ca5.yml -openapi_spec_hash: 9e418826f20acb29130fc3fd97e7eb16 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-25b8ffdcb5543ff9e3306645405651c2d538547f534a2df25bc378313bac2160.yml +openapi_spec_hash: f87c3a6f387c20df1543853a64f0a51a config_hash: 9fa10baf03f994be027bf73b29ac8572 From 6d227f8f4681fc675ca0eec196da8f28740b9e3d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 07:12:37 +0000 Subject: [PATCH 048/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 71b0a926..a0e08c66 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-25b8ffdcb5543ff9e3306645405651c2d538547f534a2df25bc378313bac2160.yml -openapi_spec_hash: f87c3a6f387c20df1543853a64f0a51a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-89b07255ef1c62b80012bdc17421939d61faa8d66ffb49266787aa5aee74d532.yml +openapi_spec_hash: 0f4a9dc896b86f7717a19a9264c73457 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 2c12f11e59b8f065719f437a8652f434f047dda1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 11 Apr 2026 01:12:39 +0000 Subject: [PATCH 049/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index a0e08c66..a34d9817 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-89b07255ef1c62b80012bdc17421939d61faa8d66ffb49266787aa5aee74d532.yml -openapi_spec_hash: 0f4a9dc896b86f7717a19a9264c73457 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-c405eb2d0f0ef8bac877fd956606d60feb1bf4e0e38ad99e3df00dc6b92657ca.yml +openapi_spec_hash: 95f4ae86e756e1c48345dc0d0d4a8bc8 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 5a5d5eed5f5bf34df796e73355824dafc30c492b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 11 Apr 2026 02:08:35 +0000 Subject: [PATCH 050/103] fix: ensure file data are only sent as 1 parameter --- src/reducto/_utils/_utils.py | 5 +++-- tests/test_extract_files.py | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/reducto/_utils/_utils.py b/src/reducto/_utils/_utils.py index eec7f4a1..63b8cd60 100644 --- a/src/reducto/_utils/_utils.py +++ b/src/reducto/_utils/_utils.py @@ -86,8 +86,9 @@ def _extract_items( index += 1 if is_dict(obj): try: - # We are at the last entry in the path so we must remove the field - if (len(path)) == index: + # Remove the field if there are no more dict keys in the path, + # only "" traversal markers or end. + if all(p == "" for p in path[index:]): item = obj.pop(key) else: item = obj[key] diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index a4c8a66f..9e158a96 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -35,6 +35,15 @@ def test_multiple_files() -> None: assert query == {"documents": [{}, {}]} +def test_top_level_file_array() -> None: + query = {"files": [b"file one", b"file two"], "title": "hello"} + assert extract_files(query, paths=[["files", ""]]) == [ + ("files[]", b"file one"), + ("files[]", b"file two"), + ] + assert query == {"title": "hello"} + + @pytest.mark.parametrize( "query,paths,expected", [ From f7b90fa8da10e32ec26f71313bd8eef7aac4bf83 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 11 Apr 2026 04:12:34 +0000 Subject: [PATCH 051/103] feat(api): api update --- .stats.yml | 4 +-- src/reducto/types/__init__.py | 1 - src/reducto/types/extract_usage.py | 18 ------------- src/reducto/types/shared/extract_response.py | 25 +++---------------- src/reducto/types/shared/pipeline_response.py | 17 +++---------- src/reducto/types/v3_extract.py | 22 +++------------- 6 files changed, 11 insertions(+), 76 deletions(-) delete mode 100644 src/reducto/types/extract_usage.py diff --git a/.stats.yml b/.stats.yml index a34d9817..ba63085e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-c405eb2d0f0ef8bac877fd956606d60feb1bf4e0e38ad99e3df00dc6b92657ca.yml -openapi_spec_hash: 95f4ae86e756e1c48345dc0d0d4a8bc8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-2714c6a71511a557b25a6e48ff64cc317d8b5df4f055a6e1968419ca7c0e6550.yml +openapi_spec_hash: 01a53f60cbb0e94dd307a914c46eb8d1 config_hash: 9fa10baf03f994be027bf73b29ac8572 diff --git a/src/reducto/types/__init__.py b/src/reducto/types/__init__.py index c0641ad1..3f217832 100644 --- a/src/reducto/types/__init__.py +++ b/src/reducto/types/__init__.py @@ -40,7 +40,6 @@ from .parse_usage import ParseUsage as ParseUsage from .bounding_box import BoundingBox as BoundingBox from .enhance_param import EnhanceParam as EnhanceParam -from .extract_usage import ExtractUsage as ExtractUsage from .settings_param import SettingsParam as SettingsParam from .edit_run_params import EditRunParams as EditRunParams from .retrieval_param import RetrievalParam as RetrievalParam diff --git a/src/reducto/types/extract_usage.py b/src/reducto/types/extract_usage.py deleted file mode 100644 index 2d6a0a30..00000000 --- a/src/reducto/types/extract_usage.py +++ /dev/null @@ -1,18 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from .._models import BaseModel - -__all__ = ["ExtractUsage"] - - -class ExtractUsage(BaseModel): - num_fields: int - - num_pages: int - - credits: Optional[float] = None - - extract_mode: Optional[Literal["super_agent", "extract", "spreadsheet_agent"]] = None diff --git a/src/reducto/types/shared/extract_response.py b/src/reducto/types/shared/extract_response.py index 1744516d..b071e9fc 100644 --- a/src/reducto/types/shared/extract_response.py +++ b/src/reducto/types/shared/extract_response.py @@ -1,27 +1,8 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional - -from ..._models import BaseModel -from ..extract_usage import ExtractUsage +from typing import Dict +from typing_extensions import TypeAlias __all__ = ["ExtractResponse"] - -class ExtractResponse(BaseModel): - citations: Optional[List[object]] = None - """The citations corresponding to the extracted response.""" - - result: List[object] - """The extracted response in your provided schema. - - This is a list of dictionaries. If disable_chunking is True (default), then it - will be a list of length one. - """ - - usage: ExtractUsage - - job_id: Optional[str] = None - - studio_link: Optional[str] = None - """The link to the studio pipeline for the document.""" +ExtractResponse: TypeAlias = Dict[str, object] diff --git a/src/reducto/types/shared/pipeline_response.py b/src/reducto/types/shared/pipeline_response.py index 3e6d9c59..1c5359dd 100644 --- a/src/reducto/types/shared/pipeline_response.py +++ b/src/reducto/types/shared/pipeline_response.py @@ -11,16 +11,7 @@ from .split_response import SplitResponse from .extract_response import ExtractResponse -__all__ = [ - "PipelineResponse", - "Result", - "ResultExtract", - "ResultExtractUnionMember0", - "ResultExtractUnionMember0Result", - "ResultParse", -] - -ResultExtractUnionMember0Result: TypeAlias = Union[ExtractResponse, V3Extract] +__all__ = ["PipelineResponse", "Result", "ResultExtractUnionMember0", "ResultParse"] class ResultExtractUnionMember0(BaseModel): @@ -28,20 +19,18 @@ class ResultExtractUnionMember0(BaseModel): page_range: List[int] - result: ResultExtractUnionMember0Result + result: Union[ExtractResponse, V3Extract] split_name: str partition: Optional[str] = None -ResultExtract: TypeAlias = Union[List[ResultExtractUnionMember0], ExtractResponse, V3Extract, None] - ResultParse: TypeAlias = Union[ParseResponse, List[ParseResponse], None] class Result(BaseModel): - extract: Optional[ResultExtract] = None + extract: Union[List[ResultExtractUnionMember0], ExtractResponse, V3Extract, None] = None parse: Optional[ResultParse] = None diff --git a/src/reducto/types/v3_extract.py b/src/reducto/types/v3_extract.py index e2b61eb0..2f197e6f 100644 --- a/src/reducto/types/v3_extract.py +++ b/src/reducto/types/v3_extract.py @@ -1,24 +1,8 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Union, Optional - -from .._models import BaseModel -from .extract_usage import ExtractUsage +from typing import Dict +from typing_extensions import TypeAlias __all__ = ["V3Extract"] - -class V3Extract(BaseModel): - result: Union[List[object], object] - """The extracted response in your provided schema. - - This is a list of dictionaries. If disable_chunking is True (default), then it - will be a list of length one. - """ - - usage: ExtractUsage - - job_id: Optional[str] = None - - studio_link: Optional[str] = None - """The link to the studio pipeline for the document.""" +V3Extract: TypeAlias = Dict[str, object] From 707c9c3864ae6a82194d5af0bc0c60c7dff7be98 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 21:12:36 +0000 Subject: [PATCH 052/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index ba63085e..1326b5ce 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-2714c6a71511a557b25a6e48ff64cc317d8b5df4f055a6e1968419ca7c0e6550.yml -openapi_spec_hash: 01a53f60cbb0e94dd307a914c46eb8d1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-0f32cd43f48d7950c980686efe301bf48ed6e02031376d8060b99fc8235a67d1.yml +openapi_spec_hash: 4a197feccb27145d2ac4da356cbdcb07 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 1e321625e3cdc7d166990da290eb91ee8ea0a08c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 15:12:40 +0000 Subject: [PATCH 053/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1326b5ce..c4e2dcb9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-0f32cd43f48d7950c980686efe301bf48ed6e02031376d8060b99fc8235a67d1.yml -openapi_spec_hash: 4a197feccb27145d2ac4da356cbdcb07 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-3c897e9af4fb27c2531bde46c076775d7e012039cada998576d07a241f485a87.yml +openapi_spec_hash: 1caa2e7294bcc07cfa89b1cf39c2e362 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 50924d198c40125021dcaa8c7da8844b9cfe6382 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 18:12:41 +0000 Subject: [PATCH 054/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c4e2dcb9..478555b8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-3c897e9af4fb27c2531bde46c076775d7e012039cada998576d07a241f485a87.yml -openapi_spec_hash: 1caa2e7294bcc07cfa89b1cf39c2e362 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-190fd6622115407de2871b2c2b0aac45bbd7a3f9c83f3c44412fa933d1511c5f.yml +openapi_spec_hash: fcf713955ffe437a447b1790a37bb82a config_hash: 9fa10baf03f994be027bf73b29ac8572 From b931135e0d1316d80266617f6024d1d5f6915385 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 00:12:38 +0000 Subject: [PATCH 055/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 478555b8..2d3c1371 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-190fd6622115407de2871b2c2b0aac45bbd7a3f9c83f3c44412fa933d1511c5f.yml -openapi_spec_hash: fcf713955ffe437a447b1790a37bb82a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-53c9f34fa73f745c6cd62494a216bc078bb935f4f4ae2f08482ee481231d5850.yml +openapi_spec_hash: 4ed5b6f007e2084b2093dfb1fb8bf558 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 649a47a84b8f931437fad418dd09d3f045af68bb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 01:12:45 +0000 Subject: [PATCH 056/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2d3c1371..af551da4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-53c9f34fa73f745c6cd62494a216bc078bb935f4f4ae2f08482ee481231d5850.yml -openapi_spec_hash: 4ed5b6f007e2084b2093dfb1fb8bf558 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ef603a65b5d3c2e5186a7625ebae2ff30260025456061331345cdf85dde55086.yml +openapi_spec_hash: cd29c0540293a911dbeecb258fe32e63 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 93905068179a3e3d65db16a0bcad7c50798fd76b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 03:12:36 +0000 Subject: [PATCH 057/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index af551da4..451f14d5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ef603a65b5d3c2e5186a7625ebae2ff30260025456061331345cdf85dde55086.yml -openapi_spec_hash: cd29c0540293a911dbeecb258fe32e63 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-7b9df39d70396663501e3bae8eceef3432569a8ba0ce12050d043820145e26f6.yml +openapi_spec_hash: 7ad05621fd208b1cfac9ee7592407f66 config_hash: 9fa10baf03f994be027bf73b29ac8572 From d37859dfa3e278a0f625c8715cac3d383b69be88 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 17:12:51 +0000 Subject: [PATCH 058/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 451f14d5..983ecd5f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-7b9df39d70396663501e3bae8eceef3432569a8ba0ce12050d043820145e26f6.yml -openapi_spec_hash: 7ad05621fd208b1cfac9ee7592407f66 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ac994ccab6e4e151b0d433d08642cab90d939c9e2b44d28087bebad13f7ec3e4.yml +openapi_spec_hash: 81159a4e0d5a29e738439decc3379465 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 545e3064c875fa4d9759d239b4b8e15e4f1741d1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 20:12:56 +0000 Subject: [PATCH 059/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 983ecd5f..ad9d3057 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ac994ccab6e4e151b0d433d08642cab90d939c9e2b44d28087bebad13f7ec3e4.yml -openapi_spec_hash: 81159a4e0d5a29e738439decc3379465 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-190bbabd8d3d7bfef42399a6acb6f2d9a0e965bbc7d03ee0397c3e7df5b547fe.yml +openapi_spec_hash: d08f20d455f275f8b05da4b835eb7a27 config_hash: 9fa10baf03f994be027bf73b29ac8572 From fda0e63f4dad8328e7ae36b93143d765c956d797 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 22:12:50 +0000 Subject: [PATCH 060/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index ad9d3057..1dcc6d68 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-190bbabd8d3d7bfef42399a6acb6f2d9a0e965bbc7d03ee0397c3e7df5b547fe.yml -openapi_spec_hash: d08f20d455f275f8b05da4b835eb7a27 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-c2b7bb5dd7c39b937f800cec69c4316bac82ae36ff180bc14c000e79830ac463.yml +openapi_spec_hash: 95827dd2170cb25e2e4feeb3cae1abbf config_hash: 9fa10baf03f994be027bf73b29ac8572 From feb94b50851c19b03944d6bea46324b1839fb03c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 00:12:51 +0000 Subject: [PATCH 061/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1dcc6d68..86f7f9b5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-c2b7bb5dd7c39b937f800cec69c4316bac82ae36ff180bc14c000e79830ac463.yml -openapi_spec_hash: 95827dd2170cb25e2e4feeb3cae1abbf +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-57ffebe4495e07de3cb29354b4bc69a1a4c69daef1134079c5953fddca6b31aa.yml +openapi_spec_hash: 4a2b08397f9ef7ff6dfc09e0695233a1 config_hash: 9fa10baf03f994be027bf73b29ac8572 From c47f11afcacac318209e04b49dc3ba3a4fa549b6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 05:12:41 +0000 Subject: [PATCH 062/103] feat(api): api update --- .stats.yml | 4 ++-- .../types/shared/experimental_processing_options.py | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 86f7f9b5..e920eadb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-57ffebe4495e07de3cb29354b4bc69a1a4c69daef1134079c5953fddca6b31aa.yml -openapi_spec_hash: 4a2b08397f9ef7ff6dfc09e0695233a1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ac5d9fa4fc671803ac11db02ee3200edd7bba978ddce2780305fafc75aaf07e3.yml +openapi_spec_hash: 7e4e965e7d07f2f8bc371d1a9ee5e74f config_hash: 9fa10baf03f994be027bf73b29ac8572 diff --git a/src/reducto/types/shared/experimental_processing_options.py b/src/reducto/types/shared/experimental_processing_options.py index 1f4d9ac2..90c9a136 100644 --- a/src/reducto/types/shared/experimental_processing_options.py +++ b/src/reducto/types/shared/experimental_processing_options.py @@ -75,7 +75,15 @@ class ExperimentalProcessingOptions(BaseModel): layout_model: Optional[ Literal[ - "default", "beta", "rfdetr", "rfdetr0302", "rfdetr0303", "rfdetrbase0218", "rfdetr0304", "qwen35_27b_0317" + "default", + "beta", + "dfine", + "rfdetr", + "rfdetr0302", + "rfdetr0303", + "rfdetrbase0218", + "rfdetr0304", + "qwen35_27b_0317", ] ] = None """The layout model to use for the document. From 92b16bdfa8c4b0e577dc00e9f795d96bc7944c61 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 23:12:50 +0000 Subject: [PATCH 063/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e920eadb..ff33082c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ac5d9fa4fc671803ac11db02ee3200edd7bba978ddce2780305fafc75aaf07e3.yml -openapi_spec_hash: 7e4e965e7d07f2f8bc371d1a9ee5e74f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-62084f3425c2ffac3857d6270c6f136c842c6d72039573aa4d8e2d5206d825c8.yml +openapi_spec_hash: 05d764ad3fc51207de437dbe1ee50b61 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 159d1831274f3a6b72073a6f13f4c2b80cc5d184 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 01:12:39 +0000 Subject: [PATCH 064/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index ff33082c..48226d10 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-62084f3425c2ffac3857d6270c6f136c842c6d72039573aa4d8e2d5206d825c8.yml -openapi_spec_hash: 05d764ad3fc51207de437dbe1ee50b61 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-4c5c9cc4b785b9e1ffeff8c0c587cdb54812cd07e63dd4f58ca9b9411185af14.yml +openapi_spec_hash: 63ecc9bd072d72b4d83ab3d20aaf61d0 config_hash: 9fa10baf03f994be027bf73b29ac8572 From dff635978cdd605235bc2e30b8a79f12a0b5b5f9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 02:12:53 +0000 Subject: [PATCH 065/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 48226d10..78f88644 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-4c5c9cc4b785b9e1ffeff8c0c587cdb54812cd07e63dd4f58ca9b9411185af14.yml -openapi_spec_hash: 63ecc9bd072d72b4d83ab3d20aaf61d0 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-420204f046b750d0665ec5899470d733d2556e264b5358ba9e4458bbdf6ff2a2.yml +openapi_spec_hash: 8d72761f7a9e83d2ed7ffe1b85f6eb61 config_hash: 9fa10baf03f994be027bf73b29ac8572 From c98d415d1e39206134afc4c29c3e646e6d2d1099 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 04:12:43 +0000 Subject: [PATCH 066/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 78f88644..68e2476f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-420204f046b750d0665ec5899470d733d2556e264b5358ba9e4458bbdf6ff2a2.yml -openapi_spec_hash: 8d72761f7a9e83d2ed7ffe1b85f6eb61 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-9664ddf167d04b13da552bc6761d998a85076d8c8c466d01b5c01aeedeead226.yml +openapi_spec_hash: 90fd9b742d614335509f0d0b9873d5c1 config_hash: 9fa10baf03f994be027bf73b29ac8572 From d2d9fc2ab66811c0b9a3d535acb0341574604739 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 17:12:40 +0000 Subject: [PATCH 067/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 68e2476f..c7807254 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-9664ddf167d04b13da552bc6761d998a85076d8c8c466d01b5c01aeedeead226.yml -openapi_spec_hash: 90fd9b742d614335509f0d0b9873d5c1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-dcd29a317223209fd2db066c914a2e58ddf0e53d398cad78a209f9ff279dd123.yml +openapi_spec_hash: 7d36288ac54bf244fffee1c775ebff6b config_hash: 9fa10baf03f994be027bf73b29ac8572 From b85232723af7788e68815321a3244fe953c84566 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 21:12:40 +0000 Subject: [PATCH 068/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c7807254..fb86aa75 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-dcd29a317223209fd2db066c914a2e58ddf0e53d398cad78a209f9ff279dd123.yml -openapi_spec_hash: 7d36288ac54bf244fffee1c775ebff6b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-0de6c58d0748d56e2c2bd5d0bc1bbcb8b291a13929c10edd1b5586b134791e88.yml +openapi_spec_hash: 6fba69b7e0f3f16f231f3ec42d714283 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 094e95ff0fcca8233e196310e014a033fc31fe8e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 02:13:07 +0000 Subject: [PATCH 069/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index fb86aa75..72689081 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-0de6c58d0748d56e2c2bd5d0bc1bbcb8b291a13929c10edd1b5586b134791e88.yml -openapi_spec_hash: 6fba69b7e0f3f16f231f3ec42d714283 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-787866cad3a80d7f704d5b099a706bf433146952fe9ea187a165c1d8b23ee039.yml +openapi_spec_hash: 4852284fd1c2b3f953142afeeb3c97aa config_hash: 9fa10baf03f994be027bf73b29ac8572 From fae719428bbc73108ed0e3e569c5c65af3cea90a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 02:14:54 +0000 Subject: [PATCH 070/103] perf(client): optimize file structure copying in multipart requests --- src/reducto/_client.py | 6 +-- src/reducto/_files.py | 56 +++++++++++++++++-- src/reducto/_utils/__init__.py | 1 - src/reducto/_utils/_utils.py | 15 ------ tests/test_deepcopy.py | 58 -------------------- tests/test_files.py | 99 +++++++++++++++++++++++++++++++++- 6 files changed, 154 insertions(+), 81 deletions(-) delete mode 100644 tests/test_deepcopy.py diff --git a/src/reducto/_client.py b/src/reducto/_client.py index df400032..81ebe7a3 100644 --- a/src/reducto/_client.py +++ b/src/reducto/_client.py @@ -11,6 +11,7 @@ from . import _exceptions from ._qs import Querystring from .types import client_upload_params +from ._files import deepcopy_with_paths from ._types import ( Body, Omit, @@ -29,7 +30,6 @@ is_given, extract_files, maybe_transform, - deepcopy_minimal, get_async_library, async_maybe_transform, ) @@ -338,7 +338,7 @@ def upload( timeout: Override the client-level default timeout for this request, in seconds """ - body = deepcopy_minimal({"file": file}) + body = deepcopy_with_paths({"file": file}, [["file"]]) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) if files: # It should be noted that the actual Content-Type header that will be @@ -649,7 +649,7 @@ async def upload( timeout: Override the client-level default timeout for this request, in seconds """ - body = deepcopy_minimal({"file": file}) + body = deepcopy_with_paths({"file": file}, [["file"]]) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) if files: # It should be noted that the actual Content-Type header that will be diff --git a/src/reducto/_files.py b/src/reducto/_files.py index 7f056768..a4b9a7b1 100644 --- a/src/reducto/_files.py +++ b/src/reducto/_files.py @@ -3,8 +3,8 @@ import io import os import pathlib -from typing import overload -from typing_extensions import TypeGuard +from typing import Sequence, cast, overload +from typing_extensions import TypeVar, TypeGuard import anyio @@ -17,7 +17,9 @@ HttpxFileContent, HttpxRequestFiles, ) -from ._utils import is_tuple_t, is_mapping_t, is_sequence_t +from ._utils import is_list, is_mapping, is_tuple_t, is_mapping_t, is_sequence_t + +_T = TypeVar("_T") def is_base64_file_input(obj: object) -> TypeGuard[Base64FileInput]: @@ -121,3 +123,51 @@ async def async_read_file_content(file: FileContent) -> HttpxFileContent: return await anyio.Path(file).read_bytes() return file + + +def deepcopy_with_paths(item: _T, paths: Sequence[Sequence[str]]) -> _T: + """Copy only the containers along the given paths. + + Used to guard against mutation by extract_files without copying the entire structure. + Only dicts and lists that lie on a path are copied; everything else + is returned by reference. + + For example, given paths=[["foo", "files", "file"]] and the structure: + { + "foo": { + "bar": {"baz": {}}, + "files": {"file": } + } + } + The root dict, "foo", and "files" are copied (they lie on the path). + "bar" and "baz" are returned by reference (off the path). + """ + return _deepcopy_with_paths(item, paths, 0) + + +def _deepcopy_with_paths(item: _T, paths: Sequence[Sequence[str]], index: int) -> _T: + if not paths: + return item + if is_mapping(item): + key_to_paths: dict[str, list[Sequence[str]]] = {} + for path in paths: + if index < len(path): + key_to_paths.setdefault(path[index], []).append(path) + + # if no path continues through this mapping, it won't be mutated and copying it is redundant + if not key_to_paths: + return item + + result = dict(item) + for key, subpaths in key_to_paths.items(): + if key in result: + result[key] = _deepcopy_with_paths(result[key], subpaths, index + 1) + return cast(_T, result) + if is_list(item): + array_paths = [path for path in paths if index < len(path) and path[index] == ""] + + # if no path expects a list here, nothing will be mutated inside it - return by reference + if not array_paths: + return cast(_T, item) + return cast(_T, [_deepcopy_with_paths(entry, array_paths, index + 1) for entry in item]) + return item diff --git a/src/reducto/_utils/__init__.py b/src/reducto/_utils/__init__.py index 10cb66d2..1c090e51 100644 --- a/src/reducto/_utils/__init__.py +++ b/src/reducto/_utils/__init__.py @@ -24,7 +24,6 @@ coerce_integer as coerce_integer, file_from_path as file_from_path, strip_not_given as strip_not_given, - deepcopy_minimal as deepcopy_minimal, get_async_library as get_async_library, maybe_coerce_float as maybe_coerce_float, get_required_header as get_required_header, diff --git a/src/reducto/_utils/_utils.py b/src/reducto/_utils/_utils.py index 63b8cd60..771859f5 100644 --- a/src/reducto/_utils/_utils.py +++ b/src/reducto/_utils/_utils.py @@ -177,21 +177,6 @@ def is_iterable(obj: object) -> TypeGuard[Iterable[object]]: return isinstance(obj, Iterable) -def deepcopy_minimal(item: _T) -> _T: - """Minimal reimplementation of copy.deepcopy() that will only copy certain object types: - - - mappings, e.g. `dict` - - list - - This is done for performance reasons. - """ - if is_mapping(item): - return cast(_T, {k: deepcopy_minimal(v) for k, v in item.items()}) - if is_list(item): - return cast(_T, [deepcopy_minimal(entry) for entry in item]) - return item - - # copied from https://github.com/Rapptz/RoboDanny def human_join(seq: Sequence[str], *, delim: str = ", ", final: str = "or") -> str: size = len(seq) diff --git a/tests/test_deepcopy.py b/tests/test_deepcopy.py deleted file mode 100644 index f2e61051..00000000 --- a/tests/test_deepcopy.py +++ /dev/null @@ -1,58 +0,0 @@ -from reducto._utils import deepcopy_minimal - - -def assert_different_identities(obj1: object, obj2: object) -> None: - assert obj1 == obj2 - assert id(obj1) != id(obj2) - - -def test_simple_dict() -> None: - obj1 = {"foo": "bar"} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - - -def test_nested_dict() -> None: - obj1 = {"foo": {"bar": True}} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert_different_identities(obj1["foo"], obj2["foo"]) - - -def test_complex_nested_dict() -> None: - obj1 = {"foo": {"bar": [{"hello": "world"}]}} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert_different_identities(obj1["foo"], obj2["foo"]) - assert_different_identities(obj1["foo"]["bar"], obj2["foo"]["bar"]) - assert_different_identities(obj1["foo"]["bar"][0], obj2["foo"]["bar"][0]) - - -def test_simple_list() -> None: - obj1 = ["a", "b", "c"] - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - - -def test_nested_list() -> None: - obj1 = ["a", [1, 2, 3]] - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert_different_identities(obj1[1], obj2[1]) - - -class MyObject: ... - - -def test_ignores_other_types() -> None: - # custom classes - my_obj = MyObject() - obj1 = {"foo": my_obj} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert obj1["foo"] is my_obj - - # tuples - obj3 = ("a", "b") - obj4 = deepcopy_minimal(obj3) - assert obj3 is obj4 diff --git a/tests/test_files.py b/tests/test_files.py index b5e73903..b76db4fd 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -4,7 +4,8 @@ import pytest from dirty_equals import IsDict, IsList, IsBytes, IsTuple -from reducto._files import to_httpx_files, async_to_httpx_files +from reducto._files import to_httpx_files, deepcopy_with_paths, async_to_httpx_files +from reducto._utils import extract_files readme_path = Path(__file__).parent.parent.joinpath("README.md") @@ -49,3 +50,99 @@ def test_string_not_allowed() -> None: "file": "foo", # type: ignore } ) + + +def assert_different_identities(obj1: object, obj2: object) -> None: + assert obj1 == obj2 + assert obj1 is not obj2 + + +class TestDeepcopyWithPaths: + def test_copies_top_level_dict(self) -> None: + original = {"file": b"data", "other": "value"} + result = deepcopy_with_paths(original, [["file"]]) + assert_different_identities(result, original) + + def test_file_value_is_same_reference(self) -> None: + file_bytes = b"contents" + original = {"file": file_bytes} + result = deepcopy_with_paths(original, [["file"]]) + assert_different_identities(result, original) + assert result["file"] is file_bytes + + def test_list_popped_wholesale(self) -> None: + files = [b"f1", b"f2"] + original = {"files": files, "title": "t"} + result = deepcopy_with_paths(original, [["files", ""]]) + assert_different_identities(result, original) + result_files = result["files"] + assert isinstance(result_files, list) + assert_different_identities(result_files, files) + + def test_nested_array_path_copies_list_and_elements(self) -> None: + elem1 = {"file": b"f1", "extra": 1} + elem2 = {"file": b"f2", "extra": 2} + original = {"items": [elem1, elem2]} + result = deepcopy_with_paths(original, [["items", "", "file"]]) + assert_different_identities(result, original) + result_items = result["items"] + assert isinstance(result_items, list) + assert_different_identities(result_items, original["items"]) + assert_different_identities(result_items[0], elem1) + assert_different_identities(result_items[1], elem2) + + def test_empty_paths_returns_same_object(self) -> None: + original = {"foo": "bar"} + result = deepcopy_with_paths(original, []) + assert result is original + + def test_multiple_paths(self) -> None: + f1 = b"file1" + f2 = b"file2" + original = {"a": f1, "b": f2, "c": "unchanged"} + result = deepcopy_with_paths(original, [["a"], ["b"]]) + assert_different_identities(result, original) + assert result["a"] is f1 + assert result["b"] is f2 + assert result["c"] is original["c"] + + def test_extract_files_does_not_mutate_original_top_level(self) -> None: + file_bytes = b"contents" + original = {"file": file_bytes, "other": "value"} + + copied = deepcopy_with_paths(original, [["file"]]) + extracted = extract_files(copied, paths=[["file"]]) + + assert extracted == [("file", file_bytes)] + assert original == {"file": file_bytes, "other": "value"} + assert copied == {"other": "value"} + + def test_extract_files_does_not_mutate_original_nested_array_path(self) -> None: + file1 = b"f1" + file2 = b"f2" + original = { + "items": [ + {"file": file1, "extra": 1}, + {"file": file2, "extra": 2}, + ], + "title": "example", + } + + copied = deepcopy_with_paths(original, [["items", "", "file"]]) + extracted = extract_files(copied, paths=[["items", "", "file"]]) + + assert extracted == [("items[][file]", file1), ("items[][file]", file2)] + assert original == { + "items": [ + {"file": file1, "extra": 1}, + {"file": file2, "extra": 2}, + ], + "title": "example", + } + assert copied == { + "items": [ + {"extra": 1}, + {"extra": 2}, + ], + "title": "example", + } From e3a9f2c83a7f280f5c1af2b1e79964a52f894835 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 05:12:48 +0000 Subject: [PATCH 071/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 72689081..bfaa277b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-787866cad3a80d7f704d5b099a706bf433146952fe9ea187a165c1d8b23ee039.yml -openapi_spec_hash: 4852284fd1c2b3f953142afeeb3c97aa +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-4523e8ace99fb0cf3fb7663a3df504eac6b4dee034afd260a2b17eb44c29667d.yml +openapi_spec_hash: 3047550dd065bf08b6e4ed2106393dbf config_hash: 9fa10baf03f994be027bf73b29ac8572 From 808ab7734b1690182be6e6fa636689e7d34b6b56 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 00:12:41 +0000 Subject: [PATCH 072/103] feat(api): api update --- .stats.yml | 4 ++-- src/reducto/types/shared/experimental_processing_options.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index bfaa277b..ffb5dd1a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-4523e8ace99fb0cf3fb7663a3df504eac6b4dee034afd260a2b17eb44c29667d.yml -openapi_spec_hash: 3047550dd065bf08b6e4ed2106393dbf +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-10e369182c416df8a9e82db083a02c64adf5017aa5efe78625d338034a033d1c.yml +openapi_spec_hash: 08b4777c472cf32d686e44648ad444a1 config_hash: 9fa10baf03f994be027bf73b29ac8572 diff --git a/src/reducto/types/shared/experimental_processing_options.py b/src/reducto/types/shared/experimental_processing_options.py index 90c9a136..6533dd4f 100644 --- a/src/reducto/types/shared/experimental_processing_options.py +++ b/src/reducto/types/shared/experimental_processing_options.py @@ -83,6 +83,7 @@ class ExperimentalProcessingOptions(BaseModel): "rfdetr0303", "rfdetrbase0218", "rfdetr0304", + "rfdetr0306", "qwen35_27b_0317", ] ] = None From d413d50ae1a168ac2fa06c89fc73293eb5cd60f3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 00:12:42 +0000 Subject: [PATCH 073/103] feat(api): api update --- .stats.yml | 4 ++-- src/reducto/types/shared/advanced_processing_options.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index ffb5dd1a..9736aa26 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-10e369182c416df8a9e82db083a02c64adf5017aa5efe78625d338034a033d1c.yml -openapi_spec_hash: 08b4777c472cf32d686e44648ad444a1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-d562f8146638d91d6e6515ed836ce3464863d4833657b004c2da2f46beee581a.yml +openapi_spec_hash: 70d1778962ebacfcbce7dabb4b2bc058 config_hash: 9fa10baf03f994be027bf73b29ac8572 diff --git a/src/reducto/types/shared/advanced_processing_options.py b/src/reducto/types/shared/advanced_processing_options.py index 9b55e5bb..8fb4c1fe 100644 --- a/src/reducto/types/shared/advanced_processing_options.py +++ b/src/reducto/types/shared/advanced_processing_options.py @@ -90,7 +90,9 @@ class AdvancedProcessingOptions(BaseModel): be merged across breaks and spaces. """ - ocr_system: Optional[Literal["highres", "multilingual", "combined", "reducto", "legacy", "reducto-v2"]] = None + ocr_system: Optional[ + Literal["highres", "multilingual", "combined", "reducto", "legacy", "reducto-v2", "reducto-v3"] + ] = None """The OCR system to use. Highres is recommended for documents with English characters. Legacy uses an From c04addfd8a04fd824e32ca6ba8ff0b7b25e78cc2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 04:12:42 +0000 Subject: [PATCH 074/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9736aa26..16d8c67c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-d562f8146638d91d6e6515ed836ce3464863d4833657b004c2da2f46beee581a.yml -openapi_spec_hash: 70d1778962ebacfcbce7dabb4b2bc058 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-fe2a4a7b11a7b969bf7fdd333f473bd8a6a071928af685954909796433a72cee.yml +openapi_spec_hash: 6f2a47ef326f3f33e0f153430cfa5f54 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 8ca0b14ea8f82814cb302dcbffe96e3c64b27e50 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 21:12:48 +0000 Subject: [PATCH 075/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 16d8c67c..8444c58d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-fe2a4a7b11a7b969bf7fdd333f473bd8a6a071928af685954909796433a72cee.yml -openapi_spec_hash: 6f2a47ef326f3f33e0f153430cfa5f54 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-64b36779c305f1acbdce5ac61579e29d6be5ebfeb997e402f62ef049d9fa3fda.yml +openapi_spec_hash: 0e6016512d5bed90ff1ba9fa7a718e15 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 05564fef1b0d9abef2762d8d54a870ee6863567b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 02:12:40 +0000 Subject: [PATCH 076/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8444c58d..bab3e21d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-64b36779c305f1acbdce5ac61579e29d6be5ebfeb997e402f62ef049d9fa3fda.yml -openapi_spec_hash: 0e6016512d5bed90ff1ba9fa7a718e15 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-8a900f24897b15af3363b28fc2ad792f120f17e1929123de62940ff8456e5563.yml +openapi_spec_hash: 1b14545ee6985aa316b7f6bc29330101 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 08256d31bca5a799c71caa7ac6405a5020df71d6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 22:13:01 +0000 Subject: [PATCH 077/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index bab3e21d..a32d08ec 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-8a900f24897b15af3363b28fc2ad792f120f17e1929123de62940ff8456e5563.yml -openapi_spec_hash: 1b14545ee6985aa316b7f6bc29330101 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-bbeb92ab31eed64cacf907613a1c51cea96ef5f24fe821731b472ec8c1a4c703.yml +openapi_spec_hash: 641e931b6746f47336426e3e6c9752df config_hash: 9fa10baf03f994be027bf73b29ac8572 From 1dc51f9c2cd6ddcfceec0d1ce04bea7897d98e3f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 23:12:45 +0000 Subject: [PATCH 078/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index a32d08ec..e5afa816 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-bbeb92ab31eed64cacf907613a1c51cea96ef5f24fe821731b472ec8c1a4c703.yml -openapi_spec_hash: 641e931b6746f47336426e3e6c9752df +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-af220ae9f0ded9509478b62f50e3b9f5345b90071c66974c9d24f49748e662b9.yml +openapi_spec_hash: f9a09a91f267528794561dd038d234c3 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 197c37118331c2b09e73bb7e600e283bd4713cd4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 02:06:08 +0000 Subject: [PATCH 079/103] chore(internal): more robust bootstrap script --- scripts/bootstrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/bootstrap b/scripts/bootstrap index b430fee3..fe8451e4 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,7 +4,7 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { echo -n "==> Install Homebrew dependencies? (y/N): " read -r response From a53946bea3c27c36a3e66352697413e0fd864829 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 03:12:28 +0000 Subject: [PATCH 080/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e5afa816..88a7ae80 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-af220ae9f0ded9509478b62f50e3b9f5345b90071c66974c9d24f49748e662b9.yml -openapi_spec_hash: f9a09a91f267528794561dd038d234c3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-9b1104efaba2d34f2d690e00025461ab02d345ac0fbc29ca58c9eec3519bcc60.yml +openapi_spec_hash: 832c07ac993af2dc98319010daab7ca1 config_hash: 9fa10baf03f994be027bf73b29ac8572 From f9e5f7445118cb233e58d9f9c2fa5cbc03224a55 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:12:34 +0000 Subject: [PATCH 081/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 88a7ae80..b1e1bfeb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-9b1104efaba2d34f2d690e00025461ab02d345ac0fbc29ca58c9eec3519bcc60.yml -openapi_spec_hash: 832c07ac993af2dc98319010daab7ca1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-c44446880673bec616aa963931fca97533b77951417446d5b7e7c77a12634725.yml +openapi_spec_hash: 07b02928e037afb8500345e85f91c1b3 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 9b03729c1828412d2abd1b81eacee1a3ffa02ea9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 02:12:32 +0000 Subject: [PATCH 082/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index b1e1bfeb..dc0c7a1e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-c44446880673bec616aa963931fca97533b77951417446d5b7e7c77a12634725.yml -openapi_spec_hash: 07b02928e037afb8500345e85f91c1b3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-384de110cc6135bb14c494c6ab9971d216ff0b70849f66152770167996d4a6fe.yml +openapi_spec_hash: 8de0a58197a2859019c48a3577a6f4b8 config_hash: 9fa10baf03f994be027bf73b29ac8572 From cc929a5debc823e7e84fe1ee8b3e1d1b191a2295 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 19:12:38 +0000 Subject: [PATCH 083/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index dc0c7a1e..c8f7f250 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-384de110cc6135bb14c494c6ab9971d216ff0b70849f66152770167996d4a6fe.yml -openapi_spec_hash: 8de0a58197a2859019c48a3577a6f4b8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-844854f668daedf94e2578f955ea9a06040dccd2f3ad0abe6718277bd775ba15.yml +openapi_spec_hash: 66dc5992e8d1d7c38df8c6176f7493a8 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 74b1661476f8c2bc2fc451ca7e624ac15e636fec Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 25 Apr 2026 01:12:36 +0000 Subject: [PATCH 084/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c8f7f250..14fdf3d3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-844854f668daedf94e2578f955ea9a06040dccd2f3ad0abe6718277bd775ba15.yml -openapi_spec_hash: 66dc5992e8d1d7c38df8c6176f7493a8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-3fd1114402fa3ea05e605729bcae2d40df0a2b3e2b81e8050e0ee14585110e07.yml +openapi_spec_hash: 3a61747234cc2cd5a6771ce34b9d94b4 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 696f0cfd1af343b6a113929b88f7cde6fbba5b79 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 25 Apr 2026 19:12:32 +0000 Subject: [PATCH 085/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 14fdf3d3..f2b8c0fc 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-3fd1114402fa3ea05e605729bcae2d40df0a2b3e2b81e8050e0ee14585110e07.yml -openapi_spec_hash: 3a61747234cc2cd5a6771ce34b9d94b4 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ad33dc55b36be5b7efa2653f52cea2f0a1078be309977ac065854d2462869738.yml +openapi_spec_hash: 836cdf17550f7c857bcfac7db04c9b1b config_hash: 9fa10baf03f994be027bf73b29ac8572 From 656612781aee5fd3b85c43cdc2ea2b32b7a4dfc1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 26 Apr 2026 04:12:32 +0000 Subject: [PATCH 086/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f2b8c0fc..0d29b8c9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ad33dc55b36be5b7efa2653f52cea2f0a1078be309977ac065854d2462869738.yml -openapi_spec_hash: 836cdf17550f7c857bcfac7db04c9b1b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-2f50309294626ee7c427ccd84a3749cf138b41ded635d70097e2be2a54d3c0be.yml +openapi_spec_hash: b6134b9e1388b6cf719c39865401d82a config_hash: 9fa10baf03f994be027bf73b29ac8572 From 74a20608032bbd3b8c14be4e79ce66daa5755d6d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 21:12:41 +0000 Subject: [PATCH 087/103] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 0d29b8c9..21fa6a0e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-2f50309294626ee7c427ccd84a3749cf138b41ded635d70097e2be2a54d3c0be.yml -openapi_spec_hash: b6134b9e1388b6cf719c39865401d82a +openapi_spec_hash: 4da30ee28a326eb915b4019b9a23e96c config_hash: 9fa10baf03f994be027bf73b29ac8572 From 00f933debb5a49d3ee915f70283a1e85f61fa611 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 02:02:03 +0000 Subject: [PATCH 088/103] fix: use correct field name format for multipart file arrays --- src/reducto/_qs.py | 8 ++----- src/reducto/_types.py | 3 +++ src/reducto/_utils/_utils.py | 42 +++++++++++++++++++++++++++++------- tests/test_extract_files.py | 28 +++++++++++++++++++----- tests/test_files.py | 2 +- 5 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/reducto/_qs.py b/src/reducto/_qs.py index de8c99bc..4127c19c 100644 --- a/src/reducto/_qs.py +++ b/src/reducto/_qs.py @@ -2,17 +2,13 @@ from typing import Any, List, Tuple, Union, Mapping, TypeVar from urllib.parse import parse_qs, urlencode -from typing_extensions import Literal, get_args +from typing_extensions import get_args -from ._types import NotGiven, not_given +from ._types import NotGiven, ArrayFormat, NestedFormat, not_given from ._utils import flatten _T = TypeVar("_T") - -ArrayFormat = Literal["comma", "repeat", "indices", "brackets"] -NestedFormat = Literal["dots", "brackets"] - PrimitiveData = Union[str, int, float, bool, None] # this should be Data = Union[PrimitiveData, "List[Data]", "Tuple[Data]", "Mapping[str, Data]"] # https://github.com/microsoft/pyright/issues/3555 diff --git a/src/reducto/_types.py b/src/reducto/_types.py index 6c70e52c..1cd25278 100644 --- a/src/reducto/_types.py +++ b/src/reducto/_types.py @@ -47,6 +47,9 @@ ModelT = TypeVar("ModelT", bound=pydantic.BaseModel) _T = TypeVar("_T") +ArrayFormat = Literal["comma", "repeat", "indices", "brackets"] +NestedFormat = Literal["dots", "brackets"] + # Approximates httpx internal ProxiesTypes and RequestFiles types # while adding support for `PathLike` instances diff --git a/src/reducto/_utils/_utils.py b/src/reducto/_utils/_utils.py index 771859f5..199cd231 100644 --- a/src/reducto/_utils/_utils.py +++ b/src/reducto/_utils/_utils.py @@ -17,11 +17,11 @@ ) from pathlib import Path from datetime import date, datetime -from typing_extensions import TypeGuard +from typing_extensions import TypeGuard, get_args import sniffio -from .._types import Omit, NotGiven, FileTypes, HeadersLike +from .._types import Omit, NotGiven, FileTypes, ArrayFormat, HeadersLike _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) @@ -40,25 +40,45 @@ def extract_files( query: Mapping[str, object], *, paths: Sequence[Sequence[str]], + array_format: ArrayFormat = "brackets", ) -> list[tuple[str, FileTypes]]: """Recursively extract files from the given dictionary based on specified paths. A path may look like this ['foo', 'files', '', 'data']. + ``array_format`` controls how ```` segments contribute to the emitted + field name. Supported values: ``"brackets"`` (``foo[]``), ``"repeat"`` and + ``"comma"`` (``foo``), ``"indices"`` (``foo[0]``, ``foo[1]``). + Note: this mutates the given dictionary. """ files: list[tuple[str, FileTypes]] = [] for path in paths: - files.extend(_extract_items(query, path, index=0, flattened_key=None)) + files.extend(_extract_items(query, path, index=0, flattened_key=None, array_format=array_format)) return files +def _array_suffix(array_format: ArrayFormat, array_index: int) -> str: + if array_format == "brackets": + return "[]" + if array_format == "indices": + return f"[{array_index}]" + if array_format == "repeat" or array_format == "comma": + # Both repeat the bare field name for each file part; there is no + # meaningful way to comma-join binary parts. + return "" + raise NotImplementedError( + f"Unknown array_format value: {array_format}, choose from {', '.join(get_args(ArrayFormat))}" + ) + + def _extract_items( obj: object, path: Sequence[str], *, index: int, flattened_key: str | None, + array_format: ArrayFormat, ) -> list[tuple[str, FileTypes]]: try: key = path[index] @@ -75,9 +95,11 @@ def _extract_items( if is_list(obj): files: list[tuple[str, FileTypes]] = [] - for entry in obj: - assert_is_file_content(entry, key=flattened_key + "[]" if flattened_key else "") - files.append((flattened_key + "[]", cast(FileTypes, entry))) + for array_index, entry in enumerate(obj): + suffix = _array_suffix(array_format, array_index) + emitted_key = (flattened_key + suffix) if flattened_key else suffix + assert_is_file_content(entry, key=emitted_key) + files.append((emitted_key, cast(FileTypes, entry))) return files assert_is_file_content(obj, key=flattened_key) @@ -106,6 +128,7 @@ def _extract_items( path, index=index, flattened_key=flattened_key, + array_format=array_format, ) elif is_list(obj): if key != "": @@ -117,9 +140,12 @@ def _extract_items( item, path, index=index, - flattened_key=flattened_key + "[]" if flattened_key is not None else "[]", + flattened_key=( + (flattened_key if flattened_key is not None else "") + _array_suffix(array_format, array_index) + ), + array_format=array_format, ) - for item in obj + for array_index, item in enumerate(obj) ] ) diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index 9e158a96..f3cccbea 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -4,7 +4,7 @@ import pytest -from reducto._types import FileTypes +from reducto._types import FileTypes, ArrayFormat from reducto._utils import extract_files @@ -37,10 +37,7 @@ def test_multiple_files() -> None: def test_top_level_file_array() -> None: query = {"files": [b"file one", b"file two"], "title": "hello"} - assert extract_files(query, paths=[["files", ""]]) == [ - ("files[]", b"file one"), - ("files[]", b"file two"), - ] + assert extract_files(query, paths=[["files", ""]]) == [("files[]", b"file one"), ("files[]", b"file two")] assert query == {"title": "hello"} @@ -71,3 +68,24 @@ def test_ignores_incorrect_paths( expected: list[tuple[str, FileTypes]], ) -> None: assert extract_files(query, paths=paths) == expected + + +@pytest.mark.parametrize( + "array_format,expected_top_level,expected_nested", + [ + ("brackets", [("files[]", b"a"), ("files[]", b"b")], [("items[][file]", b"a"), ("items[][file]", b"b")]), + ("repeat", [("files", b"a"), ("files", b"b")], [("items[file]", b"a"), ("items[file]", b"b")]), + ("comma", [("files", b"a"), ("files", b"b")], [("items[file]", b"a"), ("items[file]", b"b")]), + ("indices", [("files[0]", b"a"), ("files[1]", b"b")], [("items[0][file]", b"a"), ("items[1][file]", b"b")]), + ], +) +def test_array_format_controls_file_field_names( + array_format: ArrayFormat, + expected_top_level: list[tuple[str, FileTypes]], + expected_nested: list[tuple[str, FileTypes]], +) -> None: + top_level = {"files": [b"a", b"b"]} + assert extract_files(top_level, paths=[["files", ""]], array_format=array_format) == expected_top_level + + nested = {"items": [{"file": b"a"}, {"file": b"b"}]} + assert extract_files(nested, paths=[["items", "", "file"]], array_format=array_format) == expected_nested diff --git a/tests/test_files.py b/tests/test_files.py index b76db4fd..23535a30 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -131,7 +131,7 @@ def test_extract_files_does_not_mutate_original_nested_array_path(self) -> None: copied = deepcopy_with_paths(original, [["items", "", "file"]]) extracted = extract_files(copied, paths=[["items", "", "file"]]) - assert extracted == [("items[][file]", file1), ("items[][file]", file2)] + assert [entry for _, entry in extracted] == [file1, file2] assert original == { "items": [ {"file": file1, "extra": 1}, From 6b6b3adb6e74e10716fdd5640b310b3d20734c56 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 02:03:10 +0000 Subject: [PATCH 089/103] feat: support setting headers via env --- src/reducto/_client.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/reducto/_client.py b/src/reducto/_client.py index 81ebe7a3..81b298b8 100644 --- a/src/reducto/_client.py +++ b/src/reducto/_client.py @@ -28,6 +28,7 @@ ) from ._utils import ( is_given, + is_mapping_t, extract_files, maybe_transform, get_async_library, @@ -150,6 +151,15 @@ def __init__( except KeyError as exc: raise ValueError(f"Unknown environment: {environment}") from exc + custom_headers_env = os.environ.get("REDUCTO_CUSTOM_HEADERS") + if custom_headers_env is not None: + parsed: dict[str, str] = {} + for line in custom_headers_env.split("\n"): + colon = line.find(":") + if colon >= 0: + parsed[line[:colon].strip()] = line[colon + 1 :].strip() + default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} + super().__init__( version=__version__, base_url=base_url, @@ -461,6 +471,15 @@ def __init__( except KeyError as exc: raise ValueError(f"Unknown environment: {environment}") from exc + custom_headers_env = os.environ.get("REDUCTO_CUSTOM_HEADERS") + if custom_headers_env is not None: + parsed: dict[str, str] = {} + for line in custom_headers_env.split("\n"): + colon = line.find(":") + if colon >= 0: + parsed[line[:colon].strip()] = line[colon + 1 :].strip() + default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} + super().__init__( version=__version__, base_url=base_url, From aca3de4fbdb5afc9cbc55b50d31f2280d5405370 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 16:12:40 +0000 Subject: [PATCH 090/103] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 21fa6a0e..6fb27bef 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-2f50309294626ee7c427ccd84a3749cf138b41ded635d70097e2be2a54d3c0be.yml -openapi_spec_hash: 4da30ee28a326eb915b4019b9a23e96c +openapi_spec_hash: dea140425522d3d264eb6b9fd5c9c03b config_hash: 9fa10baf03f994be027bf73b29ac8572 From 52e9d9375cac9027a2c13ea6a84b71b5de4d30ed Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 17:12:41 +0000 Subject: [PATCH 091/103] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 6fb27bef..d7901383 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-2f50309294626ee7c427ccd84a3749cf138b41ded635d70097e2be2a54d3c0be.yml -openapi_spec_hash: dea140425522d3d264eb6b9fd5c9c03b +openapi_spec_hash: 02e9045815c1c1ee4bc9374fab7ab55e config_hash: 9fa10baf03f994be027bf73b29ac8572 From 5f4a0ff46bdcd11d5b5057ccdbd817de956813d1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 22:12:37 +0000 Subject: [PATCH 092/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d7901383..2e369549 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-2f50309294626ee7c427ccd84a3749cf138b41ded635d70097e2be2a54d3c0be.yml -openapi_spec_hash: 02e9045815c1c1ee4bc9374fab7ab55e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-de71b9bc8500496762352188fc464d575a7d94ff41cf3baf8423e64c3a1c0aaf.yml +openapi_spec_hash: 1841b17f88715c4c91476af71f0abc90 config_hash: 9fa10baf03f994be027bf73b29ac8572 From f6a16828595a63b3f026a029b89f2eba36b8203c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 02:17:06 +0000 Subject: [PATCH 093/103] feat(api): api update --- .stats.yml | 4 ++-- src/reducto/types/shared/parse_response.py | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2e369549..dbe49ed9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-de71b9bc8500496762352188fc464d575a7d94ff41cf3baf8423e64c3a1c0aaf.yml -openapi_spec_hash: 1841b17f88715c4c91476af71f0abc90 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ac81c16ff47ec23203e959d323f6b4816087bf340dc4eb2dcabb15ed48337e84.yml +openapi_spec_hash: 7df17d6c72fc7843eab0e5fb23e8b7e3 config_hash: 9fa10baf03f994be027bf73b29ac8572 diff --git a/src/reducto/types/shared/parse_response.py b/src/reducto/types/shared/parse_response.py index 8b54180f..a12ff7dc 100644 --- a/src/reducto/types/shared/parse_response.py +++ b/src/reducto/types/shared/parse_response.py @@ -177,6 +177,15 @@ class ParseResponse(BaseModel): usage: ParseUsage + parse_mode: Optional[Literal["base", "lite"]] = None + """Which pipeline produced this response. + + `lite` means Reducto Flash Lite served the request; `base` is the standard + pipeline. Optional / nullable for forward compatibility — older API instances or + persisted responses written before this field existed will leave it `None`; + treat `None` as `base`. + """ + pdf_url: Optional[str] = None """The storage URL of the converted PDF file.""" From aba64ece4eac0406cae9f46721e2db0d9b5534f7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 21:12:34 +0000 Subject: [PATCH 094/103] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index dbe49ed9..8f406842 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ac81c16ff47ec23203e959d323f6b4816087bf340dc4eb2dcabb15ed48337e84.yml -openapi_spec_hash: 7df17d6c72fc7843eab0e5fb23e8b7e3 +openapi_spec_hash: 0d5277ada3330061c022e90145b01a59 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 8b275e71c08f1d0ddbafca3df181bc9c461d4669 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 22:12:36 +0000 Subject: [PATCH 095/103] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 8f406842..d773cf5d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ac81c16ff47ec23203e959d323f6b4816087bf340dc4eb2dcabb15ed48337e84.yml -openapi_spec_hash: 0d5277ada3330061c022e90145b01a59 +openapi_spec_hash: 5868e8c1bc6bf0d926ef4d0bb7383a7f config_hash: 9fa10baf03f994be027bf73b29ac8572 From 9d5297da182dece9f0b610fcd2ebd3e9b4fb4afa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 23:12:35 +0000 Subject: [PATCH 096/103] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index d773cf5d..2f26e8d9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ac81c16ff47ec23203e959d323f6b4816087bf340dc4eb2dcabb15ed48337e84.yml -openapi_spec_hash: 5868e8c1bc6bf0d926ef4d0bb7383a7f +openapi_spec_hash: 92205884bdd964090fb5984f86f0fde1 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 7b0ced71544f3bfbf13504c579b3158ac4f02e8f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 00:12:45 +0000 Subject: [PATCH 097/103] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 2f26e8d9..1a4e2e32 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ac81c16ff47ec23203e959d323f6b4816087bf340dc4eb2dcabb15ed48337e84.yml -openapi_spec_hash: 92205884bdd964090fb5984f86f0fde1 +openapi_spec_hash: 3d8223815107cc9681a64808f44cb6dd config_hash: 9fa10baf03f994be027bf73b29ac8572 From 339de461fdf62784272ac7ee2e28ba9c821e7473 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 02:11:03 +0000 Subject: [PATCH 098/103] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 1a4e2e32..d73e84a1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto%2Freductoai-ac81c16ff47ec23203e959d323f6b4816087bf340dc4eb2dcabb15ed48337e84.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto/reductoai-cc75e7708b252477b11026d1ecd1b346e3b922341f36fbc0615795ad7a40c455.yml openapi_spec_hash: 3d8223815107cc9681a64808f44cb6dd config_hash: 9fa10baf03f994be027bf73b29ac8572 From 5df486e5b58c5e7d2d8ccd356abf3a3db7237297 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 19:14:05 +0000 Subject: [PATCH 099/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d73e84a1..b0f26b0a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto/reductoai-cc75e7708b252477b11026d1ecd1b346e3b922341f36fbc0615795ad7a40c455.yml -openapi_spec_hash: 3d8223815107cc9681a64808f44cb6dd +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto/reductoai-24ca58230430b95c3defa4eb74d7e867ab8958a2dbb5e69ffbfac7433beeb6d0.yml +openapi_spec_hash: d991660e4d427830db01842024d6bf51 config_hash: 9fa10baf03f994be027bf73b29ac8572 From ec1c3f3ec53bde309b8ec7e4f5f94ef32df8de35 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 22:12:44 +0000 Subject: [PATCH 100/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index b0f26b0a..efadcfc2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto/reductoai-24ca58230430b95c3defa4eb74d7e867ab8958a2dbb5e69ffbfac7433beeb6d0.yml -openapi_spec_hash: d991660e4d427830db01842024d6bf51 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto/reductoai-55041772e015cc21bdc1b2984e1775c32c2b2f8b9c5aae461819cebd99a6b1c6.yml +openapi_spec_hash: d26f16d90d429371d7e86266bf475584 config_hash: 9fa10baf03f994be027bf73b29ac8572 From 3c53207b214a712c0c27b1d826e2bf21baff181d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 01:12:45 +0000 Subject: [PATCH 101/103] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index efadcfc2..296b0f7f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto/reductoai-55041772e015cc21bdc1b2984e1775c32c2b2f8b9c5aae461819cebd99a6b1c6.yml -openapi_spec_hash: d26f16d90d429371d7e86266bf475584 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto/reductoai-e7db3577af4195155f5f382652d5bb5589b150d0f6e51be3a17394f684bdf217.yml +openapi_spec_hash: 06f95c19ecff0d30451aa1dbe6fb7c6e config_hash: 9fa10baf03f994be027bf73b29ac8572 From 95c19a30e0fc195f601107a1ae7dd3f151ff49d5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 02:04:55 +0000 Subject: [PATCH 102/103] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 296b0f7f..a6410018 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto/reductoai-e7db3577af4195155f5f382652d5bb5589b150d0f6e51be3a17394f684bdf217.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/reducto/reductoai-d32017996d4322082da97c33ea8a288f509d91a032960f3e00026c2c3688c188.yml openapi_spec_hash: 06f95c19ecff0d30451aa1dbe6fb7c6e config_hash: 9fa10baf03f994be027bf73b29ac8572 From 26c7fd42bfc8bb38fa1aff7e557a6a6d57e14668 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 02:11:45 +0000 Subject: [PATCH 103/103] release: 0.23.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 42 +++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- src/reducto/_version.py | 2 +- 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index cb9d2541..7f3f5c84 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.22.0" + ".": "0.23.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 14e73b73..038b4a09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,47 @@ # Changelog +## 0.23.0 (2026-05-01) + +Full Changelog: [v0.22.0...v0.23.0](https://github.com/reductoai/reducto-python-sdk/compare/v0.22.0...v0.23.0) + +### Features + +* **api:** api update ([f6a1682](https://github.com/reductoai/reducto-python-sdk/commit/f6a16828595a63b3f026a029b89f2eba36b8203c)) +* **api:** api update ([d413d50](https://github.com/reductoai/reducto-python-sdk/commit/d413d50ae1a168ac2fa06c89fc73293eb5cd60f3)) +* **api:** api update ([808ab77](https://github.com/reductoai/reducto-python-sdk/commit/808ab7734b1690182be6e6fa636689e7d34b6b56)) +* **api:** api update ([c47f11a](https://github.com/reductoai/reducto-python-sdk/commit/c47f11afcacac318209e04b49dc3ba3a4fa549b6)) +* **api:** api update ([f7b90fa](https://github.com/reductoai/reducto-python-sdk/commit/f7b90fa8da10e32ec26f71313bd8eef7aac4bf83)) +* **api:** api update ([604578f](https://github.com/reductoai/reducto-python-sdk/commit/604578fc82a9e0e9cd1c96140b288d5f7e9cfc96)) +* **api:** api update ([117ec65](https://github.com/reductoai/reducto-python-sdk/commit/117ec654884ac13bdbd9e86e40441d7a5169aeda)) +* **api:** api update ([68580e6](https://github.com/reductoai/reducto-python-sdk/commit/68580e616d0743c04631a6a03f8f0c230dae9393)) +* **pypi:** reducto package aliasing ([c19a947](https://github.com/reductoai/reducto-python-sdk/commit/c19a94757e2d42ac015e8aaae4647f1bba2c5ade)) +* support setting headers via env ([6b6b3ad](https://github.com/reductoai/reducto-python-sdk/commit/6b6b3adb6e74e10716fdd5640b310b3d20734c56)) + + +### Bug Fixes + +* **ci:** `reducto` shim publishing ([48a5558](https://github.com/reductoai/reducto-python-sdk/commit/48a5558ed79ef8c8796890b486eb5bae92cbc21f)) +* **client:** preserve hardcoded query params when merging with user params ([72d4eac](https://github.com/reductoai/reducto-python-sdk/commit/72d4eac3b2514c35b26fdafeecb1e64cc067ea80)) +* ensure file data are only sent as 1 parameter ([5a5d5ee](https://github.com/reductoai/reducto-python-sdk/commit/5a5d5eed5f5bf34df796e73355824dafc30c492b)) +* use correct field name format for multipart file arrays ([00f933d](https://github.com/reductoai/reducto-python-sdk/commit/00f933debb5a49d3ee915f70283a1e85f61fa611)) + + +### Performance Improvements + +* **client:** optimize file structure copying in multipart requests ([fae7194](https://github.com/reductoai/reducto-python-sdk/commit/fae719428bbc73108ed0e3e569c5c65af3cea90a)) + + +### Chores + +* add Renovate config and SHA-pin GitHub Actions ([5bbef22](https://github.com/reductoai/reducto-python-sdk/commit/5bbef22b185f99a82a48d4dfe578b86b7931bef6)) +* configure new SDK language ([a54762b](https://github.com/reductoai/reducto-python-sdk/commit/a54762b2a40c2da5e5b7e8dee56717bde8c94e61)) +* **internal:** more robust bootstrap script ([197c371](https://github.com/reductoai/reducto-python-sdk/commit/197c37118331c2b09e73bb7e600e283bd4713cd4)) + + +### Styles + +* format renovate.json with Prettier ([668ab0e](https://github.com/reductoai/reducto-python-sdk/commit/668ab0ecd82574651f35f1c0b3910e1e845cedd4)) + ## 0.21.0 (2026-03-29) Full Changelog: [v0.20.0...v0.21.0](https://github.com/reductoai/reducto-python-sdk/compare/v0.20.0...v0.21.0) diff --git a/pyproject.toml b/pyproject.toml index e50cc10c..2245acf5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "reductoai" -version = "0.22.0" +version = "0.23.0" description = "The official Python library for the reducto API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/reducto/_version.py b/src/reducto/_version.py index 956dea69..7f4900a2 100644 --- a/src/reducto/_version.py +++ b/src/reducto/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "reducto" -__version__ = "0.22.0" # x-release-please-version +__version__ = "0.23.0" # x-release-please-version