From 88f2d0ff89d2537b812c52e15b95977634b92d6b Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Thu, 4 Jun 2026 14:52:46 +0100 Subject: [PATCH 01/14] Add Oz SDK promotion workflow (#3) * Add promote_oz_sdk workflow Manual workflow_dispatch workflow that promotes SDK updates from this staging repository to warpdotdev/oz-sdk-python by calling the shared warpdotdev/warp-github-actions/.github/actions/promote_oz_sdk action. Only the OZ_SDK_PRODUCTION_REPO_TOKEN secret is required. The production repo name, release branch (stainless/release), and PR title ('Release SDK updates') are all managed by the shared action. Co-Authored-By: Oz * Add Oz SDK promotion workflow Co-Authored-By: Oz * Checkout full history for SDK promotion Co-Authored-By: Oz * Update action name --------- Co-authored-by: Oz --- .github/workflows/promote_sdk.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/promote_sdk.yml diff --git a/.github/workflows/promote_sdk.yml b/.github/workflows/promote_sdk.yml new file mode 100644 index 0000000..d007379 --- /dev/null +++ b/.github/workflows/promote_sdk.yml @@ -0,0 +1,26 @@ +# Promote SDK updates from this staging repository to the corresponding +# production repository. + +name: Promote SDK + +on: + workflow_dispatch: + +jobs: + promote: + name: promote + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.event.repository.default_branch }} + fetch-depth: 0 + persist-credentials: false + + - name: Promote SDK to production + uses: warpdotdev/warp-github-actions/.github/actions/promote_sdk@main + with: + production_repo_token: ${{ secrets.STAINLESS_SDK_PROD_WRITE_TOKEN }} From 5ca59d8b7e54765a1bb5b0e4468d7fd01d17f987 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2026 13:10:33 -0400 Subject: [PATCH 02/14] Bump the uv group across 1 directory with 2 updates (#4) --- updated-dependencies: - dependency-name: aiohttp dependency-version: 3.13.5 dependency-type: direct:production dependency-group: uv - dependency-name: idna dependency-version: '3.15' dependency-type: indirect dependency-group: uv ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 250 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 125 insertions(+), 125 deletions(-) diff --git a/uv.lock b/uv.lock index 816e22a..0c65e6f 100644 --- a/uv.lock +++ b/uv.lock @@ -26,7 +26,7 @@ wheels = [ [[package]] name = "aiohttp" -version = "3.13.3" +version = "3.13.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohappyeyeballs" }, @@ -38,127 +38,127 @@ dependencies = [ { name = "propcache" }, { name = "yarl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/50/42/32cf8e7704ceb4481406eb87161349abb46a57fee3f008ba9cb610968646/aiohttp-3.13.3.tar.gz", hash = "sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88", size = 7844556, upload-time = "2026-01-03T17:33:05.204Z" } +sdist = { url = "https://files.pythonhosted.org/packages/77/9a/152096d4808df8e4268befa55fba462f440f14beab85e8ad9bf990516918/aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1", size = 7858271, upload-time = "2026-03-31T22:01:03.343Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/d6/5aec9313ee6ea9c7cde8b891b69f4ff4001416867104580670a31daeba5b/aiohttp-3.13.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7", size = 738950, upload-time = "2026-01-03T17:29:13.002Z" }, - { url = "https://files.pythonhosted.org/packages/68/03/8fa90a7e6d11ff20a18837a8e2b5dd23db01aabc475aa9271c8ad33299f5/aiohttp-3.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821", size = 496099, upload-time = "2026-01-03T17:29:15.268Z" }, - { url = "https://files.pythonhosted.org/packages/d2/23/b81f744d402510a8366b74eb420fc0cc1170d0c43daca12d10814df85f10/aiohttp-3.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845", size = 491072, upload-time = "2026-01-03T17:29:16.922Z" }, - { url = "https://files.pythonhosted.org/packages/d5/e1/56d1d1c0dd334cd203dd97706ce004c1aa24b34a813b0b8daf3383039706/aiohttp-3.13.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af", size = 1671588, upload-time = "2026-01-03T17:29:18.539Z" }, - { url = "https://files.pythonhosted.org/packages/5f/34/8d7f962604f4bc2b4e39eb1220dac7d4e4cba91fb9ba0474b4ecd67db165/aiohttp-3.13.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940", size = 1640334, upload-time = "2026-01-03T17:29:21.028Z" }, - { url = "https://files.pythonhosted.org/packages/94/1d/fcccf2c668d87337ddeef9881537baee13c58d8f01f12ba8a24215f2b804/aiohttp-3.13.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160", size = 1722656, upload-time = "2026-01-03T17:29:22.531Z" }, - { url = "https://files.pythonhosted.org/packages/aa/98/c6f3b081c4c606bc1e5f2ec102e87d6411c73a9ef3616fea6f2d5c98c062/aiohttp-3.13.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7", size = 1817625, upload-time = "2026-01-03T17:29:24.276Z" }, - { url = "https://files.pythonhosted.org/packages/2c/c0/cfcc3d2e11b477f86e1af2863f3858c8850d751ce8dc39c4058a072c9e54/aiohttp-3.13.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455", size = 1672604, upload-time = "2026-01-03T17:29:26.099Z" }, - { url = "https://files.pythonhosted.org/packages/1e/77/6b4ffcbcac4c6a5d041343a756f34a6dd26174ae07f977a64fe028dda5b0/aiohttp-3.13.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279", size = 1554370, upload-time = "2026-01-03T17:29:28.121Z" }, - { url = "https://files.pythonhosted.org/packages/f2/f0/e3ddfa93f17d689dbe014ba048f18e0c9f9b456033b70e94349a2e9048be/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e", size = 1642023, upload-time = "2026-01-03T17:29:30.002Z" }, - { url = "https://files.pythonhosted.org/packages/eb/45/c14019c9ec60a8e243d06d601b33dcc4fd92379424bde3021725859d7f99/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d", size = 1649680, upload-time = "2026-01-03T17:29:31.782Z" }, - { url = "https://files.pythonhosted.org/packages/9c/fd/09c9451dae5aa5c5ed756df95ff9ef549d45d4be663bafd1e4954fd836f0/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808", size = 1692407, upload-time = "2026-01-03T17:29:33.392Z" }, - { url = "https://files.pythonhosted.org/packages/a6/81/938bc2ec33c10efd6637ccb3d22f9f3160d08e8f3aa2587a2c2d5ab578eb/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40", size = 1543047, upload-time = "2026-01-03T17:29:34.855Z" }, - { url = "https://files.pythonhosted.org/packages/f7/23/80488ee21c8d567c83045e412e1d9b7077d27171591a4eb7822586e8c06a/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29", size = 1715264, upload-time = "2026-01-03T17:29:36.389Z" }, - { url = "https://files.pythonhosted.org/packages/e2/83/259a8da6683182768200b368120ab3deff5370bed93880fb9a3a86299f34/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11", size = 1657275, upload-time = "2026-01-03T17:29:38.162Z" }, - { url = "https://files.pythonhosted.org/packages/3f/4f/2c41f800a0b560785c10fb316216ac058c105f9be50bdc6a285de88db625/aiohttp-3.13.3-cp310-cp310-win32.whl", hash = "sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd", size = 434053, upload-time = "2026-01-03T17:29:40.074Z" }, - { url = "https://files.pythonhosted.org/packages/80/df/29cd63c7ecfdb65ccc12f7d808cac4fa2a19544660c06c61a4a48462de0c/aiohttp-3.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c", size = 456687, upload-time = "2026-01-03T17:29:41.819Z" }, - { url = "https://files.pythonhosted.org/packages/f1/4c/a164164834f03924d9a29dc3acd9e7ee58f95857e0b467f6d04298594ebb/aiohttp-3.13.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b", size = 746051, upload-time = "2026-01-03T17:29:43.287Z" }, - { url = "https://files.pythonhosted.org/packages/82/71/d5c31390d18d4f58115037c432b7e0348c60f6f53b727cad33172144a112/aiohttp-3.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64", size = 499234, upload-time = "2026-01-03T17:29:44.822Z" }, - { url = "https://files.pythonhosted.org/packages/0e/c9/741f8ac91e14b1d2e7100690425a5b2b919a87a5075406582991fb7de920/aiohttp-3.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea", size = 494979, upload-time = "2026-01-03T17:29:46.405Z" }, - { url = "https://files.pythonhosted.org/packages/75/b5/31d4d2e802dfd59f74ed47eba48869c1c21552c586d5e81a9d0d5c2ad640/aiohttp-3.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a", size = 1748297, upload-time = "2026-01-03T17:29:48.083Z" }, - { url = "https://files.pythonhosted.org/packages/1a/3e/eefad0ad42959f226bb79664826883f2687d602a9ae2941a18e0484a74d3/aiohttp-3.13.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540", size = 1707172, upload-time = "2026-01-03T17:29:49.648Z" }, - { url = "https://files.pythonhosted.org/packages/c5/3a/54a64299fac2891c346cdcf2aa6803f994a2e4beeaf2e5a09dcc54acc842/aiohttp-3.13.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b", size = 1805405, upload-time = "2026-01-03T17:29:51.244Z" }, - { url = "https://files.pythonhosted.org/packages/6c/70/ddc1b7169cf64075e864f64595a14b147a895a868394a48f6a8031979038/aiohttp-3.13.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3", size = 1899449, upload-time = "2026-01-03T17:29:53.938Z" }, - { url = "https://files.pythonhosted.org/packages/a1/7e/6815aab7d3a56610891c76ef79095677b8b5be6646aaf00f69b221765021/aiohttp-3.13.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1", size = 1748444, upload-time = "2026-01-03T17:29:55.484Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f2/073b145c4100da5511f457dc0f7558e99b2987cf72600d42b559db856fbc/aiohttp-3.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3", size = 1606038, upload-time = "2026-01-03T17:29:57.179Z" }, - { url = "https://files.pythonhosted.org/packages/0a/c1/778d011920cae03ae01424ec202c513dc69243cf2db303965615b81deeea/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440", size = 1724156, upload-time = "2026-01-03T17:29:58.914Z" }, - { url = "https://files.pythonhosted.org/packages/0e/cb/3419eabf4ec1e9ec6f242c32b689248365a1cf621891f6f0386632525494/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7", size = 1722340, upload-time = "2026-01-03T17:30:01.962Z" }, - { url = "https://files.pythonhosted.org/packages/7a/e5/76cf77bdbc435bf233c1f114edad39ed4177ccbfab7c329482b179cff4f4/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c", size = 1783041, upload-time = "2026-01-03T17:30:03.609Z" }, - { url = "https://files.pythonhosted.org/packages/9d/d4/dd1ca234c794fd29c057ce8c0566b8ef7fd6a51069de5f06fa84b9a1971c/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51", size = 1596024, upload-time = "2026-01-03T17:30:05.132Z" }, - { url = "https://files.pythonhosted.org/packages/55/58/4345b5f26661a6180afa686c473620c30a66afdf120ed3dd545bbc809e85/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4", size = 1804590, upload-time = "2026-01-03T17:30:07.135Z" }, - { url = "https://files.pythonhosted.org/packages/7b/06/05950619af6c2df7e0a431d889ba2813c9f0129cec76f663e547a5ad56f2/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29", size = 1740355, upload-time = "2026-01-03T17:30:09.083Z" }, - { url = "https://files.pythonhosted.org/packages/3e/80/958f16de79ba0422d7c1e284b2abd0c84bc03394fbe631d0a39ffa10e1eb/aiohttp-3.13.3-cp311-cp311-win32.whl", hash = "sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239", size = 433701, upload-time = "2026-01-03T17:30:10.869Z" }, - { url = "https://files.pythonhosted.org/packages/dc/f2/27cdf04c9851712d6c1b99df6821a6623c3c9e55956d4b1e318c337b5a48/aiohttp-3.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f", size = 457678, upload-time = "2026-01-03T17:30:12.719Z" }, - { url = "https://files.pythonhosted.org/packages/a0/be/4fc11f202955a69e0db803a12a062b8379c970c7c84f4882b6da17337cc1/aiohttp-3.13.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c", size = 739732, upload-time = "2026-01-03T17:30:14.23Z" }, - { url = "https://files.pythonhosted.org/packages/97/2c/621d5b851f94fa0bb7430d6089b3aa970a9d9b75196bc93bb624b0db237a/aiohttp-3.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168", size = 494293, upload-time = "2026-01-03T17:30:15.96Z" }, - { url = "https://files.pythonhosted.org/packages/5d/43/4be01406b78e1be8320bb8316dc9c42dbab553d281c40364e0f862d5661c/aiohttp-3.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d", size = 493533, upload-time = "2026-01-03T17:30:17.431Z" }, - { url = "https://files.pythonhosted.org/packages/8d/a8/5a35dc56a06a2c90d4742cbf35294396907027f80eea696637945a106f25/aiohttp-3.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29", size = 1737839, upload-time = "2026-01-03T17:30:19.422Z" }, - { url = "https://files.pythonhosted.org/packages/bf/62/4b9eeb331da56530bf2e198a297e5303e1c1ebdceeb00fe9b568a65c5a0c/aiohttp-3.13.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3", size = 1703932, upload-time = "2026-01-03T17:30:21.756Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f6/af16887b5d419e6a367095994c0b1332d154f647e7dc2bd50e61876e8e3d/aiohttp-3.13.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d", size = 1771906, upload-time = "2026-01-03T17:30:23.932Z" }, - { url = "https://files.pythonhosted.org/packages/ce/83/397c634b1bcc24292fa1e0c7822800f9f6569e32934bdeef09dae7992dfb/aiohttp-3.13.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463", size = 1871020, upload-time = "2026-01-03T17:30:26Z" }, - { url = "https://files.pythonhosted.org/packages/86/f6/a62cbbf13f0ac80a70f71b1672feba90fdb21fd7abd8dbf25c0105fb6fa3/aiohttp-3.13.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc", size = 1755181, upload-time = "2026-01-03T17:30:27.554Z" }, - { url = "https://files.pythonhosted.org/packages/0a/87/20a35ad487efdd3fba93d5843efdfaa62d2f1479eaafa7453398a44faf13/aiohttp-3.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf", size = 1561794, upload-time = "2026-01-03T17:30:29.254Z" }, - { url = "https://files.pythonhosted.org/packages/de/95/8fd69a66682012f6716e1bc09ef8a1a2a91922c5725cb904689f112309c4/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033", size = 1697900, upload-time = "2026-01-03T17:30:31.033Z" }, - { url = "https://files.pythonhosted.org/packages/e5/66/7b94b3b5ba70e955ff597672dad1691333080e37f50280178967aff68657/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f", size = 1728239, upload-time = "2026-01-03T17:30:32.703Z" }, - { url = "https://files.pythonhosted.org/packages/47/71/6f72f77f9f7d74719692ab65a2a0252584bf8d5f301e2ecb4c0da734530a/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679", size = 1740527, upload-time = "2026-01-03T17:30:34.695Z" }, - { url = "https://files.pythonhosted.org/packages/fa/b4/75ec16cbbd5c01bdaf4a05b19e103e78d7ce1ef7c80867eb0ace42ff4488/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423", size = 1554489, upload-time = "2026-01-03T17:30:36.864Z" }, - { url = "https://files.pythonhosted.org/packages/52/8f/bc518c0eea29f8406dcf7ed1f96c9b48e3bc3995a96159b3fc11f9e08321/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce", size = 1767852, upload-time = "2026-01-03T17:30:39.433Z" }, - { url = "https://files.pythonhosted.org/packages/9d/f2/a07a75173124f31f11ea6f863dc44e6f09afe2bca45dd4e64979490deab1/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a", size = 1722379, upload-time = "2026-01-03T17:30:41.081Z" }, - { url = "https://files.pythonhosted.org/packages/3c/4a/1a3fee7c21350cac78e5c5cef711bac1b94feca07399f3d406972e2d8fcd/aiohttp-3.13.3-cp312-cp312-win32.whl", hash = "sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046", size = 428253, upload-time = "2026-01-03T17:30:42.644Z" }, - { url = "https://files.pythonhosted.org/packages/d9/b7/76175c7cb4eb73d91ad63c34e29fc4f77c9386bba4a65b53ba8e05ee3c39/aiohttp-3.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57", size = 455407, upload-time = "2026-01-03T17:30:44.195Z" }, - { url = "https://files.pythonhosted.org/packages/97/8a/12ca489246ca1faaf5432844adbfce7ff2cc4997733e0af120869345643a/aiohttp-3.13.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c", size = 734190, upload-time = "2026-01-03T17:30:45.832Z" }, - { url = "https://files.pythonhosted.org/packages/32/08/de43984c74ed1fca5c014808963cc83cb00d7bb06af228f132d33862ca76/aiohttp-3.13.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9", size = 491783, upload-time = "2026-01-03T17:30:47.466Z" }, - { url = "https://files.pythonhosted.org/packages/17/f8/8dd2cf6112a5a76f81f81a5130c57ca829d101ad583ce57f889179accdda/aiohttp-3.13.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3", size = 490704, upload-time = "2026-01-03T17:30:49.373Z" }, - { url = "https://files.pythonhosted.org/packages/6d/40/a46b03ca03936f832bc7eaa47cfbb1ad012ba1be4790122ee4f4f8cba074/aiohttp-3.13.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf", size = 1720652, upload-time = "2026-01-03T17:30:50.974Z" }, - { url = "https://files.pythonhosted.org/packages/f7/7e/917fe18e3607af92657e4285498f500dca797ff8c918bd7d90b05abf6c2a/aiohttp-3.13.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6", size = 1692014, upload-time = "2026-01-03T17:30:52.729Z" }, - { url = "https://files.pythonhosted.org/packages/71/b6/cefa4cbc00d315d68973b671cf105b21a609c12b82d52e5d0c9ae61d2a09/aiohttp-3.13.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d", size = 1759777, upload-time = "2026-01-03T17:30:54.537Z" }, - { url = "https://files.pythonhosted.org/packages/fb/e3/e06ee07b45e59e6d81498b591fc589629be1553abb2a82ce33efe2a7b068/aiohttp-3.13.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261", size = 1861276, upload-time = "2026-01-03T17:30:56.512Z" }, - { url = "https://files.pythonhosted.org/packages/7c/24/75d274228acf35ceeb2850b8ce04de9dd7355ff7a0b49d607ee60c29c518/aiohttp-3.13.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0", size = 1743131, upload-time = "2026-01-03T17:30:58.256Z" }, - { url = "https://files.pythonhosted.org/packages/04/98/3d21dde21889b17ca2eea54fdcff21b27b93f45b7bb94ca029c31ab59dc3/aiohttp-3.13.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730", size = 1556863, upload-time = "2026-01-03T17:31:00.445Z" }, - { url = "https://files.pythonhosted.org/packages/9e/84/da0c3ab1192eaf64782b03971ab4055b475d0db07b17eff925e8c93b3aa5/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91", size = 1682793, upload-time = "2026-01-03T17:31:03.024Z" }, - { url = "https://files.pythonhosted.org/packages/ff/0f/5802ada182f575afa02cbd0ec5180d7e13a402afb7c2c03a9aa5e5d49060/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3", size = 1716676, upload-time = "2026-01-03T17:31:04.842Z" }, - { url = "https://files.pythonhosted.org/packages/3f/8c/714d53bd8b5a4560667f7bbbb06b20c2382f9c7847d198370ec6526af39c/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4", size = 1733217, upload-time = "2026-01-03T17:31:06.868Z" }, - { url = "https://files.pythonhosted.org/packages/7d/79/e2176f46d2e963facea939f5be2d26368ce543622be6f00a12844d3c991f/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998", size = 1552303, upload-time = "2026-01-03T17:31:08.958Z" }, - { url = "https://files.pythonhosted.org/packages/ab/6a/28ed4dea1759916090587d1fe57087b03e6c784a642b85ef48217b0277ae/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0", size = 1763673, upload-time = "2026-01-03T17:31:10.676Z" }, - { url = "https://files.pythonhosted.org/packages/e8/35/4a3daeb8b9fab49240d21c04d50732313295e4bd813a465d840236dd0ce1/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591", size = 1721120, upload-time = "2026-01-03T17:31:12.575Z" }, - { url = "https://files.pythonhosted.org/packages/bc/9f/d643bb3c5fb99547323e635e251c609fbbc660d983144cfebec529e09264/aiohttp-3.13.3-cp313-cp313-win32.whl", hash = "sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf", size = 427383, upload-time = "2026-01-03T17:31:14.382Z" }, - { url = "https://files.pythonhosted.org/packages/4e/f1/ab0395f8a79933577cdd996dd2f9aa6014af9535f65dddcf88204682fe62/aiohttp-3.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e", size = 453899, upload-time = "2026-01-03T17:31:15.958Z" }, - { url = "https://files.pythonhosted.org/packages/99/36/5b6514a9f5d66f4e2597e40dea2e3db271e023eb7a5d22defe96ba560996/aiohttp-3.13.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808", size = 737238, upload-time = "2026-01-03T17:31:17.909Z" }, - { url = "https://files.pythonhosted.org/packages/f7/49/459327f0d5bcd8c6c9ca69e60fdeebc3622861e696490d8674a6d0cb90a6/aiohttp-3.13.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415", size = 492292, upload-time = "2026-01-03T17:31:19.919Z" }, - { url = "https://files.pythonhosted.org/packages/e8/0b/b97660c5fd05d3495b4eb27f2d0ef18dc1dc4eff7511a9bf371397ff0264/aiohttp-3.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f", size = 493021, upload-time = "2026-01-03T17:31:21.636Z" }, - { url = "https://files.pythonhosted.org/packages/54/d4/438efabdf74e30aeceb890c3290bbaa449780583b1270b00661126b8aae4/aiohttp-3.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6", size = 1717263, upload-time = "2026-01-03T17:31:23.296Z" }, - { url = "https://files.pythonhosted.org/packages/71/f2/7bddc7fd612367d1459c5bcf598a9e8f7092d6580d98de0e057eb42697ad/aiohttp-3.13.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687", size = 1669107, upload-time = "2026-01-03T17:31:25.334Z" }, - { url = "https://files.pythonhosted.org/packages/00/5a/1aeaecca40e22560f97610a329e0e5efef5e0b5afdf9f857f0d93839ab2e/aiohttp-3.13.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26", size = 1760196, upload-time = "2026-01-03T17:31:27.394Z" }, - { url = "https://files.pythonhosted.org/packages/f8/f8/0ff6992bea7bd560fc510ea1c815f87eedd745fe035589c71ce05612a19a/aiohttp-3.13.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a", size = 1843591, upload-time = "2026-01-03T17:31:29.238Z" }, - { url = "https://files.pythonhosted.org/packages/e3/d1/e30e537a15f53485b61f5be525f2157da719819e8377298502aebac45536/aiohttp-3.13.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1", size = 1720277, upload-time = "2026-01-03T17:31:31.053Z" }, - { url = "https://files.pythonhosted.org/packages/84/45/23f4c451d8192f553d38d838831ebbc156907ea6e05557f39563101b7717/aiohttp-3.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25", size = 1548575, upload-time = "2026-01-03T17:31:32.87Z" }, - { url = "https://files.pythonhosted.org/packages/6a/ed/0a42b127a43712eda7807e7892c083eadfaf8429ca8fb619662a530a3aab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603", size = 1679455, upload-time = "2026-01-03T17:31:34.76Z" }, - { url = "https://files.pythonhosted.org/packages/2e/b5/c05f0c2b4b4fe2c9d55e73b6d3ed4fd6c9dc2684b1d81cbdf77e7fad9adb/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a", size = 1687417, upload-time = "2026-01-03T17:31:36.699Z" }, - { url = "https://files.pythonhosted.org/packages/c9/6b/915bc5dad66aef602b9e459b5a973529304d4e89ca86999d9d75d80cbd0b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926", size = 1729968, upload-time = "2026-01-03T17:31:38.622Z" }, - { url = "https://files.pythonhosted.org/packages/11/3b/e84581290a9520024a08640b63d07673057aec5ca548177a82026187ba73/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba", size = 1545690, upload-time = "2026-01-03T17:31:40.57Z" }, - { url = "https://files.pythonhosted.org/packages/f5/04/0c3655a566c43fd647c81b895dfe361b9f9ad6d58c19309d45cff52d6c3b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c", size = 1746390, upload-time = "2026-01-03T17:31:42.857Z" }, - { url = "https://files.pythonhosted.org/packages/1f/53/71165b26978f719c3419381514c9690bd5980e764a09440a10bb816ea4ab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43", size = 1702188, upload-time = "2026-01-03T17:31:44.984Z" }, - { url = "https://files.pythonhosted.org/packages/29/a7/cbe6c9e8e136314fa1980da388a59d2f35f35395948a08b6747baebb6aa6/aiohttp-3.13.3-cp314-cp314-win32.whl", hash = "sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1", size = 433126, upload-time = "2026-01-03T17:31:47.463Z" }, - { url = "https://files.pythonhosted.org/packages/de/56/982704adea7d3b16614fc5936014e9af85c0e34b58f9046655817f04306e/aiohttp-3.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984", size = 459128, upload-time = "2026-01-03T17:31:49.2Z" }, - { url = "https://files.pythonhosted.org/packages/6c/2a/3c79b638a9c3d4658d345339d22070241ea341ed4e07b5ac60fb0f418003/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c", size = 769512, upload-time = "2026-01-03T17:31:51.134Z" }, - { url = "https://files.pythonhosted.org/packages/29/b9/3e5014d46c0ab0db8707e0ac2711ed28c4da0218c358a4e7c17bae0d8722/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592", size = 506444, upload-time = "2026-01-03T17:31:52.85Z" }, - { url = "https://files.pythonhosted.org/packages/90/03/c1d4ef9a054e151cd7839cdc497f2638f00b93cbe8043983986630d7a80c/aiohttp-3.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f", size = 510798, upload-time = "2026-01-03T17:31:54.91Z" }, - { url = "https://files.pythonhosted.org/packages/ea/76/8c1e5abbfe8e127c893fe7ead569148a4d5a799f7cf958d8c09f3eedf097/aiohttp-3.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29", size = 1868835, upload-time = "2026-01-03T17:31:56.733Z" }, - { url = "https://files.pythonhosted.org/packages/8e/ac/984c5a6f74c363b01ff97adc96a3976d9c98940b8969a1881575b279ac5d/aiohttp-3.13.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc", size = 1720486, upload-time = "2026-01-03T17:31:58.65Z" }, - { url = "https://files.pythonhosted.org/packages/b2/9a/b7039c5f099c4eb632138728828b33428585031a1e658d693d41d07d89d1/aiohttp-3.13.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2", size = 1847951, upload-time = "2026-01-03T17:32:00.989Z" }, - { url = "https://files.pythonhosted.org/packages/3c/02/3bec2b9a1ba3c19ff89a43a19324202b8eb187ca1e928d8bdac9bbdddebd/aiohttp-3.13.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587", size = 1941001, upload-time = "2026-01-03T17:32:03.122Z" }, - { url = "https://files.pythonhosted.org/packages/37/df/d879401cedeef27ac4717f6426c8c36c3091c6e9f08a9178cc87549c537f/aiohttp-3.13.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8", size = 1797246, upload-time = "2026-01-03T17:32:05.255Z" }, - { url = "https://files.pythonhosted.org/packages/8d/15/be122de1f67e6953add23335c8ece6d314ab67c8bebb3f181063010795a7/aiohttp-3.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632", size = 1627131, upload-time = "2026-01-03T17:32:07.607Z" }, - { url = "https://files.pythonhosted.org/packages/12/12/70eedcac9134cfa3219ab7af31ea56bc877395b1ac30d65b1bc4b27d0438/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64", size = 1795196, upload-time = "2026-01-03T17:32:09.59Z" }, - { url = "https://files.pythonhosted.org/packages/32/11/b30e1b1cd1f3054af86ebe60df96989c6a414dd87e27ad16950eee420bea/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0", size = 1782841, upload-time = "2026-01-03T17:32:11.445Z" }, - { url = "https://files.pythonhosted.org/packages/88/0d/d98a9367b38912384a17e287850f5695c528cff0f14f791ce8ee2e4f7796/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56", size = 1795193, upload-time = "2026-01-03T17:32:13.705Z" }, - { url = "https://files.pythonhosted.org/packages/43/a5/a2dfd1f5ff5581632c7f6a30e1744deda03808974f94f6534241ef60c751/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72", size = 1621979, upload-time = "2026-01-03T17:32:15.965Z" }, - { url = "https://files.pythonhosted.org/packages/fa/f0/12973c382ae7c1cccbc4417e129c5bf54c374dfb85af70893646e1f0e749/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df", size = 1822193, upload-time = "2026-01-03T17:32:18.219Z" }, - { url = "https://files.pythonhosted.org/packages/3c/5f/24155e30ba7f8c96918af1350eb0663e2430aad9e001c0489d89cd708ab1/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa", size = 1769801, upload-time = "2026-01-03T17:32:20.25Z" }, - { url = "https://files.pythonhosted.org/packages/eb/f8/7314031ff5c10e6ece114da79b338ec17eeff3a079e53151f7e9f43c4723/aiohttp-3.13.3-cp314-cp314t-win32.whl", hash = "sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767", size = 466523, upload-time = "2026-01-03T17:32:22.215Z" }, - { url = "https://files.pythonhosted.org/packages/b4/63/278a98c715ae467624eafe375542d8ba9b4383a016df8fdefe0ae28382a7/aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344", size = 499694, upload-time = "2026-01-03T17:32:24.546Z" }, - { url = "https://files.pythonhosted.org/packages/bf/79/446655656861d3e7e2c32bfcf160c7aa9e9dc63776a691b124dba65cdd77/aiohttp-3.13.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e", size = 741433, upload-time = "2026-01-03T17:32:26.453Z" }, - { url = "https://files.pythonhosted.org/packages/cb/49/773c4b310b5140d2fb5e79bb0bf40b7b41dad80a288ca1a8759f5f72bda9/aiohttp-3.13.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7", size = 497332, upload-time = "2026-01-03T17:32:28.37Z" }, - { url = "https://files.pythonhosted.org/packages/bc/31/1dcbc4b83a4e6f76a0ad883f07f21ffbfe29750c89db97381701508c9f45/aiohttp-3.13.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02", size = 492365, upload-time = "2026-01-03T17:32:30.234Z" }, - { url = "https://files.pythonhosted.org/packages/5a/b5/b50657496c8754482cd7964e50aaf3aa84b3db61ed45daec4c1aec5b94b4/aiohttp-3.13.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43", size = 1660440, upload-time = "2026-01-03T17:32:32.586Z" }, - { url = "https://files.pythonhosted.org/packages/2a/73/9b69e5139d89d75127569298931444ad78ea86a5befd5599780b1e9a6880/aiohttp-3.13.3-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6", size = 1632740, upload-time = "2026-01-03T17:32:34.793Z" }, - { url = "https://files.pythonhosted.org/packages/ef/fe/3ea9b5af694b4e3aec0d0613a806132ca744747146fca68e96bf056f61a7/aiohttp-3.13.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce", size = 1719782, upload-time = "2026-01-03T17:32:37.737Z" }, - { url = "https://files.pythonhosted.org/packages/fb/c2/46b3b06e60851cbb71efb0f79a3267279cbef7b12c58e68a1e897f269cca/aiohttp-3.13.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80", size = 1813527, upload-time = "2026-01-03T17:32:39.973Z" }, - { url = "https://files.pythonhosted.org/packages/36/23/71ceb78c769ed65fe4c697692de232b63dab399210678d2b00961ccb0619/aiohttp-3.13.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a", size = 1661268, upload-time = "2026-01-03T17:32:42.082Z" }, - { url = "https://files.pythonhosted.org/packages/c4/8d/86e929523d955e85ebab7c0e2b9e0cb63604cfc27dc3280e10d0063cf682/aiohttp-3.13.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6", size = 1552742, upload-time = "2026-01-03T17:32:44.622Z" }, - { url = "https://files.pythonhosted.org/packages/3a/ea/3f5987cba1bab6bd151f0d97aa60f0ce04d3c83316692a6bb6ba2fb69f92/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558", size = 1632918, upload-time = "2026-01-03T17:32:46.749Z" }, - { url = "https://files.pythonhosted.org/packages/be/2c/7e1e85121f2e31ee938cb83a8f32dfafd4908530c10fabd6d46761c12ac7/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7", size = 1644446, upload-time = "2026-01-03T17:32:49.063Z" }, - { url = "https://files.pythonhosted.org/packages/5d/35/ce6133d423ad0e8ca976a7c848f7146bca3520eea4ccf6b95e2d077c9d20/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877", size = 1689487, upload-time = "2026-01-03T17:32:51.113Z" }, - { url = "https://files.pythonhosted.org/packages/50/f7/ff7a27c15603d460fd1366b3c22054f7ae4fa9310aca40b43bde35867fcd/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3", size = 1540715, upload-time = "2026-01-03T17:32:53.38Z" }, - { url = "https://files.pythonhosted.org/packages/17/02/053f11346e5b962e6d8a1c4f8c70c29d5970a1b4b8e7894c68e12c27a57f/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704", size = 1711835, upload-time = "2026-01-03T17:32:56.088Z" }, - { url = "https://files.pythonhosted.org/packages/fb/71/9b9761ddf276fd6708d13720197cbac19b8d67ecfa9116777924056cfcaa/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f", size = 1649593, upload-time = "2026-01-03T17:32:58.181Z" }, - { url = "https://files.pythonhosted.org/packages/ae/72/5d817e9ea218acae12a5e3b9ad1178cf0c12fc3570c0b47eea2daf95f9ea/aiohttp-3.13.3-cp39-cp39-win32.whl", hash = "sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1", size = 434831, upload-time = "2026-01-03T17:33:00.577Z" }, - { url = "https://files.pythonhosted.org/packages/39/cb/22659d9bf3149b7a2927bc2769cc9c8f8f5a80eba098398e03c199a43a85/aiohttp-3.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538", size = 457697, upload-time = "2026-01-03T17:33:03.167Z" }, + { url = "https://files.pythonhosted.org/packages/bd/85/cebc47ee74d8b408749073a1a46c6fcba13d170dc8af7e61996c6c9394ac/aiohttp-3.13.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b", size = 750547, upload-time = "2026-03-31T21:56:30.024Z" }, + { url = "https://files.pythonhosted.org/packages/05/98/afd308e35b9d3d8c9ec54c0918f1d722c86dc17ddfec272fcdbcce5a3124/aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5", size = 503535, upload-time = "2026-03-31T21:56:31.935Z" }, + { url = "https://files.pythonhosted.org/packages/6f/4d/926c183e06b09d5270a309eb50fbde7b09782bfd305dec1e800f329834fb/aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670", size = 497830, upload-time = "2026-03-31T21:56:33.654Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d6/f47d1c690f115a5c2a5e8938cce4a232a5be9aac5c5fb2647efcbbbda333/aiohttp-3.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274", size = 1682474, upload-time = "2026-03-31T21:56:35.513Z" }, + { url = "https://files.pythonhosted.org/packages/01/44/056fd37b1bb52eac760303e5196acc74d9d546631b035704ae5927f7b4ac/aiohttp-3.13.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a", size = 1655259, upload-time = "2026-03-31T21:56:37.843Z" }, + { url = "https://files.pythonhosted.org/packages/91/9f/78eb1a20c1c28ae02f6a3c0f4d7b0dcc66abce5290cadd53d78ce3084175/aiohttp-3.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d", size = 1736204, upload-time = "2026-03-31T21:56:39.822Z" }, + { url = "https://files.pythonhosted.org/packages/de/6c/d20d7de23f0b52b8c1d9e2033b2db1ac4dacbb470bb74c56de0f5f86bb4f/aiohttp-3.13.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796", size = 1826198, upload-time = "2026-03-31T21:56:41.378Z" }, + { url = "https://files.pythonhosted.org/packages/2f/86/a6f3ff1fd795f49545a7c74b2c92f62729135d73e7e4055bf74da5a26c82/aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95", size = 1681329, upload-time = "2026-03-31T21:56:43.374Z" }, + { url = "https://files.pythonhosted.org/packages/fb/68/84cd3dab6b7b4f3e6fe9459a961acb142aaab846417f6e8905110d7027e5/aiohttp-3.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5", size = 1560023, upload-time = "2026-03-31T21:56:45.031Z" }, + { url = "https://files.pythonhosted.org/packages/41/2c/db61b64b0249e30f954a65ab4cb4970ced57544b1de2e3c98ee5dc24165f/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a", size = 1652372, upload-time = "2026-03-31T21:56:47.075Z" }, + { url = "https://files.pythonhosted.org/packages/25/6f/e96988a6c982d047810c772e28c43c64c300c943b0ed5c1c0c4ce1e1027c/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73", size = 1662031, upload-time = "2026-03-31T21:56:48.835Z" }, + { url = "https://files.pythonhosted.org/packages/b7/26/a56feace81f3d347b4052403a9d03754a0ab23f7940780dada0849a38c92/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297", size = 1708118, upload-time = "2026-03-31T21:56:50.833Z" }, + { url = "https://files.pythonhosted.org/packages/78/6e/b6173a8ff03d01d5e1a694bc06764b5dad1df2d4ed8f0ceec12bb3277936/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074", size = 1548667, upload-time = "2026-03-31T21:56:52.81Z" }, + { url = "https://files.pythonhosted.org/packages/16/13/13296ffe2c132d888b3fe2c195c8b9c0c24c89c3fa5cc2c44464dc23b22e/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e", size = 1724490, upload-time = "2026-03-31T21:56:54.541Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/1f1c287f4a79782ef36e5a6e62954c85343bc30470d862d30bd5f26c9fa2/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7", size = 1667109, upload-time = "2026-03-31T21:56:56.21Z" }, + { url = "https://files.pythonhosted.org/packages/ef/42/8461a2aaf60a8f4ea4549a4056be36b904b0eb03d97ca9a8a2604681a500/aiohttp-3.13.5-cp310-cp310-win32.whl", hash = "sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9", size = 439478, upload-time = "2026-03-31T21:56:58.292Z" }, + { url = "https://files.pythonhosted.org/packages/e5/71/06956304cb5ee439dfe8d86e1b2e70088bd88ed1ced1f42fb29e5d855f0e/aiohttp-3.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76", size = 462047, upload-time = "2026-03-31T21:57:00.257Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f5/a20c4ac64aeaef1679e25c9983573618ff765d7aa829fa2b84ae7573169e/aiohttp-3.13.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6", size = 757513, upload-time = "2026-03-31T21:57:02.146Z" }, + { url = "https://files.pythonhosted.org/packages/75/0a/39fa6c6b179b53fcb3e4b3d2b6d6cad0180854eda17060c7218540102bef/aiohttp-3.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d", size = 506748, upload-time = "2026-03-31T21:57:04.275Z" }, + { url = "https://files.pythonhosted.org/packages/87/ec/e38ce072e724fd7add6243613f8d1810da084f54175353d25ccf9f9c7e5a/aiohttp-3.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c", size = 501673, upload-time = "2026-03-31T21:57:06.208Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ba/3bc7525d7e2beaa11b309a70d48b0d3cfc3c2089ec6a7d0820d59c657053/aiohttp-3.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb", size = 1763757, upload-time = "2026-03-31T21:57:07.882Z" }, + { url = "https://files.pythonhosted.org/packages/5e/ab/e87744cf18f1bd78263aba24924d4953b41086bd3a31d22452378e9028a0/aiohttp-3.13.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6", size = 1720152, upload-time = "2026-03-31T21:57:09.946Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f3/ed17a6f2d742af17b50bae2d152315ed1b164b07a5fd5cc1754d99e4dfa5/aiohttp-3.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13", size = 1818010, upload-time = "2026-03-31T21:57:12.157Z" }, + { url = "https://files.pythonhosted.org/packages/53/06/ecbc63dc937192e2a5cb46df4d3edb21deb8225535818802f210a6ea5816/aiohttp-3.13.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174", size = 1907251, upload-time = "2026-03-31T21:57:14.023Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a5/0521aa32c1ddf3aa1e71dcc466be0b7db2771907a13f18cddaa45967d97b/aiohttp-3.13.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc", size = 1759969, upload-time = "2026-03-31T21:57:16.146Z" }, + { url = "https://files.pythonhosted.org/packages/f6/78/a38f8c9105199dd3b9706745865a8a59d0041b6be0ca0cc4b2ccf1bab374/aiohttp-3.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6", size = 1616871, upload-time = "2026-03-31T21:57:17.856Z" }, + { url = "https://files.pythonhosted.org/packages/6f/41/27392a61ead8ab38072105c71aa44ff891e71653fe53d576a7067da2b4e8/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49", size = 1739844, upload-time = "2026-03-31T21:57:19.679Z" }, + { url = "https://files.pythonhosted.org/packages/6e/55/5564e7ae26d94f3214250009a0b1c65a0c6af4bf88924ccb6fdab901de28/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8", size = 1731969, upload-time = "2026-03-31T21:57:22.006Z" }, + { url = "https://files.pythonhosted.org/packages/6d/c5/705a3929149865fc941bcbdd1047b238e4a72bcb215a9b16b9d7a2e8d992/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d", size = 1795193, upload-time = "2026-03-31T21:57:24.256Z" }, + { url = "https://files.pythonhosted.org/packages/a6/19/edabed62f718d02cff7231ca0db4ef1c72504235bc467f7b67adb1679f48/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c", size = 1606477, upload-time = "2026-03-31T21:57:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/de/fc/76f80ef008675637d88d0b21584596dc27410a990b0918cb1e5776545b5b/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac", size = 1813198, upload-time = "2026-03-31T21:57:28.316Z" }, + { url = "https://files.pythonhosted.org/packages/e5/67/5b3ac26b80adb20ea541c487f73730dc8fa107d632c998f25bbbab98fcda/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3", size = 1752321, upload-time = "2026-03-31T21:57:30.549Z" }, + { url = "https://files.pythonhosted.org/packages/88/06/e4a2e49255ea23fa4feeb5ab092d90240d927c15e47b5b5c48dff5a9ce29/aiohttp-3.13.5-cp311-cp311-win32.whl", hash = "sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06", size = 439069, upload-time = "2026-03-31T21:57:32.388Z" }, + { url = "https://files.pythonhosted.org/packages/c0/43/8c7163a596dab4f8be12c190cf467a1e07e4734cf90eebb39f7f5d53fc6a/aiohttp-3.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8", size = 462859, upload-time = "2026-03-31T21:57:34.455Z" }, + { url = "https://files.pythonhosted.org/packages/be/6f/353954c29e7dcce7cf00280a02c75f30e133c00793c7a2ed3776d7b2f426/aiohttp-3.13.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9", size = 748876, upload-time = "2026-03-31T21:57:36.319Z" }, + { url = "https://files.pythonhosted.org/packages/f5/1b/428a7c64687b3b2e9cd293186695affc0e1e54a445d0361743b231f11066/aiohttp-3.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416", size = 499557, upload-time = "2026-03-31T21:57:38.236Z" }, + { url = "https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2", size = 500258, upload-time = "2026-03-31T21:57:39.923Z" }, + { url = "https://files.pythonhosted.org/packages/67/84/c9ecc5828cb0b3695856c07c0a6817a99d51e2473400f705275a2b3d9239/aiohttp-3.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4", size = 1749199, upload-time = "2026-03-31T21:57:41.938Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d3/3c6d610e66b495657622edb6ae7c7fd31b2e9086b4ec50b47897ad6042a9/aiohttp-3.13.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9", size = 1721013, upload-time = "2026-03-31T21:57:43.904Z" }, + { url = "https://files.pythonhosted.org/packages/49/a0/24409c12217456df0bae7babe3b014e460b0b38a8e60753d6cb339f6556d/aiohttp-3.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5", size = 1781501, upload-time = "2026-03-31T21:57:46.285Z" }, + { url = "https://files.pythonhosted.org/packages/98/9d/b65ec649adc5bccc008b0957a9a9c691070aeac4e41cea18559fef49958b/aiohttp-3.13.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e", size = 1878981, upload-time = "2026-03-31T21:57:48.734Z" }, + { url = "https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1", size = 1767934, upload-time = "2026-03-31T21:57:51.171Z" }, + { url = "https://files.pythonhosted.org/packages/31/04/d3f8211f273356f158e3464e9e45484d3fb8c4ce5eb2f6fe9405c3273983/aiohttp-3.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286", size = 1566671, upload-time = "2026-03-31T21:57:53.326Z" }, + { url = "https://files.pythonhosted.org/packages/41/db/073e4ebe00b78e2dfcacff734291651729a62953b48933d765dc513bf798/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9", size = 1705219, upload-time = "2026-03-31T21:57:55.385Z" }, + { url = "https://files.pythonhosted.org/packages/48/45/7dfba71a2f9fd97b15c95c06819de7eb38113d2cdb6319669195a7d64270/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88", size = 1743049, upload-time = "2026-03-31T21:57:57.341Z" }, + { url = "https://files.pythonhosted.org/packages/18/71/901db0061e0f717d226386a7f471bb59b19566f2cae5f0d93874b017271f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3", size = 1749557, upload-time = "2026-03-31T21:57:59.626Z" }, + { url = "https://files.pythonhosted.org/packages/08/d5/41eebd16066e59cd43728fe74bce953d7402f2b4ddfdfef2c0e9f17ca274/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b", size = 1558931, upload-time = "2026-03-31T21:58:01.972Z" }, + { url = "https://files.pythonhosted.org/packages/30/e6/4a799798bf05740e66c3a1161079bda7a3dd8e22ca392481d7a7f9af82a6/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe", size = 1774125, upload-time = "2026-03-31T21:58:04.007Z" }, + { url = "https://files.pythonhosted.org/packages/84/63/7749337c90f92bc2cb18f9560d67aa6258c7060d1397d21529b8004fcf6f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14", size = 1732427, upload-time = "2026-03-31T21:58:06.337Z" }, + { url = "https://files.pythonhosted.org/packages/98/de/cf2f44ff98d307e72fb97d5f5bbae3bfcb442f0ea9790c0bf5c5c2331404/aiohttp-3.13.5-cp312-cp312-win32.whl", hash = "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3", size = 433534, upload-time = "2026-03-31T21:58:08.712Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1", size = 460446, upload-time = "2026-03-31T21:58:10.945Z" }, + { url = "https://files.pythonhosted.org/packages/78/e9/d76bf503005709e390122d34e15256b88f7008e246c4bdbe915cd4f1adce/aiohttp-3.13.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61", size = 742930, upload-time = "2026-03-31T21:58:13.155Z" }, + { url = "https://files.pythonhosted.org/packages/57/00/4b7b70223deaebd9bb85984d01a764b0d7bd6526fcdc73cca83bcbe7243e/aiohttp-3.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832", size = 496927, upload-time = "2026-03-31T21:58:15.073Z" }, + { url = "https://files.pythonhosted.org/packages/9c/f5/0fb20fb49f8efdcdce6cd8127604ad2c503e754a8f139f5e02b01626523f/aiohttp-3.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9", size = 497141, upload-time = "2026-03-31T21:58:17.009Z" }, + { url = "https://files.pythonhosted.org/packages/3b/86/b7c870053e36a94e8951b803cb5b909bfbc9b90ca941527f5fcafbf6b0fa/aiohttp-3.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090", size = 1732476, upload-time = "2026-03-31T21:58:18.925Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e5/4e161f84f98d80c03a238671b4136e6530453d65262867d989bbe78244d0/aiohttp-3.13.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b", size = 1706507, upload-time = "2026-03-31T21:58:21.094Z" }, + { url = "https://files.pythonhosted.org/packages/d4/56/ea11a9f01518bd5a2a2fcee869d248c4b8a0cfa0bb13401574fa31adf4d4/aiohttp-3.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a", size = 1773465, upload-time = "2026-03-31T21:58:23.159Z" }, + { url = "https://files.pythonhosted.org/packages/eb/40/333ca27fb74b0383f17c90570c748f7582501507307350a79d9f9f3c6eb1/aiohttp-3.13.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8", size = 1873523, upload-time = "2026-03-31T21:58:25.59Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d2/e2f77eef1acb7111405433c707dc735e63f67a56e176e72e9e7a2cd3f493/aiohttp-3.13.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665", size = 1754113, upload-time = "2026-03-31T21:58:27.624Z" }, + { url = "https://files.pythonhosted.org/packages/fb/56/3f653d7f53c89669301ec9e42c95233e2a0c0a6dd051269e6e678db4fdb0/aiohttp-3.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540", size = 1562351, upload-time = "2026-03-31T21:58:29.918Z" }, + { url = "https://files.pythonhosted.org/packages/ec/a6/9b3e91eb8ae791cce4ee736da02211c85c6f835f1bdfac0594a8a3b7018c/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb", size = 1693205, upload-time = "2026-03-31T21:58:32.214Z" }, + { url = "https://files.pythonhosted.org/packages/98/fc/bfb437a99a2fcebd6b6eaec609571954de2ed424f01c352f4b5504371dd3/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46", size = 1730618, upload-time = "2026-03-31T21:58:34.728Z" }, + { url = "https://files.pythonhosted.org/packages/e4/b6/c8534862126191a034f68153194c389addc285a0f1347d85096d349bbc15/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8", size = 1745185, upload-time = "2026-03-31T21:58:36.909Z" }, + { url = "https://files.pythonhosted.org/packages/0b/93/4ca8ee2ef5236e2707e0fd5fecb10ce214aee1ff4ab307af9c558bda3b37/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d", size = 1557311, upload-time = "2026-03-31T21:58:39.38Z" }, + { url = "https://files.pythonhosted.org/packages/57/ae/76177b15f18c5f5d094f19901d284025db28eccc5ae374d1d254181d33f4/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6", size = 1773147, upload-time = "2026-03-31T21:58:41.476Z" }, + { url = "https://files.pythonhosted.org/packages/01/a4/62f05a0a98d88af59d93b7fcac564e5f18f513cb7471696ac286db970d6a/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c", size = 1730356, upload-time = "2026-03-31T21:58:44.049Z" }, + { url = "https://files.pythonhosted.org/packages/e4/85/fc8601f59dfa8c9523808281f2da571f8b4699685f9809a228adcc90838d/aiohttp-3.13.5-cp313-cp313-win32.whl", hash = "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc", size = 432637, upload-time = "2026-03-31T21:58:46.167Z" }, + { url = "https://files.pythonhosted.org/packages/c0/1b/ac685a8882896acf0f6b31d689e3792199cfe7aba37969fa91da63a7fa27/aiohttp-3.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83", size = 458896, upload-time = "2026-03-31T21:58:48.119Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ce/46572759afc859e867a5bc8ec3487315869013f59281ce61764f76d879de/aiohttp-3.13.5-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c", size = 745721, upload-time = "2026-03-31T21:58:50.229Z" }, + { url = "https://files.pythonhosted.org/packages/13/fe/8a2efd7626dbe6049b2ef8ace18ffda8a4dfcbe1bcff3ac30c0c7575c20b/aiohttp-3.13.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be", size = 497663, upload-time = "2026-03-31T21:58:52.232Z" }, + { url = "https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25", size = 499094, upload-time = "2026-03-31T21:58:54.566Z" }, + { url = "https://files.pythonhosted.org/packages/0a/33/a8362cb15cf16a3af7e86ed11962d5cd7d59b449202dc576cdc731310bde/aiohttp-3.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56", size = 1726701, upload-time = "2026-03-31T21:58:56.864Z" }, + { url = "https://files.pythonhosted.org/packages/45/0c/c091ac5c3a17114bd76cbf85d674650969ddf93387876cf67f754204bd77/aiohttp-3.13.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2", size = 1683360, upload-time = "2026-03-31T21:58:59.072Z" }, + { url = "https://files.pythonhosted.org/packages/23/73/bcee1c2b79bc275e964d1446c55c54441a461938e70267c86afaae6fba27/aiohttp-3.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a", size = 1773023, upload-time = "2026-03-31T21:59:01.776Z" }, + { url = "https://files.pythonhosted.org/packages/c7/ef/720e639df03004fee2d869f771799d8c23046dec47d5b81e396c7cda583a/aiohttp-3.13.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be", size = 1853795, upload-time = "2026-03-31T21:59:04.568Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b", size = 1730405, upload-time = "2026-03-31T21:59:07.221Z" }, + { url = "https://files.pythonhosted.org/packages/ce/75/ee1fd286ca7dc599d824b5651dad7b3be7ff8d9a7e7b3fe9820d9180f7db/aiohttp-3.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94", size = 1558082, upload-time = "2026-03-31T21:59:09.484Z" }, + { url = "https://files.pythonhosted.org/packages/c3/20/1e9e6650dfc436340116b7aa89ff8cb2bbdf0abc11dfaceaad8f74273a10/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d", size = 1692346, upload-time = "2026-03-31T21:59:12.068Z" }, + { url = "https://files.pythonhosted.org/packages/d8/40/8ebc6658d48ea630ac7903912fe0dd4e262f0e16825aa4c833c56c9f1f56/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7", size = 1698891, upload-time = "2026-03-31T21:59:14.552Z" }, + { url = "https://files.pythonhosted.org/packages/d8/78/ea0ae5ec8ba7a5c10bdd6e318f1ba5e76fcde17db8275188772afc7917a4/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772", size = 1742113, upload-time = "2026-03-31T21:59:17.068Z" }, + { url = "https://files.pythonhosted.org/packages/8a/66/9d308ed71e3f2491be1acb8769d96c6f0c47d92099f3bc9119cada27b357/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5", size = 1553088, upload-time = "2026-03-31T21:59:19.541Z" }, + { url = "https://files.pythonhosted.org/packages/da/a6/6cc25ed8dfc6e00c90f5c6d126a98e2cf28957ad06fa1036bd34b6f24a2c/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1", size = 1757976, upload-time = "2026-03-31T21:59:22.311Z" }, + { url = "https://files.pythonhosted.org/packages/c1/2b/cce5b0ffe0de99c83e5e36d8f828e4161e415660a9f3e58339d07cce3006/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b", size = 1712444, upload-time = "2026-03-31T21:59:24.635Z" }, + { url = "https://files.pythonhosted.org/packages/6c/cf/9e1795b4160c58d29421eafd1a69c6ce351e2f7c8d3c6b7e4ca44aea1a5b/aiohttp-3.13.5-cp314-cp314-win32.whl", hash = "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3", size = 438128, upload-time = "2026-03-31T21:59:27.291Z" }, + { url = "https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162", size = 464029, upload-time = "2026-03-31T21:59:29.429Z" }, + { url = "https://files.pythonhosted.org/packages/79/11/c27d9332ee20d68dd164dc12a6ecdef2e2e35ecc97ed6cf0d2442844624b/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a", size = 778758, upload-time = "2026-03-31T21:59:31.547Z" }, + { url = "https://files.pythonhosted.org/packages/04/fb/377aead2e0a3ba5f09b7624f702a964bdf4f08b5b6728a9799830c80041e/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254", size = 512883, upload-time = "2026-03-31T21:59:34.098Z" }, + { url = "https://files.pythonhosted.org/packages/bb/a6/aa109a33671f7a5d3bd78b46da9d852797c5e665bfda7d6b373f56bff2ec/aiohttp-3.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36", size = 516668, upload-time = "2026-03-31T21:59:36.497Z" }, + { url = "https://files.pythonhosted.org/packages/79/b3/ca078f9f2fa9563c36fb8ef89053ea2bb146d6f792c5104574d49d8acb63/aiohttp-3.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f", size = 1883461, upload-time = "2026-03-31T21:59:38.723Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e3/a7ad633ca1ca497b852233a3cce6906a56c3225fb6d9217b5e5e60b7419d/aiohttp-3.13.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800", size = 1747661, upload-time = "2026-03-31T21:59:41.187Z" }, + { url = "https://files.pythonhosted.org/packages/33/b9/cd6fe579bed34a906d3d783fe60f2fa297ef55b27bb4538438ee49d4dc41/aiohttp-3.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf", size = 1863800, upload-time = "2026-03-31T21:59:43.84Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3f/2c1e2f5144cefa889c8afd5cf431994c32f3b29da9961698ff4e3811b79a/aiohttp-3.13.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b", size = 1958382, upload-time = "2026-03-31T21:59:46.187Z" }, + { url = "https://files.pythonhosted.org/packages/66/1d/f31ec3f1013723b3babe3609e7f119c2c2fb6ef33da90061a705ef3e1bc8/aiohttp-3.13.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a", size = 1803724, upload-time = "2026-03-31T21:59:48.656Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b4/57712dfc6f1542f067daa81eb61da282fab3e6f1966fca25db06c4fc62d5/aiohttp-3.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8", size = 1640027, upload-time = "2026-03-31T21:59:51.284Z" }, + { url = "https://files.pythonhosted.org/packages/25/3c/734c878fb43ec083d8e31bf029daae1beafeae582d1b35da234739e82ee7/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be", size = 1806644, upload-time = "2026-03-31T21:59:53.753Z" }, + { url = "https://files.pythonhosted.org/packages/20/a5/f671e5cbec1c21d044ff3078223f949748f3a7f86b14e34a365d74a5d21f/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b", size = 1791630, upload-time = "2026-03-31T21:59:56.239Z" }, + { url = "https://files.pythonhosted.org/packages/0b/63/fb8d0ad63a0b8a99be97deac8c04dacf0785721c158bdf23d679a87aa99e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6", size = 1809403, upload-time = "2026-03-31T21:59:59.103Z" }, + { url = "https://files.pythonhosted.org/packages/59/0c/bfed7f30662fcf12206481c2aac57dedee43fe1c49275e85b3a1e1742294/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037", size = 1634924, upload-time = "2026-03-31T22:00:02.116Z" }, + { url = "https://files.pythonhosted.org/packages/17/d6/fd518d668a09fd5a3319ae5e984d4d80b9a4b3df4e21c52f02251ef5a32e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500", size = 1836119, upload-time = "2026-03-31T22:00:04.756Z" }, + { url = "https://files.pythonhosted.org/packages/78/b7/15fb7a9d52e112a25b621c67b69c167805cb1f2ab8f1708a5c490d1b52fe/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9", size = 1772072, upload-time = "2026-03-31T22:00:07.494Z" }, + { url = "https://files.pythonhosted.org/packages/7e/df/57ba7f0c4a553fc2bd8b6321df236870ec6fd64a2a473a8a13d4f733214e/aiohttp-3.13.5-cp314-cp314t-win32.whl", hash = "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8", size = 471819, upload-time = "2026-03-31T22:00:10.277Z" }, + { url = "https://files.pythonhosted.org/packages/62/29/2f8418269e46454a26171bfdd6a055d74febf32234e474930f2f60a17145/aiohttp-3.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9", size = 505441, upload-time = "2026-03-31T22:00:12.791Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a5/630bc484695d4a1342bbae85fb8689bf979106525684fc88f05b397324ad/aiohttp-3.13.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf", size = 752872, upload-time = "2026-03-31T22:00:15.553Z" }, + { url = "https://files.pythonhosted.org/packages/cd/b8/6a19dda37fda94a9ebefb3c1ae0ff419ac7fbf4fb40750e992829fc13614/aiohttp-3.13.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1", size = 504582, upload-time = "2026-03-31T22:00:18.191Z" }, + { url = "https://files.pythonhosted.org/packages/d5/34/8413eafee3421ade2d6ce9e7c0da1213e1d7f0049be09dcdc342b03a39ba/aiohttp-3.13.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10", size = 499094, upload-time = "2026-03-31T22:00:21.118Z" }, + { url = "https://files.pythonhosted.org/packages/da/cf/c6f97006093d1e8ca40fbab843ff49ec7725ab668f0714dd1cb702c62cbd/aiohttp-3.13.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f", size = 1669505, upload-time = "2026-03-31T22:00:24.01Z" }, + { url = "https://files.pythonhosted.org/packages/c2/27/3b2288e66dcec8b04771b2bee3909f70e4072bea995cde5ab7e775e73ddc/aiohttp-3.13.5-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b", size = 1648928, upload-time = "2026-03-31T22:00:27.001Z" }, + { url = "https://files.pythonhosted.org/packages/3a/7f/605d766887594a88dcc27a19663499c7c5e13e7aa87f129b763765a2ee63/aiohttp-3.13.5-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643", size = 1731800, upload-time = "2026-03-31T22:00:29.603Z" }, + { url = "https://files.pythonhosted.org/packages/71/94/5a878e728e30699d22b118f1a6ad576ab6fff9eb2c6fc8a7faa9376a1c3e/aiohttp-3.13.5-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031", size = 1824247, upload-time = "2026-03-31T22:00:32.139Z" }, + { url = "https://files.pythonhosted.org/packages/37/99/84b448291e9996bb83bf4fad3a71a9786d542f19c50a3ff0531bfaba6fac/aiohttp-3.13.5-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258", size = 1670742, upload-time = "2026-03-31T22:00:34.788Z" }, + { url = "https://files.pythonhosted.org/packages/14/a8/d8d5d1ab6d29a4a3bdb9db31f161e338bfdf6638f6574ea8380f1d4a243c/aiohttp-3.13.5-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a", size = 1562474, upload-time = "2026-03-31T22:00:37.623Z" }, + { url = "https://files.pythonhosted.org/packages/92/e8/bd889697916f10b65524422c61b4eeaf919eb35a170290cccb680cbe4eb4/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88", size = 1642235, upload-time = "2026-03-31T22:00:40.541Z" }, + { url = "https://files.pythonhosted.org/packages/60/42/3f1928107131f1413a5972ace14ddcd5364968e9bd7b3ad71272defafc9c/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0", size = 1655397, upload-time = "2026-03-31T22:00:43.167Z" }, + { url = "https://files.pythonhosted.org/packages/b2/79/c4bbcf4cac3a4715a326e49720ccdc3a4b5e14a367c5029eae7727d06029/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f", size = 1703509, upload-time = "2026-03-31T22:00:45.908Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e6/32d245876f211a7308a7d5437707f9296b1f9837a2888a407ed04e61321c/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8", size = 1550098, upload-time = "2026-03-31T22:00:49.48Z" }, + { url = "https://files.pythonhosted.org/packages/db/62/ab0f1304def56ce2356e6fbb9f0b024d6544010351430070f48f53b89e0a/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f", size = 1724326, upload-time = "2026-03-31T22:00:52.165Z" }, + { url = "https://files.pythonhosted.org/packages/c4/9a/aab4469689024046220ea438aa020ea2ae04cd1dd71aea3057e094f8c357/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b", size = 1658824, upload-time = "2026-03-31T22:00:55.122Z" }, + { url = "https://files.pythonhosted.org/packages/b0/98/bcc35d4db687acabf06d41f561a99fa88bca145292513388c858d99b72c5/aiohttp-3.13.5-cp39-cp39-win32.whl", hash = "sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83", size = 440302, upload-time = "2026-03-31T22:00:57.673Z" }, + { url = "https://files.pythonhosted.org/packages/25/61/b0203c2ef6bd268fca0eda142f0efbba7cbebd7ad38f7bb01dd31c2ff68e/aiohttp-3.13.5-cp39-cp39-win_amd64.whl", hash = "sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67", size = 463076, upload-time = "2026-03-31T22:01:00.264Z" }, ] [[package]] @@ -470,11 +470,11 @@ wheels = [ [[package]] name = "idna" -version = "3.11" +version = "3.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +sdist = { url = "https://files.pythonhosted.org/packages/82/77/7b3966d0b9d1d31a36ddf1746926a11dface89a83409bf1483f0237aa758/idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc", size = 199245, upload-time = "2026-05-12T22:45:57.011Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, + { url = "https://files.pythonhosted.org/packages/d2/23/408243171aa9aaba178d3e2559159c24c1171a641aa83b67bdd3394ead8e/idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8", size = 72340, upload-time = "2026-05-12T22:45:55.733Z" }, ] [[package]] @@ -779,7 +779,7 @@ wheels = [ [[package]] name = "oz-agent-sdk" -version = "0.4.0" +version = "0.13.0" source = { editable = "." } dependencies = [ { name = "anyio" }, From 5cbfeb1a20115d98fffa454ab4f570a99f56cd59 Mon Sep 17 00:00:00 2001 From: stlc-bot Date: Thu, 11 Jun 2026 16:25:34 +0000 Subject: [PATCH 03/14] Build SDK Stainless-Generated-From: a80b3e8ef56463acbe762939a0ceaaf671b78a1b --- .github/workflows/ci.yml | 42 +- .github/workflows/promote_sdk.yml | 26 -- .github/workflows/publish-pypi.yml | 8 +- .github/workflows/release-doctor.yml | 2 + .stats.yml | 3 - CHANGELOG.md | 363 ------------------ bin/check-release-environment | 4 + release-please-config.json | 2 +- scripts/utils/upload-artifact.sh | 2 +- src/oz_agent_sdk/resources/agent/agent.py | 18 +- src/oz_agent_sdk/resources/agent/agent_.py | 25 +- src/oz_agent_sdk/resources/agent/runs.py | 4 +- .../types/agent/agent_create_params.py | 9 +- .../types/agent/agent_response.py | 12 +- .../types/agent/agent_update_params.py | 11 +- src/oz_agent_sdk/types/agent/run_item.py | 14 + .../types/agent/run_submit_followup_params.py | 4 +- src/oz_agent_sdk/types/agent_run_params.py | 3 +- src/warp_agent_sdk/lib/.keep | 4 - src/warp_api/lib/.keep | 4 - src/warp_sdk/lib/.keep | 4 - tests/api_resources/agent/test_agent_.py | 40 ++ tests/api_resources/agent/test_runs.py | 8 - uv.lock | 250 ++++++------ 24 files changed, 260 insertions(+), 602 deletions(-) delete mode 100644 .github/workflows/promote_sdk.yml delete mode 100644 CHANGELOG.md delete mode 100644 src/warp_agent_sdk/lib/.keep delete mode 100644 src/warp_api/lib/.keep delete mode 100644 src/warp_sdk/lib/.keep diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e2f90fb..d2f2ce9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: lint: timeout-minutes: 10 name: lint - runs-on: ${{ github.repository == 'stainless-sdks/warp-api-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ubuntu-latest if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -41,7 +41,7 @@ jobs: permissions: contents: read id-token: write - runs-on: ${{ github.repository == 'stainless-sdks/warp-api-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -55,41 +55,3 @@ jobs: - name: Run build run: uv build - - - name: Get GitHub OIDC Token - if: |- - github.repository == 'stainless-sdks/warp-api-python' && - !startsWith(github.ref, 'refs/heads/stl/') - id: github-oidc - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: core.setOutput('github_token', await core.getIDToken()); - - - name: Upload tarball - if: |- - github.repository == 'stainless-sdks/warp-api-python' && - !startsWith(github.ref, 'refs/heads/stl/') - env: - URL: https://pkg.stainless.com/s - AUTH: ${{ steps.github-oidc.outputs.github_token }} - SHA: ${{ github.sha }} - run: ./scripts/utils/upload-artifact.sh - - test: - timeout-minutes: 10 - name: test - runs-on: ${{ github.repository == 'stainless-sdks/warp-api-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - with: - version: '0.10.2' - - - name: Bootstrap - run: ./scripts/bootstrap - - - name: Run tests - run: ./scripts/test diff --git a/.github/workflows/promote_sdk.yml b/.github/workflows/promote_sdk.yml deleted file mode 100644 index d007379..0000000 --- a/.github/workflows/promote_sdk.yml +++ /dev/null @@ -1,26 +0,0 @@ -# Promote SDK updates from this staging repository to the corresponding -# production repository. - -name: Promote SDK - -on: - workflow_dispatch: - -jobs: - promote: - name: promote - runs-on: ubuntu-latest - permissions: - contents: read - - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - ref: ${{ github.event.repository.default_branch }} - fetch-depth: 0 - persist-credentials: false - - - name: Promote SDK to production - uses: warpdotdev/warp-github-actions/.github/actions/promote_sdk@main - with: - production_repo_token: ${{ secrets.STAINLESS_SDK_PROD_WRITE_TOKEN }} diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index bae8377..2026439 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -1,13 +1,9 @@ -# This workflow is triggered when a GitHub release is created. -# It can also be run manually to re-publish to PyPI in case it failed for some reason. -# You can run this workflow by navigating to https://www.github.com/warpdotdev/oz-sdk-python/actions/workflows/publish-pypi.yml +# workflow for re-running publishing to PyPI in case it fails for some reason +# you can run this workflow by navigating to https://www.github.com/warpdotdev/oz-sdk-python/actions/workflows/publish-pypi.yml name: Publish PyPI on: workflow_dispatch: - release: - types: [published] - jobs: publish: name: publish diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 2f3f96e..19a98a4 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -17,3 +17,5 @@ jobs: - name: Check release environment run: | bash ./bin/check-release-environment + env: + RELEASE_PLEASE_TOKEN: ${{ secrets.RELEASE_PLEASE_TOKEN }} diff --git a/.stats.yml b/.stats.yml index e679286..c125dfb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1 @@ configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-964f646a32c318735de7673531a12788aede1840f7ab4893f2efa31c83440837.yml -openapi_spec_hash: 30f07ff0bfb491efb11cd88fce79968a -config_hash: 236823a4936c76818117c16aa5c188df diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index e741eb1..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,363 +0,0 @@ -# Changelog - -## 0.13.0 (2026-05-21) - -Full Changelog: [v0.12.0...v0.13.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.12.0...v0.13.0) - -### Features - -* Add default harness selection for agents ([8cd06f6](https://github.com/warpdotdev/oz-sdk-python/commit/8cd06f6fcb48444e3861ff130d2fb4fa820e3aa7)) -* Add per-agent AWS Bedrock OIDC inference role (backend) ([e4aadec](https://github.com/warpdotdev/oz-sdk-python/commit/e4aadec916b2bea7e05e0e263b307449002e7f8b)) -* Add updated_at to agent API responses ([3188420](https://github.com/warpdotdev/oz-sdk-python/commit/318842095218a12c5b3ed1d945941e74ca5c9d54)) -* **agents:** add prompt property to agent identity data model ([520c835](https://github.com/warpdotdev/oz-sdk-python/commit/520c8350b5b7850242adc082fe83a7ae666e6da6)) -* **api:** api update ([b8306ad](https://github.com/warpdotdev/oz-sdk-python/commit/b8306ad8aff3c8e83f3c9549a8d78a1dfe22e7f5)) -* **api:** api update ([a66cdc2](https://github.com/warpdotdev/oz-sdk-python/commit/a66cdc2b99686872998efe8592b21bb14c6320cc)) -* **api:** api update ([da1ee9c](https://github.com/warpdotdev/oz-sdk-python/commit/da1ee9c25078cfbf6fb34e6e3afd09edcfe6b76b)) -* **api:** api update ([32f77e1](https://github.com/warpdotdev/oz-sdk-python/commit/32f77e19c7bd30dbeacb84ce95f5e487a7c9debf)) -* **api:** api update ([7ec4ab4](https://github.com/warpdotdev/oz-sdk-python/commit/7ec4ab432f4a3e6494d29d7db0b9bf3a08ba0885)) -* **api:** api update ([c05564a](https://github.com/warpdotdev/oz-sdk-python/commit/c05564aa69ba70685b6778859b0574f1d2d69a33)) -* **api:** api update ([0976362](https://github.com/warpdotdev/oz-sdk-python/commit/09763624c5e172aa28fa43ed18bc0e391c04331d)) -* **api:** api update ([96d640c](https://github.com/warpdotdev/oz-sdk-python/commit/96d640cd68290e1a915fca51a8629cf9dab4d81d)) -* **api:** api update ([2730eea](https://github.com/warpdotdev/oz-sdk-python/commit/2730eea19d91df998de5ef1b5da4989670a5889a)) -* **api:** api update ([af81ef3](https://github.com/warpdotdev/oz-sdk-python/commit/af81ef3a2d48f378209cf69a3074997cb02b1b6c)) -* **api:** api update ([99b2d31](https://github.com/warpdotdev/oz-sdk-python/commit/99b2d31ba1a4c2c3d79fc11c5eb8d611c55613b8)) -* Codex auth: API key support. ([cb84f0c](https://github.com/warpdotdev/oz-sdk-python/commit/cb84f0c6c9625d8c0657c728d5fadae065eb37c9)) -* **internal/types:** support eagerly validating pydantic iterators ([a588f0e](https://github.com/warpdotdev/oz-sdk-python/commit/a588f0e5ba27503659b5abf01d0ebc01f652950d)) -* **memory:** agent identity memory store attachments — API layer ([94b5348](https://github.com/warpdotdev/oz-sdk-python/commit/94b5348152c6b0bfb03b0d3887366c4a65e397fb)) -* **memory:** wire memory stores into run pipeline and add listing endpoint ([6bb74c2](https://github.com/warpdotdev/oz-sdk-python/commit/6bb74c2b695cd268fe8466fc6099f082370ba54e)) -* Partial support for multiple skills per run ([e39df48](https://github.com/warpdotdev/oz-sdk-python/commit/e39df4831329c75d13b7638a2edc146a0a2f57a1)) -* Resolve Bedrock region server-side and ship as AWS_REGION ([cef2591](https://github.com/warpdotdev/oz-sdk-python/commit/cef25915ca886a87aa5d567d1e3001ca746c8960)) -* Retrieve memories in third party harnesses ([7689e12](https://github.com/warpdotdev/oz-sdk-python/commit/7689e121d6f22efad3d81828721f8ed900b9cd28)) -* Support service account impersonation in GCP Workload Identity Federation config ([6df1722](https://github.com/warpdotdev/oz-sdk-python/commit/6df1722325b8c96d7655348e75bd82980e2bd055)) - - -### Bug Fixes - -* **client:** add missing f-string prefix in file type error message ([17a8e5b](https://github.com/warpdotdev/oz-sdk-python/commit/17a8e5bf17b882a440a067fee1569caf679f8b55)) - -## 0.12.0 (2026-05-07) - -Full Changelog: [v0.11.0...v0.12.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.11.0...v0.12.0) - -### Features - -* [APP-3106] Specs: Explicit QueryMode for cloud agent run creation ([1d4e049](https://github.com/warpdotdev/oz-sdk-python/commit/1d4e049e5c64fdfe1f8eff8dbf7bc8256ed98182)) -* [REMOTE-1481] [3/N] Add executor filter to run list API ([2dbc229](https://github.com/warpdotdev/oz-sdk-python/commit/2dbc22949c6c9475a31e74cba5eadecb018277f3)) -* [REMOTE-1538] Support base model on named agents ([7634c23](https://github.com/warpdotdev/oz-sdk-python/commit/7634c231906d3fb53c9576b39fac1fa60f694790)) -* Accept and persist executor on schedule and integration create/update APIs ([a8500aa](https://github.com/warpdotdev/oz-sdk-python/commit/a8500aa0b3e74221cd931b01d7e7569ad191d1f3)) -* Add API support for public access on oz session link ([df940e0](https://github.com/warpdotdev/oz-sdk-python/commit/df940e09b23d2cc3d314407a8826f722b9428dca)) -* Add Codex as a third-party Oz harness. ([898e18f](https://github.com/warpdotdev/oz-sdk-python/commit/898e18f8e26a2064d3bb3bdda83c08adeb91088d)) -* Add Gemini as a third-party Oz harness. ([0128722](https://github.com/warpdotdev/oz-sdk-python/commit/0128722383f87f6d5a73fd0ecafc4206a3013342)) -* Add parent_run_id filter to List runs endpoint ([33cf04c](https://github.com/warpdotdev/oz-sdk-python/commit/33cf04c0777d53059f8a3c73b925b468276aba2a)) -* Add system prompt to resolve-prompt for harnesses. ([2b7afab](https://github.com/warpdotdev/oz-sdk-python/commit/2b7afabf4a54764ab162ac32f4dbe7fe4274ba72)) -* Add trigger URL to task source. ([9662dbe](https://github.com/warpdotdev/oz-sdk-python/commit/9662dbe10cc5392271b3e56c35cb8ef95ec80eed)) -* Add worker_host to AgentListSource in OpenAPI spec ([ec0982c](https://github.com/warpdotdev/oz-sdk-python/commit/ec0982ce786b2380ab89aa7298b28998c6eade46)) -* **api:** api update ([88de4e2](https://github.com/warpdotdev/oz-sdk-python/commit/88de4e2765d70de416658f0ce0ef42585763efc9)) -* **api:** api update ([4a0d4fc](https://github.com/warpdotdev/oz-sdk-python/commit/4a0d4fc0711f3fe0d3168c3f5f7ec2176d5b0010)) -* **api:** api update ([654da59](https://github.com/warpdotdev/oz-sdk-python/commit/654da597a10a63048c5a34ca67c9d6684c72b688)) -* **api:** api update ([86d389c](https://github.com/warpdotdev/oz-sdk-python/commit/86d389c610fb2b89d7fcd17ebfd06610ef2b0b90)) -* **api:** api update ([15d68a1](https://github.com/warpdotdev/oz-sdk-python/commit/15d68a1db8178fd9cb5fae456ca6f341b60fd1e7)) -* **api:** api update ([54f5cdc](https://github.com/warpdotdev/oz-sdk-python/commit/54f5cdc819015611f7214b8ac6632df1cebf857d)) -* **api:** api update ([e290d3b](https://github.com/warpdotdev/oz-sdk-python/commit/e290d3b8cd2e8bd10a713e41992e282b704c624e)) -* **api:** api update ([35565ad](https://github.com/warpdotdev/oz-sdk-python/commit/35565ada13a8a16f9117b3ca0c12279d1708d184)) -* **api:** api update ([9cf2d03](https://github.com/warpdotdev/oz-sdk-python/commit/9cf2d0352242be5c7075fe971561cc36aaaf6e77)) -* **api:** api update ([ed871aa](https://github.com/warpdotdev/oz-sdk-python/commit/ed871aac657265138112d98be757a0de48796e02)) -* **api:** api update ([a44c455](https://github.com/warpdotdev/oz-sdk-python/commit/a44c455cb949e69b05f33f38571b40d9c0caed36)) -* **api:** api update ([e24ba64](https://github.com/warpdotdev/oz-sdk-python/commit/e24ba644c9d3624019f240fd43f51079adf7d8d4)) -* **api:** api update ([e5aea21](https://github.com/warpdotdev/oz-sdk-python/commit/e5aea2192017b1758d7b32d1e855015ce29e93ca)) -* **api:** api update ([f94b38b](https://github.com/warpdotdev/oz-sdk-python/commit/f94b38b2ffaf344a198e89ad7ace1d7b8e93c300)) -* **api:** api update ([7f419fa](https://github.com/warpdotdev/oz-sdk-python/commit/7f419faa01908e1b4a613ec2bdd708aed1a05871)) -* **api:** api update ([116f06e](https://github.com/warpdotdev/oz-sdk-python/commit/116f06e5c63e8d015e7dfea47fc22ede53ebb84e)) -* **api:** api update ([66c8521](https://github.com/warpdotdev/oz-sdk-python/commit/66c852194f355cedca2b34b944c398e796f064ab)) -* **api:** api update ([ebd2c55](https://github.com/warpdotdev/oz-sdk-python/commit/ebd2c5520128722d88285aea9dd0caf3242d9a31)) -* **api:** api update ([1ffc53b](https://github.com/warpdotdev/oz-sdk-python/commit/1ffc53b4d69eeb8060faac1903f1ba25f7a4c443)) -* **api:** api update ([cf28804](https://github.com/warpdotdev/oz-sdk-python/commit/cf288045d369ed927db45ac5e5ebd994ccebb547)) -* **api:** api update ([a6d82f1](https://github.com/warpdotdev/oz-sdk-python/commit/a6d82f1a71ad8e0ff5f10c43cc81938babc1444e)) -* **api:** api update ([b9872f2](https://github.com/warpdotdev/oz-sdk-python/commit/b9872f2642191ef6e1d4d5d3542a08f9e2784b9e)) -* **api:** api update ([0ef9c8f](https://github.com/warpdotdev/oz-sdk-python/commit/0ef9c8f483269d203a3edc7b5805f48f4263eb2f)) -* Apply service-account secrets at run creation ([db0e98c](https://github.com/warpdotdev/oz-sdk-python/commit/db0e98ca667b0cfe5b8ab182db5b1d4a19584113)) -* Extend service account API to support skills + secrets ([caf9c45](https://github.com/warpdotdev/oz-sdk-python/commit/caf9c4539ad1718ed194619ebf26425217265706)) -* implement server-side cloud-to-cloud handoff for agent follow-ups (REMOTE-1290) ([eb873a6](https://github.com/warpdotdev/oz-sdk-python/commit/eb873a6092aa1792ca6c23f5d27a7ee66c225ea0)) -* Include agent UID in scheduled agent API responses ([1714226](https://github.com/warpdotdev/oz-sdk-python/commit/1714226a85760699faacebd23cc1ea3a6bc7f0b9)) -* Inject auth secrets via ambient agent config. ([6032a0c](https://github.com/warpdotdev/oz-sdk-python/commit/6032a0ccfe2ce669ce1f815ad853b912d4ca575e)) -* Make conversation/session redirects public ([4c23bb6](https://github.com/warpdotdev/oz-sdk-python/commit/4c23bb6ebec32b5022a1731284d3e07b81a9f5ae)) -* Memory data model scaffolding. ([4ccbe03](https://github.com/warpdotdev/oz-sdk-python/commit/4ccbe0371e7bf02c454a14bc8bc2d412dcebf290)) -* support setting headers via env ([d3b4755](https://github.com/warpdotdev/oz-sdk-python/commit/d3b4755c7447d915a4e11be043b21b859f6c028d)) -* Surface platform credits in the public API ([d54b3d5](https://github.com/warpdotdev/oz-sdk-python/commit/d54b3d55760fa68853130d026dfdd88a7e226c80)) -* Update public API and graphql to support creating multiple service accounts and API keys ([8d537bc](https://github.com/warpdotdev/oz-sdk-python/commit/8d537bcbe75b344427bd04e5406ab066769f580a)) - - -### Bug Fixes - -* ensure file data are only sent as 1 parameter ([6720ea9](https://github.com/warpdotdev/oz-sdk-python/commit/6720ea9331a945cf2d030e20b8851a223697aab3)) -* use correct field name format for multipart file arrays ([f785ff2](https://github.com/warpdotdev/oz-sdk-python/commit/f785ff2bafbd319574974549a73c21643cdb5cc5)) - - -### Performance Improvements - -* **client:** optimize file structure copying in multipart requests ([b8e42cc](https://github.com/warpdotdev/oz-sdk-python/commit/b8e42cc08805eef08a3462088ba0e32cf79dac8c)) - - -### Chores - -* **internal:** more robust bootstrap script ([27c80e9](https://github.com/warpdotdev/oz-sdk-python/commit/27c80e953bc19de56ea730b0c2170aa8ffbc495a)) -* **internal:** reformat pyproject.toml ([fd17af1](https://github.com/warpdotdev/oz-sdk-python/commit/fd17af10c72ed943e4023a4e9e071ac7b8db08f7)) -* update SDK settings ([f2dd099](https://github.com/warpdotdev/oz-sdk-python/commit/f2dd099128bf4f98e304778556d55e80a4fd219c)) - -## 0.11.0 (2026-04-09) - -Full Changelog: [v0.10.1...v0.11.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.10.1...v0.11.0) - -### Features - -* [Artifacts] public API file artifact downloads ([1d2007e](https://github.com/warpdotdev/oz-sdk-python/commit/1d2007eaa692679fdcc56a6092ffdf9ad09de6ca)) -* Add harness enum to openAPI spec ([c8b44e5](https://github.com/warpdotdev/oz-sdk-python/commit/c8b44e532885d53f406babf8c0463f62d86a1fbe)) -* Add parent_run_id to retrieve/list runs API response ([c5752fb](https://github.com/warpdotdev/oz-sdk-python/commit/c5752fbbceffbc322cee5dd8b111aa0ce84ce615)) -* Add VMIdleTimeoutMinutes param to API ([31b5a63](https://github.com/warpdotdev/oz-sdk-python/commit/31b5a63204a2baca1a41f0b4124408d2d2b7e6a4)) -* Address Stainless diagnostics ([58d59e3](https://github.com/warpdotdev/oz-sdk-python/commit/58d59e3593d27ad4bb17e340c384d9709f650806)) -* **api:** api update ([9140132](https://github.com/warpdotdev/oz-sdk-python/commit/9140132ca22861c78365898e250a5c613af454a8)) -* **api:** api update ([204505c](https://github.com/warpdotdev/oz-sdk-python/commit/204505c1472d5af4b9463a975fd919c5fc4dbe78)) -* **api:** api update ([5e2d3ee](https://github.com/warpdotdev/oz-sdk-python/commit/5e2d3ee9400130c5a8dc2d51d1618ad292c051ab)) -* **api:** api update ([1238769](https://github.com/warpdotdev/oz-sdk-python/commit/12387694506b5d0d53e527db1dcdb2ca02ae2f71)) -* **api:** api update ([75b1c92](https://github.com/warpdotdev/oz-sdk-python/commit/75b1c92550babef5b0cf19689613f95131df08d7)) -* **api:** api update ([4b777eb](https://github.com/warpdotdev/oz-sdk-python/commit/4b777ebbe2483c2d882597bd0ab593128f5355d9)) -* **api:** api update ([9fe02aa](https://github.com/warpdotdev/oz-sdk-python/commit/9fe02aad21c71cbab837f7d335e5234e1974bb90)) -* **api:** api update ([7fc79ef](https://github.com/warpdotdev/oz-sdk-python/commit/7fc79efe0897451670cb44cf29c0f99b06ffe821)) -* **api:** manual updates ([ed9f4cf](https://github.com/warpdotdev/oz-sdk-python/commit/ed9f4cfa6a0db58dc3ca5564f83b09ef1a19e3a9)) -* **api:** manual updates ([e52643f](https://github.com/warpdotdev/oz-sdk-python/commit/e52643fcb1408ac9f8dd6a284b9cb818f3f468ac)) -* Create run for every local conversation and add filter ([aac84c5](https://github.com/warpdotdev/oz-sdk-python/commit/aac84c585eb3b0ed5262d683e544960a82eec2a2)) -* Define auth secrets and inject them into the environment. ([54c505b](https://github.com/warpdotdev/oz-sdk-python/commit/54c505b2d58246abab42cda52d79df3ddbfed083)) -* Endpoint to upload third-party harness block snapshots ([2f71989](https://github.com/warpdotdev/oz-sdk-python/commit/2f7198972cec56e72b802c7505fb445d10304bf4)) -* Fix the harness type in the openAPI spec ([71d7204](https://github.com/warpdotdev/oz-sdk-python/commit/71d72043f6cb8d8ae6af4c01936967059936c7b0)) -* ian/fix_conversation_id_nameing ([658c50b](https://github.com/warpdotdev/oz-sdk-python/commit/658c50b6b3937249034ad9e6993e598705d0c3c6)) -* **internal:** implement indices array format for query and form serialization ([c518876](https://github.com/warpdotdev/oz-sdk-python/commit/c518876f3da1129d3c351982ed4a06590fd15f2e)) -* Orchestrations V2: Public API endpoints ([5514980](https://github.com/warpdotdev/oz-sdk-python/commit/551498004c85dd4277069b0c059c17c7504bc18b)) -* Use correct branch for Stainless PRs ([d7b298d](https://github.com/warpdotdev/oz-sdk-python/commit/d7b298d99c5dcb5e02530329fef222de92f3e9d6)) - - -### Bug Fixes - -* **client:** preserve hardcoded query params when merging with user params ([5da3150](https://github.com/warpdotdev/oz-sdk-python/commit/5da315075e053b1a6cef709439f9972f6fd0f70f)) - -## 0.10.1 (2026-03-24) - -Full Changelog: [v0.10.0...v0.10.1](https://github.com/warpdotdev/oz-sdk-python/compare/v0.10.0...v0.10.1) - -### Chores - -* update SDK settings ([8afbeb4](https://github.com/warpdotdev/oz-sdk-python/commit/8afbeb4c91e704eac42294dbe84d1469d1743027)) -* update SDK settings ([c597727](https://github.com/warpdotdev/oz-sdk-python/commit/c59772779c50cabc63bb881c01b841e5d3c9544a)) -* update SDK settings ([628303f](https://github.com/warpdotdev/oz-sdk-python/commit/628303fee3ec94b583573b891e9ff136857a585a)) -* update SDK settings ([621aa2e](https://github.com/warpdotdev/oz-sdk-python/commit/621aa2ea925c4946c2dbd362f71859c46554038b)) - -## 0.10.0 (2026-03-24) - -Full Changelog: [v0.9.0...v0.10.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.9.0...v0.10.0) - -### Features - -* **api:** api update ([41658e2](https://github.com/warpdotdev/oz-sdk-python/commit/41658e206812a57e27f97c1f7e0be57bedcbd3c6)) -* **api:** error and error_code as types ([9766f85](https://github.com/warpdotdev/oz-sdk-python/commit/9766f85585ff3553f1f366476a3a6806f2534b22)) -* **api:** fix ScheduledAgentHistoryItem name ([ac75431](https://github.com/warpdotdev/oz-sdk-python/commit/ac754319e41b73d323cf9a36cbcf1c4dce2902bb)) -* **api:** fix schema version issues ([9c2f6a3](https://github.com/warpdotdev/oz-sdk-python/commit/9c2f6a32fa06812860efa1d76893dd8d2b60d176)) -* **api:** sorting ([0cc041e](https://github.com/warpdotdev/oz-sdk-python/commit/0cc041edf53d26c4f38c64faa7fd065d7a6760ab)) - - -### Bug Fixes - -* **deps:** bump minimum typing-extensions version ([4f3ec38](https://github.com/warpdotdev/oz-sdk-python/commit/4f3ec385748655ca8fde2457ffe402f8bf30db56)) -* **pydantic:** do not pass `by_alias` unless set ([45e0377](https://github.com/warpdotdev/oz-sdk-python/commit/45e0377a495aa67b0ee7d4415cbf13b526dbbf7e)) -* sanitize endpoint path params ([da2a124](https://github.com/warpdotdev/oz-sdk-python/commit/da2a124f15c2b69f67905cfe4b75b52d90ece562)) - - -### Chores - -* **ci:** skip lint on metadata-only changes ([c2c0d4a](https://github.com/warpdotdev/oz-sdk-python/commit/c2c0d4af8460e7d1d86fa8c14f2480323308b9a2)) -* **ci:** skip uploading artifacts on stainless-internal branches ([1ef523c](https://github.com/warpdotdev/oz-sdk-python/commit/1ef523caca4d137def551560de8c8a75c761d0f9)) -* **internal:** tweak CI branches ([21f9e2e](https://github.com/warpdotdev/oz-sdk-python/commit/21f9e2e8065a3202a149b3a2440c5adb7d084681)) -* **internal:** update gitignore ([e9e4aef](https://github.com/warpdotdev/oz-sdk-python/commit/e9e4aef20150ac3560f00edc2078979dacde8549)) -* update SDK settings ([b897579](https://github.com/warpdotdev/oz-sdk-python/commit/b89757977744858277d095a752392e2faff0bb71)) -* update SDK settings ([e4510a6](https://github.com/warpdotdev/oz-sdk-python/commit/e4510a6259d03bf4cd24b40df6243f6c879e6fb3)) - -## 0.9.0 (2026-03-03) - -Full Changelog: [v0.8.0...v0.9.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.8.0...v0.9.0) - -### Features - -* **api:** manual updates ([26fc085](https://github.com/warpdotdev/oz-sdk-python/commit/26fc0852ddd9352fe7564cba64f34203d940ac57)) -* **api:** manual updates ([1f89eca](https://github.com/warpdotdev/oz-sdk-python/commit/1f89eca19e244721d77837d5aafbf0e1de20aee7)) - -## 0.8.0 (2026-03-03) - -Full Changelog: [v0.7.0...v0.8.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.7.0...v0.8.0) - -### Features - -* **api:** manual updates ([1d27527](https://github.com/warpdotdev/oz-sdk-python/commit/1d275270bac34036ba2d2f9795792f2b71fdad3f)) - - -### Chores - -* **ci:** bump uv version ([646ee4e](https://github.com/warpdotdev/oz-sdk-python/commit/646ee4e0381123a3b24e63c4829e32c7ffc3160d)) -* **docs:** add missing descriptions ([4777a8f](https://github.com/warpdotdev/oz-sdk-python/commit/4777a8fd9d5e9644a694695190d1dc6d4c1c9941)) -* **internal:** make `test_proxy_environment_variables` more resilient to env ([3c14f7a](https://github.com/warpdotdev/oz-sdk-python/commit/3c14f7ae100fbb6df1a9f7109fd77057cf10a780)) - -## 0.7.0 (2026-02-23) - -Full Changelog: [v0.6.2...v0.7.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.6.2...v0.7.0) - -### Features - -* **api:** manual updates ([1b38e09](https://github.com/warpdotdev/oz-sdk-python/commit/1b38e0943935c83c0283523fc045eb2ff2f56109)) -* **api:** manual updates ([73b719a](https://github.com/warpdotdev/oz-sdk-python/commit/73b719a978f70ae36bd374535d80372dfaf1d47f)) - - -### Chores - -* **internal:** make `test_proxy_environment_variables` more resilient ([de1744e](https://github.com/warpdotdev/oz-sdk-python/commit/de1744eeddf1780ca9bae2690f0ed0b17406754f)) - -## 0.6.2 (2026-02-23) - -Full Changelog: [v0.6.1...v0.6.2](https://github.com/warpdotdev/oz-sdk-python/compare/v0.6.1...v0.6.2) - -### Chores - -* format all `api.md` files ([99ca557](https://github.com/warpdotdev/oz-sdk-python/commit/99ca5575a5159bc024bbf427d41a25347fe5b0f1)) -* **internal:** add request options to SSE classes ([f66a316](https://github.com/warpdotdev/oz-sdk-python/commit/f66a3167892c0c98bd77f141ef325b5c2f576f09)) -* **internal:** bump dependencies ([c487a61](https://github.com/warpdotdev/oz-sdk-python/commit/c487a61c88362ebc3b48785830d1e3b16bd7dcfe)) -* **internal:** fix lint error on Python 3.14 ([25d5626](https://github.com/warpdotdev/oz-sdk-python/commit/25d56264996ae48e38696524f244e99a32316cc3)) -* **internal:** remove mock server code ([e4b9075](https://github.com/warpdotdev/oz-sdk-python/commit/e4b90753f07d4f5da5a1075e893bb87424530cb5)) -* update mock server docs ([c253a23](https://github.com/warpdotdev/oz-sdk-python/commit/c253a238f5902a71fbd033f3e0bc0ec74406e9b9)) -* update SDK settings ([82ead07](https://github.com/warpdotdev/oz-sdk-python/commit/82ead07e4501a6e23e5db060074a5c180b0947c6)) - -## 0.6.1 (2026-02-08) - -Full Changelog: [v0.6.0...v0.6.1](https://github.com/warpdotdev/oz-sdk-python/compare/v0.6.0...v0.6.1) - -### Chores - -* update SDK settings ([c20dd4b](https://github.com/warpdotdev/oz-sdk-python/commit/c20dd4bda0c41e2bf167e1617521d9c66d6f98fd)) -* update SDK settings ([59aa425](https://github.com/warpdotdev/oz-sdk-python/commit/59aa4254f18291861ee7fb656d57566df41ad750)) -* update SDK settings ([ea483d5](https://github.com/warpdotdev/oz-sdk-python/commit/ea483d53c6242d60ece124e03510a9be6a94ffa2)) - -## 0.6.0 (2026-02-08) - -Full Changelog: [v0.5.0...v0.6.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.5.0...v0.6.0) - -### Features - -* **api:** manual updates ([75fe5e5](https://github.com/warpdotdev/oz-sdk-python/commit/75fe5e5c5ea9e044895c1bd7f1c5ab150214c8e7)) - -## 0.5.0 (2026-02-08) - -Full Changelog: [v0.4.0...v0.5.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.4.0...v0.5.0) - -### Features - -* **api:** modify openapi trigger ([db2d311](https://github.com/warpdotdev/oz-sdk-python/commit/db2d3116a353cc7a5b552e09769372264f6353b8)) - - -### Chores - -* update SDK settings ([f233ca0](https://github.com/warpdotdev/oz-sdk-python/commit/f233ca083a6cf8f49bb47f9fa348dcc3aa2b5f1c)) -* update SDK settings ([7857217](https://github.com/warpdotdev/oz-sdk-python/commit/78572179b9ad2c50849060db1d6d3981dd83297b)) -* update SDK settings ([181c928](https://github.com/warpdotdev/oz-sdk-python/commit/181c9281ec380c5aaa09de344584fe413b67728f)) - -## 0.4.0 (2026-02-06) - -Full Changelog: [v0.3.0...v0.4.0](https://github.com/warpdotdev/warp-sdk-python/compare/v0.3.0...v0.4.0) - -### ⚠ BREAKING CHANGES - -* **api:** catch up openapi, rename tasks -> runs - -### Features - -* **api:** add addnl filters to runs endpoint ([c8bf51d](https://github.com/warpdotdev/warp-sdk-python/commit/c8bf51d62e4141183a77a387f2658ad5ba0255f4)) -* **api:** add artifacts, worker_host, and new source types ([4aa1225](https://github.com/warpdotdev/warp-sdk-python/commit/4aa12253c3cd40bbd8460dfe6602fed5080554a4)) -* **api:** add computer_use_enabled param ([69cf9ca](https://github.com/warpdotdev/warp-sdk-python/commit/69cf9ca7a2b514997baa3377a9e4d96e5fc14b29)) -* **api:** add models for agent skill, user profile ([8105304](https://github.com/warpdotdev/warp-sdk-python/commit/8105304447af1bb4a28bf629cf116063621abfb5)) -* **api:** add schedules to runs ([df1b59a](https://github.com/warpdotdev/warp-sdk-python/commit/df1b59a976df5898fdd893f42173c0247b934b15)) -* **api:** add schedules, agent list, skill-spec ([1927318](https://github.com/warpdotdev/warp-sdk-python/commit/1927318b5b2a4115b3f1ec2be7db86f1e8e0d321)) -* **api:** catch up openapi, rename tasks -> runs ([fe8c5b3](https://github.com/warpdotdev/warp-sdk-python/commit/fe8c5b3f2da07a415ecd21d0f1ae5985e45f1a4d)) -* **api:** created at filter in list view ([71adb45](https://github.com/warpdotdev/warp-sdk-python/commit/71adb45481ca3248d892e62ff767b9ea011e7f21)) -* **api:** new run source types ([3237b0f](https://github.com/warpdotdev/warp-sdk-python/commit/3237b0fb12e6a28199f7ac86c8fc1fef6f96888e)) -* **api:** update artifacts ([578be41](https://github.com/warpdotdev/warp-sdk-python/commit/578be418b8f7f0e45f427bfc5c9d98f2970a31eb)) -* **client:** add custom JSON encoder for extended type support ([68f4b61](https://github.com/warpdotdev/warp-sdk-python/commit/68f4b61fd83b1f5576b72ad6ea3a28cd58e06a68)) -* **client:** add support for binary request streaming ([c64e6c4](https://github.com/warpdotdev/warp-sdk-python/commit/c64e6c44b6d02a63609d02f4976a7977dc3b0045)) - - -### Chores - -* **ci:** upgrade `actions/github-script` ([713ae7d](https://github.com/warpdotdev/warp-sdk-python/commit/713ae7d03ee5f04eeac42b9a213d96ccc91d06d7)) -* **internal:** update `actions/checkout` version ([fd0a90f](https://github.com/warpdotdev/warp-sdk-python/commit/fd0a90fae32b8a7e352217e3672e63b9b4dbc594)) - - -### Documentation - -* **dev:** Add WARP.md file ([7f1b835](https://github.com/warpdotdev/warp-sdk-python/commit/7f1b835240574dc517d424dca84251f86c4b1276)) - -## 0.3.0 (2026-01-05) - -Full Changelog: [v0.2.1...v0.3.0](https://github.com/warpdotdev/warp-sdk-python/compare/v0.2.1...v0.3.0) - -### Features - -* **api:** fix array query parameter formatting ([d1a1243](https://github.com/warpdotdev/warp-sdk-python/commit/d1a1243a0ab6b853b2340f8e7d3652bfe05ded20)) - -## 0.2.1 (2025-12-19) - -Full Changelog: [v0.2.0...v0.2.1](https://github.com/warpdotdev/warp-sdk-python/compare/v0.2.0...v0.2.1) - -### Bug Fixes - -* use async_to_httpx_files in patch method ([c02afdb](https://github.com/warpdotdev/warp-sdk-python/commit/c02afdbec958df84a3e1ec73e213e683c79b04e8)) - - -### Chores - -* **internal:** add `--fix` argument to lint script ([46a9b4b](https://github.com/warpdotdev/warp-sdk-python/commit/46a9b4bdceac62a8939f66b0227943d18db5393f)) - -## 0.2.0 (2025-12-17) - -Full Changelog: [v0.1.1...v0.2.0](https://github.com/warpdotdev/warp-sdk-python/compare/v0.1.1...v0.2.0) - -### Features - -* **api:** manual updates ([2fc23de](https://github.com/warpdotdev/warp-sdk-python/commit/2fc23de0e1d42443e691350804605243c5902026)) - - -### Chores - -* update SDK settings ([a94be20](https://github.com/warpdotdev/warp-sdk-python/commit/a94be20a45967c6ec5bd95dcc3ffcf457db84305)) - -## 0.1.1 (2025-12-17) - -Full Changelog: [v0.1.0...v0.1.1](https://github.com/warpdotdev/warp-sdk-python/compare/v0.1.0...v0.1.1) - -### Documentation - -* add environment and config usage documentation ([487b1cf](https://github.com/warpdotdev/warp-sdk-python/commit/487b1cfac5fcd89d4c91f88903ef8b601da8269d)) - -## 0.1.0 (2025-12-17) - -Full Changelog: [v0.0.1...v0.1.0](https://github.com/warpdotdev/warp-sdk-python/compare/v0.0.1...v0.1.0) - -### Features - -* **api:** manual updates ([4d4a408](https://github.com/warpdotdev/warp-sdk-python/commit/4d4a4082d453daeb3d388ac1a23cf951ada27a9e)) -* **api:** manual updates ([cd0ec74](https://github.com/warpdotdev/warp-sdk-python/commit/cd0ec747479cbb56159a361853787871c1c61395)) - - -### Chores - -* **internal:** add missing files argument to base client ([041d054](https://github.com/warpdotdev/warp-sdk-python/commit/041d0540f460ed7ecee3ed66a8db6ea9ae607360)) -* speedup initial import ([c6fa047](https://github.com/warpdotdev/warp-sdk-python/commit/c6fa04747ba3b056f9dff28e564e25b4e257ca5e)) -* update SDK settings ([217b866](https://github.com/warpdotdev/warp-sdk-python/commit/217b866ef03a583415f0fcdd65385ee76d53c664)) -* update SDK settings ([cc95759](https://github.com/warpdotdev/warp-sdk-python/commit/cc9575998cf34b016f70f8209043a02ad1677399)) - - -### Refactors - -* **internal:** switch from rye to uv ([d4cdfd0](https://github.com/warpdotdev/warp-sdk-python/commit/d4cdfd0384b63f1ce244cdbb4327043cff02f682)) diff --git a/bin/check-release-environment b/bin/check-release-environment index 1e951e9..7edad7c 100644 --- a/bin/check-release-environment +++ b/bin/check-release-environment @@ -2,6 +2,10 @@ errors=() +if [ -z "${RELEASE_PLEASE_TOKEN}" ]; then + errors+=("The RELEASE_PLEASE_TOKEN secret has not been set. Create a fine-grained GitHub PAT and add it as a repository secret.") +fi + lenErrors=${#errors[@]} if [[ lenErrors -gt 0 ]]; then diff --git a/release-please-config.json b/release-please-config.json index 37299b0..8187d51 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -2,7 +2,7 @@ "packages": { ".": {} }, - "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", "include-v-in-tag": true, "include-component-in-tag": false, "versioning": "prerelease", diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index 9f6eb1f..4ce1bc0 100755 --- a/scripts/utils/upload-artifact.sh +++ b/scripts/utils/upload-artifact.sh @@ -20,7 +20,7 @@ UPLOAD_RESPONSE=$(curl -v -X PUT \ if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then echo -e "\033[32mUploaded build to Stainless storage.\033[0m" - echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/warp-api-python/$SHA/$FILENAME'\033[0m" + echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/oz-sdk-python-staging/$SHA/$FILENAME'\033[0m" else echo -e "\033[31mFailed to upload artifact.\033[0m" exit 1 diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index af2411c..6910539 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -275,10 +275,10 @@ def run( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentRunResponse: - """Alias for POST /agent/run. + """Spawn a cloud agent with a prompt and optional configuration. - This is the preferred endpoint for creating new agent - runs. Behavior is identical to POST /agent/run. + The agent will be + queued for execution and assigned a unique run ID. Args: agent_identity_uid: Optional agent identity UID to use as the execution principal for the run. This @@ -302,7 +302,8 @@ def run( hierarchies. prompt: The prompt/instruction for the agent to execute. Required unless a skill is - specified via the skill field, config.skill_spec, or config.skills. + specified via the skill field, config.skill_spec, or config.skills. Handoff + requests may omit prompt when conversation_id is set. skill: Skill specification to use as the base prompt for the agent. Supported formats: @@ -566,10 +567,10 @@ async def run( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentRunResponse: - """Alias for POST /agent/run. + """Spawn a cloud agent with a prompt and optional configuration. - This is the preferred endpoint for creating new agent - runs. Behavior is identical to POST /agent/run. + The agent will be + queued for execution and assigned a unique run ID. Args: agent_identity_uid: Optional agent identity UID to use as the execution principal for the run. This @@ -593,7 +594,8 @@ async def run( hierarchies. prompt: The prompt/instruction for the agent to execute. Required unless a skill is - specified via the skill field, config.skill_spec, or config.skills. + specified via the skill field, config.skill_spec, or config.skills. Handoff + requests may omit prompt when conversation_id is set. skill: Skill specification to use as the base prompt for the agent. Supported formats: diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py index f79333c..65eb4d5 100644 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Iterable, Optional +from typing import Dict, Iterable, Optional import httpx @@ -19,6 +19,7 @@ from ...types.agent import agent_create_params, agent_update_params from ..._base_client import make_request_options from ...types.agent.agent_response import AgentResponse +from ...types.mcp_server_config_param import McpServerConfigParam from ...types.agent.list_agent_identities_response import ListAgentIdentitiesResponse __all__ = ["AgentResource", "AsyncAgentResource"] @@ -56,6 +57,7 @@ def create( environment_id: Optional[str] | Omit = omit, harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, inference_providers: agent_create_params.InferenceProviders | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, prompt: Optional[str] | Omit = omit, secrets: Iterable[agent_create_params.Secret] | Omit = omit, @@ -89,6 +91,9 @@ def create( inference_providers: Inference provider settings used for LLM calls. + mcp_servers: Optional map of MCP server configurations by name to attach to runs executed by + this agent. Run-level MCP config takes precedence over this agent-level default. + memory_stores: Optional list of memory stores to attach to the agent. Each store must be team-owned by the same team as the agent. Duplicate UIDs within a single request are rejected. @@ -125,6 +130,7 @@ def create( "environment_id": environment_id, "harness_auth_secrets": harness_auth_secrets, "inference_providers": inference_providers, + "mcp_servers": mcp_servers, "memory_stores": memory_stores, "prompt": prompt, "secrets": secrets, @@ -148,6 +154,7 @@ def update( environment_id: Optional[str] | Omit = omit, harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, name: str | Omit = omit, prompt: Optional[str] | Omit = omit, @@ -182,6 +189,10 @@ def update( inference_providers: Inference provider settings used for LLM calls. + mcp_servers: Replacement map of MCP server configurations by name. Omit to leave unchanged, + pass an empty object to clear, or pass a non-empty object to replace. Run-level + MCP config takes precedence over this agent-level default. + memory_stores: Replacement list of memory stores. Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array to replace. @@ -216,6 +227,7 @@ def update( "environment_id": environment_id, "harness_auth_secrets": harness_auth_secrets, "inference_providers": inference_providers, + "mcp_servers": mcp_servers, "memory_stores": memory_stores, "name": name, "prompt": prompt, @@ -357,6 +369,7 @@ async def create( environment_id: Optional[str] | Omit = omit, harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, inference_providers: agent_create_params.InferenceProviders | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, prompt: Optional[str] | Omit = omit, secrets: Iterable[agent_create_params.Secret] | Omit = omit, @@ -390,6 +403,9 @@ async def create( inference_providers: Inference provider settings used for LLM calls. + mcp_servers: Optional map of MCP server configurations by name to attach to runs executed by + this agent. Run-level MCP config takes precedence over this agent-level default. + memory_stores: Optional list of memory stores to attach to the agent. Each store must be team-owned by the same team as the agent. Duplicate UIDs within a single request are rejected. @@ -426,6 +442,7 @@ async def create( "environment_id": environment_id, "harness_auth_secrets": harness_auth_secrets, "inference_providers": inference_providers, + "mcp_servers": mcp_servers, "memory_stores": memory_stores, "prompt": prompt, "secrets": secrets, @@ -449,6 +466,7 @@ async def update( environment_id: Optional[str] | Omit = omit, harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, name: str | Omit = omit, prompt: Optional[str] | Omit = omit, @@ -483,6 +501,10 @@ async def update( inference_providers: Inference provider settings used for LLM calls. + mcp_servers: Replacement map of MCP server configurations by name. Omit to leave unchanged, + pass an empty object to clear, or pass a non-empty object to replace. Run-level + MCP config takes precedence over this agent-level default. + memory_stores: Replacement list of memory stores. Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array to replace. @@ -517,6 +539,7 @@ async def update( "environment_id": environment_id, "harness_auth_secrets": harness_auth_secrets, "inference_providers": inference_providers, + "mcp_servers": mcp_servers, "memory_stores": memory_stores, "name": name, "prompt": prompt, diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index c2d5075..fa745d3 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -301,7 +301,7 @@ def submit_followup( self, run_id: str, *, - message: str, + message: str | Omit = omit, mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -621,7 +621,7 @@ async def submit_followup( self, run_id: str, *, - message: str, + message: str | Omit = omit, mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py index 9de0a64..798e05d 100644 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -2,10 +2,11 @@ from __future__ import annotations -from typing import Iterable, Optional +from typing import Dict, Iterable, Optional from typing_extensions import Literal, Required, TypedDict from ..._types import SequenceNotStr +from ..mcp_server_config_param import McpServerConfigParam __all__ = [ "AgentCreateParams", @@ -45,6 +46,12 @@ class AgentCreateParams(TypedDict, total=False): inference_providers: InferenceProviders """Inference provider settings used for LLM calls.""" + mcp_servers: Dict[str, McpServerConfigParam] + """ + Optional map of MCP server configurations by name to attach to runs executed by + this agent. Run-level MCP config takes precedence over this agent-level default. + """ + memory_stores: Iterable[MemoryStore] """ Optional list of memory stores to attach to the agent. Each store must be diff --git a/src/oz_agent_sdk/types/agent/agent_response.py b/src/oz_agent_sdk/types/agent/agent_response.py index db0b1bf..37d13b9 100644 --- a/src/oz_agent_sdk/types/agent/agent_response.py +++ b/src/oz_agent_sdk/types/agent/agent_response.py @@ -1,10 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from datetime import datetime from typing_extensions import Literal from ..._models import BaseModel +from ..mcp_server_config import McpServerConfig __all__ = [ "AgentResponse", @@ -108,6 +109,9 @@ class AgentResponse(BaseModel): uid: str """Unique identifier for the agent""" + updated_at: datetime + """When the agent was last updated (RFC3339)""" + base_harness: Optional[str] = None """Default harness for runs executed by this agent. @@ -150,5 +154,11 @@ class AgentResponse(BaseModel): inference_providers: Optional[InferenceProviders] = None """Inference provider settings used for LLM calls.""" + mcp_servers: Optional[Dict[str, McpServerConfig]] = None + """ + MCP server configurations attached to this agent by default. Run-level MCP + config takes precedence over this agent-level default. + """ + prompt: Optional[str] = None """Optional base prompt for this agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_update_params.py b/src/oz_agent_sdk/types/agent/agent_update_params.py index fb1e36c..19082d4 100644 --- a/src/oz_agent_sdk/types/agent/agent_update_params.py +++ b/src/oz_agent_sdk/types/agent/agent_update_params.py @@ -2,10 +2,11 @@ from __future__ import annotations -from typing import Iterable, Optional +from typing import Dict, Iterable, Optional from typing_extensions import Literal, Required, TypedDict from ..._types import SequenceNotStr +from ..mcp_server_config_param import McpServerConfigParam __all__ = [ "AgentUpdateParams", @@ -51,6 +52,14 @@ class AgentUpdateParams(TypedDict, total=False): inference_providers: Optional[InferenceProviders] """Inference provider settings used for LLM calls.""" + mcp_servers: Dict[str, McpServerConfigParam] + """Replacement map of MCP server configurations by name. + + Omit to leave unchanged, pass an empty object to clear, or pass a non-empty + object to replace. Run-level MCP config takes precedence over this agent-level + default. + """ + memory_stores: Optional[Iterable[MemoryStore]] """Replacement list of memory stores. diff --git a/src/oz_agent_sdk/types/agent/run_item.py b/src/oz_agent_sdk/types/agent/run_item.py index 4293ce2..47231a1 100644 --- a/src/oz_agent_sdk/types/agent/run_item.py +++ b/src/oz_agent_sdk/types/agent/run_item.py @@ -173,6 +173,14 @@ class RunItem(BaseModel): executor: Optional[UserProfile] = None + is_run_type_cancellable: Optional[bool] = None + """Whether the run's type is eligible for cancellation via the API. + + State-independent: false for GitHub Action and local runs; true for all other + run types (including self-hosted). Clients should still gate the control on the + run's current state. + """ + is_sandbox_running: Optional[bool] = None """Whether the sandbox environment is currently running""" @@ -182,6 +190,12 @@ class RunItem(BaseModel): request_usage: Optional[RequestUsage] = None """Resource usage information for the run""" + run_time: Optional[str] = None + """Total runtime as an ISO 8601 duration (e.g. + + "PT2M30S"), computed server-side from run executions. + """ + schedule: Optional[Schedule] = None """ Information about the schedule that triggered this run (only present for diff --git a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py index 004341f..abc435b 100644 --- a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py +++ b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py @@ -2,13 +2,13 @@ from __future__ import annotations -from typing_extensions import Literal, Required, TypedDict +from typing_extensions import Literal, TypedDict __all__ = ["RunSubmitFollowupParams"] class RunSubmitFollowupParams(TypedDict, total=False): - message: Required[str] + message: str """The follow-up message to send to the run.""" mode: Literal["normal", "plan", "orchestrate"] diff --git a/src/oz_agent_sdk/types/agent_run_params.py b/src/oz_agent_sdk/types/agent_run_params.py index fa34de8..870c2de 100644 --- a/src/oz_agent_sdk/types/agent_run_params.py +++ b/src/oz_agent_sdk/types/agent_run_params.py @@ -55,7 +55,8 @@ class AgentRunParams(TypedDict, total=False): prompt: str """ The prompt/instruction for the agent to execute. Required unless a skill is - specified via the skill field, config.skill_spec, or config.skills. + specified via the skill field, config.skill_spec, or config.skills. Handoff + requests may omit prompt when conversation_id is set. """ skill: str diff --git a/src/warp_agent_sdk/lib/.keep b/src/warp_agent_sdk/lib/.keep deleted file mode 100644 index 5e2c99f..0000000 --- a/src/warp_agent_sdk/lib/.keep +++ /dev/null @@ -1,4 +0,0 @@ -File generated from our OpenAPI spec by Stainless. - -This directory can be used to store custom files to expand the SDK. -It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/src/warp_api/lib/.keep b/src/warp_api/lib/.keep deleted file mode 100644 index 5e2c99f..0000000 --- a/src/warp_api/lib/.keep +++ /dev/null @@ -1,4 +0,0 @@ -File generated from our OpenAPI spec by Stainless. - -This directory can be used to store custom files to expand the SDK. -It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/src/warp_sdk/lib/.keep b/src/warp_sdk/lib/.keep deleted file mode 100644 index 5e2c99f..0000000 --- a/src/warp_sdk/lib/.keep +++ /dev/null @@ -1,4 +0,0 @@ -File generated from our OpenAPI spec by Stainless. - -This directory can be used to store custom files to expand the SDK. -It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/tests/api_resources/agent/test_agent_.py b/tests/api_resources/agent/test_agent_.py index d6819c5..dbc1785 100644 --- a/tests/api_resources/agent/test_agent_.py +++ b/tests/api_resources/agent/test_agent_.py @@ -48,6 +48,16 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "role_arn": "role_arn", } }, + mcp_servers={ + "foo": { + "args": ["string"], + "command": "command", + "env": {"foo": "string"}, + "headers": {"foo": "string"}, + "url": "https://example.com", + "warp_id": "warp_id", + } + }, memory_stores=[ { "access": "read_write", @@ -115,6 +125,16 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "role_arn": "role_arn", } }, + mcp_servers={ + "foo": { + "args": ["string"], + "command": "command", + "env": {"foo": "string"}, + "headers": {"foo": "string"}, + "url": "https://example.com", + "warp_id": "warp_id", + } + }, memory_stores=[ { "access": "read_write", @@ -309,6 +329,16 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "role_arn": "role_arn", } }, + mcp_servers={ + "foo": { + "args": ["string"], + "command": "command", + "env": {"foo": "string"}, + "headers": {"foo": "string"}, + "url": "https://example.com", + "warp_id": "warp_id", + } + }, memory_stores=[ { "access": "read_write", @@ -376,6 +406,16 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "role_arn": "role_arn", } }, + mcp_servers={ + "foo": { + "args": ["string"], + "command": "command", + "env": {"foo": "string"}, + "headers": {"foo": "string"}, + "url": "https://example.com", + "warp_id": "warp_id", + } + }, memory_stores=[ { "access": "read_write", diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index 6af094f..54bb08c 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -209,7 +209,6 @@ def test_path_params_list_handoff_attachments(self, client: OzAPI) -> None: def test_method_submit_followup(self, client: OzAPI) -> None: run = client.agent.runs.submit_followup( run_id="runId", - message="message", ) assert_matches_type(object, run, path=["response"]) @@ -228,7 +227,6 @@ def test_method_submit_followup_with_all_params(self, client: OzAPI) -> None: def test_raw_response_submit_followup(self, client: OzAPI) -> None: response = client.agent.runs.with_raw_response.submit_followup( run_id="runId", - message="message", ) assert response.is_closed is True @@ -241,7 +239,6 @@ def test_raw_response_submit_followup(self, client: OzAPI) -> None: def test_streaming_response_submit_followup(self, client: OzAPI) -> None: with client.agent.runs.with_streaming_response.submit_followup( run_id="runId", - message="message", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -257,7 +254,6 @@ def test_path_params_submit_followup(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.agent.runs.with_raw_response.submit_followup( run_id="", - message="message", ) @@ -453,7 +449,6 @@ async def test_path_params_list_handoff_attachments(self, async_client: AsyncOzA async def test_method_submit_followup(self, async_client: AsyncOzAPI) -> None: run = await async_client.agent.runs.submit_followup( run_id="runId", - message="message", ) assert_matches_type(object, run, path=["response"]) @@ -472,7 +467,6 @@ async def test_method_submit_followup_with_all_params(self, async_client: AsyncO async def test_raw_response_submit_followup(self, async_client: AsyncOzAPI) -> None: response = await async_client.agent.runs.with_raw_response.submit_followup( run_id="runId", - message="message", ) assert response.is_closed is True @@ -485,7 +479,6 @@ async def test_raw_response_submit_followup(self, async_client: AsyncOzAPI) -> N async def test_streaming_response_submit_followup(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.runs.with_streaming_response.submit_followup( run_id="runId", - message="message", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -501,5 +494,4 @@ async def test_path_params_submit_followup(self, async_client: AsyncOzAPI) -> No with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.agent.runs.with_raw_response.submit_followup( run_id="", - message="message", ) diff --git a/uv.lock b/uv.lock index 0c65e6f..816e22a 100644 --- a/uv.lock +++ b/uv.lock @@ -26,7 +26,7 @@ wheels = [ [[package]] name = "aiohttp" -version = "3.13.5" +version = "3.13.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohappyeyeballs" }, @@ -38,127 +38,127 @@ dependencies = [ { name = "propcache" }, { name = "yarl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/77/9a/152096d4808df8e4268befa55fba462f440f14beab85e8ad9bf990516918/aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1", size = 7858271, upload-time = "2026-03-31T22:01:03.343Z" } +sdist = { url = "https://files.pythonhosted.org/packages/50/42/32cf8e7704ceb4481406eb87161349abb46a57fee3f008ba9cb610968646/aiohttp-3.13.3.tar.gz", hash = "sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88", size = 7844556, upload-time = "2026-01-03T17:33:05.204Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/85/cebc47ee74d8b408749073a1a46c6fcba13d170dc8af7e61996c6c9394ac/aiohttp-3.13.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b", size = 750547, upload-time = "2026-03-31T21:56:30.024Z" }, - { url = "https://files.pythonhosted.org/packages/05/98/afd308e35b9d3d8c9ec54c0918f1d722c86dc17ddfec272fcdbcce5a3124/aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5", size = 503535, upload-time = "2026-03-31T21:56:31.935Z" }, - { url = "https://files.pythonhosted.org/packages/6f/4d/926c183e06b09d5270a309eb50fbde7b09782bfd305dec1e800f329834fb/aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670", size = 497830, upload-time = "2026-03-31T21:56:33.654Z" }, - { url = "https://files.pythonhosted.org/packages/e4/d6/f47d1c690f115a5c2a5e8938cce4a232a5be9aac5c5fb2647efcbbbda333/aiohttp-3.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274", size = 1682474, upload-time = "2026-03-31T21:56:35.513Z" }, - { url = "https://files.pythonhosted.org/packages/01/44/056fd37b1bb52eac760303e5196acc74d9d546631b035704ae5927f7b4ac/aiohttp-3.13.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a", size = 1655259, upload-time = "2026-03-31T21:56:37.843Z" }, - { url = "https://files.pythonhosted.org/packages/91/9f/78eb1a20c1c28ae02f6a3c0f4d7b0dcc66abce5290cadd53d78ce3084175/aiohttp-3.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d", size = 1736204, upload-time = "2026-03-31T21:56:39.822Z" }, - { url = "https://files.pythonhosted.org/packages/de/6c/d20d7de23f0b52b8c1d9e2033b2db1ac4dacbb470bb74c56de0f5f86bb4f/aiohttp-3.13.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796", size = 1826198, upload-time = "2026-03-31T21:56:41.378Z" }, - { url = "https://files.pythonhosted.org/packages/2f/86/a6f3ff1fd795f49545a7c74b2c92f62729135d73e7e4055bf74da5a26c82/aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95", size = 1681329, upload-time = "2026-03-31T21:56:43.374Z" }, - { url = "https://files.pythonhosted.org/packages/fb/68/84cd3dab6b7b4f3e6fe9459a961acb142aaab846417f6e8905110d7027e5/aiohttp-3.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5", size = 1560023, upload-time = "2026-03-31T21:56:45.031Z" }, - { url = "https://files.pythonhosted.org/packages/41/2c/db61b64b0249e30f954a65ab4cb4970ced57544b1de2e3c98ee5dc24165f/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a", size = 1652372, upload-time = "2026-03-31T21:56:47.075Z" }, - { url = "https://files.pythonhosted.org/packages/25/6f/e96988a6c982d047810c772e28c43c64c300c943b0ed5c1c0c4ce1e1027c/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73", size = 1662031, upload-time = "2026-03-31T21:56:48.835Z" }, - { url = "https://files.pythonhosted.org/packages/b7/26/a56feace81f3d347b4052403a9d03754a0ab23f7940780dada0849a38c92/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297", size = 1708118, upload-time = "2026-03-31T21:56:50.833Z" }, - { url = "https://files.pythonhosted.org/packages/78/6e/b6173a8ff03d01d5e1a694bc06764b5dad1df2d4ed8f0ceec12bb3277936/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074", size = 1548667, upload-time = "2026-03-31T21:56:52.81Z" }, - { url = "https://files.pythonhosted.org/packages/16/13/13296ffe2c132d888b3fe2c195c8b9c0c24c89c3fa5cc2c44464dc23b22e/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e", size = 1724490, upload-time = "2026-03-31T21:56:54.541Z" }, - { url = "https://files.pythonhosted.org/packages/7a/b4/1f1c287f4a79782ef36e5a6e62954c85343bc30470d862d30bd5f26c9fa2/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7", size = 1667109, upload-time = "2026-03-31T21:56:56.21Z" }, - { url = "https://files.pythonhosted.org/packages/ef/42/8461a2aaf60a8f4ea4549a4056be36b904b0eb03d97ca9a8a2604681a500/aiohttp-3.13.5-cp310-cp310-win32.whl", hash = "sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9", size = 439478, upload-time = "2026-03-31T21:56:58.292Z" }, - { url = "https://files.pythonhosted.org/packages/e5/71/06956304cb5ee439dfe8d86e1b2e70088bd88ed1ced1f42fb29e5d855f0e/aiohttp-3.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76", size = 462047, upload-time = "2026-03-31T21:57:00.257Z" }, - { url = "https://files.pythonhosted.org/packages/d6/f5/a20c4ac64aeaef1679e25c9983573618ff765d7aa829fa2b84ae7573169e/aiohttp-3.13.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6", size = 757513, upload-time = "2026-03-31T21:57:02.146Z" }, - { url = "https://files.pythonhosted.org/packages/75/0a/39fa6c6b179b53fcb3e4b3d2b6d6cad0180854eda17060c7218540102bef/aiohttp-3.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d", size = 506748, upload-time = "2026-03-31T21:57:04.275Z" }, - { url = "https://files.pythonhosted.org/packages/87/ec/e38ce072e724fd7add6243613f8d1810da084f54175353d25ccf9f9c7e5a/aiohttp-3.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c", size = 501673, upload-time = "2026-03-31T21:57:06.208Z" }, - { url = "https://files.pythonhosted.org/packages/ba/ba/3bc7525d7e2beaa11b309a70d48b0d3cfc3c2089ec6a7d0820d59c657053/aiohttp-3.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb", size = 1763757, upload-time = "2026-03-31T21:57:07.882Z" }, - { url = "https://files.pythonhosted.org/packages/5e/ab/e87744cf18f1bd78263aba24924d4953b41086bd3a31d22452378e9028a0/aiohttp-3.13.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6", size = 1720152, upload-time = "2026-03-31T21:57:09.946Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f3/ed17a6f2d742af17b50bae2d152315ed1b164b07a5fd5cc1754d99e4dfa5/aiohttp-3.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13", size = 1818010, upload-time = "2026-03-31T21:57:12.157Z" }, - { url = "https://files.pythonhosted.org/packages/53/06/ecbc63dc937192e2a5cb46df4d3edb21deb8225535818802f210a6ea5816/aiohttp-3.13.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174", size = 1907251, upload-time = "2026-03-31T21:57:14.023Z" }, - { url = "https://files.pythonhosted.org/packages/7e/a5/0521aa32c1ddf3aa1e71dcc466be0b7db2771907a13f18cddaa45967d97b/aiohttp-3.13.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc", size = 1759969, upload-time = "2026-03-31T21:57:16.146Z" }, - { url = "https://files.pythonhosted.org/packages/f6/78/a38f8c9105199dd3b9706745865a8a59d0041b6be0ca0cc4b2ccf1bab374/aiohttp-3.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6", size = 1616871, upload-time = "2026-03-31T21:57:17.856Z" }, - { url = "https://files.pythonhosted.org/packages/6f/41/27392a61ead8ab38072105c71aa44ff891e71653fe53d576a7067da2b4e8/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49", size = 1739844, upload-time = "2026-03-31T21:57:19.679Z" }, - { url = "https://files.pythonhosted.org/packages/6e/55/5564e7ae26d94f3214250009a0b1c65a0c6af4bf88924ccb6fdab901de28/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8", size = 1731969, upload-time = "2026-03-31T21:57:22.006Z" }, - { url = "https://files.pythonhosted.org/packages/6d/c5/705a3929149865fc941bcbdd1047b238e4a72bcb215a9b16b9d7a2e8d992/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d", size = 1795193, upload-time = "2026-03-31T21:57:24.256Z" }, - { url = "https://files.pythonhosted.org/packages/a6/19/edabed62f718d02cff7231ca0db4ef1c72504235bc467f7b67adb1679f48/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c", size = 1606477, upload-time = "2026-03-31T21:57:26.364Z" }, - { url = "https://files.pythonhosted.org/packages/de/fc/76f80ef008675637d88d0b21584596dc27410a990b0918cb1e5776545b5b/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac", size = 1813198, upload-time = "2026-03-31T21:57:28.316Z" }, - { url = "https://files.pythonhosted.org/packages/e5/67/5b3ac26b80adb20ea541c487f73730dc8fa107d632c998f25bbbab98fcda/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3", size = 1752321, upload-time = "2026-03-31T21:57:30.549Z" }, - { url = "https://files.pythonhosted.org/packages/88/06/e4a2e49255ea23fa4feeb5ab092d90240d927c15e47b5b5c48dff5a9ce29/aiohttp-3.13.5-cp311-cp311-win32.whl", hash = "sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06", size = 439069, upload-time = "2026-03-31T21:57:32.388Z" }, - { url = "https://files.pythonhosted.org/packages/c0/43/8c7163a596dab4f8be12c190cf467a1e07e4734cf90eebb39f7f5d53fc6a/aiohttp-3.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8", size = 462859, upload-time = "2026-03-31T21:57:34.455Z" }, - { url = "https://files.pythonhosted.org/packages/be/6f/353954c29e7dcce7cf00280a02c75f30e133c00793c7a2ed3776d7b2f426/aiohttp-3.13.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9", size = 748876, upload-time = "2026-03-31T21:57:36.319Z" }, - { url = "https://files.pythonhosted.org/packages/f5/1b/428a7c64687b3b2e9cd293186695affc0e1e54a445d0361743b231f11066/aiohttp-3.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416", size = 499557, upload-time = "2026-03-31T21:57:38.236Z" }, - { url = "https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2", size = 500258, upload-time = "2026-03-31T21:57:39.923Z" }, - { url = "https://files.pythonhosted.org/packages/67/84/c9ecc5828cb0b3695856c07c0a6817a99d51e2473400f705275a2b3d9239/aiohttp-3.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4", size = 1749199, upload-time = "2026-03-31T21:57:41.938Z" }, - { url = "https://files.pythonhosted.org/packages/f0/d3/3c6d610e66b495657622edb6ae7c7fd31b2e9086b4ec50b47897ad6042a9/aiohttp-3.13.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9", size = 1721013, upload-time = "2026-03-31T21:57:43.904Z" }, - { url = "https://files.pythonhosted.org/packages/49/a0/24409c12217456df0bae7babe3b014e460b0b38a8e60753d6cb339f6556d/aiohttp-3.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5", size = 1781501, upload-time = "2026-03-31T21:57:46.285Z" }, - { url = "https://files.pythonhosted.org/packages/98/9d/b65ec649adc5bccc008b0957a9a9c691070aeac4e41cea18559fef49958b/aiohttp-3.13.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e", size = 1878981, upload-time = "2026-03-31T21:57:48.734Z" }, - { url = "https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1", size = 1767934, upload-time = "2026-03-31T21:57:51.171Z" }, - { url = "https://files.pythonhosted.org/packages/31/04/d3f8211f273356f158e3464e9e45484d3fb8c4ce5eb2f6fe9405c3273983/aiohttp-3.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286", size = 1566671, upload-time = "2026-03-31T21:57:53.326Z" }, - { url = "https://files.pythonhosted.org/packages/41/db/073e4ebe00b78e2dfcacff734291651729a62953b48933d765dc513bf798/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9", size = 1705219, upload-time = "2026-03-31T21:57:55.385Z" }, - { url = "https://files.pythonhosted.org/packages/48/45/7dfba71a2f9fd97b15c95c06819de7eb38113d2cdb6319669195a7d64270/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88", size = 1743049, upload-time = "2026-03-31T21:57:57.341Z" }, - { url = "https://files.pythonhosted.org/packages/18/71/901db0061e0f717d226386a7f471bb59b19566f2cae5f0d93874b017271f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3", size = 1749557, upload-time = "2026-03-31T21:57:59.626Z" }, - { url = "https://files.pythonhosted.org/packages/08/d5/41eebd16066e59cd43728fe74bce953d7402f2b4ddfdfef2c0e9f17ca274/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b", size = 1558931, upload-time = "2026-03-31T21:58:01.972Z" }, - { url = "https://files.pythonhosted.org/packages/30/e6/4a799798bf05740e66c3a1161079bda7a3dd8e22ca392481d7a7f9af82a6/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe", size = 1774125, upload-time = "2026-03-31T21:58:04.007Z" }, - { url = "https://files.pythonhosted.org/packages/84/63/7749337c90f92bc2cb18f9560d67aa6258c7060d1397d21529b8004fcf6f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14", size = 1732427, upload-time = "2026-03-31T21:58:06.337Z" }, - { url = "https://files.pythonhosted.org/packages/98/de/cf2f44ff98d307e72fb97d5f5bbae3bfcb442f0ea9790c0bf5c5c2331404/aiohttp-3.13.5-cp312-cp312-win32.whl", hash = "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3", size = 433534, upload-time = "2026-03-31T21:58:08.712Z" }, - { url = "https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1", size = 460446, upload-time = "2026-03-31T21:58:10.945Z" }, - { url = "https://files.pythonhosted.org/packages/78/e9/d76bf503005709e390122d34e15256b88f7008e246c4bdbe915cd4f1adce/aiohttp-3.13.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61", size = 742930, upload-time = "2026-03-31T21:58:13.155Z" }, - { url = "https://files.pythonhosted.org/packages/57/00/4b7b70223deaebd9bb85984d01a764b0d7bd6526fcdc73cca83bcbe7243e/aiohttp-3.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832", size = 496927, upload-time = "2026-03-31T21:58:15.073Z" }, - { url = "https://files.pythonhosted.org/packages/9c/f5/0fb20fb49f8efdcdce6cd8127604ad2c503e754a8f139f5e02b01626523f/aiohttp-3.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9", size = 497141, upload-time = "2026-03-31T21:58:17.009Z" }, - { url = "https://files.pythonhosted.org/packages/3b/86/b7c870053e36a94e8951b803cb5b909bfbc9b90ca941527f5fcafbf6b0fa/aiohttp-3.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090", size = 1732476, upload-time = "2026-03-31T21:58:18.925Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e5/4e161f84f98d80c03a238671b4136e6530453d65262867d989bbe78244d0/aiohttp-3.13.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b", size = 1706507, upload-time = "2026-03-31T21:58:21.094Z" }, - { url = "https://files.pythonhosted.org/packages/d4/56/ea11a9f01518bd5a2a2fcee869d248c4b8a0cfa0bb13401574fa31adf4d4/aiohttp-3.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a", size = 1773465, upload-time = "2026-03-31T21:58:23.159Z" }, - { url = "https://files.pythonhosted.org/packages/eb/40/333ca27fb74b0383f17c90570c748f7582501507307350a79d9f9f3c6eb1/aiohttp-3.13.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8", size = 1873523, upload-time = "2026-03-31T21:58:25.59Z" }, - { url = "https://files.pythonhosted.org/packages/f0/d2/e2f77eef1acb7111405433c707dc735e63f67a56e176e72e9e7a2cd3f493/aiohttp-3.13.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665", size = 1754113, upload-time = "2026-03-31T21:58:27.624Z" }, - { url = "https://files.pythonhosted.org/packages/fb/56/3f653d7f53c89669301ec9e42c95233e2a0c0a6dd051269e6e678db4fdb0/aiohttp-3.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540", size = 1562351, upload-time = "2026-03-31T21:58:29.918Z" }, - { url = "https://files.pythonhosted.org/packages/ec/a6/9b3e91eb8ae791cce4ee736da02211c85c6f835f1bdfac0594a8a3b7018c/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb", size = 1693205, upload-time = "2026-03-31T21:58:32.214Z" }, - { url = "https://files.pythonhosted.org/packages/98/fc/bfb437a99a2fcebd6b6eaec609571954de2ed424f01c352f4b5504371dd3/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46", size = 1730618, upload-time = "2026-03-31T21:58:34.728Z" }, - { url = "https://files.pythonhosted.org/packages/e4/b6/c8534862126191a034f68153194c389addc285a0f1347d85096d349bbc15/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8", size = 1745185, upload-time = "2026-03-31T21:58:36.909Z" }, - { url = "https://files.pythonhosted.org/packages/0b/93/4ca8ee2ef5236e2707e0fd5fecb10ce214aee1ff4ab307af9c558bda3b37/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d", size = 1557311, upload-time = "2026-03-31T21:58:39.38Z" }, - { url = "https://files.pythonhosted.org/packages/57/ae/76177b15f18c5f5d094f19901d284025db28eccc5ae374d1d254181d33f4/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6", size = 1773147, upload-time = "2026-03-31T21:58:41.476Z" }, - { url = "https://files.pythonhosted.org/packages/01/a4/62f05a0a98d88af59d93b7fcac564e5f18f513cb7471696ac286db970d6a/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c", size = 1730356, upload-time = "2026-03-31T21:58:44.049Z" }, - { url = "https://files.pythonhosted.org/packages/e4/85/fc8601f59dfa8c9523808281f2da571f8b4699685f9809a228adcc90838d/aiohttp-3.13.5-cp313-cp313-win32.whl", hash = "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc", size = 432637, upload-time = "2026-03-31T21:58:46.167Z" }, - { url = "https://files.pythonhosted.org/packages/c0/1b/ac685a8882896acf0f6b31d689e3792199cfe7aba37969fa91da63a7fa27/aiohttp-3.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83", size = 458896, upload-time = "2026-03-31T21:58:48.119Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ce/46572759afc859e867a5bc8ec3487315869013f59281ce61764f76d879de/aiohttp-3.13.5-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c", size = 745721, upload-time = "2026-03-31T21:58:50.229Z" }, - { url = "https://files.pythonhosted.org/packages/13/fe/8a2efd7626dbe6049b2ef8ace18ffda8a4dfcbe1bcff3ac30c0c7575c20b/aiohttp-3.13.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be", size = 497663, upload-time = "2026-03-31T21:58:52.232Z" }, - { url = "https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25", size = 499094, upload-time = "2026-03-31T21:58:54.566Z" }, - { url = "https://files.pythonhosted.org/packages/0a/33/a8362cb15cf16a3af7e86ed11962d5cd7d59b449202dc576cdc731310bde/aiohttp-3.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56", size = 1726701, upload-time = "2026-03-31T21:58:56.864Z" }, - { url = "https://files.pythonhosted.org/packages/45/0c/c091ac5c3a17114bd76cbf85d674650969ddf93387876cf67f754204bd77/aiohttp-3.13.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2", size = 1683360, upload-time = "2026-03-31T21:58:59.072Z" }, - { url = "https://files.pythonhosted.org/packages/23/73/bcee1c2b79bc275e964d1446c55c54441a461938e70267c86afaae6fba27/aiohttp-3.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a", size = 1773023, upload-time = "2026-03-31T21:59:01.776Z" }, - { url = "https://files.pythonhosted.org/packages/c7/ef/720e639df03004fee2d869f771799d8c23046dec47d5b81e396c7cda583a/aiohttp-3.13.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be", size = 1853795, upload-time = "2026-03-31T21:59:04.568Z" }, - { url = "https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b", size = 1730405, upload-time = "2026-03-31T21:59:07.221Z" }, - { url = "https://files.pythonhosted.org/packages/ce/75/ee1fd286ca7dc599d824b5651dad7b3be7ff8d9a7e7b3fe9820d9180f7db/aiohttp-3.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94", size = 1558082, upload-time = "2026-03-31T21:59:09.484Z" }, - { url = "https://files.pythonhosted.org/packages/c3/20/1e9e6650dfc436340116b7aa89ff8cb2bbdf0abc11dfaceaad8f74273a10/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d", size = 1692346, upload-time = "2026-03-31T21:59:12.068Z" }, - { url = "https://files.pythonhosted.org/packages/d8/40/8ebc6658d48ea630ac7903912fe0dd4e262f0e16825aa4c833c56c9f1f56/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7", size = 1698891, upload-time = "2026-03-31T21:59:14.552Z" }, - { url = "https://files.pythonhosted.org/packages/d8/78/ea0ae5ec8ba7a5c10bdd6e318f1ba5e76fcde17db8275188772afc7917a4/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772", size = 1742113, upload-time = "2026-03-31T21:59:17.068Z" }, - { url = "https://files.pythonhosted.org/packages/8a/66/9d308ed71e3f2491be1acb8769d96c6f0c47d92099f3bc9119cada27b357/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5", size = 1553088, upload-time = "2026-03-31T21:59:19.541Z" }, - { url = "https://files.pythonhosted.org/packages/da/a6/6cc25ed8dfc6e00c90f5c6d126a98e2cf28957ad06fa1036bd34b6f24a2c/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1", size = 1757976, upload-time = "2026-03-31T21:59:22.311Z" }, - { url = "https://files.pythonhosted.org/packages/c1/2b/cce5b0ffe0de99c83e5e36d8f828e4161e415660a9f3e58339d07cce3006/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b", size = 1712444, upload-time = "2026-03-31T21:59:24.635Z" }, - { url = "https://files.pythonhosted.org/packages/6c/cf/9e1795b4160c58d29421eafd1a69c6ce351e2f7c8d3c6b7e4ca44aea1a5b/aiohttp-3.13.5-cp314-cp314-win32.whl", hash = "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3", size = 438128, upload-time = "2026-03-31T21:59:27.291Z" }, - { url = "https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162", size = 464029, upload-time = "2026-03-31T21:59:29.429Z" }, - { url = "https://files.pythonhosted.org/packages/79/11/c27d9332ee20d68dd164dc12a6ecdef2e2e35ecc97ed6cf0d2442844624b/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a", size = 778758, upload-time = "2026-03-31T21:59:31.547Z" }, - { url = "https://files.pythonhosted.org/packages/04/fb/377aead2e0a3ba5f09b7624f702a964bdf4f08b5b6728a9799830c80041e/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254", size = 512883, upload-time = "2026-03-31T21:59:34.098Z" }, - { url = "https://files.pythonhosted.org/packages/bb/a6/aa109a33671f7a5d3bd78b46da9d852797c5e665bfda7d6b373f56bff2ec/aiohttp-3.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36", size = 516668, upload-time = "2026-03-31T21:59:36.497Z" }, - { url = "https://files.pythonhosted.org/packages/79/b3/ca078f9f2fa9563c36fb8ef89053ea2bb146d6f792c5104574d49d8acb63/aiohttp-3.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f", size = 1883461, upload-time = "2026-03-31T21:59:38.723Z" }, - { url = "https://files.pythonhosted.org/packages/b7/e3/a7ad633ca1ca497b852233a3cce6906a56c3225fb6d9217b5e5e60b7419d/aiohttp-3.13.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800", size = 1747661, upload-time = "2026-03-31T21:59:41.187Z" }, - { url = "https://files.pythonhosted.org/packages/33/b9/cd6fe579bed34a906d3d783fe60f2fa297ef55b27bb4538438ee49d4dc41/aiohttp-3.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf", size = 1863800, upload-time = "2026-03-31T21:59:43.84Z" }, - { url = "https://files.pythonhosted.org/packages/c0/3f/2c1e2f5144cefa889c8afd5cf431994c32f3b29da9961698ff4e3811b79a/aiohttp-3.13.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b", size = 1958382, upload-time = "2026-03-31T21:59:46.187Z" }, - { url = "https://files.pythonhosted.org/packages/66/1d/f31ec3f1013723b3babe3609e7f119c2c2fb6ef33da90061a705ef3e1bc8/aiohttp-3.13.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a", size = 1803724, upload-time = "2026-03-31T21:59:48.656Z" }, - { url = "https://files.pythonhosted.org/packages/0e/b4/57712dfc6f1542f067daa81eb61da282fab3e6f1966fca25db06c4fc62d5/aiohttp-3.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8", size = 1640027, upload-time = "2026-03-31T21:59:51.284Z" }, - { url = "https://files.pythonhosted.org/packages/25/3c/734c878fb43ec083d8e31bf029daae1beafeae582d1b35da234739e82ee7/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be", size = 1806644, upload-time = "2026-03-31T21:59:53.753Z" }, - { url = "https://files.pythonhosted.org/packages/20/a5/f671e5cbec1c21d044ff3078223f949748f3a7f86b14e34a365d74a5d21f/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b", size = 1791630, upload-time = "2026-03-31T21:59:56.239Z" }, - { url = "https://files.pythonhosted.org/packages/0b/63/fb8d0ad63a0b8a99be97deac8c04dacf0785721c158bdf23d679a87aa99e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6", size = 1809403, upload-time = "2026-03-31T21:59:59.103Z" }, - { url = "https://files.pythonhosted.org/packages/59/0c/bfed7f30662fcf12206481c2aac57dedee43fe1c49275e85b3a1e1742294/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037", size = 1634924, upload-time = "2026-03-31T22:00:02.116Z" }, - { url = "https://files.pythonhosted.org/packages/17/d6/fd518d668a09fd5a3319ae5e984d4d80b9a4b3df4e21c52f02251ef5a32e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500", size = 1836119, upload-time = "2026-03-31T22:00:04.756Z" }, - { url = "https://files.pythonhosted.org/packages/78/b7/15fb7a9d52e112a25b621c67b69c167805cb1f2ab8f1708a5c490d1b52fe/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9", size = 1772072, upload-time = "2026-03-31T22:00:07.494Z" }, - { url = "https://files.pythonhosted.org/packages/7e/df/57ba7f0c4a553fc2bd8b6321df236870ec6fd64a2a473a8a13d4f733214e/aiohttp-3.13.5-cp314-cp314t-win32.whl", hash = "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8", size = 471819, upload-time = "2026-03-31T22:00:10.277Z" }, - { url = "https://files.pythonhosted.org/packages/62/29/2f8418269e46454a26171bfdd6a055d74febf32234e474930f2f60a17145/aiohttp-3.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9", size = 505441, upload-time = "2026-03-31T22:00:12.791Z" }, - { url = "https://files.pythonhosted.org/packages/e2/a5/630bc484695d4a1342bbae85fb8689bf979106525684fc88f05b397324ad/aiohttp-3.13.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf", size = 752872, upload-time = "2026-03-31T22:00:15.553Z" }, - { url = "https://files.pythonhosted.org/packages/cd/b8/6a19dda37fda94a9ebefb3c1ae0ff419ac7fbf4fb40750e992829fc13614/aiohttp-3.13.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1", size = 504582, upload-time = "2026-03-31T22:00:18.191Z" }, - { url = "https://files.pythonhosted.org/packages/d5/34/8413eafee3421ade2d6ce9e7c0da1213e1d7f0049be09dcdc342b03a39ba/aiohttp-3.13.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10", size = 499094, upload-time = "2026-03-31T22:00:21.118Z" }, - { url = "https://files.pythonhosted.org/packages/da/cf/c6f97006093d1e8ca40fbab843ff49ec7725ab668f0714dd1cb702c62cbd/aiohttp-3.13.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f", size = 1669505, upload-time = "2026-03-31T22:00:24.01Z" }, - { url = "https://files.pythonhosted.org/packages/c2/27/3b2288e66dcec8b04771b2bee3909f70e4072bea995cde5ab7e775e73ddc/aiohttp-3.13.5-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b", size = 1648928, upload-time = "2026-03-31T22:00:27.001Z" }, - { url = "https://files.pythonhosted.org/packages/3a/7f/605d766887594a88dcc27a19663499c7c5e13e7aa87f129b763765a2ee63/aiohttp-3.13.5-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643", size = 1731800, upload-time = "2026-03-31T22:00:29.603Z" }, - { url = "https://files.pythonhosted.org/packages/71/94/5a878e728e30699d22b118f1a6ad576ab6fff9eb2c6fc8a7faa9376a1c3e/aiohttp-3.13.5-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031", size = 1824247, upload-time = "2026-03-31T22:00:32.139Z" }, - { url = "https://files.pythonhosted.org/packages/37/99/84b448291e9996bb83bf4fad3a71a9786d542f19c50a3ff0531bfaba6fac/aiohttp-3.13.5-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258", size = 1670742, upload-time = "2026-03-31T22:00:34.788Z" }, - { url = "https://files.pythonhosted.org/packages/14/a8/d8d5d1ab6d29a4a3bdb9db31f161e338bfdf6638f6574ea8380f1d4a243c/aiohttp-3.13.5-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a", size = 1562474, upload-time = "2026-03-31T22:00:37.623Z" }, - { url = "https://files.pythonhosted.org/packages/92/e8/bd889697916f10b65524422c61b4eeaf919eb35a170290cccb680cbe4eb4/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88", size = 1642235, upload-time = "2026-03-31T22:00:40.541Z" }, - { url = "https://files.pythonhosted.org/packages/60/42/3f1928107131f1413a5972ace14ddcd5364968e9bd7b3ad71272defafc9c/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0", size = 1655397, upload-time = "2026-03-31T22:00:43.167Z" }, - { url = "https://files.pythonhosted.org/packages/b2/79/c4bbcf4cac3a4715a326e49720ccdc3a4b5e14a367c5029eae7727d06029/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f", size = 1703509, upload-time = "2026-03-31T22:00:45.908Z" }, - { url = "https://files.pythonhosted.org/packages/d1/e6/32d245876f211a7308a7d5437707f9296b1f9837a2888a407ed04e61321c/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8", size = 1550098, upload-time = "2026-03-31T22:00:49.48Z" }, - { url = "https://files.pythonhosted.org/packages/db/62/ab0f1304def56ce2356e6fbb9f0b024d6544010351430070f48f53b89e0a/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f", size = 1724326, upload-time = "2026-03-31T22:00:52.165Z" }, - { url = "https://files.pythonhosted.org/packages/c4/9a/aab4469689024046220ea438aa020ea2ae04cd1dd71aea3057e094f8c357/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b", size = 1658824, upload-time = "2026-03-31T22:00:55.122Z" }, - { url = "https://files.pythonhosted.org/packages/b0/98/bcc35d4db687acabf06d41f561a99fa88bca145292513388c858d99b72c5/aiohttp-3.13.5-cp39-cp39-win32.whl", hash = "sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83", size = 440302, upload-time = "2026-03-31T22:00:57.673Z" }, - { url = "https://files.pythonhosted.org/packages/25/61/b0203c2ef6bd268fca0eda142f0efbba7cbebd7ad38f7bb01dd31c2ff68e/aiohttp-3.13.5-cp39-cp39-win_amd64.whl", hash = "sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67", size = 463076, upload-time = "2026-03-31T22:01:00.264Z" }, + { url = "https://files.pythonhosted.org/packages/36/d6/5aec9313ee6ea9c7cde8b891b69f4ff4001416867104580670a31daeba5b/aiohttp-3.13.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7", size = 738950, upload-time = "2026-01-03T17:29:13.002Z" }, + { url = "https://files.pythonhosted.org/packages/68/03/8fa90a7e6d11ff20a18837a8e2b5dd23db01aabc475aa9271c8ad33299f5/aiohttp-3.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821", size = 496099, upload-time = "2026-01-03T17:29:15.268Z" }, + { url = "https://files.pythonhosted.org/packages/d2/23/b81f744d402510a8366b74eb420fc0cc1170d0c43daca12d10814df85f10/aiohttp-3.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845", size = 491072, upload-time = "2026-01-03T17:29:16.922Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e1/56d1d1c0dd334cd203dd97706ce004c1aa24b34a813b0b8daf3383039706/aiohttp-3.13.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af", size = 1671588, upload-time = "2026-01-03T17:29:18.539Z" }, + { url = "https://files.pythonhosted.org/packages/5f/34/8d7f962604f4bc2b4e39eb1220dac7d4e4cba91fb9ba0474b4ecd67db165/aiohttp-3.13.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940", size = 1640334, upload-time = "2026-01-03T17:29:21.028Z" }, + { url = "https://files.pythonhosted.org/packages/94/1d/fcccf2c668d87337ddeef9881537baee13c58d8f01f12ba8a24215f2b804/aiohttp-3.13.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160", size = 1722656, upload-time = "2026-01-03T17:29:22.531Z" }, + { url = "https://files.pythonhosted.org/packages/aa/98/c6f3b081c4c606bc1e5f2ec102e87d6411c73a9ef3616fea6f2d5c98c062/aiohttp-3.13.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7", size = 1817625, upload-time = "2026-01-03T17:29:24.276Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c0/cfcc3d2e11b477f86e1af2863f3858c8850d751ce8dc39c4058a072c9e54/aiohttp-3.13.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455", size = 1672604, upload-time = "2026-01-03T17:29:26.099Z" }, + { url = "https://files.pythonhosted.org/packages/1e/77/6b4ffcbcac4c6a5d041343a756f34a6dd26174ae07f977a64fe028dda5b0/aiohttp-3.13.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279", size = 1554370, upload-time = "2026-01-03T17:29:28.121Z" }, + { url = "https://files.pythonhosted.org/packages/f2/f0/e3ddfa93f17d689dbe014ba048f18e0c9f9b456033b70e94349a2e9048be/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e", size = 1642023, upload-time = "2026-01-03T17:29:30.002Z" }, + { url = "https://files.pythonhosted.org/packages/eb/45/c14019c9ec60a8e243d06d601b33dcc4fd92379424bde3021725859d7f99/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d", size = 1649680, upload-time = "2026-01-03T17:29:31.782Z" }, + { url = "https://files.pythonhosted.org/packages/9c/fd/09c9451dae5aa5c5ed756df95ff9ef549d45d4be663bafd1e4954fd836f0/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808", size = 1692407, upload-time = "2026-01-03T17:29:33.392Z" }, + { url = "https://files.pythonhosted.org/packages/a6/81/938bc2ec33c10efd6637ccb3d22f9f3160d08e8f3aa2587a2c2d5ab578eb/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40", size = 1543047, upload-time = "2026-01-03T17:29:34.855Z" }, + { url = "https://files.pythonhosted.org/packages/f7/23/80488ee21c8d567c83045e412e1d9b7077d27171591a4eb7822586e8c06a/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29", size = 1715264, upload-time = "2026-01-03T17:29:36.389Z" }, + { url = "https://files.pythonhosted.org/packages/e2/83/259a8da6683182768200b368120ab3deff5370bed93880fb9a3a86299f34/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11", size = 1657275, upload-time = "2026-01-03T17:29:38.162Z" }, + { url = "https://files.pythonhosted.org/packages/3f/4f/2c41f800a0b560785c10fb316216ac058c105f9be50bdc6a285de88db625/aiohttp-3.13.3-cp310-cp310-win32.whl", hash = "sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd", size = 434053, upload-time = "2026-01-03T17:29:40.074Z" }, + { url = "https://files.pythonhosted.org/packages/80/df/29cd63c7ecfdb65ccc12f7d808cac4fa2a19544660c06c61a4a48462de0c/aiohttp-3.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c", size = 456687, upload-time = "2026-01-03T17:29:41.819Z" }, + { url = "https://files.pythonhosted.org/packages/f1/4c/a164164834f03924d9a29dc3acd9e7ee58f95857e0b467f6d04298594ebb/aiohttp-3.13.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b", size = 746051, upload-time = "2026-01-03T17:29:43.287Z" }, + { url = "https://files.pythonhosted.org/packages/82/71/d5c31390d18d4f58115037c432b7e0348c60f6f53b727cad33172144a112/aiohttp-3.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64", size = 499234, upload-time = "2026-01-03T17:29:44.822Z" }, + { url = "https://files.pythonhosted.org/packages/0e/c9/741f8ac91e14b1d2e7100690425a5b2b919a87a5075406582991fb7de920/aiohttp-3.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea", size = 494979, upload-time = "2026-01-03T17:29:46.405Z" }, + { url = "https://files.pythonhosted.org/packages/75/b5/31d4d2e802dfd59f74ed47eba48869c1c21552c586d5e81a9d0d5c2ad640/aiohttp-3.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a", size = 1748297, upload-time = "2026-01-03T17:29:48.083Z" }, + { url = "https://files.pythonhosted.org/packages/1a/3e/eefad0ad42959f226bb79664826883f2687d602a9ae2941a18e0484a74d3/aiohttp-3.13.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540", size = 1707172, upload-time = "2026-01-03T17:29:49.648Z" }, + { url = "https://files.pythonhosted.org/packages/c5/3a/54a64299fac2891c346cdcf2aa6803f994a2e4beeaf2e5a09dcc54acc842/aiohttp-3.13.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b", size = 1805405, upload-time = "2026-01-03T17:29:51.244Z" }, + { url = "https://files.pythonhosted.org/packages/6c/70/ddc1b7169cf64075e864f64595a14b147a895a868394a48f6a8031979038/aiohttp-3.13.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3", size = 1899449, upload-time = "2026-01-03T17:29:53.938Z" }, + { url = "https://files.pythonhosted.org/packages/a1/7e/6815aab7d3a56610891c76ef79095677b8b5be6646aaf00f69b221765021/aiohttp-3.13.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1", size = 1748444, upload-time = "2026-01-03T17:29:55.484Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f2/073b145c4100da5511f457dc0f7558e99b2987cf72600d42b559db856fbc/aiohttp-3.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3", size = 1606038, upload-time = "2026-01-03T17:29:57.179Z" }, + { url = "https://files.pythonhosted.org/packages/0a/c1/778d011920cae03ae01424ec202c513dc69243cf2db303965615b81deeea/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440", size = 1724156, upload-time = "2026-01-03T17:29:58.914Z" }, + { url = "https://files.pythonhosted.org/packages/0e/cb/3419eabf4ec1e9ec6f242c32b689248365a1cf621891f6f0386632525494/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7", size = 1722340, upload-time = "2026-01-03T17:30:01.962Z" }, + { url = "https://files.pythonhosted.org/packages/7a/e5/76cf77bdbc435bf233c1f114edad39ed4177ccbfab7c329482b179cff4f4/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c", size = 1783041, upload-time = "2026-01-03T17:30:03.609Z" }, + { url = "https://files.pythonhosted.org/packages/9d/d4/dd1ca234c794fd29c057ce8c0566b8ef7fd6a51069de5f06fa84b9a1971c/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51", size = 1596024, upload-time = "2026-01-03T17:30:05.132Z" }, + { url = "https://files.pythonhosted.org/packages/55/58/4345b5f26661a6180afa686c473620c30a66afdf120ed3dd545bbc809e85/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4", size = 1804590, upload-time = "2026-01-03T17:30:07.135Z" }, + { url = "https://files.pythonhosted.org/packages/7b/06/05950619af6c2df7e0a431d889ba2813c9f0129cec76f663e547a5ad56f2/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29", size = 1740355, upload-time = "2026-01-03T17:30:09.083Z" }, + { url = "https://files.pythonhosted.org/packages/3e/80/958f16de79ba0422d7c1e284b2abd0c84bc03394fbe631d0a39ffa10e1eb/aiohttp-3.13.3-cp311-cp311-win32.whl", hash = "sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239", size = 433701, upload-time = "2026-01-03T17:30:10.869Z" }, + { url = "https://files.pythonhosted.org/packages/dc/f2/27cdf04c9851712d6c1b99df6821a6623c3c9e55956d4b1e318c337b5a48/aiohttp-3.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f", size = 457678, upload-time = "2026-01-03T17:30:12.719Z" }, + { url = "https://files.pythonhosted.org/packages/a0/be/4fc11f202955a69e0db803a12a062b8379c970c7c84f4882b6da17337cc1/aiohttp-3.13.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c", size = 739732, upload-time = "2026-01-03T17:30:14.23Z" }, + { url = "https://files.pythonhosted.org/packages/97/2c/621d5b851f94fa0bb7430d6089b3aa970a9d9b75196bc93bb624b0db237a/aiohttp-3.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168", size = 494293, upload-time = "2026-01-03T17:30:15.96Z" }, + { url = "https://files.pythonhosted.org/packages/5d/43/4be01406b78e1be8320bb8316dc9c42dbab553d281c40364e0f862d5661c/aiohttp-3.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d", size = 493533, upload-time = "2026-01-03T17:30:17.431Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a8/5a35dc56a06a2c90d4742cbf35294396907027f80eea696637945a106f25/aiohttp-3.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29", size = 1737839, upload-time = "2026-01-03T17:30:19.422Z" }, + { url = "https://files.pythonhosted.org/packages/bf/62/4b9eeb331da56530bf2e198a297e5303e1c1ebdceeb00fe9b568a65c5a0c/aiohttp-3.13.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3", size = 1703932, upload-time = "2026-01-03T17:30:21.756Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f6/af16887b5d419e6a367095994c0b1332d154f647e7dc2bd50e61876e8e3d/aiohttp-3.13.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d", size = 1771906, upload-time = "2026-01-03T17:30:23.932Z" }, + { url = "https://files.pythonhosted.org/packages/ce/83/397c634b1bcc24292fa1e0c7822800f9f6569e32934bdeef09dae7992dfb/aiohttp-3.13.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463", size = 1871020, upload-time = "2026-01-03T17:30:26Z" }, + { url = "https://files.pythonhosted.org/packages/86/f6/a62cbbf13f0ac80a70f71b1672feba90fdb21fd7abd8dbf25c0105fb6fa3/aiohttp-3.13.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc", size = 1755181, upload-time = "2026-01-03T17:30:27.554Z" }, + { url = "https://files.pythonhosted.org/packages/0a/87/20a35ad487efdd3fba93d5843efdfaa62d2f1479eaafa7453398a44faf13/aiohttp-3.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf", size = 1561794, upload-time = "2026-01-03T17:30:29.254Z" }, + { url = "https://files.pythonhosted.org/packages/de/95/8fd69a66682012f6716e1bc09ef8a1a2a91922c5725cb904689f112309c4/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033", size = 1697900, upload-time = "2026-01-03T17:30:31.033Z" }, + { url = "https://files.pythonhosted.org/packages/e5/66/7b94b3b5ba70e955ff597672dad1691333080e37f50280178967aff68657/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f", size = 1728239, upload-time = "2026-01-03T17:30:32.703Z" }, + { url = "https://files.pythonhosted.org/packages/47/71/6f72f77f9f7d74719692ab65a2a0252584bf8d5f301e2ecb4c0da734530a/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679", size = 1740527, upload-time = "2026-01-03T17:30:34.695Z" }, + { url = "https://files.pythonhosted.org/packages/fa/b4/75ec16cbbd5c01bdaf4a05b19e103e78d7ce1ef7c80867eb0ace42ff4488/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423", size = 1554489, upload-time = "2026-01-03T17:30:36.864Z" }, + { url = "https://files.pythonhosted.org/packages/52/8f/bc518c0eea29f8406dcf7ed1f96c9b48e3bc3995a96159b3fc11f9e08321/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce", size = 1767852, upload-time = "2026-01-03T17:30:39.433Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f2/a07a75173124f31f11ea6f863dc44e6f09afe2bca45dd4e64979490deab1/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a", size = 1722379, upload-time = "2026-01-03T17:30:41.081Z" }, + { url = "https://files.pythonhosted.org/packages/3c/4a/1a3fee7c21350cac78e5c5cef711bac1b94feca07399f3d406972e2d8fcd/aiohttp-3.13.3-cp312-cp312-win32.whl", hash = "sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046", size = 428253, upload-time = "2026-01-03T17:30:42.644Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b7/76175c7cb4eb73d91ad63c34e29fc4f77c9386bba4a65b53ba8e05ee3c39/aiohttp-3.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57", size = 455407, upload-time = "2026-01-03T17:30:44.195Z" }, + { url = "https://files.pythonhosted.org/packages/97/8a/12ca489246ca1faaf5432844adbfce7ff2cc4997733e0af120869345643a/aiohttp-3.13.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c", size = 734190, upload-time = "2026-01-03T17:30:45.832Z" }, + { url = "https://files.pythonhosted.org/packages/32/08/de43984c74ed1fca5c014808963cc83cb00d7bb06af228f132d33862ca76/aiohttp-3.13.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9", size = 491783, upload-time = "2026-01-03T17:30:47.466Z" }, + { url = "https://files.pythonhosted.org/packages/17/f8/8dd2cf6112a5a76f81f81a5130c57ca829d101ad583ce57f889179accdda/aiohttp-3.13.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3", size = 490704, upload-time = "2026-01-03T17:30:49.373Z" }, + { url = "https://files.pythonhosted.org/packages/6d/40/a46b03ca03936f832bc7eaa47cfbb1ad012ba1be4790122ee4f4f8cba074/aiohttp-3.13.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf", size = 1720652, upload-time = "2026-01-03T17:30:50.974Z" }, + { url = "https://files.pythonhosted.org/packages/f7/7e/917fe18e3607af92657e4285498f500dca797ff8c918bd7d90b05abf6c2a/aiohttp-3.13.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6", size = 1692014, upload-time = "2026-01-03T17:30:52.729Z" }, + { url = "https://files.pythonhosted.org/packages/71/b6/cefa4cbc00d315d68973b671cf105b21a609c12b82d52e5d0c9ae61d2a09/aiohttp-3.13.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d", size = 1759777, upload-time = "2026-01-03T17:30:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e3/e06ee07b45e59e6d81498b591fc589629be1553abb2a82ce33efe2a7b068/aiohttp-3.13.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261", size = 1861276, upload-time = "2026-01-03T17:30:56.512Z" }, + { url = "https://files.pythonhosted.org/packages/7c/24/75d274228acf35ceeb2850b8ce04de9dd7355ff7a0b49d607ee60c29c518/aiohttp-3.13.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0", size = 1743131, upload-time = "2026-01-03T17:30:58.256Z" }, + { url = "https://files.pythonhosted.org/packages/04/98/3d21dde21889b17ca2eea54fdcff21b27b93f45b7bb94ca029c31ab59dc3/aiohttp-3.13.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730", size = 1556863, upload-time = "2026-01-03T17:31:00.445Z" }, + { url = "https://files.pythonhosted.org/packages/9e/84/da0c3ab1192eaf64782b03971ab4055b475d0db07b17eff925e8c93b3aa5/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91", size = 1682793, upload-time = "2026-01-03T17:31:03.024Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0f/5802ada182f575afa02cbd0ec5180d7e13a402afb7c2c03a9aa5e5d49060/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3", size = 1716676, upload-time = "2026-01-03T17:31:04.842Z" }, + { url = "https://files.pythonhosted.org/packages/3f/8c/714d53bd8b5a4560667f7bbbb06b20c2382f9c7847d198370ec6526af39c/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4", size = 1733217, upload-time = "2026-01-03T17:31:06.868Z" }, + { url = "https://files.pythonhosted.org/packages/7d/79/e2176f46d2e963facea939f5be2d26368ce543622be6f00a12844d3c991f/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998", size = 1552303, upload-time = "2026-01-03T17:31:08.958Z" }, + { url = "https://files.pythonhosted.org/packages/ab/6a/28ed4dea1759916090587d1fe57087b03e6c784a642b85ef48217b0277ae/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0", size = 1763673, upload-time = "2026-01-03T17:31:10.676Z" }, + { url = "https://files.pythonhosted.org/packages/e8/35/4a3daeb8b9fab49240d21c04d50732313295e4bd813a465d840236dd0ce1/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591", size = 1721120, upload-time = "2026-01-03T17:31:12.575Z" }, + { url = "https://files.pythonhosted.org/packages/bc/9f/d643bb3c5fb99547323e635e251c609fbbc660d983144cfebec529e09264/aiohttp-3.13.3-cp313-cp313-win32.whl", hash = "sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf", size = 427383, upload-time = "2026-01-03T17:31:14.382Z" }, + { url = "https://files.pythonhosted.org/packages/4e/f1/ab0395f8a79933577cdd996dd2f9aa6014af9535f65dddcf88204682fe62/aiohttp-3.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e", size = 453899, upload-time = "2026-01-03T17:31:15.958Z" }, + { url = "https://files.pythonhosted.org/packages/99/36/5b6514a9f5d66f4e2597e40dea2e3db271e023eb7a5d22defe96ba560996/aiohttp-3.13.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808", size = 737238, upload-time = "2026-01-03T17:31:17.909Z" }, + { url = "https://files.pythonhosted.org/packages/f7/49/459327f0d5bcd8c6c9ca69e60fdeebc3622861e696490d8674a6d0cb90a6/aiohttp-3.13.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415", size = 492292, upload-time = "2026-01-03T17:31:19.919Z" }, + { url = "https://files.pythonhosted.org/packages/e8/0b/b97660c5fd05d3495b4eb27f2d0ef18dc1dc4eff7511a9bf371397ff0264/aiohttp-3.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f", size = 493021, upload-time = "2026-01-03T17:31:21.636Z" }, + { url = "https://files.pythonhosted.org/packages/54/d4/438efabdf74e30aeceb890c3290bbaa449780583b1270b00661126b8aae4/aiohttp-3.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6", size = 1717263, upload-time = "2026-01-03T17:31:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/71/f2/7bddc7fd612367d1459c5bcf598a9e8f7092d6580d98de0e057eb42697ad/aiohttp-3.13.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687", size = 1669107, upload-time = "2026-01-03T17:31:25.334Z" }, + { url = "https://files.pythonhosted.org/packages/00/5a/1aeaecca40e22560f97610a329e0e5efef5e0b5afdf9f857f0d93839ab2e/aiohttp-3.13.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26", size = 1760196, upload-time = "2026-01-03T17:31:27.394Z" }, + { url = "https://files.pythonhosted.org/packages/f8/f8/0ff6992bea7bd560fc510ea1c815f87eedd745fe035589c71ce05612a19a/aiohttp-3.13.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a", size = 1843591, upload-time = "2026-01-03T17:31:29.238Z" }, + { url = "https://files.pythonhosted.org/packages/e3/d1/e30e537a15f53485b61f5be525f2157da719819e8377298502aebac45536/aiohttp-3.13.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1", size = 1720277, upload-time = "2026-01-03T17:31:31.053Z" }, + { url = "https://files.pythonhosted.org/packages/84/45/23f4c451d8192f553d38d838831ebbc156907ea6e05557f39563101b7717/aiohttp-3.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25", size = 1548575, upload-time = "2026-01-03T17:31:32.87Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ed/0a42b127a43712eda7807e7892c083eadfaf8429ca8fb619662a530a3aab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603", size = 1679455, upload-time = "2026-01-03T17:31:34.76Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b5/c05f0c2b4b4fe2c9d55e73b6d3ed4fd6c9dc2684b1d81cbdf77e7fad9adb/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a", size = 1687417, upload-time = "2026-01-03T17:31:36.699Z" }, + { url = "https://files.pythonhosted.org/packages/c9/6b/915bc5dad66aef602b9e459b5a973529304d4e89ca86999d9d75d80cbd0b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926", size = 1729968, upload-time = "2026-01-03T17:31:38.622Z" }, + { url = "https://files.pythonhosted.org/packages/11/3b/e84581290a9520024a08640b63d07673057aec5ca548177a82026187ba73/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba", size = 1545690, upload-time = "2026-01-03T17:31:40.57Z" }, + { url = "https://files.pythonhosted.org/packages/f5/04/0c3655a566c43fd647c81b895dfe361b9f9ad6d58c19309d45cff52d6c3b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c", size = 1746390, upload-time = "2026-01-03T17:31:42.857Z" }, + { url = "https://files.pythonhosted.org/packages/1f/53/71165b26978f719c3419381514c9690bd5980e764a09440a10bb816ea4ab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43", size = 1702188, upload-time = "2026-01-03T17:31:44.984Z" }, + { url = "https://files.pythonhosted.org/packages/29/a7/cbe6c9e8e136314fa1980da388a59d2f35f35395948a08b6747baebb6aa6/aiohttp-3.13.3-cp314-cp314-win32.whl", hash = "sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1", size = 433126, upload-time = "2026-01-03T17:31:47.463Z" }, + { url = "https://files.pythonhosted.org/packages/de/56/982704adea7d3b16614fc5936014e9af85c0e34b58f9046655817f04306e/aiohttp-3.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984", size = 459128, upload-time = "2026-01-03T17:31:49.2Z" }, + { url = "https://files.pythonhosted.org/packages/6c/2a/3c79b638a9c3d4658d345339d22070241ea341ed4e07b5ac60fb0f418003/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c", size = 769512, upload-time = "2026-01-03T17:31:51.134Z" }, + { url = "https://files.pythonhosted.org/packages/29/b9/3e5014d46c0ab0db8707e0ac2711ed28c4da0218c358a4e7c17bae0d8722/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592", size = 506444, upload-time = "2026-01-03T17:31:52.85Z" }, + { url = "https://files.pythonhosted.org/packages/90/03/c1d4ef9a054e151cd7839cdc497f2638f00b93cbe8043983986630d7a80c/aiohttp-3.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f", size = 510798, upload-time = "2026-01-03T17:31:54.91Z" }, + { url = "https://files.pythonhosted.org/packages/ea/76/8c1e5abbfe8e127c893fe7ead569148a4d5a799f7cf958d8c09f3eedf097/aiohttp-3.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29", size = 1868835, upload-time = "2026-01-03T17:31:56.733Z" }, + { url = "https://files.pythonhosted.org/packages/8e/ac/984c5a6f74c363b01ff97adc96a3976d9c98940b8969a1881575b279ac5d/aiohttp-3.13.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc", size = 1720486, upload-time = "2026-01-03T17:31:58.65Z" }, + { url = "https://files.pythonhosted.org/packages/b2/9a/b7039c5f099c4eb632138728828b33428585031a1e658d693d41d07d89d1/aiohttp-3.13.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2", size = 1847951, upload-time = "2026-01-03T17:32:00.989Z" }, + { url = "https://files.pythonhosted.org/packages/3c/02/3bec2b9a1ba3c19ff89a43a19324202b8eb187ca1e928d8bdac9bbdddebd/aiohttp-3.13.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587", size = 1941001, upload-time = "2026-01-03T17:32:03.122Z" }, + { url = "https://files.pythonhosted.org/packages/37/df/d879401cedeef27ac4717f6426c8c36c3091c6e9f08a9178cc87549c537f/aiohttp-3.13.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8", size = 1797246, upload-time = "2026-01-03T17:32:05.255Z" }, + { url = "https://files.pythonhosted.org/packages/8d/15/be122de1f67e6953add23335c8ece6d314ab67c8bebb3f181063010795a7/aiohttp-3.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632", size = 1627131, upload-time = "2026-01-03T17:32:07.607Z" }, + { url = "https://files.pythonhosted.org/packages/12/12/70eedcac9134cfa3219ab7af31ea56bc877395b1ac30d65b1bc4b27d0438/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64", size = 1795196, upload-time = "2026-01-03T17:32:09.59Z" }, + { url = "https://files.pythonhosted.org/packages/32/11/b30e1b1cd1f3054af86ebe60df96989c6a414dd87e27ad16950eee420bea/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0", size = 1782841, upload-time = "2026-01-03T17:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/88/0d/d98a9367b38912384a17e287850f5695c528cff0f14f791ce8ee2e4f7796/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56", size = 1795193, upload-time = "2026-01-03T17:32:13.705Z" }, + { url = "https://files.pythonhosted.org/packages/43/a5/a2dfd1f5ff5581632c7f6a30e1744deda03808974f94f6534241ef60c751/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72", size = 1621979, upload-time = "2026-01-03T17:32:15.965Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/12973c382ae7c1cccbc4417e129c5bf54c374dfb85af70893646e1f0e749/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df", size = 1822193, upload-time = "2026-01-03T17:32:18.219Z" }, + { url = "https://files.pythonhosted.org/packages/3c/5f/24155e30ba7f8c96918af1350eb0663e2430aad9e001c0489d89cd708ab1/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa", size = 1769801, upload-time = "2026-01-03T17:32:20.25Z" }, + { url = "https://files.pythonhosted.org/packages/eb/f8/7314031ff5c10e6ece114da79b338ec17eeff3a079e53151f7e9f43c4723/aiohttp-3.13.3-cp314-cp314t-win32.whl", hash = "sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767", size = 466523, upload-time = "2026-01-03T17:32:22.215Z" }, + { url = "https://files.pythonhosted.org/packages/b4/63/278a98c715ae467624eafe375542d8ba9b4383a016df8fdefe0ae28382a7/aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344", size = 499694, upload-time = "2026-01-03T17:32:24.546Z" }, + { url = "https://files.pythonhosted.org/packages/bf/79/446655656861d3e7e2c32bfcf160c7aa9e9dc63776a691b124dba65cdd77/aiohttp-3.13.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e", size = 741433, upload-time = "2026-01-03T17:32:26.453Z" }, + { url = "https://files.pythonhosted.org/packages/cb/49/773c4b310b5140d2fb5e79bb0bf40b7b41dad80a288ca1a8759f5f72bda9/aiohttp-3.13.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7", size = 497332, upload-time = "2026-01-03T17:32:28.37Z" }, + { url = "https://files.pythonhosted.org/packages/bc/31/1dcbc4b83a4e6f76a0ad883f07f21ffbfe29750c89db97381701508c9f45/aiohttp-3.13.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02", size = 492365, upload-time = "2026-01-03T17:32:30.234Z" }, + { url = "https://files.pythonhosted.org/packages/5a/b5/b50657496c8754482cd7964e50aaf3aa84b3db61ed45daec4c1aec5b94b4/aiohttp-3.13.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43", size = 1660440, upload-time = "2026-01-03T17:32:32.586Z" }, + { url = "https://files.pythonhosted.org/packages/2a/73/9b69e5139d89d75127569298931444ad78ea86a5befd5599780b1e9a6880/aiohttp-3.13.3-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6", size = 1632740, upload-time = "2026-01-03T17:32:34.793Z" }, + { url = "https://files.pythonhosted.org/packages/ef/fe/3ea9b5af694b4e3aec0d0613a806132ca744747146fca68e96bf056f61a7/aiohttp-3.13.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce", size = 1719782, upload-time = "2026-01-03T17:32:37.737Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c2/46b3b06e60851cbb71efb0f79a3267279cbef7b12c58e68a1e897f269cca/aiohttp-3.13.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80", size = 1813527, upload-time = "2026-01-03T17:32:39.973Z" }, + { url = "https://files.pythonhosted.org/packages/36/23/71ceb78c769ed65fe4c697692de232b63dab399210678d2b00961ccb0619/aiohttp-3.13.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a", size = 1661268, upload-time = "2026-01-03T17:32:42.082Z" }, + { url = "https://files.pythonhosted.org/packages/c4/8d/86e929523d955e85ebab7c0e2b9e0cb63604cfc27dc3280e10d0063cf682/aiohttp-3.13.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6", size = 1552742, upload-time = "2026-01-03T17:32:44.622Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ea/3f5987cba1bab6bd151f0d97aa60f0ce04d3c83316692a6bb6ba2fb69f92/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558", size = 1632918, upload-time = "2026-01-03T17:32:46.749Z" }, + { url = "https://files.pythonhosted.org/packages/be/2c/7e1e85121f2e31ee938cb83a8f32dfafd4908530c10fabd6d46761c12ac7/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7", size = 1644446, upload-time = "2026-01-03T17:32:49.063Z" }, + { url = "https://files.pythonhosted.org/packages/5d/35/ce6133d423ad0e8ca976a7c848f7146bca3520eea4ccf6b95e2d077c9d20/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877", size = 1689487, upload-time = "2026-01-03T17:32:51.113Z" }, + { url = "https://files.pythonhosted.org/packages/50/f7/ff7a27c15603d460fd1366b3c22054f7ae4fa9310aca40b43bde35867fcd/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3", size = 1540715, upload-time = "2026-01-03T17:32:53.38Z" }, + { url = "https://files.pythonhosted.org/packages/17/02/053f11346e5b962e6d8a1c4f8c70c29d5970a1b4b8e7894c68e12c27a57f/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704", size = 1711835, upload-time = "2026-01-03T17:32:56.088Z" }, + { url = "https://files.pythonhosted.org/packages/fb/71/9b9761ddf276fd6708d13720197cbac19b8d67ecfa9116777924056cfcaa/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f", size = 1649593, upload-time = "2026-01-03T17:32:58.181Z" }, + { url = "https://files.pythonhosted.org/packages/ae/72/5d817e9ea218acae12a5e3b9ad1178cf0c12fc3570c0b47eea2daf95f9ea/aiohttp-3.13.3-cp39-cp39-win32.whl", hash = "sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1", size = 434831, upload-time = "2026-01-03T17:33:00.577Z" }, + { url = "https://files.pythonhosted.org/packages/39/cb/22659d9bf3149b7a2927bc2769cc9c8f8f5a80eba098398e03c199a43a85/aiohttp-3.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538", size = 457697, upload-time = "2026-01-03T17:33:03.167Z" }, ] [[package]] @@ -470,11 +470,11 @@ wheels = [ [[package]] name = "idna" -version = "3.15" +version = "3.11" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/82/77/7b3966d0b9d1d31a36ddf1746926a11dface89a83409bf1483f0237aa758/idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc", size = 199245, upload-time = "2026-05-12T22:45:57.011Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/23/408243171aa9aaba178d3e2559159c24c1171a641aa83b67bdd3394ead8e/idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8", size = 72340, upload-time = "2026-05-12T22:45:55.733Z" }, + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, ] [[package]] @@ -779,7 +779,7 @@ wheels = [ [[package]] name = "oz-agent-sdk" -version = "0.13.0" +version = "0.4.0" source = { editable = "." } dependencies = [ { name = "anyio" }, From 7ac7b1fa205754be70a409721d30a2f8b9a4d175 Mon Sep 17 00:00:00 2001 From: Ian Hodge Date: Thu, 11 Jun 2026 12:36:04 -0400 Subject: [PATCH 04/14] chore: restore promote workflow and changelog as sealed custom code Stainless-Generated-From: c19340ba90218aca1b6f161cda3c8432341896b8 --- .github/workflows/promote_sdk.yml | 26 ++ CHANGELOG.md | 363 +++++++++++++++++++++++ src/oz_agent_sdk/types/agent/run_item.py | 8 - 3 files changed, 389 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/promote_sdk.yml create mode 100644 CHANGELOG.md diff --git a/.github/workflows/promote_sdk.yml b/.github/workflows/promote_sdk.yml new file mode 100644 index 0000000..d007379 --- /dev/null +++ b/.github/workflows/promote_sdk.yml @@ -0,0 +1,26 @@ +# Promote SDK updates from this staging repository to the corresponding +# production repository. + +name: Promote SDK + +on: + workflow_dispatch: + +jobs: + promote: + name: promote + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.event.repository.default_branch }} + fetch-depth: 0 + persist-credentials: false + + - name: Promote SDK to production + uses: warpdotdev/warp-github-actions/.github/actions/promote_sdk@main + with: + production_repo_token: ${{ secrets.STAINLESS_SDK_PROD_WRITE_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e741eb1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,363 @@ +# Changelog + +## 0.13.0 (2026-05-21) + +Full Changelog: [v0.12.0...v0.13.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.12.0...v0.13.0) + +### Features + +* Add default harness selection for agents ([8cd06f6](https://github.com/warpdotdev/oz-sdk-python/commit/8cd06f6fcb48444e3861ff130d2fb4fa820e3aa7)) +* Add per-agent AWS Bedrock OIDC inference role (backend) ([e4aadec](https://github.com/warpdotdev/oz-sdk-python/commit/e4aadec916b2bea7e05e0e263b307449002e7f8b)) +* Add updated_at to agent API responses ([3188420](https://github.com/warpdotdev/oz-sdk-python/commit/318842095218a12c5b3ed1d945941e74ca5c9d54)) +* **agents:** add prompt property to agent identity data model ([520c835](https://github.com/warpdotdev/oz-sdk-python/commit/520c8350b5b7850242adc082fe83a7ae666e6da6)) +* **api:** api update ([b8306ad](https://github.com/warpdotdev/oz-sdk-python/commit/b8306ad8aff3c8e83f3c9549a8d78a1dfe22e7f5)) +* **api:** api update ([a66cdc2](https://github.com/warpdotdev/oz-sdk-python/commit/a66cdc2b99686872998efe8592b21bb14c6320cc)) +* **api:** api update ([da1ee9c](https://github.com/warpdotdev/oz-sdk-python/commit/da1ee9c25078cfbf6fb34e6e3afd09edcfe6b76b)) +* **api:** api update ([32f77e1](https://github.com/warpdotdev/oz-sdk-python/commit/32f77e19c7bd30dbeacb84ce95f5e487a7c9debf)) +* **api:** api update ([7ec4ab4](https://github.com/warpdotdev/oz-sdk-python/commit/7ec4ab432f4a3e6494d29d7db0b9bf3a08ba0885)) +* **api:** api update ([c05564a](https://github.com/warpdotdev/oz-sdk-python/commit/c05564aa69ba70685b6778859b0574f1d2d69a33)) +* **api:** api update ([0976362](https://github.com/warpdotdev/oz-sdk-python/commit/09763624c5e172aa28fa43ed18bc0e391c04331d)) +* **api:** api update ([96d640c](https://github.com/warpdotdev/oz-sdk-python/commit/96d640cd68290e1a915fca51a8629cf9dab4d81d)) +* **api:** api update ([2730eea](https://github.com/warpdotdev/oz-sdk-python/commit/2730eea19d91df998de5ef1b5da4989670a5889a)) +* **api:** api update ([af81ef3](https://github.com/warpdotdev/oz-sdk-python/commit/af81ef3a2d48f378209cf69a3074997cb02b1b6c)) +* **api:** api update ([99b2d31](https://github.com/warpdotdev/oz-sdk-python/commit/99b2d31ba1a4c2c3d79fc11c5eb8d611c55613b8)) +* Codex auth: API key support. ([cb84f0c](https://github.com/warpdotdev/oz-sdk-python/commit/cb84f0c6c9625d8c0657c728d5fadae065eb37c9)) +* **internal/types:** support eagerly validating pydantic iterators ([a588f0e](https://github.com/warpdotdev/oz-sdk-python/commit/a588f0e5ba27503659b5abf01d0ebc01f652950d)) +* **memory:** agent identity memory store attachments — API layer ([94b5348](https://github.com/warpdotdev/oz-sdk-python/commit/94b5348152c6b0bfb03b0d3887366c4a65e397fb)) +* **memory:** wire memory stores into run pipeline and add listing endpoint ([6bb74c2](https://github.com/warpdotdev/oz-sdk-python/commit/6bb74c2b695cd268fe8466fc6099f082370ba54e)) +* Partial support for multiple skills per run ([e39df48](https://github.com/warpdotdev/oz-sdk-python/commit/e39df4831329c75d13b7638a2edc146a0a2f57a1)) +* Resolve Bedrock region server-side and ship as AWS_REGION ([cef2591](https://github.com/warpdotdev/oz-sdk-python/commit/cef25915ca886a87aa5d567d1e3001ca746c8960)) +* Retrieve memories in third party harnesses ([7689e12](https://github.com/warpdotdev/oz-sdk-python/commit/7689e121d6f22efad3d81828721f8ed900b9cd28)) +* Support service account impersonation in GCP Workload Identity Federation config ([6df1722](https://github.com/warpdotdev/oz-sdk-python/commit/6df1722325b8c96d7655348e75bd82980e2bd055)) + + +### Bug Fixes + +* **client:** add missing f-string prefix in file type error message ([17a8e5b](https://github.com/warpdotdev/oz-sdk-python/commit/17a8e5bf17b882a440a067fee1569caf679f8b55)) + +## 0.12.0 (2026-05-07) + +Full Changelog: [v0.11.0...v0.12.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.11.0...v0.12.0) + +### Features + +* [APP-3106] Specs: Explicit QueryMode for cloud agent run creation ([1d4e049](https://github.com/warpdotdev/oz-sdk-python/commit/1d4e049e5c64fdfe1f8eff8dbf7bc8256ed98182)) +* [REMOTE-1481] [3/N] Add executor filter to run list API ([2dbc229](https://github.com/warpdotdev/oz-sdk-python/commit/2dbc22949c6c9475a31e74cba5eadecb018277f3)) +* [REMOTE-1538] Support base model on named agents ([7634c23](https://github.com/warpdotdev/oz-sdk-python/commit/7634c231906d3fb53c9576b39fac1fa60f694790)) +* Accept and persist executor on schedule and integration create/update APIs ([a8500aa](https://github.com/warpdotdev/oz-sdk-python/commit/a8500aa0b3e74221cd931b01d7e7569ad191d1f3)) +* Add API support for public access on oz session link ([df940e0](https://github.com/warpdotdev/oz-sdk-python/commit/df940e09b23d2cc3d314407a8826f722b9428dca)) +* Add Codex as a third-party Oz harness. ([898e18f](https://github.com/warpdotdev/oz-sdk-python/commit/898e18f8e26a2064d3bb3bdda83c08adeb91088d)) +* Add Gemini as a third-party Oz harness. ([0128722](https://github.com/warpdotdev/oz-sdk-python/commit/0128722383f87f6d5a73fd0ecafc4206a3013342)) +* Add parent_run_id filter to List runs endpoint ([33cf04c](https://github.com/warpdotdev/oz-sdk-python/commit/33cf04c0777d53059f8a3c73b925b468276aba2a)) +* Add system prompt to resolve-prompt for harnesses. ([2b7afab](https://github.com/warpdotdev/oz-sdk-python/commit/2b7afabf4a54764ab162ac32f4dbe7fe4274ba72)) +* Add trigger URL to task source. ([9662dbe](https://github.com/warpdotdev/oz-sdk-python/commit/9662dbe10cc5392271b3e56c35cb8ef95ec80eed)) +* Add worker_host to AgentListSource in OpenAPI spec ([ec0982c](https://github.com/warpdotdev/oz-sdk-python/commit/ec0982ce786b2380ab89aa7298b28998c6eade46)) +* **api:** api update ([88de4e2](https://github.com/warpdotdev/oz-sdk-python/commit/88de4e2765d70de416658f0ce0ef42585763efc9)) +* **api:** api update ([4a0d4fc](https://github.com/warpdotdev/oz-sdk-python/commit/4a0d4fc0711f3fe0d3168c3f5f7ec2176d5b0010)) +* **api:** api update ([654da59](https://github.com/warpdotdev/oz-sdk-python/commit/654da597a10a63048c5a34ca67c9d6684c72b688)) +* **api:** api update ([86d389c](https://github.com/warpdotdev/oz-sdk-python/commit/86d389c610fb2b89d7fcd17ebfd06610ef2b0b90)) +* **api:** api update ([15d68a1](https://github.com/warpdotdev/oz-sdk-python/commit/15d68a1db8178fd9cb5fae456ca6f341b60fd1e7)) +* **api:** api update ([54f5cdc](https://github.com/warpdotdev/oz-sdk-python/commit/54f5cdc819015611f7214b8ac6632df1cebf857d)) +* **api:** api update ([e290d3b](https://github.com/warpdotdev/oz-sdk-python/commit/e290d3b8cd2e8bd10a713e41992e282b704c624e)) +* **api:** api update ([35565ad](https://github.com/warpdotdev/oz-sdk-python/commit/35565ada13a8a16f9117b3ca0c12279d1708d184)) +* **api:** api update ([9cf2d03](https://github.com/warpdotdev/oz-sdk-python/commit/9cf2d0352242be5c7075fe971561cc36aaaf6e77)) +* **api:** api update ([ed871aa](https://github.com/warpdotdev/oz-sdk-python/commit/ed871aac657265138112d98be757a0de48796e02)) +* **api:** api update ([a44c455](https://github.com/warpdotdev/oz-sdk-python/commit/a44c455cb949e69b05f33f38571b40d9c0caed36)) +* **api:** api update ([e24ba64](https://github.com/warpdotdev/oz-sdk-python/commit/e24ba644c9d3624019f240fd43f51079adf7d8d4)) +* **api:** api update ([e5aea21](https://github.com/warpdotdev/oz-sdk-python/commit/e5aea2192017b1758d7b32d1e855015ce29e93ca)) +* **api:** api update ([f94b38b](https://github.com/warpdotdev/oz-sdk-python/commit/f94b38b2ffaf344a198e89ad7ace1d7b8e93c300)) +* **api:** api update ([7f419fa](https://github.com/warpdotdev/oz-sdk-python/commit/7f419faa01908e1b4a613ec2bdd708aed1a05871)) +* **api:** api update ([116f06e](https://github.com/warpdotdev/oz-sdk-python/commit/116f06e5c63e8d015e7dfea47fc22ede53ebb84e)) +* **api:** api update ([66c8521](https://github.com/warpdotdev/oz-sdk-python/commit/66c852194f355cedca2b34b944c398e796f064ab)) +* **api:** api update ([ebd2c55](https://github.com/warpdotdev/oz-sdk-python/commit/ebd2c5520128722d88285aea9dd0caf3242d9a31)) +* **api:** api update ([1ffc53b](https://github.com/warpdotdev/oz-sdk-python/commit/1ffc53b4d69eeb8060faac1903f1ba25f7a4c443)) +* **api:** api update ([cf28804](https://github.com/warpdotdev/oz-sdk-python/commit/cf288045d369ed927db45ac5e5ebd994ccebb547)) +* **api:** api update ([a6d82f1](https://github.com/warpdotdev/oz-sdk-python/commit/a6d82f1a71ad8e0ff5f10c43cc81938babc1444e)) +* **api:** api update ([b9872f2](https://github.com/warpdotdev/oz-sdk-python/commit/b9872f2642191ef6e1d4d5d3542a08f9e2784b9e)) +* **api:** api update ([0ef9c8f](https://github.com/warpdotdev/oz-sdk-python/commit/0ef9c8f483269d203a3edc7b5805f48f4263eb2f)) +* Apply service-account secrets at run creation ([db0e98c](https://github.com/warpdotdev/oz-sdk-python/commit/db0e98ca667b0cfe5b8ab182db5b1d4a19584113)) +* Extend service account API to support skills + secrets ([caf9c45](https://github.com/warpdotdev/oz-sdk-python/commit/caf9c4539ad1718ed194619ebf26425217265706)) +* implement server-side cloud-to-cloud handoff for agent follow-ups (REMOTE-1290) ([eb873a6](https://github.com/warpdotdev/oz-sdk-python/commit/eb873a6092aa1792ca6c23f5d27a7ee66c225ea0)) +* Include agent UID in scheduled agent API responses ([1714226](https://github.com/warpdotdev/oz-sdk-python/commit/1714226a85760699faacebd23cc1ea3a6bc7f0b9)) +* Inject auth secrets via ambient agent config. ([6032a0c](https://github.com/warpdotdev/oz-sdk-python/commit/6032a0ccfe2ce669ce1f815ad853b912d4ca575e)) +* Make conversation/session redirects public ([4c23bb6](https://github.com/warpdotdev/oz-sdk-python/commit/4c23bb6ebec32b5022a1731284d3e07b81a9f5ae)) +* Memory data model scaffolding. ([4ccbe03](https://github.com/warpdotdev/oz-sdk-python/commit/4ccbe0371e7bf02c454a14bc8bc2d412dcebf290)) +* support setting headers via env ([d3b4755](https://github.com/warpdotdev/oz-sdk-python/commit/d3b4755c7447d915a4e11be043b21b859f6c028d)) +* Surface platform credits in the public API ([d54b3d5](https://github.com/warpdotdev/oz-sdk-python/commit/d54b3d55760fa68853130d026dfdd88a7e226c80)) +* Update public API and graphql to support creating multiple service accounts and API keys ([8d537bc](https://github.com/warpdotdev/oz-sdk-python/commit/8d537bcbe75b344427bd04e5406ab066769f580a)) + + +### Bug Fixes + +* ensure file data are only sent as 1 parameter ([6720ea9](https://github.com/warpdotdev/oz-sdk-python/commit/6720ea9331a945cf2d030e20b8851a223697aab3)) +* use correct field name format for multipart file arrays ([f785ff2](https://github.com/warpdotdev/oz-sdk-python/commit/f785ff2bafbd319574974549a73c21643cdb5cc5)) + + +### Performance Improvements + +* **client:** optimize file structure copying in multipart requests ([b8e42cc](https://github.com/warpdotdev/oz-sdk-python/commit/b8e42cc08805eef08a3462088ba0e32cf79dac8c)) + + +### Chores + +* **internal:** more robust bootstrap script ([27c80e9](https://github.com/warpdotdev/oz-sdk-python/commit/27c80e953bc19de56ea730b0c2170aa8ffbc495a)) +* **internal:** reformat pyproject.toml ([fd17af1](https://github.com/warpdotdev/oz-sdk-python/commit/fd17af10c72ed943e4023a4e9e071ac7b8db08f7)) +* update SDK settings ([f2dd099](https://github.com/warpdotdev/oz-sdk-python/commit/f2dd099128bf4f98e304778556d55e80a4fd219c)) + +## 0.11.0 (2026-04-09) + +Full Changelog: [v0.10.1...v0.11.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.10.1...v0.11.0) + +### Features + +* [Artifacts] public API file artifact downloads ([1d2007e](https://github.com/warpdotdev/oz-sdk-python/commit/1d2007eaa692679fdcc56a6092ffdf9ad09de6ca)) +* Add harness enum to openAPI spec ([c8b44e5](https://github.com/warpdotdev/oz-sdk-python/commit/c8b44e532885d53f406babf8c0463f62d86a1fbe)) +* Add parent_run_id to retrieve/list runs API response ([c5752fb](https://github.com/warpdotdev/oz-sdk-python/commit/c5752fbbceffbc322cee5dd8b111aa0ce84ce615)) +* Add VMIdleTimeoutMinutes param to API ([31b5a63](https://github.com/warpdotdev/oz-sdk-python/commit/31b5a63204a2baca1a41f0b4124408d2d2b7e6a4)) +* Address Stainless diagnostics ([58d59e3](https://github.com/warpdotdev/oz-sdk-python/commit/58d59e3593d27ad4bb17e340c384d9709f650806)) +* **api:** api update ([9140132](https://github.com/warpdotdev/oz-sdk-python/commit/9140132ca22861c78365898e250a5c613af454a8)) +* **api:** api update ([204505c](https://github.com/warpdotdev/oz-sdk-python/commit/204505c1472d5af4b9463a975fd919c5fc4dbe78)) +* **api:** api update ([5e2d3ee](https://github.com/warpdotdev/oz-sdk-python/commit/5e2d3ee9400130c5a8dc2d51d1618ad292c051ab)) +* **api:** api update ([1238769](https://github.com/warpdotdev/oz-sdk-python/commit/12387694506b5d0d53e527db1dcdb2ca02ae2f71)) +* **api:** api update ([75b1c92](https://github.com/warpdotdev/oz-sdk-python/commit/75b1c92550babef5b0cf19689613f95131df08d7)) +* **api:** api update ([4b777eb](https://github.com/warpdotdev/oz-sdk-python/commit/4b777ebbe2483c2d882597bd0ab593128f5355d9)) +* **api:** api update ([9fe02aa](https://github.com/warpdotdev/oz-sdk-python/commit/9fe02aad21c71cbab837f7d335e5234e1974bb90)) +* **api:** api update ([7fc79ef](https://github.com/warpdotdev/oz-sdk-python/commit/7fc79efe0897451670cb44cf29c0f99b06ffe821)) +* **api:** manual updates ([ed9f4cf](https://github.com/warpdotdev/oz-sdk-python/commit/ed9f4cfa6a0db58dc3ca5564f83b09ef1a19e3a9)) +* **api:** manual updates ([e52643f](https://github.com/warpdotdev/oz-sdk-python/commit/e52643fcb1408ac9f8dd6a284b9cb818f3f468ac)) +* Create run for every local conversation and add filter ([aac84c5](https://github.com/warpdotdev/oz-sdk-python/commit/aac84c585eb3b0ed5262d683e544960a82eec2a2)) +* Define auth secrets and inject them into the environment. ([54c505b](https://github.com/warpdotdev/oz-sdk-python/commit/54c505b2d58246abab42cda52d79df3ddbfed083)) +* Endpoint to upload third-party harness block snapshots ([2f71989](https://github.com/warpdotdev/oz-sdk-python/commit/2f7198972cec56e72b802c7505fb445d10304bf4)) +* Fix the harness type in the openAPI spec ([71d7204](https://github.com/warpdotdev/oz-sdk-python/commit/71d72043f6cb8d8ae6af4c01936967059936c7b0)) +* ian/fix_conversation_id_nameing ([658c50b](https://github.com/warpdotdev/oz-sdk-python/commit/658c50b6b3937249034ad9e6993e598705d0c3c6)) +* **internal:** implement indices array format for query and form serialization ([c518876](https://github.com/warpdotdev/oz-sdk-python/commit/c518876f3da1129d3c351982ed4a06590fd15f2e)) +* Orchestrations V2: Public API endpoints ([5514980](https://github.com/warpdotdev/oz-sdk-python/commit/551498004c85dd4277069b0c059c17c7504bc18b)) +* Use correct branch for Stainless PRs ([d7b298d](https://github.com/warpdotdev/oz-sdk-python/commit/d7b298d99c5dcb5e02530329fef222de92f3e9d6)) + + +### Bug Fixes + +* **client:** preserve hardcoded query params when merging with user params ([5da3150](https://github.com/warpdotdev/oz-sdk-python/commit/5da315075e053b1a6cef709439f9972f6fd0f70f)) + +## 0.10.1 (2026-03-24) + +Full Changelog: [v0.10.0...v0.10.1](https://github.com/warpdotdev/oz-sdk-python/compare/v0.10.0...v0.10.1) + +### Chores + +* update SDK settings ([8afbeb4](https://github.com/warpdotdev/oz-sdk-python/commit/8afbeb4c91e704eac42294dbe84d1469d1743027)) +* update SDK settings ([c597727](https://github.com/warpdotdev/oz-sdk-python/commit/c59772779c50cabc63bb881c01b841e5d3c9544a)) +* update SDK settings ([628303f](https://github.com/warpdotdev/oz-sdk-python/commit/628303fee3ec94b583573b891e9ff136857a585a)) +* update SDK settings ([621aa2e](https://github.com/warpdotdev/oz-sdk-python/commit/621aa2ea925c4946c2dbd362f71859c46554038b)) + +## 0.10.0 (2026-03-24) + +Full Changelog: [v0.9.0...v0.10.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.9.0...v0.10.0) + +### Features + +* **api:** api update ([41658e2](https://github.com/warpdotdev/oz-sdk-python/commit/41658e206812a57e27f97c1f7e0be57bedcbd3c6)) +* **api:** error and error_code as types ([9766f85](https://github.com/warpdotdev/oz-sdk-python/commit/9766f85585ff3553f1f366476a3a6806f2534b22)) +* **api:** fix ScheduledAgentHistoryItem name ([ac75431](https://github.com/warpdotdev/oz-sdk-python/commit/ac754319e41b73d323cf9a36cbcf1c4dce2902bb)) +* **api:** fix schema version issues ([9c2f6a3](https://github.com/warpdotdev/oz-sdk-python/commit/9c2f6a32fa06812860efa1d76893dd8d2b60d176)) +* **api:** sorting ([0cc041e](https://github.com/warpdotdev/oz-sdk-python/commit/0cc041edf53d26c4f38c64faa7fd065d7a6760ab)) + + +### Bug Fixes + +* **deps:** bump minimum typing-extensions version ([4f3ec38](https://github.com/warpdotdev/oz-sdk-python/commit/4f3ec385748655ca8fde2457ffe402f8bf30db56)) +* **pydantic:** do not pass `by_alias` unless set ([45e0377](https://github.com/warpdotdev/oz-sdk-python/commit/45e0377a495aa67b0ee7d4415cbf13b526dbbf7e)) +* sanitize endpoint path params ([da2a124](https://github.com/warpdotdev/oz-sdk-python/commit/da2a124f15c2b69f67905cfe4b75b52d90ece562)) + + +### Chores + +* **ci:** skip lint on metadata-only changes ([c2c0d4a](https://github.com/warpdotdev/oz-sdk-python/commit/c2c0d4af8460e7d1d86fa8c14f2480323308b9a2)) +* **ci:** skip uploading artifacts on stainless-internal branches ([1ef523c](https://github.com/warpdotdev/oz-sdk-python/commit/1ef523caca4d137def551560de8c8a75c761d0f9)) +* **internal:** tweak CI branches ([21f9e2e](https://github.com/warpdotdev/oz-sdk-python/commit/21f9e2e8065a3202a149b3a2440c5adb7d084681)) +* **internal:** update gitignore ([e9e4aef](https://github.com/warpdotdev/oz-sdk-python/commit/e9e4aef20150ac3560f00edc2078979dacde8549)) +* update SDK settings ([b897579](https://github.com/warpdotdev/oz-sdk-python/commit/b89757977744858277d095a752392e2faff0bb71)) +* update SDK settings ([e4510a6](https://github.com/warpdotdev/oz-sdk-python/commit/e4510a6259d03bf4cd24b40df6243f6c879e6fb3)) + +## 0.9.0 (2026-03-03) + +Full Changelog: [v0.8.0...v0.9.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.8.0...v0.9.0) + +### Features + +* **api:** manual updates ([26fc085](https://github.com/warpdotdev/oz-sdk-python/commit/26fc0852ddd9352fe7564cba64f34203d940ac57)) +* **api:** manual updates ([1f89eca](https://github.com/warpdotdev/oz-sdk-python/commit/1f89eca19e244721d77837d5aafbf0e1de20aee7)) + +## 0.8.0 (2026-03-03) + +Full Changelog: [v0.7.0...v0.8.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.7.0...v0.8.0) + +### Features + +* **api:** manual updates ([1d27527](https://github.com/warpdotdev/oz-sdk-python/commit/1d275270bac34036ba2d2f9795792f2b71fdad3f)) + + +### Chores + +* **ci:** bump uv version ([646ee4e](https://github.com/warpdotdev/oz-sdk-python/commit/646ee4e0381123a3b24e63c4829e32c7ffc3160d)) +* **docs:** add missing descriptions ([4777a8f](https://github.com/warpdotdev/oz-sdk-python/commit/4777a8fd9d5e9644a694695190d1dc6d4c1c9941)) +* **internal:** make `test_proxy_environment_variables` more resilient to env ([3c14f7a](https://github.com/warpdotdev/oz-sdk-python/commit/3c14f7ae100fbb6df1a9f7109fd77057cf10a780)) + +## 0.7.0 (2026-02-23) + +Full Changelog: [v0.6.2...v0.7.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.6.2...v0.7.0) + +### Features + +* **api:** manual updates ([1b38e09](https://github.com/warpdotdev/oz-sdk-python/commit/1b38e0943935c83c0283523fc045eb2ff2f56109)) +* **api:** manual updates ([73b719a](https://github.com/warpdotdev/oz-sdk-python/commit/73b719a978f70ae36bd374535d80372dfaf1d47f)) + + +### Chores + +* **internal:** make `test_proxy_environment_variables` more resilient ([de1744e](https://github.com/warpdotdev/oz-sdk-python/commit/de1744eeddf1780ca9bae2690f0ed0b17406754f)) + +## 0.6.2 (2026-02-23) + +Full Changelog: [v0.6.1...v0.6.2](https://github.com/warpdotdev/oz-sdk-python/compare/v0.6.1...v0.6.2) + +### Chores + +* format all `api.md` files ([99ca557](https://github.com/warpdotdev/oz-sdk-python/commit/99ca5575a5159bc024bbf427d41a25347fe5b0f1)) +* **internal:** add request options to SSE classes ([f66a316](https://github.com/warpdotdev/oz-sdk-python/commit/f66a3167892c0c98bd77f141ef325b5c2f576f09)) +* **internal:** bump dependencies ([c487a61](https://github.com/warpdotdev/oz-sdk-python/commit/c487a61c88362ebc3b48785830d1e3b16bd7dcfe)) +* **internal:** fix lint error on Python 3.14 ([25d5626](https://github.com/warpdotdev/oz-sdk-python/commit/25d56264996ae48e38696524f244e99a32316cc3)) +* **internal:** remove mock server code ([e4b9075](https://github.com/warpdotdev/oz-sdk-python/commit/e4b90753f07d4f5da5a1075e893bb87424530cb5)) +* update mock server docs ([c253a23](https://github.com/warpdotdev/oz-sdk-python/commit/c253a238f5902a71fbd033f3e0bc0ec74406e9b9)) +* update SDK settings ([82ead07](https://github.com/warpdotdev/oz-sdk-python/commit/82ead07e4501a6e23e5db060074a5c180b0947c6)) + +## 0.6.1 (2026-02-08) + +Full Changelog: [v0.6.0...v0.6.1](https://github.com/warpdotdev/oz-sdk-python/compare/v0.6.0...v0.6.1) + +### Chores + +* update SDK settings ([c20dd4b](https://github.com/warpdotdev/oz-sdk-python/commit/c20dd4bda0c41e2bf167e1617521d9c66d6f98fd)) +* update SDK settings ([59aa425](https://github.com/warpdotdev/oz-sdk-python/commit/59aa4254f18291861ee7fb656d57566df41ad750)) +* update SDK settings ([ea483d5](https://github.com/warpdotdev/oz-sdk-python/commit/ea483d53c6242d60ece124e03510a9be6a94ffa2)) + +## 0.6.0 (2026-02-08) + +Full Changelog: [v0.5.0...v0.6.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.5.0...v0.6.0) + +### Features + +* **api:** manual updates ([75fe5e5](https://github.com/warpdotdev/oz-sdk-python/commit/75fe5e5c5ea9e044895c1bd7f1c5ab150214c8e7)) + +## 0.5.0 (2026-02-08) + +Full Changelog: [v0.4.0...v0.5.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.4.0...v0.5.0) + +### Features + +* **api:** modify openapi trigger ([db2d311](https://github.com/warpdotdev/oz-sdk-python/commit/db2d3116a353cc7a5b552e09769372264f6353b8)) + + +### Chores + +* update SDK settings ([f233ca0](https://github.com/warpdotdev/oz-sdk-python/commit/f233ca083a6cf8f49bb47f9fa348dcc3aa2b5f1c)) +* update SDK settings ([7857217](https://github.com/warpdotdev/oz-sdk-python/commit/78572179b9ad2c50849060db1d6d3981dd83297b)) +* update SDK settings ([181c928](https://github.com/warpdotdev/oz-sdk-python/commit/181c9281ec380c5aaa09de344584fe413b67728f)) + +## 0.4.0 (2026-02-06) + +Full Changelog: [v0.3.0...v0.4.0](https://github.com/warpdotdev/warp-sdk-python/compare/v0.3.0...v0.4.0) + +### ⚠ BREAKING CHANGES + +* **api:** catch up openapi, rename tasks -> runs + +### Features + +* **api:** add addnl filters to runs endpoint ([c8bf51d](https://github.com/warpdotdev/warp-sdk-python/commit/c8bf51d62e4141183a77a387f2658ad5ba0255f4)) +* **api:** add artifacts, worker_host, and new source types ([4aa1225](https://github.com/warpdotdev/warp-sdk-python/commit/4aa12253c3cd40bbd8460dfe6602fed5080554a4)) +* **api:** add computer_use_enabled param ([69cf9ca](https://github.com/warpdotdev/warp-sdk-python/commit/69cf9ca7a2b514997baa3377a9e4d96e5fc14b29)) +* **api:** add models for agent skill, user profile ([8105304](https://github.com/warpdotdev/warp-sdk-python/commit/8105304447af1bb4a28bf629cf116063621abfb5)) +* **api:** add schedules to runs ([df1b59a](https://github.com/warpdotdev/warp-sdk-python/commit/df1b59a976df5898fdd893f42173c0247b934b15)) +* **api:** add schedules, agent list, skill-spec ([1927318](https://github.com/warpdotdev/warp-sdk-python/commit/1927318b5b2a4115b3f1ec2be7db86f1e8e0d321)) +* **api:** catch up openapi, rename tasks -> runs ([fe8c5b3](https://github.com/warpdotdev/warp-sdk-python/commit/fe8c5b3f2da07a415ecd21d0f1ae5985e45f1a4d)) +* **api:** created at filter in list view ([71adb45](https://github.com/warpdotdev/warp-sdk-python/commit/71adb45481ca3248d892e62ff767b9ea011e7f21)) +* **api:** new run source types ([3237b0f](https://github.com/warpdotdev/warp-sdk-python/commit/3237b0fb12e6a28199f7ac86c8fc1fef6f96888e)) +* **api:** update artifacts ([578be41](https://github.com/warpdotdev/warp-sdk-python/commit/578be418b8f7f0e45f427bfc5c9d98f2970a31eb)) +* **client:** add custom JSON encoder for extended type support ([68f4b61](https://github.com/warpdotdev/warp-sdk-python/commit/68f4b61fd83b1f5576b72ad6ea3a28cd58e06a68)) +* **client:** add support for binary request streaming ([c64e6c4](https://github.com/warpdotdev/warp-sdk-python/commit/c64e6c44b6d02a63609d02f4976a7977dc3b0045)) + + +### Chores + +* **ci:** upgrade `actions/github-script` ([713ae7d](https://github.com/warpdotdev/warp-sdk-python/commit/713ae7d03ee5f04eeac42b9a213d96ccc91d06d7)) +* **internal:** update `actions/checkout` version ([fd0a90f](https://github.com/warpdotdev/warp-sdk-python/commit/fd0a90fae32b8a7e352217e3672e63b9b4dbc594)) + + +### Documentation + +* **dev:** Add WARP.md file ([7f1b835](https://github.com/warpdotdev/warp-sdk-python/commit/7f1b835240574dc517d424dca84251f86c4b1276)) + +## 0.3.0 (2026-01-05) + +Full Changelog: [v0.2.1...v0.3.0](https://github.com/warpdotdev/warp-sdk-python/compare/v0.2.1...v0.3.0) + +### Features + +* **api:** fix array query parameter formatting ([d1a1243](https://github.com/warpdotdev/warp-sdk-python/commit/d1a1243a0ab6b853b2340f8e7d3652bfe05ded20)) + +## 0.2.1 (2025-12-19) + +Full Changelog: [v0.2.0...v0.2.1](https://github.com/warpdotdev/warp-sdk-python/compare/v0.2.0...v0.2.1) + +### Bug Fixes + +* use async_to_httpx_files in patch method ([c02afdb](https://github.com/warpdotdev/warp-sdk-python/commit/c02afdbec958df84a3e1ec73e213e683c79b04e8)) + + +### Chores + +* **internal:** add `--fix` argument to lint script ([46a9b4b](https://github.com/warpdotdev/warp-sdk-python/commit/46a9b4bdceac62a8939f66b0227943d18db5393f)) + +## 0.2.0 (2025-12-17) + +Full Changelog: [v0.1.1...v0.2.0](https://github.com/warpdotdev/warp-sdk-python/compare/v0.1.1...v0.2.0) + +### Features + +* **api:** manual updates ([2fc23de](https://github.com/warpdotdev/warp-sdk-python/commit/2fc23de0e1d42443e691350804605243c5902026)) + + +### Chores + +* update SDK settings ([a94be20](https://github.com/warpdotdev/warp-sdk-python/commit/a94be20a45967c6ec5bd95dcc3ffcf457db84305)) + +## 0.1.1 (2025-12-17) + +Full Changelog: [v0.1.0...v0.1.1](https://github.com/warpdotdev/warp-sdk-python/compare/v0.1.0...v0.1.1) + +### Documentation + +* add environment and config usage documentation ([487b1cf](https://github.com/warpdotdev/warp-sdk-python/commit/487b1cfac5fcd89d4c91f88903ef8b601da8269d)) + +## 0.1.0 (2025-12-17) + +Full Changelog: [v0.0.1...v0.1.0](https://github.com/warpdotdev/warp-sdk-python/compare/v0.0.1...v0.1.0) + +### Features + +* **api:** manual updates ([4d4a408](https://github.com/warpdotdev/warp-sdk-python/commit/4d4a4082d453daeb3d388ac1a23cf951ada27a9e)) +* **api:** manual updates ([cd0ec74](https://github.com/warpdotdev/warp-sdk-python/commit/cd0ec747479cbb56159a361853787871c1c61395)) + + +### Chores + +* **internal:** add missing files argument to base client ([041d054](https://github.com/warpdotdev/warp-sdk-python/commit/041d0540f460ed7ecee3ed66a8db6ea9ae607360)) +* speedup initial import ([c6fa047](https://github.com/warpdotdev/warp-sdk-python/commit/c6fa04747ba3b056f9dff28e564e25b4e257ca5e)) +* update SDK settings ([217b866](https://github.com/warpdotdev/warp-sdk-python/commit/217b866ef03a583415f0fcdd65385ee76d53c664)) +* update SDK settings ([cc95759](https://github.com/warpdotdev/warp-sdk-python/commit/cc9575998cf34b016f70f8209043a02ad1677399)) + + +### Refactors + +* **internal:** switch from rye to uv ([d4cdfd0](https://github.com/warpdotdev/warp-sdk-python/commit/d4cdfd0384b63f1ce244cdbb4327043cff02f682)) diff --git a/src/oz_agent_sdk/types/agent/run_item.py b/src/oz_agent_sdk/types/agent/run_item.py index 47231a1..6181203 100644 --- a/src/oz_agent_sdk/types/agent/run_item.py +++ b/src/oz_agent_sdk/types/agent/run_item.py @@ -173,14 +173,6 @@ class RunItem(BaseModel): executor: Optional[UserProfile] = None - is_run_type_cancellable: Optional[bool] = None - """Whether the run's type is eligible for cancellation via the API. - - State-independent: false for GitHub Action and local runs; true for all other - run types (including self-hosted). Clients should still gate the control on the - run's current state. - """ - is_sandbox_running: Optional[bool] = None """Whether the sandbox environment is currently running""" From d575bc99e7d9b7ebdbaafd8134cd7bd9c8dbe683 Mon Sep 17 00:00:00 2001 From: Ian Hodge Date: Wed, 17 Jun 2026 14:44:59 -0400 Subject: [PATCH 05/14] Build SDK Stainless-Generated-From: 93f5653b5c1b4e8b1a31ac8cd58be725f76642c8 --- README.md | 49 +- api.md | 41 +- scripts/utils/ruffen-docs.py | 4 +- src/oz_agent_sdk/__init__.py | 82 +- src/oz_agent_sdk/_base_client.py | 84 +- src/oz_agent_sdk/_client.py | 329 +++---- src/oz_agent_sdk/_compat.py | 7 +- src/oz_agent_sdk/_constants.py | 2 +- src/oz_agent_sdk/_exceptions.py | 46 +- src/oz_agent_sdk/_models.py | 51 +- src/oz_agent_sdk/_qs.py | 2 +- src/oz_agent_sdk/_resource.py | 11 +- src/oz_agent_sdk/_response.py | 11 +- src/oz_agent_sdk/_streaming.py | 12 +- src/oz_agent_sdk/_types.py | 19 +- src/oz_agent_sdk/_utils/__init__.py | 2 +- src/oz_agent_sdk/_utils/_resources_proxy.py | 1 - src/oz_agent_sdk/_utils/_sync.py | 4 +- src/oz_agent_sdk/_utils/_transform.py | 4 +- src/oz_agent_sdk/_utils/_utils.py | 9 +- src/oz_agent_sdk/_version.py | 2 +- src/oz_agent_sdk/pagination.py | 52 +- src/oz_agent_sdk/resources/__init__.py | 18 +- src/oz_agent_sdk/resources/agent/__init__.py | 78 +- src/oz_agent_sdk/resources/agent/agent.py | 487 +++++----- src/oz_agent_sdk/resources/agent/agent_.py | 521 +++++------ .../resources/agent/conversations.py | 98 +- src/oz_agent_sdk/resources/agent/runs.py | 546 ++++++----- src/oz_agent_sdk/resources/agent/schedules.py | 562 ++++++------ src/oz_agent_sdk/resources/agent/sessions.py | 98 +- src/oz_agent_sdk/types/__init__.py | 26 +- src/oz_agent_sdk/types/agent/__init__.py | 26 +- .../types/agent/agent_create_params.py | 28 +- .../types/agent/agent_response.py | 31 +- .../types/agent/agent_update_params.py | 28 +- src/oz_agent_sdk/types/agent/artifact_item.py | 33 +- .../conversation_check_redirect_response.py | 7 +- .../agent/list_agent_identities_response.py | 6 +- .../types/agent/run_cancel_response.py | 4 +- src/oz_agent_sdk/types/agent/run_item.py | 42 +- .../run_list_handoff_attachments_response.py | 10 +- .../types/agent/run_list_params.py | 19 +- .../types/agent/run_source_type.py | 6 +- src/oz_agent_sdk/types/agent/run_state.py | 6 +- .../types/agent/run_submit_followup_params.py | 5 +- .../types/agent/schedule_create_params.py | 5 +- .../types/agent/schedule_delete_response.py | 3 +- .../types/agent/schedule_list_response.py | 6 +- .../types/agent/schedule_update_params.py | 5 +- .../agent/scheduled_agent_history_item.py | 9 +- .../types/agent/scheduled_agent_item.py | 17 +- .../agent/session_check_redirect_response.py | 7 +- .../types/agent_get_artifact_response.py | 35 +- .../types/agent_list_environments_params.py | 5 +- .../types/agent_list_environments_response.py | 6 +- src/oz_agent_sdk/types/agent_list_params.py | 5 +- src/oz_agent_sdk/types/agent_list_response.py | 6 +- src/oz_agent_sdk/types/agent_run_params.py | 22 +- src/oz_agent_sdk/types/agent_run_response.py | 8 +- src/oz_agent_sdk/types/agent_skill.py | 13 +- .../types/ambient_agent_config.py | 36 +- .../types/ambient_agent_config_param.py | 30 +- src/oz_agent_sdk/types/aws_provider_config.py | 4 +- src/oz_agent_sdk/types/cloud_environment.py | 19 +- .../types/cloud_environment_config.py | 13 +- src/oz_agent_sdk/types/error_code.py | 21 +- src/oz_agent_sdk/types/gcp_provider_config.py | 8 +- src/oz_agent_sdk/types/mcp_server_config.py | 8 +- .../types/mcp_server_config_param.py | 9 +- src/oz_agent_sdk/types/scope.py | 9 +- src/oz_agent_sdk/types/user_profile.py | 8 +- tests/__init__.py | 2 +- tests/api_resources/__init__.py | 2 +- tests/api_resources/agent/__init__.py | 2 +- tests/api_resources/agent/test_agent_.py | 289 +++--- .../api_resources/agent/test_conversations.py | 64 +- tests/api_resources/agent/test_runs.py | 224 ++--- tests/api_resources/agent/test_schedules.py | 408 +++++---- tests/api_resources/agent/test_sessions.py | 64 +- tests/api_resources/test_agent.py | 245 ++--- tests/conftest.py | 37 +- tests/test_client.py | 860 +++++++----------- tests/test_extract_files.py | 17 +- tests/test_files.py | 2 +- tests/test_models.py | 2 +- tests/test_response.py | 2 +- tests/test_streaming.py | 28 +- tests/test_transform.py | 2 +- tests/test_utils/test_datetime_parse.py | 1 - tests/utils.py | 4 +- 90 files changed, 2675 insertions(+), 3406 deletions(-) diff --git a/README.md b/README.md index 9aba4a6..1ce7591 100644 --- a/README.md +++ b/README.md @@ -114,13 +114,11 @@ client = AsyncOzAPI( api_key=os.environ.get("WARP_API_KEY"), # This is the default and can be omitted ) - async def main() -> None: - response = await client.agent.run( - prompt="Fix the bug in auth.go", - ) - print(response.run_id) - + response = await client.agent.run( + prompt="Fix the bug in auth.go", + ) + print(response.run_id) asyncio.run(main()) ``` @@ -146,17 +144,15 @@ import asyncio from oz_agent_sdk import DefaultAioHttpClient from oz_agent_sdk import AsyncOzAPI - async def main() -> None: - async with AsyncOzAPI( - api_key=os.environ.get("WARP_API_KEY"), # This is the default and can be omitted - http_client=DefaultAioHttpClient(), - ) as client: - response = await client.agent.run( - prompt="Fix the bug in auth.go", - ) - print(response.run_id) - + async with AsyncOzAPI( + api_key=os.environ.get("WARP_API_KEY"), # This is the default and can be omitted + http_client=DefaultAioHttpClient(), +) as client: + response = await client.agent.run( + prompt="Fix the bug in auth.go", + ) + print(response.run_id) asyncio.run(main()) ``` @@ -197,7 +193,6 @@ from oz_agent_sdk import AsyncOzAPI client = AsyncOzAPI() - async def main() -> None: all_runs = [] # Iterate through items across all pages, issuing requests as needed. @@ -205,7 +200,6 @@ async def main() -> None: all_runs.append(run) print(all_runs) - asyncio.run(main()) ``` @@ -226,7 +220,7 @@ Or just work directly with the returned data: ```python first_page = await client.agent.runs.list() -print(f"next page cursor: {first_page.page_info.next_cursor}") # => "next page cursor: ..." +print(f"next page cursor: {first_page.page_info.next_cursor}") # => "next page cursor: ..." for run in first_page.runs: print(run.run_id) @@ -269,7 +263,7 @@ try: ) except oz_agent_sdk.APIConnectionError as e: print("The server could not be reached") - print(e.__cause__) # an underlying Exception, likely raised within httpx. + print(e.__cause__) # an underlying Exception, likely raised within httpx. except oz_agent_sdk.RateLimitError as e: print("A 429 status code was received; we should back off a bit.") except oz_agent_sdk.APIStatusError as e: @@ -309,7 +303,7 @@ client = OzAPI( ) # Or, configure per-request: -client.with_options(max_retries=5).agent.run( +client.with_options(max_retries = 5).agent.run( prompt="Fix the bug in auth.go", ) ``` @@ -334,7 +328,7 @@ client = OzAPI( ) # Override per-request: -client.with_options(timeout=5.0).agent.run( +client.with_options(timeout = 5.0).agent.run( prompt="Fix the bug in auth.go", ) ``` @@ -399,11 +393,11 @@ To stream the response body, use `.with_streaming_response` instead, which requi ```python with client.agent.with_streaming_response.run( prompt="Fix the bug in auth.go", -) as response: - print(response.headers.get("X-My-Header")) +) as response : + print(response.headers.get('X-My-Header')) for line in response.iter_lines(): - print(line) + print(line) ``` The context manager is required so that the response will reliably be closed. @@ -457,10 +451,7 @@ from oz_agent_sdk import OzAPI, DefaultHttpxClient client = OzAPI( # Or use the `OZ_API_BASE_URL` env var base_url="http://my.test.server.example.com:8083", - http_client=DefaultHttpxClient( - proxy="http://my.test.proxy.example.com", - transport=httpx.HTTPTransport(local_address="0.0.0.0"), - ), + http_client=DefaultHttpxClient(proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0")), ) ``` diff --git a/api.md b/api.md index e82443c..7b728ae 100644 --- a/api.md +++ b/api.md @@ -3,23 +3,7 @@ Types: ```python -from oz_agent_sdk.types import ( - AgentSkill, - AmbientAgentConfig, - AwsProviderConfig, - CloudEnvironment, - CloudEnvironmentConfig, - Error, - ErrorCode, - GcpProviderConfig, - McpServerConfig, - Scope, - UserProfile, - AgentListResponse, - AgentGetArtifactResponse, - AgentListEnvironmentsResponse, - AgentRunResponse, -) +from oz_agent_sdk.types import AgentSkill, AmbientAgentConfig, AwsProviderConfig, CloudEnvironment, CloudEnvironmentConfig, Error, ErrorCode, GcpProviderConfig, McpServerConfig, Scope, UserProfile, AgentListResponse, AgentGetArtifactResponse, AgentListEnvironmentsResponse, AgentRunResponse ``` Methods: @@ -34,14 +18,7 @@ Methods: Types: ```python -from oz_agent_sdk.types.agent import ( - ArtifactItem, - RunItem, - RunSourceType, - RunState, - RunCancelResponse, - RunListHandoffAttachmentsResponse, -) +from oz_agent_sdk.types.agent import ArtifactItem, RunItem, RunSourceType, RunState, RunCancelResponse, RunListHandoffAttachmentsResponse ``` Methods: @@ -57,12 +34,7 @@ Methods: Types: ```python -from oz_agent_sdk.types.agent import ( - ScheduledAgentHistoryItem, - ScheduledAgentItem, - ScheduleListResponse, - ScheduleDeleteResponse, -) +from oz_agent_sdk.types.agent import ScheduledAgentHistoryItem, ScheduledAgentItem, ScheduleListResponse, ScheduleDeleteResponse ``` Methods: @@ -80,12 +52,7 @@ Methods: Types: ```python -from oz_agent_sdk.types.agent import ( - AgentResponse, - CreateAgentRequest, - ListAgentIdentitiesResponse, - UpdateAgentRequest, -) +from oz_agent_sdk.types.agent import AgentResponse, CreateAgentRequest, ListAgentIdentitiesResponse, UpdateAgentRequest ``` Methods: diff --git a/scripts/utils/ruffen-docs.py b/scripts/utils/ruffen-docs.py index 0cf2bd2..37b3d94 100644 --- a/scripts/utils/ruffen-docs.py +++ b/scripts/utils/ruffen-docs.py @@ -47,7 +47,7 @@ def _md_match(match: Match[str]) -> str: with _collect_error(match): code = format_code_block(code) code = textwrap.indent(code, match["indent"]) - return f"{match['before']}{code}{match['after']}" + return f'{match["before"]}{code}{match["after"]}' def _pycon_match(match: Match[str]) -> str: code = "" @@ -97,7 +97,7 @@ def finish_fragment() -> None: def _md_pycon_match(match: Match[str]) -> str: code = _pycon_match(match) code = textwrap.indent(code, match["indent"]) - return f"{match['before']}{code}{match['after']}" + return f'{match["before"]}{code}{match["after"]}' src = MD_RE.sub(_md_match, src) src = MD_PYCON_RE.sub(_md_pycon_match, src) diff --git a/src/oz_agent_sdk/__init__.py b/src/oz_agent_sdk/__init__.py index ea8b882..b487a31 100644 --- a/src/oz_agent_sdk/__init__.py +++ b/src/oz_agent_sdk/__init__.py @@ -1,80 +1,22 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import typing as _t - from . import types -from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes, omit, not_given +from ._version import __version__, __title__ +from ._client import Timeout,Transport,RequestOptions,Client,AsyncClient,Stream,AsyncStream,OzAPI,AsyncOzAPI +from ._exceptions import OzAPIError,APIError,APIStatusError,APITimeoutError,APIConnectionError,APIResponseValidationError,BadRequestError,AuthenticationError,PermissionDeniedError,NotFoundError,ConflictError,UnprocessableEntityError,RateLimitError,InternalServerError +from ._types import NoneType,Transport,ProxiesTypes,NotGiven,NOT_GIVEN,not_given,Omit,omit from ._utils import file_from_path -from ._client import OzAPI, Client, Stream, Timeout, Transport, AsyncOzAPI, AsyncClient, AsyncStream, RequestOptions from ._models import BaseModel -from ._version import __title__, __version__ -from ._response import APIResponse as APIResponse, AsyncAPIResponse as AsyncAPIResponse -from ._constants import DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES, DEFAULT_CONNECTION_LIMITS -from ._exceptions import ( - APIError, - OzAPIError, - ConflictError, - NotFoundError, - APIStatusError, - RateLimitError, - APITimeoutError, - BadRequestError, - APIConnectionError, - AuthenticationError, - InternalServerError, - PermissionDeniedError, - UnprocessableEntityError, - APIResponseValidationError, -) -from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient +from ._constants import DEFAULT_TIMEOUT,DEFAULT_MAX_RETRIES,DEFAULT_CONNECTION_LIMITS +from ._base_client import DefaultHttpxClient,DefaultAsyncHttpxClient,DefaultAioHttpClient from ._utils._logs import setup_logging as _setup_logging +from ._response import APIResponse as APIResponse, AsyncAPIResponse as AsyncAPIResponse +import typing as _t -__all__ = [ - "types", - "__version__", - "__title__", - "NoneType", - "Transport", - "ProxiesTypes", - "NotGiven", - "NOT_GIVEN", - "not_given", - "Omit", - "omit", - "OzAPIError", - "APIError", - "APIStatusError", - "APITimeoutError", - "APIConnectionError", - "APIResponseValidationError", - "BadRequestError", - "AuthenticationError", - "PermissionDeniedError", - "NotFoundError", - "ConflictError", - "UnprocessableEntityError", - "RateLimitError", - "InternalServerError", - "Timeout", - "RequestOptions", - "Client", - "AsyncClient", - "Stream", - "AsyncStream", - "OzAPI", - "AsyncOzAPI", - "file_from_path", - "BaseModel", - "DEFAULT_TIMEOUT", - "DEFAULT_MAX_RETRIES", - "DEFAULT_CONNECTION_LIMITS", - "DefaultHttpxClient", - "DefaultAsyncHttpxClient", - "DefaultAioHttpClient", -] +__all__ = ["types", "__version__", "__title__", "NoneType", "Transport", "ProxiesTypes", "NotGiven", "NOT_GIVEN", "not_given", "Omit", "omit", "OzAPIError", "APIError", "APIStatusError", "APITimeoutError", "APIConnectionError", "APIResponseValidationError", "BadRequestError", "AuthenticationError", "PermissionDeniedError", "NotFoundError", "ConflictError", "UnprocessableEntityError", "RateLimitError", "InternalServerError", "Timeout", "RequestOptions", "Client", "AsyncClient", "Stream", "AsyncStream", "OzAPI", "AsyncOzAPI", "file_from_path", "BaseModel", "DEFAULT_TIMEOUT", "DEFAULT_MAX_RETRIES", "DEFAULT_CONNECTION_LIMITS", "DefaultHttpxClient", "DefaultAsyncHttpxClient", "DefaultAioHttpClient"] if not _t.TYPE_CHECKING: - from ._utils._resources_proxy import resources as resources + from ._utils._resources_proxy import resources as resources _setup_logging() @@ -86,7 +28,7 @@ for __name in __all__: if not __name.startswith("__"): try: - __locals[__name].__module__ = "oz_agent_sdk" + setattr(__locals[__name], "__module__", "oz_agent_sdk") except (TypeError, AttributeError): # Some of our exported symbols are builtins which we can't set attributes for. - pass + pass \ No newline at end of file diff --git a/src/oz_agent_sdk/_base_client.py b/src/oz_agent_sdk/_base_client.py index 047d5bb..ef52153 100644 --- a/src/oz_agent_sdk/_base_client.py +++ b/src/oz_agent_sdk/_base_client.py @@ -5,11 +5,11 @@ import time import uuid import email +import warnings import asyncio import inspect import logging import platform -import warnings import email.utils from types import TracebackType from random import random @@ -63,7 +63,7 @@ ) from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping from ._compat import PYDANTIC_V1, model_copy, model_dump -from ._models import GenericModel, SecurityOptions, FinalRequestOptions, validate_type, construct_type +from ._models import GenericModel, FinalRequestOptions, SecurityOptions, validate_type, construct_type from ._response import ( APIResponse, BaseAPIResponse, @@ -86,6 +86,7 @@ APIConnectionError, APIResponseValidationError, ) +from ._legacy_response import LegacyAPIResponse from ._utils._json import openapi_dumps log: logging.Logger = logging.getLogger(__name__) @@ -436,32 +437,32 @@ def _auth_headers( self, security: SecurityOptions, # noqa: ARG002 ) -> dict[str, str]: - return {} - + return {} + def _auth_query( self, security: SecurityOptions, # noqa: ARG002 ) -> dict[str, str]: - return {} - + return {} + def _custom_auth( self, security: SecurityOptions, # noqa: ARG002 ) -> httpx.Auth | None: - return None - + return None + def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0) -> httpx.Headers: custom_headers = options.headers or {} headers_dict = _merge_mappings({**self._auth_headers(options.security), **self.default_headers}, custom_headers) self._validate_headers(headers_dict, custom_headers) - + # headers are case-insensitive while dictionaries are not. headers = httpx.Headers(headers_dict) - + idempotency_header = self._idempotency_header if idempotency_header and options.idempotency_key and idempotency_header not in headers: headers[idempotency_header] = options.idempotency_key - + # Don't set these headers if they were already set or removed by the caller. We check # `custom_headers`, which can contain `Omit()`, instead of `headers` to account for the removal case. lower_custom_headers = [header.lower() for header in custom_headers] @@ -473,7 +474,7 @@ def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0 timeout = timeout.read if timeout is not None: headers["x-stainless-read-timeout"] = str(timeout) - + return headers def _prepare_url(self, url: str) -> URL: @@ -513,7 +514,7 @@ def _build_request( ), ) kwargs: dict[str, Any] = {} - + json_data = options.json_data if options.extra_json is not None: if json_data is None: @@ -522,12 +523,12 @@ def _build_request( json_data = _merge_mappings(json_data, options.extra_json) else: raise RuntimeError(f"Unexpected JSON data type, {type(json_data)}, cannot merge with `extra_body`") - + headers = self._build_headers(options, retries_taken=retries_taken) params = _merge_mappings({**self._auth_query(options.security), **self.default_query}, options.params) content_type = headers.get("Content-Type") files = options.files - + # If the given Content-Type header is multipart/form-data then it # has to be removed so that httpx can generate the header with # additional information for us as it has to be in this form @@ -538,7 +539,7 @@ def _build_request( # only remove the header if the boundary hasn't been explicitly set # as the caller doesn't want httpx to come up with their own boundary headers.pop("Content-Type") - + # As we are now sending multipart/form-data instead of application/json # we need to tell httpx to use it, https://www.python-httpx.org/advanced/clients/#multipart-file-encoding if json_data: @@ -547,7 +548,7 @@ def _build_request( f"Expected query input to be a dictionary for multipart requests but got {type(json_data)} instead." ) kwargs["data"] = self._serialize_multipartform(json_data) - + # httpx determines whether or not to send a "multipart/form-data" # request based on the truthiness of the "files" argument. # This gets around that issue by generating a dict value that @@ -556,7 +557,7 @@ def _build_request( # https://github.com/encode/httpx/discussions/2399#discussioncomment-3814186 if not files: 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: @@ -565,9 +566,9 @@ def _build_request( if "_" in prepared_url.host: # work around https://github.com/encode/httpx/discussions/2880 kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")} - + is_body_allowed = options.method.lower() != "get" - + if is_body_allowed: if options.content is not None and json_data is not None: raise TypeError("Passing both `content` and `json_data` is not supported") @@ -585,7 +586,7 @@ def _build_request( else: headers.pop("Content-Type", None) kwargs.pop("data", None) - + # TODO: report this error to httpx return self._client.build_request( # pyright: ignore[reportUnknownMemberType] headers=headers, @@ -605,7 +606,7 @@ def _serialize_multipartform(self, data: Mapping[object, object]) -> dict[str, o # TODO: type ignore is required as stringify_items is well typed but we can't be # well typed without heavy validation. data, # type: ignore - array_format="brackets", + array_format="brackets" ) serialized: dict[str, object] = {} for key, value in items: @@ -693,7 +694,7 @@ def default_headers(self) -> dict[str, str | Omit]: "Content-Type": "application/json", "User-Agent": self.user_agent, **self.platform_headers(), - **self._custom_headers, + **self._custom_headers } @property @@ -1064,6 +1065,7 @@ def request( response.reason_phrase, response.headers, ) + try: response.raise_for_status() @@ -1124,6 +1126,8 @@ def _process_response( stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, retries_taken: int = 0, ) -> ResponseT: + + origin = get_origin(cast_to) or cast_to if ( @@ -1301,6 +1305,8 @@ def post( ) return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) + + def patch( self, path: str, @@ -1322,9 +1328,7 @@ def patch( DeprecationWarning, stacklevel=2, ) - opts = FinalRequestOptions.construct( - method="patch", url=path, json_data=body, content=content, files=to_httpx_files(files), **options - ) + opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, content=content, files=to_httpx_files(files), **options) return self.request(cast_to, opts) def put( @@ -1648,6 +1652,7 @@ async def request( response.reason_phrase, response.headers, ) + try: response.raise_for_status() @@ -1708,6 +1713,8 @@ async def _process_response( stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, retries_taken: int = 0, ) -> ResponseT: + + origin = get_origin(cast_to) or cast_to if ( @@ -1873,6 +1880,8 @@ async def post( ) return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls) + + async def patch( self, path: str, @@ -1894,14 +1903,7 @@ async def patch( DeprecationWarning, stacklevel=2, ) - opts = FinalRequestOptions.construct( - method="patch", - url=path, - json_data=body, - content=content, - files=await async_to_httpx_files(files), - **options, - ) + opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options) return await self.request(cast_to, opts) async def put( @@ -1965,17 +1967,7 @@ def get_api_list( return self._request_api_list(model, page, opts) -def make_request_options( - *, - query: Query | None = None, - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - idempotency_key: str | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - post_parser: PostParser | NotGiven = not_given, - security: SecurityOptions | None = None, -) -> RequestOptions: +def make_request_options(*, query: Query | None = None, extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, idempotency_key: str | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, post_parser: PostParser | NotGiven = not_given, security: SecurityOptions | None = None) -> RequestOptions: """Create a dict of type RequestOptions without keys of NotGiven values.""" options: RequestOptions = {} if extra_headers is not None: @@ -2001,7 +1993,7 @@ def make_request_options( options["post_parser"] = post_parser # type: ignore if security is not None: - options["security"] = security + options['security'] = security return options diff --git a/src/oz_agent_sdk/_client.py b/src/oz_agent_sdk/_client.py index 949709b..75ab68d 100644 --- a/src/oz_agent_sdk/_client.py +++ b/src/oz_agent_sdk/_client.py @@ -2,115 +2,111 @@ from __future__ import annotations +import httpx + import os -from typing import TYPE_CHECKING, Any, Mapping -from typing_extensions import Self, override -import httpx +from ._streaming import AsyncStream as AsyncStream, Stream as Stream + +from ._types import NotGiven, not_given + +from typing import Mapping, Any + +from ._exceptions import OzAPIError, APIStatusError + +from ._utils import is_mapping_t, get_async_library -from . import _exceptions -from ._qs import Querystring -from ._types import ( - Omit, - Timeout, - NotGiven, - Transport, - ProxiesTypes, - RequestOptions, - not_given, -) -from ._utils import ( - is_given, - is_mapping_t, - get_async_library, -) from ._compat import cached_property + +from typing_extensions import override, Self + from ._models import SecurityOptions + +from . import _exceptions + +import os +import asyncio +from typing_extensions import Literal + +import httpx + from ._version import __version__ -from ._streaming import Stream as Stream, AsyncStream as AsyncStream -from ._exceptions import OzAPIError, APIStatusError +from ._qs import Querystring +from ._utils import maybe_coerce_integer, maybe_coerce_float, maybe_coerce_boolean, is_given +from ._types import Omit, Timeout, Transport, ProxiesTypes, RequestOptions, Headers, NoneType, Query, Body from ._base_client import ( + DEFAULT_CONNECTION_LIMITS, + DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES, + ResponseT, + SyncHttpxClientWrapper, + AsyncHttpxClientWrapper, SyncAPIClient, AsyncAPIClient, + make_request_options, ) +from typing import TYPE_CHECKING + if TYPE_CHECKING: - from .resources import agent - from .resources.agent.agent import AgentResource, AsyncAgentResource + from .resources import agent + from .resources import agent + from .resources import agent + from .resources import agent + from .resources.agent.agent import AgentResource, AsyncAgentResource __all__ = ["Timeout", "Transport", "ProxiesTypes", "RequestOptions", "OzAPI", "AsyncOzAPI", "Client", "AsyncClient"] - class OzAPI(SyncAPIClient): # client options api_key: str - def __init__( - self, - *, - api_key: str | None = None, - base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = not_given, - max_retries: int = DEFAULT_MAX_RETRIES, - default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - # Configure a custom httpx client. - # We provide a `DefaultHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. - # See the [httpx documentation](https://www.python-httpx.org/api/#client) for more details. - http_client: httpx.Client | None = None, - # Enable or disable schema validation for data returned by the API. - # When enabled an error APIResponseValidationError is raised - # if the API responds with invalid data for the expected schema. - # - # This parameter may be removed or changed in the future. - # If you rely on this feature, please open a GitHub issue - # outlining your use-case to help us decide if it should be - # part of our public interface in the future. - _strict_response_validation: bool = False, - ) -> None: + def __init__(self, *, api_key: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, + # Configure a custom httpx client. + # We provide a `DefaultHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. + # See the [httpx documentation](https://www.python-httpx.org/api/#client) for more details. + http_client: httpx.Client | None = None, + # Enable or disable schema validation for data returned by the API. + # When enabled an error APIResponseValidationError is raised + # if the API responds with invalid data for the expected schema. + # + # This parameter may be removed or changed in the future. + # If you rely on this feature, please open a GitHub issue + # outlining your use-case to help us decide if it should be + # part of our public interface in the future. + _strict_response_validation: bool = False) -> None: """Construct a new synchronous OzAPI client instance. This automatically infers the `api_key` argument from the `WARP_API_KEY` environment variable if it is not provided. """ if api_key is None: - api_key = os.environ.get("WARP_API_KEY") + api_key = os.environ.get("WARP_API_KEY") if api_key is None: - raise OzAPIError( - "The api_key client option must be set either by passing api_key to the client or by setting the WARP_API_KEY environment variable" - ) + raise OzAPIError( + "The api_key client option must be set either by passing api_key to the client or by setting the WARP_API_KEY environment variable" + ) self.api_key = api_key if base_url is None: - base_url = os.environ.get("OZ_API_BASE_URL") + base_url = os.environ.get("OZ_API_BASE_URL") if base_url is None: - base_url = f"https://app.warp.dev/api/v1" + base_url = f"https://app.warp.dev/api/v1" custom_headers_env = os.environ.get("OZ_API_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, - max_retries=max_retries, - timeout=timeout, - http_client=http_client, - custom_headers=default_headers, - custom_query=default_query, - _strict_response_validation=_strict_response_validation, - ) + 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, max_retries=max_retries, timeout=timeout, http_client=http_client, custom_headers=default_headers, custom_query=default_query, _strict_response_validation=_strict_response_validation) @cached_property def agent(self) -> AgentResource: """Operations for running and managing cloud agents""" from .resources.agent import AgentResource - return AgentResource(self) @cached_property @@ -135,39 +131,32 @@ def _auth_headers(self, security: SecurityOptions) -> dict[str, str]: @property def _bearer_auth(self) -> dict[str, str]: api_key = self.api_key - return {"Authorization": f"Bearer {api_key}"} + return { + "Authorization": f"Bearer {api_key}" + } @property @override def default_headers(self) -> dict[str, str | Omit]: return { - **super().default_headers, - "X-Stainless-Async": "false", - **self._custom_headers, + **super().default_headers, + "X-Stainless-Async": "false", + **self._custom_headers, } - def copy( - self, - *, - api_key: str | None = None, - base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = not_given, - http_client: httpx.Client | None = None, - max_retries: int | NotGiven = not_given, - default_headers: Mapping[str, str] | None = None, - set_default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - set_default_query: Mapping[str, object] | None = None, - _extra_kwargs: Mapping[str, Any] = {}, - ) -> Self: + def copy(self, *, api_key: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, set_default_query: Mapping[str, object] | None = None, _extra_kwargs: Mapping[str, Any] = {}) -> Self: """ Create a new client instance re-using the same options given to the current client with optional overriding. """ if default_headers is not None and set_default_headers is not None: - raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive") + raise ValueError( + 'The `default_headers` and `set_default_headers` arguments are mutually exclusive' + ) if default_query is not None and set_default_query is not None: - raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive") + raise ValueError( + 'The `default_query` and `set_default_query` arguments are mutually exclusive' + ) headers = self._custom_headers if default_headers is not None: @@ -182,29 +171,14 @@ def copy( params = set_default_query http_client = http_client or self._client - return self.__class__( - api_key=api_key or self.api_key, - base_url=base_url or self.base_url, - timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, - http_client=http_client, - max_retries=max_retries if is_given(max_retries) else self.max_retries, - default_headers=headers, - default_query=params, - **_extra_kwargs, - ) + return self.__class__(api_key = api_key or self.api_key, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, max_retries=max_retries if is_given(max_retries) else self.max_retries, default_headers=headers, default_query=params, **_extra_kwargs) # Alias for `copy` for nicer inline usage, e.g. # client.with_options(timeout=10).foo.create(...) with_options = copy @override - def _make_status_error( - self, - err_msg: str, - *, - body: object, - response: httpx.Response, - ) -> APIStatusError: + def _make_status_error(self, err_msg: str, *, body: object, response: httpx.Response,) -> APIStatusError: if response.status_code == 400: return _exceptions.BadRequestError(err_msg, response=response, body=body) @@ -230,76 +204,56 @@ def _make_status_error( return _exceptions.InternalServerError(err_msg, response=response, body=body) return APIStatusError(err_msg, response=response, body=body) - class AsyncOzAPI(AsyncAPIClient): # client options api_key: str - def __init__( - self, - *, - api_key: str | None = None, - base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = not_given, - max_retries: int = DEFAULT_MAX_RETRIES, - default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - # Configure a custom httpx client. - # We provide a `DefaultAsyncHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. - # See the [httpx documentation](https://www.python-httpx.org/api/#asyncclient) for more details. - http_client: httpx.AsyncClient | None = None, - # Enable or disable schema validation for data returned by the API. - # When enabled an error APIResponseValidationError is raised - # if the API responds with invalid data for the expected schema. - # - # This parameter may be removed or changed in the future. - # If you rely on this feature, please open a GitHub issue - # outlining your use-case to help us decide if it should be - # part of our public interface in the future. - _strict_response_validation: bool = False, - ) -> None: + def __init__(self, *, api_key: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, + # Configure a custom httpx client. + # We provide a `DefaultAsyncHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. + # See the [httpx documentation](https://www.python-httpx.org/api/#asyncclient) for more details. + http_client: httpx.AsyncClient | None = None, + # Enable or disable schema validation for data returned by the API. + # When enabled an error APIResponseValidationError is raised + # if the API responds with invalid data for the expected schema. + # + # This parameter may be removed or changed in the future. + # If you rely on this feature, please open a GitHub issue + # outlining your use-case to help us decide if it should be + # part of our public interface in the future. + _strict_response_validation: bool = False) -> None: """Construct a new async AsyncOzAPI client instance. This automatically infers the `api_key` argument from the `WARP_API_KEY` environment variable if it is not provided. """ if api_key is None: - api_key = os.environ.get("WARP_API_KEY") + api_key = os.environ.get("WARP_API_KEY") if api_key is None: - raise OzAPIError( - "The api_key client option must be set either by passing api_key to the client or by setting the WARP_API_KEY environment variable" - ) + raise OzAPIError( + "The api_key client option must be set either by passing api_key to the client or by setting the WARP_API_KEY environment variable" + ) self.api_key = api_key if base_url is None: - base_url = os.environ.get("OZ_API_BASE_URL") + base_url = os.environ.get("OZ_API_BASE_URL") if base_url is None: - base_url = f"https://app.warp.dev/api/v1" + base_url = f"https://app.warp.dev/api/v1" custom_headers_env = os.environ.get("OZ_API_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, - max_retries=max_retries, - timeout=timeout, - http_client=http_client, - custom_headers=default_headers, - custom_query=default_query, - _strict_response_validation=_strict_response_validation, - ) + 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, max_retries=max_retries, timeout=timeout, http_client=http_client, custom_headers=default_headers, custom_query=default_query, _strict_response_validation=_strict_response_validation) @cached_property def agent(self) -> AsyncAgentResource: """Operations for running and managing cloud agents""" from .resources.agent import AsyncAgentResource - return AsyncAgentResource(self) @cached_property @@ -324,39 +278,32 @@ def _auth_headers(self, security: SecurityOptions) -> dict[str, str]: @property def _bearer_auth(self) -> dict[str, str]: api_key = self.api_key - return {"Authorization": f"Bearer {api_key}"} + return { + "Authorization": f"Bearer {api_key}" + } @property @override def default_headers(self) -> dict[str, str | Omit]: return { - **super().default_headers, - "X-Stainless-Async": f"async:{get_async_library()}", - **self._custom_headers, + **super().default_headers, + "X-Stainless-Async": f'async:{get_async_library()}', + **self._custom_headers, } - def copy( - self, - *, - api_key: str | None = None, - base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = not_given, - http_client: httpx.AsyncClient | None = None, - max_retries: int | NotGiven = not_given, - default_headers: Mapping[str, str] | None = None, - set_default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - set_default_query: Mapping[str, object] | None = None, - _extra_kwargs: Mapping[str, Any] = {}, - ) -> Self: + def copy(self, *, api_key: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, set_default_query: Mapping[str, object] | None = None, _extra_kwargs: Mapping[str, Any] = {}) -> Self: """ Create a new client instance re-using the same options given to the current client with optional overriding. """ if default_headers is not None and set_default_headers is not None: - raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive") + raise ValueError( + 'The `default_headers` and `set_default_headers` arguments are mutually exclusive' + ) if default_query is not None and set_default_query is not None: - raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive") + raise ValueError( + 'The `default_query` and `set_default_query` arguments are mutually exclusive' + ) headers = self._custom_headers if default_headers is not None: @@ -371,29 +318,14 @@ def copy( params = set_default_query http_client = http_client or self._client - return self.__class__( - api_key=api_key or self.api_key, - base_url=base_url or self.base_url, - timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, - http_client=http_client, - max_retries=max_retries if is_given(max_retries) else self.max_retries, - default_headers=headers, - default_query=params, - **_extra_kwargs, - ) + return self.__class__(api_key = api_key or self.api_key, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, max_retries=max_retries if is_given(max_retries) else self.max_retries, default_headers=headers, default_query=params, **_extra_kwargs) # Alias for `copy` for nicer inline usage, e.g. # client.with_options(timeout=10).foo.create(...) with_options = copy @override - def _make_status_error( - self, - err_msg: str, - *, - body: object, - response: httpx.Response, - ) -> APIStatusError: + def _make_status_error(self, err_msg: str, *, body: object, response: httpx.Response,) -> APIStatusError: if response.status_code == 400: return _exceptions.BadRequestError(err_msg, response=response, body=body) @@ -419,7 +351,6 @@ def _make_status_error( return _exceptions.InternalServerError(err_msg, response=response, body=body) return APIStatusError(err_msg, response=response, body=body) - class OzAPIWithRawResponse: _client: OzAPI @@ -430,10 +361,8 @@ def __init__(self, client: OzAPI) -> None: def agent(self) -> agent.AgentResourceWithRawResponse: """Operations for running and managing cloud agents""" from .resources.agent import AgentResourceWithRawResponse - return AgentResourceWithRawResponse(self._client.agent) - class AsyncOzAPIWithRawResponse: _client: AsyncOzAPI @@ -444,10 +373,8 @@ def __init__(self, client: AsyncOzAPI) -> None: def agent(self) -> agent.AsyncAgentResourceWithRawResponse: """Operations for running and managing cloud agents""" from .resources.agent import AsyncAgentResourceWithRawResponse - return AsyncAgentResourceWithRawResponse(self._client.agent) - class OzAPIWithStreamedResponse: _client: OzAPI @@ -458,10 +385,8 @@ def __init__(self, client: OzAPI) -> None: def agent(self) -> agent.AgentResourceWithStreamingResponse: """Operations for running and managing cloud agents""" from .resources.agent import AgentResourceWithStreamingResponse - return AgentResourceWithStreamingResponse(self._client.agent) - class AsyncOzAPIWithStreamedResponse: _client: AsyncOzAPI @@ -472,10 +397,8 @@ def __init__(self, client: AsyncOzAPI) -> None: def agent(self) -> agent.AsyncAgentResourceWithStreamingResponse: """Operations for running and managing cloud agents""" from .resources.agent import AsyncAgentResourceWithStreamingResponse - return AsyncAgentResourceWithStreamingResponse(self._client.agent) - Client = OzAPI -AsyncClient = AsyncOzAPI +AsyncClient = AsyncOzAPI \ No newline at end of file diff --git a/src/oz_agent_sdk/_compat.py b/src/oz_agent_sdk/_compat.py index e6690a4..2763563 100644 --- a/src/oz_agent_sdk/_compat.py +++ b/src/oz_agent_sdk/_compat.py @@ -156,12 +156,15 @@ def model_dump( exclude_defaults=exclude_defaults, # warnings are not supported in Pydantic v1 warnings=True if PYDANTIC_V1 else warnings, - **kwargs, + **kwargs ) return cast( "dict[str, Any]", model.dict( # pyright: ignore[reportDeprecated, reportUnnecessaryCast] - exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, by_alias=bool(by_alias) + exclude=exclude, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + by_alias=bool(by_alias) ), ) diff --git a/src/oz_agent_sdk/_constants.py b/src/oz_agent_sdk/_constants.py index 6ddf2c7..f32ba27 100644 --- a/src/oz_agent_sdk/_constants.py +++ b/src/oz_agent_sdk/_constants.py @@ -11,4 +11,4 @@ DEFAULT_CONNECTION_LIMITS = httpx.Limits(max_connections=100, max_keepalive_connections=20) INITIAL_RETRY_DELAY = 0.5 -MAX_RETRY_DELAY = 8.0 +MAX_RETRY_DELAY = 8.0 \ No newline at end of file diff --git a/src/oz_agent_sdk/_exceptions.py b/src/oz_agent_sdk/_exceptions.py index d84512f..541647b 100644 --- a/src/oz_agent_sdk/_exceptions.py +++ b/src/oz_agent_sdk/_exceptions.py @@ -2,26 +2,15 @@ from __future__ import annotations -from typing_extensions import Literal - import httpx -__all__ = [ - "BadRequestError", - "AuthenticationError", - "PermissionDeniedError", - "NotFoundError", - "ConflictError", - "UnprocessableEntityError", - "RateLimitError", - "InternalServerError", -] +from typing_extensions import Literal +__all__ = ["BadRequestError", "AuthenticationError", "PermissionDeniedError", "NotFoundError", "ConflictError", "UnprocessableEntityError", "RateLimitError", "InternalServerError"] class OzAPIError(Exception): pass - class APIError(OzAPIError): message: str request: httpx.Request @@ -43,7 +32,6 @@ def __init__(self, message: str, request: httpx.Request, *, body: object | None) self.message = message self.body = body - class APIResponseValidationError(APIError): response: httpx.Response status_code: int @@ -53,10 +41,8 @@ def __init__(self, response: httpx.Response, body: object | None, *, message: st self.response = response self.status_code = response.status_code - class APIStatusError(APIError): """Raised when an API response has a status code of 4xx or 5xx.""" - response: httpx.Response status_code: int @@ -65,44 +51,34 @@ def __init__(self, message: str, *, response: httpx.Response, body: object | Non self.response = response self.status_code = response.status_code - class APIConnectionError(APIError): def __init__(self, *, message: str = "Connection error.", request: httpx.Request) -> None: super().__init__(message, request, body=None) - class APITimeoutError(APIConnectionError): def __init__(self, request: httpx.Request) -> None: - super().__init__(message="Request timed out.", request=request) - + super().__init__(message= "Request timed out.", request=request) class BadRequestError(APIStatusError): - status_code: Literal[400] = 400 # pyright: ignore[reportIncompatibleVariableOverride] - + status_code: Literal[400] = 400 # pyright: ignore[reportIncompatibleVariableOverride] class AuthenticationError(APIStatusError): - status_code: Literal[401] = 401 # pyright: ignore[reportIncompatibleVariableOverride] - + status_code: Literal[401] = 401 # pyright: ignore[reportIncompatibleVariableOverride] class PermissionDeniedError(APIStatusError): - status_code: Literal[403] = 403 # pyright: ignore[reportIncompatibleVariableOverride] - + status_code: Literal[403] = 403 # pyright: ignore[reportIncompatibleVariableOverride] class NotFoundError(APIStatusError): - status_code: Literal[404] = 404 # pyright: ignore[reportIncompatibleVariableOverride] - + status_code: Literal[404] = 404 # pyright: ignore[reportIncompatibleVariableOverride] class ConflictError(APIStatusError): - status_code: Literal[409] = 409 # pyright: ignore[reportIncompatibleVariableOverride] - + status_code: Literal[409] = 409 # pyright: ignore[reportIncompatibleVariableOverride] class UnprocessableEntityError(APIStatusError): - status_code: Literal[422] = 422 # pyright: ignore[reportIncompatibleVariableOverride] - + status_code: Literal[422] = 422 # pyright: ignore[reportIncompatibleVariableOverride] class RateLimitError(APIStatusError): - status_code: Literal[429] = 429 # pyright: ignore[reportIncompatibleVariableOverride] - + status_code: Literal[429] = 429 # pyright: ignore[reportIncompatibleVariableOverride] class InternalServerError(APIStatusError): - pass + pass \ No newline at end of file diff --git a/src/oz_agent_sdk/_models.py b/src/oz_agent_sdk/_models.py index 69f41a6..cd1d14e 100644 --- a/src/oz_agent_sdk/_models.py +++ b/src/oz_agent_sdk/_models.py @@ -1,33 +1,23 @@ from __future__ import annotations +from typing_extensions import TypedDict + import os import inspect import weakref -from typing import ( - IO, - TYPE_CHECKING, - Any, - Type, - Union, - Generic, - TypeVar, - Callable, - Iterable, - Optional, - AsyncIterable, - cast, -) +from typing import IO, TYPE_CHECKING, Any, AsyncIterable, AsyncIterable, Iterable, Type, Union, Generic, TypeVar, Callable, Optional, cast from datetime import date, datetime from typing_extensions import ( + Annotated, + TypeAlias, + Self, List, Unpack, Literal, ClassVar, Protocol, Required, - Annotated, ParamSpec, - TypeAlias, TypedDict, TypeGuard, final, @@ -98,12 +88,10 @@ P = ParamSpec("P") - @runtime_checkable class _ConfigProtocol(Protocol): allow_population_by_field_name: bool - class BaseModel(pydantic.BaseModel): if PYDANTIC_V1: @@ -405,7 +393,6 @@ def model_dump_json( exclude_none=exclude_none, ) - class _EagerIterable(list[_T], Generic[_T]): """ Accepts any Iterable[T] input (including generators), consumes it @@ -472,10 +459,8 @@ def _serialize(v: Iterable[_T]) -> list[_T]: return v return list(v) - EagerIterable: TypeAlias = Annotated[Iterable[_T], _EagerIterable] - def _construct_field(value: object, field: FieldInfo, key: str) -> object: if value is None: return field_get_default(field) @@ -490,7 +475,6 @@ def _construct_field(value: object, field: FieldInfo, key: str) -> object: return construct_type(value=value, type_=type_, metadata=getattr(field, "metadata", None)) - def _get_extra_fields_type(cls: type[pydantic.BaseModel]) -> type | None: if PYDANTIC_V1: # TODO @@ -507,7 +491,6 @@ def _get_extra_fields_type(cls: type[pydantic.BaseModel]) -> type | None: return None - def is_basemodel(type_: type) -> bool: """Returns whether or not the given type is either a `BaseModel` or a union of `BaseModel`""" if is_union(type_): @@ -519,14 +502,12 @@ def is_basemodel(type_: type) -> bool: return is_basemodel_type(type_) - def is_basemodel_type(type_: type) -> TypeGuard[type[BaseModel] | type[GenericModel]]: origin = get_origin(type_) or type_ if not inspect.isclass(origin): return False return issubclass(origin, BaseModel) or issubclass(origin, GenericModel) - def build( base_model_cls: Callable[P, _BaseModelT], *args: P.args, @@ -549,7 +530,6 @@ def build( return cast(_BaseModelT, construct_type(type_=base_model_cls, value=kwargs)) - def construct_type_unchecked(*, value: object, type_: type[_T]) -> _T: """Loose coercion to the expected type with construction of nested values. @@ -558,7 +538,6 @@ def construct_type_unchecked(*, value: object, type_: type[_T]) -> _T: """ return cast(_T, construct_type(value=value, type_=type_)) - def construct_type(*, value: object, type_: object, metadata: Optional[List[Any]] = None) -> object: """Loose coercion to the expected type with construction of nested values. @@ -678,15 +657,12 @@ def construct_type(*, value: object, type_: object, metadata: Optional[List[Any] return value - @runtime_checkable class CachedDiscriminatorType(Protocol): __discriminator__: DiscriminatorDetails - DISCRIMINATOR_CACHE: weakref.WeakKeyDictionary[type, DiscriminatorDetails] = weakref.WeakKeyDictionary() - class DiscriminatorDetails: field_name: str """The name of the discriminator field in the variant class, e.g. @@ -727,7 +703,6 @@ def __init__( self.field_name = discriminator_field self.field_alias_from = discriminator_alias - def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, ...]) -> DiscriminatorDetails | None: cached = DISCRIMINATOR_CACHE.get(union) if cached is not None: @@ -787,7 +762,6 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, DISCRIMINATOR_CACHE.setdefault(union, details) return details - def _extract_field_schema_pv2(model: type[BaseModel], field_name: str) -> ModelField | None: schema = model.__pydantic_core_schema__ if schema["type"] == "definitions": @@ -808,7 +782,6 @@ def _extract_field_schema_pv2(model: type[BaseModel], field_name: str) -> ModelF return cast("ModelField", field) # pyright: ignore[reportUnnecessaryCast] - def validate_type(*, type_: type[_T], value: object) -> _T: """Strict validation that the given value matches the expected type""" if inspect.isclass(type_) and issubclass(type_, pydantic.BaseModel): @@ -816,7 +789,6 @@ def validate_type(*, type_: type[_T], value: object) -> _T: return cast(_T, _validate_non_model_type(type_=type_, value=value)) - def set_pydantic_config(typ: Any, config: pydantic.ConfigDict) -> None: """Add a pydantic config for the given type. @@ -824,7 +796,6 @@ def set_pydantic_config(typ: Any, config: pydantic.ConfigDict) -> None: """ setattr(typ, "__pydantic_config__", config) # noqa: B010 - # our use of subclassing here causes weirdness for type checkers, # so we just pretend that we don't subclass if TYPE_CHECKING: @@ -834,7 +805,6 @@ def set_pydantic_config(typ: Any, config: pydantic.ConfigDict) -> None: class GenericModel(BaseGenericModel, BaseModel): pass - if not PYDANTIC_V1: from pydantic import TypeAdapter as _TypeAdapter @@ -870,11 +840,9 @@ def _validate_non_model_type(*, type_: type[_T], value: object) -> _T: def _create_pydantic_model(type_: _T) -> Type[RootModel[_T]]: return RootModel[type_] # type: ignore - class SecurityOptions(TypedDict, total=False): bearer_auth: bool - class FinalRequestOptionsInput(TypedDict, total=False): method: Required[str] url: Required[str] @@ -890,7 +858,6 @@ class FinalRequestOptionsInput(TypedDict, total=False): follow_redirects: bool security: SecurityOptions - @final class FinalRequestOptions(pydantic.BaseModel): method: str @@ -903,7 +870,9 @@ class FinalRequestOptions(pydantic.BaseModel): idempotency_key: Union[str, None] = None post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven() follow_redirects: Union[bool, None] = None - security: SecurityOptions = {"bearer_auth": True} + security: SecurityOptions = { + "bearer_auth": True + } content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None] = None # It should be noted that we cannot use `json` here as that would override @@ -955,4 +924,4 @@ def construct( # type: ignore if not TYPE_CHECKING: # type checkers incorrectly complain about this assignment - model_construct = construct + model_construct = construct \ No newline at end of file diff --git a/src/oz_agent_sdk/_qs.py b/src/oz_agent_sdk/_qs.py index 4127c19..92464ff 100644 --- a/src/oz_agent_sdk/_qs.py +++ b/src/oz_agent_sdk/_qs.py @@ -4,7 +4,7 @@ from urllib.parse import parse_qs, urlencode from typing_extensions import get_args -from ._types import NotGiven, ArrayFormat, NestedFormat, not_given +from ._types import ArrayFormat, NestedFormat, not_given, NotGiven from ._utils import flatten _T = TypeVar("_T") diff --git a/src/oz_agent_sdk/_resource.py b/src/oz_agent_sdk/_resource.py index b875682..a94a9d7 100644 --- a/src/oz_agent_sdk/_resource.py +++ b/src/oz_agent_sdk/_resource.py @@ -3,13 +3,13 @@ from __future__ import annotations import time -from typing import TYPE_CHECKING import anyio -if TYPE_CHECKING: - from ._client import OzAPI, AsyncOzAPI +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from ._client import OzAPI, AsyncOzAPI class SyncAPIResource: _client: OzAPI @@ -24,8 +24,7 @@ def __init__(self, client: OzAPI) -> None: self._get_api_list = client.get_api_list def _sleep(self, seconds: float) -> None: - time.sleep(seconds) - + time.sleep(seconds) class AsyncAPIResource: _client: AsyncOzAPI @@ -40,4 +39,4 @@ def __init__(self, client: AsyncOzAPI) -> None: self._get_api_list = client.get_api_list async def _sleep(self, seconds: float) -> None: - await anyio.sleep(seconds) + await anyio.sleep(seconds) \ No newline at end of file diff --git a/src/oz_agent_sdk/_response.py b/src/oz_agent_sdk/_response.py index 4781d7c..c5e15aa 100644 --- a/src/oz_agent_sdk/_response.py +++ b/src/oz_agent_sdk/_response.py @@ -25,12 +25,14 @@ import pydantic from ._types import NoneType -from ._utils import is_given, extract_type_arg, is_annotated_type, is_type_alias_type, extract_type_var_from_base +from ._utils import is_given, extract_type_arg, is_annotated_type, extract_type_var_from_base, is_type_alias_type +from ._streaming import extract_stream_chunk_type from ._models import BaseModel, is_basemodel from ._constants import RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER from ._streaming import Stream, AsyncStream, is_stream_class_type, extract_stream_chunk_type from ._exceptions import OzAPIError, APIResponseValidationError + if TYPE_CHECKING: from ._models import FinalRequestOptions from ._base_client import BaseClient @@ -138,6 +140,8 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: origin = get_origin(cast_to) or cast_to + + if self._is_sse_stream: if to: if not is_stream_class_type(to): @@ -200,6 +204,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: if cast_to == bool: return cast(R, response.text.lower() == "true") + if origin == APIResponse: raise RuntimeError("Unexpected state - cast_to is `APIResponse`") @@ -273,6 +278,8 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: class APIResponse(BaseAPIResponse[R]): + + @overload def parse(self, *, to: type[_T]) -> _T: ... @@ -375,6 +382,8 @@ def iter_lines(self) -> Iterator[str]: class AsyncAPIResponse(BaseAPIResponse[R]): + + @overload async def parse(self, *, to: type[_T]) -> _T: ... diff --git a/src/oz_agent_sdk/_streaming.py b/src/oz_agent_sdk/_streaming.py index dbfe0f8..944e14d 100644 --- a/src/oz_agent_sdk/_streaming.py +++ b/src/oz_agent_sdk/_streaming.py @@ -4,16 +4,18 @@ import json import inspect from types import TracebackType -from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, Optional, AsyncIterator, cast +from typing import TYPE_CHECKING, Optional, Any, Generic, TypeVar, Iterator, AsyncIterator, cast from typing_extensions import Self, Protocol, TypeGuard, override, get_origin, runtime_checkable import httpx -from ._utils import extract_type_var_from_base +from ._utils import is_mapping, is_dict, extract_type_var_from_base +from ._exceptions import APIError +from ._response import APIResponse, AsyncAPIResponse if TYPE_CHECKING: - from ._client import OzAPI, AsyncOzAPI from ._models import FinalRequestOptions + from ._client import OzAPI, AsyncOzAPI _T = TypeVar("_T") @@ -56,7 +58,7 @@ def __stream__(self) -> Iterator[_T]: response = self.response process_data = self._client._process_response_data iterator = self._iter_events() - + try: for sse in iterator: yield process_data(data=sse.json(), cast_to=cast_to, response=response) @@ -122,7 +124,7 @@ async def __stream__(self) -> AsyncIterator[_T]: response = self.response process_data = self._client._process_response_data iterator = self._iter_events() - + try: async for sse in iterator: yield process_data(data=sse.json(), cast_to=cast_to, response=response) diff --git a/src/oz_agent_sdk/_types.py b/src/oz_agent_sdk/_types.py index 09db394..ba9f701 100644 --- a/src/oz_agent_sdk/_types.py +++ b/src/oz_agent_sdk/_types.py @@ -5,7 +5,9 @@ IO, TYPE_CHECKING, Any, + AsyncIterable, Dict, + Iterable, List, Type, Tuple, @@ -13,23 +15,12 @@ Mapping, TypeVar, Callable, - Iterable, Iterator, Optional, Sequence, - AsyncIterable, -) -from typing_extensions import ( - Set, - Literal, - Protocol, - TypeAlias, - TypedDict, - SupportsIndex, - overload, - override, - runtime_checkable, + ) +from typing_extensions import Set, SupportsIndex, Literal, Protocol, TypeAlias, TypedDict, overload, override, runtime_checkable import httpx import pydantic @@ -38,6 +29,7 @@ if TYPE_CHECKING: from ._models import BaseModel, SecurityOptions from ._response import APIResponse, AsyncAPIResponse + from ._legacy_response import HttpxBinaryResponseContent Transport = BaseTransport AsyncTransport = AsyncBaseTransport @@ -141,7 +133,6 @@ class NotGiven: ```py def create(timeout: Timeout | None | NotGiven = not_given): ... - create(timeout=1) # 1s timeout create(timeout=None) # No timeout create() # Default timeout behavior diff --git a/src/oz_agent_sdk/_utils/__init__.py b/src/oz_agent_sdk/_utils/__init__.py index 1c090e5..2594310 100644 --- a/src/oz_agent_sdk/_utils/__init__.py +++ b/src/oz_agent_sdk/_utils/__init__.py @@ -1,4 +1,3 @@ -from ._path import path_template as path_template from ._sync import asyncify as asyncify from ._proxy import LazyProxy as LazyProxy from ._utils import ( @@ -62,3 +61,4 @@ assert_signatures_in_sync as assert_signatures_in_sync, ) from ._datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime +from ._path import path_template as path_template diff --git a/src/oz_agent_sdk/_utils/_resources_proxy.py b/src/oz_agent_sdk/_utils/_resources_proxy.py index 961a666..30be4ee 100644 --- a/src/oz_agent_sdk/_utils/_resources_proxy.py +++ b/src/oz_agent_sdk/_utils/_resources_proxy.py @@ -16,7 +16,6 @@ class ResourcesProxy(LazyProxy[Any]): @override def __load__(self) -> Any: import importlib - mod = importlib.import_module("oz_agent_sdk.resources") return mod diff --git a/src/oz_agent_sdk/_utils/_sync.py b/src/oz_agent_sdk/_utils/_sync.py index f6027c1..fdcdf5f 100644 --- a/src/oz_agent_sdk/_utils/_sync.py +++ b/src/oz_agent_sdk/_utils/_sync.py @@ -1,8 +1,10 @@ from __future__ import annotations +import sys import asyncio import functools -from typing import TypeVar, Callable, Awaitable +import contextvars +from typing import Any, TypeVar, Callable, Awaitable from typing_extensions import ParamSpec import anyio diff --git a/src/oz_agent_sdk/_utils/_transform.py b/src/oz_agent_sdk/_utils/_transform.py index 5207549..941ebb7 100644 --- a/src/oz_agent_sdk/_utils/_transform.py +++ b/src/oz_agent_sdk/_utils/_transform.py @@ -12,21 +12,21 @@ from ._utils import ( is_list, + is_sequence, is_given, lru_cache, is_mapping, is_iterable, - is_sequence, ) from .._files import is_base64_file_input from ._compat import get_origin, is_typeddict from ._typing import ( is_list_type, + is_sequence_type, is_union_type, extract_type_arg, is_iterable_type, is_required_type, - is_sequence_type, is_annotated_type, strip_annotated_type, ) diff --git a/src/oz_agent_sdk/_utils/_utils.py b/src/oz_agent_sdk/_utils/_utils.py index 199cd23..ed33f38 100644 --- a/src/oz_agent_sdk/_utils/_utils.py +++ b/src/oz_agent_sdk/_utils/_utils.py @@ -21,7 +21,7 @@ import sniffio -from .._types import Omit, NotGiven, FileTypes, ArrayFormat, HeadersLike +from .._types import ArrayFormat, NotGiven, FileTypes, HeadersLike, Omit _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) @@ -54,7 +54,9 @@ def extract_files( """ files: list[tuple[str, FileTypes]] = [] for path in paths: - files.extend(_extract_items(query, path, index=0, flattened_key=None, array_format=array_format)) + files.extend( + _extract_items(query, path, index=0, flattened_key=None, array_format=array_format) + ) return files @@ -141,7 +143,8 @@ def _extract_items( path, index=index, flattened_key=( - (flattened_key if flattened_key is not None else "") + _array_suffix(array_format, array_index) + (flattened_key if flattened_key is not None else "") + + _array_suffix(array_format, array_index) ), array_format=array_format, ) diff --git a/src/oz_agent_sdk/_version.py b/src/oz_agent_sdk/_version.py index 1762ab1..7565cbc 100644 --- a/src/oz_agent_sdk/_version.py +++ b/src/oz_agent_sdk/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "oz_agent_sdk" -__version__ = "0.13.0" # x-release-please-version +__version__ = "0.13.0" # x-release-please-version \ No newline at end of file diff --git a/src/oz_agent_sdk/pagination.py b/src/oz_agent_sdk/pagination.py index 3f925ea..a682efa 100644 --- a/src/oz_agent_sdk/pagination.py +++ b/src/oz_agent_sdk/pagination.py @@ -1,22 +1,29 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Generic, TypeVar, Optional +from typing import TypeVar, Optional, Generic, List + +from ._models import BaseModel + from typing_extensions import override +import re +from typing_extensions import TypedDict, Literal, Annotated, Protocol, runtime_checkable + +from httpx import URL, Response + from ._models import BaseModel -from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage +from ._utils import PropertyInfo, is_mapping +from ._base_client import BasePage, BaseSyncPage, BaseAsyncPage, PageInfo __all__ = ["RunsCursorPagePageInfo", "SyncRunsCursorPage", "AsyncRunsCursorPage"] -_T = TypeVar("_T") - +_T = TypeVar('_T') class RunsCursorPagePageInfo(BaseModel): has_next_page: Optional[bool] = None next_cursor: Optional[str] = None - class SyncRunsCursorPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]): runs: List[_T] page_info: Optional[RunsCursorPagePageInfo] = None @@ -31,26 +38,25 @@ def _get_page_items(self) -> List[_T]: @override def has_next_page(self) -> bool: has_next_page = None - if self.page_info is not None: - if self.page_info.has_next_page is not None: - has_next_page = self.page_info.has_next_page + if self.page_info is not None : + if self.page_info.has_next_page is not None : + has_next_page = self.page_info.has_next_page if has_next_page is not None and has_next_page is False: - return False + return False return super().has_next_page() @override def next_page_info(self) -> Optional[PageInfo]: next_cursor = None - if self.page_info is not None: - if self.page_info.next_cursor is not None: - next_cursor = self.page_info.next_cursor + if self.page_info is not None : + if self.page_info.next_cursor is not None : + next_cursor = self.page_info.next_cursor if not next_cursor: - return None + return None return PageInfo(params={"cursor": next_cursor}) - class AsyncRunsCursorPage(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): runs: List[_T] page_info: Optional[RunsCursorPagePageInfo] = None @@ -65,21 +71,21 @@ def _get_page_items(self) -> List[_T]: @override def has_next_page(self) -> bool: has_next_page = None - if self.page_info is not None: - if self.page_info.has_next_page is not None: - has_next_page = self.page_info.has_next_page + if self.page_info is not None : + if self.page_info.has_next_page is not None : + has_next_page = self.page_info.has_next_page if has_next_page is not None and has_next_page is False: - return False + return False return super().has_next_page() @override def next_page_info(self) -> Optional[PageInfo]: next_cursor = None - if self.page_info is not None: - if self.page_info.next_cursor is not None: - next_cursor = self.page_info.next_cursor + if self.page_info is not None : + if self.page_info.next_cursor is not None : + next_cursor = self.page_info.next_cursor if not next_cursor: - return None + return None - return PageInfo(params={"cursor": next_cursor}) + return PageInfo(params={"cursor": next_cursor}) \ No newline at end of file diff --git a/src/oz_agent_sdk/resources/__init__.py b/src/oz_agent_sdk/resources/__init__.py index 38032a4..874bf62 100644 --- a/src/oz_agent_sdk/resources/__init__.py +++ b/src/oz_agent_sdk/resources/__init__.py @@ -1,19 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .agent import ( - AgentResource, - AsyncAgentResource, - AgentResourceWithRawResponse, - AsyncAgentResourceWithRawResponse, - AgentResourceWithStreamingResponse, - AsyncAgentResourceWithStreamingResponse, -) +from .agent import AgentResource, AsyncAgentResource, AgentResourceWithRawResponse, AsyncAgentResourceWithRawResponse, AgentResourceWithStreamingResponse, AsyncAgentResourceWithStreamingResponse -__all__ = [ - "AgentResource", - "AsyncAgentResource", - "AgentResourceWithRawResponse", - "AsyncAgentResourceWithRawResponse", - "AgentResourceWithStreamingResponse", - "AsyncAgentResourceWithStreamingResponse", -] +__all__ = ["AgentResource", "AsyncAgentResource", "AgentResourceWithRawResponse", "AsyncAgentResourceWithRawResponse", "AgentResourceWithStreamingResponse", "AsyncAgentResourceWithStreamingResponse"] \ No newline at end of file diff --git a/src/oz_agent_sdk/resources/agent/__init__.py b/src/oz_agent_sdk/resources/agent/__init__.py index 69e9075..b653809 100644 --- a/src/oz_agent_sdk/resources/agent/__init__.py +++ b/src/oz_agent_sdk/resources/agent/__init__.py @@ -1,75 +1,9 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .runs import ( - RunsResource, - AsyncRunsResource, - RunsResourceWithRawResponse, - AsyncRunsResourceWithRawResponse, - RunsResourceWithStreamingResponse, - AsyncRunsResourceWithStreamingResponse, -) -from .agent import ( - AgentResource, - AsyncAgentResource, - AgentResourceWithRawResponse, - AsyncAgentResourceWithRawResponse, - AgentResourceWithStreamingResponse, - AsyncAgentResourceWithStreamingResponse, -) -from .sessions import ( - SessionsResource, - AsyncSessionsResource, - SessionsResourceWithRawResponse, - AsyncSessionsResourceWithRawResponse, - SessionsResourceWithStreamingResponse, - AsyncSessionsResourceWithStreamingResponse, -) -from .schedules import ( - SchedulesResource, - AsyncSchedulesResource, - SchedulesResourceWithRawResponse, - AsyncSchedulesResourceWithRawResponse, - SchedulesResourceWithStreamingResponse, - AsyncSchedulesResourceWithStreamingResponse, -) -from .conversations import ( - ConversationsResource, - AsyncConversationsResource, - ConversationsResourceWithRawResponse, - AsyncConversationsResourceWithRawResponse, - ConversationsResourceWithStreamingResponse, - AsyncConversationsResourceWithStreamingResponse, -) +from .runs import RunsResource, AsyncRunsResource, RunsResourceWithRawResponse, AsyncRunsResourceWithRawResponse, RunsResourceWithStreamingResponse, AsyncRunsResourceWithStreamingResponse +from .schedules import SchedulesResource, AsyncSchedulesResource, SchedulesResourceWithRawResponse, AsyncSchedulesResourceWithRawResponse, SchedulesResourceWithStreamingResponse, AsyncSchedulesResourceWithStreamingResponse +from .sessions import SessionsResource, AsyncSessionsResource, SessionsResourceWithRawResponse, AsyncSessionsResourceWithRawResponse, SessionsResourceWithStreamingResponse, AsyncSessionsResourceWithStreamingResponse +from .conversations import ConversationsResource, AsyncConversationsResource, ConversationsResourceWithRawResponse, AsyncConversationsResourceWithRawResponse, ConversationsResourceWithStreamingResponse, AsyncConversationsResourceWithStreamingResponse +from .agent import AgentResource, AsyncAgentResource, AgentResourceWithRawResponse, AsyncAgentResourceWithRawResponse, AgentResourceWithStreamingResponse, AsyncAgentResourceWithStreamingResponse -__all__ = [ - "RunsResource", - "AsyncRunsResource", - "RunsResourceWithRawResponse", - "AsyncRunsResourceWithRawResponse", - "RunsResourceWithStreamingResponse", - "AsyncRunsResourceWithStreamingResponse", - "SchedulesResource", - "AsyncSchedulesResource", - "SchedulesResourceWithRawResponse", - "AsyncSchedulesResourceWithRawResponse", - "SchedulesResourceWithStreamingResponse", - "AsyncSchedulesResourceWithStreamingResponse", - "SessionsResource", - "AsyncSessionsResource", - "SessionsResourceWithRawResponse", - "AsyncSessionsResourceWithRawResponse", - "SessionsResourceWithStreamingResponse", - "AsyncSessionsResourceWithStreamingResponse", - "ConversationsResource", - "AsyncConversationsResource", - "ConversationsResourceWithRawResponse", - "AsyncConversationsResourceWithRawResponse", - "ConversationsResourceWithStreamingResponse", - "AsyncConversationsResourceWithStreamingResponse", - "AgentResource", - "AsyncAgentResource", - "AgentResourceWithRawResponse", - "AsyncAgentResourceWithRawResponse", - "AgentResourceWithStreamingResponse", - "AsyncAgentResourceWithStreamingResponse", -] +__all__ = ["RunsResource", "AsyncRunsResource", "RunsResourceWithRawResponse", "AsyncRunsResourceWithRawResponse", "RunsResourceWithStreamingResponse", "AsyncRunsResourceWithStreamingResponse", "SchedulesResource", "AsyncSchedulesResource", "SchedulesResourceWithRawResponse", "AsyncSchedulesResourceWithRawResponse", "SchedulesResourceWithStreamingResponse", "AsyncSchedulesResourceWithStreamingResponse", "SessionsResource", "AsyncSessionsResource", "SessionsResourceWithRawResponse", "AsyncSessionsResourceWithRawResponse", "SessionsResourceWithStreamingResponse", "AsyncSessionsResourceWithStreamingResponse", "ConversationsResource", "AsyncConversationsResource", "ConversationsResourceWithRawResponse", "AsyncConversationsResourceWithRawResponse", "ConversationsResourceWithStreamingResponse", "AsyncConversationsResourceWithStreamingResponse", "AgentResource", "AsyncAgentResource", "AgentResourceWithRawResponse", "AsyncAgentResourceWithRawResponse", "AgentResourceWithStreamingResponse", "AsyncAgentResourceWithStreamingResponse"] \ No newline at end of file diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index 6910539..d2d8e98 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -2,68 +2,57 @@ from __future__ import annotations -from typing import Any, Iterable, cast -from typing_extensions import Literal - import httpx -from . import agent_ as agent -from .runs import ( - RunsResource, - AsyncRunsResource, - RunsResourceWithRawResponse, - AsyncRunsResourceWithRawResponse, - RunsResourceWithStreamingResponse, - AsyncRunsResourceWithStreamingResponse, -) -from ...types import agent_run_params, agent_list_params, agent_list_environments_params -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform -from .sessions import ( - SessionsResource, - AsyncSessionsResource, - SessionsResourceWithRawResponse, - AsyncSessionsResourceWithRawResponse, - SessionsResourceWithStreamingResponse, - AsyncSessionsResourceWithStreamingResponse, -) -from ..._compat import cached_property -from .schedules import ( - SchedulesResource, - AsyncSchedulesResource, - SchedulesResourceWithRawResponse, - AsyncSchedulesResourceWithRawResponse, - SchedulesResourceWithStreamingResponse, - AsyncSchedulesResourceWithStreamingResponse, -) from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from .conversations import ( - ConversationsResource, - AsyncConversationsResource, - ConversationsResourceWithRawResponse, - AsyncConversationsResourceWithRawResponse, - ConversationsResourceWithStreamingResponse, - AsyncConversationsResourceWithStreamingResponse, -) -from ..._base_client import make_request_options -from ...types.agent_run_response import AgentRunResponse + +from .runs import RunsResource, AsyncRunsResource, RunsResourceWithRawResponse, AsyncRunsResourceWithRawResponse, RunsResourceWithStreamingResponse, AsyncRunsResourceWithStreamingResponse + +from ..._compat import cached_property + +from .schedules import SchedulesResource, AsyncSchedulesResource, SchedulesResourceWithRawResponse, AsyncSchedulesResourceWithRawResponse, SchedulesResourceWithStreamingResponse, AsyncSchedulesResourceWithStreamingResponse + +from .sessions import SessionsResource, AsyncSessionsResource, SessionsResourceWithRawResponse, AsyncSessionsResourceWithRawResponse, SessionsResourceWithStreamingResponse, AsyncSessionsResourceWithStreamingResponse + +from .conversations import ConversationsResource, AsyncConversationsResource, ConversationsResourceWithRawResponse, AsyncConversationsResourceWithRawResponse, ConversationsResourceWithStreamingResponse, AsyncConversationsResourceWithStreamingResponse + from ...types.agent_list_response import AgentListResponse -from ...types.ambient_agent_config_param import AmbientAgentConfigParam + +from ..._base_client import make_request_options + +from ..._utils import maybe_transform, path_template, async_maybe_transform + +from ..._types import Omit, omit, NotGiven + +from typing_extensions import Literal + from ...types.agent_get_artifact_response import AgentGetArtifactResponse + +from typing import Any, cast, Iterable + from ...types.agent_list_environments_response import AgentListEnvironmentsResponse -__all__ = ["AgentResource", "AsyncAgentResource"] +from ...types.agent_run_response import AgentRunResponse + +from ...types.ambient_agent_config_param import AmbientAgentConfigParam + +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper, to_streamed_response_wrapper, async_to_streamed_response_wrapper +from . import agent_ as agent + +from ...types import agent_run_params + +from typing_extensions import Literal, overload +from ..._types import Timeout, Headers, NotGiven, not_given, Omit, omit, NoneType, Query, Body +from ...types import agent_list_params +from ...types import agent_list_environments_params +from ...types import agent_run_params +from ...types import AmbientAgentConfig + +__all__ = ["AgentResource", "AsyncAgentResource"] class AgentResource(SyncAPIResource): """Operations for running and managing cloud agents""" - @cached_property def runs(self) -> RunsResource: """Operations for running and managing cloud agents""" @@ -108,20 +97,18 @@ def with_streaming_response(self) -> AgentResourceWithStreamingResponse: """ return AgentResourceWithStreamingResponse(self) - def list( - self, - *, - include_malformed_skills: bool | Omit = omit, - refresh: bool | Omit = omit, - repo: str | Omit = omit, - sort_by: Literal["name", "last_run"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentListResponse: + def list(self, + *, + include_malformed_skills: bool | Omit = omit, + refresh: bool | Omit = omit, + repo: str | Omit = omit, + sort_by: Literal["name", "last_run"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentListResponse: """ Retrieve a list of available agents (skills) that can be used to run tasks. Agents are discovered from environments or a specific repository. @@ -152,35 +139,24 @@ def list( """ return self._get( "/agent", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "include_malformed_skills": include_malformed_skills, - "refresh": refresh, - "repo": repo, - "sort_by": sort_by, - }, - agent_list_params.AgentListParams, - ), - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({ + "include_malformed_skills": include_malformed_skills, + "refresh": refresh, + "repo": repo, + "sort_by": sort_by, + }, agent_list_params.AgentListParams)), cast_to=AgentListResponse, ) - def get_artifact( - self, - artifact_uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentGetArtifactResponse: + def get_artifact(self, + artifact_uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentGetArtifactResponse: """Retrieve an artifact by its UUID. For downloadable file-like artifacts, returns @@ -197,31 +173,24 @@ def get_artifact( timeout: Override the client-level default timeout for this request, in seconds """ if not artifact_uid: - raise ValueError(f"Expected a non-empty value for `artifact_uid` but received {artifact_uid!r}") - return cast( - AgentGetArtifactResponse, - self._get( - path_template("/agent/artifacts/{artifact_uid}", artifact_uid=artifact_uid), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast( - Any, AgentGetArtifactResponse - ), # Union types cannot be passed in as arguments in the type system - ), - ) - - def list_environments( - self, - *, - sort_by: Literal["name", "last_updated"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentListEnvironmentsResponse: + raise ValueError( + f'Expected a non-empty value for `artifact_uid` but received {artifact_uid!r}' + ) + return cast(AgentGetArtifactResponse, self._get( + path_template("/agent/artifacts/{artifact_uid}", artifact_uid=artifact_uid), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + cast_to=cast(Any, AgentGetArtifactResponse), # Union types cannot be passed in as arguments in the type system + )) + + def list_environments(self, + *, + sort_by: Literal["name", "last_updated"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentListEnvironmentsResponse: """Retrieve cloud environments accessible to the authenticated principal. Returns @@ -244,37 +213,31 @@ def list_environments( """ return self._get( "/agent/environments", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"sort_by": sort_by}, agent_list_environments_params.AgentListEnvironmentsParams), - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({ + "sort_by": sort_by + }, agent_list_environments_params.AgentListEnvironmentsParams)), cast_to=AgentListEnvironmentsResponse, ) - def run( - self, - *, - agent_identity_uid: str | Omit = omit, - attachments: Iterable[agent_run_params.Attachment] | Omit = omit, - config: AmbientAgentConfigParam | Omit = omit, - conversation_id: str | Omit = omit, - interactive: bool | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - parent_run_id: str | Omit = omit, - prompt: str | Omit = omit, - skill: str | Omit = omit, - team: bool | Omit = omit, - title: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentRunResponse: + def run(self, + *, + agent_identity_uid: str | Omit = omit, + attachments: Iterable[agent_run_params.Attachment] | Omit = omit, + config: AmbientAgentConfigParam | Omit = omit, + conversation_id: str | Omit = omit, + interactive: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + parent_run_id: str | Omit = omit, + prompt: str | Omit = omit, + skill: str | Omit = omit, + team: bool | Omit = omit, + title: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentRunResponse: """Spawn a cloud agent with a prompt and optional configuration. The agent will be @@ -328,32 +291,25 @@ def run( """ return self._post( "/agent/runs", - body=maybe_transform( - { - "agent_identity_uid": agent_identity_uid, - "attachments": attachments, - "config": config, - "conversation_id": conversation_id, - "interactive": interactive, - "mode": mode, - "parent_run_id": parent_run_id, - "prompt": prompt, - "skill": skill, - "team": team, - "title": title, - }, - agent_run_params.AgentRunParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + body=maybe_transform({ + "agent_identity_uid": agent_identity_uid, + "attachments": attachments, + "config": config, + "conversation_id": conversation_id, + "interactive": interactive, + "mode": mode, + "parent_run_id": parent_run_id, + "prompt": prompt, + "skill": skill, + "team": team, + "title": title, + }, agent_run_params.AgentRunParams), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=AgentRunResponse, ) - class AsyncAgentResource(AsyncAPIResource): """Operations for running and managing cloud agents""" - @cached_property def runs(self) -> AsyncRunsResource: """Operations for running and managing cloud agents""" @@ -398,20 +354,18 @@ def with_streaming_response(self) -> AsyncAgentResourceWithStreamingResponse: """ return AsyncAgentResourceWithStreamingResponse(self) - async def list( - self, - *, - include_malformed_skills: bool | Omit = omit, - refresh: bool | Omit = omit, - repo: str | Omit = omit, - sort_by: Literal["name", "last_run"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentListResponse: + async def list(self, + *, + include_malformed_skills: bool | Omit = omit, + refresh: bool | Omit = omit, + repo: str | Omit = omit, + sort_by: Literal["name", "last_run"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentListResponse: """ Retrieve a list of available agents (skills) that can be used to run tasks. Agents are discovered from environments or a specific repository. @@ -442,35 +396,24 @@ async def list( """ return await self._get( "/agent", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "include_malformed_skills": include_malformed_skills, - "refresh": refresh, - "repo": repo, - "sort_by": sort_by, - }, - agent_list_params.AgentListParams, - ), - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform({ + "include_malformed_skills": include_malformed_skills, + "refresh": refresh, + "repo": repo, + "sort_by": sort_by, + }, agent_list_params.AgentListParams)), cast_to=AgentListResponse, ) - async def get_artifact( - self, - artifact_uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentGetArtifactResponse: + async def get_artifact(self, + artifact_uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentGetArtifactResponse: """Retrieve an artifact by its UUID. For downloadable file-like artifacts, returns @@ -487,31 +430,24 @@ async def get_artifact( timeout: Override the client-level default timeout for this request, in seconds """ if not artifact_uid: - raise ValueError(f"Expected a non-empty value for `artifact_uid` but received {artifact_uid!r}") - return cast( - AgentGetArtifactResponse, - await self._get( - path_template("/agent/artifacts/{artifact_uid}", artifact_uid=artifact_uid), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast( - Any, AgentGetArtifactResponse - ), # Union types cannot be passed in as arguments in the type system - ), - ) - - async def list_environments( - self, - *, - sort_by: Literal["name", "last_updated"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentListEnvironmentsResponse: + raise ValueError( + f'Expected a non-empty value for `artifact_uid` but received {artifact_uid!r}' + ) + return cast(AgentGetArtifactResponse, await self._get( + path_template("/agent/artifacts/{artifact_uid}", artifact_uid=artifact_uid), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + cast_to=cast(Any, AgentGetArtifactResponse), # Union types cannot be passed in as arguments in the type system + )) + + async def list_environments(self, + *, + sort_by: Literal["name", "last_updated"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentListEnvironmentsResponse: """Retrieve cloud environments accessible to the authenticated principal. Returns @@ -534,39 +470,31 @@ async def list_environments( """ return await self._get( "/agent/environments", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - {"sort_by": sort_by}, agent_list_environments_params.AgentListEnvironmentsParams - ), - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform({ + "sort_by": sort_by + }, agent_list_environments_params.AgentListEnvironmentsParams)), cast_to=AgentListEnvironmentsResponse, ) - async def run( - self, - *, - agent_identity_uid: str | Omit = omit, - attachments: Iterable[agent_run_params.Attachment] | Omit = omit, - config: AmbientAgentConfigParam | Omit = omit, - conversation_id: str | Omit = omit, - interactive: bool | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - parent_run_id: str | Omit = omit, - prompt: str | Omit = omit, - skill: str | Omit = omit, - team: bool | Omit = omit, - title: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentRunResponse: + async def run(self, + *, + agent_identity_uid: str | Omit = omit, + attachments: Iterable[agent_run_params.Attachment] | Omit = omit, + config: AmbientAgentConfigParam | Omit = omit, + conversation_id: str | Omit = omit, + interactive: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + parent_run_id: str | Omit = omit, + prompt: str | Omit = omit, + skill: str | Omit = omit, + team: bool | Omit = omit, + title: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentRunResponse: """Spawn a cloud agent with a prompt and optional configuration. The agent will be @@ -620,29 +548,23 @@ async def run( """ return await self._post( "/agent/runs", - body=await async_maybe_transform( - { - "agent_identity_uid": agent_identity_uid, - "attachments": attachments, - "config": config, - "conversation_id": conversation_id, - "interactive": interactive, - "mode": mode, - "parent_run_id": parent_run_id, - "prompt": prompt, - "skill": skill, - "team": team, - "title": title, - }, - agent_run_params.AgentRunParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + body=await async_maybe_transform({ + "agent_identity_uid": agent_identity_uid, + "attachments": attachments, + "config": config, + "conversation_id": conversation_id, + "interactive": interactive, + "mode": mode, + "parent_run_id": parent_run_id, + "prompt": prompt, + "skill": skill, + "team": team, + "title": title, + }, agent_run_params.AgentRunParams), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=AgentRunResponse, ) - class AgentResourceWithRawResponse: def __init__(self, agent: AgentResource) -> None: self._agent = agent @@ -685,7 +607,6 @@ def conversations(self) -> ConversationsResourceWithRawResponse: """Operations for running and managing cloud agents""" return ConversationsResourceWithRawResponse(self._agent.conversations) - class AsyncAgentResourceWithRawResponse: def __init__(self, agent: AsyncAgentResource) -> None: self._agent = agent @@ -728,7 +649,6 @@ def conversations(self) -> AsyncConversationsResourceWithRawResponse: """Operations for running and managing cloud agents""" return AsyncConversationsResourceWithRawResponse(self._agent.conversations) - class AgentResourceWithStreamingResponse: def __init__(self, agent: AgentResource) -> None: self._agent = agent @@ -771,7 +691,6 @@ def conversations(self) -> ConversationsResourceWithStreamingResponse: """Operations for running and managing cloud agents""" return ConversationsResourceWithStreamingResponse(self._agent.conversations) - class AsyncAgentResourceWithStreamingResponse: def __init__(self, agent: AsyncAgentResource) -> None: self._agent = agent @@ -812,4 +731,4 @@ def sessions(self) -> AsyncSessionsResourceWithStreamingResponse: @cached_property def conversations(self) -> AsyncConversationsResourceWithStreamingResponse: """Operations for running and managing cloud agents""" - return AsyncConversationsResourceWithStreamingResponse(self._agent.conversations) + return AsyncConversationsResourceWithStreamingResponse(self._agent.conversations) \ No newline at end of file diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py index 65eb4d5..fa43b31 100644 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -2,32 +2,39 @@ from __future__ import annotations -from typing import Dict, Iterable, Optional - import httpx -from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform -from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...types.agent import agent_create_params, agent_update_params -from ..._base_client import make_request_options + +from ..._compat import cached_property + from ...types.agent.agent_response import AgentResponse + +from ..._utils import maybe_transform, path_template, async_maybe_transform + +from ..._base_client import make_request_options + +from typing import Optional, Dict, Iterable + +from ..._types import Omit, omit, SequenceNotStr, NotGiven + from ...types.mcp_server_config_param import McpServerConfigParam + from ...types.agent.list_agent_identities_response import ListAgentIdentitiesResponse -__all__ = ["AgentResource", "AsyncAgentResource"] +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper, to_streamed_response_wrapper, async_to_streamed_response_wrapper + +from ...types.agent import agent_create_params, agent_update_params +from typing_extensions import Literal, overload +from ..._types import Timeout, Headers, NotGiven, not_given, Omit, omit, NoneType, Query, Body +from ...types.agent import agent_create_params +from ...types.agent import agent_update_params + +__all__ = ["AgentResource", "AsyncAgentResource"] class AgentResource(SyncAPIResource): """Operations for running and managing cloud agents""" - @cached_property def with_raw_response(self) -> AgentResourceWithRawResponse: """ @@ -47,28 +54,26 @@ def with_streaming_response(self) -> AgentResourceWithStreamingResponse: """ return AgentResourceWithStreamingResponse(self) - def create( - self, - *, - name: str, - base_harness: Optional[str] | Omit = omit, - base_model: Optional[str] | Omit = omit, - description: Optional[str] | Omit = omit, - environment_id: Optional[str] | Omit = omit, - harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, - inference_providers: agent_create_params.InferenceProviders | Omit = omit, - mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, - memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, - prompt: Optional[str] | Omit = omit, - secrets: Iterable[agent_create_params.Secret] | Omit = omit, - skills: SequenceNotStr[str] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentResponse: + def create(self, + *, + name: str, + base_harness: Optional[str] | Omit = omit, + base_model: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, + environment_id: Optional[str] | Omit = omit, + harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, + inference_providers: agent_create_params.InferenceProviders | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, + memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, + prompt: Optional[str] | Omit = omit, + secrets: Iterable[agent_create_params.Secret] | Omit = omit, + skills: SequenceNotStr[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentResponse: """Create a new agent for the caller's team. Agents can be used as the execution @@ -121,52 +126,45 @@ def create( """ return self._post( "/agent/identities", - body=maybe_transform( - { - "name": name, - "base_harness": base_harness, - "base_model": base_model, - "description": description, - "environment_id": environment_id, - "harness_auth_secrets": harness_auth_secrets, - "inference_providers": inference_providers, - "mcp_servers": mcp_servers, - "memory_stores": memory_stores, - "prompt": prompt, - "secrets": secrets, - "skills": skills, - }, - agent_create_params.AgentCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + body=maybe_transform({ + "name": name, + "base_harness": base_harness, + "base_model": base_model, + "description": description, + "environment_id": environment_id, + "harness_auth_secrets": harness_auth_secrets, + "inference_providers": inference_providers, + "mcp_servers": mcp_servers, + "memory_stores": memory_stores, + "prompt": prompt, + "secrets": secrets, + "skills": skills, + }, agent_create_params.AgentCreateParams), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=AgentResponse, ) - def update( - self, - uid: str, - *, - base_harness: Optional[str] | Omit = omit, - base_model: Optional[str] | Omit = omit, - description: Optional[str] | Omit = omit, - environment_id: Optional[str] | Omit = omit, - harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, - inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, - mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, - memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, - name: str | Omit = omit, - prompt: Optional[str] | Omit = omit, - secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, - skills: Optional[SequenceNotStr[str]] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentResponse: + def update(self, + uid: str, + *, + base_harness: Optional[str] | Omit = omit, + base_model: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, + environment_id: Optional[str] | Omit = omit, + harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, + inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, + memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, + name: str | Omit = omit, + prompt: Optional[str] | Omit = omit, + secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, + skills: Optional[SequenceNotStr[str]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentResponse: """Update an existing agent. Args: @@ -216,42 +214,37 @@ def update( timeout: Override the client-level default timeout for this request, in seconds """ if not uid: - raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + raise ValueError( + f'Expected a non-empty value for `uid` but received {uid!r}' + ) return self._put( path_template("/agent/identities/{uid}", uid=uid), - body=maybe_transform( - { - "base_harness": base_harness, - "base_model": base_model, - "description": description, - "environment_id": environment_id, - "harness_auth_secrets": harness_auth_secrets, - "inference_providers": inference_providers, - "mcp_servers": mcp_servers, - "memory_stores": memory_stores, - "name": name, - "prompt": prompt, - "secrets": secrets, - "skills": skills, - }, - agent_update_params.AgentUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + body=maybe_transform({ + "base_harness": base_harness, + "base_model": base_model, + "description": description, + "environment_id": environment_id, + "harness_auth_secrets": harness_auth_secrets, + "inference_providers": inference_providers, + "mcp_servers": mcp_servers, + "memory_stores": memory_stores, + "name": name, + "prompt": prompt, + "secrets": secrets, + "skills": skills, + }, agent_update_params.AgentUpdateParams), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=AgentResponse, ) - def list( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ListAgentIdentitiesResponse: + def list(self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ListAgentIdentitiesResponse: """List all agents for the caller's team. Each agent includes an `available` flag @@ -259,23 +252,19 @@ def list( """ return self._get( "/agent/identities", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ListAgentIdentitiesResponse, ) - def delete( - self, - uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: + def delete(self, + uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> None: """Delete an agent. All API keys associated with the agent are deleted atomically. @@ -290,27 +279,25 @@ def delete( timeout: Override the client-level default timeout for this request, in seconds """ if not uid: - raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + raise ValueError( + f'Expected a non-empty value for `uid` but received {uid!r}' + ) extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._delete( path_template("/agent/identities/{uid}", uid=uid), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=NoneType, ) - def get( - self, - uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentResponse: + def get(self, + uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentResponse: """Retrieve a single agent by its unique identifier. The response includes an @@ -327,19 +314,17 @@ def get( timeout: Override the client-level default timeout for this request, in seconds """ if not uid: - raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + raise ValueError( + f'Expected a non-empty value for `uid` but received {uid!r}' + ) return self._get( path_template("/agent/identities/{uid}", uid=uid), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=AgentResponse, ) - class AsyncAgentResource(AsyncAPIResource): """Operations for running and managing cloud agents""" - @cached_property def with_raw_response(self) -> AsyncAgentResourceWithRawResponse: """ @@ -359,28 +344,26 @@ def with_streaming_response(self) -> AsyncAgentResourceWithStreamingResponse: """ return AsyncAgentResourceWithStreamingResponse(self) - async def create( - self, - *, - name: str, - base_harness: Optional[str] | Omit = omit, - base_model: Optional[str] | Omit = omit, - description: Optional[str] | Omit = omit, - environment_id: Optional[str] | Omit = omit, - harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, - inference_providers: agent_create_params.InferenceProviders | Omit = omit, - mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, - memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, - prompt: Optional[str] | Omit = omit, - secrets: Iterable[agent_create_params.Secret] | Omit = omit, - skills: SequenceNotStr[str] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentResponse: + async def create(self, + *, + name: str, + base_harness: Optional[str] | Omit = omit, + base_model: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, + environment_id: Optional[str] | Omit = omit, + harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, + inference_providers: agent_create_params.InferenceProviders | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, + memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, + prompt: Optional[str] | Omit = omit, + secrets: Iterable[agent_create_params.Secret] | Omit = omit, + skills: SequenceNotStr[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentResponse: """Create a new agent for the caller's team. Agents can be used as the execution @@ -433,52 +416,45 @@ async def create( """ return await self._post( "/agent/identities", - body=await async_maybe_transform( - { - "name": name, - "base_harness": base_harness, - "base_model": base_model, - "description": description, - "environment_id": environment_id, - "harness_auth_secrets": harness_auth_secrets, - "inference_providers": inference_providers, - "mcp_servers": mcp_servers, - "memory_stores": memory_stores, - "prompt": prompt, - "secrets": secrets, - "skills": skills, - }, - agent_create_params.AgentCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + body=await async_maybe_transform({ + "name": name, + "base_harness": base_harness, + "base_model": base_model, + "description": description, + "environment_id": environment_id, + "harness_auth_secrets": harness_auth_secrets, + "inference_providers": inference_providers, + "mcp_servers": mcp_servers, + "memory_stores": memory_stores, + "prompt": prompt, + "secrets": secrets, + "skills": skills, + }, agent_create_params.AgentCreateParams), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=AgentResponse, ) - async def update( - self, - uid: str, - *, - base_harness: Optional[str] | Omit = omit, - base_model: Optional[str] | Omit = omit, - description: Optional[str] | Omit = omit, - environment_id: Optional[str] | Omit = omit, - harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, - inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, - mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, - memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, - name: str | Omit = omit, - prompt: Optional[str] | Omit = omit, - secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, - skills: Optional[SequenceNotStr[str]] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentResponse: + async def update(self, + uid: str, + *, + base_harness: Optional[str] | Omit = omit, + base_model: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, + environment_id: Optional[str] | Omit = omit, + harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, + inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, + memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, + name: str | Omit = omit, + prompt: Optional[str] | Omit = omit, + secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, + skills: Optional[SequenceNotStr[str]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentResponse: """Update an existing agent. Args: @@ -528,42 +504,37 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ if not uid: - raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + raise ValueError( + f'Expected a non-empty value for `uid` but received {uid!r}' + ) return await self._put( path_template("/agent/identities/{uid}", uid=uid), - body=await async_maybe_transform( - { - "base_harness": base_harness, - "base_model": base_model, - "description": description, - "environment_id": environment_id, - "harness_auth_secrets": harness_auth_secrets, - "inference_providers": inference_providers, - "mcp_servers": mcp_servers, - "memory_stores": memory_stores, - "name": name, - "prompt": prompt, - "secrets": secrets, - "skills": skills, - }, - agent_update_params.AgentUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + body=await async_maybe_transform({ + "base_harness": base_harness, + "base_model": base_model, + "description": description, + "environment_id": environment_id, + "harness_auth_secrets": harness_auth_secrets, + "inference_providers": inference_providers, + "mcp_servers": mcp_servers, + "memory_stores": memory_stores, + "name": name, + "prompt": prompt, + "secrets": secrets, + "skills": skills, + }, agent_update_params.AgentUpdateParams), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=AgentResponse, ) - async def list( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ListAgentIdentitiesResponse: + async def list(self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ListAgentIdentitiesResponse: """List all agents for the caller's team. Each agent includes an `available` flag @@ -571,23 +542,19 @@ async def list( """ return await self._get( "/agent/identities", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ListAgentIdentitiesResponse, ) - async def delete( - self, - uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: + async def delete(self, + uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> None: """Delete an agent. All API keys associated with the agent are deleted atomically. @@ -602,27 +569,25 @@ async def delete( timeout: Override the client-level default timeout for this request, in seconds """ if not uid: - raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + raise ValueError( + f'Expected a non-empty value for `uid` but received {uid!r}' + ) extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._delete( path_template("/agent/identities/{uid}", uid=uid), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=NoneType, ) - async def get( - self, - uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentResponse: + async def get(self, + uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentResponse: """Retrieve a single agent by its unique identifier. The response includes an @@ -639,16 +604,15 @@ async def get( timeout: Override the client-level default timeout for this request, in seconds """ if not uid: - raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + raise ValueError( + f'Expected a non-empty value for `uid` but received {uid!r}' + ) return await self._get( path_template("/agent/identities/{uid}", uid=uid), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=AgentResponse, ) - class AgentResourceWithRawResponse: def __init__(self, agent: AgentResource) -> None: self._agent = agent @@ -669,7 +633,6 @@ def __init__(self, agent: AgentResource) -> None: agent.get, ) - class AsyncAgentResourceWithRawResponse: def __init__(self, agent: AsyncAgentResource) -> None: self._agent = agent @@ -690,7 +653,6 @@ def __init__(self, agent: AsyncAgentResource) -> None: agent.get, ) - class AgentResourceWithStreamingResponse: def __init__(self, agent: AgentResource) -> None: self._agent = agent @@ -711,7 +673,6 @@ def __init__(self, agent: AgentResource) -> None: agent.get, ) - class AsyncAgentResourceWithStreamingResponse: def __init__(self, agent: AsyncAgentResource) -> None: self._agent = agent @@ -730,4 +691,4 @@ def __init__(self, agent: AsyncAgentResource) -> None: ) self.get = async_to_streamed_response_wrapper( agent.get, - ) + ) \ No newline at end of file diff --git a/src/oz_agent_sdk/resources/agent/conversations.py b/src/oz_agent_sdk/resources/agent/conversations.py index 2525916..d131c80 100644 --- a/src/oz_agent_sdk/resources/agent/conversations.py +++ b/src/oz_agent_sdk/resources/agent/conversations.py @@ -4,25 +4,27 @@ import httpx -from ..._types import Body, Query, Headers, NotGiven, not_given -from ..._utils import path_template -from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ..._base_client import make_request_options + +from ..._compat import cached_property + +from ..._utils import path_template + from ...types.agent.conversation_check_redirect_response import ConversationCheckRedirectResponse -__all__ = ["ConversationsResource", "AsyncConversationsResource"] +from ..._base_client import make_request_options + +from ..._types import NotGiven +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper, to_streamed_response_wrapper, async_to_streamed_response_wrapper + +from typing_extensions import Literal, overload +from ..._types import Timeout, Headers, NotGiven, not_given, Omit, omit, NoneType, Query, Body + +__all__ = ["ConversationsResource", "AsyncConversationsResource"] class ConversationsResource(SyncAPIResource): """Operations for running and managing cloud agents""" - @cached_property def with_raw_response(self) -> ConversationsResourceWithRawResponse: """ @@ -42,17 +44,15 @@ def with_streaming_response(self) -> ConversationsResourceWithStreamingResponse: """ return ConversationsResourceWithStreamingResponse(self) - def check_redirect( - self, - conversation_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ConversationCheckRedirectResponse: + def check_redirect(self, + conversation_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ConversationCheckRedirectResponse: """Check whether a conversation should redirect to a live shared session. Returns a @@ -73,23 +73,17 @@ def check_redirect( timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: - raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") + raise ValueError( + f'Expected a non-empty value for `conversation_id` but received {conversation_id!r}' + ) return self._get( path_template("/agent/conversations/{conversation_id}/redirect", conversation_id=conversation_id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - security={}, - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, security={}), cast_to=ConversationCheckRedirectResponse, ) - class AsyncConversationsResource(AsyncAPIResource): """Operations for running and managing cloud agents""" - @cached_property def with_raw_response(self) -> AsyncConversationsResourceWithRawResponse: """ @@ -109,17 +103,15 @@ def with_streaming_response(self) -> AsyncConversationsResourceWithStreamingResp """ return AsyncConversationsResourceWithStreamingResponse(self) - async def check_redirect( - self, - conversation_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ConversationCheckRedirectResponse: + async def check_redirect(self, + conversation_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ConversationCheckRedirectResponse: """Check whether a conversation should redirect to a live shared session. Returns a @@ -140,20 +132,15 @@ async def check_redirect( timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: - raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") + raise ValueError( + f'Expected a non-empty value for `conversation_id` but received {conversation_id!r}' + ) return await self._get( path_template("/agent/conversations/{conversation_id}/redirect", conversation_id=conversation_id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - security={}, - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, security={}), cast_to=ConversationCheckRedirectResponse, ) - class ConversationsResourceWithRawResponse: def __init__(self, conversations: ConversationsResource) -> None: self._conversations = conversations @@ -162,7 +149,6 @@ def __init__(self, conversations: ConversationsResource) -> None: conversations.check_redirect, ) - class AsyncConversationsResourceWithRawResponse: def __init__(self, conversations: AsyncConversationsResource) -> None: self._conversations = conversations @@ -171,7 +157,6 @@ def __init__(self, conversations: AsyncConversationsResource) -> None: conversations.check_redirect, ) - class ConversationsResourceWithStreamingResponse: def __init__(self, conversations: ConversationsResource) -> None: self._conversations = conversations @@ -180,11 +165,10 @@ def __init__(self, conversations: ConversationsResource) -> None: conversations.check_redirect, ) - class AsyncConversationsResourceWithStreamingResponse: def __init__(self, conversations: AsyncConversationsResource) -> None: self._conversations = conversations self.check_redirect = async_to_streamed_response_wrapper( conversations.check_redirect, - ) + ) \ No newline at end of file diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index fa745d3..d916323 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -2,36 +2,48 @@ from __future__ import annotations -from typing import List, Union -from datetime import datetime -from typing_extensions import Literal - import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform -from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...pagination import SyncRunsCursorPage, AsyncRunsCursorPage -from ...types.agent import RunSourceType, run_list_params, run_submit_followup_params -from ..._base_client import AsyncPaginator, make_request_options + +from ..._compat import cached_property + +from ..._utils import path_template, maybe_transform, async_maybe_transform + from ...types.agent.run_item import RunItem -from ...types.agent.run_state import RunState + +from ..._base_client import make_request_options, AsyncPaginator + +from ..._types import NotGiven, Omit, omit + +from ...pagination import SyncRunsCursorPage, AsyncRunsCursorPage + +from typing_extensions import Literal + +from typing import Union, List + +from datetime import datetime + from ...types.agent.run_source_type import RunSourceType + +from ...types.agent.run_state import RunState + +from ...types.agent.run_cancel_response import RunCancelResponse + from ...types.agent.run_list_handoff_attachments_response import RunListHandoffAttachmentsResponse -__all__ = ["RunsResource", "AsyncRunsResource"] +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper, to_streamed_response_wrapper, async_to_streamed_response_wrapper + +from typing_extensions import Literal, overload +from ..._types import Timeout, Headers, NotGiven, not_given, Omit, omit, NoneType, Query, Body +from ...types.agent import run_list_params +from ...types.agent import run_submit_followup_params +from ...types.agent import RunSourceType +__all__ = ["RunsResource", "AsyncRunsResource"] class RunsResource(SyncAPIResource): """Operations for running and managing cloud agents""" - @cached_property def with_raw_response(self) -> RunsResourceWithRawResponse: """ @@ -51,17 +63,15 @@ def with_streaming_response(self) -> RunsResourceWithStreamingResponse: """ return RunsResourceWithStreamingResponse(self) - def retrieve( - self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunItem: + def retrieve(self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> RunItem: """ Retrieve detailed information about a specific agent run, including the full prompt, session link, and resolved configuration. @@ -76,46 +86,44 @@ def retrieve( timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + raise ValueError( + f'Expected a non-empty value for `run_id` but received {run_id!r}' + ) return self._get( path_template("/agent/runs/{run_id}", run_id=run_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=RunItem, ) - def list( - self, - *, - ancestor_run_id: str | Omit = omit, - artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, - created_after: Union[str, datetime] | Omit = omit, - created_before: Union[str, datetime] | Omit = omit, - creator: str | Omit = omit, - cursor: str | Omit = omit, - environment_id: str | Omit = omit, - execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, - executor: str | Omit = omit, - limit: int | Omit = omit, - model_id: str | Omit = omit, - name: str | Omit = omit, - q: str | Omit = omit, - schedule_id: str | Omit = omit, - skill: str | Omit = omit, - skill_spec: str | Omit = omit, - sort_by: Literal["updated_at", "created_at", "title", "agent"] | Omit = omit, - sort_order: Literal["asc", "desc"] | Omit = omit, - source: RunSourceType | Omit = omit, - state: List[RunState] | Omit = omit, - updated_after: Union[str, datetime] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SyncRunsCursorPage[RunItem]: + def list(self, + *, + ancestor_run_id: str | Omit = omit, + artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, + created_after: Union[str, datetime] | Omit = omit, + created_before: Union[str, datetime] | Omit = omit, + creator: str | Omit = omit, + cursor: str | Omit = omit, + environment_id: str | Omit = omit, + execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, + executor: str | Omit = omit, + limit: int | Omit = omit, + model_id: str | Omit = omit, + name: str | Omit = omit, + q: str | Omit = omit, + schedule_id: str | Omit = omit, + skill: str | Omit = omit, + skill_spec: str | Omit = omit, + sort_by: Literal["updated_at", "created_at", "title", "agent"] | Omit = omit, + sort_order: Literal["asc", "desc"] | Omit = omit, + source: RunSourceType | Omit = omit, + state: List[RunState] | Omit = omit, + updated_after: Union[str, datetime] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> SyncRunsCursorPage[RunItem]: """Retrieve a paginated list of agent runs with optional filtering. Results default @@ -183,53 +191,42 @@ def list( """ return self._get_api_list( "/agent/runs", - page=SyncRunsCursorPage[RunItem], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "ancestor_run_id": ancestor_run_id, - "artifact_type": artifact_type, - "created_after": created_after, - "created_before": created_before, - "creator": creator, - "cursor": cursor, - "environment_id": environment_id, - "execution_location": execution_location, - "executor": executor, - "limit": limit, - "model_id": model_id, - "name": name, - "q": q, - "schedule_id": schedule_id, - "skill": skill, - "skill_spec": skill_spec, - "sort_by": sort_by, - "sort_order": sort_order, - "source": source, - "state": state, - "updated_after": updated_after, - }, - run_list_params.RunListParams, - ), - ), + page = SyncRunsCursorPage[RunItem], + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({ + "ancestor_run_id": ancestor_run_id, + "artifact_type": artifact_type, + "created_after": created_after, + "created_before": created_before, + "creator": creator, + "cursor": cursor, + "environment_id": environment_id, + "execution_location": execution_location, + "executor": executor, + "limit": limit, + "model_id": model_id, + "name": name, + "q": q, + "schedule_id": schedule_id, + "skill": skill, + "skill_spec": skill_spec, + "sort_by": sort_by, + "sort_order": sort_order, + "source": source, + "state": state, + "updated_after": updated_after, + }, run_list_params.RunListParams)), model=RunItem, ) - def cancel( - self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> str: + def cancel(self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> str: """Cancel an agent run that is currently queued or in progress. Once cancelled, the @@ -249,26 +246,24 @@ def cancel( timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + raise ValueError( + f'Expected a non-empty value for `run_id` but received {run_id!r}' + ) return self._post( path_template("/agent/runs/{run_id}/cancel", run_id=run_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=str, ) - def list_handoff_attachments( - self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunListHandoffAttachmentsResponse: + def list_handoff_attachments(self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> RunListHandoffAttachmentsResponse: """ Return fresh presigned download URLs for handoff snapshot files uploaded by the latest ended execution of this run. An empty list is returned when no ended @@ -288,28 +283,26 @@ def list_handoff_attachments( timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + raise ValueError( + f'Expected a non-empty value for `run_id` but received {run_id!r}' + ) return self._get( path_template("/agent/runs/{run_id}/handoff/attachments", run_id=run_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=RunListHandoffAttachmentsResponse, ) - def submit_followup( - self, - run_id: str, - *, - message: str | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> object: + def submit_followup(self, + run_id: str, + *, + message: str | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> object: """Send a follow-up message to an existing run. The server transparently routes the @@ -332,26 +325,21 @@ def submit_followup( timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + raise ValueError( + f'Expected a non-empty value for `run_id` but received {run_id!r}' + ) return self._post( path_template("/agent/runs/{run_id}/followups", run_id=run_id), - body=maybe_transform( - { - "message": message, - "mode": mode, - }, - run_submit_followup_params.RunSubmitFollowupParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + body=maybe_transform({ + "message": message, + "mode": mode, + }, run_submit_followup_params.RunSubmitFollowupParams), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=object, ) - class AsyncRunsResource(AsyncAPIResource): """Operations for running and managing cloud agents""" - @cached_property def with_raw_response(self) -> AsyncRunsResourceWithRawResponse: """ @@ -371,17 +359,15 @@ def with_streaming_response(self) -> AsyncRunsResourceWithStreamingResponse: """ return AsyncRunsResourceWithStreamingResponse(self) - async def retrieve( - self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunItem: + async def retrieve(self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> RunItem: """ Retrieve detailed information about a specific agent run, including the full prompt, session link, and resolved configuration. @@ -396,46 +382,44 @@ async def retrieve( timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + raise ValueError( + f'Expected a non-empty value for `run_id` but received {run_id!r}' + ) return await self._get( path_template("/agent/runs/{run_id}", run_id=run_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=RunItem, ) - def list( - self, - *, - ancestor_run_id: str | Omit = omit, - artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, - created_after: Union[str, datetime] | Omit = omit, - created_before: Union[str, datetime] | Omit = omit, - creator: str | Omit = omit, - cursor: str | Omit = omit, - environment_id: str | Omit = omit, - execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, - executor: str | Omit = omit, - limit: int | Omit = omit, - model_id: str | Omit = omit, - name: str | Omit = omit, - q: str | Omit = omit, - schedule_id: str | Omit = omit, - skill: str | Omit = omit, - skill_spec: str | Omit = omit, - sort_by: Literal["updated_at", "created_at", "title", "agent"] | Omit = omit, - sort_order: Literal["asc", "desc"] | Omit = omit, - source: RunSourceType | Omit = omit, - state: List[RunState] | Omit = omit, - updated_after: Union[str, datetime] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncPaginator[RunItem, AsyncRunsCursorPage[RunItem]]: + def list(self, + *, + ancestor_run_id: str | Omit = omit, + artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, + created_after: Union[str, datetime] | Omit = omit, + created_before: Union[str, datetime] | Omit = omit, + creator: str | Omit = omit, + cursor: str | Omit = omit, + environment_id: str | Omit = omit, + execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, + executor: str | Omit = omit, + limit: int | Omit = omit, + model_id: str | Omit = omit, + name: str | Omit = omit, + q: str | Omit = omit, + schedule_id: str | Omit = omit, + skill: str | Omit = omit, + skill_spec: str | Omit = omit, + sort_by: Literal["updated_at", "created_at", "title", "agent"] | Omit = omit, + sort_order: Literal["asc", "desc"] | Omit = omit, + source: RunSourceType | Omit = omit, + state: List[RunState] | Omit = omit, + updated_after: Union[str, datetime] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AsyncPaginator[RunItem, AsyncRunsCursorPage[RunItem]]: """Retrieve a paginated list of agent runs with optional filtering. Results default @@ -503,53 +487,42 @@ def list( """ return self._get_api_list( "/agent/runs", - page=AsyncRunsCursorPage[RunItem], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "ancestor_run_id": ancestor_run_id, - "artifact_type": artifact_type, - "created_after": created_after, - "created_before": created_before, - "creator": creator, - "cursor": cursor, - "environment_id": environment_id, - "execution_location": execution_location, - "executor": executor, - "limit": limit, - "model_id": model_id, - "name": name, - "q": q, - "schedule_id": schedule_id, - "skill": skill, - "skill_spec": skill_spec, - "sort_by": sort_by, - "sort_order": sort_order, - "source": source, - "state": state, - "updated_after": updated_after, - }, - run_list_params.RunListParams, - ), - ), + page = AsyncRunsCursorPage[RunItem], + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({ + "ancestor_run_id": ancestor_run_id, + "artifact_type": artifact_type, + "created_after": created_after, + "created_before": created_before, + "creator": creator, + "cursor": cursor, + "environment_id": environment_id, + "execution_location": execution_location, + "executor": executor, + "limit": limit, + "model_id": model_id, + "name": name, + "q": q, + "schedule_id": schedule_id, + "skill": skill, + "skill_spec": skill_spec, + "sort_by": sort_by, + "sort_order": sort_order, + "source": source, + "state": state, + "updated_after": updated_after, + }, run_list_params.RunListParams)), model=RunItem, ) - async def cancel( - self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> str: + async def cancel(self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> str: """Cancel an agent run that is currently queued or in progress. Once cancelled, the @@ -569,26 +542,24 @@ async def cancel( timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + raise ValueError( + f'Expected a non-empty value for `run_id` but received {run_id!r}' + ) return await self._post( path_template("/agent/runs/{run_id}/cancel", run_id=run_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=str, ) - async def list_handoff_attachments( - self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunListHandoffAttachmentsResponse: + async def list_handoff_attachments(self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> RunListHandoffAttachmentsResponse: """ Return fresh presigned download URLs for handoff snapshot files uploaded by the latest ended execution of this run. An empty list is returned when no ended @@ -608,28 +579,26 @@ async def list_handoff_attachments( timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + raise ValueError( + f'Expected a non-empty value for `run_id` but received {run_id!r}' + ) return await self._get( path_template("/agent/runs/{run_id}/handoff/attachments", run_id=run_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=RunListHandoffAttachmentsResponse, ) - async def submit_followup( - self, - run_id: str, - *, - message: str | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> object: + async def submit_followup(self, + run_id: str, + *, + message: str | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> object: """Send a follow-up message to an existing run. The server transparently routes the @@ -652,23 +621,19 @@ async def submit_followup( timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + raise ValueError( + f'Expected a non-empty value for `run_id` but received {run_id!r}' + ) return await self._post( path_template("/agent/runs/{run_id}/followups", run_id=run_id), - body=await async_maybe_transform( - { - "message": message, - "mode": mode, - }, - run_submit_followup_params.RunSubmitFollowupParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + body=await async_maybe_transform({ + "message": message, + "mode": mode, + }, run_submit_followup_params.RunSubmitFollowupParams), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=object, ) - class RunsResourceWithRawResponse: def __init__(self, runs: RunsResource) -> None: self._runs = runs @@ -689,7 +654,6 @@ def __init__(self, runs: RunsResource) -> None: runs.submit_followup, ) - class AsyncRunsResourceWithRawResponse: def __init__(self, runs: AsyncRunsResource) -> None: self._runs = runs @@ -710,7 +674,6 @@ def __init__(self, runs: AsyncRunsResource) -> None: runs.submit_followup, ) - class RunsResourceWithStreamingResponse: def __init__(self, runs: RunsResource) -> None: self._runs = runs @@ -731,7 +694,6 @@ def __init__(self, runs: RunsResource) -> None: runs.submit_followup, ) - class AsyncRunsResourceWithStreamingResponse: def __init__(self, runs: AsyncRunsResource) -> None: self._runs = runs @@ -750,4 +712,4 @@ def __init__(self, runs: AsyncRunsResource) -> None: ) self.submit_followup = async_to_streamed_response_wrapper( runs.submit_followup, - ) + ) \ No newline at end of file diff --git a/src/oz_agent_sdk/resources/agent/schedules.py b/src/oz_agent_sdk/resources/agent/schedules.py index 67eaab9..75daa91 100644 --- a/src/oz_agent_sdk/resources/agent/schedules.py +++ b/src/oz_agent_sdk/resources/agent/schedules.py @@ -2,33 +2,41 @@ from __future__ import annotations -from typing_extensions import Literal - import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform -from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...types.agent import schedule_create_params, schedule_update_params -from ..._base_client import make_request_options + +from ..._compat import cached_property + from ...types.agent.scheduled_agent_item import ScheduledAgentItem + +from ..._utils import maybe_transform, path_template, async_maybe_transform + +from ..._base_client import make_request_options + from ...types.ambient_agent_config_param import AmbientAgentConfigParam + +from ..._types import Omit, omit, NotGiven + +from typing_extensions import Literal + from ...types.agent.schedule_list_response import ScheduleListResponse + from ...types.agent.schedule_delete_response import ScheduleDeleteResponse -__all__ = ["SchedulesResource", "AsyncSchedulesResource"] +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper, to_streamed_response_wrapper, async_to_streamed_response_wrapper +from typing_extensions import Literal, overload +from ..._types import Timeout, Headers, NotGiven, not_given, Omit, omit, NoneType, Query, Body +from ...types.agent import schedule_create_params +from ...types.agent import schedule_update_params +from ...types import AmbientAgentConfig +from ...types import AmbientAgentConfig + +__all__ = ["SchedulesResource", "AsyncSchedulesResource"] class SchedulesResource(SyncAPIResource): """Operations for creating and managing scheduled agents""" - @cached_property def with_raw_response(self) -> SchedulesResourceWithRawResponse: """ @@ -48,24 +56,22 @@ def with_streaming_response(self) -> SchedulesResourceWithStreamingResponse: """ return SchedulesResourceWithStreamingResponse(self) - def create( - self, - *, - cron_schedule: str, - name: str, - agent_config: AmbientAgentConfigParam | Omit = omit, - agent_uid: str | Omit = omit, - enabled: bool | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - prompt: str | Omit = omit, - team: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduledAgentItem: + def create(self, + *, + cron_schedule: str, + name: str, + agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, + enabled: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + prompt: str | Omit = omit, + team: bool | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: """Create a new scheduled agent that runs on a cron schedule. The agent will be @@ -103,36 +109,29 @@ def create( """ return self._post( "/agent/schedules", - body=maybe_transform( - { - "cron_schedule": cron_schedule, - "name": name, - "agent_config": agent_config, - "agent_uid": agent_uid, - "enabled": enabled, - "mode": mode, - "prompt": prompt, - "team": team, - }, - schedule_create_params.ScheduleCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + body=maybe_transform({ + "cron_schedule": cron_schedule, + "name": name, + "agent_config": agent_config, + "agent_uid": agent_uid, + "enabled": enabled, + "mode": mode, + "prompt": prompt, + "team": team, + }, schedule_create_params.ScheduleCreateParams), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduledAgentItem, ) - def retrieve( - self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduledAgentItem: + def retrieve(self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: """ Retrieve detailed information about a specific scheduled agent, including its configuration, history, and next scheduled run time. @@ -147,33 +146,31 @@ def retrieve( timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + raise ValueError( + f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' + ) return self._get( path_template("/agent/schedules/{schedule_id}", schedule_id=schedule_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduledAgentItem, ) - def update( - self, - schedule_id: str, - *, - cron_schedule: str, - enabled: bool, - name: str, - agent_config: AmbientAgentConfigParam | Omit = omit, - agent_uid: str | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - prompt: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduledAgentItem: + def update(self, + schedule_id: str, + *, + cron_schedule: str, + enabled: bool, + name: str, + agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + prompt: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: """Update an existing scheduled agent's configuration. All fields except @@ -206,37 +203,32 @@ def update( timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + raise ValueError( + f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' + ) return self._put( path_template("/agent/schedules/{schedule_id}", schedule_id=schedule_id), - body=maybe_transform( - { - "cron_schedule": cron_schedule, - "enabled": enabled, - "name": name, - "agent_config": agent_config, - "agent_uid": agent_uid, - "mode": mode, - "prompt": prompt, - }, - schedule_update_params.ScheduleUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + body=maybe_transform({ + "cron_schedule": cron_schedule, + "enabled": enabled, + "name": name, + "agent_config": agent_config, + "agent_uid": agent_uid, + "mode": mode, + "prompt": prompt, + }, schedule_update_params.ScheduleUpdateParams), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduledAgentItem, ) - def list( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduleListResponse: + def list(self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduleListResponse: """Retrieve all scheduled agents accessible to the authenticated user. Results are @@ -244,23 +236,19 @@ def list( """ return self._get( "/agent/schedules", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduleListResponse, ) - def delete( - self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduleDeleteResponse: + def delete(self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduleDeleteResponse: """Delete a scheduled agent. This will stop all future scheduled runs. @@ -275,26 +263,24 @@ def delete( timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + raise ValueError( + f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' + ) return self._delete( path_template("/agent/schedules/{schedule_id}", schedule_id=schedule_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduleDeleteResponse, ) - def pause( - self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduledAgentItem: + def pause(self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: """Pause a scheduled agent. The agent will not run until resumed. @@ -309,26 +295,24 @@ def pause( timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + raise ValueError( + f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' + ) return self._post( path_template("/agent/schedules/{schedule_id}/pause", schedule_id=schedule_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduledAgentItem, ) - def resume( - self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduledAgentItem: + def resume(self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: """Resume a paused scheduled agent. The agent will start running according to its @@ -344,19 +328,17 @@ def resume( timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + raise ValueError( + f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' + ) return self._post( path_template("/agent/schedules/{schedule_id}/resume", schedule_id=schedule_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduledAgentItem, ) - class AsyncSchedulesResource(AsyncAPIResource): """Operations for creating and managing scheduled agents""" - @cached_property def with_raw_response(self) -> AsyncSchedulesResourceWithRawResponse: """ @@ -376,24 +358,22 @@ def with_streaming_response(self) -> AsyncSchedulesResourceWithStreamingResponse """ return AsyncSchedulesResourceWithStreamingResponse(self) - async def create( - self, - *, - cron_schedule: str, - name: str, - agent_config: AmbientAgentConfigParam | Omit = omit, - agent_uid: str | Omit = omit, - enabled: bool | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - prompt: str | Omit = omit, - team: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduledAgentItem: + async def create(self, + *, + cron_schedule: str, + name: str, + agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, + enabled: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + prompt: str | Omit = omit, + team: bool | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: """Create a new scheduled agent that runs on a cron schedule. The agent will be @@ -431,36 +411,29 @@ async def create( """ return await self._post( "/agent/schedules", - body=await async_maybe_transform( - { - "cron_schedule": cron_schedule, - "name": name, - "agent_config": agent_config, - "agent_uid": agent_uid, - "enabled": enabled, - "mode": mode, - "prompt": prompt, - "team": team, - }, - schedule_create_params.ScheduleCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + body=await async_maybe_transform({ + "cron_schedule": cron_schedule, + "name": name, + "agent_config": agent_config, + "agent_uid": agent_uid, + "enabled": enabled, + "mode": mode, + "prompt": prompt, + "team": team, + }, schedule_create_params.ScheduleCreateParams), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduledAgentItem, ) - async def retrieve( - self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduledAgentItem: + async def retrieve(self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: """ Retrieve detailed information about a specific scheduled agent, including its configuration, history, and next scheduled run time. @@ -475,33 +448,31 @@ async def retrieve( timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + raise ValueError( + f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' + ) return await self._get( path_template("/agent/schedules/{schedule_id}", schedule_id=schedule_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduledAgentItem, ) - async def update( - self, - schedule_id: str, - *, - cron_schedule: str, - enabled: bool, - name: str, - agent_config: AmbientAgentConfigParam | Omit = omit, - agent_uid: str | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - prompt: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduledAgentItem: + async def update(self, + schedule_id: str, + *, + cron_schedule: str, + enabled: bool, + name: str, + agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + prompt: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: """Update an existing scheduled agent's configuration. All fields except @@ -534,37 +505,32 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + raise ValueError( + f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' + ) return await self._put( path_template("/agent/schedules/{schedule_id}", schedule_id=schedule_id), - body=await async_maybe_transform( - { - "cron_schedule": cron_schedule, - "enabled": enabled, - "name": name, - "agent_config": agent_config, - "agent_uid": agent_uid, - "mode": mode, - "prompt": prompt, - }, - schedule_update_params.ScheduleUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + body=await async_maybe_transform({ + "cron_schedule": cron_schedule, + "enabled": enabled, + "name": name, + "agent_config": agent_config, + "agent_uid": agent_uid, + "mode": mode, + "prompt": prompt, + }, schedule_update_params.ScheduleUpdateParams), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduledAgentItem, ) - async def list( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduleListResponse: + async def list(self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduleListResponse: """Retrieve all scheduled agents accessible to the authenticated user. Results are @@ -572,23 +538,19 @@ async def list( """ return await self._get( "/agent/schedules", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduleListResponse, ) - async def delete( - self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduleDeleteResponse: + async def delete(self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduleDeleteResponse: """Delete a scheduled agent. This will stop all future scheduled runs. @@ -603,26 +565,24 @@ async def delete( timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + raise ValueError( + f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' + ) return await self._delete( path_template("/agent/schedules/{schedule_id}", schedule_id=schedule_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduleDeleteResponse, ) - async def pause( - self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduledAgentItem: + async def pause(self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: """Pause a scheduled agent. The agent will not run until resumed. @@ -637,26 +597,24 @@ async def pause( timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + raise ValueError( + f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' + ) return await self._post( path_template("/agent/schedules/{schedule_id}/pause", schedule_id=schedule_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduledAgentItem, ) - async def resume( - self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduledAgentItem: + async def resume(self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: """Resume a paused scheduled agent. The agent will start running according to its @@ -672,16 +630,15 @@ async def resume( timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + raise ValueError( + f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' + ) return await self._post( path_template("/agent/schedules/{schedule_id}/resume", schedule_id=schedule_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), cast_to=ScheduledAgentItem, ) - class SchedulesResourceWithRawResponse: def __init__(self, schedules: SchedulesResource) -> None: self._schedules = schedules @@ -708,7 +665,6 @@ def __init__(self, schedules: SchedulesResource) -> None: schedules.resume, ) - class AsyncSchedulesResourceWithRawResponse: def __init__(self, schedules: AsyncSchedulesResource) -> None: self._schedules = schedules @@ -735,7 +691,6 @@ def __init__(self, schedules: AsyncSchedulesResource) -> None: schedules.resume, ) - class SchedulesResourceWithStreamingResponse: def __init__(self, schedules: SchedulesResource) -> None: self._schedules = schedules @@ -762,7 +717,6 @@ def __init__(self, schedules: SchedulesResource) -> None: schedules.resume, ) - class AsyncSchedulesResourceWithStreamingResponse: def __init__(self, schedules: AsyncSchedulesResource) -> None: self._schedules = schedules @@ -787,4 +741,4 @@ def __init__(self, schedules: AsyncSchedulesResource) -> None: ) self.resume = async_to_streamed_response_wrapper( schedules.resume, - ) + ) \ No newline at end of file diff --git a/src/oz_agent_sdk/resources/agent/sessions.py b/src/oz_agent_sdk/resources/agent/sessions.py index d704bd6..fff5e27 100644 --- a/src/oz_agent_sdk/resources/agent/sessions.py +++ b/src/oz_agent_sdk/resources/agent/sessions.py @@ -4,25 +4,27 @@ import httpx -from ..._types import Body, Query, Headers, NotGiven, not_given -from ..._utils import path_template -from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ..._base_client import make_request_options + +from ..._compat import cached_property + +from ..._utils import path_template + from ...types.agent.session_check_redirect_response import SessionCheckRedirectResponse -__all__ = ["SessionsResource", "AsyncSessionsResource"] +from ..._base_client import make_request_options + +from ..._types import NotGiven +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper, to_streamed_response_wrapper, async_to_streamed_response_wrapper + +from typing_extensions import Literal, overload +from ..._types import Timeout, Headers, NotGiven, not_given, Omit, omit, NoneType, Query, Body + +__all__ = ["SessionsResource", "AsyncSessionsResource"] class SessionsResource(SyncAPIResource): """Operations for running and managing cloud agents""" - @cached_property def with_raw_response(self) -> SessionsResourceWithRawResponse: """ @@ -42,17 +44,15 @@ def with_streaming_response(self) -> SessionsResourceWithStreamingResponse: """ return SessionsResourceWithStreamingResponse(self) - def check_redirect( - self, - session_uuid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SessionCheckRedirectResponse: + def check_redirect(self, + session_uuid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> SessionCheckRedirectResponse: """ Check whether a shared session should redirect to a conversation transcript. Returns a conversation_id if the agent sandbox has finished and conversation @@ -72,23 +72,17 @@ def check_redirect( timeout: Override the client-level default timeout for this request, in seconds """ if not session_uuid: - raise ValueError(f"Expected a non-empty value for `session_uuid` but received {session_uuid!r}") + raise ValueError( + f'Expected a non-empty value for `session_uuid` but received {session_uuid!r}' + ) return self._get( path_template("/agent/sessions/{session_uuid}/redirect", session_uuid=session_uuid), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - security={}, - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, security={}), cast_to=SessionCheckRedirectResponse, ) - class AsyncSessionsResource(AsyncAPIResource): """Operations for running and managing cloud agents""" - @cached_property def with_raw_response(self) -> AsyncSessionsResourceWithRawResponse: """ @@ -108,17 +102,15 @@ def with_streaming_response(self) -> AsyncSessionsResourceWithStreamingResponse: """ return AsyncSessionsResourceWithStreamingResponse(self) - async def check_redirect( - self, - session_uuid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SessionCheckRedirectResponse: + async def check_redirect(self, + session_uuid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> SessionCheckRedirectResponse: """ Check whether a shared session should redirect to a conversation transcript. Returns a conversation_id if the agent sandbox has finished and conversation @@ -138,20 +130,15 @@ async def check_redirect( timeout: Override the client-level default timeout for this request, in seconds """ if not session_uuid: - raise ValueError(f"Expected a non-empty value for `session_uuid` but received {session_uuid!r}") + raise ValueError( + f'Expected a non-empty value for `session_uuid` but received {session_uuid!r}' + ) return await self._get( path_template("/agent/sessions/{session_uuid}/redirect", session_uuid=session_uuid), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - security={}, - ), + options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, security={}), cast_to=SessionCheckRedirectResponse, ) - class SessionsResourceWithRawResponse: def __init__(self, sessions: SessionsResource) -> None: self._sessions = sessions @@ -160,7 +147,6 @@ def __init__(self, sessions: SessionsResource) -> None: sessions.check_redirect, ) - class AsyncSessionsResourceWithRawResponse: def __init__(self, sessions: AsyncSessionsResource) -> None: self._sessions = sessions @@ -169,7 +155,6 @@ def __init__(self, sessions: AsyncSessionsResource) -> None: sessions.check_redirect, ) - class SessionsResourceWithStreamingResponse: def __init__(self, sessions: SessionsResource) -> None: self._sessions = sessions @@ -178,11 +163,10 @@ def __init__(self, sessions: SessionsResource) -> None: sessions.check_redirect, ) - class AsyncSessionsResourceWithStreamingResponse: def __init__(self, sessions: AsyncSessionsResource) -> None: self._sessions = sessions self.check_redirect = async_to_streamed_response_wrapper( sessions.check_redirect, - ) + ) \ No newline at end of file diff --git a/src/oz_agent_sdk/types/__init__.py b/src/oz_agent_sdk/types/__init__.py index e27ca02..e188048 100644 --- a/src/oz_agent_sdk/types/__init__.py +++ b/src/oz_agent_sdk/types/__init__.py @@ -2,22 +2,22 @@ from __future__ import annotations -from .scope import Scope as Scope -from .error_code import ErrorCode as ErrorCode from .agent_skill import AgentSkill as AgentSkill -from .user_profile import UserProfile as UserProfile -from .agent_run_params import AgentRunParams as AgentRunParams -from .agent_list_params import AgentListParams as AgentListParams -from .cloud_environment import CloudEnvironment as CloudEnvironment -from .mcp_server_config import McpServerConfig as McpServerConfig -from .agent_run_response import AgentRunResponse as AgentRunResponse -from .agent_list_response import AgentListResponse as AgentListResponse +from .ambient_agent_config import AmbientAgentConfig as AmbientAgentConfig +from .ambient_agent_config_param import AmbientAgentConfigParam as AmbientAgentConfigParam from .aws_provider_config import AwsProviderConfig as AwsProviderConfig +from .cloud_environment import CloudEnvironment as CloudEnvironment +from .cloud_environment_config import CloudEnvironmentConfig as CloudEnvironmentConfig +from .error_code import ErrorCode as ErrorCode from .gcp_provider_config import GcpProviderConfig as GcpProviderConfig -from .ambient_agent_config import AmbientAgentConfig as AmbientAgentConfig +from .mcp_server_config import McpServerConfig as McpServerConfig from .mcp_server_config_param import McpServerConfigParam as McpServerConfigParam -from .cloud_environment_config import CloudEnvironmentConfig as CloudEnvironmentConfig -from .ambient_agent_config_param import AmbientAgentConfigParam as AmbientAgentConfigParam +from .scope import Scope as Scope +from .user_profile import UserProfile as UserProfile +from .agent_list_response import AgentListResponse as AgentListResponse from .agent_get_artifact_response import AgentGetArtifactResponse as AgentGetArtifactResponse -from .agent_list_environments_params import AgentListEnvironmentsParams as AgentListEnvironmentsParams from .agent_list_environments_response import AgentListEnvironmentsResponse as AgentListEnvironmentsResponse +from .agent_run_response import AgentRunResponse as AgentRunResponse +from .agent_list_params import AgentListParams as AgentListParams +from .agent_list_environments_params import AgentListEnvironmentsParams as AgentListEnvironmentsParams +from .agent_run_params import AgentRunParams as AgentRunParams \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/__init__.py b/src/oz_agent_sdk/types/agent/__init__.py index 07bab46..6658587 100644 --- a/src/oz_agent_sdk/types/agent/__init__.py +++ b/src/oz_agent_sdk/types/agent/__init__.py @@ -2,25 +2,23 @@ from __future__ import annotations -from .run_item import RunItem as RunItem -from .run_state import RunState as RunState from .artifact_item import ArtifactItem as ArtifactItem -from .agent_response import AgentResponse as AgentResponse -from .run_list_params import RunListParams as RunListParams +from .run_item import RunItem as RunItem from .run_source_type import RunSourceType as RunSourceType -from .agent_create_params import AgentCreateParams as AgentCreateParams -from .agent_update_params import AgentUpdateParams as AgentUpdateParams +from .run_state import RunState as RunState from .run_cancel_response import RunCancelResponse as RunCancelResponse +from .run_list_handoff_attachments_response import RunListHandoffAttachmentsResponse as RunListHandoffAttachmentsResponse +from .run_list_params import RunListParams as RunListParams +from .run_submit_followup_params import RunSubmitFollowupParams as RunSubmitFollowupParams +from .scheduled_agent_history_item import ScheduledAgentHistoryItem as ScheduledAgentHistoryItem from .scheduled_agent_item import ScheduledAgentItem as ScheduledAgentItem -from .schedule_create_params import ScheduleCreateParams as ScheduleCreateParams from .schedule_list_response import ScheduleListResponse as ScheduleListResponse -from .schedule_update_params import ScheduleUpdateParams as ScheduleUpdateParams from .schedule_delete_response import ScheduleDeleteResponse as ScheduleDeleteResponse -from .run_submit_followup_params import RunSubmitFollowupParams as RunSubmitFollowupParams -from .scheduled_agent_history_item import ScheduledAgentHistoryItem as ScheduledAgentHistoryItem +from .schedule_create_params import ScheduleCreateParams as ScheduleCreateParams +from .schedule_update_params import ScheduleUpdateParams as ScheduleUpdateParams +from .agent_response import AgentResponse as AgentResponse from .list_agent_identities_response import ListAgentIdentitiesResponse as ListAgentIdentitiesResponse +from .agent_create_params import AgentCreateParams as AgentCreateParams +from .agent_update_params import AgentUpdateParams as AgentUpdateParams from .session_check_redirect_response import SessionCheckRedirectResponse as SessionCheckRedirectResponse -from .conversation_check_redirect_response import ConversationCheckRedirectResponse as ConversationCheckRedirectResponse -from .run_list_handoff_attachments_response import ( - RunListHandoffAttachmentsResponse as RunListHandoffAttachmentsResponse, -) +from .conversation_check_redirect_response import ConversationCheckRedirectResponse as ConversationCheckRedirectResponse \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py index 798e05d..987d525 100644 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -2,21 +2,15 @@ from __future__ import annotations -from typing import Dict, Iterable, Optional -from typing_extensions import Literal, Required, TypedDict +from typing_extensions import TypedDict, Required, Literal + +from typing import Optional, Dict, Iterable -from ..._types import SequenceNotStr from ..mcp_server_config_param import McpServerConfigParam -__all__ = [ - "AgentCreateParams", - "HarnessAuthSecrets", - "InferenceProviders", - "InferenceProvidersAws", - "MemoryStore", - "Secret", -] +from ..._types import SequenceNotStr +__all__ = ["AgentCreateParams", "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws", "MemoryStore", "Secret"] class AgentCreateParams(TypedDict, total=False): name: Required[str] @@ -78,13 +72,11 @@ class AgentCreateParams(TypedDict, total=False): or malformed specs are rejected. """ - class HarnessAuthSecrets(TypedDict, total=False): """ Authentication secrets for third-party harnesses. Only the secret for the harness specified gets injected into the environment. """ - claude_auth_secret_name: str """ Name of a managed secret for Claude Code harness authentication. The secret must @@ -99,13 +91,11 @@ class HarnessAuthSecrets(TypedDict, total=False): "codex". """ - class InferenceProvidersAws(TypedDict, total=False): """ Configures AWS Bedrock as the LLM inference provider for this agent or run. """ - disabled: bool """If true, opt out of Bedrock at this layer.""" @@ -115,17 +105,13 @@ class InferenceProvidersAws(TypedDict, total=False): role_arn: str """IAM role ARN to assume when calling Bedrock.""" - class InferenceProviders(TypedDict, total=False): """Inference provider settings used for LLM calls.""" - aws: InferenceProvidersAws """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" - class MemoryStore(TypedDict, total=False): """Reference to a memory store to attach to an agent.""" - access: Required[Literal["read_write", "read_only"]] """Access level for the store.""" @@ -135,9 +121,7 @@ class MemoryStore(TypedDict, total=False): uid: Required[str] """UID of the memory store.""" - class Secret(TypedDict, total=False): """Reference to a managed secret by name.""" - name: Required[str] - """Name of the managed secret.""" + """Name of the managed secret.""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/agent_response.py b/src/oz_agent_sdk/types/agent/agent_response.py index 37d13b9..68792bf 100644 --- a/src/oz_agent_sdk/types/agent/agent_response.py +++ b/src/oz_agent_sdk/types/agent/agent_response.py @@ -1,25 +1,19 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional -from datetime import datetime +from ..._models import BaseModel + from typing_extensions import Literal -from ..._models import BaseModel -from ..mcp_server_config import McpServerConfig +from typing import Optional, List, Dict -__all__ = [ - "AgentResponse", - "MemoryStore", - "Secret", - "HarnessAuthSecrets", - "InferenceProviders", - "InferenceProvidersAws", -] +from datetime import datetime + +from ..mcp_server_config import McpServerConfig +__all__ = ["AgentResponse", "MemoryStore", "Secret", "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws"] class MemoryStore(BaseModel): """Reference to a memory store to attach to an agent.""" - access: Literal["read_write", "read_only"] """Access level for the store.""" @@ -29,20 +23,16 @@ class MemoryStore(BaseModel): uid: str """UID of the memory store.""" - class Secret(BaseModel): """Reference to a managed secret by name.""" - name: str """Name of the managed secret.""" - class HarnessAuthSecrets(BaseModel): """ Authentication secrets for third-party harnesses. Only the secret for the harness specified gets injected into the environment. """ - claude_auth_secret_name: Optional[str] = None """ Name of a managed secret for Claude Code harness authentication. The secret must @@ -57,13 +47,11 @@ class HarnessAuthSecrets(BaseModel): "codex". """ - class InferenceProvidersAws(BaseModel): """ Configures AWS Bedrock as the LLM inference provider for this agent or run. """ - disabled: Optional[bool] = None """If true, opt out of Bedrock at this layer.""" @@ -73,14 +61,11 @@ class InferenceProvidersAws(BaseModel): role_arn: Optional[str] = None """IAM role ARN to assume when calling Bedrock.""" - class InferenceProviders(BaseModel): """Inference provider settings used for LLM calls.""" - aws: Optional[InferenceProvidersAws] = None """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" - class AgentResponse(BaseModel): available: bool """Whether this agent is within the team's plan limit and can be used for runs""" @@ -161,4 +146,4 @@ class AgentResponse(BaseModel): """ prompt: Optional[str] = None - """Optional base prompt for this agent""" + """Optional base prompt for this agent""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/agent_update_params.py b/src/oz_agent_sdk/types/agent/agent_update_params.py index 19082d4..d67e417 100644 --- a/src/oz_agent_sdk/types/agent/agent_update_params.py +++ b/src/oz_agent_sdk/types/agent/agent_update_params.py @@ -2,21 +2,15 @@ from __future__ import annotations -from typing import Dict, Iterable, Optional -from typing_extensions import Literal, Required, TypedDict +from typing_extensions import TypedDict, Literal, Required + +from typing import Optional, Dict, Iterable -from ..._types import SequenceNotStr from ..mcp_server_config_param import McpServerConfigParam -__all__ = [ - "AgentUpdateParams", - "HarnessAuthSecrets", - "InferenceProviders", - "InferenceProvidersAws", - "MemoryStore", - "Secret", -] +from ..._types import SequenceNotStr +__all__ = ["AgentUpdateParams", "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws", "MemoryStore", "Secret"] class AgentUpdateParams(TypedDict, total=False): base_harness: Optional[str] @@ -90,13 +84,11 @@ class AgentUpdateParams(TypedDict, total=False): to replace. """ - class HarnessAuthSecrets(TypedDict, total=False): """ Authentication secrets for third-party harnesses. Only the secret for the harness specified gets injected into the environment. """ - claude_auth_secret_name: str """ Name of a managed secret for Claude Code harness authentication. The secret must @@ -111,13 +103,11 @@ class HarnessAuthSecrets(TypedDict, total=False): "codex". """ - class InferenceProvidersAws(TypedDict, total=False): """ Configures AWS Bedrock as the LLM inference provider for this agent or run. """ - disabled: bool """If true, opt out of Bedrock at this layer.""" @@ -127,17 +117,13 @@ class InferenceProvidersAws(TypedDict, total=False): role_arn: str """IAM role ARN to assume when calling Bedrock.""" - class InferenceProviders(TypedDict, total=False): """Inference provider settings used for LLM calls.""" - aws: InferenceProvidersAws """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" - class MemoryStore(TypedDict, total=False): """Reference to a memory store to attach to an agent.""" - access: Required[Literal["read_write", "read_only"]] """Access level for the store.""" @@ -147,9 +133,7 @@ class MemoryStore(TypedDict, total=False): uid: Required[str] """UID of the memory store.""" - class Secret(TypedDict, total=False): """Reference to a managed secret by name.""" - name: Required[str] - """Name of the managed secret.""" + """Name of the managed secret.""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/artifact_item.py b/src/oz_agent_sdk/types/agent/artifact_item.py index 437b857..226a754 100644 --- a/src/oz_agent_sdk/types/agent/artifact_item.py +++ b/src/oz_agent_sdk/types/agent/artifact_item.py @@ -1,24 +1,16 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional -from datetime import datetime -from typing_extensions import Literal, Annotated, TypeAlias -from ..._utils import PropertyInfo from ..._models import BaseModel -__all__ = [ - "ArtifactItem", - "PlanArtifact", - "PlanArtifactData", - "PullRequestArtifact", - "PullRequestArtifactData", - "ScreenshotArtifact", - "ScreenshotArtifactData", - "FileArtifact", - "FileArtifactData", -] +from typing_extensions import Literal, Annotated, TypeAliasType, TypeAlias +from datetime import datetime + +from ..._utils import PropertyInfo + +__all__ = ["ArtifactItem", "PlanArtifact", "PlanArtifactData", "PullRequestArtifact", "PullRequestArtifactData", "ScreenshotArtifact", "ScreenshotArtifactData", "FileArtifact", "FileArtifactData"] class PlanArtifactData(BaseModel): document_uid: str @@ -39,7 +31,6 @@ class PlanArtifactData(BaseModel): url: Optional[str] = None """URL to open the plan in Warp Drive""" - class PlanArtifact(BaseModel): artifact_type: Literal["PLAN"] """Type of the artifact""" @@ -49,7 +40,6 @@ class PlanArtifact(BaseModel): data: PlanArtifactData - class PullRequestArtifactData(BaseModel): branch: str """Branch name for the pull request""" @@ -57,7 +47,6 @@ class PullRequestArtifactData(BaseModel): url: str """URL of the pull request""" - class PullRequestArtifact(BaseModel): artifact_type: Literal["PULL_REQUEST"] """Type of the artifact""" @@ -67,7 +56,6 @@ class PullRequestArtifact(BaseModel): data: PullRequestArtifactData - class ScreenshotArtifactData(BaseModel): artifact_uid: str """Unique identifier for the screenshot artifact""" @@ -78,7 +66,6 @@ class ScreenshotArtifactData(BaseModel): description: Optional[str] = None """Optional description of the screenshot""" - class ScreenshotArtifact(BaseModel): artifact_type: Literal["SCREENSHOT"] """Type of the artifact""" @@ -88,7 +75,6 @@ class ScreenshotArtifact(BaseModel): data: ScreenshotArtifactData - class FileArtifactData(BaseModel): artifact_uid: str """Unique identifier for the file artifact""" @@ -108,7 +94,6 @@ class FileArtifactData(BaseModel): size_bytes: Optional[int] = None """Size of the uploaded file in bytes""" - class FileArtifact(BaseModel): artifact_type: Literal["FILE"] """Type of the artifact""" @@ -118,8 +103,4 @@ class FileArtifact(BaseModel): data: FileArtifactData - -ArtifactItem: TypeAlias = Annotated[ - Union[PlanArtifact, PullRequestArtifact, ScreenshotArtifact, FileArtifact], - PropertyInfo(discriminator="artifact_type"), -] +ArtifactItem: TypeAlias = Annotated[Union[PlanArtifact, PullRequestArtifact, ScreenshotArtifact, FileArtifact], PropertyInfo(discriminator="artifact_type")] \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/conversation_check_redirect_response.py b/src/oz_agent_sdk/types/agent/conversation_check_redirect_response.py index d18fa13..143aa8d 100644 --- a/src/oz_agent_sdk/types/agent/conversation_check_redirect_response.py +++ b/src/oz_agent_sdk/types/agent/conversation_check_redirect_response.py @@ -1,12 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional - from ..._models import BaseModel -__all__ = ["ConversationCheckRedirectResponse"] +from typing import Optional +__all__ = ["ConversationCheckRedirectResponse"] class ConversationCheckRedirectResponse(BaseModel): session_id: Optional[str] = None - """The shared session UUID to redirect to (only present when redirect is needed)""" + """The shared session UUID to redirect to (only present when redirect is needed)""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/list_agent_identities_response.py b/src/oz_agent_sdk/types/agent/list_agent_identities_response.py index d796e6f..53e0d5d 100644 --- a/src/oz_agent_sdk/types/agent/list_agent_identities_response.py +++ b/src/oz_agent_sdk/types/agent/list_agent_identities_response.py @@ -1,12 +1,12 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from ..._models import BaseModel + from typing import List -from ..._models import BaseModel from .agent_response import AgentResponse __all__ = ["ListAgentIdentitiesResponse"] - class ListAgentIdentitiesResponse(BaseModel): - agents: List[AgentResponse] + agents: List[AgentResponse] \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/run_cancel_response.py b/src/oz_agent_sdk/types/agent/run_cancel_response.py index b002815..ecb9017 100644 --- a/src/oz_agent_sdk/types/agent/run_cancel_response.py +++ b/src/oz_agent_sdk/types/agent/run_cancel_response.py @@ -1,7 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing_extensions import TypeAlias +from typing_extensions import TypeAliasType, TypeAlias __all__ = ["RunCancelResponse"] -RunCancelResponse: TypeAlias = str +RunCancelResponse: TypeAlias = str \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/run_item.py b/src/oz_agent_sdk/types/agent/run_item.py index 6181203..e587baf 100644 --- a/src/oz_agent_sdk/types/agent/run_item.py +++ b/src/oz_agent_sdk/types/agent/run_item.py @@ -1,27 +1,34 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from ..._models import BaseModel + +from typing import Optional, List + +from ..error_code import ErrorCode + from datetime import datetime -from typing_extensions import Literal -from ..scope import Scope -from ..._models import BaseModel from .run_state import RunState -from ..error_code import ErrorCode -from ..user_profile import UserProfile + +from ..ambient_agent_config import AmbientAgentConfig + from .artifact_item import ArtifactItem + +from ..user_profile import UserProfile + +from typing_extensions import Literal + +from ..scope import Scope + from .run_source_type import RunSourceType -from ..ambient_agent_config import AmbientAgentConfig __all__ = ["RunItem", "AgentSkill", "RequestUsage", "Schedule", "StatusMessage"] - class AgentSkill(BaseModel): """ Information about the agent skill used for the run. Either full_path or bundled_skill_id will be set, but not both. """ - bundled_skill_id: Optional[str] = None """Unique identifier for bundled skills""" @@ -34,10 +41,8 @@ class AgentSkill(BaseModel): name: Optional[str] = None """Human-readable name of the skill""" - class RequestUsage(BaseModel): """Resource usage information for the run""" - compute_cost: Optional[float] = None """Cost of compute resources for the run""" @@ -47,12 +52,10 @@ class RequestUsage(BaseModel): platform_cost: Optional[float] = None """Cost of platform usage for the run""" - class Schedule(BaseModel): """ Information about the schedule that triggered this run (only present for scheduled runs) """ - cron_schedule: str """Cron expression at the time the run was created""" @@ -62,14 +65,12 @@ class Schedule(BaseModel): schedule_name: str """Name of the schedule at the time the run was created""" - class StatusMessage(BaseModel): """Status message for a run. For terminal error states, includes structured error code and retryability info from the platform error catalog. """ - message: str """Human-readable status message""" @@ -110,7 +111,6 @@ class StatusMessage(BaseModel): the underlying cause will not succeed. """ - class RunItem(BaseModel): created_at: datetime """Timestamp when the run was created (RFC3339)""" @@ -173,6 +173,14 @@ class RunItem(BaseModel): executor: Optional[UserProfile] = None + is_run_type_cancellable: Optional[bool] = None + """Whether the run's type is eligible for cancellation via the API. + + State-independent: false for GitHub Action and local runs; true for all other + run types (including self-hosted). Clients should still gate the control on the + run's current state. + """ + is_sandbox_running: Optional[bool] = None """Whether the sandbox environment is currently running""" @@ -228,4 +236,4 @@ class RunItem(BaseModel): """ trigger_url: Optional[str] = None - """URL to the run trigger (e.g. Slack thread, Linear issue, schedule)""" + """URL to the run trigger (e.g. Slack thread, Linear issue, schedule)""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py b/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py index b3ac5b8..f1a50dc 100644 --- a/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py +++ b/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py @@ -1,15 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional - from ..._models import BaseModel -__all__ = ["RunListHandoffAttachmentsResponse", "Attachment"] +from typing import Optional, List +__all__ = ["RunListHandoffAttachmentsResponse", "Attachment"] class Attachment(BaseModel): """A handoff snapshot attachment exposed for download.""" - attachment_id: str """Identifier for the snapshot attachment within the run.""" @@ -22,12 +20,10 @@ class Attachment(BaseModel): mime_type: Optional[str] = None """MIME type of the snapshot attachment, if known.""" - class RunListHandoffAttachmentsResponse(BaseModel): """Response body for listing handoff snapshot attachments.""" - attachments: List[Attachment] """ Handoff snapshot attachments exposed by the latest ended execution. Empty when no ended execution exists or no files were uploaded. - """ + """ \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/run_list_params.py b/src/oz_agent_sdk/types/agent/run_list_params.py index 2e2d36f..5763223 100644 --- a/src/oz_agent_sdk/types/agent/run_list_params.py +++ b/src/oz_agent_sdk/types/agent/run_list_params.py @@ -2,16 +2,19 @@ from __future__ import annotations -from typing import List, Union +from typing_extensions import TypedDict, Literal, Annotated + +from typing import Union, List + from datetime import datetime -from typing_extensions import Literal, Annotated, TypedDict from ..._utils import PropertyInfo -from .run_state import RunState + from .run_source_type import RunSourceType -__all__ = ["RunListParams"] +from .run_state import RunState +__all__ = ["RunListParams"] class RunListParams(TypedDict, total=False): ancestor_run_id: str @@ -23,10 +26,10 @@ class RunListParams(TypedDict, total=False): artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] """Filter runs by artifact type""" - created_after: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + created_after: Annotated[Union[str, datetime], PropertyInfo(format = "iso8601")] """Filter runs created after this timestamp (RFC3339 format)""" - created_before: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + created_before: Annotated[Union[str, datetime], PropertyInfo(format = "iso8601")] """Filter runs created before this timestamp (RFC3339 format)""" creator: str @@ -93,5 +96,5 @@ class RunListParams(TypedDict, total=False): Can be specified multiple times to match any of the given states. """ - updated_after: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] - """Filter runs updated after this timestamp (RFC3339 format)""" + updated_after: Annotated[Union[str, datetime], PropertyInfo(format = "iso8601")] + """Filter runs updated after this timestamp (RFC3339 format)""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/run_source_type.py b/src/oz_agent_sdk/types/agent/run_source_type.py index 344fa13..77d0cdb 100644 --- a/src/oz_agent_sdk/types/agent/run_source_type.py +++ b/src/oz_agent_sdk/types/agent/run_source_type.py @@ -1,9 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, TypeAliasType, TypeAlias __all__ = ["RunSourceType"] -RunSourceType: TypeAlias = Literal[ - "LINEAR", "API", "SLACK", "LOCAL", "SCHEDULED_AGENT", "WEB_APP", "GITHUB_ACTION", "CLOUD_MODE", "CLI" -] +RunSourceType: TypeAlias = Literal["LINEAR", "API", "SLACK", "LOCAL", "SCHEDULED_AGENT", "WEB_APP", "GITHUB_ACTION", "CLOUD_MODE", "CLI"] \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/run_state.py b/src/oz_agent_sdk/types/agent/run_state.py index c3fbe73..9d07ca0 100644 --- a/src/oz_agent_sdk/types/agent/run_state.py +++ b/src/oz_agent_sdk/types/agent/run_state.py @@ -1,9 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, TypeAliasType, TypeAlias __all__ = ["RunState"] -RunState: TypeAlias = Literal[ - "QUEUED", "PENDING", "CLAIMED", "INPROGRESS", "SUCCEEDED", "FAILED", "BLOCKED", "ERROR", "CANCELLED" -] +RunState: TypeAlias = Literal["QUEUED", "PENDING", "CLAIMED", "INPROGRESS", "SUCCEEDED", "FAILED", "BLOCKED", "ERROR", "CANCELLED"] \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py index abc435b..5b3ae2a 100644 --- a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py +++ b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py @@ -2,11 +2,10 @@ from __future__ import annotations -from typing_extensions import Literal, TypedDict +from typing_extensions import TypedDict, Literal __all__ = ["RunSubmitFollowupParams"] - class RunSubmitFollowupParams(TypedDict, total=False): message: str """The follow-up message to send to the run.""" @@ -16,4 +15,4 @@ class RunSubmitFollowupParams(TypedDict, total=False): Defaults to `normal` when omitted. The server does not infer mode from prompt prefixes such as `/plan`. - """ + """ \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/schedule_create_params.py b/src/oz_agent_sdk/types/agent/schedule_create_params.py index 484b594..cca91bf 100644 --- a/src/oz_agent_sdk/types/agent/schedule_create_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_create_params.py @@ -2,13 +2,12 @@ from __future__ import annotations -from typing_extensions import Literal, Required, TypedDict +from typing_extensions import TypedDict, Required, Literal from ..ambient_agent_config_param import AmbientAgentConfigParam __all__ = ["ScheduleCreateParams"] - class ScheduleCreateParams(TypedDict, total=False): cron_schedule: Required[str] """ @@ -48,4 +47,4 @@ class ScheduleCreateParams(TypedDict, total=False): """ Whether to create a team-owned schedule. Defaults to true for users on a single team. - """ + """ \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/schedule_delete_response.py b/src/oz_agent_sdk/types/agent/schedule_delete_response.py index af8e5fd..ad1c739 100644 --- a/src/oz_agent_sdk/types/agent/schedule_delete_response.py +++ b/src/oz_agent_sdk/types/agent/schedule_delete_response.py @@ -4,7 +4,6 @@ __all__ = ["ScheduleDeleteResponse"] - class ScheduleDeleteResponse(BaseModel): success: bool - """Whether the deletion was successful""" + """Whether the deletion was successful""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/schedule_list_response.py b/src/oz_agent_sdk/types/agent/schedule_list_response.py index e0983ef..13af968 100644 --- a/src/oz_agent_sdk/types/agent/schedule_list_response.py +++ b/src/oz_agent_sdk/types/agent/schedule_list_response.py @@ -1,13 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from ..._models import BaseModel + from typing import List -from ..._models import BaseModel from .scheduled_agent_item import ScheduledAgentItem __all__ = ["ScheduleListResponse"] - class ScheduleListResponse(BaseModel): schedules: List[ScheduledAgentItem] - """List of scheduled agents""" + """List of scheduled agents""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/schedule_update_params.py b/src/oz_agent_sdk/types/agent/schedule_update_params.py index 1ca6805..b2a35ee 100644 --- a/src/oz_agent_sdk/types/agent/schedule_update_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_update_params.py @@ -2,13 +2,12 @@ from __future__ import annotations -from typing_extensions import Literal, Required, TypedDict +from typing_extensions import TypedDict, Required, Literal from ..ambient_agent_config_param import AmbientAgentConfigParam __all__ = ["ScheduleUpdateParams"] - class ScheduleUpdateParams(TypedDict, total=False): cron_schedule: Required[str] """Cron expression defining when the agent runs""" @@ -39,4 +38,4 @@ class ScheduleUpdateParams(TypedDict, total=False): """ The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec or agent_config.skills is provided. - """ + """ \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/scheduled_agent_history_item.py b/src/oz_agent_sdk/types/agent/scheduled_agent_history_item.py index d8ad5f7..4a6994e 100644 --- a/src/oz_agent_sdk/types/agent/scheduled_agent_history_item.py +++ b/src/oz_agent_sdk/types/agent/scheduled_agent_history_item.py @@ -1,18 +1,17 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from ..._models import BaseModel + from typing import Optional -from datetime import datetime -from ..._models import BaseModel +from datetime import datetime __all__ = ["ScheduledAgentHistoryItem"] - class ScheduledAgentHistoryItem(BaseModel): """Scheduler-derived history metadata for a scheduled agent""" - last_ran: Optional[datetime] = None """Timestamp of the last successful run (RFC3339)""" next_run: Optional[datetime] = None - """Timestamp of the next scheduled run (RFC3339)""" + """Timestamp of the next scheduled run (RFC3339)""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/scheduled_agent_item.py b/src/oz_agent_sdk/types/agent/scheduled_agent_item.py index d307d25..5c2c73f 100644 --- a/src/oz_agent_sdk/types/agent/scheduled_agent_item.py +++ b/src/oz_agent_sdk/types/agent/scheduled_agent_item.py @@ -1,17 +1,22 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from ..._models import BaseModel + from datetime import datetime -from ..scope import Scope -from ..._models import BaseModel -from ..user_profile import UserProfile +from typing import Optional + from ..ambient_agent_config import AmbientAgentConfig + +from ..user_profile import UserProfile + from ..cloud_environment_config import CloudEnvironmentConfig + from .scheduled_agent_history_item import ScheduledAgentHistoryItem -__all__ = ["ScheduledAgentItem"] +from ..scope import Scope +__all__ = ["ScheduledAgentItem"] class ScheduledAgentItem(BaseModel): id: str @@ -58,4 +63,4 @@ class ScheduledAgentItem(BaseModel): scope: Optional[Scope] = None """Ownership scope for a resource (team or personal)""" - updated_by: Optional[UserProfile] = None + updated_by: Optional[UserProfile] = None \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent/session_check_redirect_response.py b/src/oz_agent_sdk/types/agent/session_check_redirect_response.py index 9a287fc..47d50d4 100644 --- a/src/oz_agent_sdk/types/agent/session_check_redirect_response.py +++ b/src/oz_agent_sdk/types/agent/session_check_redirect_response.py @@ -1,12 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional - from ..._models import BaseModel -__all__ = ["SessionCheckRedirectResponse"] +from typing import Optional +__all__ = ["SessionCheckRedirectResponse"] class SessionCheckRedirectResponse(BaseModel): conversation_id: Optional[str] = None - """The conversation ID to redirect to (only present when redirect is needed)""" + """The conversation ID to redirect to (only present when redirect is needed)""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent_get_artifact_response.py b/src/oz_agent_sdk/types/agent_get_artifact_response.py index 7e835c8..4fef192 100644 --- a/src/oz_agent_sdk/types/agent_get_artifact_response.py +++ b/src/oz_agent_sdk/types/agent_get_artifact_response.py @@ -1,26 +1,19 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional -from datetime import datetime -from typing_extensions import Literal, Annotated, TypeAlias -from .._utils import PropertyInfo from .._models import BaseModel -__all__ = [ - "AgentGetArtifactResponse", - "PlanArtifactResponse", - "PlanArtifactResponseData", - "ScreenshotArtifactResponse", - "ScreenshotArtifactResponseData", - "FileArtifactResponse", - "FileArtifactResponseData", -] +from typing_extensions import Literal, Annotated, TypeAliasType, TypeAlias +from datetime import datetime + +from .._utils import PropertyInfo + +__all__ = ["AgentGetArtifactResponse", "PlanArtifactResponse", "PlanArtifactResponseData", "ScreenshotArtifactResponse", "ScreenshotArtifactResponseData", "FileArtifactResponse", "FileArtifactResponseData"] class PlanArtifactResponseData(BaseModel): """Response data for a plan artifact, including current markdown content.""" - content: str """Current markdown content of the plan""" @@ -39,10 +32,8 @@ class PlanArtifactResponseData(BaseModel): url: Optional[str] = None """URL to open the plan in Warp Drive""" - class PlanArtifactResponse(BaseModel): """Response for retrieving a plan artifact.""" - artifact_type: Literal["PLAN"] """Type of the artifact""" @@ -55,10 +46,8 @@ class PlanArtifactResponse(BaseModel): data: PlanArtifactResponseData """Response data for a plan artifact, including current markdown content.""" - class ScreenshotArtifactResponseData(BaseModel): """Response data for a screenshot artifact, including a signed download URL.""" - content_type: str """MIME type of the screenshot (e.g., image/png)""" @@ -71,10 +60,8 @@ class ScreenshotArtifactResponseData(BaseModel): description: Optional[str] = None """Optional description of the screenshot""" - class ScreenshotArtifactResponse(BaseModel): """Response for retrieving a screenshot artifact.""" - artifact_type: Literal["SCREENSHOT"] """Type of the artifact""" @@ -87,10 +74,8 @@ class ScreenshotArtifactResponse(BaseModel): data: ScreenshotArtifactResponseData """Response data for a screenshot artifact, including a signed download URL.""" - class FileArtifactResponseData(BaseModel): """Response data for a file artifact, including a signed download URL.""" - content_type: str """MIME type of the uploaded file""" @@ -112,10 +97,8 @@ class FileArtifactResponseData(BaseModel): size_bytes: Optional[int] = None """Size of the uploaded file in bytes""" - class FileArtifactResponse(BaseModel): """Response for retrieving a file artifact.""" - artifact_type: Literal["FILE"] """Type of the artifact""" @@ -128,8 +111,4 @@ class FileArtifactResponse(BaseModel): data: FileArtifactResponseData """Response data for a file artifact, including a signed download URL.""" - -AgentGetArtifactResponse: TypeAlias = Annotated[ - Union[PlanArtifactResponse, ScreenshotArtifactResponse, FileArtifactResponse], - PropertyInfo(discriminator="artifact_type"), -] +AgentGetArtifactResponse: TypeAlias = Annotated[Union[PlanArtifactResponse, ScreenshotArtifactResponse, FileArtifactResponse], PropertyInfo(discriminator="artifact_type")] \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent_list_environments_params.py b/src/oz_agent_sdk/types/agent_list_environments_params.py index 481c31d..aa340a4 100644 --- a/src/oz_agent_sdk/types/agent_list_environments_params.py +++ b/src/oz_agent_sdk/types/agent_list_environments_params.py @@ -2,15 +2,14 @@ from __future__ import annotations -from typing_extensions import Literal, TypedDict +from typing_extensions import TypedDict, Literal __all__ = ["AgentListEnvironmentsParams"] - class AgentListEnvironmentsParams(TypedDict, total=False): sort_by: Literal["name", "last_updated"] """Sort order for the returned environments. - `name`: alphabetical by environment name - `last_updated`: most recently updated first (default) - """ + """ \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent_list_environments_response.py b/src/oz_agent_sdk/types/agent_list_environments_response.py index 103845a..79fb430 100644 --- a/src/oz_agent_sdk/types/agent_list_environments_response.py +++ b/src/oz_agent_sdk/types/agent_list_environments_response.py @@ -1,13 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from .._models import BaseModel + from typing import List -from .._models import BaseModel from .cloud_environment import CloudEnvironment __all__ = ["AgentListEnvironmentsResponse"] - class AgentListEnvironmentsResponse(BaseModel): environments: List[CloudEnvironment] - """List of accessible cloud environments""" + """List of accessible cloud environments""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent_list_params.py b/src/oz_agent_sdk/types/agent_list_params.py index d3157f4..26e1300 100644 --- a/src/oz_agent_sdk/types/agent_list_params.py +++ b/src/oz_agent_sdk/types/agent_list_params.py @@ -2,11 +2,10 @@ from __future__ import annotations -from typing_extensions import Literal, TypedDict +from typing_extensions import TypedDict, Literal __all__ = ["AgentListParams"] - class AgentListParams(TypedDict, total=False): include_malformed_skills: bool """When true, includes skills whose SKILL.md file exists but is malformed. @@ -32,4 +31,4 @@ class AgentListParams(TypedDict, total=False): - "name": Sort alphabetically by name (default) - "last_run": Sort by most recently used - """ + """ \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent_list_response.py b/src/oz_agent_sdk/types/agent_list_response.py index b32e870..62bec00 100644 --- a/src/oz_agent_sdk/types/agent_list_response.py +++ b/src/oz_agent_sdk/types/agent_list_response.py @@ -1,13 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from .._models import BaseModel + from typing import List -from .._models import BaseModel from .agent_skill import AgentSkill __all__ = ["AgentListResponse"] - class AgentListResponse(BaseModel): agents: List[AgentSkill] - """List of available agents""" + """List of available agents""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent_run_params.py b/src/oz_agent_sdk/types/agent_run_params.py index 870c2de..788b18f 100644 --- a/src/oz_agent_sdk/types/agent_run_params.py +++ b/src/oz_agent_sdk/types/agent_run_params.py @@ -2,17 +2,20 @@ from __future__ import annotations -from typing import Union, Iterable -from typing_extensions import Literal, Required, Annotated, TypedDict +from typing_extensions import TypedDict, Literal, Annotated, Required + +from typing import Iterable, Union + +from .ambient_agent_config_param import AmbientAgentConfigParam + +from .._models import set_pydantic_config from .._types import Base64FileInput + from .._utils import PropertyInfo -from .._models import set_pydantic_config -from .ambient_agent_config_param import AmbientAgentConfigParam __all__ = ["AgentRunParams", "Attachment"] - class AgentRunParams(TypedDict, total=False): agent_identity_uid: str """ @@ -77,11 +80,9 @@ class AgentRunParams(TypedDict, total=False): title: str """Custom title for the run (auto-generated if not provided)""" - class Attachment(TypedDict, total=False): """A base64-encoded file attachment to include with the prompt""" - - data: Required[Annotated[Union[str, Base64FileInput], PropertyInfo(format="base64")]] + data: Required[Annotated[Union[str, Base64FileInput], PropertyInfo(format = "base64")]] """Base64-encoded attachment data""" file_name: Required[str] @@ -93,5 +94,6 @@ class Attachment(TypedDict, total=False): image/gif, image/webp """ - -set_pydantic_config(Attachment, {"arbitrary_types_allowed": True}) +set_pydantic_config(Attachment, { + "arbitrary_types_allowed": True +}) \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent_run_response.py b/src/oz_agent_sdk/types/agent_run_response.py index fb2480e..812632b 100644 --- a/src/oz_agent_sdk/types/agent_run_response.py +++ b/src/oz_agent_sdk/types/agent_run_response.py @@ -1,12 +1,12 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional - from .._models import BaseModel + from .agent.run_state import RunState -__all__ = ["AgentRunResponse"] +from typing import Optional +__all__ = ["AgentRunResponse"] class AgentRunResponse(BaseModel): run_id: str @@ -33,4 +33,4 @@ class AgentRunResponse(BaseModel): """ at_capacity: Optional[bool] = None - """Whether the system is at capacity when the run was created""" + """Whether the system is at capacity when the run was created""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/agent_skill.py b/src/oz_agent_sdk/types/agent_skill.py index b7b9ef4..5cf4468 100644 --- a/src/oz_agent_sdk/types/agent_skill.py +++ b/src/oz_agent_sdk/types/agent_skill.py @@ -1,12 +1,12 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional -from datetime import datetime - from .._models import BaseModel -__all__ = ["AgentSkill", "Variant", "VariantEnvironment", "VariantSource"] +from typing import Optional, List +from datetime import datetime + +__all__ = ["AgentSkill", "Variant", "VariantEnvironment", "VariantSource"] class VariantEnvironment(BaseModel): name: str @@ -15,7 +15,6 @@ class VariantEnvironment(BaseModel): uid: str """Unique identifier for the environment""" - class VariantSource(BaseModel): name: str """GitHub repository name""" @@ -33,7 +32,6 @@ class VariantSource(BaseModel): linked to environments). """ - class Variant(BaseModel): id: str """ @@ -62,10 +60,9 @@ class Variant(BaseModel): last_run_timestamp: Optional[datetime] = None """Timestamp of the last time this skill was run (RFC3339)""" - class AgentSkill(BaseModel): name: str """Human-readable name of the agent""" variants: List[Variant] - """Available variants of this agent""" + """Available variants of this agent""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index a12a31a..6cc94a6 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -1,30 +1,22 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional -from typing_extensions import Literal +from .._models import BaseModel -from pydantic import Field as FieldInfo +from typing import Optional, Dict, List + +from typing_extensions import Literal -from .._models import BaseModel from .mcp_server_config import McpServerConfig -__all__ = [ - "AmbientAgentConfig", - "Harness", - "HarnessAuthSecrets", - "InferenceProviders", - "InferenceProvidersAws", - "MemoryStore", - "SessionSharing", -] +from pydantic import Field as FieldInfo +__all__ = ["AmbientAgentConfig", "Harness", "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws", "MemoryStore", "SessionSharing"] class Harness(BaseModel): """ Specifies which execution harness to use for the agent run. Default (nil/empty) uses Warp's built-in harness. """ - type: Optional[Literal["oz", "claude", "gemini", "codex"]] = None """The harness type identifier. @@ -34,13 +26,11 @@ class Harness(BaseModel): - codex: Codex CLI harness """ - class HarnessAuthSecrets(BaseModel): """ Authentication secrets for third-party harnesses. Only the secret for the harness specified gets injected into the environment. """ - claude_auth_secret_name: Optional[str] = None """ Name of a managed secret for Claude Code harness authentication. The secret must @@ -55,13 +45,11 @@ class HarnessAuthSecrets(BaseModel): "codex". """ - class InferenceProvidersAws(BaseModel): """ Configures AWS Bedrock as the LLM inference provider for this agent or run. """ - disabled: Optional[bool] = None """If true, opt out of Bedrock at this layer.""" @@ -71,17 +59,13 @@ class InferenceProvidersAws(BaseModel): role_arn: Optional[str] = None """IAM role ARN to assume when calling Bedrock.""" - class InferenceProviders(BaseModel): """Inference provider settings used for LLM calls.""" - aws: Optional[InferenceProvidersAws] = None """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" - class MemoryStore(BaseModel): """Reference to a memory store to attach to an agent.""" - access: Literal["read_write", "read_only"] """Access level for the store.""" @@ -91,7 +75,6 @@ class MemoryStore(BaseModel): uid: str """UID of the memory store.""" - class SessionSharing(BaseModel): """ Configures sharing behavior for the run's shared session. @@ -101,7 +84,6 @@ class SessionSharing(BaseModel): link viewers can read the conversation without being on the run's team. Subject to the workspace-level anyone-with-link sharing setting. """ - public_access: Optional[Literal["VIEWER", "EDITOR"]] = None """ Grants anyone-with-link access at the specified level to the run's shared @@ -113,10 +95,8 @@ class SessionSharing(BaseModel): still be authenticated Warp users. """ - class AmbientAgentConfig(BaseModel): """Configuration for a cloud agent run""" - base_prompt: Optional[str] = None """Custom base prompt for the agent""" @@ -157,7 +137,7 @@ class AmbientAgentConfig(BaseModel): memory_stores: Optional[List[MemoryStore]] = None """Memory stores to attach to this run.""" - api_model_id: Optional[str] = FieldInfo(alias="model_id", default=None) + api_model_id: Optional[str] = FieldInfo(alias = "model_id", default = None) """LLM model to use (uses team default if not specified)""" name: Optional[str] = None @@ -200,4 +180,4 @@ class AmbientAgentConfig(BaseModel): """ Self-hosted worker ID that should execute this task. If not specified or set to "warp", the task runs on Warp-hosted workers. - """ + """ \ No newline at end of file diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index e1f241e..a22f34b 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -3,28 +3,20 @@ from __future__ import annotations from typing import Dict, Iterable -from typing_extensions import Literal, Required, TypedDict -from .._types import SequenceNotStr from .mcp_server_config_param import McpServerConfigParam -__all__ = [ - "AmbientAgentConfigParam", - "Harness", - "HarnessAuthSecrets", - "InferenceProviders", - "InferenceProvidersAws", - "MemoryStore", - "SessionSharing", -] +from .._types import SequenceNotStr + +from typing_extensions import Literal, TypedDict, Required +__all__ = ["AmbientAgentConfigParam", "Harness", "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws", "MemoryStore", "SessionSharing"] class Harness(TypedDict, total=False): """ Specifies which execution harness to use for the agent run. Default (nil/empty) uses Warp's built-in harness. """ - type: Literal["oz", "claude", "gemini", "codex"] """The harness type identifier. @@ -34,13 +26,11 @@ class Harness(TypedDict, total=False): - codex: Codex CLI harness """ - class HarnessAuthSecrets(TypedDict, total=False): """ Authentication secrets for third-party harnesses. Only the secret for the harness specified gets injected into the environment. """ - claude_auth_secret_name: str """ Name of a managed secret for Claude Code harness authentication. The secret must @@ -55,13 +45,11 @@ class HarnessAuthSecrets(TypedDict, total=False): "codex". """ - class InferenceProvidersAws(TypedDict, total=False): """ Configures AWS Bedrock as the LLM inference provider for this agent or run. """ - disabled: bool """If true, opt out of Bedrock at this layer.""" @@ -71,17 +59,13 @@ class InferenceProvidersAws(TypedDict, total=False): role_arn: str """IAM role ARN to assume when calling Bedrock.""" - class InferenceProviders(TypedDict, total=False): """Inference provider settings used for LLM calls.""" - aws: InferenceProvidersAws """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" - class MemoryStore(TypedDict, total=False): """Reference to a memory store to attach to an agent.""" - access: Required[Literal["read_write", "read_only"]] """Access level for the store.""" @@ -91,7 +75,6 @@ class MemoryStore(TypedDict, total=False): uid: Required[str] """UID of the memory store.""" - class SessionSharing(TypedDict, total=False): """ Configures sharing behavior for the run's shared session. @@ -101,7 +84,6 @@ class SessionSharing(TypedDict, total=False): link viewers can read the conversation without being on the run's team. Subject to the workspace-level anyone-with-link sharing setting. """ - public_access: Literal["VIEWER", "EDITOR"] """ Grants anyone-with-link access at the specified level to the run's shared @@ -113,10 +95,8 @@ class SessionSharing(TypedDict, total=False): still be authenticated Warp users. """ - class AmbientAgentConfigParam(TypedDict, total=False): """Configuration for a cloud agent run""" - base_prompt: str """Custom base prompt for the agent""" @@ -200,4 +180,4 @@ class AmbientAgentConfigParam(TypedDict, total=False): """ Self-hosted worker ID that should execute this task. If not specified or set to "warp", the task runs on Warp-hosted workers. - """ + """ \ No newline at end of file diff --git a/src/oz_agent_sdk/types/aws_provider_config.py b/src/oz_agent_sdk/types/aws_provider_config.py index 61020d8..c358b4e 100644 --- a/src/oz_agent_sdk/types/aws_provider_config.py +++ b/src/oz_agent_sdk/types/aws_provider_config.py @@ -4,9 +4,7 @@ __all__ = ["AwsProviderConfig"] - class AwsProviderConfig(BaseModel): """AWS IAM role assumption settings""" - role_arn: str - """AWS IAM role ARN to assume""" + """AWS IAM role ARN to assume""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/cloud_environment.py b/src/oz_agent_sdk/types/cloud_environment.py index 4bde98c..537e08f 100644 --- a/src/oz_agent_sdk/types/cloud_environment.py +++ b/src/oz_agent_sdk/types/cloud_environment.py @@ -1,20 +1,23 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from .._models import BaseModel + from datetime import datetime -from .scope import Scope -from .._models import BaseModel -from .user_profile import UserProfile from .agent.run_state import RunState + +from typing import Optional + from .cloud_environment_config import CloudEnvironmentConfig -__all__ = ["CloudEnvironment", "LastTaskCreated"] +from .user_profile import UserProfile + +from .scope import Scope +__all__ = ["CloudEnvironment", "LastTaskCreated"] class LastTaskCreated(BaseModel): """Summary of the most recently created task for an environment""" - id: str """Unique identifier of the task""" @@ -44,10 +47,8 @@ class LastTaskCreated(BaseModel): started_at: Optional[datetime] = None """When the task started running (RFC3339), null if not yet started""" - class CloudEnvironment(BaseModel): """A cloud environment for running agents""" - config: CloudEnvironmentConfig """Configuration for a cloud environment used by scheduled agents""" @@ -71,4 +72,4 @@ class CloudEnvironment(BaseModel): """Timestamp of the most recent task run in this environment (RFC3339)""" scope: Optional[Scope] = None - """Ownership scope for a resource (team or personal)""" + """Ownership scope for a resource (team or personal)""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/cloud_environment_config.py b/src/oz_agent_sdk/types/cloud_environment_config.py index 15ef158..61f034b 100644 --- a/src/oz_agent_sdk/types/cloud_environment_config.py +++ b/src/oz_agent_sdk/types/cloud_environment_config.py @@ -1,14 +1,15 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional - from .._models import BaseModel + +from typing import Optional, List + from .aws_provider_config import AwsProviderConfig + from .gcp_provider_config import GcpProviderConfig __all__ = ["CloudEnvironmentConfig", "GitHubRepo", "Providers"] - class GitHubRepo(BaseModel): owner: str """GitHub repository owner (user or organization)""" @@ -16,20 +17,16 @@ class GitHubRepo(BaseModel): repo: str """GitHub repository name""" - class Providers(BaseModel): """Optional cloud provider configurations for automatic auth""" - aws: Optional[AwsProviderConfig] = None """AWS IAM role assumption settings""" gcp: Optional[GcpProviderConfig] = None """GCP Workload Identity Federation settings""" - class CloudEnvironmentConfig(BaseModel): """Configuration for a cloud environment used by scheduled agents""" - description: Optional[str] = None """Optional description of the environment""" @@ -46,4 +43,4 @@ class CloudEnvironmentConfig(BaseModel): """Optional cloud provider configurations for automatic auth""" setup_commands: Optional[List[str]] = None - """Shell commands to run during environment setup""" + """Shell commands to run during environment setup""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/error_code.py b/src/oz_agent_sdk/types/error_code.py index 5732142..b734fbf 100644 --- a/src/oz_agent_sdk/types/error_code.py +++ b/src/oz_agent_sdk/types/error_code.py @@ -1,24 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, TypeAliasType, TypeAlias __all__ = ["ErrorCode"] -ErrorCode: TypeAlias = Literal[ - "insufficient_credits", - "feature_not_available", - "external_authentication_required", - "not_authorized", - "invalid_request", - "resource_not_found", - "budget_exceeded", - "integration_disabled", - "integration_not_configured", - "operation_not_supported", - "environment_setup_failed", - "content_policy_violation", - "conflict", - "authentication_required", - "resource_unavailable", - "internal_error", -] +ErrorCode: TypeAlias = Literal["insufficient_credits", "feature_not_available", "external_authentication_required", "not_authorized", "invalid_request", "resource_not_found", "budget_exceeded", "integration_disabled", "integration_not_configured", "operation_not_supported", "environment_setup_failed", "content_policy_violation", "conflict", "authentication_required", "resource_unavailable", "internal_error"] \ No newline at end of file diff --git a/src/oz_agent_sdk/types/gcp_provider_config.py b/src/oz_agent_sdk/types/gcp_provider_config.py index e849b7e..bf43a23 100644 --- a/src/oz_agent_sdk/types/gcp_provider_config.py +++ b/src/oz_agent_sdk/types/gcp_provider_config.py @@ -1,15 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional - from .._models import BaseModel -__all__ = ["GcpProviderConfig"] +from typing import Optional +__all__ = ["GcpProviderConfig"] class GcpProviderConfig(BaseModel): """GCP Workload Identity Federation settings""" - project_number: str """GCP project number""" @@ -20,4 +18,4 @@ class GcpProviderConfig(BaseModel): """Workload Identity Federation provider ID""" service_account_email: Optional[str] = None - """Optional GCP service account email to impersonate""" + """Optional GCP service account email to impersonate""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/mcp_server_config.py b/src/oz_agent_sdk/types/mcp_server_config.py index c9b7134..3f77e7b 100644 --- a/src/oz_agent_sdk/types/mcp_server_config.py +++ b/src/oz_agent_sdk/types/mcp_server_config.py @@ -1,18 +1,16 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional - from .._models import BaseModel -__all__ = ["McpServerConfig"] +from typing import Optional, List, Dict +__all__ = ["McpServerConfig"] class McpServerConfig(BaseModel): """Configuration for an MCP server. Must have exactly one of: warp_id, command, or url. """ - args: Optional[List[str]] = None """Stdio transport - command arguments""" @@ -29,4 +27,4 @@ class McpServerConfig(BaseModel): """SSE/HTTP transport - server URL""" warp_id: Optional[str] = None - """Reference to a Warp shared MCP server by UUID""" + """Reference to a Warp shared MCP server by UUID""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/mcp_server_config_param.py b/src/oz_agent_sdk/types/mcp_server_config_param.py index 63a63aa..8124273 100644 --- a/src/oz_agent_sdk/types/mcp_server_config_param.py +++ b/src/oz_agent_sdk/types/mcp_server_config_param.py @@ -2,20 +2,19 @@ from __future__ import annotations +from .._types import SequenceNotStr + from typing import Dict -from typing_extensions import TypedDict -from .._types import SequenceNotStr +from typing_extensions import TypedDict __all__ = ["McpServerConfigParam"] - class McpServerConfigParam(TypedDict, total=False): """Configuration for an MCP server. Must have exactly one of: warp_id, command, or url. """ - args: SequenceNotStr[str] """Stdio transport - command arguments""" @@ -32,4 +31,4 @@ class McpServerConfigParam(TypedDict, total=False): """SSE/HTTP transport - server URL""" warp_id: str - """Reference to a Warp shared MCP server by UUID""" + """Reference to a Warp shared MCP server by UUID""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/scope.py b/src/oz_agent_sdk/types/scope.py index ac765e3..c086d02 100644 --- a/src/oz_agent_sdk/types/scope.py +++ b/src/oz_agent_sdk/types/scope.py @@ -1,18 +1,17 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from .._models import BaseModel + from typing_extensions import Literal -from .._models import BaseModel +from typing import Optional __all__ = ["Scope"] - class Scope(BaseModel): """Ownership scope for a resource (team or personal)""" - type: Literal["User", "Team"] """Type of ownership ("User" for personal, "Team" for team-owned)""" uid: Optional[str] = None - """UID of the owning user or team""" + """UID of the owning user or team""" \ No newline at end of file diff --git a/src/oz_agent_sdk/types/user_profile.py b/src/oz_agent_sdk/types/user_profile.py index 5892be4..c4ca035 100644 --- a/src/oz_agent_sdk/types/user_profile.py +++ b/src/oz_agent_sdk/types/user_profile.py @@ -1,13 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from .._models import BaseModel + from typing import Optional -from typing_extensions import Literal -from .._models import BaseModel +from typing_extensions import Literal __all__ = ["UserProfile"] - class UserProfile(BaseModel): display_name: Optional[str] = None """Display name of the creator""" @@ -22,4 +22,4 @@ class UserProfile(BaseModel): """Type of the creator principal""" uid: Optional[str] = None - """Unique identifier of the creator""" + """Unique identifier of the creator""" \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py index fd8019a..bd67c17 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. \ No newline at end of file diff --git a/tests/api_resources/__init__.py b/tests/api_resources/__init__.py index fd8019a..bd67c17 100644 --- a/tests/api_resources/__init__.py +++ b/tests/api_resources/__init__.py @@ -1 +1 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. \ No newline at end of file diff --git a/tests/api_resources/agent/__init__.py b/tests/api_resources/agent/__init__.py index fd8019a..bd67c17 100644 --- a/tests/api_resources/agent/__init__.py +++ b/tests/api_resources/agent/__init__.py @@ -1 +1 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. \ No newline at end of file diff --git a/tests/api_resources/agent/test_agent_.py b/tests/api_resources/agent/test_agent_.py index dbc1785..04d9bfa 100644 --- a/tests/api_resources/agent/test_agent_.py +++ b/tests/api_resources/agent/test_agent_.py @@ -2,23 +2,27 @@ from __future__ import annotations -import os -from typing import Any, cast +from oz_agent_sdk import OzAPI, AsyncOzAPI -import pytest +from oz_agent_sdk.types.agent import AgentResponse, ListAgentIdentitiesResponse -from tests.utils import assert_matches_type +from typing import cast, Any + +import os +import pytest +import httpx +from typing_extensions import get_args +from respx import MockRouter from oz_agent_sdk import OzAPI, AsyncOzAPI -from oz_agent_sdk.types.agent import ( - AgentResponse, - ListAgentIdentitiesResponse, -) +from tests.utils import assert_matches_type +from oz_agent_sdk.types.agent import agent_create_params +from oz_agent_sdk.types.agent import agent_update_params base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - class TestAgent: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=['loose', 'strict']) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -26,7 +30,7 @@ def test_method_create(self, client: OzAPI) -> None: agent = client.agent.agent.create( name="name", ) - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -52,48 +56,53 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "foo": { "args": ["string"], "command": "command", - "env": {"foo": "string"}, - "headers": {"foo": "string"}, + "env": { + "foo": "string" + }, + "headers": { + "foo": "string" + }, "url": "https://example.com", "warp_id": "warp_id", } }, - memory_stores=[ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + memory_stores=[{ + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + }], prompt="prompt", - secrets=[{"name": "name"}], + secrets=[{ + "name": "name" + }], skills=["string"], ) - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_create(self, client: OzAPI) -> None: + response = client.agent.agent.with_raw_response.create( name="name", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_create(self, client: OzAPI) -> None: with client.agent.agent.with_streaming_response.create( name="name", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -103,7 +112,7 @@ def test_method_update(self, client: OzAPI) -> None: agent = client.agent.agent.update( uid="uid", ) - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -129,49 +138,54 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "foo": { "args": ["string"], "command": "command", - "env": {"foo": "string"}, - "headers": {"foo": "string"}, + "env": { + "foo": "string" + }, + "headers": { + "foo": "string" + }, "url": "https://example.com", "warp_id": "warp_id", } }, - memory_stores=[ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + memory_stores=[{ + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + }], name="name", prompt="prompt", - secrets=[{"name": "name"}], + secrets=[{ + "name": "name" + }], skills=["string"], ) - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_update(self, client: OzAPI) -> None: + response = client.agent.agent.with_raw_response.update( uid="uid", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_update(self, client: OzAPI) -> None: with client.agent.agent.with_streaming_response.update( uid="uid", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -179,35 +193,36 @@ def test_streaming_response_update(self, client: OzAPI) -> None: @parametrize def test_path_params_update(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - client.agent.agent.with_raw_response.update( - uid="", - ) + client.agent.agent.with_raw_response.update( + uid="", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list(self, client: OzAPI) -> None: agent = client.agent.agent.list() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + assert_matches_type(ListAgentIdentitiesResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_list(self, client: OzAPI) -> None: + response = client.agent.agent.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + assert_matches_type(ListAgentIdentitiesResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_list(self, client: OzAPI) -> None: - with client.agent.agent.with_streaming_response.list() as response: + with client.agent.agent.with_streaming_response.list() as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + assert_matches_type(ListAgentIdentitiesResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -222,12 +237,13 @@ def test_method_delete(self, client: OzAPI) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_delete(self, client: OzAPI) -> None: + response = client.agent.agent.with_raw_response.delete( "uid", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() assert agent is None @@ -236,9 +252,9 @@ def test_raw_response_delete(self, client: OzAPI) -> None: def test_streaming_response_delete(self, client: OzAPI) -> None: with client.agent.agent.with_streaming_response.delete( "uid", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() assert agent is None @@ -249,9 +265,9 @@ def test_streaming_response_delete(self, client: OzAPI) -> None: @parametrize def test_path_params_delete(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - client.agent.agent.with_raw_response.delete( - "", - ) + client.agent.agent.with_raw_response.delete( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -259,31 +275,32 @@ def test_method_get(self, client: OzAPI) -> None: agent = client.agent.agent.get( "uid", ) - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_get(self, client: OzAPI) -> None: + response = client.agent.agent.with_raw_response.get( "uid", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_get(self, client: OzAPI) -> None: with client.agent.agent.with_streaming_response.get( "uid", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -291,15 +308,12 @@ def test_streaming_response_get(self, client: OzAPI) -> None: @parametrize def test_path_params_get(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - client.agent.agent.with_raw_response.get( - "", - ) - - + client.agent.agent.with_raw_response.get( + "", + ) class TestAsyncAgent: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) + parametrize = pytest.mark.parametrize("async_client", [False, True, {'http_client': 'aiohttp'}], indirect=True, ids=['loose', 'strict', 'aiohttp']) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -307,7 +321,7 @@ async def test_method_create(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.agent.create( name="name", ) - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -333,48 +347,53 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "foo": { "args": ["string"], "command": "command", - "env": {"foo": "string"}, - "headers": {"foo": "string"}, + "env": { + "foo": "string" + }, + "headers": { + "foo": "string" + }, "url": "https://example.com", "warp_id": "warp_id", } }, - memory_stores=[ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + memory_stores=[{ + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + }], prompt="prompt", - secrets=[{"name": "name"}], + secrets=[{ + "name": "name" + }], skills=["string"], ) - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_create(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.agent.with_raw_response.create( name="name", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_create(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.agent.with_streaming_response.create( name="name", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -384,7 +403,7 @@ async def test_method_update(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.agent.update( uid="uid", ) - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -410,49 +429,54 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "foo": { "args": ["string"], "command": "command", - "env": {"foo": "string"}, - "headers": {"foo": "string"}, + "env": { + "foo": "string" + }, + "headers": { + "foo": "string" + }, "url": "https://example.com", "warp_id": "warp_id", } }, - memory_stores=[ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + memory_stores=[{ + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + }], name="name", prompt="prompt", - secrets=[{"name": "name"}], + secrets=[{ + "name": "name" + }], skills=["string"], ) - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_update(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.agent.with_raw_response.update( uid="uid", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_update(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.agent.with_streaming_response.update( uid="uid", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -460,35 +484,36 @@ async def test_streaming_response_update(self, async_client: AsyncOzAPI) -> None @parametrize async def test_path_params_update(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - await async_client.agent.agent.with_raw_response.update( - uid="", - ) + await async_client.agent.agent.with_raw_response.update( + uid="", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.agent.list() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + assert_matches_type(ListAgentIdentitiesResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_list(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.agent.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + assert_matches_type(ListAgentIdentitiesResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_list(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.agent.with_streaming_response.list() as response: + async with async_client.agent.agent.with_streaming_response.list() as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + assert_matches_type(ListAgentIdentitiesResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -503,12 +528,13 @@ async def test_method_delete(self, async_client: AsyncOzAPI) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_delete(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.agent.with_raw_response.delete( "uid", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() assert agent is None @@ -517,9 +543,9 @@ async def test_raw_response_delete(self, async_client: AsyncOzAPI) -> None: async def test_streaming_response_delete(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.agent.with_streaming_response.delete( "uid", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() assert agent is None @@ -530,9 +556,9 @@ async def test_streaming_response_delete(self, async_client: AsyncOzAPI) -> None @parametrize async def test_path_params_delete(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - await async_client.agent.agent.with_raw_response.delete( - "", - ) + await async_client.agent.agent.with_raw_response.delete( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -540,31 +566,32 @@ async def test_method_get(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.agent.get( "uid", ) - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_get(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.agent.with_raw_response.get( "uid", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_get(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.agent.with_streaming_response.get( "uid", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) + assert_matches_type(AgentResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -572,6 +599,6 @@ async def test_streaming_response_get(self, async_client: AsyncOzAPI) -> None: @parametrize async def test_path_params_get(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - await async_client.agent.agent.with_raw_response.get( - "", - ) + await async_client.agent.agent.with_raw_response.get( + "", + ) \ No newline at end of file diff --git a/tests/api_resources/agent/test_conversations.py b/tests/api_resources/agent/test_conversations.py index e1a21d4..e6200f0 100644 --- a/tests/api_resources/agent/test_conversations.py +++ b/tests/api_resources/agent/test_conversations.py @@ -2,20 +2,25 @@ from __future__ import annotations -import os -from typing import Any, cast +from oz_agent_sdk import OzAPI, AsyncOzAPI -import pytest +from oz_agent_sdk.types.agent import ConversationCheckRedirectResponse -from tests.utils import assert_matches_type +from typing import cast, Any + +import os +import pytest +import httpx +from typing_extensions import get_args +from respx import MockRouter from oz_agent_sdk import OzAPI, AsyncOzAPI -from oz_agent_sdk.types.agent import ConversationCheckRedirectResponse +from tests.utils import assert_matches_type base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - class TestConversations: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=['loose', 'strict']) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -23,31 +28,32 @@ def test_method_check_redirect(self, client: OzAPI) -> None: conversation = client.agent.conversations.check_redirect( "conversationId", ) - assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_check_redirect(self, client: OzAPI) -> None: + response = client.agent.conversations.with_raw_response.check_redirect( "conversationId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' conversation = response.parse() - assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_check_redirect(self, client: OzAPI) -> None: with client.agent.conversations.with_streaming_response.check_redirect( "conversationId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' conversation = response.parse() - assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=['response']) assert cast(Any, response.is_closed) is True @@ -55,15 +61,12 @@ def test_streaming_response_check_redirect(self, client: OzAPI) -> None: @parametrize def test_path_params_check_redirect(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): - client.agent.conversations.with_raw_response.check_redirect( - "", - ) - - + client.agent.conversations.with_raw_response.check_redirect( + "", + ) class TestAsyncConversations: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) + parametrize = pytest.mark.parametrize("async_client", [False, True, {'http_client': 'aiohttp'}], indirect=True, ids=['loose', 'strict', 'aiohttp']) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -71,31 +74,32 @@ async def test_method_check_redirect(self, async_client: AsyncOzAPI) -> None: conversation = await async_client.agent.conversations.check_redirect( "conversationId", ) - assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_check_redirect(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.conversations.with_raw_response.check_redirect( "conversationId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' conversation = await response.parse() - assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_check_redirect(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.conversations.with_streaming_response.check_redirect( "conversationId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' conversation = await response.parse() - assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=['response']) assert cast(Any, response.is_closed) is True @@ -103,6 +107,6 @@ async def test_streaming_response_check_redirect(self, async_client: AsyncOzAPI) @parametrize async def test_path_params_check_redirect(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): - await async_client.agent.conversations.with_raw_response.check_redirect( - "", - ) + await async_client.agent.conversations.with_raw_response.check_redirect( + "", + ) \ No newline at end of file diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index 54bb08c..5b92ce3 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -2,25 +2,32 @@ from __future__ import annotations -import os -from typing import Any, cast +from oz_agent_sdk import OzAPI, AsyncOzAPI -import pytest +from oz_agent_sdk.types.agent import RunItem, RunCancelResponse, RunListHandoffAttachmentsResponse + +from typing import cast, Any -from tests.utils import assert_matches_type -from oz_agent_sdk import OzAPI, AsyncOzAPI -from oz_agent_sdk._utils import parse_datetime from oz_agent_sdk.pagination import SyncRunsCursorPage, AsyncRunsCursorPage -from oz_agent_sdk.types.agent import ( - RunItem, - RunListHandoffAttachmentsResponse, -) -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") +from oz_agent_sdk._utils import parse_datetime +import os +import pytest +import httpx +from typing_extensions import get_args +from respx import MockRouter +from oz_agent_sdk import OzAPI, AsyncOzAPI +from tests.utils import assert_matches_type +from oz_agent_sdk.types.agent import run_list_params +from oz_agent_sdk.types.agent import run_submit_followup_params +from oz_agent_sdk.types.agent import RunSourceType + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestRuns: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=['loose', 'strict']) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -28,31 +35,32 @@ def test_method_retrieve(self, client: OzAPI) -> None: run = client.agent.runs.retrieve( "runId", ) - assert_matches_type(RunItem, run, path=["response"]) + assert_matches_type(RunItem, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_retrieve(self, client: OzAPI) -> None: + response = client.agent.runs.with_raw_response.retrieve( "runId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = response.parse() - assert_matches_type(RunItem, run, path=["response"]) + assert_matches_type(RunItem, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_retrieve(self, client: OzAPI) -> None: with client.agent.runs.with_streaming_response.retrieve( "runId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = response.parse() - assert_matches_type(RunItem, run, path=["response"]) + assert_matches_type(RunItem, run, path=['response']) assert cast(Any, response.is_closed) is True @@ -60,15 +68,15 @@ def test_streaming_response_retrieve(self, client: OzAPI) -> None: @parametrize def test_path_params_retrieve(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - client.agent.runs.with_raw_response.retrieve( - "", - ) + client.agent.runs.with_raw_response.retrieve( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list(self, client: OzAPI) -> None: run = client.agent.runs.list() - assert_matches_type(SyncRunsCursorPage[RunItem], run, path=["response"]) + assert_matches_type(SyncRunsCursorPage[RunItem], run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -96,27 +104,28 @@ def test_method_list_with_all_params(self, client: OzAPI) -> None: state=["QUEUED"], updated_after=parse_datetime("2019-12-27T18:11:19.117Z"), ) - assert_matches_type(SyncRunsCursorPage[RunItem], run, path=["response"]) + assert_matches_type(SyncRunsCursorPage[RunItem], run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_list(self, client: OzAPI) -> None: + response = client.agent.runs.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = response.parse() - assert_matches_type(SyncRunsCursorPage[RunItem], run, path=["response"]) + assert_matches_type(SyncRunsCursorPage[RunItem], run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_list(self, client: OzAPI) -> None: - with client.agent.runs.with_streaming_response.list() as response: + with client.agent.runs.with_streaming_response.list() as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = response.parse() - assert_matches_type(SyncRunsCursorPage[RunItem], run, path=["response"]) + assert_matches_type(SyncRunsCursorPage[RunItem], run, path=['response']) assert cast(Any, response.is_closed) is True @@ -126,31 +135,32 @@ def test_method_cancel(self, client: OzAPI) -> None: run = client.agent.runs.cancel( "runId", ) - assert_matches_type(str, run, path=["response"]) + assert_matches_type(str, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_cancel(self, client: OzAPI) -> None: + response = client.agent.runs.with_raw_response.cancel( "runId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = response.parse() - assert_matches_type(str, run, path=["response"]) + assert_matches_type(str, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_cancel(self, client: OzAPI) -> None: with client.agent.runs.with_streaming_response.cancel( "runId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = response.parse() - assert_matches_type(str, run, path=["response"]) + assert_matches_type(str, run, path=['response']) assert cast(Any, response.is_closed) is True @@ -158,9 +168,9 @@ def test_streaming_response_cancel(self, client: OzAPI) -> None: @parametrize def test_path_params_cancel(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - client.agent.runs.with_raw_response.cancel( - "", - ) + client.agent.runs.with_raw_response.cancel( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -168,31 +178,32 @@ def test_method_list_handoff_attachments(self, client: OzAPI) -> None: run = client.agent.runs.list_handoff_attachments( "runId", ) - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_list_handoff_attachments(self, client: OzAPI) -> None: + response = client.agent.runs.with_raw_response.list_handoff_attachments( "runId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = response.parse() - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_list_handoff_attachments(self, client: OzAPI) -> None: with client.agent.runs.with_streaming_response.list_handoff_attachments( "runId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = response.parse() - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=['response']) assert cast(Any, response.is_closed) is True @@ -200,9 +211,9 @@ def test_streaming_response_list_handoff_attachments(self, client: OzAPI) -> Non @parametrize def test_path_params_list_handoff_attachments(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - client.agent.runs.with_raw_response.list_handoff_attachments( - "", - ) + client.agent.runs.with_raw_response.list_handoff_attachments( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -210,7 +221,7 @@ def test_method_submit_followup(self, client: OzAPI) -> None: run = client.agent.runs.submit_followup( run_id="runId", ) - assert_matches_type(object, run, path=["response"]) + assert_matches_type(object, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -220,31 +231,32 @@ def test_method_submit_followup_with_all_params(self, client: OzAPI) -> None: message="message", mode="normal", ) - assert_matches_type(object, run, path=["response"]) + assert_matches_type(object, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_submit_followup(self, client: OzAPI) -> None: + response = client.agent.runs.with_raw_response.submit_followup( run_id="runId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = response.parse() - assert_matches_type(object, run, path=["response"]) + assert_matches_type(object, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_submit_followup(self, client: OzAPI) -> None: with client.agent.runs.with_streaming_response.submit_followup( run_id="runId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = response.parse() - assert_matches_type(object, run, path=["response"]) + assert_matches_type(object, run, path=['response']) assert cast(Any, response.is_closed) is True @@ -252,15 +264,12 @@ def test_streaming_response_submit_followup(self, client: OzAPI) -> None: @parametrize def test_path_params_submit_followup(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - client.agent.runs.with_raw_response.submit_followup( - run_id="", - ) - - + client.agent.runs.with_raw_response.submit_followup( + run_id="", + ) class TestAsyncRuns: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) + parametrize = pytest.mark.parametrize("async_client", [False, True, {'http_client': 'aiohttp'}], indirect=True, ids=['loose', 'strict', 'aiohttp']) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -268,31 +277,32 @@ async def test_method_retrieve(self, async_client: AsyncOzAPI) -> None: run = await async_client.agent.runs.retrieve( "runId", ) - assert_matches_type(RunItem, run, path=["response"]) + assert_matches_type(RunItem, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.runs.with_raw_response.retrieve( "runId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = await response.parse() - assert_matches_type(RunItem, run, path=["response"]) + assert_matches_type(RunItem, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.runs.with_streaming_response.retrieve( "runId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = await response.parse() - assert_matches_type(RunItem, run, path=["response"]) + assert_matches_type(RunItem, run, path=['response']) assert cast(Any, response.is_closed) is True @@ -300,15 +310,15 @@ async def test_streaming_response_retrieve(self, async_client: AsyncOzAPI) -> No @parametrize async def test_path_params_retrieve(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - await async_client.agent.runs.with_raw_response.retrieve( - "", - ) + await async_client.agent.runs.with_raw_response.retrieve( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncOzAPI) -> None: run = await async_client.agent.runs.list() - assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=["response"]) + assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -336,27 +346,28 @@ async def test_method_list_with_all_params(self, async_client: AsyncOzAPI) -> No state=["QUEUED"], updated_after=parse_datetime("2019-12-27T18:11:19.117Z"), ) - assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=["response"]) + assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_list(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.runs.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = await response.parse() - assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=["response"]) + assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_list(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.runs.with_streaming_response.list() as response: + async with async_client.agent.runs.with_streaming_response.list() as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = await response.parse() - assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=["response"]) + assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=['response']) assert cast(Any, response.is_closed) is True @@ -366,31 +377,32 @@ async def test_method_cancel(self, async_client: AsyncOzAPI) -> None: run = await async_client.agent.runs.cancel( "runId", ) - assert_matches_type(str, run, path=["response"]) + assert_matches_type(str, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_cancel(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.runs.with_raw_response.cancel( "runId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = await response.parse() - assert_matches_type(str, run, path=["response"]) + assert_matches_type(str, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_cancel(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.runs.with_streaming_response.cancel( "runId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = await response.parse() - assert_matches_type(str, run, path=["response"]) + assert_matches_type(str, run, path=['response']) assert cast(Any, response.is_closed) is True @@ -398,9 +410,9 @@ async def test_streaming_response_cancel(self, async_client: AsyncOzAPI) -> None @parametrize async def test_path_params_cancel(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - await async_client.agent.runs.with_raw_response.cancel( - "", - ) + await async_client.agent.runs.with_raw_response.cancel( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -408,31 +420,32 @@ async def test_method_list_handoff_attachments(self, async_client: AsyncOzAPI) - run = await async_client.agent.runs.list_handoff_attachments( "runId", ) - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.runs.with_raw_response.list_handoff_attachments( "runId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = await response.parse() - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.runs.with_streaming_response.list_handoff_attachments( "runId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = await response.parse() - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=['response']) assert cast(Any, response.is_closed) is True @@ -440,9 +453,9 @@ async def test_streaming_response_list_handoff_attachments(self, async_client: A @parametrize async def test_path_params_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - await async_client.agent.runs.with_raw_response.list_handoff_attachments( - "", - ) + await async_client.agent.runs.with_raw_response.list_handoff_attachments( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -450,7 +463,7 @@ async def test_method_submit_followup(self, async_client: AsyncOzAPI) -> None: run = await async_client.agent.runs.submit_followup( run_id="runId", ) - assert_matches_type(object, run, path=["response"]) + assert_matches_type(object, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -460,31 +473,32 @@ async def test_method_submit_followup_with_all_params(self, async_client: AsyncO message="message", mode="normal", ) - assert_matches_type(object, run, path=["response"]) + assert_matches_type(object, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_submit_followup(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.runs.with_raw_response.submit_followup( run_id="runId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = await response.parse() - assert_matches_type(object, run, path=["response"]) + assert_matches_type(object, run, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_submit_followup(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.runs.with_streaming_response.submit_followup( run_id="runId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' run = await response.parse() - assert_matches_type(object, run, path=["response"]) + assert_matches_type(object, run, path=['response']) assert cast(Any, response.is_closed) is True @@ -492,6 +506,6 @@ async def test_streaming_response_submit_followup(self, async_client: AsyncOzAPI @parametrize async def test_path_params_submit_followup(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - await async_client.agent.runs.with_raw_response.submit_followup( - run_id="", - ) + await async_client.agent.runs.with_raw_response.submit_followup( + run_id="", + ) \ No newline at end of file diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index 272c7e3..00ce34d 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -2,24 +2,29 @@ from __future__ import annotations -import os -from typing import Any, cast +from oz_agent_sdk import OzAPI, AsyncOzAPI -import pytest +from oz_agent_sdk.types.agent import ScheduledAgentItem, ScheduleListResponse, ScheduleDeleteResponse -from tests.utils import assert_matches_type +from typing import cast, Any + +import os +import pytest +import httpx +from typing_extensions import get_args +from respx import MockRouter from oz_agent_sdk import OzAPI, AsyncOzAPI -from oz_agent_sdk.types.agent import ( - ScheduledAgentItem, - ScheduleListResponse, - ScheduleDeleteResponse, -) +from tests.utils import assert_matches_type +from oz_agent_sdk.types.agent import schedule_create_params +from oz_agent_sdk.types.agent import schedule_update_params +from oz_agent_sdk.types import AmbientAgentConfig +from oz_agent_sdk.types import AmbientAgentConfig base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - class TestSchedules: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=['loose', 'strict']) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -28,7 +33,7 @@ def test_method_create(self, client: OzAPI) -> None: cron_schedule="0 9 * * *", name="Daily Code Review", ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -40,7 +45,9 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": {"type": "oz"}, + "harness": { + "type": "oz" + }, "harness_auth_secrets": { "claude_auth_secret_name": "claude_auth_secret_name", "codex_auth_secret_name": "codex_auth_secret_name", @@ -57,22 +64,26 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "foo": { "args": ["string"], "command": "command", - "env": {"foo": "string"}, - "headers": {"foo": "string"}, + "env": { + "foo": "string" + }, + "headers": { + "foo": "string" + }, "url": "https://example.com", "warp_id": "warp_id", } }, - "memory_stores": [ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + "memory_stores": [{ + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + }], "model_id": "model_id", "name": "name", - "session_sharing": {"public_access": "VIEWER"}, + "session_sharing": { + "public_access": "VIEWER" + }, "skill_spec": "skill_spec", "skills": ["string"], "worker_host": "worker_host", @@ -83,20 +94,21 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: prompt="Review open pull requests and provide feedback", team=True, ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_create(self, client: OzAPI) -> None: + response = client.agent.schedules.with_raw_response.create( cron_schedule="0 9 * * *", name="Daily Code Review", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -104,12 +116,12 @@ def test_streaming_response_create(self, client: OzAPI) -> None: with client.agent.schedules.with_streaming_response.create( cron_schedule="0 9 * * *", name="Daily Code Review", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -119,31 +131,32 @@ def test_method_retrieve(self, client: OzAPI) -> None: schedule = client.agent.schedules.retrieve( "scheduleId", ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_retrieve(self, client: OzAPI) -> None: + response = client.agent.schedules.with_raw_response.retrieve( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_retrieve(self, client: OzAPI) -> None: with client.agent.schedules.with_streaming_response.retrieve( "scheduleId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -151,9 +164,9 @@ def test_streaming_response_retrieve(self, client: OzAPI) -> None: @parametrize def test_path_params_retrieve(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - client.agent.schedules.with_raw_response.retrieve( - "", - ) + client.agent.schedules.with_raw_response.retrieve( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -164,7 +177,7 @@ def test_method_update(self, client: OzAPI) -> None: enabled=True, name="name", ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -178,7 +191,9 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": {"type": "oz"}, + "harness": { + "type": "oz" + }, "harness_auth_secrets": { "claude_auth_secret_name": "claude_auth_secret_name", "codex_auth_secret_name": "codex_auth_secret_name", @@ -195,22 +210,26 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "foo": { "args": ["string"], "command": "command", - "env": {"foo": "string"}, - "headers": {"foo": "string"}, + "env": { + "foo": "string" + }, + "headers": { + "foo": "string" + }, "url": "https://example.com", "warp_id": "warp_id", } }, - "memory_stores": [ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + "memory_stores": [{ + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + }], "model_id": "model_id", "name": "name", - "session_sharing": {"public_access": "VIEWER"}, + "session_sharing": { + "public_access": "VIEWER" + }, "skill_spec": "skill_spec", "skills": ["string"], "worker_host": "worker_host", @@ -219,11 +238,12 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: mode="normal", prompt="prompt", ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_update(self, client: OzAPI) -> None: + response = client.agent.schedules.with_raw_response.update( schedule_id="scheduleId", cron_schedule="cron_schedule", @@ -232,9 +252,9 @@ def test_raw_response_update(self, client: OzAPI) -> None: ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -244,12 +264,12 @@ def test_streaming_response_update(self, client: OzAPI) -> None: cron_schedule="cron_schedule", enabled=True, name="name", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -257,38 +277,39 @@ def test_streaming_response_update(self, client: OzAPI) -> None: @parametrize def test_path_params_update(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - client.agent.schedules.with_raw_response.update( - schedule_id="", - cron_schedule="cron_schedule", - enabled=True, - name="name", - ) + client.agent.schedules.with_raw_response.update( + schedule_id="", + cron_schedule="cron_schedule", + enabled=True, + name="name", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list(self, client: OzAPI) -> None: schedule = client.agent.schedules.list() - assert_matches_type(ScheduleListResponse, schedule, path=["response"]) + assert_matches_type(ScheduleListResponse, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_list(self, client: OzAPI) -> None: + response = client.agent.schedules.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduleListResponse, schedule, path=["response"]) + assert_matches_type(ScheduleListResponse, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_list(self, client: OzAPI) -> None: - with client.agent.schedules.with_streaming_response.list() as response: + with client.agent.schedules.with_streaming_response.list() as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduleListResponse, schedule, path=["response"]) + assert_matches_type(ScheduleListResponse, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -298,31 +319,32 @@ def test_method_delete(self, client: OzAPI) -> None: schedule = client.agent.schedules.delete( "scheduleId", ) - assert_matches_type(ScheduleDeleteResponse, schedule, path=["response"]) + assert_matches_type(ScheduleDeleteResponse, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_delete(self, client: OzAPI) -> None: + response = client.agent.schedules.with_raw_response.delete( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduleDeleteResponse, schedule, path=["response"]) + assert_matches_type(ScheduleDeleteResponse, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_delete(self, client: OzAPI) -> None: with client.agent.schedules.with_streaming_response.delete( "scheduleId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduleDeleteResponse, schedule, path=["response"]) + assert_matches_type(ScheduleDeleteResponse, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -330,9 +352,9 @@ def test_streaming_response_delete(self, client: OzAPI) -> None: @parametrize def test_path_params_delete(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - client.agent.schedules.with_raw_response.delete( - "", - ) + client.agent.schedules.with_raw_response.delete( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -340,31 +362,32 @@ def test_method_pause(self, client: OzAPI) -> None: schedule = client.agent.schedules.pause( "scheduleId", ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_pause(self, client: OzAPI) -> None: + response = client.agent.schedules.with_raw_response.pause( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_pause(self, client: OzAPI) -> None: with client.agent.schedules.with_streaming_response.pause( "scheduleId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -372,9 +395,9 @@ def test_streaming_response_pause(self, client: OzAPI) -> None: @parametrize def test_path_params_pause(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - client.agent.schedules.with_raw_response.pause( - "", - ) + client.agent.schedules.with_raw_response.pause( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -382,31 +405,32 @@ def test_method_resume(self, client: OzAPI) -> None: schedule = client.agent.schedules.resume( "scheduleId", ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_resume(self, client: OzAPI) -> None: + response = client.agent.schedules.with_raw_response.resume( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_resume(self, client: OzAPI) -> None: with client.agent.schedules.with_streaming_response.resume( "scheduleId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -414,15 +438,12 @@ def test_streaming_response_resume(self, client: OzAPI) -> None: @parametrize def test_path_params_resume(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - client.agent.schedules.with_raw_response.resume( - "", - ) - - + client.agent.schedules.with_raw_response.resume( + "", + ) class TestAsyncSchedules: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) + parametrize = pytest.mark.parametrize("async_client", [False, True, {'http_client': 'aiohttp'}], indirect=True, ids=['loose', 'strict', 'aiohttp']) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -431,7 +452,7 @@ async def test_method_create(self, async_client: AsyncOzAPI) -> None: cron_schedule="0 9 * * *", name="Daily Code Review", ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -443,7 +464,9 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": {"type": "oz"}, + "harness": { + "type": "oz" + }, "harness_auth_secrets": { "claude_auth_secret_name": "claude_auth_secret_name", "codex_auth_secret_name": "codex_auth_secret_name", @@ -460,22 +483,26 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "foo": { "args": ["string"], "command": "command", - "env": {"foo": "string"}, - "headers": {"foo": "string"}, + "env": { + "foo": "string" + }, + "headers": { + "foo": "string" + }, "url": "https://example.com", "warp_id": "warp_id", } }, - "memory_stores": [ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + "memory_stores": [{ + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + }], "model_id": "model_id", "name": "name", - "session_sharing": {"public_access": "VIEWER"}, + "session_sharing": { + "public_access": "VIEWER" + }, "skill_spec": "skill_spec", "skills": ["string"], "worker_host": "worker_host", @@ -486,20 +513,21 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> prompt="Review open pull requests and provide feedback", team=True, ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_create(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.schedules.with_raw_response.create( cron_schedule="0 9 * * *", name="Daily Code Review", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -507,12 +535,12 @@ async def test_streaming_response_create(self, async_client: AsyncOzAPI) -> None async with async_client.agent.schedules.with_streaming_response.create( cron_schedule="0 9 * * *", name="Daily Code Review", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -522,31 +550,32 @@ async def test_method_retrieve(self, async_client: AsyncOzAPI) -> None: schedule = await async_client.agent.schedules.retrieve( "scheduleId", ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.schedules.with_raw_response.retrieve( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.schedules.with_streaming_response.retrieve( "scheduleId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -554,9 +583,9 @@ async def test_streaming_response_retrieve(self, async_client: AsyncOzAPI) -> No @parametrize async def test_path_params_retrieve(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - await async_client.agent.schedules.with_raw_response.retrieve( - "", - ) + await async_client.agent.schedules.with_raw_response.retrieve( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -567,7 +596,7 @@ async def test_method_update(self, async_client: AsyncOzAPI) -> None: enabled=True, name="name", ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -581,7 +610,9 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": {"type": "oz"}, + "harness": { + "type": "oz" + }, "harness_auth_secrets": { "claude_auth_secret_name": "claude_auth_secret_name", "codex_auth_secret_name": "codex_auth_secret_name", @@ -598,22 +629,26 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "foo": { "args": ["string"], "command": "command", - "env": {"foo": "string"}, - "headers": {"foo": "string"}, + "env": { + "foo": "string" + }, + "headers": { + "foo": "string" + }, "url": "https://example.com", "warp_id": "warp_id", } }, - "memory_stores": [ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + "memory_stores": [{ + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + }], "model_id": "model_id", "name": "name", - "session_sharing": {"public_access": "VIEWER"}, + "session_sharing": { + "public_access": "VIEWER" + }, "skill_spec": "skill_spec", "skills": ["string"], "worker_host": "worker_host", @@ -622,11 +657,12 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> mode="normal", prompt="prompt", ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_update(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.schedules.with_raw_response.update( schedule_id="scheduleId", cron_schedule="cron_schedule", @@ -635,9 +671,9 @@ async def test_raw_response_update(self, async_client: AsyncOzAPI) -> None: ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -647,12 +683,12 @@ async def test_streaming_response_update(self, async_client: AsyncOzAPI) -> None cron_schedule="cron_schedule", enabled=True, name="name", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -660,38 +696,39 @@ async def test_streaming_response_update(self, async_client: AsyncOzAPI) -> None @parametrize async def test_path_params_update(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - await async_client.agent.schedules.with_raw_response.update( - schedule_id="", - cron_schedule="cron_schedule", - enabled=True, - name="name", - ) + await async_client.agent.schedules.with_raw_response.update( + schedule_id="", + cron_schedule="cron_schedule", + enabled=True, + name="name", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncOzAPI) -> None: schedule = await async_client.agent.schedules.list() - assert_matches_type(ScheduleListResponse, schedule, path=["response"]) + assert_matches_type(ScheduleListResponse, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_list(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.schedules.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduleListResponse, schedule, path=["response"]) + assert_matches_type(ScheduleListResponse, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_list(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.schedules.with_streaming_response.list() as response: + async with async_client.agent.schedules.with_streaming_response.list() as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduleListResponse, schedule, path=["response"]) + assert_matches_type(ScheduleListResponse, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -701,31 +738,32 @@ async def test_method_delete(self, async_client: AsyncOzAPI) -> None: schedule = await async_client.agent.schedules.delete( "scheduleId", ) - assert_matches_type(ScheduleDeleteResponse, schedule, path=["response"]) + assert_matches_type(ScheduleDeleteResponse, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_delete(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.schedules.with_raw_response.delete( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduleDeleteResponse, schedule, path=["response"]) + assert_matches_type(ScheduleDeleteResponse, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_delete(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.schedules.with_streaming_response.delete( "scheduleId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduleDeleteResponse, schedule, path=["response"]) + assert_matches_type(ScheduleDeleteResponse, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -733,9 +771,9 @@ async def test_streaming_response_delete(self, async_client: AsyncOzAPI) -> None @parametrize async def test_path_params_delete(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - await async_client.agent.schedules.with_raw_response.delete( - "", - ) + await async_client.agent.schedules.with_raw_response.delete( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -743,31 +781,32 @@ async def test_method_pause(self, async_client: AsyncOzAPI) -> None: schedule = await async_client.agent.schedules.pause( "scheduleId", ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_pause(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.schedules.with_raw_response.pause( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_pause(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.schedules.with_streaming_response.pause( "scheduleId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -775,9 +814,9 @@ async def test_streaming_response_pause(self, async_client: AsyncOzAPI) -> None: @parametrize async def test_path_params_pause(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - await async_client.agent.schedules.with_raw_response.pause( - "", - ) + await async_client.agent.schedules.with_raw_response.pause( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -785,31 +824,32 @@ async def test_method_resume(self, async_client: AsyncOzAPI) -> None: schedule = await async_client.agent.schedules.resume( "scheduleId", ) - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_resume(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.schedules.with_raw_response.resume( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_resume(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.schedules.with_streaming_response.resume( "scheduleId", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) + assert_matches_type(ScheduledAgentItem, schedule, path=['response']) assert cast(Any, response.is_closed) is True @@ -817,6 +857,6 @@ async def test_streaming_response_resume(self, async_client: AsyncOzAPI) -> None @parametrize async def test_path_params_resume(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - await async_client.agent.schedules.with_raw_response.resume( - "", - ) + await async_client.agent.schedules.with_raw_response.resume( + "", + ) \ No newline at end of file diff --git a/tests/api_resources/agent/test_sessions.py b/tests/api_resources/agent/test_sessions.py index 5b344ac..7519323 100644 --- a/tests/api_resources/agent/test_sessions.py +++ b/tests/api_resources/agent/test_sessions.py @@ -2,20 +2,25 @@ from __future__ import annotations -import os -from typing import Any, cast +from oz_agent_sdk import OzAPI, AsyncOzAPI -import pytest +from oz_agent_sdk.types.agent import SessionCheckRedirectResponse -from tests.utils import assert_matches_type +from typing import cast, Any + +import os +import pytest +import httpx +from typing_extensions import get_args +from respx import MockRouter from oz_agent_sdk import OzAPI, AsyncOzAPI -from oz_agent_sdk.types.agent import SessionCheckRedirectResponse +from tests.utils import assert_matches_type base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - class TestSessions: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=['loose', 'strict']) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -23,31 +28,32 @@ def test_method_check_redirect(self, client: OzAPI) -> None: session = client.agent.sessions.check_redirect( "sessionUuid", ) - assert_matches_type(SessionCheckRedirectResponse, session, path=["response"]) + assert_matches_type(SessionCheckRedirectResponse, session, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_check_redirect(self, client: OzAPI) -> None: + response = client.agent.sessions.with_raw_response.check_redirect( "sessionUuid", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' session = response.parse() - assert_matches_type(SessionCheckRedirectResponse, session, path=["response"]) + assert_matches_type(SessionCheckRedirectResponse, session, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_check_redirect(self, client: OzAPI) -> None: with client.agent.sessions.with_streaming_response.check_redirect( "sessionUuid", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' session = response.parse() - assert_matches_type(SessionCheckRedirectResponse, session, path=["response"]) + assert_matches_type(SessionCheckRedirectResponse, session, path=['response']) assert cast(Any, response.is_closed) is True @@ -55,15 +61,12 @@ def test_streaming_response_check_redirect(self, client: OzAPI) -> None: @parametrize def test_path_params_check_redirect(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_uuid` but received ''"): - client.agent.sessions.with_raw_response.check_redirect( - "", - ) - - + client.agent.sessions.with_raw_response.check_redirect( + "", + ) class TestAsyncSessions: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) + parametrize = pytest.mark.parametrize("async_client", [False, True, {'http_client': 'aiohttp'}], indirect=True, ids=['loose', 'strict', 'aiohttp']) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -71,31 +74,32 @@ async def test_method_check_redirect(self, async_client: AsyncOzAPI) -> None: session = await async_client.agent.sessions.check_redirect( "sessionUuid", ) - assert_matches_type(SessionCheckRedirectResponse, session, path=["response"]) + assert_matches_type(SessionCheckRedirectResponse, session, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_check_redirect(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.sessions.with_raw_response.check_redirect( "sessionUuid", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' session = await response.parse() - assert_matches_type(SessionCheckRedirectResponse, session, path=["response"]) + assert_matches_type(SessionCheckRedirectResponse, session, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_check_redirect(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.sessions.with_streaming_response.check_redirect( "sessionUuid", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' session = await response.parse() - assert_matches_type(SessionCheckRedirectResponse, session, path=["response"]) + assert_matches_type(SessionCheckRedirectResponse, session, path=['response']) assert cast(Any, response.is_closed) is True @@ -103,6 +107,6 @@ async def test_streaming_response_check_redirect(self, async_client: AsyncOzAPI) @parametrize async def test_path_params_check_redirect(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_uuid` but received ''"): - await async_client.agent.sessions.with_raw_response.check_redirect( - "", - ) + await async_client.agent.sessions.with_raw_response.check_redirect( + "", + ) \ No newline at end of file diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index d7d463e..5593546 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -2,31 +2,35 @@ from __future__ import annotations -import os -from typing import Any, cast +from oz_agent_sdk import OzAPI, AsyncOzAPI -import pytest +from oz_agent_sdk.types import AgentListResponse, AgentGetArtifactResponse, AgentListEnvironmentsResponse, AgentRunResponse -from tests.utils import assert_matches_type +from typing import cast, Any + +import os +import pytest +import httpx +from typing_extensions import get_args +from respx import MockRouter from oz_agent_sdk import OzAPI, AsyncOzAPI -from oz_agent_sdk.types import ( - AgentRunResponse, - AgentListResponse, - AgentGetArtifactResponse, - AgentListEnvironmentsResponse, -) +from tests.utils import assert_matches_type +from oz_agent_sdk.types import agent_list_params +from oz_agent_sdk.types import agent_list_environments_params +from oz_agent_sdk.types import agent_run_params +from oz_agent_sdk.types import AmbientAgentConfig base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - class TestAgent: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=['loose', 'strict']) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list(self, client: OzAPI) -> None: agent = client.agent.list() - assert_matches_type(AgentListResponse, agent, path=["response"]) + assert_matches_type(AgentListResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -37,27 +41,28 @@ def test_method_list_with_all_params(self, client: OzAPI) -> None: repo="repo", sort_by="name", ) - assert_matches_type(AgentListResponse, agent, path=["response"]) + assert_matches_type(AgentListResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_list(self, client: OzAPI) -> None: + response = client.agent.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentListResponse, agent, path=["response"]) + assert_matches_type(AgentListResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_list(self, client: OzAPI) -> None: - with client.agent.with_streaming_response.list() as response: + with client.agent.with_streaming_response.list() as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentListResponse, agent, path=["response"]) + assert_matches_type(AgentListResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -67,31 +72,32 @@ def test_method_get_artifact(self, client: OzAPI) -> None: agent = client.agent.get_artifact( "artifactUid", ) - assert_matches_type(AgentGetArtifactResponse, agent, path=["response"]) + assert_matches_type(AgentGetArtifactResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_get_artifact(self, client: OzAPI) -> None: + response = client.agent.with_raw_response.get_artifact( "artifactUid", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentGetArtifactResponse, agent, path=["response"]) + assert_matches_type(AgentGetArtifactResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_get_artifact(self, client: OzAPI) -> None: with client.agent.with_streaming_response.get_artifact( "artifactUid", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentGetArtifactResponse, agent, path=["response"]) + assert_matches_type(AgentGetArtifactResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -99,15 +105,15 @@ def test_streaming_response_get_artifact(self, client: OzAPI) -> None: @parametrize def test_path_params_get_artifact(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `artifact_uid` but received ''"): - client.agent.with_raw_response.get_artifact( - "", - ) + client.agent.with_raw_response.get_artifact( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list_environments(self, client: OzAPI) -> None: agent = client.agent.list_environments() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -115,27 +121,28 @@ def test_method_list_environments_with_all_params(self, client: OzAPI) -> None: agent = client.agent.list_environments( sort_by="name", ) - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_list_environments(self, client: OzAPI) -> None: + response = client.agent.with_raw_response.list_environments() assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_list_environments(self, client: OzAPI) -> None: - with client.agent.with_streaming_response.list_environments() as response: + with client.agent.with_streaming_response.list_environments() as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -143,25 +150,25 @@ def test_streaming_response_list_environments(self, client: OzAPI) -> None: @parametrize def test_method_run(self, client: OzAPI) -> None: agent = client.agent.run() - assert_matches_type(AgentRunResponse, agent, path=["response"]) + assert_matches_type(AgentRunResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_run_with_all_params(self, client: OzAPI) -> None: agent = client.agent.run( agent_identity_uid="agent_identity_uid", - attachments=[ - { - "data": "U3RhaW5sZXNzIHJvY2tz", - "file_name": "file_name", - "mime_type": "mime_type", - } - ], + attachments=[{ + "data": "U3RhaW5sZXNzIHJvY2tz", + "file_name": "file_name", + "mime_type": "mime_type", + }], config={ "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": {"type": "oz"}, + "harness": { + "type": "oz" + }, "harness_auth_secrets": { "claude_auth_secret_name": "claude_auth_secret_name", "codex_auth_secret_name": "codex_auth_secret_name", @@ -178,22 +185,26 @@ def test_method_run_with_all_params(self, client: OzAPI) -> None: "foo": { "args": ["string"], "command": "command", - "env": {"foo": "string"}, - "headers": {"foo": "string"}, + "env": { + "foo": "string" + }, + "headers": { + "foo": "string" + }, "url": "https://example.com", "warp_id": "warp_id", } }, - "memory_stores": [ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + "memory_stores": [{ + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + }], "model_id": "model_id", "name": "name", - "session_sharing": {"public_access": "VIEWER"}, + "session_sharing": { + "public_access": "VIEWER" + }, "skill_spec": "skill_spec", "skills": ["string"], "worker_host": "worker_host", @@ -207,41 +218,39 @@ def test_method_run_with_all_params(self, client: OzAPI) -> None: team=True, title="title", ) - assert_matches_type(AgentRunResponse, agent, path=["response"]) + assert_matches_type(AgentRunResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_run(self, client: OzAPI) -> None: + response = client.agent.with_raw_response.run() assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentRunResponse, agent, path=["response"]) + assert_matches_type(AgentRunResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_run(self, client: OzAPI) -> None: - with client.agent.with_streaming_response.run() as response: + with client.agent.with_streaming_response.run() as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = response.parse() - assert_matches_type(AgentRunResponse, agent, path=["response"]) + assert_matches_type(AgentRunResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True - - class TestAsyncAgent: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) + parametrize = pytest.mark.parametrize("async_client", [False, True, {'http_client': 'aiohttp'}], indirect=True, ids=['loose', 'strict', 'aiohttp']) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.list() - assert_matches_type(AgentListResponse, agent, path=["response"]) + assert_matches_type(AgentListResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -252,27 +261,28 @@ async def test_method_list_with_all_params(self, async_client: AsyncOzAPI) -> No repo="repo", sort_by="name", ) - assert_matches_type(AgentListResponse, agent, path=["response"]) + assert_matches_type(AgentListResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_list(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentListResponse, agent, path=["response"]) + assert_matches_type(AgentListResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_list(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.with_streaming_response.list() as response: + async with async_client.agent.with_streaming_response.list() as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentListResponse, agent, path=["response"]) + assert_matches_type(AgentListResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -282,31 +292,32 @@ async def test_method_get_artifact(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.get_artifact( "artifactUid", ) - assert_matches_type(AgentGetArtifactResponse, agent, path=["response"]) + assert_matches_type(AgentGetArtifactResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_get_artifact(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.with_raw_response.get_artifact( "artifactUid", ) assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentGetArtifactResponse, agent, path=["response"]) + assert_matches_type(AgentGetArtifactResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_get_artifact(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.with_streaming_response.get_artifact( "artifactUid", - ) as response: + ) as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentGetArtifactResponse, agent, path=["response"]) + assert_matches_type(AgentGetArtifactResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -314,15 +325,15 @@ async def test_streaming_response_get_artifact(self, async_client: AsyncOzAPI) - @parametrize async def test_path_params_get_artifact(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `artifact_uid` but received ''"): - await async_client.agent.with_raw_response.get_artifact( - "", - ) + await async_client.agent.with_raw_response.get_artifact( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list_environments(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.list_environments() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -330,27 +341,28 @@ async def test_method_list_environments_with_all_params(self, async_client: Asyn agent = await async_client.agent.list_environments( sort_by="name", ) - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_list_environments(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.with_raw_response.list_environments() assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_list_environments(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.with_streaming_response.list_environments() as response: + async with async_client.agent.with_streaming_response.list_environments() as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) assert cast(Any, response.is_closed) is True @@ -358,25 +370,25 @@ async def test_streaming_response_list_environments(self, async_client: AsyncOzA @parametrize async def test_method_run(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.run() - assert_matches_type(AgentRunResponse, agent, path=["response"]) + assert_matches_type(AgentRunResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.run( agent_identity_uid="agent_identity_uid", - attachments=[ - { - "data": "U3RhaW5sZXNzIHJvY2tz", - "file_name": "file_name", - "mime_type": "mime_type", - } - ], + attachments=[{ + "data": "U3RhaW5sZXNzIHJvY2tz", + "file_name": "file_name", + "mime_type": "mime_type", + }], config={ "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": {"type": "oz"}, + "harness": { + "type": "oz" + }, "harness_auth_secrets": { "claude_auth_secret_name": "claude_auth_secret_name", "codex_auth_secret_name": "codex_auth_secret_name", @@ -393,22 +405,26 @@ async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> Non "foo": { "args": ["string"], "command": "command", - "env": {"foo": "string"}, - "headers": {"foo": "string"}, + "env": { + "foo": "string" + }, + "headers": { + "foo": "string" + }, "url": "https://example.com", "warp_id": "warp_id", } }, - "memory_stores": [ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + "memory_stores": [{ + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + }], "model_id": "model_id", "name": "name", - "session_sharing": {"public_access": "VIEWER"}, + "session_sharing": { + "public_access": "VIEWER" + }, "skill_spec": "skill_spec", "skills": ["string"], "worker_host": "worker_host", @@ -422,26 +438,27 @@ async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> Non team=True, title="title", ) - assert_matches_type(AgentRunResponse, agent, path=["response"]) + assert_matches_type(AgentRunResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_run(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.with_raw_response.run() assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentRunResponse, agent, path=["response"]) + assert_matches_type(AgentRunResponse, agent, path=['response']) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_run(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.with_streaming_response.run() as response: + async with async_client.agent.with_streaming_response.run() as response : assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assert response.http_request.headers.get('X-Stainless-Lang') == 'python' agent = await response.parse() - assert_matches_type(AgentRunResponse, agent, path=["response"]) + assert_matches_type(AgentRunResponse, agent, path=['response']) - assert cast(Any, response.is_closed) is True + assert cast(Any, response.is_closed) is True \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 5884465..1dc9683 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,25 +2,31 @@ from __future__ import annotations -import os import logging -from typing import TYPE_CHECKING, Iterator, AsyncIterator import httpx + +from oz_agent_sdk import OzAPI, DefaultAioHttpClient, AsyncOzAPI + +from oz_agent_sdk._utils import is_dict + +import logging +from typing import Iterator + import pytest from pytest_asyncio import is_async_test +import os +from typing import TYPE_CHECKING, AsyncIterator -from oz_agent_sdk import OzAPI, AsyncOzAPI, DefaultAioHttpClient -from oz_agent_sdk._utils import is_dict +from oz_agent_sdk import OzAPI, AsyncOzAPI if TYPE_CHECKING: - from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage] + from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage] pytest.register_assert_rewrite("tests.utils") logging.getLogger("oz_agent_sdk").setLevel(logging.DEBUG) - # automatically add `pytest.mark.asyncio()` to all of our async tests # so we don't have to add that boilerplate everywhere def pytest_collection_modifyitems(items: list[pytest.Function]) -> None: @@ -35,29 +41,26 @@ def pytest_collection_modifyitems(items: list[pytest.Function]) -> None: if "async_client" not in item.fixturenames or "respx_mock" not in item.fixturenames: continue - if not hasattr(item, "callspec"): - continue + if not hasattr(item, 'callspec'): + continue async_client_param = item.callspec.params.get("async_client") if is_dict(async_client_param) and async_client_param.get("http_client") == "aiohttp": item.add_marker(pytest.mark.skip(reason="aiohttp client is not compatible with respx_mock")) - base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My API Key" - @pytest.fixture(scope="session") def client(request: FixtureRequest) -> Iterator[OzAPI]: - strict = getattr(request, "param", True) + strict = getattr(request, 'param', True) if not isinstance(strict, bool): - raise TypeError(f"Unexpected fixture parameter type {type(strict)}, expected {bool}") + raise TypeError(f'Unexpected fixture parameter type {type(strict)}, expected {bool}') - with OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client: + with OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client : yield client - @pytest.fixture(scope="session") async def async_client(request: FixtureRequest) -> AsyncIterator[AsyncOzAPI]: param = getattr(request, "param", True) @@ -78,7 +81,5 @@ async def async_client(request: FixtureRequest) -> AsyncIterator[AsyncOzAPI]: else: raise TypeError(f"Unexpected fixture parameter type {type(param)}, expected bool or dict") - async with AsyncOzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=strict, http_client=http_client - ) as client: - yield client + async with AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=strict, http_client=http_client) as client : + yield client \ No newline at end of file diff --git a/tests/test_client.py b/tests/test_client.py index 988622f..d3a0d01 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -2,106 +2,109 @@ from __future__ import annotations -import gc -import os +import dataclasses + +import pytest + import sys -import json + +import httpx + +from oz_agent_sdk import OzAPI, AsyncOzAPI + +from oz_agent_sdk._exceptions import APITimeoutError, APIStatusError, OzAPIError, APIResponseValidationError + +from typing import TypeVar, Callable, Coroutine, Iterable, Optional, Iterator, cast, Any, Union + +from typing_extensions import override, AsyncIterator, Literal + +from oz_agent_sdk._types import Omit + +from pydantic import ValidationError + +from oz_agent_sdk._base_client import DefaultHttpxClient, get_platform, OtherPlatform, DefaultAsyncHttpxClient + +from oz_agent_sdk._utils import asyncify + import asyncio +import gc import inspect -import dataclasses +import json +import os import tracemalloc -from typing import Any, Union, TypeVar, Callable, Iterable, Iterator, Optional, Coroutine, cast from unittest import mock -from typing_extensions import Literal, AsyncIterator, override import httpx import pytest from respx import MockRouter -from pydantic import ValidationError from oz_agent_sdk import OzAPI, AsyncOzAPI, APIResponseValidationError +from oz_agent_sdk._models import FinalRequestOptions, BaseModel +from oz_agent_sdk._types import Headers, Query, Body, Timeout, Omit +from oz_agent_sdk._base_client import DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, BaseClient, RequestOptions, make_request_options +from oz_agent_sdk._streaming import Stream, AsyncStream +from oz_agent_sdk._constants import RAW_RESPONSE_HEADER +from oz_agent_sdk._response import APIResponse, AsyncAPIResponse from oz_agent_sdk._types import Omit -from oz_agent_sdk._utils import asyncify -from oz_agent_sdk._models import BaseModel, FinalRequestOptions -from oz_agent_sdk._exceptions import OzAPIError, APIStatusError, APITimeoutError, APIResponseValidationError -from oz_agent_sdk._base_client import ( - DEFAULT_TIMEOUT, - HTTPX_DEFAULT_TIMEOUT, - BaseClient, - OtherPlatform, - DefaultHttpxClient, - DefaultAsyncHttpxClient, - get_platform, - make_request_options, -) - from .utils import update_env T = TypeVar("T") base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My API Key" - def _get_params(client: BaseClient[Any, Any]) -> dict[str, str]: - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - url = httpx.URL(request.url) - return dict(url.params) - + request = client._build_request(FinalRequestOptions(method="get", url='/foo')) + url = httpx.URL(request.url) + return dict(url.params) def _low_retry_timeout(*_args: Any, **_kwargs: Any) -> float: return 0.1 - def mirror_request_content(request: httpx.Request) -> httpx.Response: - return httpx.Response(200, content=request.content) - + return httpx.Response(200, content=request.content) # note: we can't use the httpx.MockTransport class as it consumes the request # body itself, which means we can't test that the body is read lazily class MockTransport(httpx.BaseTransport, httpx.AsyncBaseTransport): - def __init__( - self, - handler: Callable[[httpx.Request], httpx.Response] - | Callable[[httpx.Request], Coroutine[Any, Any, httpx.Response]], - ) -> None: - self.handler = handler - - @override - def handle_request( - self, - request: httpx.Request, - ) -> httpx.Response: - assert not inspect.iscoroutinefunction(self.handler), "handler must not be a coroutine function" - assert inspect.isfunction(self.handler), "handler must be a function" - return self.handler(request) - - @override - async def handle_async_request( - self, - request: httpx.Request, - ) -> httpx.Response: - assert inspect.iscoroutinefunction(self.handler), "handler must be a coroutine function" - return await self.handler(request) - + def __init__( + self, + handler: Callable[[httpx.Request], httpx.Response] + | Callable[[httpx.Request], Coroutine[Any, Any, httpx.Response]], + ) -> None: + self.handler = handler + + @override + def handle_request( + self, + request: httpx.Request, + ) -> httpx.Response: + assert not inspect.iscoroutinefunction(self.handler), "handler must not be a coroutine function" + assert inspect.isfunction(self.handler), "handler must be a function" + return self.handler(request) + + @override + async def handle_async_request( + self, + request: httpx.Request, + ) -> httpx.Response: + assert inspect.iscoroutinefunction(self.handler), "handler must be a coroutine function" + return await self.handler(request) @dataclasses.dataclass class Counter: value: int = 0 - def _make_sync_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> Iterator[T]: - for item in iterable: - if counter: - counter.value += 1 - yield item - + for item in iterable: + if counter: + counter.value += 1 + yield item async def _make_async_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> AsyncIterator[T]: - for item in iterable: - if counter: - counter.value += 1 - yield item - + for item in iterable: + if counter: + counter.value += 1 + yield item def _get_open_connections(client: OzAPI | AsyncOzAPI) -> int: transport = client._client._transport @@ -110,7 +113,6 @@ def _get_open_connections(client: OzAPI | AsyncOzAPI) -> int: pool = transport._pool return len(pool._requests) - class TestOzAPI: @pytest.mark.respx(base_url=base_url) def test_raw_response(self, respx_mock: MockRouter, client: OzAPI) -> None: @@ -123,9 +125,7 @@ def test_raw_response(self, respx_mock: MockRouter, client: OzAPI) -> None: @pytest.mark.respx(base_url=base_url) def test_raw_response_for_binary(self, respx_mock: MockRouter, client: OzAPI) -> None: - respx_mock.post("/foo").mock( - return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') - ) + respx_mock.post("/foo").mock(return_value=httpx.Response(200, headers={'Content-Type':'application/binary'}, content='{"foo": "bar"}')) response = client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 @@ -157,59 +157,59 @@ def test_copy_default_options(self, client: OzAPI) -> None: assert isinstance(client.timeout, httpx.Timeout) def test_copy_default_headers(self) -> None: - client = OzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} - ) - assert client.default_headers["X-Foo"] == "bar" + client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ + "X-Foo": "bar" + }) + assert client.default_headers['X-Foo'] == 'bar' # does not override the already given value when not specified copied = client.copy() - assert copied.default_headers["X-Foo"] == "bar" + assert copied.default_headers['X-Foo'] == 'bar' # merges already given headers - copied = client.copy(default_headers={"X-Bar": "stainless"}) - assert copied.default_headers["X-Foo"] == "bar" - assert copied.default_headers["X-Bar"] == "stainless" + copied = client.copy(default_headers={'X-Bar': 'stainless'}) + assert copied.default_headers['X-Foo'] == 'bar' + assert copied.default_headers['X-Bar'] == 'stainless' # uses new values for any already given headers - copied = client.copy(default_headers={"X-Foo": "stainless"}) - assert copied.default_headers["X-Foo"] == "stainless" + copied = client.copy(default_headers={'X-Foo': 'stainless'}) + assert copied.default_headers['X-Foo'] == 'stainless' # set_default_headers # completely overrides already set values copied = client.copy(set_default_headers={}) - assert copied.default_headers.get("X-Foo") is None + assert copied.default_headers.get('X-Foo') is None - copied = client.copy(set_default_headers={"X-Bar": "Robert"}) - assert copied.default_headers["X-Bar"] == "Robert" + copied = client.copy(set_default_headers={'X-Bar': 'Robert'}) + assert copied.default_headers['X-Bar'] == 'Robert' with pytest.raises( - ValueError, - match="`default_headers` and `set_default_headers` arguments are mutually exclusive", + ValueError, + match='`default_headers` and `set_default_headers` arguments are mutually exclusive', ): - client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) + client.copy(set_default_headers={}, default_headers={'X-Foo': 'Bar'}) client.close() def test_copy_default_query(self) -> None: - client = OzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} - ) - assert _get_params(client)["foo"] == "bar" + client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={ + "foo": "bar" + }) + assert _get_params(client)['foo'] == 'bar' # does not override the already given value when not specified copied = client.copy() - assert _get_params(copied)["foo"] == "bar" + assert _get_params(copied)['foo'] == 'bar' # merges already given params - copied = client.copy(default_query={"bar": "stainless"}) + copied = client.copy(default_query={'bar': 'stainless'}) params = _get_params(copied) - assert params["foo"] == "bar" - assert params["bar"] == "stainless" + assert params['foo'] == 'bar' + assert params['bar'] == 'stainless' # uses new values for any already given headers - copied = client.copy(default_query={"foo": "stainless"}) - assert _get_params(copied)["foo"] == "stainless" + copied = client.copy(default_query={'foo': 'stainless'}) + assert _get_params(copied)['foo'] == 'stainless' # set_default_query @@ -217,23 +217,23 @@ def test_copy_default_query(self) -> None: copied = client.copy(set_default_query={}) assert _get_params(copied) == {} - copied = client.copy(set_default_query={"bar": "Robert"}) - assert _get_params(copied)["bar"] == "Robert" + copied = client.copy(set_default_query={'bar': 'Robert'}) + assert _get_params(copied)['bar'] == 'Robert' with pytest.raises( - ValueError, - # TODO: update - match="`default_query` and `set_default_query` arguments are mutually exclusive", + ValueError, + # TODO: update + match='`default_query` and `set_default_query` arguments are mutually exclusive', ): - client.copy(set_default_query={}, default_query={"foo": "Bar"}) + client.copy(set_default_query={}, default_query={'foo': 'Bar'}) client.close() def test_copy_signature(self, client: OzAPI) -> None: # ensure the same parameters that can be passed to the client are defined in the `.copy()` method init_signature = inspect.signature( - # mypy doesn't like that we access the `__init__` property. - client.__init__, # type: ignore[misc] + # mypy doesn't like that we access the `__init__` property. + client.__init__, # type: ignore[misc] ) copy_signature = inspect.signature(client.copy) exclude_params = {"transport", "proxies", "_strict_response_validation"} @@ -313,7 +313,9 @@ def test_request_timeout(self, client: OzAPI) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT - request = client._build_request(FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0))) + request = client._build_request( + FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0)) + ) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(100.0) @@ -329,89 +331,75 @@ def test_client_timeout_option(self) -> None: def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used with httpx.Client(timeout=None) as http_client: - client = OzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client - ) + client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == httpx.Timeout(None) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == httpx.Timeout(None) - client.close() + client.close() # no timeout given to the httpx client should not use the httpx default with httpx.Client() as http_client: - client = OzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client - ) + client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT - client.close() + client.close() # explicitly passing the default timeout currently results in it being ignored with httpx.Client(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: - client = OzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client - ) + client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT # our default + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT # our default - client.close() + client.close() async def test_invalid_http_client(self) -> None: - with pytest.raises(TypeError, match="Invalid `http_client` arg"): - async with httpx.AsyncClient() as http_client: - OzAPI( - base_url=base_url, - api_key=api_key, - _strict_response_validation=True, - http_client=cast(Any, http_client), - ) + with pytest.raises(TypeError, match='Invalid `http_client` arg') : + async with httpx.AsyncClient() as http_client : + OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=cast(Any, http_client)) def test_default_headers_option(self) -> None: - test_client = OzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} - ) - request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) - assert request.headers.get("x-foo") == "bar" - assert request.headers.get("x-stainless-lang") == "python" - - test_client2 = OzAPI( - base_url=base_url, - api_key=api_key, - _strict_response_validation=True, - default_headers={ - "X-Foo": "stainless", - "X-Stainless-Lang": "my-overriding-header", - }, - ) - request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) - assert request.headers.get("x-foo") == "stainless" - assert request.headers.get("x-stainless-lang") == "my-overriding-header" + test_client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ + "X-Foo": "bar" + }) + request = test_client._build_request(FinalRequestOptions(method="get", url='/foo')) + assert request.headers.get('x-foo') == 'bar' + assert request.headers.get('x-stainless-lang') == 'python' + + test_client2 = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ + "X-Foo": "stainless", + "X-Stainless-Lang": "my-overriding-header", + }) + request = test_client2._build_request(FinalRequestOptions(method="get", url='/foo')) + assert request.headers.get('x-foo') == 'stainless' + assert request.headers.get('x-stainless-lang') == 'my-overriding-header' test_client.close() test_client2.close() def test_validate_headers(self) -> None: client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + request = client._build_request(FinalRequestOptions(method="get", url='/foo')) assert request.headers.get("Authorization") == f"Bearer {api_key}" with pytest.raises(OzAPIError): - with update_env(**{"WARP_API_KEY": Omit()}): + with update_env(**{ + "WARP_API_KEY": Omit() + }) : client2 = OzAPI(base_url=base_url, api_key=None, _strict_response_validation=True) _ = client2 def test_default_query_option(self) -> None: - client = OzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} - ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={ + "query_param": "bar" + }) + request = client._build_request(FinalRequestOptions(method="get", url='/foo')) url = httpx.URL(request.url) assert dict(url.params) == {"query_param": "bar"} @@ -423,7 +411,7 @@ def test_default_query_option(self) -> None: ) ) url = httpx.URL(request.url) - assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} + assert dict(url.params) == {'foo': 'baz', "query_param": "overridden"} client.close() @@ -532,7 +520,7 @@ def test_request_extra_query(self, client: OzAPI) -> None: ), ) params = dict(request.url.params) - assert params == {"bar": "1", "foo": "2"} + assert params == {'bar': '1', 'foo': '2'} # `extra_query` takes priority over `query` when keys clash request = client._build_request( @@ -546,7 +534,7 @@ def test_request_extra_query(self, client: OzAPI) -> None: ), ) params = dict(request.url.params) - assert params == {"foo": "2"} + assert params == {'foo': '2'} def test_multipart_repeating_array(self, client: OzAPI) -> None: request = client._build_request( @@ -583,12 +571,7 @@ def test_binary_content_upload(self, respx_mock: MockRouter, client: OzAPI) -> N file_content = b"Hello, this is a test file." - response = client.post( - "/upload", - content=file_content, - cast_to=httpx.Response, - options={"headers": {"Content-Type": "application/octet-stream"}}, - ) + response = client.post("/upload", content=file_content, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" @@ -603,23 +586,13 @@ def mock_handler(request: httpx.Request) -> httpx.Response: assert counter.value == 0, "the request body should not have been read" return httpx.Response(200, content=request.read()) - with OzAPI( - base_url=base_url, - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.Client(transport=MockTransport(handler=mock_handler)), - ) as client: - response = client.post( - "/upload", - content=iterator, - cast_to=httpx.Response, - options={"headers": {"Content-Type": "application/octet-stream"}}, - ) + with OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=httpx.Client(transport = MockTransport(handler=mock_handler))) as client: + response = client.post("/upload", content=iterator, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}) - assert response.status_code == 200 - assert response.request.headers["Content-Type"] == "application/octet-stream" - assert response.content == file_content - assert counter.value == 1 + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + assert counter.value == 1 @pytest.mark.respx(base_url=base_url) def test_binary_content_upload_with_body_is_deprecated(self, respx_mock: MockRouter, client: OzAPI) -> None: @@ -630,12 +603,7 @@ def test_binary_content_upload_with_body_is_deprecated(self, respx_mock: MockRou with pytest.deprecated_call( match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." ): - response = client.post( - "/upload", - body=file_content, - cast_to=httpx.Response, - options={"headers": {"Content-Type": "application/octet-stream"}}, - ) + response = client.post("/upload", body=file_content, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" @@ -649,29 +617,27 @@ class Model1(BaseModel): class Model2(BaseModel): foo: str - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + respx_mock.get('/foo').mock(return_value=httpx.Response(200, json={'foo': 'bar'})) response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) - assert response.foo == "bar" - + assert response.foo == 'bar' @pytest.mark.respx(base_url=base_url) def test_union_response_different_types(self, respx_mock: MockRouter, client: OzAPI) -> None: """Union of objects with the same field name using a different type""" - class Model1(BaseModel): foo: int class Model2(BaseModel): foo: str - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + respx_mock.get('/foo').mock(return_value=httpx.Response(200, json={'foo': 'bar'})) response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) - assert response.foo == "bar" + assert response.foo == 'bar' - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) + respx_mock.get('/foo').mock(return_value=httpx.Response(200, json={'foo': 1})) response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model1) @@ -682,7 +648,6 @@ def test_non_application_json_content_type_for_json_data(self, respx_mock: MockR """ Response that sets Content-Type to something other than application/json but returns json data """ - class Model(BaseModel): foo: int @@ -709,23 +674,11 @@ def test_base_url_setter(self) -> None: client.close() def test_base_url_env(self) -> None: - with update_env(OZ_API_BASE_URL="http://localhost:5000/from/env"): - client = OzAPI(api_key=api_key, _strict_response_validation=True) - assert client.base_url == "http://localhost:5000/from/env/" + with update_env(OZ_API_BASE_URL='http://localhost:5000/from/env'): + client = OzAPI(api_key=api_key, _strict_response_validation=True) + assert client.base_url == 'http://localhost:5000/from/env/' - @pytest.mark.parametrize( - "client", - [ - OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), - OzAPI( - base_url="http://localhost:5000/custom/path/", - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.Client(), - ), - ], - ids=["standard", "custom http client"], - ) + @pytest.mark.parametrize("client", [OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.Client())], ids = ["standard", "custom http client"]) def test_base_url_trailing_slash(self, client: OzAPI) -> None: request = client._build_request( FinalRequestOptions( @@ -737,19 +690,7 @@ def test_base_url_trailing_slash(self, client: OzAPI) -> None: assert request.url == "http://localhost:5000/custom/path/foo" client.close() - @pytest.mark.parametrize( - "client", - [ - OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), - OzAPI( - base_url="http://localhost:5000/custom/path/", - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.Client(), - ), - ], - ids=["standard", "custom http client"], - ) + @pytest.mark.parametrize("client", [OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.Client())], ids = ["standard", "custom http client"]) def test_base_url_no_trailing_slash(self, client: OzAPI) -> None: request = client._build_request( FinalRequestOptions( @@ -761,19 +702,7 @@ def test_base_url_no_trailing_slash(self, client: OzAPI) -> None: assert request.url == "http://localhost:5000/custom/path/foo" client.close() - @pytest.mark.parametrize( - "client", - [ - OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), - OzAPI( - base_url="http://localhost:5000/custom/path/", - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.Client(), - ), - ], - ids=["standard", "custom http client"], - ) + @pytest.mark.parametrize("client", [OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.Client())], ids = ["standard", "custom http client"]) def test_absolute_request_url(self, client: OzAPI) -> None: request = client._build_request( FinalRequestOptions( @@ -799,9 +728,9 @@ def test_copied_client_does_not_close_http(self) -> None: def test_client_context_manager(self) -> None: test_client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True) with test_client as c2: - assert c2 is test_client - assert not c2.is_closed() - assert not test_client.is_closed() + assert c2 is test_client + assert not c2.is_closed() + assert not test_client.is_closed() assert test_client.is_closed() @pytest.mark.respx(base_url=base_url) @@ -818,7 +747,7 @@ class Model(BaseModel): def test_client_max_retries_validation(self) -> None: with pytest.raises(TypeError, match=r"max_retries cannot be None"): - OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None)) + OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None)) @pytest.mark.respx(base_url=base_url) def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: @@ -830,7 +759,7 @@ class Model(BaseModel): strict_client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True) with pytest.raises(APIResponseValidationError): - strict_client.get("/foo", cast_to=Model) + strict_client.get("/foo", cast_to=Model) non_strict_client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=False) @@ -841,34 +770,32 @@ class Model(BaseModel): non_strict_client.close() @pytest.mark.parametrize( - "remaining_retries,retry_after,timeout", - [ - [3, "20", 20], - [3, "0", 0.5], - [3, "-10", 0.5], - [3, "60", 60], - [3, "61", 0.5], - [3, "Fri, 29 Sep 2023 16:26:57 GMT", 20], - [3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5], - [3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5], - [3, "Fri, 29 Sep 2023 16:27:37 GMT", 60], - [3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5], - [3, "99999999999999999999999999999999999", 0.5], - [3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5], - [3, "", 0.5], - [2, "", 0.5 * 2.0], - [1, "", 0.5 * 4.0], - [-1100, "", 8], # test large number potentially overflowing - ], - ) + "remaining_retries,retry_after,timeout", + [ + [ 3, "20", 20 ], + [ 3, "0", 0.5 ], + [ 3, "-10", 0.5 ], + [ 3, "60", 60 ], + [ 3, "61", 0.5 ], + [ 3, "Fri, 29 Sep 2023 16:26:57 GMT", 20 ], + [ 3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5 ], + [ 3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5 ], + [ 3, "Fri, 29 Sep 2023 16:27:37 GMT", 60 ], + [ 3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5 ], + [ 3, "99999999999999999999999999999999999", 0.5 ], + [ 3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5 ], + [ 3, "", 0.5 ], + [ 2, "", 0.5 * 2.0 ], + [ 1, "", 0.5 * 4.0 ], + [-1100, "", 8], # test large number potentially overflowing + ], + ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) - def test_parse_retry_after_header( - self, remaining_retries: int, retry_after: str, timeout: float, client: OzAPI - ) -> None: + def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float, client: OzAPI) -> None: headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) calculated = client._calculate_retry_timeout(remaining_retries, options, headers) - assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] + assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] @mock.patch("oz_agent_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @@ -898,7 +825,7 @@ def test_retries_taken( client: OzAPI, failures_before_success: int, failure_mode: Literal["status", "exception"], - respx_mock: MockRouter, + respx_mock: MockRouter ) -> None: client = client.with_options(max_retries=4) @@ -909,7 +836,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: if nb_retries < failures_before_success: nb_retries += 1 if failure_mode == "exception": - raise RuntimeError("oops") + raise RuntimeError("oops") return httpx.Response(500) return httpx.Response(200) @@ -923,7 +850,12 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("oz_agent_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - def test_omit_retry_count_header(self, client: OzAPI, failures_before_success: int, respx_mock: MockRouter) -> None: + def test_omit_retry_count_header( + self, + client: OzAPI, + failures_before_success: int, + respx_mock: MockRouter + ) -> None: client = client.with_options(max_retries=4) nb_retries = 0 @@ -937,15 +869,18 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/agent/runs").mock(side_effect=retry_handler) - response = client.agent.with_raw_response.run(extra_headers={"x-stainless-retry-count": Omit()}) + response = client.agent.with_raw_response.run(extra_headers={'x-stainless-retry-count': Omit()}) - assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 + assert len(response.http_request.headers.get_list('x-stainless-retry-count')) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("oz_agent_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_overwrite_retry_count_header( - self, client: OzAPI, failures_before_success: int, respx_mock: MockRouter + self, + client: OzAPI, + failures_before_success: int, + respx_mock: MockRouter ) -> None: client = client.with_options(max_retries=4) @@ -960,9 +895,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/agent/runs").mock(side_effect=retry_handler) - response = client.agent.with_raw_response.run(extra_headers={"x-stainless-retry-count": "42"}) + response = client.agent.with_raw_response.run(extra_headers={'x-stainless-retry-count': '42'}) - assert response.http_request.headers.get("x-stainless-retry-count") == "42" + assert response.http_request.headers.get('x-stainless-retry-count') == '42' def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: # Test that the proxy environment variables are set correctly @@ -1018,8 +953,6 @@ def test_follow_redirects_disabled(self, respx_mock: MockRouter, client: OzAPI) assert exc_info.value.response.status_code == 302 assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" - - class TestAsyncOzAPI: @pytest.mark.respx(base_url=base_url) async def test_raw_response(self, respx_mock: MockRouter, async_client: AsyncOzAPI) -> None: @@ -1032,9 +965,7 @@ async def test_raw_response(self, respx_mock: MockRouter, async_client: AsyncOzA @pytest.mark.respx(base_url=base_url) async def test_raw_response_for_binary(self, respx_mock: MockRouter, async_client: AsyncOzAPI) -> None: - respx_mock.post("/foo").mock( - return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') - ) + respx_mock.post("/foo").mock(return_value=httpx.Response(200, headers={'Content-Type':'application/binary'}, content='{"foo": "bar"}')) response = await async_client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 @@ -1066,59 +997,59 @@ def test_copy_default_options(self, async_client: AsyncOzAPI) -> None: assert isinstance(async_client.timeout, httpx.Timeout) async def test_copy_default_headers(self) -> None: - client = AsyncOzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} - ) - assert client.default_headers["X-Foo"] == "bar" + client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ + "X-Foo": "bar" + }) + assert client.default_headers['X-Foo'] == 'bar' # does not override the already given value when not specified copied = client.copy() - assert copied.default_headers["X-Foo"] == "bar" + assert copied.default_headers['X-Foo'] == 'bar' # merges already given headers - copied = client.copy(default_headers={"X-Bar": "stainless"}) - assert copied.default_headers["X-Foo"] == "bar" - assert copied.default_headers["X-Bar"] == "stainless" + copied = client.copy(default_headers={'X-Bar': 'stainless'}) + assert copied.default_headers['X-Foo'] == 'bar' + assert copied.default_headers['X-Bar'] == 'stainless' # uses new values for any already given headers - copied = client.copy(default_headers={"X-Foo": "stainless"}) - assert copied.default_headers["X-Foo"] == "stainless" + copied = client.copy(default_headers={'X-Foo': 'stainless'}) + assert copied.default_headers['X-Foo'] == 'stainless' # set_default_headers # completely overrides already set values copied = client.copy(set_default_headers={}) - assert copied.default_headers.get("X-Foo") is None + assert copied.default_headers.get('X-Foo') is None - copied = client.copy(set_default_headers={"X-Bar": "Robert"}) - assert copied.default_headers["X-Bar"] == "Robert" + copied = client.copy(set_default_headers={'X-Bar': 'Robert'}) + assert copied.default_headers['X-Bar'] == 'Robert' with pytest.raises( - ValueError, - match="`default_headers` and `set_default_headers` arguments are mutually exclusive", + ValueError, + match='`default_headers` and `set_default_headers` arguments are mutually exclusive', ): - client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) + client.copy(set_default_headers={}, default_headers={'X-Foo': 'Bar'}) await client.close() async def test_copy_default_query(self) -> None: - client = AsyncOzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} - ) - assert _get_params(client)["foo"] == "bar" + client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={ + "foo": "bar" + }) + assert _get_params(client)['foo'] == 'bar' # does not override the already given value when not specified copied = client.copy() - assert _get_params(copied)["foo"] == "bar" + assert _get_params(copied)['foo'] == 'bar' # merges already given params - copied = client.copy(default_query={"bar": "stainless"}) + copied = client.copy(default_query={'bar': 'stainless'}) params = _get_params(copied) - assert params["foo"] == "bar" - assert params["bar"] == "stainless" + assert params['foo'] == 'bar' + assert params['bar'] == 'stainless' # uses new values for any already given headers - copied = client.copy(default_query={"foo": "stainless"}) - assert _get_params(copied)["foo"] == "stainless" + copied = client.copy(default_query={'foo': 'stainless'}) + assert _get_params(copied)['foo'] == 'stainless' # set_default_query @@ -1126,23 +1057,23 @@ async def test_copy_default_query(self) -> None: copied = client.copy(set_default_query={}) assert _get_params(copied) == {} - copied = client.copy(set_default_query={"bar": "Robert"}) - assert _get_params(copied)["bar"] == "Robert" + copied = client.copy(set_default_query={'bar': 'Robert'}) + assert _get_params(copied)['bar'] == 'Robert' with pytest.raises( - ValueError, - # TODO: update - match="`default_query` and `set_default_query` arguments are mutually exclusive", + ValueError, + # TODO: update + match='`default_query` and `set_default_query` arguments are mutually exclusive', ): - client.copy(set_default_query={}, default_query={"foo": "Bar"}) + client.copy(set_default_query={}, default_query={'foo': 'Bar'}) await client.close() def test_copy_signature(self, async_client: AsyncOzAPI) -> None: # ensure the same parameters that can be passed to the client are defined in the `.copy()` method init_signature = inspect.signature( - # mypy doesn't like that we access the `__init__` property. - async_client.__init__, # type: ignore[misc] + # mypy doesn't like that we access the `__init__` property. + async_client.__init__, # type: ignore[misc] ) copy_signature = inspect.signature(async_client.copy) exclude_params = {"transport", "proxies", "_strict_response_validation"} @@ -1229,9 +1160,7 @@ async def test_request_timeout(self, async_client: AsyncOzAPI) -> None: assert timeout == httpx.Timeout(100.0) async def test_client_timeout_option(self) -> None: - client = AsyncOzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0) - ) + client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0)) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore @@ -1242,89 +1171,75 @@ async def test_client_timeout_option(self) -> None: async def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used async with httpx.AsyncClient(timeout=None) as http_client: - client = AsyncOzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client - ) + client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == httpx.Timeout(None) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == httpx.Timeout(None) - await client.close() + await client.close() # no timeout given to the httpx client should not use the httpx default async with httpx.AsyncClient() as http_client: - client = AsyncOzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client - ) + client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT - await client.close() + await client.close() # explicitly passing the default timeout currently results in it being ignored async with httpx.AsyncClient(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: - client = AsyncOzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client - ) + client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT # our default + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT # our default - await client.close() + await client.close() def test_invalid_http_client(self) -> None: - with pytest.raises(TypeError, match="Invalid `http_client` arg"): - with httpx.Client() as http_client: - AsyncOzAPI( - base_url=base_url, - api_key=api_key, - _strict_response_validation=True, - http_client=cast(Any, http_client), - ) + with pytest.raises(TypeError, match='Invalid `http_client` arg') : + with httpx.Client() as http_client : + AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=cast(Any, http_client)) async def test_default_headers_option(self) -> None: - test_client = AsyncOzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} - ) - request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) - assert request.headers.get("x-foo") == "bar" - assert request.headers.get("x-stainless-lang") == "python" - - test_client2 = AsyncOzAPI( - base_url=base_url, - api_key=api_key, - _strict_response_validation=True, - default_headers={ - "X-Foo": "stainless", - "X-Stainless-Lang": "my-overriding-header", - }, - ) - request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) - assert request.headers.get("x-foo") == "stainless" - assert request.headers.get("x-stainless-lang") == "my-overriding-header" + test_client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ + "X-Foo": "bar" + }) + request = test_client._build_request(FinalRequestOptions(method="get", url='/foo')) + assert request.headers.get('x-foo') == 'bar' + assert request.headers.get('x-stainless-lang') == 'python' + + test_client2 = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ + "X-Foo": "stainless", + "X-Stainless-Lang": "my-overriding-header", + }) + request = test_client2._build_request(FinalRequestOptions(method="get", url='/foo')) + assert request.headers.get('x-foo') == 'stainless' + assert request.headers.get('x-stainless-lang') == 'my-overriding-header' await test_client.close() await test_client2.close() def test_validate_headers(self) -> None: client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + request = client._build_request(FinalRequestOptions(method="get", url='/foo')) assert request.headers.get("Authorization") == f"Bearer {api_key}" with pytest.raises(OzAPIError): - with update_env(**{"WARP_API_KEY": Omit()}): + with update_env(**{ + "WARP_API_KEY": Omit() + }) : client2 = AsyncOzAPI(base_url=base_url, api_key=None, _strict_response_validation=True) _ = client2 async def test_default_query_option(self) -> None: - client = AsyncOzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} - ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={ + "query_param": "bar" + }) + request = client._build_request(FinalRequestOptions(method="get", url='/foo')) url = httpx.URL(request.url) assert dict(url.params) == {"query_param": "bar"} @@ -1336,7 +1251,7 @@ async def test_default_query_option(self) -> None: ) ) url = httpx.URL(request.url) - assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} + assert dict(url.params) == {'foo': 'baz', "query_param": "overridden"} await client.close() @@ -1445,7 +1360,7 @@ def test_request_extra_query(self, client: OzAPI) -> None: ), ) params = dict(request.url.params) - assert params == {"bar": "1", "foo": "2"} + assert params == {'bar': '1', 'foo': '2'} # `extra_query` takes priority over `query` when keys clash request = client._build_request( @@ -1459,7 +1374,7 @@ def test_request_extra_query(self, client: OzAPI) -> None: ), ) params = dict(request.url.params) - assert params == {"foo": "2"} + assert params == {'foo': '2'} def test_multipart_repeating_array(self, async_client: AsyncOzAPI) -> None: request = async_client._build_request( @@ -1496,12 +1411,7 @@ async def test_binary_content_upload(self, respx_mock: MockRouter, async_client: file_content = b"Hello, this is a test file." - response = await async_client.post( - "/upload", - content=file_content, - cast_to=httpx.Response, - options={"headers": {"Content-Type": "application/octet-stream"}}, - ) + response = await async_client.post("/upload", content=file_content, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" @@ -1516,28 +1426,16 @@ async def mock_handler(request: httpx.Request) -> httpx.Response: assert counter.value == 0, "the request body should not have been read" return httpx.Response(200, content=await request.aread()) - async with AsyncOzAPI( - base_url=base_url, - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.AsyncClient(transport=MockTransport(handler=mock_handler)), - ) as client: - response = await client.post( - "/upload", - content=iterator, - cast_to=httpx.Response, - options={"headers": {"Content-Type": "application/octet-stream"}}, - ) + async with AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient(transport = MockTransport(handler=mock_handler))) as client: + response = await client.post("/upload", content=iterator, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}) - assert response.status_code == 200 - assert response.request.headers["Content-Type"] == "application/octet-stream" - assert response.content == file_content - assert counter.value == 1 + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + assert counter.value == 1 @pytest.mark.respx(base_url=base_url) - async def test_binary_content_upload_with_body_is_deprecated( - self, respx_mock: MockRouter, async_client: AsyncOzAPI - ) -> None: + async def test_binary_content_upload_with_body_is_deprecated(self, respx_mock: MockRouter, async_client: AsyncOzAPI) -> None: respx_mock.post("/upload").mock(side_effect=mirror_request_content) file_content = b"Hello, this is a test file." @@ -1545,12 +1443,7 @@ async def test_binary_content_upload_with_body_is_deprecated( with pytest.deprecated_call( match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." ): - response = await async_client.post( - "/upload", - body=file_content, - cast_to=httpx.Response, - options={"headers": {"Content-Type": "application/octet-stream"}}, - ) + response = await async_client.post("/upload", body=file_content, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" @@ -1564,42 +1457,37 @@ class Model1(BaseModel): class Model2(BaseModel): foo: str - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + respx_mock.get('/foo').mock(return_value=httpx.Response(200, json={'foo': 'bar'})) response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) - assert response.foo == "bar" - + assert response.foo == 'bar' @pytest.mark.respx(base_url=base_url) async def test_union_response_different_types(self, respx_mock: MockRouter, async_client: AsyncOzAPI) -> None: """Union of objects with the same field name using a different type""" - class Model1(BaseModel): foo: int class Model2(BaseModel): foo: str - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + respx_mock.get('/foo').mock(return_value=httpx.Response(200, json={'foo': 'bar'})) response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) - assert response.foo == "bar" + assert response.foo == 'bar' - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) + respx_mock.get('/foo').mock(return_value=httpx.Response(200, json={'foo': 1})) response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model1) assert response.foo == 1 @pytest.mark.respx(base_url=base_url) - async def test_non_application_json_content_type_for_json_data( - self, respx_mock: MockRouter, async_client: AsyncOzAPI - ) -> None: + async def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter, async_client: AsyncOzAPI) -> None: """ Response that sets Content-Type to something other than application/json but returns json data """ - class Model(BaseModel): foo: int @@ -1626,25 +1514,11 @@ async def test_base_url_setter(self) -> None: await client.close() async def test_base_url_env(self) -> None: - with update_env(OZ_API_BASE_URL="http://localhost:5000/from/env"): - client = AsyncOzAPI(api_key=api_key, _strict_response_validation=True) - assert client.base_url == "http://localhost:5000/from/env/" + with update_env(OZ_API_BASE_URL='http://localhost:5000/from/env'): + client = AsyncOzAPI(api_key=api_key, _strict_response_validation=True) + assert client.base_url == 'http://localhost:5000/from/env/' - @pytest.mark.parametrize( - "client", - [ - AsyncOzAPI( - base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True - ), - AsyncOzAPI( - base_url="http://localhost:5000/custom/path/", - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.AsyncClient(), - ), - ], - ids=["standard", "custom http client"], - ) + @pytest.mark.parametrize("client", [AsyncOzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), AsyncOzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient())], ids = ["standard", "custom http client"]) async def test_base_url_trailing_slash(self, client: AsyncOzAPI) -> None: request = client._build_request( FinalRequestOptions( @@ -1656,21 +1530,7 @@ async def test_base_url_trailing_slash(self, client: AsyncOzAPI) -> None: assert request.url == "http://localhost:5000/custom/path/foo" await client.close() - @pytest.mark.parametrize( - "client", - [ - AsyncOzAPI( - base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True - ), - AsyncOzAPI( - base_url="http://localhost:5000/custom/path/", - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.AsyncClient(), - ), - ], - ids=["standard", "custom http client"], - ) + @pytest.mark.parametrize("client", [AsyncOzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), AsyncOzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient())], ids = ["standard", "custom http client"]) async def test_base_url_no_trailing_slash(self, client: AsyncOzAPI) -> None: request = client._build_request( FinalRequestOptions( @@ -1682,21 +1542,7 @@ async def test_base_url_no_trailing_slash(self, client: AsyncOzAPI) -> None: assert request.url == "http://localhost:5000/custom/path/foo" await client.close() - @pytest.mark.parametrize( - "client", - [ - AsyncOzAPI( - base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True - ), - AsyncOzAPI( - base_url="http://localhost:5000/custom/path/", - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.AsyncClient(), - ), - ], - ids=["standard", "custom http client"], - ) + @pytest.mark.parametrize("client", [AsyncOzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), AsyncOzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient())], ids = ["standard", "custom http client"]) async def test_absolute_request_url(self, client: AsyncOzAPI) -> None: request = client._build_request( FinalRequestOptions( @@ -1723,9 +1569,9 @@ async def test_copied_client_does_not_close_http(self) -> None: async def test_client_context_manager(self) -> None: test_client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True) async with test_client as c2: - assert c2 is test_client - assert not c2.is_closed() - assert not test_client.is_closed() + assert c2 is test_client + assert not c2.is_closed() + assert not test_client.is_closed() assert test_client.is_closed() @pytest.mark.respx(base_url=base_url) @@ -1742,9 +1588,7 @@ class Model(BaseModel): async def test_client_max_retries_validation(self) -> None: with pytest.raises(TypeError, match=r"max_retries cannot be None"): - AsyncOzAPI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None) - ) + AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None)) @pytest.mark.respx(base_url=base_url) async def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: @@ -1756,7 +1600,7 @@ class Model(BaseModel): strict_client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True) with pytest.raises(APIResponseValidationError): - await strict_client.get("/foo", cast_to=Model) + await strict_client.get("/foo", cast_to=Model) non_strict_client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=False) @@ -1767,34 +1611,32 @@ class Model(BaseModel): await non_strict_client.close() @pytest.mark.parametrize( - "remaining_retries,retry_after,timeout", - [ - [3, "20", 20], - [3, "0", 0.5], - [3, "-10", 0.5], - [3, "60", 60], - [3, "61", 0.5], - [3, "Fri, 29 Sep 2023 16:26:57 GMT", 20], - [3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5], - [3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5], - [3, "Fri, 29 Sep 2023 16:27:37 GMT", 60], - [3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5], - [3, "99999999999999999999999999999999999", 0.5], - [3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5], - [3, "", 0.5], - [2, "", 0.5 * 2.0], - [1, "", 0.5 * 4.0], - [-1100, "", 8], # test large number potentially overflowing - ], - ) + "remaining_retries,retry_after,timeout", + [ + [ 3, "20", 20 ], + [ 3, "0", 0.5 ], + [ 3, "-10", 0.5 ], + [ 3, "60", 60 ], + [ 3, "61", 0.5 ], + [ 3, "Fri, 29 Sep 2023 16:26:57 GMT", 20 ], + [ 3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5 ], + [ 3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5 ], + [ 3, "Fri, 29 Sep 2023 16:27:37 GMT", 60 ], + [ 3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5 ], + [ 3, "99999999999999999999999999999999999", 0.5 ], + [ 3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5 ], + [ 3, "", 0.5 ], + [ 2, "", 0.5 * 2.0 ], + [ 1, "", 0.5 * 4.0 ], + [-1100, "", 8], # test large number potentially overflowing + ], + ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) - async def test_parse_retry_after_header( - self, remaining_retries: int, retry_after: str, timeout: float, async_client: AsyncOzAPI - ) -> None: + async def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float, async_client: AsyncOzAPI) -> None: headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) calculated = async_client._calculate_retry_timeout(remaining_retries, options, headers) - assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] + assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] @mock.patch("oz_agent_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @@ -1824,7 +1666,7 @@ async def test_retries_taken( async_client: AsyncOzAPI, failures_before_success: int, failure_mode: Literal["status", "exception"], - respx_mock: MockRouter, + respx_mock: MockRouter ) -> None: client = async_client.with_options(max_retries=4) @@ -1835,7 +1677,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: if nb_retries < failures_before_success: nb_retries += 1 if failure_mode == "exception": - raise RuntimeError("oops") + raise RuntimeError("oops") return httpx.Response(500) return httpx.Response(200) @@ -1850,7 +1692,10 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @mock.patch("oz_agent_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_omit_retry_count_header( - self, async_client: AsyncOzAPI, failures_before_success: int, respx_mock: MockRouter + self, + async_client: AsyncOzAPI, + failures_before_success: int, + respx_mock: MockRouter ) -> None: client = async_client.with_options(max_retries=4) @@ -1865,15 +1710,18 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/agent/runs").mock(side_effect=retry_handler) - response = await client.agent.with_raw_response.run(extra_headers={"x-stainless-retry-count": Omit()}) + response = await client.agent.with_raw_response.run(extra_headers={'x-stainless-retry-count': Omit()}) - assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 + assert len(response.http_request.headers.get_list('x-stainless-retry-count')) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("oz_agent_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_overwrite_retry_count_header( - self, async_client: AsyncOzAPI, failures_before_success: int, respx_mock: MockRouter + self, + async_client: AsyncOzAPI, + failures_before_success: int, + respx_mock: MockRouter ) -> None: client = async_client.with_options(max_retries=4) @@ -1888,9 +1736,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/agent/runs").mock(side_effect=retry_handler) - response = await client.agent.with_raw_response.run(extra_headers={"x-stainless-retry-count": "42"}) + response = await client.agent.with_raw_response.run(extra_headers={'x-stainless-retry-count': '42'}) - assert response.http_request.headers.get("x-stainless-retry-count") == "42" + assert response.http_request.headers.get('x-stainless-retry-count') == '42' async def test_get_platform(self) -> None: platform = await asyncify(get_platform)() @@ -1946,9 +1794,7 @@ async def test_follow_redirects_disabled(self, respx_mock: MockRouter, async_cli ) with pytest.raises(APIStatusError) as exc_info: - await async_client.post( - "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response - ) + await async_client.post("/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response) assert exc_info.value.response.status_code == 302 - assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" + assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" \ No newline at end of file diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index c7d7add..c378416 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -4,7 +4,7 @@ import pytest -from oz_agent_sdk._types import FileTypes, ArrayFormat +from oz_agent_sdk._types import ArrayFormat, FileTypes from oz_agent_sdk._utils import extract_files @@ -28,10 +28,7 @@ def test_removes_files_from_input() -> None: def test_multiple_files() -> None: query = {"documents": [{"file": b"My first file"}, {"file": b"My second file"}]} - assert extract_files(query, paths=[["documents", "", "file"]]) == [ - ("documents[][file]", b"My first file"), - ("documents[][file]", b"My second file"), - ] + assert extract_files(query, paths=[["documents", "", "file"]]) == [("documents[][file]", b"My first file"), ("documents[][file]", b"My second file")] assert query == {"documents": [{}, {}]} @@ -85,7 +82,13 @@ def test_array_format_controls_file_field_names( 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 + 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 + 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 393aa1a..3f0fe1c 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -4,7 +4,7 @@ import pytest from dirty_equals import IsDict, IsList, IsBytes, IsTuple -from oz_agent_sdk._files import to_httpx_files, deepcopy_with_paths, async_to_httpx_files +from oz_agent_sdk._files import async_to_httpx_files, deepcopy_with_paths, to_httpx_files from oz_agent_sdk._utils import extract_files readme_path = Path(__file__).parent.parent.joinpath("README.md") diff --git a/tests/test_models.py b/tests/test_models.py index ae6ec09..3c7f182 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,7 +1,7 @@ import json +from collections import deque from typing import TYPE_CHECKING, Any, Dict, List, Union, Iterable, Optional, cast from datetime import datetime, timezone -from collections import deque from typing_extensions import Literal, Annotated, TypedDict, TypeAliasType import pytest diff --git a/tests/test_response.py b/tests/test_response.py index b81481c..407d828 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -6,7 +6,7 @@ import pytest import pydantic -from oz_agent_sdk import OzAPI, BaseModel, AsyncOzAPI +from oz_agent_sdk import BaseModel, OzAPI, AsyncOzAPI from oz_agent_sdk._response import ( APIResponse, BaseAPIResponse, diff --git a/tests/test_streaming.py b/tests/test_streaming.py index b9b682f..ace9284 100644 --- a/tests/test_streaming.py +++ b/tests/test_streaming.py @@ -28,7 +28,9 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_data_missing_event(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: +async def test_data_missing_event( + sync: bool, client: OzAPI, async_client: AsyncOzAPI +) -> None: def body() -> Iterator[bytes]: yield b'data: {"foo":true}\n' yield b"\n" @@ -44,7 +46,9 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_event_missing_data(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: +async def test_event_missing_data( + sync: bool, client: OzAPI, async_client: AsyncOzAPI +) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"\n" @@ -60,7 +64,9 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_events(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: +async def test_multiple_events( + sync: bool, client: OzAPI, async_client: AsyncOzAPI +) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"\n" @@ -82,7 +88,9 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_events_with_data(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: +async def test_multiple_events_with_data( + sync: bool, client: OzAPI, async_client: AsyncOzAPI +) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b'data: {"foo":true}\n' @@ -106,7 +114,9 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_data_lines_with_empty_line(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: +async def test_multiple_data_lines_with_empty_line( + sync: bool, client: OzAPI, async_client: AsyncOzAPI +) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"data: {\n" @@ -128,7 +138,9 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_data_json_escaped_double_new_line(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: +async def test_data_json_escaped_double_new_line( + sync: bool, client: OzAPI, async_client: AsyncOzAPI +) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b'data: {"foo": "my long\\n\\ncontent"}' @@ -145,7 +157,9 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_data_lines(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: +async def test_multiple_data_lines( + sync: bool, client: OzAPI, async_client: AsyncOzAPI +) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"data: {\n" diff --git a/tests/test_transform.py b/tests/test_transform.py index 6b1bb6b..a7385fa 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -8,7 +8,7 @@ import pytest -from oz_agent_sdk._types import Base64FileInput, omit, not_given +from oz_agent_sdk._types import not_given, omit, Base64FileInput from oz_agent_sdk._utils import ( PropertyInfo, transform as _transform, diff --git a/tests/test_utils/test_datetime_parse.py b/tests/test_utils/test_datetime_parse.py index de12854..3b5c823 100644 --- a/tests/test_utils/test_datetime_parse.py +++ b/tests/test_utils/test_datetime_parse.py @@ -7,7 +7,6 @@ from datetime import date, datetime, timezone, timedelta import pytest - from oz_agent_sdk._utils import parse_date, parse_datetime diff --git a/tests/utils.py b/tests/utils.py index 3e9d221..526ea2e 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -4,7 +4,7 @@ import inspect import traceback import contextlib -from typing import Any, TypeVar, Iterator, Sequence, cast +from typing import Any, Sequence, TypeVar, Iterator, cast from datetime import date, datetime from typing_extensions import Literal, get_args, get_origin, assert_type @@ -13,9 +13,9 @@ is_dict, is_list, is_list_type, + is_sequence_type, is_union_type, extract_type_arg, - is_sequence_type, is_annotated_type, is_type_alias_type, ) From 27e79ac7caea54928333f9a44367c7830ee4c13a Mon Sep 17 00:00:00 2001 From: Ian Hodge Date: Wed, 17 Jun 2026 14:46:35 -0400 Subject: [PATCH 06/14] feat(deps): seal idna>=3.15 + aiohttp>=3.13.5 CVE floors as custom code Stainless-Generated-From: e3a3b28417a6ab3ebf0d1f3dfd20208b4d76ff7b --- pyproject.toml | 7 +- uv.lock | 423 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 293 insertions(+), 137 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 533a8e4..2d37867 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,11 +41,16 @@ Homepage = "https://github.com/warpdotdev/oz-sdk-python" Repository = "https://github.com/warpdotdev/oz-sdk-python" [project.optional-dependencies] -aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"] +aiohttp = ["aiohttp>=3.13.5", "httpx_aiohttp>=0.1.9"] [tool.uv] managed = true required-version = ">=0.9" +# Security pin: idna is a transitive dependency (via httpx + anyio) and is not +# declared above. Versions <3.15 are vulnerable to CVE-2026-45409 +# (GHSA-65pc-fj4g-8rjx), so constrain it without adding it as a direct +# dependency. Sealed as custom code so it survives SDK regeneration. +constraint-dependencies = ["idna>=3.15"] conflicts = [ [ { group = "pydantic-v1" }, diff --git a/uv.lock b/uv.lock index 816e22a..13132d8 100644 --- a/uv.lock +++ b/uv.lock @@ -15,6 +15,9 @@ conflicts = [[ { package = "oz-agent-sdk", group = "pydantic-v2" }, ]] +[manifest] +constraints = [{ name = "idna", specifier = ">=3.15" }] + [[package]] name = "aiohappyeyeballs" version = "2.6.1" @@ -26,139 +29,285 @@ wheels = [ [[package]] name = "aiohttp" -version = "3.13.3" +version = "3.13.5" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] dependencies = [ - { name = "aiohappyeyeballs" }, - { name = "aiosignal" }, - { name = "async-timeout", marker = "python_full_version < '3.11' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "attrs" }, - { name = "frozenlist" }, - { name = "multidict" }, - { name = "propcache" }, - { name = "yarl" }, + { name = "aiohappyeyeballs", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "aiosignal", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "async-timeout", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "attrs", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "frozenlist", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "multidict", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "propcache", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "yarl", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/77/9a/152096d4808df8e4268befa55fba462f440f14beab85e8ad9bf990516918/aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1", size = 7858271, upload-time = "2026-03-31T22:01:03.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/85/cebc47ee74d8b408749073a1a46c6fcba13d170dc8af7e61996c6c9394ac/aiohttp-3.13.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b", size = 750547, upload-time = "2026-03-31T21:56:30.024Z" }, + { url = "https://files.pythonhosted.org/packages/05/98/afd308e35b9d3d8c9ec54c0918f1d722c86dc17ddfec272fcdbcce5a3124/aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5", size = 503535, upload-time = "2026-03-31T21:56:31.935Z" }, + { url = "https://files.pythonhosted.org/packages/6f/4d/926c183e06b09d5270a309eb50fbde7b09782bfd305dec1e800f329834fb/aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670", size = 497830, upload-time = "2026-03-31T21:56:33.654Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d6/f47d1c690f115a5c2a5e8938cce4a232a5be9aac5c5fb2647efcbbbda333/aiohttp-3.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274", size = 1682474, upload-time = "2026-03-31T21:56:35.513Z" }, + { url = "https://files.pythonhosted.org/packages/01/44/056fd37b1bb52eac760303e5196acc74d9d546631b035704ae5927f7b4ac/aiohttp-3.13.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a", size = 1655259, upload-time = "2026-03-31T21:56:37.843Z" }, + { url = "https://files.pythonhosted.org/packages/91/9f/78eb1a20c1c28ae02f6a3c0f4d7b0dcc66abce5290cadd53d78ce3084175/aiohttp-3.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d", size = 1736204, upload-time = "2026-03-31T21:56:39.822Z" }, + { url = "https://files.pythonhosted.org/packages/de/6c/d20d7de23f0b52b8c1d9e2033b2db1ac4dacbb470bb74c56de0f5f86bb4f/aiohttp-3.13.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796", size = 1826198, upload-time = "2026-03-31T21:56:41.378Z" }, + { url = "https://files.pythonhosted.org/packages/2f/86/a6f3ff1fd795f49545a7c74b2c92f62729135d73e7e4055bf74da5a26c82/aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95", size = 1681329, upload-time = "2026-03-31T21:56:43.374Z" }, + { url = "https://files.pythonhosted.org/packages/fb/68/84cd3dab6b7b4f3e6fe9459a961acb142aaab846417f6e8905110d7027e5/aiohttp-3.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5", size = 1560023, upload-time = "2026-03-31T21:56:45.031Z" }, + { url = "https://files.pythonhosted.org/packages/41/2c/db61b64b0249e30f954a65ab4cb4970ced57544b1de2e3c98ee5dc24165f/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a", size = 1652372, upload-time = "2026-03-31T21:56:47.075Z" }, + { url = "https://files.pythonhosted.org/packages/25/6f/e96988a6c982d047810c772e28c43c64c300c943b0ed5c1c0c4ce1e1027c/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73", size = 1662031, upload-time = "2026-03-31T21:56:48.835Z" }, + { url = "https://files.pythonhosted.org/packages/b7/26/a56feace81f3d347b4052403a9d03754a0ab23f7940780dada0849a38c92/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297", size = 1708118, upload-time = "2026-03-31T21:56:50.833Z" }, + { url = "https://files.pythonhosted.org/packages/78/6e/b6173a8ff03d01d5e1a694bc06764b5dad1df2d4ed8f0ceec12bb3277936/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074", size = 1548667, upload-time = "2026-03-31T21:56:52.81Z" }, + { url = "https://files.pythonhosted.org/packages/16/13/13296ffe2c132d888b3fe2c195c8b9c0c24c89c3fa5cc2c44464dc23b22e/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e", size = 1724490, upload-time = "2026-03-31T21:56:54.541Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/1f1c287f4a79782ef36e5a6e62954c85343bc30470d862d30bd5f26c9fa2/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7", size = 1667109, upload-time = "2026-03-31T21:56:56.21Z" }, + { url = "https://files.pythonhosted.org/packages/ef/42/8461a2aaf60a8f4ea4549a4056be36b904b0eb03d97ca9a8a2604681a500/aiohttp-3.13.5-cp310-cp310-win32.whl", hash = "sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9", size = 439478, upload-time = "2026-03-31T21:56:58.292Z" }, + { url = "https://files.pythonhosted.org/packages/e5/71/06956304cb5ee439dfe8d86e1b2e70088bd88ed1ced1f42fb29e5d855f0e/aiohttp-3.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76", size = 462047, upload-time = "2026-03-31T21:57:00.257Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f5/a20c4ac64aeaef1679e25c9983573618ff765d7aa829fa2b84ae7573169e/aiohttp-3.13.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6", size = 757513, upload-time = "2026-03-31T21:57:02.146Z" }, + { url = "https://files.pythonhosted.org/packages/75/0a/39fa6c6b179b53fcb3e4b3d2b6d6cad0180854eda17060c7218540102bef/aiohttp-3.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d", size = 506748, upload-time = "2026-03-31T21:57:04.275Z" }, + { url = "https://files.pythonhosted.org/packages/87/ec/e38ce072e724fd7add6243613f8d1810da084f54175353d25ccf9f9c7e5a/aiohttp-3.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c", size = 501673, upload-time = "2026-03-31T21:57:06.208Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ba/3bc7525d7e2beaa11b309a70d48b0d3cfc3c2089ec6a7d0820d59c657053/aiohttp-3.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb", size = 1763757, upload-time = "2026-03-31T21:57:07.882Z" }, + { url = "https://files.pythonhosted.org/packages/5e/ab/e87744cf18f1bd78263aba24924d4953b41086bd3a31d22452378e9028a0/aiohttp-3.13.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6", size = 1720152, upload-time = "2026-03-31T21:57:09.946Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f3/ed17a6f2d742af17b50bae2d152315ed1b164b07a5fd5cc1754d99e4dfa5/aiohttp-3.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13", size = 1818010, upload-time = "2026-03-31T21:57:12.157Z" }, + { url = "https://files.pythonhosted.org/packages/53/06/ecbc63dc937192e2a5cb46df4d3edb21deb8225535818802f210a6ea5816/aiohttp-3.13.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174", size = 1907251, upload-time = "2026-03-31T21:57:14.023Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a5/0521aa32c1ddf3aa1e71dcc466be0b7db2771907a13f18cddaa45967d97b/aiohttp-3.13.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc", size = 1759969, upload-time = "2026-03-31T21:57:16.146Z" }, + { url = "https://files.pythonhosted.org/packages/f6/78/a38f8c9105199dd3b9706745865a8a59d0041b6be0ca0cc4b2ccf1bab374/aiohttp-3.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6", size = 1616871, upload-time = "2026-03-31T21:57:17.856Z" }, + { url = "https://files.pythonhosted.org/packages/6f/41/27392a61ead8ab38072105c71aa44ff891e71653fe53d576a7067da2b4e8/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49", size = 1739844, upload-time = "2026-03-31T21:57:19.679Z" }, + { url = "https://files.pythonhosted.org/packages/6e/55/5564e7ae26d94f3214250009a0b1c65a0c6af4bf88924ccb6fdab901de28/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8", size = 1731969, upload-time = "2026-03-31T21:57:22.006Z" }, + { url = "https://files.pythonhosted.org/packages/6d/c5/705a3929149865fc941bcbdd1047b238e4a72bcb215a9b16b9d7a2e8d992/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d", size = 1795193, upload-time = "2026-03-31T21:57:24.256Z" }, + { url = "https://files.pythonhosted.org/packages/a6/19/edabed62f718d02cff7231ca0db4ef1c72504235bc467f7b67adb1679f48/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c", size = 1606477, upload-time = "2026-03-31T21:57:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/de/fc/76f80ef008675637d88d0b21584596dc27410a990b0918cb1e5776545b5b/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac", size = 1813198, upload-time = "2026-03-31T21:57:28.316Z" }, + { url = "https://files.pythonhosted.org/packages/e5/67/5b3ac26b80adb20ea541c487f73730dc8fa107d632c998f25bbbab98fcda/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3", size = 1752321, upload-time = "2026-03-31T21:57:30.549Z" }, + { url = "https://files.pythonhosted.org/packages/88/06/e4a2e49255ea23fa4feeb5ab092d90240d927c15e47b5b5c48dff5a9ce29/aiohttp-3.13.5-cp311-cp311-win32.whl", hash = "sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06", size = 439069, upload-time = "2026-03-31T21:57:32.388Z" }, + { url = "https://files.pythonhosted.org/packages/c0/43/8c7163a596dab4f8be12c190cf467a1e07e4734cf90eebb39f7f5d53fc6a/aiohttp-3.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8", size = 462859, upload-time = "2026-03-31T21:57:34.455Z" }, + { url = "https://files.pythonhosted.org/packages/be/6f/353954c29e7dcce7cf00280a02c75f30e133c00793c7a2ed3776d7b2f426/aiohttp-3.13.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9", size = 748876, upload-time = "2026-03-31T21:57:36.319Z" }, + { url = "https://files.pythonhosted.org/packages/f5/1b/428a7c64687b3b2e9cd293186695affc0e1e54a445d0361743b231f11066/aiohttp-3.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416", size = 499557, upload-time = "2026-03-31T21:57:38.236Z" }, + { url = "https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2", size = 500258, upload-time = "2026-03-31T21:57:39.923Z" }, + { url = "https://files.pythonhosted.org/packages/67/84/c9ecc5828cb0b3695856c07c0a6817a99d51e2473400f705275a2b3d9239/aiohttp-3.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4", size = 1749199, upload-time = "2026-03-31T21:57:41.938Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d3/3c6d610e66b495657622edb6ae7c7fd31b2e9086b4ec50b47897ad6042a9/aiohttp-3.13.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9", size = 1721013, upload-time = "2026-03-31T21:57:43.904Z" }, + { url = "https://files.pythonhosted.org/packages/49/a0/24409c12217456df0bae7babe3b014e460b0b38a8e60753d6cb339f6556d/aiohttp-3.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5", size = 1781501, upload-time = "2026-03-31T21:57:46.285Z" }, + { url = "https://files.pythonhosted.org/packages/98/9d/b65ec649adc5bccc008b0957a9a9c691070aeac4e41cea18559fef49958b/aiohttp-3.13.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e", size = 1878981, upload-time = "2026-03-31T21:57:48.734Z" }, + { url = "https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1", size = 1767934, upload-time = "2026-03-31T21:57:51.171Z" }, + { url = "https://files.pythonhosted.org/packages/31/04/d3f8211f273356f158e3464e9e45484d3fb8c4ce5eb2f6fe9405c3273983/aiohttp-3.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286", size = 1566671, upload-time = "2026-03-31T21:57:53.326Z" }, + { url = "https://files.pythonhosted.org/packages/41/db/073e4ebe00b78e2dfcacff734291651729a62953b48933d765dc513bf798/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9", size = 1705219, upload-time = "2026-03-31T21:57:55.385Z" }, + { url = "https://files.pythonhosted.org/packages/48/45/7dfba71a2f9fd97b15c95c06819de7eb38113d2cdb6319669195a7d64270/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88", size = 1743049, upload-time = "2026-03-31T21:57:57.341Z" }, + { url = "https://files.pythonhosted.org/packages/18/71/901db0061e0f717d226386a7f471bb59b19566f2cae5f0d93874b017271f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3", size = 1749557, upload-time = "2026-03-31T21:57:59.626Z" }, + { url = "https://files.pythonhosted.org/packages/08/d5/41eebd16066e59cd43728fe74bce953d7402f2b4ddfdfef2c0e9f17ca274/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b", size = 1558931, upload-time = "2026-03-31T21:58:01.972Z" }, + { url = "https://files.pythonhosted.org/packages/30/e6/4a799798bf05740e66c3a1161079bda7a3dd8e22ca392481d7a7f9af82a6/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe", size = 1774125, upload-time = "2026-03-31T21:58:04.007Z" }, + { url = "https://files.pythonhosted.org/packages/84/63/7749337c90f92bc2cb18f9560d67aa6258c7060d1397d21529b8004fcf6f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14", size = 1732427, upload-time = "2026-03-31T21:58:06.337Z" }, + { url = "https://files.pythonhosted.org/packages/98/de/cf2f44ff98d307e72fb97d5f5bbae3bfcb442f0ea9790c0bf5c5c2331404/aiohttp-3.13.5-cp312-cp312-win32.whl", hash = "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3", size = 433534, upload-time = "2026-03-31T21:58:08.712Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1", size = 460446, upload-time = "2026-03-31T21:58:10.945Z" }, + { url = "https://files.pythonhosted.org/packages/78/e9/d76bf503005709e390122d34e15256b88f7008e246c4bdbe915cd4f1adce/aiohttp-3.13.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61", size = 742930, upload-time = "2026-03-31T21:58:13.155Z" }, + { url = "https://files.pythonhosted.org/packages/57/00/4b7b70223deaebd9bb85984d01a764b0d7bd6526fcdc73cca83bcbe7243e/aiohttp-3.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832", size = 496927, upload-time = "2026-03-31T21:58:15.073Z" }, + { url = "https://files.pythonhosted.org/packages/9c/f5/0fb20fb49f8efdcdce6cd8127604ad2c503e754a8f139f5e02b01626523f/aiohttp-3.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9", size = 497141, upload-time = "2026-03-31T21:58:17.009Z" }, + { url = "https://files.pythonhosted.org/packages/3b/86/b7c870053e36a94e8951b803cb5b909bfbc9b90ca941527f5fcafbf6b0fa/aiohttp-3.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090", size = 1732476, upload-time = "2026-03-31T21:58:18.925Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e5/4e161f84f98d80c03a238671b4136e6530453d65262867d989bbe78244d0/aiohttp-3.13.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b", size = 1706507, upload-time = "2026-03-31T21:58:21.094Z" }, + { url = "https://files.pythonhosted.org/packages/d4/56/ea11a9f01518bd5a2a2fcee869d248c4b8a0cfa0bb13401574fa31adf4d4/aiohttp-3.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a", size = 1773465, upload-time = "2026-03-31T21:58:23.159Z" }, + { url = "https://files.pythonhosted.org/packages/eb/40/333ca27fb74b0383f17c90570c748f7582501507307350a79d9f9f3c6eb1/aiohttp-3.13.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8", size = 1873523, upload-time = "2026-03-31T21:58:25.59Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d2/e2f77eef1acb7111405433c707dc735e63f67a56e176e72e9e7a2cd3f493/aiohttp-3.13.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665", size = 1754113, upload-time = "2026-03-31T21:58:27.624Z" }, + { url = "https://files.pythonhosted.org/packages/fb/56/3f653d7f53c89669301ec9e42c95233e2a0c0a6dd051269e6e678db4fdb0/aiohttp-3.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540", size = 1562351, upload-time = "2026-03-31T21:58:29.918Z" }, + { url = "https://files.pythonhosted.org/packages/ec/a6/9b3e91eb8ae791cce4ee736da02211c85c6f835f1bdfac0594a8a3b7018c/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb", size = 1693205, upload-time = "2026-03-31T21:58:32.214Z" }, + { url = "https://files.pythonhosted.org/packages/98/fc/bfb437a99a2fcebd6b6eaec609571954de2ed424f01c352f4b5504371dd3/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46", size = 1730618, upload-time = "2026-03-31T21:58:34.728Z" }, + { url = "https://files.pythonhosted.org/packages/e4/b6/c8534862126191a034f68153194c389addc285a0f1347d85096d349bbc15/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8", size = 1745185, upload-time = "2026-03-31T21:58:36.909Z" }, + { url = "https://files.pythonhosted.org/packages/0b/93/4ca8ee2ef5236e2707e0fd5fecb10ce214aee1ff4ab307af9c558bda3b37/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d", size = 1557311, upload-time = "2026-03-31T21:58:39.38Z" }, + { url = "https://files.pythonhosted.org/packages/57/ae/76177b15f18c5f5d094f19901d284025db28eccc5ae374d1d254181d33f4/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6", size = 1773147, upload-time = "2026-03-31T21:58:41.476Z" }, + { url = "https://files.pythonhosted.org/packages/01/a4/62f05a0a98d88af59d93b7fcac564e5f18f513cb7471696ac286db970d6a/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c", size = 1730356, upload-time = "2026-03-31T21:58:44.049Z" }, + { url = "https://files.pythonhosted.org/packages/e4/85/fc8601f59dfa8c9523808281f2da571f8b4699685f9809a228adcc90838d/aiohttp-3.13.5-cp313-cp313-win32.whl", hash = "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc", size = 432637, upload-time = "2026-03-31T21:58:46.167Z" }, + { url = "https://files.pythonhosted.org/packages/c0/1b/ac685a8882896acf0f6b31d689e3792199cfe7aba37969fa91da63a7fa27/aiohttp-3.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83", size = 458896, upload-time = "2026-03-31T21:58:48.119Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ce/46572759afc859e867a5bc8ec3487315869013f59281ce61764f76d879de/aiohttp-3.13.5-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c", size = 745721, upload-time = "2026-03-31T21:58:50.229Z" }, + { url = "https://files.pythonhosted.org/packages/13/fe/8a2efd7626dbe6049b2ef8ace18ffda8a4dfcbe1bcff3ac30c0c7575c20b/aiohttp-3.13.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be", size = 497663, upload-time = "2026-03-31T21:58:52.232Z" }, + { url = "https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25", size = 499094, upload-time = "2026-03-31T21:58:54.566Z" }, + { url = "https://files.pythonhosted.org/packages/0a/33/a8362cb15cf16a3af7e86ed11962d5cd7d59b449202dc576cdc731310bde/aiohttp-3.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56", size = 1726701, upload-time = "2026-03-31T21:58:56.864Z" }, + { url = "https://files.pythonhosted.org/packages/45/0c/c091ac5c3a17114bd76cbf85d674650969ddf93387876cf67f754204bd77/aiohttp-3.13.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2", size = 1683360, upload-time = "2026-03-31T21:58:59.072Z" }, + { url = "https://files.pythonhosted.org/packages/23/73/bcee1c2b79bc275e964d1446c55c54441a461938e70267c86afaae6fba27/aiohttp-3.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a", size = 1773023, upload-time = "2026-03-31T21:59:01.776Z" }, + { url = "https://files.pythonhosted.org/packages/c7/ef/720e639df03004fee2d869f771799d8c23046dec47d5b81e396c7cda583a/aiohttp-3.13.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be", size = 1853795, upload-time = "2026-03-31T21:59:04.568Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b", size = 1730405, upload-time = "2026-03-31T21:59:07.221Z" }, + { url = "https://files.pythonhosted.org/packages/ce/75/ee1fd286ca7dc599d824b5651dad7b3be7ff8d9a7e7b3fe9820d9180f7db/aiohttp-3.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94", size = 1558082, upload-time = "2026-03-31T21:59:09.484Z" }, + { url = "https://files.pythonhosted.org/packages/c3/20/1e9e6650dfc436340116b7aa89ff8cb2bbdf0abc11dfaceaad8f74273a10/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d", size = 1692346, upload-time = "2026-03-31T21:59:12.068Z" }, + { url = "https://files.pythonhosted.org/packages/d8/40/8ebc6658d48ea630ac7903912fe0dd4e262f0e16825aa4c833c56c9f1f56/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7", size = 1698891, upload-time = "2026-03-31T21:59:14.552Z" }, + { url = "https://files.pythonhosted.org/packages/d8/78/ea0ae5ec8ba7a5c10bdd6e318f1ba5e76fcde17db8275188772afc7917a4/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772", size = 1742113, upload-time = "2026-03-31T21:59:17.068Z" }, + { url = "https://files.pythonhosted.org/packages/8a/66/9d308ed71e3f2491be1acb8769d96c6f0c47d92099f3bc9119cada27b357/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5", size = 1553088, upload-time = "2026-03-31T21:59:19.541Z" }, + { url = "https://files.pythonhosted.org/packages/da/a6/6cc25ed8dfc6e00c90f5c6d126a98e2cf28957ad06fa1036bd34b6f24a2c/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1", size = 1757976, upload-time = "2026-03-31T21:59:22.311Z" }, + { url = "https://files.pythonhosted.org/packages/c1/2b/cce5b0ffe0de99c83e5e36d8f828e4161e415660a9f3e58339d07cce3006/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b", size = 1712444, upload-time = "2026-03-31T21:59:24.635Z" }, + { url = "https://files.pythonhosted.org/packages/6c/cf/9e1795b4160c58d29421eafd1a69c6ce351e2f7c8d3c6b7e4ca44aea1a5b/aiohttp-3.13.5-cp314-cp314-win32.whl", hash = "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3", size = 438128, upload-time = "2026-03-31T21:59:27.291Z" }, + { url = "https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162", size = 464029, upload-time = "2026-03-31T21:59:29.429Z" }, + { url = "https://files.pythonhosted.org/packages/79/11/c27d9332ee20d68dd164dc12a6ecdef2e2e35ecc97ed6cf0d2442844624b/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a", size = 778758, upload-time = "2026-03-31T21:59:31.547Z" }, + { url = "https://files.pythonhosted.org/packages/04/fb/377aead2e0a3ba5f09b7624f702a964bdf4f08b5b6728a9799830c80041e/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254", size = 512883, upload-time = "2026-03-31T21:59:34.098Z" }, + { url = "https://files.pythonhosted.org/packages/bb/a6/aa109a33671f7a5d3bd78b46da9d852797c5e665bfda7d6b373f56bff2ec/aiohttp-3.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36", size = 516668, upload-time = "2026-03-31T21:59:36.497Z" }, + { url = "https://files.pythonhosted.org/packages/79/b3/ca078f9f2fa9563c36fb8ef89053ea2bb146d6f792c5104574d49d8acb63/aiohttp-3.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f", size = 1883461, upload-time = "2026-03-31T21:59:38.723Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e3/a7ad633ca1ca497b852233a3cce6906a56c3225fb6d9217b5e5e60b7419d/aiohttp-3.13.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800", size = 1747661, upload-time = "2026-03-31T21:59:41.187Z" }, + { url = "https://files.pythonhosted.org/packages/33/b9/cd6fe579bed34a906d3d783fe60f2fa297ef55b27bb4538438ee49d4dc41/aiohttp-3.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf", size = 1863800, upload-time = "2026-03-31T21:59:43.84Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3f/2c1e2f5144cefa889c8afd5cf431994c32f3b29da9961698ff4e3811b79a/aiohttp-3.13.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b", size = 1958382, upload-time = "2026-03-31T21:59:46.187Z" }, + { url = "https://files.pythonhosted.org/packages/66/1d/f31ec3f1013723b3babe3609e7f119c2c2fb6ef33da90061a705ef3e1bc8/aiohttp-3.13.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a", size = 1803724, upload-time = "2026-03-31T21:59:48.656Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b4/57712dfc6f1542f067daa81eb61da282fab3e6f1966fca25db06c4fc62d5/aiohttp-3.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8", size = 1640027, upload-time = "2026-03-31T21:59:51.284Z" }, + { url = "https://files.pythonhosted.org/packages/25/3c/734c878fb43ec083d8e31bf029daae1beafeae582d1b35da234739e82ee7/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be", size = 1806644, upload-time = "2026-03-31T21:59:53.753Z" }, + { url = "https://files.pythonhosted.org/packages/20/a5/f671e5cbec1c21d044ff3078223f949748f3a7f86b14e34a365d74a5d21f/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b", size = 1791630, upload-time = "2026-03-31T21:59:56.239Z" }, + { url = "https://files.pythonhosted.org/packages/0b/63/fb8d0ad63a0b8a99be97deac8c04dacf0785721c158bdf23d679a87aa99e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6", size = 1809403, upload-time = "2026-03-31T21:59:59.103Z" }, + { url = "https://files.pythonhosted.org/packages/59/0c/bfed7f30662fcf12206481c2aac57dedee43fe1c49275e85b3a1e1742294/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037", size = 1634924, upload-time = "2026-03-31T22:00:02.116Z" }, + { url = "https://files.pythonhosted.org/packages/17/d6/fd518d668a09fd5a3319ae5e984d4d80b9a4b3df4e21c52f02251ef5a32e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500", size = 1836119, upload-time = "2026-03-31T22:00:04.756Z" }, + { url = "https://files.pythonhosted.org/packages/78/b7/15fb7a9d52e112a25b621c67b69c167805cb1f2ab8f1708a5c490d1b52fe/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9", size = 1772072, upload-time = "2026-03-31T22:00:07.494Z" }, + { url = "https://files.pythonhosted.org/packages/7e/df/57ba7f0c4a553fc2bd8b6321df236870ec6fd64a2a473a8a13d4f733214e/aiohttp-3.13.5-cp314-cp314t-win32.whl", hash = "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8", size = 471819, upload-time = "2026-03-31T22:00:10.277Z" }, + { url = "https://files.pythonhosted.org/packages/62/29/2f8418269e46454a26171bfdd6a055d74febf32234e474930f2f60a17145/aiohttp-3.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9", size = 505441, upload-time = "2026-03-31T22:00:12.791Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a5/630bc484695d4a1342bbae85fb8689bf979106525684fc88f05b397324ad/aiohttp-3.13.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf", size = 752872, upload-time = "2026-03-31T22:00:15.553Z" }, + { url = "https://files.pythonhosted.org/packages/cd/b8/6a19dda37fda94a9ebefb3c1ae0ff419ac7fbf4fb40750e992829fc13614/aiohttp-3.13.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1", size = 504582, upload-time = "2026-03-31T22:00:18.191Z" }, + { url = "https://files.pythonhosted.org/packages/d5/34/8413eafee3421ade2d6ce9e7c0da1213e1d7f0049be09dcdc342b03a39ba/aiohttp-3.13.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10", size = 499094, upload-time = "2026-03-31T22:00:21.118Z" }, + { url = "https://files.pythonhosted.org/packages/da/cf/c6f97006093d1e8ca40fbab843ff49ec7725ab668f0714dd1cb702c62cbd/aiohttp-3.13.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f", size = 1669505, upload-time = "2026-03-31T22:00:24.01Z" }, + { url = "https://files.pythonhosted.org/packages/c2/27/3b2288e66dcec8b04771b2bee3909f70e4072bea995cde5ab7e775e73ddc/aiohttp-3.13.5-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b", size = 1648928, upload-time = "2026-03-31T22:00:27.001Z" }, + { url = "https://files.pythonhosted.org/packages/3a/7f/605d766887594a88dcc27a19663499c7c5e13e7aa87f129b763765a2ee63/aiohttp-3.13.5-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643", size = 1731800, upload-time = "2026-03-31T22:00:29.603Z" }, + { url = "https://files.pythonhosted.org/packages/71/94/5a878e728e30699d22b118f1a6ad576ab6fff9eb2c6fc8a7faa9376a1c3e/aiohttp-3.13.5-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031", size = 1824247, upload-time = "2026-03-31T22:00:32.139Z" }, + { url = "https://files.pythonhosted.org/packages/37/99/84b448291e9996bb83bf4fad3a71a9786d542f19c50a3ff0531bfaba6fac/aiohttp-3.13.5-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258", size = 1670742, upload-time = "2026-03-31T22:00:34.788Z" }, + { url = "https://files.pythonhosted.org/packages/14/a8/d8d5d1ab6d29a4a3bdb9db31f161e338bfdf6638f6574ea8380f1d4a243c/aiohttp-3.13.5-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a", size = 1562474, upload-time = "2026-03-31T22:00:37.623Z" }, + { url = "https://files.pythonhosted.org/packages/92/e8/bd889697916f10b65524422c61b4eeaf919eb35a170290cccb680cbe4eb4/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88", size = 1642235, upload-time = "2026-03-31T22:00:40.541Z" }, + { url = "https://files.pythonhosted.org/packages/60/42/3f1928107131f1413a5972ace14ddcd5364968e9bd7b3ad71272defafc9c/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0", size = 1655397, upload-time = "2026-03-31T22:00:43.167Z" }, + { url = "https://files.pythonhosted.org/packages/b2/79/c4bbcf4cac3a4715a326e49720ccdc3a4b5e14a367c5029eae7727d06029/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f", size = 1703509, upload-time = "2026-03-31T22:00:45.908Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e6/32d245876f211a7308a7d5437707f9296b1f9837a2888a407ed04e61321c/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8", size = 1550098, upload-time = "2026-03-31T22:00:49.48Z" }, + { url = "https://files.pythonhosted.org/packages/db/62/ab0f1304def56ce2356e6fbb9f0b024d6544010351430070f48f53b89e0a/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f", size = 1724326, upload-time = "2026-03-31T22:00:52.165Z" }, + { url = "https://files.pythonhosted.org/packages/c4/9a/aab4469689024046220ea438aa020ea2ae04cd1dd71aea3057e094f8c357/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b", size = 1658824, upload-time = "2026-03-31T22:00:55.122Z" }, + { url = "https://files.pythonhosted.org/packages/b0/98/bcc35d4db687acabf06d41f561a99fa88bca145292513388c858d99b72c5/aiohttp-3.13.5-cp39-cp39-win32.whl", hash = "sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83", size = 440302, upload-time = "2026-03-31T22:00:57.673Z" }, + { url = "https://files.pythonhosted.org/packages/25/61/b0203c2ef6bd268fca0eda142f0efbba7cbebd7ad38f7bb01dd31c2ff68e/aiohttp-3.13.5-cp39-cp39-win_amd64.whl", hash = "sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67", size = 463076, upload-time = "2026-03-31T22:01:00.264Z" }, +] + +[[package]] +name = "aiohttp" +version = "3.14.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2'", + "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2'", + "python_full_version >= '3.10' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra != 'group-12-oz-agent-sdk-pydantic-v2'", + "python_full_version >= '3.10' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra != 'group-12-oz-agent-sdk-pydantic-v2'", +] +dependencies = [ + { name = "aiohappyeyeballs", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "aiosignal", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "async-timeout", marker = "python_full_version == '3.10.*' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "attrs", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "frozenlist", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "multidict", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "propcache", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "typing-extensions", marker = "(python_full_version >= '3.10' and python_full_version < '3.13') or (python_full_version < '3.10' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2') or (python_full_version >= '3.13' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "yarl", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/50/42/32cf8e7704ceb4481406eb87161349abb46a57fee3f008ba9cb610968646/aiohttp-3.13.3.tar.gz", hash = "sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88", size = 7844556, upload-time = "2026-01-03T17:33:05.204Z" } +sdist = { url = "https://files.pythonhosted.org/packages/82/78/8ea7308cac6934de8c74a14f3d5f65d1c89287426688be79538d0e5c013d/aiohttp-3.14.1.tar.gz", hash = "sha256:307f2cff90a764d329e77040603fa032db89c5c24fdad50c4c15334cba744035", size = 7955794, upload-time = "2026-06-07T21:09:35.529Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/d6/5aec9313ee6ea9c7cde8b891b69f4ff4001416867104580670a31daeba5b/aiohttp-3.13.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7", size = 738950, upload-time = "2026-01-03T17:29:13.002Z" }, - { url = "https://files.pythonhosted.org/packages/68/03/8fa90a7e6d11ff20a18837a8e2b5dd23db01aabc475aa9271c8ad33299f5/aiohttp-3.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821", size = 496099, upload-time = "2026-01-03T17:29:15.268Z" }, - { url = "https://files.pythonhosted.org/packages/d2/23/b81f744d402510a8366b74eb420fc0cc1170d0c43daca12d10814df85f10/aiohttp-3.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845", size = 491072, upload-time = "2026-01-03T17:29:16.922Z" }, - { url = "https://files.pythonhosted.org/packages/d5/e1/56d1d1c0dd334cd203dd97706ce004c1aa24b34a813b0b8daf3383039706/aiohttp-3.13.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af", size = 1671588, upload-time = "2026-01-03T17:29:18.539Z" }, - { url = "https://files.pythonhosted.org/packages/5f/34/8d7f962604f4bc2b4e39eb1220dac7d4e4cba91fb9ba0474b4ecd67db165/aiohttp-3.13.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940", size = 1640334, upload-time = "2026-01-03T17:29:21.028Z" }, - { url = "https://files.pythonhosted.org/packages/94/1d/fcccf2c668d87337ddeef9881537baee13c58d8f01f12ba8a24215f2b804/aiohttp-3.13.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160", size = 1722656, upload-time = "2026-01-03T17:29:22.531Z" }, - { url = "https://files.pythonhosted.org/packages/aa/98/c6f3b081c4c606bc1e5f2ec102e87d6411c73a9ef3616fea6f2d5c98c062/aiohttp-3.13.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7", size = 1817625, upload-time = "2026-01-03T17:29:24.276Z" }, - { url = "https://files.pythonhosted.org/packages/2c/c0/cfcc3d2e11b477f86e1af2863f3858c8850d751ce8dc39c4058a072c9e54/aiohttp-3.13.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455", size = 1672604, upload-time = "2026-01-03T17:29:26.099Z" }, - { url = "https://files.pythonhosted.org/packages/1e/77/6b4ffcbcac4c6a5d041343a756f34a6dd26174ae07f977a64fe028dda5b0/aiohttp-3.13.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279", size = 1554370, upload-time = "2026-01-03T17:29:28.121Z" }, - { url = "https://files.pythonhosted.org/packages/f2/f0/e3ddfa93f17d689dbe014ba048f18e0c9f9b456033b70e94349a2e9048be/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e", size = 1642023, upload-time = "2026-01-03T17:29:30.002Z" }, - { url = "https://files.pythonhosted.org/packages/eb/45/c14019c9ec60a8e243d06d601b33dcc4fd92379424bde3021725859d7f99/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d", size = 1649680, upload-time = "2026-01-03T17:29:31.782Z" }, - { url = "https://files.pythonhosted.org/packages/9c/fd/09c9451dae5aa5c5ed756df95ff9ef549d45d4be663bafd1e4954fd836f0/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808", size = 1692407, upload-time = "2026-01-03T17:29:33.392Z" }, - { url = "https://files.pythonhosted.org/packages/a6/81/938bc2ec33c10efd6637ccb3d22f9f3160d08e8f3aa2587a2c2d5ab578eb/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40", size = 1543047, upload-time = "2026-01-03T17:29:34.855Z" }, - { url = "https://files.pythonhosted.org/packages/f7/23/80488ee21c8d567c83045e412e1d9b7077d27171591a4eb7822586e8c06a/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29", size = 1715264, upload-time = "2026-01-03T17:29:36.389Z" }, - { url = "https://files.pythonhosted.org/packages/e2/83/259a8da6683182768200b368120ab3deff5370bed93880fb9a3a86299f34/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11", size = 1657275, upload-time = "2026-01-03T17:29:38.162Z" }, - { url = "https://files.pythonhosted.org/packages/3f/4f/2c41f800a0b560785c10fb316216ac058c105f9be50bdc6a285de88db625/aiohttp-3.13.3-cp310-cp310-win32.whl", hash = "sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd", size = 434053, upload-time = "2026-01-03T17:29:40.074Z" }, - { url = "https://files.pythonhosted.org/packages/80/df/29cd63c7ecfdb65ccc12f7d808cac4fa2a19544660c06c61a4a48462de0c/aiohttp-3.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c", size = 456687, upload-time = "2026-01-03T17:29:41.819Z" }, - { url = "https://files.pythonhosted.org/packages/f1/4c/a164164834f03924d9a29dc3acd9e7ee58f95857e0b467f6d04298594ebb/aiohttp-3.13.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b", size = 746051, upload-time = "2026-01-03T17:29:43.287Z" }, - { url = "https://files.pythonhosted.org/packages/82/71/d5c31390d18d4f58115037c432b7e0348c60f6f53b727cad33172144a112/aiohttp-3.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64", size = 499234, upload-time = "2026-01-03T17:29:44.822Z" }, - { url = "https://files.pythonhosted.org/packages/0e/c9/741f8ac91e14b1d2e7100690425a5b2b919a87a5075406582991fb7de920/aiohttp-3.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea", size = 494979, upload-time = "2026-01-03T17:29:46.405Z" }, - { url = "https://files.pythonhosted.org/packages/75/b5/31d4d2e802dfd59f74ed47eba48869c1c21552c586d5e81a9d0d5c2ad640/aiohttp-3.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a", size = 1748297, upload-time = "2026-01-03T17:29:48.083Z" }, - { url = "https://files.pythonhosted.org/packages/1a/3e/eefad0ad42959f226bb79664826883f2687d602a9ae2941a18e0484a74d3/aiohttp-3.13.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540", size = 1707172, upload-time = "2026-01-03T17:29:49.648Z" }, - { url = "https://files.pythonhosted.org/packages/c5/3a/54a64299fac2891c346cdcf2aa6803f994a2e4beeaf2e5a09dcc54acc842/aiohttp-3.13.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b", size = 1805405, upload-time = "2026-01-03T17:29:51.244Z" }, - { url = "https://files.pythonhosted.org/packages/6c/70/ddc1b7169cf64075e864f64595a14b147a895a868394a48f6a8031979038/aiohttp-3.13.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3", size = 1899449, upload-time = "2026-01-03T17:29:53.938Z" }, - { url = "https://files.pythonhosted.org/packages/a1/7e/6815aab7d3a56610891c76ef79095677b8b5be6646aaf00f69b221765021/aiohttp-3.13.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1", size = 1748444, upload-time = "2026-01-03T17:29:55.484Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f2/073b145c4100da5511f457dc0f7558e99b2987cf72600d42b559db856fbc/aiohttp-3.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3", size = 1606038, upload-time = "2026-01-03T17:29:57.179Z" }, - { url = "https://files.pythonhosted.org/packages/0a/c1/778d011920cae03ae01424ec202c513dc69243cf2db303965615b81deeea/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440", size = 1724156, upload-time = "2026-01-03T17:29:58.914Z" }, - { url = "https://files.pythonhosted.org/packages/0e/cb/3419eabf4ec1e9ec6f242c32b689248365a1cf621891f6f0386632525494/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7", size = 1722340, upload-time = "2026-01-03T17:30:01.962Z" }, - { url = "https://files.pythonhosted.org/packages/7a/e5/76cf77bdbc435bf233c1f114edad39ed4177ccbfab7c329482b179cff4f4/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c", size = 1783041, upload-time = "2026-01-03T17:30:03.609Z" }, - { url = "https://files.pythonhosted.org/packages/9d/d4/dd1ca234c794fd29c057ce8c0566b8ef7fd6a51069de5f06fa84b9a1971c/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51", size = 1596024, upload-time = "2026-01-03T17:30:05.132Z" }, - { url = "https://files.pythonhosted.org/packages/55/58/4345b5f26661a6180afa686c473620c30a66afdf120ed3dd545bbc809e85/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4", size = 1804590, upload-time = "2026-01-03T17:30:07.135Z" }, - { url = "https://files.pythonhosted.org/packages/7b/06/05950619af6c2df7e0a431d889ba2813c9f0129cec76f663e547a5ad56f2/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29", size = 1740355, upload-time = "2026-01-03T17:30:09.083Z" }, - { url = "https://files.pythonhosted.org/packages/3e/80/958f16de79ba0422d7c1e284b2abd0c84bc03394fbe631d0a39ffa10e1eb/aiohttp-3.13.3-cp311-cp311-win32.whl", hash = "sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239", size = 433701, upload-time = "2026-01-03T17:30:10.869Z" }, - { url = "https://files.pythonhosted.org/packages/dc/f2/27cdf04c9851712d6c1b99df6821a6623c3c9e55956d4b1e318c337b5a48/aiohttp-3.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f", size = 457678, upload-time = "2026-01-03T17:30:12.719Z" }, - { url = "https://files.pythonhosted.org/packages/a0/be/4fc11f202955a69e0db803a12a062b8379c970c7c84f4882b6da17337cc1/aiohttp-3.13.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c", size = 739732, upload-time = "2026-01-03T17:30:14.23Z" }, - { url = "https://files.pythonhosted.org/packages/97/2c/621d5b851f94fa0bb7430d6089b3aa970a9d9b75196bc93bb624b0db237a/aiohttp-3.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168", size = 494293, upload-time = "2026-01-03T17:30:15.96Z" }, - { url = "https://files.pythonhosted.org/packages/5d/43/4be01406b78e1be8320bb8316dc9c42dbab553d281c40364e0f862d5661c/aiohttp-3.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d", size = 493533, upload-time = "2026-01-03T17:30:17.431Z" }, - { url = "https://files.pythonhosted.org/packages/8d/a8/5a35dc56a06a2c90d4742cbf35294396907027f80eea696637945a106f25/aiohttp-3.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29", size = 1737839, upload-time = "2026-01-03T17:30:19.422Z" }, - { url = "https://files.pythonhosted.org/packages/bf/62/4b9eeb331da56530bf2e198a297e5303e1c1ebdceeb00fe9b568a65c5a0c/aiohttp-3.13.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3", size = 1703932, upload-time = "2026-01-03T17:30:21.756Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f6/af16887b5d419e6a367095994c0b1332d154f647e7dc2bd50e61876e8e3d/aiohttp-3.13.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d", size = 1771906, upload-time = "2026-01-03T17:30:23.932Z" }, - { url = "https://files.pythonhosted.org/packages/ce/83/397c634b1bcc24292fa1e0c7822800f9f6569e32934bdeef09dae7992dfb/aiohttp-3.13.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463", size = 1871020, upload-time = "2026-01-03T17:30:26Z" }, - { url = "https://files.pythonhosted.org/packages/86/f6/a62cbbf13f0ac80a70f71b1672feba90fdb21fd7abd8dbf25c0105fb6fa3/aiohttp-3.13.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc", size = 1755181, upload-time = "2026-01-03T17:30:27.554Z" }, - { url = "https://files.pythonhosted.org/packages/0a/87/20a35ad487efdd3fba93d5843efdfaa62d2f1479eaafa7453398a44faf13/aiohttp-3.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf", size = 1561794, upload-time = "2026-01-03T17:30:29.254Z" }, - { url = "https://files.pythonhosted.org/packages/de/95/8fd69a66682012f6716e1bc09ef8a1a2a91922c5725cb904689f112309c4/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033", size = 1697900, upload-time = "2026-01-03T17:30:31.033Z" }, - { url = "https://files.pythonhosted.org/packages/e5/66/7b94b3b5ba70e955ff597672dad1691333080e37f50280178967aff68657/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f", size = 1728239, upload-time = "2026-01-03T17:30:32.703Z" }, - { url = "https://files.pythonhosted.org/packages/47/71/6f72f77f9f7d74719692ab65a2a0252584bf8d5f301e2ecb4c0da734530a/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679", size = 1740527, upload-time = "2026-01-03T17:30:34.695Z" }, - { url = "https://files.pythonhosted.org/packages/fa/b4/75ec16cbbd5c01bdaf4a05b19e103e78d7ce1ef7c80867eb0ace42ff4488/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423", size = 1554489, upload-time = "2026-01-03T17:30:36.864Z" }, - { url = "https://files.pythonhosted.org/packages/52/8f/bc518c0eea29f8406dcf7ed1f96c9b48e3bc3995a96159b3fc11f9e08321/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce", size = 1767852, upload-time = "2026-01-03T17:30:39.433Z" }, - { url = "https://files.pythonhosted.org/packages/9d/f2/a07a75173124f31f11ea6f863dc44e6f09afe2bca45dd4e64979490deab1/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a", size = 1722379, upload-time = "2026-01-03T17:30:41.081Z" }, - { url = "https://files.pythonhosted.org/packages/3c/4a/1a3fee7c21350cac78e5c5cef711bac1b94feca07399f3d406972e2d8fcd/aiohttp-3.13.3-cp312-cp312-win32.whl", hash = "sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046", size = 428253, upload-time = "2026-01-03T17:30:42.644Z" }, - { url = "https://files.pythonhosted.org/packages/d9/b7/76175c7cb4eb73d91ad63c34e29fc4f77c9386bba4a65b53ba8e05ee3c39/aiohttp-3.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57", size = 455407, upload-time = "2026-01-03T17:30:44.195Z" }, - { url = "https://files.pythonhosted.org/packages/97/8a/12ca489246ca1faaf5432844adbfce7ff2cc4997733e0af120869345643a/aiohttp-3.13.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c", size = 734190, upload-time = "2026-01-03T17:30:45.832Z" }, - { url = "https://files.pythonhosted.org/packages/32/08/de43984c74ed1fca5c014808963cc83cb00d7bb06af228f132d33862ca76/aiohttp-3.13.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9", size = 491783, upload-time = "2026-01-03T17:30:47.466Z" }, - { url = "https://files.pythonhosted.org/packages/17/f8/8dd2cf6112a5a76f81f81a5130c57ca829d101ad583ce57f889179accdda/aiohttp-3.13.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3", size = 490704, upload-time = "2026-01-03T17:30:49.373Z" }, - { url = "https://files.pythonhosted.org/packages/6d/40/a46b03ca03936f832bc7eaa47cfbb1ad012ba1be4790122ee4f4f8cba074/aiohttp-3.13.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf", size = 1720652, upload-time = "2026-01-03T17:30:50.974Z" }, - { url = "https://files.pythonhosted.org/packages/f7/7e/917fe18e3607af92657e4285498f500dca797ff8c918bd7d90b05abf6c2a/aiohttp-3.13.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6", size = 1692014, upload-time = "2026-01-03T17:30:52.729Z" }, - { url = "https://files.pythonhosted.org/packages/71/b6/cefa4cbc00d315d68973b671cf105b21a609c12b82d52e5d0c9ae61d2a09/aiohttp-3.13.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d", size = 1759777, upload-time = "2026-01-03T17:30:54.537Z" }, - { url = "https://files.pythonhosted.org/packages/fb/e3/e06ee07b45e59e6d81498b591fc589629be1553abb2a82ce33efe2a7b068/aiohttp-3.13.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261", size = 1861276, upload-time = "2026-01-03T17:30:56.512Z" }, - { url = "https://files.pythonhosted.org/packages/7c/24/75d274228acf35ceeb2850b8ce04de9dd7355ff7a0b49d607ee60c29c518/aiohttp-3.13.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0", size = 1743131, upload-time = "2026-01-03T17:30:58.256Z" }, - { url = "https://files.pythonhosted.org/packages/04/98/3d21dde21889b17ca2eea54fdcff21b27b93f45b7bb94ca029c31ab59dc3/aiohttp-3.13.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730", size = 1556863, upload-time = "2026-01-03T17:31:00.445Z" }, - { url = "https://files.pythonhosted.org/packages/9e/84/da0c3ab1192eaf64782b03971ab4055b475d0db07b17eff925e8c93b3aa5/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91", size = 1682793, upload-time = "2026-01-03T17:31:03.024Z" }, - { url = "https://files.pythonhosted.org/packages/ff/0f/5802ada182f575afa02cbd0ec5180d7e13a402afb7c2c03a9aa5e5d49060/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3", size = 1716676, upload-time = "2026-01-03T17:31:04.842Z" }, - { url = "https://files.pythonhosted.org/packages/3f/8c/714d53bd8b5a4560667f7bbbb06b20c2382f9c7847d198370ec6526af39c/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4", size = 1733217, upload-time = "2026-01-03T17:31:06.868Z" }, - { url = "https://files.pythonhosted.org/packages/7d/79/e2176f46d2e963facea939f5be2d26368ce543622be6f00a12844d3c991f/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998", size = 1552303, upload-time = "2026-01-03T17:31:08.958Z" }, - { url = "https://files.pythonhosted.org/packages/ab/6a/28ed4dea1759916090587d1fe57087b03e6c784a642b85ef48217b0277ae/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0", size = 1763673, upload-time = "2026-01-03T17:31:10.676Z" }, - { url = "https://files.pythonhosted.org/packages/e8/35/4a3daeb8b9fab49240d21c04d50732313295e4bd813a465d840236dd0ce1/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591", size = 1721120, upload-time = "2026-01-03T17:31:12.575Z" }, - { url = "https://files.pythonhosted.org/packages/bc/9f/d643bb3c5fb99547323e635e251c609fbbc660d983144cfebec529e09264/aiohttp-3.13.3-cp313-cp313-win32.whl", hash = "sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf", size = 427383, upload-time = "2026-01-03T17:31:14.382Z" }, - { url = "https://files.pythonhosted.org/packages/4e/f1/ab0395f8a79933577cdd996dd2f9aa6014af9535f65dddcf88204682fe62/aiohttp-3.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e", size = 453899, upload-time = "2026-01-03T17:31:15.958Z" }, - { url = "https://files.pythonhosted.org/packages/99/36/5b6514a9f5d66f4e2597e40dea2e3db271e023eb7a5d22defe96ba560996/aiohttp-3.13.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808", size = 737238, upload-time = "2026-01-03T17:31:17.909Z" }, - { url = "https://files.pythonhosted.org/packages/f7/49/459327f0d5bcd8c6c9ca69e60fdeebc3622861e696490d8674a6d0cb90a6/aiohttp-3.13.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415", size = 492292, upload-time = "2026-01-03T17:31:19.919Z" }, - { url = "https://files.pythonhosted.org/packages/e8/0b/b97660c5fd05d3495b4eb27f2d0ef18dc1dc4eff7511a9bf371397ff0264/aiohttp-3.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f", size = 493021, upload-time = "2026-01-03T17:31:21.636Z" }, - { url = "https://files.pythonhosted.org/packages/54/d4/438efabdf74e30aeceb890c3290bbaa449780583b1270b00661126b8aae4/aiohttp-3.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6", size = 1717263, upload-time = "2026-01-03T17:31:23.296Z" }, - { url = "https://files.pythonhosted.org/packages/71/f2/7bddc7fd612367d1459c5bcf598a9e8f7092d6580d98de0e057eb42697ad/aiohttp-3.13.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687", size = 1669107, upload-time = "2026-01-03T17:31:25.334Z" }, - { url = "https://files.pythonhosted.org/packages/00/5a/1aeaecca40e22560f97610a329e0e5efef5e0b5afdf9f857f0d93839ab2e/aiohttp-3.13.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26", size = 1760196, upload-time = "2026-01-03T17:31:27.394Z" }, - { url = "https://files.pythonhosted.org/packages/f8/f8/0ff6992bea7bd560fc510ea1c815f87eedd745fe035589c71ce05612a19a/aiohttp-3.13.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a", size = 1843591, upload-time = "2026-01-03T17:31:29.238Z" }, - { url = "https://files.pythonhosted.org/packages/e3/d1/e30e537a15f53485b61f5be525f2157da719819e8377298502aebac45536/aiohttp-3.13.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1", size = 1720277, upload-time = "2026-01-03T17:31:31.053Z" }, - { url = "https://files.pythonhosted.org/packages/84/45/23f4c451d8192f553d38d838831ebbc156907ea6e05557f39563101b7717/aiohttp-3.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25", size = 1548575, upload-time = "2026-01-03T17:31:32.87Z" }, - { url = "https://files.pythonhosted.org/packages/6a/ed/0a42b127a43712eda7807e7892c083eadfaf8429ca8fb619662a530a3aab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603", size = 1679455, upload-time = "2026-01-03T17:31:34.76Z" }, - { url = "https://files.pythonhosted.org/packages/2e/b5/c05f0c2b4b4fe2c9d55e73b6d3ed4fd6c9dc2684b1d81cbdf77e7fad9adb/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a", size = 1687417, upload-time = "2026-01-03T17:31:36.699Z" }, - { url = "https://files.pythonhosted.org/packages/c9/6b/915bc5dad66aef602b9e459b5a973529304d4e89ca86999d9d75d80cbd0b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926", size = 1729968, upload-time = "2026-01-03T17:31:38.622Z" }, - { url = "https://files.pythonhosted.org/packages/11/3b/e84581290a9520024a08640b63d07673057aec5ca548177a82026187ba73/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba", size = 1545690, upload-time = "2026-01-03T17:31:40.57Z" }, - { url = "https://files.pythonhosted.org/packages/f5/04/0c3655a566c43fd647c81b895dfe361b9f9ad6d58c19309d45cff52d6c3b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c", size = 1746390, upload-time = "2026-01-03T17:31:42.857Z" }, - { url = "https://files.pythonhosted.org/packages/1f/53/71165b26978f719c3419381514c9690bd5980e764a09440a10bb816ea4ab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43", size = 1702188, upload-time = "2026-01-03T17:31:44.984Z" }, - { url = "https://files.pythonhosted.org/packages/29/a7/cbe6c9e8e136314fa1980da388a59d2f35f35395948a08b6747baebb6aa6/aiohttp-3.13.3-cp314-cp314-win32.whl", hash = "sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1", size = 433126, upload-time = "2026-01-03T17:31:47.463Z" }, - { url = "https://files.pythonhosted.org/packages/de/56/982704adea7d3b16614fc5936014e9af85c0e34b58f9046655817f04306e/aiohttp-3.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984", size = 459128, upload-time = "2026-01-03T17:31:49.2Z" }, - { url = "https://files.pythonhosted.org/packages/6c/2a/3c79b638a9c3d4658d345339d22070241ea341ed4e07b5ac60fb0f418003/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c", size = 769512, upload-time = "2026-01-03T17:31:51.134Z" }, - { url = "https://files.pythonhosted.org/packages/29/b9/3e5014d46c0ab0db8707e0ac2711ed28c4da0218c358a4e7c17bae0d8722/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592", size = 506444, upload-time = "2026-01-03T17:31:52.85Z" }, - { url = "https://files.pythonhosted.org/packages/90/03/c1d4ef9a054e151cd7839cdc497f2638f00b93cbe8043983986630d7a80c/aiohttp-3.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f", size = 510798, upload-time = "2026-01-03T17:31:54.91Z" }, - { url = "https://files.pythonhosted.org/packages/ea/76/8c1e5abbfe8e127c893fe7ead569148a4d5a799f7cf958d8c09f3eedf097/aiohttp-3.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29", size = 1868835, upload-time = "2026-01-03T17:31:56.733Z" }, - { url = "https://files.pythonhosted.org/packages/8e/ac/984c5a6f74c363b01ff97adc96a3976d9c98940b8969a1881575b279ac5d/aiohttp-3.13.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc", size = 1720486, upload-time = "2026-01-03T17:31:58.65Z" }, - { url = "https://files.pythonhosted.org/packages/b2/9a/b7039c5f099c4eb632138728828b33428585031a1e658d693d41d07d89d1/aiohttp-3.13.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2", size = 1847951, upload-time = "2026-01-03T17:32:00.989Z" }, - { url = "https://files.pythonhosted.org/packages/3c/02/3bec2b9a1ba3c19ff89a43a19324202b8eb187ca1e928d8bdac9bbdddebd/aiohttp-3.13.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587", size = 1941001, upload-time = "2026-01-03T17:32:03.122Z" }, - { url = "https://files.pythonhosted.org/packages/37/df/d879401cedeef27ac4717f6426c8c36c3091c6e9f08a9178cc87549c537f/aiohttp-3.13.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8", size = 1797246, upload-time = "2026-01-03T17:32:05.255Z" }, - { url = "https://files.pythonhosted.org/packages/8d/15/be122de1f67e6953add23335c8ece6d314ab67c8bebb3f181063010795a7/aiohttp-3.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632", size = 1627131, upload-time = "2026-01-03T17:32:07.607Z" }, - { url = "https://files.pythonhosted.org/packages/12/12/70eedcac9134cfa3219ab7af31ea56bc877395b1ac30d65b1bc4b27d0438/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64", size = 1795196, upload-time = "2026-01-03T17:32:09.59Z" }, - { url = "https://files.pythonhosted.org/packages/32/11/b30e1b1cd1f3054af86ebe60df96989c6a414dd87e27ad16950eee420bea/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0", size = 1782841, upload-time = "2026-01-03T17:32:11.445Z" }, - { url = "https://files.pythonhosted.org/packages/88/0d/d98a9367b38912384a17e287850f5695c528cff0f14f791ce8ee2e4f7796/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56", size = 1795193, upload-time = "2026-01-03T17:32:13.705Z" }, - { url = "https://files.pythonhosted.org/packages/43/a5/a2dfd1f5ff5581632c7f6a30e1744deda03808974f94f6534241ef60c751/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72", size = 1621979, upload-time = "2026-01-03T17:32:15.965Z" }, - { url = "https://files.pythonhosted.org/packages/fa/f0/12973c382ae7c1cccbc4417e129c5bf54c374dfb85af70893646e1f0e749/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df", size = 1822193, upload-time = "2026-01-03T17:32:18.219Z" }, - { url = "https://files.pythonhosted.org/packages/3c/5f/24155e30ba7f8c96918af1350eb0663e2430aad9e001c0489d89cd708ab1/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa", size = 1769801, upload-time = "2026-01-03T17:32:20.25Z" }, - { url = "https://files.pythonhosted.org/packages/eb/f8/7314031ff5c10e6ece114da79b338ec17eeff3a079e53151f7e9f43c4723/aiohttp-3.13.3-cp314-cp314t-win32.whl", hash = "sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767", size = 466523, upload-time = "2026-01-03T17:32:22.215Z" }, - { url = "https://files.pythonhosted.org/packages/b4/63/278a98c715ae467624eafe375542d8ba9b4383a016df8fdefe0ae28382a7/aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344", size = 499694, upload-time = "2026-01-03T17:32:24.546Z" }, - { url = "https://files.pythonhosted.org/packages/bf/79/446655656861d3e7e2c32bfcf160c7aa9e9dc63776a691b124dba65cdd77/aiohttp-3.13.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e", size = 741433, upload-time = "2026-01-03T17:32:26.453Z" }, - { url = "https://files.pythonhosted.org/packages/cb/49/773c4b310b5140d2fb5e79bb0bf40b7b41dad80a288ca1a8759f5f72bda9/aiohttp-3.13.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7", size = 497332, upload-time = "2026-01-03T17:32:28.37Z" }, - { url = "https://files.pythonhosted.org/packages/bc/31/1dcbc4b83a4e6f76a0ad883f07f21ffbfe29750c89db97381701508c9f45/aiohttp-3.13.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02", size = 492365, upload-time = "2026-01-03T17:32:30.234Z" }, - { url = "https://files.pythonhosted.org/packages/5a/b5/b50657496c8754482cd7964e50aaf3aa84b3db61ed45daec4c1aec5b94b4/aiohttp-3.13.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43", size = 1660440, upload-time = "2026-01-03T17:32:32.586Z" }, - { url = "https://files.pythonhosted.org/packages/2a/73/9b69e5139d89d75127569298931444ad78ea86a5befd5599780b1e9a6880/aiohttp-3.13.3-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6", size = 1632740, upload-time = "2026-01-03T17:32:34.793Z" }, - { url = "https://files.pythonhosted.org/packages/ef/fe/3ea9b5af694b4e3aec0d0613a806132ca744747146fca68e96bf056f61a7/aiohttp-3.13.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce", size = 1719782, upload-time = "2026-01-03T17:32:37.737Z" }, - { url = "https://files.pythonhosted.org/packages/fb/c2/46b3b06e60851cbb71efb0f79a3267279cbef7b12c58e68a1e897f269cca/aiohttp-3.13.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80", size = 1813527, upload-time = "2026-01-03T17:32:39.973Z" }, - { url = "https://files.pythonhosted.org/packages/36/23/71ceb78c769ed65fe4c697692de232b63dab399210678d2b00961ccb0619/aiohttp-3.13.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a", size = 1661268, upload-time = "2026-01-03T17:32:42.082Z" }, - { url = "https://files.pythonhosted.org/packages/c4/8d/86e929523d955e85ebab7c0e2b9e0cb63604cfc27dc3280e10d0063cf682/aiohttp-3.13.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6", size = 1552742, upload-time = "2026-01-03T17:32:44.622Z" }, - { url = "https://files.pythonhosted.org/packages/3a/ea/3f5987cba1bab6bd151f0d97aa60f0ce04d3c83316692a6bb6ba2fb69f92/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558", size = 1632918, upload-time = "2026-01-03T17:32:46.749Z" }, - { url = "https://files.pythonhosted.org/packages/be/2c/7e1e85121f2e31ee938cb83a8f32dfafd4908530c10fabd6d46761c12ac7/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7", size = 1644446, upload-time = "2026-01-03T17:32:49.063Z" }, - { url = "https://files.pythonhosted.org/packages/5d/35/ce6133d423ad0e8ca976a7c848f7146bca3520eea4ccf6b95e2d077c9d20/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877", size = 1689487, upload-time = "2026-01-03T17:32:51.113Z" }, - { url = "https://files.pythonhosted.org/packages/50/f7/ff7a27c15603d460fd1366b3c22054f7ae4fa9310aca40b43bde35867fcd/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3", size = 1540715, upload-time = "2026-01-03T17:32:53.38Z" }, - { url = "https://files.pythonhosted.org/packages/17/02/053f11346e5b962e6d8a1c4f8c70c29d5970a1b4b8e7894c68e12c27a57f/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704", size = 1711835, upload-time = "2026-01-03T17:32:56.088Z" }, - { url = "https://files.pythonhosted.org/packages/fb/71/9b9761ddf276fd6708d13720197cbac19b8d67ecfa9116777924056cfcaa/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f", size = 1649593, upload-time = "2026-01-03T17:32:58.181Z" }, - { url = "https://files.pythonhosted.org/packages/ae/72/5d817e9ea218acae12a5e3b9ad1178cf0c12fc3570c0b47eea2daf95f9ea/aiohttp-3.13.3-cp39-cp39-win32.whl", hash = "sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1", size = 434831, upload-time = "2026-01-03T17:33:00.577Z" }, - { url = "https://files.pythonhosted.org/packages/39/cb/22659d9bf3149b7a2927bc2769cc9c8f8f5a80eba098398e03c199a43a85/aiohttp-3.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538", size = 457697, upload-time = "2026-01-03T17:33:03.167Z" }, + { url = "https://files.pythonhosted.org/packages/6d/67/58ded4b3f2e10f94972d8928050c85330e249a31dd45a0e5f3c0e9c3fa05/aiohttp-3.14.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8f6bb621e5863cfe8fe5ff5468002d200ec31f30f1280b259dc505b02595099e", size = 766140, upload-time = "2026-06-07T21:05:37.471Z" }, + { url = "https://files.pythonhosted.org/packages/18/68/4ae5b4e08943f316594bb68da89957d3baf5760588fa09509594bd777e4b/aiohttp-3.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4f7215cb3933784f79ed20e5f050e15984f390424339b22375d5a53c933a0491", size = 519430, upload-time = "2026-06-07T21:05:40.751Z" }, + { url = "https://files.pythonhosted.org/packages/cb/c1/316c8f3549dbe5245f92bfd523ec6f32dd4d98cafe21df3f6a19b1184c75/aiohttp-3.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d9d4e294455b23a68c9b8f042d0e8e377a265bcb15332753695f6e5b6819e0ce", size = 514406, upload-time = "2026-06-07T21:05:42.111Z" }, + { url = "https://files.pythonhosted.org/packages/5a/ee/fb0ac28684e8d753b83c8a4eebc19a5846912aa0a4daaabb6a9936363840/aiohttp-3.14.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b238af795833d5731d049d82bc84b768ae6f8f97f0495963b3ed9935c5901cc3", size = 1703649, upload-time = "2026-06-07T21:05:43.427Z" }, + { url = "https://files.pythonhosted.org/packages/3b/57/aa2beab673331f111885db8a7b69dfe3ab0e53e446a0ace18ca694b4dc58/aiohttp-3.14.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e4e5e0ae56914ecdbf446493addefc0159053dd53962cef37d7839f37f73d505", size = 1675126, upload-time = "2026-06-07T21:05:44.897Z" }, + { url = "https://files.pythonhosted.org/packages/47/ea/dad128abe365e79be03b16ed464198ac73e0d257e8260c6f7d6f31cbef26/aiohttp-3.14.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:092e4ce3619a7c6dee52a6bdabda973d9b34b66781f840ce93c7e0cec30cf521", size = 1771558, upload-time = "2026-06-07T21:05:46.405Z" }, + { url = "https://files.pythonhosted.org/packages/63/f3/b5b4e10327cb85d34d24232c6b71b64602f190b3ccb238a043ac6b187dac/aiohttp-3.14.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb33777ea21e8b7ecde0e6fc84f598be0a1192eab1a63bc746d75aa75d38e7bd", size = 1856631, upload-time = "2026-06-07T21:05:47.844Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9d/93294c3045775c708ac8310eb3d3622a11d2951345ad590d532d62a1faa4/aiohttp-3.14.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23119f8fd4f5d16902ed459b63b100bcd269628075162bddac56cc7b5273b3fb", size = 1714139, upload-time = "2026-06-07T21:05:49.982Z" }, + { url = "https://files.pythonhosted.org/packages/29/c4/93067c85a0373492ce8e577435203c5947c454af074ac48ed4f3a1b9dd4a/aiohttp-3.14.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:57fc6745a4b7d0f5a9eb4f40a69718be6c0bc1b8368cc9fe89e90118719f4f42", size = 1588321, upload-time = "2026-06-07T21:05:51.431Z" }, + { url = "https://files.pythonhosted.org/packages/c4/39/9ff91aaf02af8b7b8222a987466da539f154c3e01732c22b5f5a20a8ee66/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6fd35beba67c4183b09375c5fff9accb47524191a244a99f95fd4472f5402c2b", size = 1670375, upload-time = "2026-06-07T21:05:53.109Z" }, + { url = "https://files.pythonhosted.org/packages/aa/e4/77452a3676b8d99ac1375f77691d6bf65ea6e9f4b201b82ef77c916dc767/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:672b9d65f42eb877f5c3f234a4547e4e1a226ca8c2eed879bb34670a0ce51192", size = 1690933, upload-time = "2026-06-07T21:05:54.902Z" }, + { url = "https://files.pythonhosted.org/packages/7d/84/b0059a7c7fc05ea23f3bc1596ba91c12f79588b9450564a24cac37536d0a/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:24ba13339fed9251d9b1a1bec8c7ab84c0d1675d79d33501e11f94f8b9a84e05", size = 1740798, upload-time = "2026-06-07T21:05:56.458Z" }, + { url = "https://files.pythonhosted.org/packages/8f/3a/e2a513ecbfc362591caa51a7f7e011b3bfc8938b388ae44cd95560d36999/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:94da27378da0610e341c4d30de29a191672683cc82b8f9556e8f7c7212a020fe", size = 1576412, upload-time = "2026-06-07T21:05:57.953Z" }, + { url = "https://files.pythonhosted.org/packages/a1/10/08f1654f538f93d36dcac66310a06eefce4641cdafca83f9f0a5317be254/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:52cdac9432d8b4a719f35094a818d95adcae0f0b4fe9b9b921909e0c87de9e7d", size = 1750199, upload-time = "2026-06-07T21:05:59.488Z" }, + { url = "https://files.pythonhosted.org/packages/99/e4/d91b70c57d8b8e9611e4a2e52238ca3698d3dc1c2efe25b7a9bf594ac584/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:672ac254412a24d0d0cf00a9e6c238877e4be5e5fa2d188832c1244f45f31966", size = 1699356, upload-time = "2026-06-07T21:06:01.131Z" }, + { url = "https://files.pythonhosted.org/packages/3d/f1/15340176f35ff61b95dbe34020bcf43f9e624a2d7bbac934715ff97d2033/aiohttp-3.14.1-cp310-cp310-win32.whl", hash = "sha256:2fe3607e71acc6ebb0ec8e492a247bf7a291226192dc0084236dfc12478916f6", size = 458939, upload-time = "2026-06-07T21:06:02.86Z" }, + { url = "https://files.pythonhosted.org/packages/c3/c2/a2f1ec5b37f903109e43ae2862268cfe4a67a60c1b2cf43169fcdff5995f/aiohttp-3.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:30099eda75a53c32efb0920e9c33c195314d2cc1c680fbfd30894932ac5f27df", size = 482583, upload-time = "2026-06-07T21:06:04.666Z" }, + { url = "https://files.pythonhosted.org/packages/d0/7a/7b56f6732ef79530afaa72aa335d41b67c8d79b946995f0b11ad72985435/aiohttp-3.14.1-cp310-cp310-win_arm64.whl", hash = "sha256:5a837f49d901f9e368651b676912bff1104ed8c1a83b280bcd7b29adccef5c9c", size = 453470, upload-time = "2026-06-07T21:06:06.322Z" }, + { url = "https://files.pythonhosted.org/packages/26/dd/bf526e6f0a1120dd6f2df2e97bacfe4d358f13d17a0ff5847301a1375a51/aiohttp-3.14.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:aa00140699487bd435fde4342d85c94cb256b7cd3a5b9c3396c67f19922afda2", size = 765225, upload-time = "2026-06-07T21:06:07.957Z" }, + { url = "https://files.pythonhosted.org/packages/8f/e1/a2872aa55495a70f61310d411541c6ee23812d9a884e000c716e1bc3edbf/aiohttp-3.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1c1af67559445498b502030c35c59db59966f47041ca9de5b4e707f86bd10b5f", size = 518743, upload-time = "2026-06-07T21:06:09.749Z" }, + { url = "https://files.pythonhosted.org/packages/5b/e7/c60c7b209e509cc787de3cea0550a518538cfc08003e1c1e14c1c63fff71/aiohttp-3.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d44ec478e713ee7f29b439f7eb8dc2b9d4079e11ae114d2c2ac3d5daf30516c8", size = 514139, upload-time = "2026-06-07T21:06:11.26Z" }, + { url = "https://files.pythonhosted.org/packages/5b/8d/614ace2f579702c9840ab1e1447fd8509e35b0b904f7196418fa2f57b25d/aiohttp-3.14.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d3b1a184a9a8f548a6b73f1e26b96b052193e4b3175ed7342aaf1151a1f00a04", size = 1784088, upload-time = "2026-06-07T21:06:12.887Z" }, + { url = "https://files.pythonhosted.org/packages/49/e0/726e90f99542bf292f81a96a12cc4847deb86f3ccf62c6f4014a201f4d33/aiohttp-3.14.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5f2504bc0322437c9a1ff6d3333ca56c7477b727c995f036b976ae17b98372c8", size = 1737835, upload-time = "2026-06-07T21:06:14.564Z" }, + { url = "https://files.pythonhosted.org/packages/0b/4b/d176d5c4db9d33dacf0543102ea59503bc1d528af4cfd0b719949ca49389/aiohttp-3.14.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73f05ea02013e02512c3bf42714f1208c57168c779cc6fe23516e4543089d0a6", size = 1842801, upload-time = "2026-06-07T21:06:16.228Z" }, + { url = "https://files.pythonhosted.org/packages/dc/d6/5a99b563690ea0cbed912ae94a2ce33993a5709a651a3a4fe761e7dd973a/aiohttp-3.14.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:797457503c2d426bee06eef808d07b31ede30b65e054444e7de64cad0061b7af", size = 1929992, upload-time = "2026-06-07T21:06:17.947Z" }, + { url = "https://files.pythonhosted.org/packages/76/7f/a987b14a3859094b3cea3f4825219c3e5536242564af6e3f9c2f6c994eb2/aiohttp-3.14.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b821a1f7dedf7e37450654e620038ac3b2e81e8fa6ea269337e97101978ec730", size = 1786989, upload-time = "2026-06-07T21:06:19.677Z" }, + { url = "https://files.pythonhosted.org/packages/f1/1a/420e5c85a3e73349372ed22ce0b6af86bfa6ce16a4b20a64a2e94608c781/aiohttp-3.14.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4cd96b5ba05d67ed0cf00b5b405c8cd99586d8e3481e8ee0a831057591af7621", size = 1640129, upload-time = "2026-06-07T21:06:22.558Z" }, + { url = "https://files.pythonhosted.org/packages/a7/80/18a592ed3be0a402cc03670bd72ee1f8563ddbe1d8d5542dbf868f274136/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d459b98a932296c6f0e94f87511a0b1b90a8a02c30a50e60a297619cd5a58ee", size = 1756576, upload-time = "2026-06-07T21:06:24.8Z" }, + { url = "https://files.pythonhosted.org/packages/ec/0b/8b3d5713373858ff71a617daf6e3b0e81ad63e79d09a3cf2f6b6b983939c/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:764457a7be60825fb770a644852ff717bcbb5042f189f2bd16df61a81b3f6573", size = 1754668, upload-time = "2026-06-07T21:06:26.528Z" }, + { url = "https://files.pythonhosted.org/packages/9f/49/fd564575cf225821d7ba5a117cb8bc27213d8a7e1811162afb43ae077039/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f7a16ef45b081454ef844502d87a848876c490c4cb5c650c230f6ec79ed2c1e7", size = 1817019, upload-time = "2026-06-07T21:06:28.297Z" }, + { url = "https://files.pythonhosted.org/packages/ed/1b/e850c9ae6fc91356552ae668bb6c51e93fa29c8aef13398a10b56678557f/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2fbc3ed048b3475b9f0cbcb9978e9d2d3511acd91ead203af26ed9f0056004cf", size = 1631638, upload-time = "2026-06-07T21:06:30.242Z" }, + { url = "https://files.pythonhosted.org/packages/eb/94/3c337ba72451a89806ace6f75bddc92bafc5b8d53d90115a512858024b63/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bedb0cd073cc2dc035e30aeb99444389d3cd2113afe4ef9fcd23d439f5bade85", size = 1835660, upload-time = "2026-06-07T21:06:31.943Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9c/9c18cf367a0498212d9ba7daf990b504a5e8ae064cda4b504e2647c89c03/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b6feea921016eb3d4e04d65fc4e9ca402d1a3801f562aef94989f54694917af3", size = 1775698, upload-time = "2026-06-07T21:06:33.72Z" }, + { url = "https://files.pythonhosted.org/packages/b5/63/a251a9d2a6cb45065b2ddc0bde2b3dd10108740a9a42f632c66405a761a2/aiohttp-3.14.1-cp311-cp311-win32.whl", hash = "sha256:313701e488100074ce99850404ee36e741abf6330179fec908a1944ecf570126", size = 458386, upload-time = "2026-06-07T21:06:35.279Z" }, + { url = "https://files.pythonhosted.org/packages/17/ca/69274c51dcd6e8947d77b2806cf47a4a15f2c846e2cbeb1882547d3da283/aiohttp-3.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:03ab4530fdcb3a543a122ba4b65ac9919da9fe9f78a03d328a6e38ff962f7aa5", size = 483406, upload-time = "2026-06-07T21:06:36.824Z" }, + { url = "https://files.pythonhosted.org/packages/2c/8a/c25904f77690c3688ec140f87591ef11a0cfe36bf3d5c0f1f38056fb62b3/aiohttp-3.14.1-cp311-cp311-win_arm64.whl", hash = "sha256:486f7d16ed54c39c2cbd7ca71fd8ba2b8bb7860df65bd7b6ed640bab96a38a8b", size = 452987, upload-time = "2026-06-07T21:06:38.371Z" }, + { url = "https://files.pythonhosted.org/packages/1d/21/151624b51cd92553d95424daf4bf19f19ce9be9002d19253e7e7ce67197b/aiohttp-3.14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d35143e27778b4bb0fb189562d7f275bff79c62ab8e98459717c0ea617ff2480", size = 757402, upload-time = "2026-06-07T21:06:40.311Z" }, + { url = "https://files.pythonhosted.org/packages/c2/82/280619e0bd7bf2454987e19282616e84762255dd9c8468f62382e8c191f1/aiohttp-3.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bcfb80a2cc36fba2534e5e5b5264dc7ae6fcd9bf15256da3e53d2f499e6fa29d", size = 512310, upload-time = "2026-06-07T21:06:42.207Z" }, + { url = "https://files.pythonhosted.org/packages/55/b2/2aac325583aaa1353045f96dffa586d8a34e8322e14a7ba49cffeb103ab4/aiohttp-3.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27fd7c91e51729b4f7e1577865fa6d34c9adccbc39aabe9000285b48af9f0ec2", size = 512448, upload-time = "2026-06-07T21:06:43.813Z" }, + { url = "https://files.pythonhosted.org/packages/8a/72/a60607cb849faa8af8a356c9329ea2eb6f395d49e82cc82ccba1fd8deb8f/aiohttp-3.14.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:64c567bf9eaf664280116a8688f63016e6b32db2505908e2bdaca1b6438142f2", size = 1766854, upload-time = "2026-06-07T21:06:45.391Z" }, + { url = "https://files.pythonhosted.org/packages/b5/d3/d9fe1c9ec7557ab4d0d82bebaa728c6418f0b93295ec2f4ab015f7710cc7/aiohttp-3.14.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f5e6ff2bdbb8f4cd3fbe41f99e25bbcd58e3bf9f13d3dd31a11e7917251cc77a", size = 1740884, upload-time = "2026-06-07T21:06:47.413Z" }, + { url = "https://files.pythonhosted.org/packages/c1/dc/f2cecfaf9337ba3e63f181500814ff502aa3d00d9c7ec93a9d23d10a27b2/aiohttp-3.14.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2f73e01dc37122325caf079982621262f96d74823c179038a82fddfc50359264", size = 1810034, upload-time = "2026-06-07T21:06:50.165Z" }, + { url = "https://files.pythonhosted.org/packages/66/d7/2ff65c5e65c0d7476daf7e15c032e0805e36811185b9623e3238ad6c763e/aiohttp-3.14.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb2c0c80d431c0d03f2c7dbf125150fedd4f0de17366a7ca33f7ccb822391842", size = 1904054, upload-time = "2026-06-07T21:06:52.035Z" }, + { url = "https://files.pythonhosted.org/packages/20/9c/d445818389df371f56d141d881153ba23183c4735a03f7356ffb43f7757d/aiohttp-3.14.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e6fc1a85fa7194a1a7d19f44e8609180f4a8eb5fa4c7ed8b4355f080fad235c", size = 1790278, upload-time = "2026-06-07T21:06:54.049Z" }, + { url = "https://files.pythonhosted.org/packages/4d/aa/bf04cb4d865fc6101c2229a294ad744973b72e513fdc5a6b791e6983d72a/aiohttp-3.14.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:686b6c0d3911ec387b444ddf5dc62fb7f7c0a7d5186a7861626496a5ab4aff95", size = 1591795, upload-time = "2026-06-07T21:06:55.911Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b4/4dac0038960427ba832f6609dfb4ea5437d7fd80c72001b9e48f834f428b/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c6fa4dc7ad6f8109c70bb1499e589f76b0b792baf39f9b017eb92c8a81d0a199", size = 1728397, upload-time = "2026-06-07T21:06:57.777Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f9/7cd4e8ad7aa3b75f17d56bb5498dd604a93d4e6eece822ba0568c413fff0/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:87a5eea1b2a5e21e1ebdbb33ad4165359189327e63fc4e4894693e7f821ac817", size = 1766504, upload-time = "2026-06-07T21:07:00.009Z" }, + { url = "https://files.pythonhosted.org/packages/f9/df/fc01d9fcad0f73fed3f3d361f1f94f975947b50dff82919f6dc2bf4316cc/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1c1421eb01d4fd608d88cc8290211d177a58532b55ad94076fb349c5bf467f0a", size = 1777806, upload-time = "2026-06-07T21:07:02.064Z" }, + { url = "https://files.pythonhosted.org/packages/41/09/47e2d090bddcc8fb4ccb4c314aadc32d7c5d9bb55f50f6ad1c92fc15d501/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:34b257ec41345c1e8f2df68fa908a7952f5de932723871eb633ecbbff396c9a4", size = 1580707, upload-time = "2026-06-07T21:07:03.942Z" }, + { url = "https://files.pythonhosted.org/packages/3d/36/f1a4ce904ae0b6930cfe9afc96d0896f7ec1a620c400405d63783bb95a9c/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:de538791a80e5d862addbc183f70f0158ac9b9bb872bb147f1fd2a683691e087", size = 1798121, upload-time = "2026-06-07T21:07:05.987Z" }, + { url = "https://files.pythonhosted.org/packages/70/0a/e0075ce9ca0279ee1d4f0c0b85f54fea02ebc83c3007651a72bece658fec/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f71173be42d3241d428f760122febb748de0623f44308a6f120d0dd9ec572e3", size = 1767580, upload-time = "2026-06-07T21:07:07.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/a0c0a8f327a9c52095cdd8e312391b00d3ed64ab6c72bb5c33d8ec251cf7/aiohttp-3.14.1-cp312-cp312-win32.whl", hash = "sha256:ec8dc383ee57ea3e883477dcca3f11b65d58199f1080acaf4cd6ad9a99698be4", size = 452771, upload-time = "2026-06-07T21:07:09.669Z" }, + { url = "https://files.pythonhosted.org/packages/df/d9/ea367c75f16ac9c6cdc8febb25e8318fa21a2b1bc8d6514d4b2d890bface/aiohttp-3.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2aa92c87868cd13674989f9ee83e5f9f7ea4237589b728048e1f0c8f6caa3271", size = 479873, upload-time = "2026-06-07T21:07:11.538Z" }, + { url = "https://files.pythonhosted.org/packages/03/64/8d96784a7851156db8a4c6c3f6f91042fdf39fb15a4cc38c8b3c14833c45/aiohttp-3.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:2c840c90759922cb5e6dda94596e079a30fb5a5ba548e7e0dc00574703940847", size = 448073, upload-time = "2026-06-07T21:07:13.637Z" }, + { url = "https://files.pythonhosted.org/packages/bc/97/bd137012dd97e1649162b099135a80e1fd59aaa807b2430fc448d1029aff/aiohttp-3.14.1-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:b3a03285a7f9c7b016324574a6d92a1c895da6b978cb8f1deee3ac72bc6da178", size = 506882, upload-time = "2026-06-07T21:07:15.501Z" }, + { url = "https://files.pythonhosted.org/packages/ef/79/e5cc690e9d922a66887ceeaca53a8ffd5a7b0be3816142b7abc433742d89/aiohttp-3.14.1-cp313-cp313-android_21_x86_64.whl", hash = "sha256:2a73f487ab8ef5abbb24b7aa9b73e98eaba9e9e031804ff2416f02eca315ccaf", size = 515270, upload-time = "2026-06-07T21:07:17.53Z" }, + { url = "https://files.pythonhosted.org/packages/fe/22/a73ccbf9dbd6e26dda0b24d5fd5db7da92ee3383a79f47677ffb834c5c5b/aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:915fbb7b41b115192259f8c9ae58f3ddc444d2b5579917270211858e606a4afd", size = 485841, upload-time = "2026-06-07T21:07:19.555Z" }, + { url = "https://files.pythonhosted.org/packages/3b/b9/57ed8eaf596321c2ad747bd480fb1700dbd7177c60dfc9e4c187f629662e/aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:7fb4bdf95b0561a79f259f9d28fbc109728c5ee7f27aff6391f0ca703a329abe", size = 492088, upload-time = "2026-06-07T21:07:21.581Z" }, + { url = "https://files.pythonhosted.org/packages/78/c0/5ebe5270a7c140d7c6f79dcb018640225f14d406c149e4eec04a7d82fe71/aiohttp-3.14.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1b9748363260121d2927704f5d4fc498150669ca3ae93625986ee89c8f80dcd4", size = 501564, upload-time = "2026-06-07T21:07:23.388Z" }, + { url = "https://files.pythonhosted.org/packages/75/7f/8cdaa24fc7983865e0915153b96a9ac5bcdd3548d64c5a27d17cecccad2d/aiohttp-3.14.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:86a6dab78b0e43e2897a3bbe15745aa60dc5423ca437b7b0b164c069bf91b876", size = 751998, upload-time = "2026-06-07T21:07:25.046Z" }, + { url = "https://files.pythonhosted.org/packages/b2/f4/c4227aacfacc5cb0cc2d119b65301d177912a6842cd64e120c47af76064f/aiohttp-3.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4dfd6e47d3c44c2279907607f73a4240b88c69eb8b90da7e2441a8045dfd21da", size = 510918, upload-time = "2026-06-07T21:07:27.28Z" }, + { url = "https://files.pythonhosted.org/packages/ab/01/a2d5f96cd4e74424864d30bc0a7e44d0a12dacdcfa91b5b2d1bd3dca6bf3/aiohttp-3.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:317acd9f8602858dc7d59679812c376c7f0b97bcbbf16e0d6237f54141d8a8a6", size = 508657, upload-time = "2026-06-07T21:07:29.252Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ed/3c0fb5c500fdd8e7ebc10d1889c04384fffa1a9163eac1356088ca9da1b1/aiohttp-3.14.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd869c427324e5cb15195793de951295710db28be7d818247f3097b4ab5d4b96", size = 1757907, upload-time = "2026-06-07T21:07:31.03Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ab/d4c924d9bd5be3050c226612413ce68cb54c70d2c31b661bfc8d9a5b6a70/aiohttp-3.14.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:93b032b5ec3255473c143627d21a69ac74ae12f7f33974cb587c564d11b1066f", size = 1737565, upload-time = "2026-06-07T21:07:33.031Z" }, + { url = "https://files.pythonhosted.org/packages/19/2a/37326821ff779084020cdc33224d20b19f42f4183a500ff92022a739eda7/aiohttp-3.14.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f234b4deb12f3ad59127e037bc57c40c21e45b45282df7d3a55a0f409f595296", size = 1799018, upload-time = "2026-06-07T21:07:35.003Z" }, + { url = "https://files.pythonhosted.org/packages/b3/4f/6e947ba73e4ce09070761c05ed3a8ceb7c21f5e46798671d8b2aac0e4626/aiohttp-3.14.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9af6779bfb46abf124068327abcdf9ce95c9ef8287a3e8da76ccf2d0f16c28fa", size = 1894416, upload-time = "2026-06-07T21:07:36.956Z" }, + { url = "https://files.pythonhosted.org/packages/9d/6e/dbf1d0625dc711fb2851f4f3c3055c39ed58bae92082d8c627dbe6013736/aiohttp-3.14.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:faccab372e66bc76d5731525e7f1143c922271725b9d38c9f97edcc66266b451", size = 1783881, upload-time = "2026-06-07T21:07:39.063Z" }, + { url = "https://files.pythonhosted.org/packages/44/c2/5e25098a67268ed369483ae7d1a58bd0a13d03aab860d2a0e4a6eb25b046/aiohttp-3.14.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f380468b09d2a81633ee863b0ec5648d364bd17bb8ecfb8c2f387f7ac1faf42c", size = 1587572, upload-time = "2026-06-07T21:07:41.058Z" }, + { url = "https://files.pythonhosted.org/packages/2a/bd/cf9cee17e140f942a3de73e658a543aa8fbf35a5fc67a9d2538d52d77f0b/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:97e704dcd26271f5bda3fa07c3ce0fb76d6d3f8659f4baa1a24442cc9ba177ca", size = 1722137, upload-time = "2026-06-07T21:07:43.014Z" }, + { url = "https://files.pythonhosted.org/packages/89/6d/5684f8c59045c96f81a18cefbc1fbbd79d25b88f1c622f2a5c5c08fcb632/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:269b76ac5394092b95bc4a098f4fc6c191c083c3bd12775d1e30e663132f6a09", size = 1755953, upload-time = "2026-06-07T21:07:45.933Z" }, + { url = "https://files.pythonhosted.org/packages/a8/40/35caf3170f8359760740a7d9aa0fff2e344bef98e1d1186f5a0f6dec17e6/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c0b3e614340c889d575451696374c9d17affd54cd607ca0babed8f8c37b9397", size = 1766479, upload-time = "2026-06-07T21:07:48.047Z" }, + { url = "https://files.pythonhosted.org/packages/6d/a1/b0c61e7a137f0d81de49a82023a6df73c3c16d6fefb0f8e4a93d21639002/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:5663ee9257cfa1add7253a7da3035a02f31b6600ec48261585e1800a81533080", size = 1580077, upload-time = "2026-06-07T21:07:50.069Z" }, + { url = "https://files.pythonhosted.org/packages/0b/41/194ea4623693009fcefebef7aef63c141754f153e9cd0d39d3b9e36c175c/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:603a2c834142172ffddc054067f5ec0ca65d57a0aa98a71bc81952573208e345", size = 1791688, upload-time = "2026-06-07T21:07:52.106Z" }, + { url = "https://files.pythonhosted.org/packages/ba/45/4de841f005cfe1fd63e2a2fe011262c515e2a62aa6994b15947e7d717ac9/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cb21957bb8aca671c1765e32f58164cf0c50e6bf41c0bbbd16da20732ecaf588", size = 1761094, upload-time = "2026-06-07T21:07:54.113Z" }, + { url = "https://files.pythonhosted.org/packages/e4/ae/dbce10533d3896d544d5053939ed75b7dc31a1b0973d959b1b5ae21028d6/aiohttp-3.14.1-cp313-cp313-win32.whl", hash = "sha256:e509a55f681e6158c20f70f102f9cf61fb20fbc382272bc6d94b7343f2582780", size = 452662, upload-time = "2026-06-07T21:07:56.06Z" }, + { url = "https://files.pythonhosted.org/packages/7b/d9/0bf1a19362c32f06229da5e7ddfcec91f93474d6307f7a2d3135e9c674dc/aiohttp-3.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:1ac8531b638959718e18c2207fbfe297819875da46a740b29dfa29beba64355a", size = 479748, upload-time = "2026-06-07T21:07:58.319Z" }, + { url = "https://files.pythonhosted.org/packages/22/0a/62e7232dc9484fbec112ceb32efb6a624cc7994ec6e2b019286f17c4e8f2/aiohttp-3.14.1-cp313-cp313-win_arm64.whl", hash = "sha256:250d14af67f6b6a1a4a811049b1afa69d61d617fca6bf33149b3ab1a6dbcf7b8", size = 447723, upload-time = "2026-06-07T21:08:00.154Z" }, + { url = "https://files.pythonhosted.org/packages/c4/a1/5fafa04e1ca91ddb47608699d60649c1c6db3cf41c99e78fc4056f9513db/aiohttp-3.14.1-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:7c106c26852ca1c2047c6b80384f17100b4e439af276f21ef3d4e2f450ae7e15", size = 508531, upload-time = "2026-06-07T21:08:02.093Z" }, + { url = "https://files.pythonhosted.org/packages/fa/2e/bfa02f699d87ffc86d5959270b28f1cb410add3ccaced8ed2e0b8a5238fc/aiohttp-3.14.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:20205f7f5ade7aaec9f4b500549bbc071b046453aed72f9c06dcab87896a83e8", size = 514718, upload-time = "2026-06-07T21:08:04.476Z" }, + { url = "https://files.pythonhosted.org/packages/85/a5/9594ad6289eebbc97d167c44213d557807f90e59115caad24de21ad2c3b1/aiohttp-3.14.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:62a759436b29e677181a9e76bab8b8f689a29cb9c535f45f7c48c9c830d3f8c3", size = 487918, upload-time = "2026-06-07T21:08:06.377Z" }, + { url = "https://files.pythonhosted.org/packages/b4/61/16a32c36c3c49edec122a3dc811f2057df2f94d3b14aa107c8017d981618/aiohttp-3.14.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:2964cbf553df4d7a57348da44d961d871895fc1ee4e8c322b2a95612c7b17fba", size = 494014, upload-time = "2026-06-07T21:08:08.263Z" }, + { url = "https://files.pythonhosted.org/packages/9b/89/3ebcf96ed99c05bec9c434aaac6963fd3cbab4a786ae739908a144d9ce44/aiohttp-3.14.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:237651caadc3a59badd39319c54642b5299e9cc98a3a194310e55d5bb9f5e397", size = 502398, upload-time = "2026-06-07T21:08:10.244Z" }, + { url = "https://files.pythonhosted.org/packages/fd/3d/b74870a0c2d40c355928cd5b96c7a11fa821b8a40fc41365e64479b151fb/aiohttp-3.14.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:896e12dfdbbab9d8f7e16d2b28c6769a60126fa92095d1ebf9473d02593a2448", size = 758018, upload-time = "2026-06-07T21:08:12.447Z" }, + { url = "https://files.pythonhosted.org/packages/d3/66/f42f5c984d99e49c6cff5f26f590750f2e2f7ef1fcfb99966ab5be1b632e/aiohttp-3.14.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d03f281ed22579314ba00821ce20115a7c0ac430660b4cc05704a3f818b3e004", size = 512462, upload-time = "2026-06-07T21:08:14.624Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a7/248e1aebe0c7810b0271e021a0f2a5eb6e78a051885b3c9df49f42a5802d/aiohttp-3.14.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:07eabb979d236335fed927e137a928c9adfb7df3b9ec7aa31726f133a62be983", size = 512824, upload-time = "2026-06-07T21:08:16.572Z" }, + { url = "https://files.pythonhosted.org/packages/26/97/2aa0e5ba0727dc3bd5aaebb7ccbc510f7dfb7fb961ec87497cd496635ab1/aiohttp-3.14.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4fe1f1087cbadb280b5e1bb054a4f00d1423c74d6626c5e48400d871d34ecefe", size = 1749898, upload-time = "2026-06-07T21:08:18.635Z" }, + { url = "https://files.pythonhosted.org/packages/00/8d/e97f6c96c891d457c8479d92a514ba194d0412f981d72c70341ee18488ed/aiohttp-3.14.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:367a9314fdc79dab0fac96e216cb41dd73c85bdca85306ce8999118ba7e0f333", size = 1710114, upload-time = "2026-06-07T21:08:20.892Z" }, + { url = "https://files.pythonhosted.org/packages/6f/e6/aa8d7e863048c8fceb5cd6ce74017311cec3ead07847387e12265fb4444e/aiohttp-3.14.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a24f677ebe83749039e7bdf862ff0bbb16818ae4193d4ef96505e269375bcce0", size = 1802541, upload-time = "2026-06-07T21:08:23.044Z" }, + { url = "https://files.pythonhosted.org/packages/83/a8/72193137de57fda4ebfae4563182d082c8856e3b6e9871d0b46f028fb369/aiohttp-3.14.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c83afe0ba876be7e943d2e0ba645809ad441575d2840c895c21ee5de93b9377a", size = 1875776, upload-time = "2026-06-07T21:08:25.288Z" }, + { url = "https://files.pythonhosted.org/packages/a0/18/938441025db6769a3464596b2410af3afde0b21eb2f204c6f766f68af4bd/aiohttp-3.14.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:634e385930fb6d2d479cf3aa66515955863b77a5e3c2b5894ca259a25b308602", size = 1760329, upload-time = "2026-06-07T21:08:27.363Z" }, + { url = "https://files.pythonhosted.org/packages/60/29/bf2496b4065e76e09fe48015aaffe5ce161d8f089b06ac6982070f653076/aiohttp-3.14.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeea07c4397bbc57719c4eed8f9c284874d4f175f9b6d57f7a1546b976d455ca", size = 1587293, upload-time = "2026-06-07T21:08:29.805Z" }, + { url = "https://files.pythonhosted.org/packages/49/a2/2136674d52123b1354bd05dd5753c318db47dc0c927cc70b27bab3755456/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:335c0cc3e3545ce98dcb9cfcb836f40c3411f43fa03dab757597d80c89af8a35", size = 1714756, upload-time = "2026-06-07T21:08:32.094Z" }, + { url = "https://files.pythonhosted.org/packages/a7/b9/e5fd2e6f915503081c0f9b1e8540947037929c70c191da2e4d54b31a21a1/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ae6be797afdef264e8a84864a85b196ca06045586481b3df8a967322fd2fa844", size = 1721052, upload-time = "2026-06-07T21:08:34.167Z" }, + { url = "https://files.pythonhosted.org/packages/63/5a/2833e324a2263e104e31e2e91bc5bbee81bc499afd32203faee048a883f0/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:8560b4d712474335d08907db7973f71912d3a9a8f1dee992ec06b5d2fe359496", size = 1766888, upload-time = "2026-06-07T21:08:36.95Z" }, + { url = "https://files.pythonhosted.org/packages/57/fa/dea6511870913162f3b2e8c42a7614eb203a4540b8c2da43e0bfb0548f3c/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7edd08e0a5deb1e8564a2fcd8f4561014a3f05252334671bbf55ddd47db0e5", size = 1581679, upload-time = "2026-06-07T21:08:39.292Z" }, + { url = "https://files.pythonhosted.org/packages/14/bd/3cf0d55e71784b33534e9710a67d382d900598b4787fbce6cc7317f8c42a/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:b6ff7fcee63287ae57b5df3e4f5957ce032122802509246dec1a5bcc55904c95", size = 1782021, upload-time = "2026-06-07T21:08:41.407Z" }, + { url = "https://files.pythonhosted.org/packages/c1/af/14bb5843eccbe234f4dfb78ab73e549d99727247e62ae5d62cbd22eaf5b0/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6ffbb2f4ec1ceaff7e07d43922954da26b223d188bf30658e561b98e23089444", size = 1742574, upload-time = "2026-06-07T21:08:43.795Z" }, + { url = "https://files.pythonhosted.org/packages/f2/1e/fbeb7af9210a67ac0f9c9bec0f8f4568497924e33137a3d5b48e1cf85f3f/aiohttp-3.14.1-cp314-cp314-win32.whl", hash = "sha256:a9875b46d910cff3ea2f5962f9d266b465459fe634e22556ab9bd6fc1192eea0", size = 457773, upload-time = "2026-06-07T21:08:46.168Z" }, + { url = "https://files.pythonhosted.org/packages/f0/2b/13e8d741a9ec5db7d900c060554cf8352ab85e44e2a4469ebb9d377bda17/aiohttp-3.14.1-cp314-cp314-win_amd64.whl", hash = "sha256:af8b4b81a960eeaf1234971ac3cd0ba5901f3cd42eae42a46b4d089a8b492719", size = 485001, upload-time = "2026-06-07T21:08:48.401Z" }, + { url = "https://files.pythonhosted.org/packages/df/30/491acfa2c4d6c3ff59c49a14fc1b50be3241e25bbb0c84c09e2da4d11395/aiohttp-3.14.1-cp314-cp314-win_arm64.whl", hash = "sha256:cf4491381b1b57425c315a56a439251b1bdac07b2275f19a8c44bc57744532ec", size = 453809, upload-time = "2026-06-07T21:08:50.7Z" }, + { url = "https://files.pythonhosted.org/packages/34/e3/19dbe1a1f4cc6230eb9e314de7fe68053b0992f9302b27d12141a0b5db53/aiohttp-3.14.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:819c054312f1af92947e6a55883d1b66feefab11531a7fc45e0fb9b63880b5c2", size = 793320, upload-time = "2026-06-07T21:08:52.775Z" }, + { url = "https://files.pythonhosted.org/packages/7f/20/1b7182219ba1b108430d6e4dc53d25ae02dcfcf5a045b33af4e8c5167527/aiohttp-3.14.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10ee9c1753a8f706345b22496c79fbddb5be0599e0823f3738b1534058e25340", size = 529077, upload-time = "2026-06-07T21:08:55Z" }, + { url = "https://files.pythonhosted.org/packages/b9/c8/14ce60ec31a2e5f5274bb17d383a6f7a3aabca31ac04eee05585bbadab16/aiohttp-3.14.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1601cc37baf5750ccacae618ec2daf020769581695550e3b654a911f859c563d", size = 532476, upload-time = "2026-06-07T21:08:57.176Z" }, + { url = "https://files.pythonhosted.org/packages/7e/02/9ac85e081e53da2e061b02fa7758fe0a12d17b8ce2d1f5e6c7cb76730328/aiohttp-3.14.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4d6e0ac9da31c9c04c84e1c0182ad8d6df35965a85cae29cd71d089621b3ae94", size = 1922347, upload-time = "2026-06-07T21:08:59.563Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3e/d3ba07a0ab38b5389e10bec4362d21e10a4f667cba2d79ba30837b3a5059/aiohttp-3.14.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9e8f2d660c350b3d0e259c7a7e3d9b7fc8b41210cbcc3d4a7076ff0a5e5c2fdc", size = 1786465, upload-time = "2026-06-07T21:09:01.909Z" }, + { url = "https://files.pythonhosted.org/packages/0b/cb/e2ee978a00cfb2df829704a69528b18154eba5939f45bc1efa8f33aee4c5/aiohttp-3.14.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4691802dda97be727f79d86818acaad7eb8e9252626a1d6b519fedbb92d5e251", size = 1909423, upload-time = "2026-06-07T21:09:04.357Z" }, + { url = "https://files.pythonhosted.org/packages/73/5d/1430334858b1022b58ae50399a918f0bd6fe8fa7fa183598d657ff61e040/aiohttp-3.14.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c389c482a7e9b9dc3ee2701ac46c4125297a3818875b9c305ddb603c04828fd1", size = 2001906, upload-time = "2026-06-07T21:09:06.722Z" }, + { url = "https://files.pythonhosted.org/packages/66/4e/560c7472d3d198a23aa5c8b19a5115bf6a9b77b7d3e4bb363da320430ad2/aiohttp-3.14.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fc0cacab7ba4e56f0f81c82a98c09bed2f39c940107b03a34b168bdf7597edd3", size = 1877095, upload-time = "2026-06-07T21:09:09.011Z" }, + { url = "https://files.pythonhosted.org/packages/0d/f1/4745806578d447db4a784a8591e2dae3afdfc2bcb96f8f81271b13df6543/aiohttp-3.14.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:979ed4717f59b8bb12e3963378fa285d93d367e15bcd66c721311826d3c44a6c", size = 1676222, upload-time = "2026-06-07T21:09:11.461Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c9/48255813cca749a229ef0ab476004ec623728ad79a9c0840616f6c076325/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:38e1e7daaea81df51c952e18483f323d878499a1e2bfe564790e0f9701d6f203", size = 1842922, upload-time = "2026-06-07T21:09:14.118Z" }, + { url = "https://files.pythonhosted.org/packages/3d/c0/bbd054e2bee909f529523a5af3891052606af5143c09f5f183ec3b234676/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:4132e72c608fe9fecb8f409113567605915b83e9bdd3ea56538d2f9cd35002f1", size = 1825035, upload-time = "2026-06-07T21:09:16.447Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ae/90395d4376deceb74e09ec26b6adf7d2015a6f8802d6d84446af860fef04/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:eefd9cc9b6d4a2db5f00a26bc3e4f9acf71926a6ec557cd56c9c6f27c290b665", size = 1849512, upload-time = "2026-06-07T21:09:18.742Z" }, + { url = "https://files.pythonhosted.org/packages/93/bd/fb25f3049957553d4ce0ba6ae480aa2f592a6985497fca590837d16c1be0/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b165790117eea512d7f3fb22f1f6dad3d55a7189571993eb015591c1401276d1", size = 1668571, upload-time = "2026-06-07T21:09:21.458Z" }, + { url = "https://files.pythonhosted.org/packages/3f/22/7f73303d64dd567ff3addca90b556690ed1233a47b8f55d242fb90af3681/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:ed09c7eb1c391271c2ed0314a51903e72a3acb653d5ccfc264cdf3ef11f8269d", size = 1881159, upload-time = "2026-06-07T21:09:23.813Z" }, + { url = "https://files.pythonhosted.org/packages/44/be/0474c5a8b5640e1e4aa1923430a91f4151be82e511373fe764189b89aef5/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:99abd37084b82f5830c635fddd0b4993b9742a66eb746dacf433c8590e8f9e3c", size = 1841409, upload-time = "2026-06-07T21:09:26.207Z" }, + { url = "https://files.pythonhosted.org/packages/7b/3c/bb4a7cba26956cb3da4553cc2056cf67be5b5ff6e6d8fa4fbdff73bfb7ae/aiohttp-3.14.1-cp314-cp314t-win32.whl", hash = "sha256:47ddf841cdecc810749921d25606dee45857d12d2ad5ddb7b5bd7eab12e4b365", size = 494166, upload-time = "2026-06-07T21:09:28.505Z" }, + { url = "https://files.pythonhosted.org/packages/8a/84/ec80c2c1f66a952555a9f86df6b33af65108a6febfa0471b69013a12f807/aiohttp-3.14.1-cp314-cp314t-win_amd64.whl", hash = "sha256:5e78b522b7a6e27e0b25d19b247b75039ac4c94f99823e3c9e53ae1603a9f7e9", size = 530255, upload-time = "2026-06-07T21:09:30.843Z" }, + { url = "https://files.pythonhosted.org/packages/2a/71/6e22be134a4061ada85a92951b842f2657f17d926b727f3f94c56ae963d6/aiohttp-3.14.1-cp314-cp314t-win_arm64.whl", hash = "sha256:90d53f1609c29ccc2193945ef732428382a28f78d0456ae4d3daf0d48b74f0f6", size = 469640, upload-time = "2026-06-07T21:09:33.028Z" }, ] [[package]] @@ -460,7 +609,8 @@ name = "httpx-aiohttp" version = "0.1.12" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "aiohttp" }, + { name = "aiohttp", version = "3.13.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "aiohttp", version = "3.14.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "httpx" }, ] sdist = { url = "https://files.pythonhosted.org/packages/63/2c/b894861cecf030fb45675ea24aa55b5722e97c602a163d872fca66c5a6d8/httpx_aiohttp-0.1.12.tar.gz", hash = "sha256:81feec51fd82c0ecfa0e9aaf1b1a6c2591260d5e2bcbeb7eb0277a78e610df2c", size = 275945, upload-time = "2025-12-12T10:12:15.283Z" } @@ -470,11 +620,11 @@ wheels = [ [[package]] name = "idna" -version = "3.11" +version = "3.18" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, + { url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" }, ] [[package]] @@ -779,7 +929,7 @@ wheels = [ [[package]] name = "oz-agent-sdk" -version = "0.4.0" +version = "0.13.0" source = { editable = "." } dependencies = [ { name = "anyio" }, @@ -793,7 +943,8 @@ dependencies = [ [package.optional-dependencies] aiohttp = [ - { name = "aiohttp" }, + { name = "aiohttp", version = "3.13.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "aiohttp", version = "3.14.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "httpx-aiohttp" }, ] @@ -823,7 +974,7 @@ pydantic-v2 = [ [package.metadata] requires-dist = [ - { name = "aiohttp", marker = "extra == 'aiohttp'" }, + { name = "aiohttp", marker = "extra == 'aiohttp'", specifier = ">=3.13.5" }, { name = "anyio", specifier = ">=3.5.0,<5" }, { name = "distro", specifier = ">=1.7.0,<2" }, { name = "httpx", specifier = ">=0.23.0,<1" }, From 24e711e57c81a92280b6a29efb5a7bb403e18ba4 Mon Sep 17 00:00:00 2001 From: Ian Hodge Date: Wed, 17 Jun 2026 15:00:10 -0400 Subject: [PATCH 07/14] Build SDK Stainless-Generated-From: 6fa5d3b68b9104c4abd495d1bc4831a12884e231 --- README.md | 49 +- api.md | 41 +- scripts/utils/ruffen-docs.py | 4 +- src/oz_agent_sdk/__init__.py | 82 +- src/oz_agent_sdk/_base_client.py | 84 +- src/oz_agent_sdk/_client.py | 329 ++++--- src/oz_agent_sdk/_compat.py | 7 +- src/oz_agent_sdk/_constants.py | 2 +- src/oz_agent_sdk/_exceptions.py | 46 +- src/oz_agent_sdk/_models.py | 51 +- src/oz_agent_sdk/_qs.py | 2 +- src/oz_agent_sdk/_resource.py | 11 +- src/oz_agent_sdk/_response.py | 11 +- src/oz_agent_sdk/_streaming.py | 12 +- src/oz_agent_sdk/_types.py | 19 +- src/oz_agent_sdk/_utils/__init__.py | 2 +- src/oz_agent_sdk/_utils/_resources_proxy.py | 1 + src/oz_agent_sdk/_utils/_sync.py | 4 +- src/oz_agent_sdk/_utils/_transform.py | 4 +- src/oz_agent_sdk/_utils/_utils.py | 9 +- src/oz_agent_sdk/_version.py | 2 +- src/oz_agent_sdk/pagination.py | 52 +- src/oz_agent_sdk/resources/__init__.py | 18 +- src/oz_agent_sdk/resources/agent/__init__.py | 78 +- src/oz_agent_sdk/resources/agent/agent.py | 487 +++++----- src/oz_agent_sdk/resources/agent/agent_.py | 521 ++++++----- .../resources/agent/conversations.py | 98 +- src/oz_agent_sdk/resources/agent/runs.py | 546 +++++------ src/oz_agent_sdk/resources/agent/schedules.py | 562 ++++++------ src/oz_agent_sdk/resources/agent/sessions.py | 98 +- src/oz_agent_sdk/types/__init__.py | 26 +- src/oz_agent_sdk/types/agent/__init__.py | 26 +- .../types/agent/agent_create_params.py | 28 +- .../types/agent/agent_response.py | 31 +- .../types/agent/agent_update_params.py | 28 +- src/oz_agent_sdk/types/agent/artifact_item.py | 33 +- .../conversation_check_redirect_response.py | 7 +- .../agent/list_agent_identities_response.py | 6 +- .../types/agent/run_cancel_response.py | 4 +- src/oz_agent_sdk/types/agent/run_item.py | 34 +- .../run_list_handoff_attachments_response.py | 10 +- .../types/agent/run_list_params.py | 19 +- .../types/agent/run_source_type.py | 6 +- src/oz_agent_sdk/types/agent/run_state.py | 6 +- .../types/agent/run_submit_followup_params.py | 5 +- .../types/agent/schedule_create_params.py | 5 +- .../types/agent/schedule_delete_response.py | 3 +- .../types/agent/schedule_list_response.py | 6 +- .../types/agent/schedule_update_params.py | 5 +- .../agent/scheduled_agent_history_item.py | 9 +- .../types/agent/scheduled_agent_item.py | 17 +- .../agent/session_check_redirect_response.py | 7 +- .../types/agent_get_artifact_response.py | 35 +- .../types/agent_list_environments_params.py | 5 +- .../types/agent_list_environments_response.py | 6 +- src/oz_agent_sdk/types/agent_list_params.py | 5 +- src/oz_agent_sdk/types/agent_list_response.py | 6 +- src/oz_agent_sdk/types/agent_run_params.py | 22 +- src/oz_agent_sdk/types/agent_run_response.py | 8 +- src/oz_agent_sdk/types/agent_skill.py | 13 +- .../types/ambient_agent_config.py | 36 +- .../types/ambient_agent_config_param.py | 30 +- src/oz_agent_sdk/types/aws_provider_config.py | 4 +- src/oz_agent_sdk/types/cloud_environment.py | 19 +- .../types/cloud_environment_config.py | 13 +- src/oz_agent_sdk/types/error_code.py | 21 +- src/oz_agent_sdk/types/gcp_provider_config.py | 8 +- src/oz_agent_sdk/types/mcp_server_config.py | 8 +- .../types/mcp_server_config_param.py | 9 +- src/oz_agent_sdk/types/scope.py | 9 +- src/oz_agent_sdk/types/user_profile.py | 8 +- tests/__init__.py | 2 +- tests/api_resources/__init__.py | 2 +- tests/api_resources/agent/__init__.py | 2 +- tests/api_resources/agent/test_agent_.py | 289 +++--- .../api_resources/agent/test_conversations.py | 64 +- tests/api_resources/agent/test_runs.py | 224 +++-- tests/api_resources/agent/test_schedules.py | 408 ++++----- tests/api_resources/agent/test_sessions.py | 64 +- tests/api_resources/test_agent.py | 245 +++-- tests/conftest.py | 37 +- tests/test_client.py | 860 +++++++++++------- tests/test_extract_files.py | 17 +- tests/test_files.py | 2 +- tests/test_models.py | 2 +- tests/test_response.py | 2 +- tests/test_streaming.py | 28 +- tests/test_transform.py | 2 +- tests/test_utils/test_datetime_parse.py | 1 + tests/utils.py | 4 +- 90 files changed, 3406 insertions(+), 2667 deletions(-) diff --git a/README.md b/README.md index 1ce7591..9aba4a6 100644 --- a/README.md +++ b/README.md @@ -114,11 +114,13 @@ client = AsyncOzAPI( api_key=os.environ.get("WARP_API_KEY"), # This is the default and can be omitted ) + async def main() -> None: - response = await client.agent.run( - prompt="Fix the bug in auth.go", - ) - print(response.run_id) + response = await client.agent.run( + prompt="Fix the bug in auth.go", + ) + print(response.run_id) + asyncio.run(main()) ``` @@ -144,15 +146,17 @@ import asyncio from oz_agent_sdk import DefaultAioHttpClient from oz_agent_sdk import AsyncOzAPI + async def main() -> None: - async with AsyncOzAPI( - api_key=os.environ.get("WARP_API_KEY"), # This is the default and can be omitted - http_client=DefaultAioHttpClient(), -) as client: - response = await client.agent.run( - prompt="Fix the bug in auth.go", - ) - print(response.run_id) + async with AsyncOzAPI( + api_key=os.environ.get("WARP_API_KEY"), # This is the default and can be omitted + http_client=DefaultAioHttpClient(), + ) as client: + response = await client.agent.run( + prompt="Fix the bug in auth.go", + ) + print(response.run_id) + asyncio.run(main()) ``` @@ -193,6 +197,7 @@ from oz_agent_sdk import AsyncOzAPI client = AsyncOzAPI() + async def main() -> None: all_runs = [] # Iterate through items across all pages, issuing requests as needed. @@ -200,6 +205,7 @@ async def main() -> None: all_runs.append(run) print(all_runs) + asyncio.run(main()) ``` @@ -220,7 +226,7 @@ Or just work directly with the returned data: ```python first_page = await client.agent.runs.list() -print(f"next page cursor: {first_page.page_info.next_cursor}") # => "next page cursor: ..." +print(f"next page cursor: {first_page.page_info.next_cursor}") # => "next page cursor: ..." for run in first_page.runs: print(run.run_id) @@ -263,7 +269,7 @@ try: ) except oz_agent_sdk.APIConnectionError as e: print("The server could not be reached") - print(e.__cause__) # an underlying Exception, likely raised within httpx. + print(e.__cause__) # an underlying Exception, likely raised within httpx. except oz_agent_sdk.RateLimitError as e: print("A 429 status code was received; we should back off a bit.") except oz_agent_sdk.APIStatusError as e: @@ -303,7 +309,7 @@ client = OzAPI( ) # Or, configure per-request: -client.with_options(max_retries = 5).agent.run( +client.with_options(max_retries=5).agent.run( prompt="Fix the bug in auth.go", ) ``` @@ -328,7 +334,7 @@ client = OzAPI( ) # Override per-request: -client.with_options(timeout = 5.0).agent.run( +client.with_options(timeout=5.0).agent.run( prompt="Fix the bug in auth.go", ) ``` @@ -393,11 +399,11 @@ To stream the response body, use `.with_streaming_response` instead, which requi ```python with client.agent.with_streaming_response.run( prompt="Fix the bug in auth.go", -) as response : - print(response.headers.get('X-My-Header')) +) as response: + print(response.headers.get("X-My-Header")) for line in response.iter_lines(): - print(line) + print(line) ``` The context manager is required so that the response will reliably be closed. @@ -451,7 +457,10 @@ from oz_agent_sdk import OzAPI, DefaultHttpxClient client = OzAPI( # Or use the `OZ_API_BASE_URL` env var base_url="http://my.test.server.example.com:8083", - http_client=DefaultHttpxClient(proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0")), + http_client=DefaultHttpxClient( + proxy="http://my.test.proxy.example.com", + transport=httpx.HTTPTransport(local_address="0.0.0.0"), + ), ) ``` diff --git a/api.md b/api.md index 7b728ae..e82443c 100644 --- a/api.md +++ b/api.md @@ -3,7 +3,23 @@ Types: ```python -from oz_agent_sdk.types import AgentSkill, AmbientAgentConfig, AwsProviderConfig, CloudEnvironment, CloudEnvironmentConfig, Error, ErrorCode, GcpProviderConfig, McpServerConfig, Scope, UserProfile, AgentListResponse, AgentGetArtifactResponse, AgentListEnvironmentsResponse, AgentRunResponse +from oz_agent_sdk.types import ( + AgentSkill, + AmbientAgentConfig, + AwsProviderConfig, + CloudEnvironment, + CloudEnvironmentConfig, + Error, + ErrorCode, + GcpProviderConfig, + McpServerConfig, + Scope, + UserProfile, + AgentListResponse, + AgentGetArtifactResponse, + AgentListEnvironmentsResponse, + AgentRunResponse, +) ``` Methods: @@ -18,7 +34,14 @@ Methods: Types: ```python -from oz_agent_sdk.types.agent import ArtifactItem, RunItem, RunSourceType, RunState, RunCancelResponse, RunListHandoffAttachmentsResponse +from oz_agent_sdk.types.agent import ( + ArtifactItem, + RunItem, + RunSourceType, + RunState, + RunCancelResponse, + RunListHandoffAttachmentsResponse, +) ``` Methods: @@ -34,7 +57,12 @@ Methods: Types: ```python -from oz_agent_sdk.types.agent import ScheduledAgentHistoryItem, ScheduledAgentItem, ScheduleListResponse, ScheduleDeleteResponse +from oz_agent_sdk.types.agent import ( + ScheduledAgentHistoryItem, + ScheduledAgentItem, + ScheduleListResponse, + ScheduleDeleteResponse, +) ``` Methods: @@ -52,7 +80,12 @@ Methods: Types: ```python -from oz_agent_sdk.types.agent import AgentResponse, CreateAgentRequest, ListAgentIdentitiesResponse, UpdateAgentRequest +from oz_agent_sdk.types.agent import ( + AgentResponse, + CreateAgentRequest, + ListAgentIdentitiesResponse, + UpdateAgentRequest, +) ``` Methods: diff --git a/scripts/utils/ruffen-docs.py b/scripts/utils/ruffen-docs.py index 37b3d94..0cf2bd2 100644 --- a/scripts/utils/ruffen-docs.py +++ b/scripts/utils/ruffen-docs.py @@ -47,7 +47,7 @@ def _md_match(match: Match[str]) -> str: with _collect_error(match): code = format_code_block(code) code = textwrap.indent(code, match["indent"]) - return f'{match["before"]}{code}{match["after"]}' + return f"{match['before']}{code}{match['after']}" def _pycon_match(match: Match[str]) -> str: code = "" @@ -97,7 +97,7 @@ def finish_fragment() -> None: def _md_pycon_match(match: Match[str]) -> str: code = _pycon_match(match) code = textwrap.indent(code, match["indent"]) - return f'{match["before"]}{code}{match["after"]}' + return f"{match['before']}{code}{match['after']}" src = MD_RE.sub(_md_match, src) src = MD_PYCON_RE.sub(_md_pycon_match, src) diff --git a/src/oz_agent_sdk/__init__.py b/src/oz_agent_sdk/__init__.py index b487a31..ea8b882 100644 --- a/src/oz_agent_sdk/__init__.py +++ b/src/oz_agent_sdk/__init__.py @@ -1,22 +1,80 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import typing as _t + from . import types -from ._version import __version__, __title__ -from ._client import Timeout,Transport,RequestOptions,Client,AsyncClient,Stream,AsyncStream,OzAPI,AsyncOzAPI -from ._exceptions import OzAPIError,APIError,APIStatusError,APITimeoutError,APIConnectionError,APIResponseValidationError,BadRequestError,AuthenticationError,PermissionDeniedError,NotFoundError,ConflictError,UnprocessableEntityError,RateLimitError,InternalServerError -from ._types import NoneType,Transport,ProxiesTypes,NotGiven,NOT_GIVEN,not_given,Omit,omit +from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes, omit, not_given from ._utils import file_from_path +from ._client import OzAPI, Client, Stream, Timeout, Transport, AsyncOzAPI, AsyncClient, AsyncStream, RequestOptions from ._models import BaseModel -from ._constants import DEFAULT_TIMEOUT,DEFAULT_MAX_RETRIES,DEFAULT_CONNECTION_LIMITS -from ._base_client import DefaultHttpxClient,DefaultAsyncHttpxClient,DefaultAioHttpClient -from ._utils._logs import setup_logging as _setup_logging +from ._version import __title__, __version__ from ._response import APIResponse as APIResponse, AsyncAPIResponse as AsyncAPIResponse -import typing as _t +from ._constants import DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES, DEFAULT_CONNECTION_LIMITS +from ._exceptions import ( + APIError, + OzAPIError, + ConflictError, + NotFoundError, + APIStatusError, + RateLimitError, + APITimeoutError, + BadRequestError, + APIConnectionError, + AuthenticationError, + InternalServerError, + PermissionDeniedError, + UnprocessableEntityError, + APIResponseValidationError, +) +from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient +from ._utils._logs import setup_logging as _setup_logging -__all__ = ["types", "__version__", "__title__", "NoneType", "Transport", "ProxiesTypes", "NotGiven", "NOT_GIVEN", "not_given", "Omit", "omit", "OzAPIError", "APIError", "APIStatusError", "APITimeoutError", "APIConnectionError", "APIResponseValidationError", "BadRequestError", "AuthenticationError", "PermissionDeniedError", "NotFoundError", "ConflictError", "UnprocessableEntityError", "RateLimitError", "InternalServerError", "Timeout", "RequestOptions", "Client", "AsyncClient", "Stream", "AsyncStream", "OzAPI", "AsyncOzAPI", "file_from_path", "BaseModel", "DEFAULT_TIMEOUT", "DEFAULT_MAX_RETRIES", "DEFAULT_CONNECTION_LIMITS", "DefaultHttpxClient", "DefaultAsyncHttpxClient", "DefaultAioHttpClient"] +__all__ = [ + "types", + "__version__", + "__title__", + "NoneType", + "Transport", + "ProxiesTypes", + "NotGiven", + "NOT_GIVEN", + "not_given", + "Omit", + "omit", + "OzAPIError", + "APIError", + "APIStatusError", + "APITimeoutError", + "APIConnectionError", + "APIResponseValidationError", + "BadRequestError", + "AuthenticationError", + "PermissionDeniedError", + "NotFoundError", + "ConflictError", + "UnprocessableEntityError", + "RateLimitError", + "InternalServerError", + "Timeout", + "RequestOptions", + "Client", + "AsyncClient", + "Stream", + "AsyncStream", + "OzAPI", + "AsyncOzAPI", + "file_from_path", + "BaseModel", + "DEFAULT_TIMEOUT", + "DEFAULT_MAX_RETRIES", + "DEFAULT_CONNECTION_LIMITS", + "DefaultHttpxClient", + "DefaultAsyncHttpxClient", + "DefaultAioHttpClient", +] if not _t.TYPE_CHECKING: - from ._utils._resources_proxy import resources as resources + from ._utils._resources_proxy import resources as resources _setup_logging() @@ -28,7 +86,7 @@ for __name in __all__: if not __name.startswith("__"): try: - setattr(__locals[__name], "__module__", "oz_agent_sdk") + __locals[__name].__module__ = "oz_agent_sdk" except (TypeError, AttributeError): # Some of our exported symbols are builtins which we can't set attributes for. - pass \ No newline at end of file + pass diff --git a/src/oz_agent_sdk/_base_client.py b/src/oz_agent_sdk/_base_client.py index ef52153..047d5bb 100644 --- a/src/oz_agent_sdk/_base_client.py +++ b/src/oz_agent_sdk/_base_client.py @@ -5,11 +5,11 @@ import time import uuid import email -import warnings import asyncio import inspect import logging import platform +import warnings import email.utils from types import TracebackType from random import random @@ -63,7 +63,7 @@ ) from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping from ._compat import PYDANTIC_V1, model_copy, model_dump -from ._models import GenericModel, FinalRequestOptions, SecurityOptions, validate_type, construct_type +from ._models import GenericModel, SecurityOptions, FinalRequestOptions, validate_type, construct_type from ._response import ( APIResponse, BaseAPIResponse, @@ -86,7 +86,6 @@ APIConnectionError, APIResponseValidationError, ) -from ._legacy_response import LegacyAPIResponse from ._utils._json import openapi_dumps log: logging.Logger = logging.getLogger(__name__) @@ -437,32 +436,32 @@ def _auth_headers( self, security: SecurityOptions, # noqa: ARG002 ) -> dict[str, str]: - return {} - + return {} + def _auth_query( self, security: SecurityOptions, # noqa: ARG002 ) -> dict[str, str]: - return {} - + return {} + def _custom_auth( self, security: SecurityOptions, # noqa: ARG002 ) -> httpx.Auth | None: - return None - + return None + def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0) -> httpx.Headers: custom_headers = options.headers or {} headers_dict = _merge_mappings({**self._auth_headers(options.security), **self.default_headers}, custom_headers) self._validate_headers(headers_dict, custom_headers) - + # headers are case-insensitive while dictionaries are not. headers = httpx.Headers(headers_dict) - + idempotency_header = self._idempotency_header if idempotency_header and options.idempotency_key and idempotency_header not in headers: headers[idempotency_header] = options.idempotency_key - + # Don't set these headers if they were already set or removed by the caller. We check # `custom_headers`, which can contain `Omit()`, instead of `headers` to account for the removal case. lower_custom_headers = [header.lower() for header in custom_headers] @@ -474,7 +473,7 @@ def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0 timeout = timeout.read if timeout is not None: headers["x-stainless-read-timeout"] = str(timeout) - + return headers def _prepare_url(self, url: str) -> URL: @@ -514,7 +513,7 @@ def _build_request( ), ) kwargs: dict[str, Any] = {} - + json_data = options.json_data if options.extra_json is not None: if json_data is None: @@ -523,12 +522,12 @@ def _build_request( json_data = _merge_mappings(json_data, options.extra_json) else: raise RuntimeError(f"Unexpected JSON data type, {type(json_data)}, cannot merge with `extra_body`") - + headers = self._build_headers(options, retries_taken=retries_taken) params = _merge_mappings({**self._auth_query(options.security), **self.default_query}, options.params) content_type = headers.get("Content-Type") files = options.files - + # If the given Content-Type header is multipart/form-data then it # has to be removed so that httpx can generate the header with # additional information for us as it has to be in this form @@ -539,7 +538,7 @@ def _build_request( # only remove the header if the boundary hasn't been explicitly set # as the caller doesn't want httpx to come up with their own boundary headers.pop("Content-Type") - + # As we are now sending multipart/form-data instead of application/json # we need to tell httpx to use it, https://www.python-httpx.org/advanced/clients/#multipart-file-encoding if json_data: @@ -548,7 +547,7 @@ def _build_request( f"Expected query input to be a dictionary for multipart requests but got {type(json_data)} instead." ) kwargs["data"] = self._serialize_multipartform(json_data) - + # httpx determines whether or not to send a "multipart/form-data" # request based on the truthiness of the "files" argument. # This gets around that issue by generating a dict value that @@ -557,7 +556,7 @@ def _build_request( # https://github.com/encode/httpx/discussions/2399#discussioncomment-3814186 if not files: 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: @@ -566,9 +565,9 @@ def _build_request( if "_" in prepared_url.host: # work around https://github.com/encode/httpx/discussions/2880 kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")} - + is_body_allowed = options.method.lower() != "get" - + if is_body_allowed: if options.content is not None and json_data is not None: raise TypeError("Passing both `content` and `json_data` is not supported") @@ -586,7 +585,7 @@ def _build_request( else: headers.pop("Content-Type", None) kwargs.pop("data", None) - + # TODO: report this error to httpx return self._client.build_request( # pyright: ignore[reportUnknownMemberType] headers=headers, @@ -606,7 +605,7 @@ def _serialize_multipartform(self, data: Mapping[object, object]) -> dict[str, o # TODO: type ignore is required as stringify_items is well typed but we can't be # well typed without heavy validation. data, # type: ignore - array_format="brackets" + array_format="brackets", ) serialized: dict[str, object] = {} for key, value in items: @@ -694,7 +693,7 @@ def default_headers(self) -> dict[str, str | Omit]: "Content-Type": "application/json", "User-Agent": self.user_agent, **self.platform_headers(), - **self._custom_headers + **self._custom_headers, } @property @@ -1065,7 +1064,6 @@ def request( response.reason_phrase, response.headers, ) - try: response.raise_for_status() @@ -1126,8 +1124,6 @@ def _process_response( stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, retries_taken: int = 0, ) -> ResponseT: - - origin = get_origin(cast_to) or cast_to if ( @@ -1305,8 +1301,6 @@ def post( ) return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) - - def patch( self, path: str, @@ -1328,7 +1322,9 @@ def patch( DeprecationWarning, stacklevel=2, ) - opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, content=content, files=to_httpx_files(files), **options) + opts = FinalRequestOptions.construct( + method="patch", url=path, json_data=body, content=content, files=to_httpx_files(files), **options + ) return self.request(cast_to, opts) def put( @@ -1652,7 +1648,6 @@ async def request( response.reason_phrase, response.headers, ) - try: response.raise_for_status() @@ -1713,8 +1708,6 @@ async def _process_response( stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, retries_taken: int = 0, ) -> ResponseT: - - origin = get_origin(cast_to) or cast_to if ( @@ -1880,8 +1873,6 @@ async def post( ) return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls) - - async def patch( self, path: str, @@ -1903,7 +1894,14 @@ async def patch( DeprecationWarning, stacklevel=2, ) - opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options) + opts = FinalRequestOptions.construct( + method="patch", + url=path, + json_data=body, + content=content, + files=await async_to_httpx_files(files), + **options, + ) return await self.request(cast_to, opts) async def put( @@ -1967,7 +1965,17 @@ def get_api_list( return self._request_api_list(model, page, opts) -def make_request_options(*, query: Query | None = None, extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, idempotency_key: str | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, post_parser: PostParser | NotGiven = not_given, security: SecurityOptions | None = None) -> RequestOptions: +def make_request_options( + *, + query: Query | None = None, + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + idempotency_key: str | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + post_parser: PostParser | NotGiven = not_given, + security: SecurityOptions | None = None, +) -> RequestOptions: """Create a dict of type RequestOptions without keys of NotGiven values.""" options: RequestOptions = {} if extra_headers is not None: @@ -1993,7 +2001,7 @@ def make_request_options(*, query: Query | None = None, extra_headers: Headers | options["post_parser"] = post_parser # type: ignore if security is not None: - options['security'] = security + options["security"] = security return options diff --git a/src/oz_agent_sdk/_client.py b/src/oz_agent_sdk/_client.py index 75ab68d..949709b 100644 --- a/src/oz_agent_sdk/_client.py +++ b/src/oz_agent_sdk/_client.py @@ -2,111 +2,115 @@ from __future__ import annotations -import httpx - import os +from typing import TYPE_CHECKING, Any, Mapping +from typing_extensions import Self, override -from ._streaming import AsyncStream as AsyncStream, Stream as Stream - -from ._types import NotGiven, not_given - -from typing import Mapping, Any - -from ._exceptions import OzAPIError, APIStatusError - -from ._utils import is_mapping_t, get_async_library +import httpx +from . import _exceptions +from ._qs import Querystring +from ._types import ( + Omit, + Timeout, + NotGiven, + Transport, + ProxiesTypes, + RequestOptions, + not_given, +) +from ._utils import ( + is_given, + is_mapping_t, + get_async_library, +) from ._compat import cached_property - -from typing_extensions import override, Self - from ._models import SecurityOptions - -from . import _exceptions - -import os -import asyncio -from typing_extensions import Literal - -import httpx - from ._version import __version__ -from ._qs import Querystring -from ._utils import maybe_coerce_integer, maybe_coerce_float, maybe_coerce_boolean, is_given -from ._types import Omit, Timeout, Transport, ProxiesTypes, RequestOptions, Headers, NoneType, Query, Body +from ._streaming import Stream as Stream, AsyncStream as AsyncStream +from ._exceptions import OzAPIError, APIStatusError from ._base_client import ( - DEFAULT_CONNECTION_LIMITS, - DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES, - ResponseT, - SyncHttpxClientWrapper, - AsyncHttpxClientWrapper, SyncAPIClient, AsyncAPIClient, - make_request_options, ) -from typing import TYPE_CHECKING - if TYPE_CHECKING: - from .resources import agent - from .resources import agent - from .resources import agent - from .resources import agent - from .resources.agent.agent import AgentResource, AsyncAgentResource + from .resources import agent + from .resources.agent.agent import AgentResource, AsyncAgentResource __all__ = ["Timeout", "Transport", "ProxiesTypes", "RequestOptions", "OzAPI", "AsyncOzAPI", "Client", "AsyncClient"] + class OzAPI(SyncAPIClient): # client options api_key: str - def __init__(self, *, api_key: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, - # Configure a custom httpx client. - # We provide a `DefaultHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. - # See the [httpx documentation](https://www.python-httpx.org/api/#client) for more details. - http_client: httpx.Client | None = None, - # Enable or disable schema validation for data returned by the API. - # When enabled an error APIResponseValidationError is raised - # if the API responds with invalid data for the expected schema. - # - # This parameter may be removed or changed in the future. - # If you rely on this feature, please open a GitHub issue - # outlining your use-case to help us decide if it should be - # part of our public interface in the future. - _strict_response_validation: bool = False) -> None: + def __init__( + self, + *, + api_key: str | None = None, + base_url: str | httpx.URL | None = None, + timeout: float | Timeout | None | NotGiven = not_given, + max_retries: int = DEFAULT_MAX_RETRIES, + default_headers: Mapping[str, str] | None = None, + default_query: Mapping[str, object] | None = None, + # Configure a custom httpx client. + # We provide a `DefaultHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. + # See the [httpx documentation](https://www.python-httpx.org/api/#client) for more details. + http_client: httpx.Client | None = None, + # Enable or disable schema validation for data returned by the API. + # When enabled an error APIResponseValidationError is raised + # if the API responds with invalid data for the expected schema. + # + # This parameter may be removed or changed in the future. + # If you rely on this feature, please open a GitHub issue + # outlining your use-case to help us decide if it should be + # part of our public interface in the future. + _strict_response_validation: bool = False, + ) -> None: """Construct a new synchronous OzAPI client instance. This automatically infers the `api_key` argument from the `WARP_API_KEY` environment variable if it is not provided. """ if api_key is None: - api_key = os.environ.get("WARP_API_KEY") + api_key = os.environ.get("WARP_API_KEY") if api_key is None: - raise OzAPIError( - "The api_key client option must be set either by passing api_key to the client or by setting the WARP_API_KEY environment variable" - ) + raise OzAPIError( + "The api_key client option must be set either by passing api_key to the client or by setting the WARP_API_KEY environment variable" + ) self.api_key = api_key if base_url is None: - base_url = os.environ.get("OZ_API_BASE_URL") + base_url = os.environ.get("OZ_API_BASE_URL") if base_url is None: - base_url = f"https://app.warp.dev/api/v1" + base_url = f"https://app.warp.dev/api/v1" custom_headers_env = os.environ.get("OZ_API_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, max_retries=max_retries, timeout=timeout, http_client=http_client, custom_headers=default_headers, custom_query=default_query, _strict_response_validation=_strict_response_validation) + 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, + max_retries=max_retries, + timeout=timeout, + http_client=http_client, + custom_headers=default_headers, + custom_query=default_query, + _strict_response_validation=_strict_response_validation, + ) @cached_property def agent(self) -> AgentResource: """Operations for running and managing cloud agents""" from .resources.agent import AgentResource + return AgentResource(self) @cached_property @@ -131,32 +135,39 @@ def _auth_headers(self, security: SecurityOptions) -> dict[str, str]: @property def _bearer_auth(self) -> dict[str, str]: api_key = self.api_key - return { - "Authorization": f"Bearer {api_key}" - } + return {"Authorization": f"Bearer {api_key}"} @property @override def default_headers(self) -> dict[str, str | Omit]: return { - **super().default_headers, - "X-Stainless-Async": "false", - **self._custom_headers, + **super().default_headers, + "X-Stainless-Async": "false", + **self._custom_headers, } - def copy(self, *, api_key: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, set_default_query: Mapping[str, object] | None = None, _extra_kwargs: Mapping[str, Any] = {}) -> Self: + def copy( + self, + *, + api_key: str | None = None, + base_url: str | httpx.URL | None = None, + timeout: float | Timeout | None | NotGiven = not_given, + http_client: httpx.Client | None = None, + max_retries: int | NotGiven = not_given, + default_headers: Mapping[str, str] | None = None, + set_default_headers: Mapping[str, str] | None = None, + default_query: Mapping[str, object] | None = None, + set_default_query: Mapping[str, object] | None = None, + _extra_kwargs: Mapping[str, Any] = {}, + ) -> Self: """ Create a new client instance re-using the same options given to the current client with optional overriding. """ if default_headers is not None and set_default_headers is not None: - raise ValueError( - 'The `default_headers` and `set_default_headers` arguments are mutually exclusive' - ) + raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive") if default_query is not None and set_default_query is not None: - raise ValueError( - 'The `default_query` and `set_default_query` arguments are mutually exclusive' - ) + raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive") headers = self._custom_headers if default_headers is not None: @@ -171,14 +182,29 @@ def copy(self, *, api_key: str | None = None, base_url: str | httpx.URL | None = params = set_default_query http_client = http_client or self._client - return self.__class__(api_key = api_key or self.api_key, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, max_retries=max_retries if is_given(max_retries) else self.max_retries, default_headers=headers, default_query=params, **_extra_kwargs) + return self.__class__( + api_key=api_key or self.api_key, + base_url=base_url or self.base_url, + timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, + http_client=http_client, + max_retries=max_retries if is_given(max_retries) else self.max_retries, + default_headers=headers, + default_query=params, + **_extra_kwargs, + ) # Alias for `copy` for nicer inline usage, e.g. # client.with_options(timeout=10).foo.create(...) with_options = copy @override - def _make_status_error(self, err_msg: str, *, body: object, response: httpx.Response,) -> APIStatusError: + def _make_status_error( + self, + err_msg: str, + *, + body: object, + response: httpx.Response, + ) -> APIStatusError: if response.status_code == 400: return _exceptions.BadRequestError(err_msg, response=response, body=body) @@ -204,56 +230,76 @@ def _make_status_error(self, err_msg: str, *, body: object, response: httpx.Resp return _exceptions.InternalServerError(err_msg, response=response, body=body) return APIStatusError(err_msg, response=response, body=body) + class AsyncOzAPI(AsyncAPIClient): # client options api_key: str - def __init__(self, *, api_key: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, - # Configure a custom httpx client. - # We provide a `DefaultAsyncHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. - # See the [httpx documentation](https://www.python-httpx.org/api/#asyncclient) for more details. - http_client: httpx.AsyncClient | None = None, - # Enable or disable schema validation for data returned by the API. - # When enabled an error APIResponseValidationError is raised - # if the API responds with invalid data for the expected schema. - # - # This parameter may be removed or changed in the future. - # If you rely on this feature, please open a GitHub issue - # outlining your use-case to help us decide if it should be - # part of our public interface in the future. - _strict_response_validation: bool = False) -> None: + def __init__( + self, + *, + api_key: str | None = None, + base_url: str | httpx.URL | None = None, + timeout: float | Timeout | None | NotGiven = not_given, + max_retries: int = DEFAULT_MAX_RETRIES, + default_headers: Mapping[str, str] | None = None, + default_query: Mapping[str, object] | None = None, + # Configure a custom httpx client. + # We provide a `DefaultAsyncHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. + # See the [httpx documentation](https://www.python-httpx.org/api/#asyncclient) for more details. + http_client: httpx.AsyncClient | None = None, + # Enable or disable schema validation for data returned by the API. + # When enabled an error APIResponseValidationError is raised + # if the API responds with invalid data for the expected schema. + # + # This parameter may be removed or changed in the future. + # If you rely on this feature, please open a GitHub issue + # outlining your use-case to help us decide if it should be + # part of our public interface in the future. + _strict_response_validation: bool = False, + ) -> None: """Construct a new async AsyncOzAPI client instance. This automatically infers the `api_key` argument from the `WARP_API_KEY` environment variable if it is not provided. """ if api_key is None: - api_key = os.environ.get("WARP_API_KEY") + api_key = os.environ.get("WARP_API_KEY") if api_key is None: - raise OzAPIError( - "The api_key client option must be set either by passing api_key to the client or by setting the WARP_API_KEY environment variable" - ) + raise OzAPIError( + "The api_key client option must be set either by passing api_key to the client or by setting the WARP_API_KEY environment variable" + ) self.api_key = api_key if base_url is None: - base_url = os.environ.get("OZ_API_BASE_URL") + base_url = os.environ.get("OZ_API_BASE_URL") if base_url is None: - base_url = f"https://app.warp.dev/api/v1" + base_url = f"https://app.warp.dev/api/v1" custom_headers_env = os.environ.get("OZ_API_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, max_retries=max_retries, timeout=timeout, http_client=http_client, custom_headers=default_headers, custom_query=default_query, _strict_response_validation=_strict_response_validation) + 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, + max_retries=max_retries, + timeout=timeout, + http_client=http_client, + custom_headers=default_headers, + custom_query=default_query, + _strict_response_validation=_strict_response_validation, + ) @cached_property def agent(self) -> AsyncAgentResource: """Operations for running and managing cloud agents""" from .resources.agent import AsyncAgentResource + return AsyncAgentResource(self) @cached_property @@ -278,32 +324,39 @@ def _auth_headers(self, security: SecurityOptions) -> dict[str, str]: @property def _bearer_auth(self) -> dict[str, str]: api_key = self.api_key - return { - "Authorization": f"Bearer {api_key}" - } + return {"Authorization": f"Bearer {api_key}"} @property @override def default_headers(self) -> dict[str, str | Omit]: return { - **super().default_headers, - "X-Stainless-Async": f'async:{get_async_library()}', - **self._custom_headers, + **super().default_headers, + "X-Stainless-Async": f"async:{get_async_library()}", + **self._custom_headers, } - def copy(self, *, api_key: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, set_default_query: Mapping[str, object] | None = None, _extra_kwargs: Mapping[str, Any] = {}) -> Self: + def copy( + self, + *, + api_key: str | None = None, + base_url: str | httpx.URL | None = None, + timeout: float | Timeout | None | NotGiven = not_given, + http_client: httpx.AsyncClient | None = None, + max_retries: int | NotGiven = not_given, + default_headers: Mapping[str, str] | None = None, + set_default_headers: Mapping[str, str] | None = None, + default_query: Mapping[str, object] | None = None, + set_default_query: Mapping[str, object] | None = None, + _extra_kwargs: Mapping[str, Any] = {}, + ) -> Self: """ Create a new client instance re-using the same options given to the current client with optional overriding. """ if default_headers is not None and set_default_headers is not None: - raise ValueError( - 'The `default_headers` and `set_default_headers` arguments are mutually exclusive' - ) + raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive") if default_query is not None and set_default_query is not None: - raise ValueError( - 'The `default_query` and `set_default_query` arguments are mutually exclusive' - ) + raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive") headers = self._custom_headers if default_headers is not None: @@ -318,14 +371,29 @@ def copy(self, *, api_key: str | None = None, base_url: str | httpx.URL | None = params = set_default_query http_client = http_client or self._client - return self.__class__(api_key = api_key or self.api_key, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, max_retries=max_retries if is_given(max_retries) else self.max_retries, default_headers=headers, default_query=params, **_extra_kwargs) + return self.__class__( + api_key=api_key or self.api_key, + base_url=base_url or self.base_url, + timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, + http_client=http_client, + max_retries=max_retries if is_given(max_retries) else self.max_retries, + default_headers=headers, + default_query=params, + **_extra_kwargs, + ) # Alias for `copy` for nicer inline usage, e.g. # client.with_options(timeout=10).foo.create(...) with_options = copy @override - def _make_status_error(self, err_msg: str, *, body: object, response: httpx.Response,) -> APIStatusError: + def _make_status_error( + self, + err_msg: str, + *, + body: object, + response: httpx.Response, + ) -> APIStatusError: if response.status_code == 400: return _exceptions.BadRequestError(err_msg, response=response, body=body) @@ -351,6 +419,7 @@ def _make_status_error(self, err_msg: str, *, body: object, response: httpx.Resp return _exceptions.InternalServerError(err_msg, response=response, body=body) return APIStatusError(err_msg, response=response, body=body) + class OzAPIWithRawResponse: _client: OzAPI @@ -361,8 +430,10 @@ def __init__(self, client: OzAPI) -> None: def agent(self) -> agent.AgentResourceWithRawResponse: """Operations for running and managing cloud agents""" from .resources.agent import AgentResourceWithRawResponse + return AgentResourceWithRawResponse(self._client.agent) + class AsyncOzAPIWithRawResponse: _client: AsyncOzAPI @@ -373,8 +444,10 @@ def __init__(self, client: AsyncOzAPI) -> None: def agent(self) -> agent.AsyncAgentResourceWithRawResponse: """Operations for running and managing cloud agents""" from .resources.agent import AsyncAgentResourceWithRawResponse + return AsyncAgentResourceWithRawResponse(self._client.agent) + class OzAPIWithStreamedResponse: _client: OzAPI @@ -385,8 +458,10 @@ def __init__(self, client: OzAPI) -> None: def agent(self) -> agent.AgentResourceWithStreamingResponse: """Operations for running and managing cloud agents""" from .resources.agent import AgentResourceWithStreamingResponse + return AgentResourceWithStreamingResponse(self._client.agent) + class AsyncOzAPIWithStreamedResponse: _client: AsyncOzAPI @@ -397,8 +472,10 @@ def __init__(self, client: AsyncOzAPI) -> None: def agent(self) -> agent.AsyncAgentResourceWithStreamingResponse: """Operations for running and managing cloud agents""" from .resources.agent import AsyncAgentResourceWithStreamingResponse + return AsyncAgentResourceWithStreamingResponse(self._client.agent) + Client = OzAPI -AsyncClient = AsyncOzAPI \ No newline at end of file +AsyncClient = AsyncOzAPI diff --git a/src/oz_agent_sdk/_compat.py b/src/oz_agent_sdk/_compat.py index 2763563..e6690a4 100644 --- a/src/oz_agent_sdk/_compat.py +++ b/src/oz_agent_sdk/_compat.py @@ -156,15 +156,12 @@ def model_dump( exclude_defaults=exclude_defaults, # warnings are not supported in Pydantic v1 warnings=True if PYDANTIC_V1 else warnings, - **kwargs + **kwargs, ) return cast( "dict[str, Any]", model.dict( # pyright: ignore[reportDeprecated, reportUnnecessaryCast] - exclude=exclude, - exclude_unset=exclude_unset, - exclude_defaults=exclude_defaults, - by_alias=bool(by_alias) + exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, by_alias=bool(by_alias) ), ) diff --git a/src/oz_agent_sdk/_constants.py b/src/oz_agent_sdk/_constants.py index f32ba27..6ddf2c7 100644 --- a/src/oz_agent_sdk/_constants.py +++ b/src/oz_agent_sdk/_constants.py @@ -11,4 +11,4 @@ DEFAULT_CONNECTION_LIMITS = httpx.Limits(max_connections=100, max_keepalive_connections=20) INITIAL_RETRY_DELAY = 0.5 -MAX_RETRY_DELAY = 8.0 \ No newline at end of file +MAX_RETRY_DELAY = 8.0 diff --git a/src/oz_agent_sdk/_exceptions.py b/src/oz_agent_sdk/_exceptions.py index 541647b..d84512f 100644 --- a/src/oz_agent_sdk/_exceptions.py +++ b/src/oz_agent_sdk/_exceptions.py @@ -2,15 +2,26 @@ from __future__ import annotations +from typing_extensions import Literal + import httpx -from typing_extensions import Literal +__all__ = [ + "BadRequestError", + "AuthenticationError", + "PermissionDeniedError", + "NotFoundError", + "ConflictError", + "UnprocessableEntityError", + "RateLimitError", + "InternalServerError", +] -__all__ = ["BadRequestError", "AuthenticationError", "PermissionDeniedError", "NotFoundError", "ConflictError", "UnprocessableEntityError", "RateLimitError", "InternalServerError"] class OzAPIError(Exception): pass + class APIError(OzAPIError): message: str request: httpx.Request @@ -32,6 +43,7 @@ def __init__(self, message: str, request: httpx.Request, *, body: object | None) self.message = message self.body = body + class APIResponseValidationError(APIError): response: httpx.Response status_code: int @@ -41,8 +53,10 @@ def __init__(self, response: httpx.Response, body: object | None, *, message: st self.response = response self.status_code = response.status_code + class APIStatusError(APIError): """Raised when an API response has a status code of 4xx or 5xx.""" + response: httpx.Response status_code: int @@ -51,34 +65,44 @@ def __init__(self, message: str, *, response: httpx.Response, body: object | Non self.response = response self.status_code = response.status_code + class APIConnectionError(APIError): def __init__(self, *, message: str = "Connection error.", request: httpx.Request) -> None: super().__init__(message, request, body=None) + class APITimeoutError(APIConnectionError): def __init__(self, request: httpx.Request) -> None: - super().__init__(message= "Request timed out.", request=request) + super().__init__(message="Request timed out.", request=request) + class BadRequestError(APIStatusError): - status_code: Literal[400] = 400 # pyright: ignore[reportIncompatibleVariableOverride] + status_code: Literal[400] = 400 # pyright: ignore[reportIncompatibleVariableOverride] + class AuthenticationError(APIStatusError): - status_code: Literal[401] = 401 # pyright: ignore[reportIncompatibleVariableOverride] + status_code: Literal[401] = 401 # pyright: ignore[reportIncompatibleVariableOverride] + class PermissionDeniedError(APIStatusError): - status_code: Literal[403] = 403 # pyright: ignore[reportIncompatibleVariableOverride] + status_code: Literal[403] = 403 # pyright: ignore[reportIncompatibleVariableOverride] + class NotFoundError(APIStatusError): - status_code: Literal[404] = 404 # pyright: ignore[reportIncompatibleVariableOverride] + status_code: Literal[404] = 404 # pyright: ignore[reportIncompatibleVariableOverride] + class ConflictError(APIStatusError): - status_code: Literal[409] = 409 # pyright: ignore[reportIncompatibleVariableOverride] + status_code: Literal[409] = 409 # pyright: ignore[reportIncompatibleVariableOverride] + class UnprocessableEntityError(APIStatusError): - status_code: Literal[422] = 422 # pyright: ignore[reportIncompatibleVariableOverride] + status_code: Literal[422] = 422 # pyright: ignore[reportIncompatibleVariableOverride] + class RateLimitError(APIStatusError): - status_code: Literal[429] = 429 # pyright: ignore[reportIncompatibleVariableOverride] + status_code: Literal[429] = 429 # pyright: ignore[reportIncompatibleVariableOverride] + class InternalServerError(APIStatusError): - pass \ No newline at end of file + pass diff --git a/src/oz_agent_sdk/_models.py b/src/oz_agent_sdk/_models.py index cd1d14e..69f41a6 100644 --- a/src/oz_agent_sdk/_models.py +++ b/src/oz_agent_sdk/_models.py @@ -1,23 +1,33 @@ from __future__ import annotations -from typing_extensions import TypedDict - import os import inspect import weakref -from typing import IO, TYPE_CHECKING, Any, AsyncIterable, AsyncIterable, Iterable, Type, Union, Generic, TypeVar, Callable, Optional, cast +from typing import ( + IO, + TYPE_CHECKING, + Any, + Type, + Union, + Generic, + TypeVar, + Callable, + Iterable, + Optional, + AsyncIterable, + cast, +) from datetime import date, datetime from typing_extensions import ( - Annotated, - TypeAlias, - Self, List, Unpack, Literal, ClassVar, Protocol, Required, + Annotated, ParamSpec, + TypeAlias, TypedDict, TypeGuard, final, @@ -88,10 +98,12 @@ P = ParamSpec("P") + @runtime_checkable class _ConfigProtocol(Protocol): allow_population_by_field_name: bool + class BaseModel(pydantic.BaseModel): if PYDANTIC_V1: @@ -393,6 +405,7 @@ def model_dump_json( exclude_none=exclude_none, ) + class _EagerIterable(list[_T], Generic[_T]): """ Accepts any Iterable[T] input (including generators), consumes it @@ -459,8 +472,10 @@ def _serialize(v: Iterable[_T]) -> list[_T]: return v return list(v) + EagerIterable: TypeAlias = Annotated[Iterable[_T], _EagerIterable] + def _construct_field(value: object, field: FieldInfo, key: str) -> object: if value is None: return field_get_default(field) @@ -475,6 +490,7 @@ def _construct_field(value: object, field: FieldInfo, key: str) -> object: return construct_type(value=value, type_=type_, metadata=getattr(field, "metadata", None)) + def _get_extra_fields_type(cls: type[pydantic.BaseModel]) -> type | None: if PYDANTIC_V1: # TODO @@ -491,6 +507,7 @@ def _get_extra_fields_type(cls: type[pydantic.BaseModel]) -> type | None: return None + def is_basemodel(type_: type) -> bool: """Returns whether or not the given type is either a `BaseModel` or a union of `BaseModel`""" if is_union(type_): @@ -502,12 +519,14 @@ def is_basemodel(type_: type) -> bool: return is_basemodel_type(type_) + def is_basemodel_type(type_: type) -> TypeGuard[type[BaseModel] | type[GenericModel]]: origin = get_origin(type_) or type_ if not inspect.isclass(origin): return False return issubclass(origin, BaseModel) or issubclass(origin, GenericModel) + def build( base_model_cls: Callable[P, _BaseModelT], *args: P.args, @@ -530,6 +549,7 @@ def build( return cast(_BaseModelT, construct_type(type_=base_model_cls, value=kwargs)) + def construct_type_unchecked(*, value: object, type_: type[_T]) -> _T: """Loose coercion to the expected type with construction of nested values. @@ -538,6 +558,7 @@ def construct_type_unchecked(*, value: object, type_: type[_T]) -> _T: """ return cast(_T, construct_type(value=value, type_=type_)) + def construct_type(*, value: object, type_: object, metadata: Optional[List[Any]] = None) -> object: """Loose coercion to the expected type with construction of nested values. @@ -657,12 +678,15 @@ def construct_type(*, value: object, type_: object, metadata: Optional[List[Any] return value + @runtime_checkable class CachedDiscriminatorType(Protocol): __discriminator__: DiscriminatorDetails + DISCRIMINATOR_CACHE: weakref.WeakKeyDictionary[type, DiscriminatorDetails] = weakref.WeakKeyDictionary() + class DiscriminatorDetails: field_name: str """The name of the discriminator field in the variant class, e.g. @@ -703,6 +727,7 @@ def __init__( self.field_name = discriminator_field self.field_alias_from = discriminator_alias + def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, ...]) -> DiscriminatorDetails | None: cached = DISCRIMINATOR_CACHE.get(union) if cached is not None: @@ -762,6 +787,7 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, DISCRIMINATOR_CACHE.setdefault(union, details) return details + def _extract_field_schema_pv2(model: type[BaseModel], field_name: str) -> ModelField | None: schema = model.__pydantic_core_schema__ if schema["type"] == "definitions": @@ -782,6 +808,7 @@ def _extract_field_schema_pv2(model: type[BaseModel], field_name: str) -> ModelF return cast("ModelField", field) # pyright: ignore[reportUnnecessaryCast] + def validate_type(*, type_: type[_T], value: object) -> _T: """Strict validation that the given value matches the expected type""" if inspect.isclass(type_) and issubclass(type_, pydantic.BaseModel): @@ -789,6 +816,7 @@ def validate_type(*, type_: type[_T], value: object) -> _T: return cast(_T, _validate_non_model_type(type_=type_, value=value)) + def set_pydantic_config(typ: Any, config: pydantic.ConfigDict) -> None: """Add a pydantic config for the given type. @@ -796,6 +824,7 @@ def set_pydantic_config(typ: Any, config: pydantic.ConfigDict) -> None: """ setattr(typ, "__pydantic_config__", config) # noqa: B010 + # our use of subclassing here causes weirdness for type checkers, # so we just pretend that we don't subclass if TYPE_CHECKING: @@ -805,6 +834,7 @@ def set_pydantic_config(typ: Any, config: pydantic.ConfigDict) -> None: class GenericModel(BaseGenericModel, BaseModel): pass + if not PYDANTIC_V1: from pydantic import TypeAdapter as _TypeAdapter @@ -840,9 +870,11 @@ def _validate_non_model_type(*, type_: type[_T], value: object) -> _T: def _create_pydantic_model(type_: _T) -> Type[RootModel[_T]]: return RootModel[type_] # type: ignore + class SecurityOptions(TypedDict, total=False): bearer_auth: bool + class FinalRequestOptionsInput(TypedDict, total=False): method: Required[str] url: Required[str] @@ -858,6 +890,7 @@ class FinalRequestOptionsInput(TypedDict, total=False): follow_redirects: bool security: SecurityOptions + @final class FinalRequestOptions(pydantic.BaseModel): method: str @@ -870,9 +903,7 @@ class FinalRequestOptions(pydantic.BaseModel): idempotency_key: Union[str, None] = None post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven() follow_redirects: Union[bool, None] = None - security: SecurityOptions = { - "bearer_auth": True - } + security: SecurityOptions = {"bearer_auth": True} content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None] = None # It should be noted that we cannot use `json` here as that would override @@ -924,4 +955,4 @@ def construct( # type: ignore if not TYPE_CHECKING: # type checkers incorrectly complain about this assignment - model_construct = construct \ No newline at end of file + model_construct = construct diff --git a/src/oz_agent_sdk/_qs.py b/src/oz_agent_sdk/_qs.py index 92464ff..4127c19 100644 --- a/src/oz_agent_sdk/_qs.py +++ b/src/oz_agent_sdk/_qs.py @@ -4,7 +4,7 @@ from urllib.parse import parse_qs, urlencode from typing_extensions import get_args -from ._types import ArrayFormat, NestedFormat, not_given, NotGiven +from ._types import NotGiven, ArrayFormat, NestedFormat, not_given from ._utils import flatten _T = TypeVar("_T") diff --git a/src/oz_agent_sdk/_resource.py b/src/oz_agent_sdk/_resource.py index a94a9d7..b875682 100644 --- a/src/oz_agent_sdk/_resource.py +++ b/src/oz_agent_sdk/_resource.py @@ -3,13 +3,13 @@ from __future__ import annotations import time +from typing import TYPE_CHECKING import anyio -from typing import TYPE_CHECKING - if TYPE_CHECKING: - from ._client import OzAPI, AsyncOzAPI + from ._client import OzAPI, AsyncOzAPI + class SyncAPIResource: _client: OzAPI @@ -24,7 +24,8 @@ def __init__(self, client: OzAPI) -> None: self._get_api_list = client.get_api_list def _sleep(self, seconds: float) -> None: - time.sleep(seconds) + time.sleep(seconds) + class AsyncAPIResource: _client: AsyncOzAPI @@ -39,4 +40,4 @@ def __init__(self, client: AsyncOzAPI) -> None: self._get_api_list = client.get_api_list async def _sleep(self, seconds: float) -> None: - await anyio.sleep(seconds) \ No newline at end of file + await anyio.sleep(seconds) diff --git a/src/oz_agent_sdk/_response.py b/src/oz_agent_sdk/_response.py index c5e15aa..4781d7c 100644 --- a/src/oz_agent_sdk/_response.py +++ b/src/oz_agent_sdk/_response.py @@ -25,14 +25,12 @@ import pydantic from ._types import NoneType -from ._utils import is_given, extract_type_arg, is_annotated_type, extract_type_var_from_base, is_type_alias_type -from ._streaming import extract_stream_chunk_type +from ._utils import is_given, extract_type_arg, is_annotated_type, is_type_alias_type, extract_type_var_from_base from ._models import BaseModel, is_basemodel from ._constants import RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER from ._streaming import Stream, AsyncStream, is_stream_class_type, extract_stream_chunk_type from ._exceptions import OzAPIError, APIResponseValidationError - if TYPE_CHECKING: from ._models import FinalRequestOptions from ._base_client import BaseClient @@ -140,8 +138,6 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: origin = get_origin(cast_to) or cast_to - - if self._is_sse_stream: if to: if not is_stream_class_type(to): @@ -204,7 +200,6 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: if cast_to == bool: return cast(R, response.text.lower() == "true") - if origin == APIResponse: raise RuntimeError("Unexpected state - cast_to is `APIResponse`") @@ -278,8 +273,6 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: class APIResponse(BaseAPIResponse[R]): - - @overload def parse(self, *, to: type[_T]) -> _T: ... @@ -382,8 +375,6 @@ def iter_lines(self) -> Iterator[str]: class AsyncAPIResponse(BaseAPIResponse[R]): - - @overload async def parse(self, *, to: type[_T]) -> _T: ... diff --git a/src/oz_agent_sdk/_streaming.py b/src/oz_agent_sdk/_streaming.py index 944e14d..dbfe0f8 100644 --- a/src/oz_agent_sdk/_streaming.py +++ b/src/oz_agent_sdk/_streaming.py @@ -4,18 +4,16 @@ import json import inspect from types import TracebackType -from typing import TYPE_CHECKING, Optional, Any, Generic, TypeVar, Iterator, AsyncIterator, cast +from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, Optional, AsyncIterator, cast from typing_extensions import Self, Protocol, TypeGuard, override, get_origin, runtime_checkable import httpx -from ._utils import is_mapping, is_dict, extract_type_var_from_base -from ._exceptions import APIError -from ._response import APIResponse, AsyncAPIResponse +from ._utils import extract_type_var_from_base if TYPE_CHECKING: - from ._models import FinalRequestOptions from ._client import OzAPI, AsyncOzAPI + from ._models import FinalRequestOptions _T = TypeVar("_T") @@ -58,7 +56,7 @@ def __stream__(self) -> Iterator[_T]: response = self.response process_data = self._client._process_response_data iterator = self._iter_events() - + try: for sse in iterator: yield process_data(data=sse.json(), cast_to=cast_to, response=response) @@ -124,7 +122,7 @@ async def __stream__(self) -> AsyncIterator[_T]: response = self.response process_data = self._client._process_response_data iterator = self._iter_events() - + try: async for sse in iterator: yield process_data(data=sse.json(), cast_to=cast_to, response=response) diff --git a/src/oz_agent_sdk/_types.py b/src/oz_agent_sdk/_types.py index ba9f701..09db394 100644 --- a/src/oz_agent_sdk/_types.py +++ b/src/oz_agent_sdk/_types.py @@ -5,9 +5,7 @@ IO, TYPE_CHECKING, Any, - AsyncIterable, Dict, - Iterable, List, Type, Tuple, @@ -15,12 +13,23 @@ Mapping, TypeVar, Callable, + Iterable, Iterator, Optional, Sequence, - + AsyncIterable, +) +from typing_extensions import ( + Set, + Literal, + Protocol, + TypeAlias, + TypedDict, + SupportsIndex, + overload, + override, + runtime_checkable, ) -from typing_extensions import Set, SupportsIndex, Literal, Protocol, TypeAlias, TypedDict, overload, override, runtime_checkable import httpx import pydantic @@ -29,7 +38,6 @@ if TYPE_CHECKING: from ._models import BaseModel, SecurityOptions from ._response import APIResponse, AsyncAPIResponse - from ._legacy_response import HttpxBinaryResponseContent Transport = BaseTransport AsyncTransport = AsyncBaseTransport @@ -133,6 +141,7 @@ class NotGiven: ```py def create(timeout: Timeout | None | NotGiven = not_given): ... + create(timeout=1) # 1s timeout create(timeout=None) # No timeout create() # Default timeout behavior diff --git a/src/oz_agent_sdk/_utils/__init__.py b/src/oz_agent_sdk/_utils/__init__.py index 2594310..1c090e5 100644 --- a/src/oz_agent_sdk/_utils/__init__.py +++ b/src/oz_agent_sdk/_utils/__init__.py @@ -1,3 +1,4 @@ +from ._path import path_template as path_template from ._sync import asyncify as asyncify from ._proxy import LazyProxy as LazyProxy from ._utils import ( @@ -61,4 +62,3 @@ assert_signatures_in_sync as assert_signatures_in_sync, ) from ._datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime -from ._path import path_template as path_template diff --git a/src/oz_agent_sdk/_utils/_resources_proxy.py b/src/oz_agent_sdk/_utils/_resources_proxy.py index 30be4ee..961a666 100644 --- a/src/oz_agent_sdk/_utils/_resources_proxy.py +++ b/src/oz_agent_sdk/_utils/_resources_proxy.py @@ -16,6 +16,7 @@ class ResourcesProxy(LazyProxy[Any]): @override def __load__(self) -> Any: import importlib + mod = importlib.import_module("oz_agent_sdk.resources") return mod diff --git a/src/oz_agent_sdk/_utils/_sync.py b/src/oz_agent_sdk/_utils/_sync.py index fdcdf5f..f6027c1 100644 --- a/src/oz_agent_sdk/_utils/_sync.py +++ b/src/oz_agent_sdk/_utils/_sync.py @@ -1,10 +1,8 @@ from __future__ import annotations -import sys import asyncio import functools -import contextvars -from typing import Any, TypeVar, Callable, Awaitable +from typing import TypeVar, Callable, Awaitable from typing_extensions import ParamSpec import anyio diff --git a/src/oz_agent_sdk/_utils/_transform.py b/src/oz_agent_sdk/_utils/_transform.py index 941ebb7..5207549 100644 --- a/src/oz_agent_sdk/_utils/_transform.py +++ b/src/oz_agent_sdk/_utils/_transform.py @@ -12,21 +12,21 @@ from ._utils import ( is_list, - is_sequence, is_given, lru_cache, is_mapping, is_iterable, + is_sequence, ) from .._files import is_base64_file_input from ._compat import get_origin, is_typeddict from ._typing import ( is_list_type, - is_sequence_type, is_union_type, extract_type_arg, is_iterable_type, is_required_type, + is_sequence_type, is_annotated_type, strip_annotated_type, ) diff --git a/src/oz_agent_sdk/_utils/_utils.py b/src/oz_agent_sdk/_utils/_utils.py index ed33f38..199cd23 100644 --- a/src/oz_agent_sdk/_utils/_utils.py +++ b/src/oz_agent_sdk/_utils/_utils.py @@ -21,7 +21,7 @@ import sniffio -from .._types import ArrayFormat, NotGiven, FileTypes, HeadersLike, Omit +from .._types import Omit, NotGiven, FileTypes, ArrayFormat, HeadersLike _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) @@ -54,9 +54,7 @@ def extract_files( """ files: list[tuple[str, FileTypes]] = [] for path in paths: - files.extend( - _extract_items(query, path, index=0, flattened_key=None, array_format=array_format) - ) + files.extend(_extract_items(query, path, index=0, flattened_key=None, array_format=array_format)) return files @@ -143,8 +141,7 @@ def _extract_items( path, index=index, flattened_key=( - (flattened_key if flattened_key is not None else "") - + _array_suffix(array_format, array_index) + (flattened_key if flattened_key is not None else "") + _array_suffix(array_format, array_index) ), array_format=array_format, ) diff --git a/src/oz_agent_sdk/_version.py b/src/oz_agent_sdk/_version.py index 7565cbc..1762ab1 100644 --- a/src/oz_agent_sdk/_version.py +++ b/src/oz_agent_sdk/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "oz_agent_sdk" -__version__ = "0.13.0" # x-release-please-version \ No newline at end of file +__version__ = "0.13.0" # x-release-please-version diff --git a/src/oz_agent_sdk/pagination.py b/src/oz_agent_sdk/pagination.py index a682efa..3f925ea 100644 --- a/src/oz_agent_sdk/pagination.py +++ b/src/oz_agent_sdk/pagination.py @@ -1,29 +1,22 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TypeVar, Optional, Generic, List - -from ._models import BaseModel - +from typing import List, Generic, TypeVar, Optional from typing_extensions import override -import re -from typing_extensions import TypedDict, Literal, Annotated, Protocol, runtime_checkable - -from httpx import URL, Response - from ._models import BaseModel -from ._utils import PropertyInfo, is_mapping -from ._base_client import BasePage, BaseSyncPage, BaseAsyncPage, PageInfo +from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage __all__ = ["RunsCursorPagePageInfo", "SyncRunsCursorPage", "AsyncRunsCursorPage"] -_T = TypeVar('_T') +_T = TypeVar("_T") + class RunsCursorPagePageInfo(BaseModel): has_next_page: Optional[bool] = None next_cursor: Optional[str] = None + class SyncRunsCursorPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]): runs: List[_T] page_info: Optional[RunsCursorPagePageInfo] = None @@ -38,25 +31,26 @@ def _get_page_items(self) -> List[_T]: @override def has_next_page(self) -> bool: has_next_page = None - if self.page_info is not None : - if self.page_info.has_next_page is not None : - has_next_page = self.page_info.has_next_page + if self.page_info is not None: + if self.page_info.has_next_page is not None: + has_next_page = self.page_info.has_next_page if has_next_page is not None and has_next_page is False: - return False + return False return super().has_next_page() @override def next_page_info(self) -> Optional[PageInfo]: next_cursor = None - if self.page_info is not None : - if self.page_info.next_cursor is not None : - next_cursor = self.page_info.next_cursor + if self.page_info is not None: + if self.page_info.next_cursor is not None: + next_cursor = self.page_info.next_cursor if not next_cursor: - return None + return None return PageInfo(params={"cursor": next_cursor}) + class AsyncRunsCursorPage(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): runs: List[_T] page_info: Optional[RunsCursorPagePageInfo] = None @@ -71,21 +65,21 @@ def _get_page_items(self) -> List[_T]: @override def has_next_page(self) -> bool: has_next_page = None - if self.page_info is not None : - if self.page_info.has_next_page is not None : - has_next_page = self.page_info.has_next_page + if self.page_info is not None: + if self.page_info.has_next_page is not None: + has_next_page = self.page_info.has_next_page if has_next_page is not None and has_next_page is False: - return False + return False return super().has_next_page() @override def next_page_info(self) -> Optional[PageInfo]: next_cursor = None - if self.page_info is not None : - if self.page_info.next_cursor is not None : - next_cursor = self.page_info.next_cursor + if self.page_info is not None: + if self.page_info.next_cursor is not None: + next_cursor = self.page_info.next_cursor if not next_cursor: - return None + return None - return PageInfo(params={"cursor": next_cursor}) \ No newline at end of file + return PageInfo(params={"cursor": next_cursor}) diff --git a/src/oz_agent_sdk/resources/__init__.py b/src/oz_agent_sdk/resources/__init__.py index 874bf62..38032a4 100644 --- a/src/oz_agent_sdk/resources/__init__.py +++ b/src/oz_agent_sdk/resources/__init__.py @@ -1,5 +1,19 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .agent import AgentResource, AsyncAgentResource, AgentResourceWithRawResponse, AsyncAgentResourceWithRawResponse, AgentResourceWithStreamingResponse, AsyncAgentResourceWithStreamingResponse +from .agent import ( + AgentResource, + AsyncAgentResource, + AgentResourceWithRawResponse, + AsyncAgentResourceWithRawResponse, + AgentResourceWithStreamingResponse, + AsyncAgentResourceWithStreamingResponse, +) -__all__ = ["AgentResource", "AsyncAgentResource", "AgentResourceWithRawResponse", "AsyncAgentResourceWithRawResponse", "AgentResourceWithStreamingResponse", "AsyncAgentResourceWithStreamingResponse"] \ No newline at end of file +__all__ = [ + "AgentResource", + "AsyncAgentResource", + "AgentResourceWithRawResponse", + "AsyncAgentResourceWithRawResponse", + "AgentResourceWithStreamingResponse", + "AsyncAgentResourceWithStreamingResponse", +] diff --git a/src/oz_agent_sdk/resources/agent/__init__.py b/src/oz_agent_sdk/resources/agent/__init__.py index b653809..69e9075 100644 --- a/src/oz_agent_sdk/resources/agent/__init__.py +++ b/src/oz_agent_sdk/resources/agent/__init__.py @@ -1,9 +1,75 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .runs import RunsResource, AsyncRunsResource, RunsResourceWithRawResponse, AsyncRunsResourceWithRawResponse, RunsResourceWithStreamingResponse, AsyncRunsResourceWithStreamingResponse -from .schedules import SchedulesResource, AsyncSchedulesResource, SchedulesResourceWithRawResponse, AsyncSchedulesResourceWithRawResponse, SchedulesResourceWithStreamingResponse, AsyncSchedulesResourceWithStreamingResponse -from .sessions import SessionsResource, AsyncSessionsResource, SessionsResourceWithRawResponse, AsyncSessionsResourceWithRawResponse, SessionsResourceWithStreamingResponse, AsyncSessionsResourceWithStreamingResponse -from .conversations import ConversationsResource, AsyncConversationsResource, ConversationsResourceWithRawResponse, AsyncConversationsResourceWithRawResponse, ConversationsResourceWithStreamingResponse, AsyncConversationsResourceWithStreamingResponse -from .agent import AgentResource, AsyncAgentResource, AgentResourceWithRawResponse, AsyncAgentResourceWithRawResponse, AgentResourceWithStreamingResponse, AsyncAgentResourceWithStreamingResponse +from .runs import ( + RunsResource, + AsyncRunsResource, + RunsResourceWithRawResponse, + AsyncRunsResourceWithRawResponse, + RunsResourceWithStreamingResponse, + AsyncRunsResourceWithStreamingResponse, +) +from .agent import ( + AgentResource, + AsyncAgentResource, + AgentResourceWithRawResponse, + AsyncAgentResourceWithRawResponse, + AgentResourceWithStreamingResponse, + AsyncAgentResourceWithStreamingResponse, +) +from .sessions import ( + SessionsResource, + AsyncSessionsResource, + SessionsResourceWithRawResponse, + AsyncSessionsResourceWithRawResponse, + SessionsResourceWithStreamingResponse, + AsyncSessionsResourceWithStreamingResponse, +) +from .schedules import ( + SchedulesResource, + AsyncSchedulesResource, + SchedulesResourceWithRawResponse, + AsyncSchedulesResourceWithRawResponse, + SchedulesResourceWithStreamingResponse, + AsyncSchedulesResourceWithStreamingResponse, +) +from .conversations import ( + ConversationsResource, + AsyncConversationsResource, + ConversationsResourceWithRawResponse, + AsyncConversationsResourceWithRawResponse, + ConversationsResourceWithStreamingResponse, + AsyncConversationsResourceWithStreamingResponse, +) -__all__ = ["RunsResource", "AsyncRunsResource", "RunsResourceWithRawResponse", "AsyncRunsResourceWithRawResponse", "RunsResourceWithStreamingResponse", "AsyncRunsResourceWithStreamingResponse", "SchedulesResource", "AsyncSchedulesResource", "SchedulesResourceWithRawResponse", "AsyncSchedulesResourceWithRawResponse", "SchedulesResourceWithStreamingResponse", "AsyncSchedulesResourceWithStreamingResponse", "SessionsResource", "AsyncSessionsResource", "SessionsResourceWithRawResponse", "AsyncSessionsResourceWithRawResponse", "SessionsResourceWithStreamingResponse", "AsyncSessionsResourceWithStreamingResponse", "ConversationsResource", "AsyncConversationsResource", "ConversationsResourceWithRawResponse", "AsyncConversationsResourceWithRawResponse", "ConversationsResourceWithStreamingResponse", "AsyncConversationsResourceWithStreamingResponse", "AgentResource", "AsyncAgentResource", "AgentResourceWithRawResponse", "AsyncAgentResourceWithRawResponse", "AgentResourceWithStreamingResponse", "AsyncAgentResourceWithStreamingResponse"] \ No newline at end of file +__all__ = [ + "RunsResource", + "AsyncRunsResource", + "RunsResourceWithRawResponse", + "AsyncRunsResourceWithRawResponse", + "RunsResourceWithStreamingResponse", + "AsyncRunsResourceWithStreamingResponse", + "SchedulesResource", + "AsyncSchedulesResource", + "SchedulesResourceWithRawResponse", + "AsyncSchedulesResourceWithRawResponse", + "SchedulesResourceWithStreamingResponse", + "AsyncSchedulesResourceWithStreamingResponse", + "SessionsResource", + "AsyncSessionsResource", + "SessionsResourceWithRawResponse", + "AsyncSessionsResourceWithRawResponse", + "SessionsResourceWithStreamingResponse", + "AsyncSessionsResourceWithStreamingResponse", + "ConversationsResource", + "AsyncConversationsResource", + "ConversationsResourceWithRawResponse", + "AsyncConversationsResourceWithRawResponse", + "ConversationsResourceWithStreamingResponse", + "AsyncConversationsResourceWithStreamingResponse", + "AgentResource", + "AsyncAgentResource", + "AgentResourceWithRawResponse", + "AsyncAgentResourceWithRawResponse", + "AgentResourceWithStreamingResponse", + "AsyncAgentResourceWithStreamingResponse", +] diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index d2d8e98..6910539 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -2,57 +2,68 @@ from __future__ import annotations -import httpx - -from ..._resource import SyncAPIResource, AsyncAPIResource +from typing import Any, Iterable, cast +from typing_extensions import Literal -from .runs import RunsResource, AsyncRunsResource, RunsResourceWithRawResponse, AsyncRunsResourceWithRawResponse, RunsResourceWithStreamingResponse, AsyncRunsResourceWithStreamingResponse +import httpx +from . import agent_ as agent +from .runs import ( + RunsResource, + AsyncRunsResource, + RunsResourceWithRawResponse, + AsyncRunsResourceWithRawResponse, + RunsResourceWithStreamingResponse, + AsyncRunsResourceWithStreamingResponse, +) +from ...types import agent_run_params, agent_list_params, agent_list_environments_params +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import path_template, maybe_transform, async_maybe_transform +from .sessions import ( + SessionsResource, + AsyncSessionsResource, + SessionsResourceWithRawResponse, + AsyncSessionsResourceWithRawResponse, + SessionsResourceWithStreamingResponse, + AsyncSessionsResourceWithStreamingResponse, +) from ..._compat import cached_property - -from .schedules import SchedulesResource, AsyncSchedulesResource, SchedulesResourceWithRawResponse, AsyncSchedulesResourceWithRawResponse, SchedulesResourceWithStreamingResponse, AsyncSchedulesResourceWithStreamingResponse - -from .sessions import SessionsResource, AsyncSessionsResource, SessionsResourceWithRawResponse, AsyncSessionsResourceWithRawResponse, SessionsResourceWithStreamingResponse, AsyncSessionsResourceWithStreamingResponse - -from .conversations import ConversationsResource, AsyncConversationsResource, ConversationsResourceWithRawResponse, AsyncConversationsResourceWithRawResponse, ConversationsResourceWithStreamingResponse, AsyncConversationsResourceWithStreamingResponse - -from ...types.agent_list_response import AgentListResponse - +from .schedules import ( + SchedulesResource, + AsyncSchedulesResource, + SchedulesResourceWithRawResponse, + AsyncSchedulesResourceWithRawResponse, + SchedulesResourceWithStreamingResponse, + AsyncSchedulesResourceWithStreamingResponse, +) +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .conversations import ( + ConversationsResource, + AsyncConversationsResource, + ConversationsResourceWithRawResponse, + AsyncConversationsResourceWithRawResponse, + ConversationsResourceWithStreamingResponse, + AsyncConversationsResourceWithStreamingResponse, +) from ..._base_client import make_request_options - -from ..._utils import maybe_transform, path_template, async_maybe_transform - -from ..._types import Omit, omit, NotGiven - -from typing_extensions import Literal - -from ...types.agent_get_artifact_response import AgentGetArtifactResponse - -from typing import Any, cast, Iterable - -from ...types.agent_list_environments_response import AgentListEnvironmentsResponse - from ...types.agent_run_response import AgentRunResponse - +from ...types.agent_list_response import AgentListResponse from ...types.ambient_agent_config_param import AmbientAgentConfigParam - -from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper, to_streamed_response_wrapper, async_to_streamed_response_wrapper - -from . import agent_ as agent - -from ...types import agent_run_params - -from typing_extensions import Literal, overload -from ..._types import Timeout, Headers, NotGiven, not_given, Omit, omit, NoneType, Query, Body -from ...types import agent_list_params -from ...types import agent_list_environments_params -from ...types import agent_run_params -from ...types import AmbientAgentConfig +from ...types.agent_get_artifact_response import AgentGetArtifactResponse +from ...types.agent_list_environments_response import AgentListEnvironmentsResponse __all__ = ["AgentResource", "AsyncAgentResource"] + class AgentResource(SyncAPIResource): """Operations for running and managing cloud agents""" + @cached_property def runs(self) -> RunsResource: """Operations for running and managing cloud agents""" @@ -97,18 +108,20 @@ def with_streaming_response(self) -> AgentResourceWithStreamingResponse: """ return AgentResourceWithStreamingResponse(self) - def list(self, - *, - include_malformed_skills: bool | Omit = omit, - refresh: bool | Omit = omit, - repo: str | Omit = omit, - sort_by: Literal["name", "last_run"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentListResponse: + def list( + self, + *, + include_malformed_skills: bool | Omit = omit, + refresh: bool | Omit = omit, + repo: str | Omit = omit, + sort_by: Literal["name", "last_run"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentListResponse: """ Retrieve a list of available agents (skills) that can be used to run tasks. Agents are discovered from environments or a specific repository. @@ -139,24 +152,35 @@ def list(self, """ return self._get( "/agent", - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({ - "include_malformed_skills": include_malformed_skills, - "refresh": refresh, - "repo": repo, - "sort_by": sort_by, - }, agent_list_params.AgentListParams)), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "include_malformed_skills": include_malformed_skills, + "refresh": refresh, + "repo": repo, + "sort_by": sort_by, + }, + agent_list_params.AgentListParams, + ), + ), cast_to=AgentListResponse, ) - def get_artifact(self, - artifact_uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentGetArtifactResponse: + def get_artifact( + self, + artifact_uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentGetArtifactResponse: """Retrieve an artifact by its UUID. For downloadable file-like artifacts, returns @@ -173,24 +197,31 @@ def get_artifact(self, timeout: Override the client-level default timeout for this request, in seconds """ if not artifact_uid: - raise ValueError( - f'Expected a non-empty value for `artifact_uid` but received {artifact_uid!r}' - ) - return cast(AgentGetArtifactResponse, self._get( - path_template("/agent/artifacts/{artifact_uid}", artifact_uid=artifact_uid), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), - cast_to=cast(Any, AgentGetArtifactResponse), # Union types cannot be passed in as arguments in the type system - )) - - def list_environments(self, - *, - sort_by: Literal["name", "last_updated"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentListEnvironmentsResponse: + raise ValueError(f"Expected a non-empty value for `artifact_uid` but received {artifact_uid!r}") + return cast( + AgentGetArtifactResponse, + self._get( + path_template("/agent/artifacts/{artifact_uid}", artifact_uid=artifact_uid), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, AgentGetArtifactResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + + def list_environments( + self, + *, + sort_by: Literal["name", "last_updated"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentListEnvironmentsResponse: """Retrieve cloud environments accessible to the authenticated principal. Returns @@ -213,31 +244,37 @@ def list_environments(self, """ return self._get( "/agent/environments", - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({ - "sort_by": sort_by - }, agent_list_environments_params.AgentListEnvironmentsParams)), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"sort_by": sort_by}, agent_list_environments_params.AgentListEnvironmentsParams), + ), cast_to=AgentListEnvironmentsResponse, ) - def run(self, - *, - agent_identity_uid: str | Omit = omit, - attachments: Iterable[agent_run_params.Attachment] | Omit = omit, - config: AmbientAgentConfigParam | Omit = omit, - conversation_id: str | Omit = omit, - interactive: bool | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - parent_run_id: str | Omit = omit, - prompt: str | Omit = omit, - skill: str | Omit = omit, - team: bool | Omit = omit, - title: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentRunResponse: + def run( + self, + *, + agent_identity_uid: str | Omit = omit, + attachments: Iterable[agent_run_params.Attachment] | Omit = omit, + config: AmbientAgentConfigParam | Omit = omit, + conversation_id: str | Omit = omit, + interactive: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + parent_run_id: str | Omit = omit, + prompt: str | Omit = omit, + skill: str | Omit = omit, + team: bool | Omit = omit, + title: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentRunResponse: """Spawn a cloud agent with a prompt and optional configuration. The agent will be @@ -291,25 +328,32 @@ def run(self, """ return self._post( "/agent/runs", - body=maybe_transform({ - "agent_identity_uid": agent_identity_uid, - "attachments": attachments, - "config": config, - "conversation_id": conversation_id, - "interactive": interactive, - "mode": mode, - "parent_run_id": parent_run_id, - "prompt": prompt, - "skill": skill, - "team": team, - "title": title, - }, agent_run_params.AgentRunParams), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + body=maybe_transform( + { + "agent_identity_uid": agent_identity_uid, + "attachments": attachments, + "config": config, + "conversation_id": conversation_id, + "interactive": interactive, + "mode": mode, + "parent_run_id": parent_run_id, + "prompt": prompt, + "skill": skill, + "team": team, + "title": title, + }, + agent_run_params.AgentRunParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=AgentRunResponse, ) + class AsyncAgentResource(AsyncAPIResource): """Operations for running and managing cloud agents""" + @cached_property def runs(self) -> AsyncRunsResource: """Operations for running and managing cloud agents""" @@ -354,18 +398,20 @@ def with_streaming_response(self) -> AsyncAgentResourceWithStreamingResponse: """ return AsyncAgentResourceWithStreamingResponse(self) - async def list(self, - *, - include_malformed_skills: bool | Omit = omit, - refresh: bool | Omit = omit, - repo: str | Omit = omit, - sort_by: Literal["name", "last_run"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentListResponse: + async def list( + self, + *, + include_malformed_skills: bool | Omit = omit, + refresh: bool | Omit = omit, + repo: str | Omit = omit, + sort_by: Literal["name", "last_run"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentListResponse: """ Retrieve a list of available agents (skills) that can be used to run tasks. Agents are discovered from environments or a specific repository. @@ -396,24 +442,35 @@ async def list(self, """ return await self._get( "/agent", - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform({ - "include_malformed_skills": include_malformed_skills, - "refresh": refresh, - "repo": repo, - "sort_by": sort_by, - }, agent_list_params.AgentListParams)), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "include_malformed_skills": include_malformed_skills, + "refresh": refresh, + "repo": repo, + "sort_by": sort_by, + }, + agent_list_params.AgentListParams, + ), + ), cast_to=AgentListResponse, ) - async def get_artifact(self, - artifact_uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentGetArtifactResponse: + async def get_artifact( + self, + artifact_uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentGetArtifactResponse: """Retrieve an artifact by its UUID. For downloadable file-like artifacts, returns @@ -430,24 +487,31 @@ async def get_artifact(self, timeout: Override the client-level default timeout for this request, in seconds """ if not artifact_uid: - raise ValueError( - f'Expected a non-empty value for `artifact_uid` but received {artifact_uid!r}' - ) - return cast(AgentGetArtifactResponse, await self._get( - path_template("/agent/artifacts/{artifact_uid}", artifact_uid=artifact_uid), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), - cast_to=cast(Any, AgentGetArtifactResponse), # Union types cannot be passed in as arguments in the type system - )) - - async def list_environments(self, - *, - sort_by: Literal["name", "last_updated"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentListEnvironmentsResponse: + raise ValueError(f"Expected a non-empty value for `artifact_uid` but received {artifact_uid!r}") + return cast( + AgentGetArtifactResponse, + await self._get( + path_template("/agent/artifacts/{artifact_uid}", artifact_uid=artifact_uid), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, AgentGetArtifactResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + + async def list_environments( + self, + *, + sort_by: Literal["name", "last_updated"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentListEnvironmentsResponse: """Retrieve cloud environments accessible to the authenticated principal. Returns @@ -470,31 +534,39 @@ async def list_environments(self, """ return await self._get( "/agent/environments", - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform({ - "sort_by": sort_by - }, agent_list_environments_params.AgentListEnvironmentsParams)), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"sort_by": sort_by}, agent_list_environments_params.AgentListEnvironmentsParams + ), + ), cast_to=AgentListEnvironmentsResponse, ) - async def run(self, - *, - agent_identity_uid: str | Omit = omit, - attachments: Iterable[agent_run_params.Attachment] | Omit = omit, - config: AmbientAgentConfigParam | Omit = omit, - conversation_id: str | Omit = omit, - interactive: bool | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - parent_run_id: str | Omit = omit, - prompt: str | Omit = omit, - skill: str | Omit = omit, - team: bool | Omit = omit, - title: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentRunResponse: + async def run( + self, + *, + agent_identity_uid: str | Omit = omit, + attachments: Iterable[agent_run_params.Attachment] | Omit = omit, + config: AmbientAgentConfigParam | Omit = omit, + conversation_id: str | Omit = omit, + interactive: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + parent_run_id: str | Omit = omit, + prompt: str | Omit = omit, + skill: str | Omit = omit, + team: bool | Omit = omit, + title: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentRunResponse: """Spawn a cloud agent with a prompt and optional configuration. The agent will be @@ -548,23 +620,29 @@ async def run(self, """ return await self._post( "/agent/runs", - body=await async_maybe_transform({ - "agent_identity_uid": agent_identity_uid, - "attachments": attachments, - "config": config, - "conversation_id": conversation_id, - "interactive": interactive, - "mode": mode, - "parent_run_id": parent_run_id, - "prompt": prompt, - "skill": skill, - "team": team, - "title": title, - }, agent_run_params.AgentRunParams), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + body=await async_maybe_transform( + { + "agent_identity_uid": agent_identity_uid, + "attachments": attachments, + "config": config, + "conversation_id": conversation_id, + "interactive": interactive, + "mode": mode, + "parent_run_id": parent_run_id, + "prompt": prompt, + "skill": skill, + "team": team, + "title": title, + }, + agent_run_params.AgentRunParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=AgentRunResponse, ) + class AgentResourceWithRawResponse: def __init__(self, agent: AgentResource) -> None: self._agent = agent @@ -607,6 +685,7 @@ def conversations(self) -> ConversationsResourceWithRawResponse: """Operations for running and managing cloud agents""" return ConversationsResourceWithRawResponse(self._agent.conversations) + class AsyncAgentResourceWithRawResponse: def __init__(self, agent: AsyncAgentResource) -> None: self._agent = agent @@ -649,6 +728,7 @@ def conversations(self) -> AsyncConversationsResourceWithRawResponse: """Operations for running and managing cloud agents""" return AsyncConversationsResourceWithRawResponse(self._agent.conversations) + class AgentResourceWithStreamingResponse: def __init__(self, agent: AgentResource) -> None: self._agent = agent @@ -691,6 +771,7 @@ def conversations(self) -> ConversationsResourceWithStreamingResponse: """Operations for running and managing cloud agents""" return ConversationsResourceWithStreamingResponse(self._agent.conversations) + class AsyncAgentResourceWithStreamingResponse: def __init__(self, agent: AsyncAgentResource) -> None: self._agent = agent @@ -731,4 +812,4 @@ def sessions(self) -> AsyncSessionsResourceWithStreamingResponse: @cached_property def conversations(self) -> AsyncConversationsResourceWithStreamingResponse: """Operations for running and managing cloud agents""" - return AsyncConversationsResourceWithStreamingResponse(self._agent.conversations) \ No newline at end of file + return AsyncConversationsResourceWithStreamingResponse(self._agent.conversations) diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py index fa43b31..65eb4d5 100644 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -2,39 +2,32 @@ from __future__ import annotations -import httpx +from typing import Dict, Iterable, Optional -from ..._resource import SyncAPIResource, AsyncAPIResource +import httpx +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given +from ..._utils import path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property - -from ...types.agent.agent_response import AgentResponse - -from ..._utils import maybe_transform, path_template, async_maybe_transform - +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...types.agent import agent_create_params, agent_update_params from ..._base_client import make_request_options - -from typing import Optional, Dict, Iterable - -from ..._types import Omit, omit, SequenceNotStr, NotGiven - +from ...types.agent.agent_response import AgentResponse from ...types.mcp_server_config_param import McpServerConfigParam - from ...types.agent.list_agent_identities_response import ListAgentIdentitiesResponse -from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper, to_streamed_response_wrapper, async_to_streamed_response_wrapper - -from ...types.agent import agent_create_params, agent_update_params - -from typing_extensions import Literal, overload -from ..._types import Timeout, Headers, NotGiven, not_given, Omit, omit, NoneType, Query, Body -from ...types.agent import agent_create_params -from ...types.agent import agent_update_params - __all__ = ["AgentResource", "AsyncAgentResource"] + class AgentResource(SyncAPIResource): """Operations for running and managing cloud agents""" + @cached_property def with_raw_response(self) -> AgentResourceWithRawResponse: """ @@ -54,26 +47,28 @@ def with_streaming_response(self) -> AgentResourceWithStreamingResponse: """ return AgentResourceWithStreamingResponse(self) - def create(self, - *, - name: str, - base_harness: Optional[str] | Omit = omit, - base_model: Optional[str] | Omit = omit, - description: Optional[str] | Omit = omit, - environment_id: Optional[str] | Omit = omit, - harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, - inference_providers: agent_create_params.InferenceProviders | Omit = omit, - mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, - memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, - prompt: Optional[str] | Omit = omit, - secrets: Iterable[agent_create_params.Secret] | Omit = omit, - skills: SequenceNotStr[str] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentResponse: + def create( + self, + *, + name: str, + base_harness: Optional[str] | Omit = omit, + base_model: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, + environment_id: Optional[str] | Omit = omit, + harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, + inference_providers: agent_create_params.InferenceProviders | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, + memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, + prompt: Optional[str] | Omit = omit, + secrets: Iterable[agent_create_params.Secret] | Omit = omit, + skills: SequenceNotStr[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: """Create a new agent for the caller's team. Agents can be used as the execution @@ -126,45 +121,52 @@ def create(self, """ return self._post( "/agent/identities", - body=maybe_transform({ - "name": name, - "base_harness": base_harness, - "base_model": base_model, - "description": description, - "environment_id": environment_id, - "harness_auth_secrets": harness_auth_secrets, - "inference_providers": inference_providers, - "mcp_servers": mcp_servers, - "memory_stores": memory_stores, - "prompt": prompt, - "secrets": secrets, - "skills": skills, - }, agent_create_params.AgentCreateParams), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + body=maybe_transform( + { + "name": name, + "base_harness": base_harness, + "base_model": base_model, + "description": description, + "environment_id": environment_id, + "harness_auth_secrets": harness_auth_secrets, + "inference_providers": inference_providers, + "mcp_servers": mcp_servers, + "memory_stores": memory_stores, + "prompt": prompt, + "secrets": secrets, + "skills": skills, + }, + agent_create_params.AgentCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=AgentResponse, ) - def update(self, - uid: str, - *, - base_harness: Optional[str] | Omit = omit, - base_model: Optional[str] | Omit = omit, - description: Optional[str] | Omit = omit, - environment_id: Optional[str] | Omit = omit, - harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, - inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, - mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, - memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, - name: str | Omit = omit, - prompt: Optional[str] | Omit = omit, - secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, - skills: Optional[SequenceNotStr[str]] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentResponse: + def update( + self, + uid: str, + *, + base_harness: Optional[str] | Omit = omit, + base_model: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, + environment_id: Optional[str] | Omit = omit, + harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, + inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, + memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, + name: str | Omit = omit, + prompt: Optional[str] | Omit = omit, + secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, + skills: Optional[SequenceNotStr[str]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: """Update an existing agent. Args: @@ -214,37 +216,42 @@ def update(self, timeout: Override the client-level default timeout for this request, in seconds """ if not uid: - raise ValueError( - f'Expected a non-empty value for `uid` but received {uid!r}' - ) + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return self._put( path_template("/agent/identities/{uid}", uid=uid), - body=maybe_transform({ - "base_harness": base_harness, - "base_model": base_model, - "description": description, - "environment_id": environment_id, - "harness_auth_secrets": harness_auth_secrets, - "inference_providers": inference_providers, - "mcp_servers": mcp_servers, - "memory_stores": memory_stores, - "name": name, - "prompt": prompt, - "secrets": secrets, - "skills": skills, - }, agent_update_params.AgentUpdateParams), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + body=maybe_transform( + { + "base_harness": base_harness, + "base_model": base_model, + "description": description, + "environment_id": environment_id, + "harness_auth_secrets": harness_auth_secrets, + "inference_providers": inference_providers, + "mcp_servers": mcp_servers, + "memory_stores": memory_stores, + "name": name, + "prompt": prompt, + "secrets": secrets, + "skills": skills, + }, + agent_update_params.AgentUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=AgentResponse, ) - def list(self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ListAgentIdentitiesResponse: + def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ListAgentIdentitiesResponse: """List all agents for the caller's team. Each agent includes an `available` flag @@ -252,19 +259,23 @@ def list(self, """ return self._get( "/agent/identities", - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ListAgentIdentitiesResponse, ) - def delete(self, - uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> None: + def delete( + self, + uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: """Delete an agent. All API keys associated with the agent are deleted atomically. @@ -279,25 +290,27 @@ def delete(self, timeout: Override the client-level default timeout for this request, in seconds """ if not uid: - raise ValueError( - f'Expected a non-empty value for `uid` but received {uid!r}' - ) + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._delete( path_template("/agent/identities/{uid}", uid=uid), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=NoneType, ) - def get(self, - uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentResponse: + def get( + self, + uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: """Retrieve a single agent by its unique identifier. The response includes an @@ -314,17 +327,19 @@ def get(self, timeout: Override the client-level default timeout for this request, in seconds """ if not uid: - raise ValueError( - f'Expected a non-empty value for `uid` but received {uid!r}' - ) + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return self._get( path_template("/agent/identities/{uid}", uid=uid), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=AgentResponse, ) + class AsyncAgentResource(AsyncAPIResource): """Operations for running and managing cloud agents""" + @cached_property def with_raw_response(self) -> AsyncAgentResourceWithRawResponse: """ @@ -344,26 +359,28 @@ def with_streaming_response(self) -> AsyncAgentResourceWithStreamingResponse: """ return AsyncAgentResourceWithStreamingResponse(self) - async def create(self, - *, - name: str, - base_harness: Optional[str] | Omit = omit, - base_model: Optional[str] | Omit = omit, - description: Optional[str] | Omit = omit, - environment_id: Optional[str] | Omit = omit, - harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, - inference_providers: agent_create_params.InferenceProviders | Omit = omit, - mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, - memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, - prompt: Optional[str] | Omit = omit, - secrets: Iterable[agent_create_params.Secret] | Omit = omit, - skills: SequenceNotStr[str] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentResponse: + async def create( + self, + *, + name: str, + base_harness: Optional[str] | Omit = omit, + base_model: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, + environment_id: Optional[str] | Omit = omit, + harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, + inference_providers: agent_create_params.InferenceProviders | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, + memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, + prompt: Optional[str] | Omit = omit, + secrets: Iterable[agent_create_params.Secret] | Omit = omit, + skills: SequenceNotStr[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: """Create a new agent for the caller's team. Agents can be used as the execution @@ -416,45 +433,52 @@ async def create(self, """ return await self._post( "/agent/identities", - body=await async_maybe_transform({ - "name": name, - "base_harness": base_harness, - "base_model": base_model, - "description": description, - "environment_id": environment_id, - "harness_auth_secrets": harness_auth_secrets, - "inference_providers": inference_providers, - "mcp_servers": mcp_servers, - "memory_stores": memory_stores, - "prompt": prompt, - "secrets": secrets, - "skills": skills, - }, agent_create_params.AgentCreateParams), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + body=await async_maybe_transform( + { + "name": name, + "base_harness": base_harness, + "base_model": base_model, + "description": description, + "environment_id": environment_id, + "harness_auth_secrets": harness_auth_secrets, + "inference_providers": inference_providers, + "mcp_servers": mcp_servers, + "memory_stores": memory_stores, + "prompt": prompt, + "secrets": secrets, + "skills": skills, + }, + agent_create_params.AgentCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=AgentResponse, ) - async def update(self, - uid: str, - *, - base_harness: Optional[str] | Omit = omit, - base_model: Optional[str] | Omit = omit, - description: Optional[str] | Omit = omit, - environment_id: Optional[str] | Omit = omit, - harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, - inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, - mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, - memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, - name: str | Omit = omit, - prompt: Optional[str] | Omit = omit, - secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, - skills: Optional[SequenceNotStr[str]] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentResponse: + async def update( + self, + uid: str, + *, + base_harness: Optional[str] | Omit = omit, + base_model: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, + environment_id: Optional[str] | Omit = omit, + harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, + inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, + memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, + name: str | Omit = omit, + prompt: Optional[str] | Omit = omit, + secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, + skills: Optional[SequenceNotStr[str]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: """Update an existing agent. Args: @@ -504,37 +528,42 @@ async def update(self, timeout: Override the client-level default timeout for this request, in seconds """ if not uid: - raise ValueError( - f'Expected a non-empty value for `uid` but received {uid!r}' - ) + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return await self._put( path_template("/agent/identities/{uid}", uid=uid), - body=await async_maybe_transform({ - "base_harness": base_harness, - "base_model": base_model, - "description": description, - "environment_id": environment_id, - "harness_auth_secrets": harness_auth_secrets, - "inference_providers": inference_providers, - "mcp_servers": mcp_servers, - "memory_stores": memory_stores, - "name": name, - "prompt": prompt, - "secrets": secrets, - "skills": skills, - }, agent_update_params.AgentUpdateParams), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + body=await async_maybe_transform( + { + "base_harness": base_harness, + "base_model": base_model, + "description": description, + "environment_id": environment_id, + "harness_auth_secrets": harness_auth_secrets, + "inference_providers": inference_providers, + "mcp_servers": mcp_servers, + "memory_stores": memory_stores, + "name": name, + "prompt": prompt, + "secrets": secrets, + "skills": skills, + }, + agent_update_params.AgentUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=AgentResponse, ) - async def list(self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ListAgentIdentitiesResponse: + async def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ListAgentIdentitiesResponse: """List all agents for the caller's team. Each agent includes an `available` flag @@ -542,19 +571,23 @@ async def list(self, """ return await self._get( "/agent/identities", - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ListAgentIdentitiesResponse, ) - async def delete(self, - uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> None: + async def delete( + self, + uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: """Delete an agent. All API keys associated with the agent are deleted atomically. @@ -569,25 +602,27 @@ async def delete(self, timeout: Override the client-level default timeout for this request, in seconds """ if not uid: - raise ValueError( - f'Expected a non-empty value for `uid` but received {uid!r}' - ) + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._delete( path_template("/agent/identities/{uid}", uid=uid), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=NoneType, ) - async def get(self, - uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AgentResponse: + async def get( + self, + uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: """Retrieve a single agent by its unique identifier. The response includes an @@ -604,15 +639,16 @@ async def get(self, timeout: Override the client-level default timeout for this request, in seconds """ if not uid: - raise ValueError( - f'Expected a non-empty value for `uid` but received {uid!r}' - ) + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return await self._get( path_template("/agent/identities/{uid}", uid=uid), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=AgentResponse, ) + class AgentResourceWithRawResponse: def __init__(self, agent: AgentResource) -> None: self._agent = agent @@ -633,6 +669,7 @@ def __init__(self, agent: AgentResource) -> None: agent.get, ) + class AsyncAgentResourceWithRawResponse: def __init__(self, agent: AsyncAgentResource) -> None: self._agent = agent @@ -653,6 +690,7 @@ def __init__(self, agent: AsyncAgentResource) -> None: agent.get, ) + class AgentResourceWithStreamingResponse: def __init__(self, agent: AgentResource) -> None: self._agent = agent @@ -673,6 +711,7 @@ def __init__(self, agent: AgentResource) -> None: agent.get, ) + class AsyncAgentResourceWithStreamingResponse: def __init__(self, agent: AsyncAgentResource) -> None: self._agent = agent @@ -691,4 +730,4 @@ def __init__(self, agent: AsyncAgentResource) -> None: ) self.get = async_to_streamed_response_wrapper( agent.get, - ) \ No newline at end of file + ) diff --git a/src/oz_agent_sdk/resources/agent/conversations.py b/src/oz_agent_sdk/resources/agent/conversations.py index d131c80..2525916 100644 --- a/src/oz_agent_sdk/resources/agent/conversations.py +++ b/src/oz_agent_sdk/resources/agent/conversations.py @@ -4,27 +4,25 @@ import httpx -from ..._resource import SyncAPIResource, AsyncAPIResource - -from ..._compat import cached_property - +from ..._types import Body, Query, Headers, NotGiven, not_given from ..._utils import path_template - -from ...types.agent.conversation_check_redirect_response import ConversationCheckRedirectResponse - +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) from ..._base_client import make_request_options - -from ..._types import NotGiven - -from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper, to_streamed_response_wrapper, async_to_streamed_response_wrapper - -from typing_extensions import Literal, overload -from ..._types import Timeout, Headers, NotGiven, not_given, Omit, omit, NoneType, Query, Body +from ...types.agent.conversation_check_redirect_response import ConversationCheckRedirectResponse __all__ = ["ConversationsResource", "AsyncConversationsResource"] + class ConversationsResource(SyncAPIResource): """Operations for running and managing cloud agents""" + @cached_property def with_raw_response(self) -> ConversationsResourceWithRawResponse: """ @@ -44,15 +42,17 @@ def with_streaming_response(self) -> ConversationsResourceWithStreamingResponse: """ return ConversationsResourceWithStreamingResponse(self) - def check_redirect(self, - conversation_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ConversationCheckRedirectResponse: + def check_redirect( + self, + conversation_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ConversationCheckRedirectResponse: """Check whether a conversation should redirect to a live shared session. Returns a @@ -73,17 +73,23 @@ def check_redirect(self, timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: - raise ValueError( - f'Expected a non-empty value for `conversation_id` but received {conversation_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") return self._get( path_template("/agent/conversations/{conversation_id}/redirect", conversation_id=conversation_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, security={}), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + security={}, + ), cast_to=ConversationCheckRedirectResponse, ) + class AsyncConversationsResource(AsyncAPIResource): """Operations for running and managing cloud agents""" + @cached_property def with_raw_response(self) -> AsyncConversationsResourceWithRawResponse: """ @@ -103,15 +109,17 @@ def with_streaming_response(self) -> AsyncConversationsResourceWithStreamingResp """ return AsyncConversationsResourceWithStreamingResponse(self) - async def check_redirect(self, - conversation_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ConversationCheckRedirectResponse: + async def check_redirect( + self, + conversation_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ConversationCheckRedirectResponse: """Check whether a conversation should redirect to a live shared session. Returns a @@ -132,15 +140,20 @@ async def check_redirect(self, timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: - raise ValueError( - f'Expected a non-empty value for `conversation_id` but received {conversation_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") return await self._get( path_template("/agent/conversations/{conversation_id}/redirect", conversation_id=conversation_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, security={}), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + security={}, + ), cast_to=ConversationCheckRedirectResponse, ) + class ConversationsResourceWithRawResponse: def __init__(self, conversations: ConversationsResource) -> None: self._conversations = conversations @@ -149,6 +162,7 @@ def __init__(self, conversations: ConversationsResource) -> None: conversations.check_redirect, ) + class AsyncConversationsResourceWithRawResponse: def __init__(self, conversations: AsyncConversationsResource) -> None: self._conversations = conversations @@ -157,6 +171,7 @@ def __init__(self, conversations: AsyncConversationsResource) -> None: conversations.check_redirect, ) + class ConversationsResourceWithStreamingResponse: def __init__(self, conversations: ConversationsResource) -> None: self._conversations = conversations @@ -165,10 +180,11 @@ def __init__(self, conversations: ConversationsResource) -> None: conversations.check_redirect, ) + class AsyncConversationsResourceWithStreamingResponse: def __init__(self, conversations: AsyncConversationsResource) -> None: self._conversations = conversations self.check_redirect = async_to_streamed_response_wrapper( conversations.check_redirect, - ) \ No newline at end of file + ) diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index d916323..fa745d3 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -2,48 +2,36 @@ from __future__ import annotations -import httpx - -from ..._resource import SyncAPIResource, AsyncAPIResource +from typing import List, Union +from datetime import datetime +from typing_extensions import Literal -from ..._compat import cached_property +import httpx +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import path_template, maybe_transform, async_maybe_transform - -from ...types.agent.run_item import RunItem - -from ..._base_client import make_request_options, AsyncPaginator - -from ..._types import NotGiven, Omit, omit - +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) from ...pagination import SyncRunsCursorPage, AsyncRunsCursorPage - -from typing_extensions import Literal - -from typing import Union, List - -from datetime import datetime - -from ...types.agent.run_source_type import RunSourceType - +from ...types.agent import RunSourceType, run_list_params, run_submit_followup_params +from ..._base_client import AsyncPaginator, make_request_options +from ...types.agent.run_item import RunItem from ...types.agent.run_state import RunState - -from ...types.agent.run_cancel_response import RunCancelResponse - +from ...types.agent.run_source_type import RunSourceType from ...types.agent.run_list_handoff_attachments_response import RunListHandoffAttachmentsResponse -from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper, to_streamed_response_wrapper, async_to_streamed_response_wrapper - -from typing_extensions import Literal, overload -from ..._types import Timeout, Headers, NotGiven, not_given, Omit, omit, NoneType, Query, Body -from ...types.agent import run_list_params -from ...types.agent import run_submit_followup_params -from ...types.agent import RunSourceType - __all__ = ["RunsResource", "AsyncRunsResource"] + class RunsResource(SyncAPIResource): """Operations for running and managing cloud agents""" + @cached_property def with_raw_response(self) -> RunsResourceWithRawResponse: """ @@ -63,15 +51,17 @@ def with_streaming_response(self) -> RunsResourceWithStreamingResponse: """ return RunsResourceWithStreamingResponse(self) - def retrieve(self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> RunItem: + def retrieve( + self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RunItem: """ Retrieve detailed information about a specific agent run, including the full prompt, session link, and resolved configuration. @@ -86,44 +76,46 @@ def retrieve(self, timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError( - f'Expected a non-empty value for `run_id` but received {run_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return self._get( path_template("/agent/runs/{run_id}", run_id=run_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=RunItem, ) - def list(self, - *, - ancestor_run_id: str | Omit = omit, - artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, - created_after: Union[str, datetime] | Omit = omit, - created_before: Union[str, datetime] | Omit = omit, - creator: str | Omit = omit, - cursor: str | Omit = omit, - environment_id: str | Omit = omit, - execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, - executor: str | Omit = omit, - limit: int | Omit = omit, - model_id: str | Omit = omit, - name: str | Omit = omit, - q: str | Omit = omit, - schedule_id: str | Omit = omit, - skill: str | Omit = omit, - skill_spec: str | Omit = omit, - sort_by: Literal["updated_at", "created_at", "title", "agent"] | Omit = omit, - sort_order: Literal["asc", "desc"] | Omit = omit, - source: RunSourceType | Omit = omit, - state: List[RunState] | Omit = omit, - updated_after: Union[str, datetime] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> SyncRunsCursorPage[RunItem]: + def list( + self, + *, + ancestor_run_id: str | Omit = omit, + artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, + created_after: Union[str, datetime] | Omit = omit, + created_before: Union[str, datetime] | Omit = omit, + creator: str | Omit = omit, + cursor: str | Omit = omit, + environment_id: str | Omit = omit, + execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, + executor: str | Omit = omit, + limit: int | Omit = omit, + model_id: str | Omit = omit, + name: str | Omit = omit, + q: str | Omit = omit, + schedule_id: str | Omit = omit, + skill: str | Omit = omit, + skill_spec: str | Omit = omit, + sort_by: Literal["updated_at", "created_at", "title", "agent"] | Omit = omit, + sort_order: Literal["asc", "desc"] | Omit = omit, + source: RunSourceType | Omit = omit, + state: List[RunState] | Omit = omit, + updated_after: Union[str, datetime] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SyncRunsCursorPage[RunItem]: """Retrieve a paginated list of agent runs with optional filtering. Results default @@ -191,42 +183,53 @@ def list(self, """ return self._get_api_list( "/agent/runs", - page = SyncRunsCursorPage[RunItem], - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({ - "ancestor_run_id": ancestor_run_id, - "artifact_type": artifact_type, - "created_after": created_after, - "created_before": created_before, - "creator": creator, - "cursor": cursor, - "environment_id": environment_id, - "execution_location": execution_location, - "executor": executor, - "limit": limit, - "model_id": model_id, - "name": name, - "q": q, - "schedule_id": schedule_id, - "skill": skill, - "skill_spec": skill_spec, - "sort_by": sort_by, - "sort_order": sort_order, - "source": source, - "state": state, - "updated_after": updated_after, - }, run_list_params.RunListParams)), + page=SyncRunsCursorPage[RunItem], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "ancestor_run_id": ancestor_run_id, + "artifact_type": artifact_type, + "created_after": created_after, + "created_before": created_before, + "creator": creator, + "cursor": cursor, + "environment_id": environment_id, + "execution_location": execution_location, + "executor": executor, + "limit": limit, + "model_id": model_id, + "name": name, + "q": q, + "schedule_id": schedule_id, + "skill": skill, + "skill_spec": skill_spec, + "sort_by": sort_by, + "sort_order": sort_order, + "source": source, + "state": state, + "updated_after": updated_after, + }, + run_list_params.RunListParams, + ), + ), model=RunItem, ) - def cancel(self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> str: + def cancel( + self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> str: """Cancel an agent run that is currently queued or in progress. Once cancelled, the @@ -246,24 +249,26 @@ def cancel(self, timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError( - f'Expected a non-empty value for `run_id` but received {run_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return self._post( path_template("/agent/runs/{run_id}/cancel", run_id=run_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=str, ) - def list_handoff_attachments(self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> RunListHandoffAttachmentsResponse: + def list_handoff_attachments( + self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RunListHandoffAttachmentsResponse: """ Return fresh presigned download URLs for handoff snapshot files uploaded by the latest ended execution of this run. An empty list is returned when no ended @@ -283,26 +288,28 @@ def list_handoff_attachments(self, timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError( - f'Expected a non-empty value for `run_id` but received {run_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return self._get( path_template("/agent/runs/{run_id}/handoff/attachments", run_id=run_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=RunListHandoffAttachmentsResponse, ) - def submit_followup(self, - run_id: str, - *, - message: str | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> object: + def submit_followup( + self, + run_id: str, + *, + message: str | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> object: """Send a follow-up message to an existing run. The server transparently routes the @@ -325,21 +332,26 @@ def submit_followup(self, timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError( - f'Expected a non-empty value for `run_id` but received {run_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return self._post( path_template("/agent/runs/{run_id}/followups", run_id=run_id), - body=maybe_transform({ - "message": message, - "mode": mode, - }, run_submit_followup_params.RunSubmitFollowupParams), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + body=maybe_transform( + { + "message": message, + "mode": mode, + }, + run_submit_followup_params.RunSubmitFollowupParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=object, ) + class AsyncRunsResource(AsyncAPIResource): """Operations for running and managing cloud agents""" + @cached_property def with_raw_response(self) -> AsyncRunsResourceWithRawResponse: """ @@ -359,15 +371,17 @@ def with_streaming_response(self) -> AsyncRunsResourceWithStreamingResponse: """ return AsyncRunsResourceWithStreamingResponse(self) - async def retrieve(self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> RunItem: + async def retrieve( + self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RunItem: """ Retrieve detailed information about a specific agent run, including the full prompt, session link, and resolved configuration. @@ -382,44 +396,46 @@ async def retrieve(self, timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError( - f'Expected a non-empty value for `run_id` but received {run_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return await self._get( path_template("/agent/runs/{run_id}", run_id=run_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=RunItem, ) - def list(self, - *, - ancestor_run_id: str | Omit = omit, - artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, - created_after: Union[str, datetime] | Omit = omit, - created_before: Union[str, datetime] | Omit = omit, - creator: str | Omit = omit, - cursor: str | Omit = omit, - environment_id: str | Omit = omit, - execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, - executor: str | Omit = omit, - limit: int | Omit = omit, - model_id: str | Omit = omit, - name: str | Omit = omit, - q: str | Omit = omit, - schedule_id: str | Omit = omit, - skill: str | Omit = omit, - skill_spec: str | Omit = omit, - sort_by: Literal["updated_at", "created_at", "title", "agent"] | Omit = omit, - sort_order: Literal["asc", "desc"] | Omit = omit, - source: RunSourceType | Omit = omit, - state: List[RunState] | Omit = omit, - updated_after: Union[str, datetime] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> AsyncPaginator[RunItem, AsyncRunsCursorPage[RunItem]]: + def list( + self, + *, + ancestor_run_id: str | Omit = omit, + artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, + created_after: Union[str, datetime] | Omit = omit, + created_before: Union[str, datetime] | Omit = omit, + creator: str | Omit = omit, + cursor: str | Omit = omit, + environment_id: str | Omit = omit, + execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, + executor: str | Omit = omit, + limit: int | Omit = omit, + model_id: str | Omit = omit, + name: str | Omit = omit, + q: str | Omit = omit, + schedule_id: str | Omit = omit, + skill: str | Omit = omit, + skill_spec: str | Omit = omit, + sort_by: Literal["updated_at", "created_at", "title", "agent"] | Omit = omit, + sort_order: Literal["asc", "desc"] | Omit = omit, + source: RunSourceType | Omit = omit, + state: List[RunState] | Omit = omit, + updated_after: Union[str, datetime] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncPaginator[RunItem, AsyncRunsCursorPage[RunItem]]: """Retrieve a paginated list of agent runs with optional filtering. Results default @@ -487,42 +503,53 @@ def list(self, """ return self._get_api_list( "/agent/runs", - page = AsyncRunsCursorPage[RunItem], - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({ - "ancestor_run_id": ancestor_run_id, - "artifact_type": artifact_type, - "created_after": created_after, - "created_before": created_before, - "creator": creator, - "cursor": cursor, - "environment_id": environment_id, - "execution_location": execution_location, - "executor": executor, - "limit": limit, - "model_id": model_id, - "name": name, - "q": q, - "schedule_id": schedule_id, - "skill": skill, - "skill_spec": skill_spec, - "sort_by": sort_by, - "sort_order": sort_order, - "source": source, - "state": state, - "updated_after": updated_after, - }, run_list_params.RunListParams)), + page=AsyncRunsCursorPage[RunItem], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "ancestor_run_id": ancestor_run_id, + "artifact_type": artifact_type, + "created_after": created_after, + "created_before": created_before, + "creator": creator, + "cursor": cursor, + "environment_id": environment_id, + "execution_location": execution_location, + "executor": executor, + "limit": limit, + "model_id": model_id, + "name": name, + "q": q, + "schedule_id": schedule_id, + "skill": skill, + "skill_spec": skill_spec, + "sort_by": sort_by, + "sort_order": sort_order, + "source": source, + "state": state, + "updated_after": updated_after, + }, + run_list_params.RunListParams, + ), + ), model=RunItem, ) - async def cancel(self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> str: + async def cancel( + self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> str: """Cancel an agent run that is currently queued or in progress. Once cancelled, the @@ -542,24 +569,26 @@ async def cancel(self, timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError( - f'Expected a non-empty value for `run_id` but received {run_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return await self._post( path_template("/agent/runs/{run_id}/cancel", run_id=run_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=str, ) - async def list_handoff_attachments(self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> RunListHandoffAttachmentsResponse: + async def list_handoff_attachments( + self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RunListHandoffAttachmentsResponse: """ Return fresh presigned download URLs for handoff snapshot files uploaded by the latest ended execution of this run. An empty list is returned when no ended @@ -579,26 +608,28 @@ async def list_handoff_attachments(self, timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError( - f'Expected a non-empty value for `run_id` but received {run_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return await self._get( path_template("/agent/runs/{run_id}/handoff/attachments", run_id=run_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=RunListHandoffAttachmentsResponse, ) - async def submit_followup(self, - run_id: str, - *, - message: str | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> object: + async def submit_followup( + self, + run_id: str, + *, + message: str | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> object: """Send a follow-up message to an existing run. The server transparently routes the @@ -621,19 +652,23 @@ async def submit_followup(self, timeout: Override the client-level default timeout for this request, in seconds """ if not run_id: - raise ValueError( - f'Expected a non-empty value for `run_id` but received {run_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return await self._post( path_template("/agent/runs/{run_id}/followups", run_id=run_id), - body=await async_maybe_transform({ - "message": message, - "mode": mode, - }, run_submit_followup_params.RunSubmitFollowupParams), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + body=await async_maybe_transform( + { + "message": message, + "mode": mode, + }, + run_submit_followup_params.RunSubmitFollowupParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=object, ) + class RunsResourceWithRawResponse: def __init__(self, runs: RunsResource) -> None: self._runs = runs @@ -654,6 +689,7 @@ def __init__(self, runs: RunsResource) -> None: runs.submit_followup, ) + class AsyncRunsResourceWithRawResponse: def __init__(self, runs: AsyncRunsResource) -> None: self._runs = runs @@ -674,6 +710,7 @@ def __init__(self, runs: AsyncRunsResource) -> None: runs.submit_followup, ) + class RunsResourceWithStreamingResponse: def __init__(self, runs: RunsResource) -> None: self._runs = runs @@ -694,6 +731,7 @@ def __init__(self, runs: RunsResource) -> None: runs.submit_followup, ) + class AsyncRunsResourceWithStreamingResponse: def __init__(self, runs: AsyncRunsResource) -> None: self._runs = runs @@ -712,4 +750,4 @@ def __init__(self, runs: AsyncRunsResource) -> None: ) self.submit_followup = async_to_streamed_response_wrapper( runs.submit_followup, - ) \ No newline at end of file + ) diff --git a/src/oz_agent_sdk/resources/agent/schedules.py b/src/oz_agent_sdk/resources/agent/schedules.py index 75daa91..67eaab9 100644 --- a/src/oz_agent_sdk/resources/agent/schedules.py +++ b/src/oz_agent_sdk/resources/agent/schedules.py @@ -2,41 +2,33 @@ from __future__ import annotations -import httpx +from typing_extensions import Literal -from ..._resource import SyncAPIResource, AsyncAPIResource +import httpx +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property - -from ...types.agent.scheduled_agent_item import ScheduledAgentItem - -from ..._utils import maybe_transform, path_template, async_maybe_transform - +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...types.agent import schedule_create_params, schedule_update_params from ..._base_client import make_request_options - +from ...types.agent.scheduled_agent_item import ScheduledAgentItem from ...types.ambient_agent_config_param import AmbientAgentConfigParam - -from ..._types import Omit, omit, NotGiven - -from typing_extensions import Literal - from ...types.agent.schedule_list_response import ScheduleListResponse - from ...types.agent.schedule_delete_response import ScheduleDeleteResponse -from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper, to_streamed_response_wrapper, async_to_streamed_response_wrapper - -from typing_extensions import Literal, overload -from ..._types import Timeout, Headers, NotGiven, not_given, Omit, omit, NoneType, Query, Body -from ...types.agent import schedule_create_params -from ...types.agent import schedule_update_params -from ...types import AmbientAgentConfig -from ...types import AmbientAgentConfig - __all__ = ["SchedulesResource", "AsyncSchedulesResource"] + class SchedulesResource(SyncAPIResource): """Operations for creating and managing scheduled agents""" + @cached_property def with_raw_response(self) -> SchedulesResourceWithRawResponse: """ @@ -56,22 +48,24 @@ def with_streaming_response(self) -> SchedulesResourceWithStreamingResponse: """ return SchedulesResourceWithStreamingResponse(self) - def create(self, - *, - cron_schedule: str, - name: str, - agent_config: AmbientAgentConfigParam | Omit = omit, - agent_uid: str | Omit = omit, - enabled: bool | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - prompt: str | Omit = omit, - team: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: + def create( + self, + *, + cron_schedule: str, + name: str, + agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, + enabled: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + prompt: str | Omit = omit, + team: bool | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduledAgentItem: """Create a new scheduled agent that runs on a cron schedule. The agent will be @@ -109,29 +103,36 @@ def create(self, """ return self._post( "/agent/schedules", - body=maybe_transform({ - "cron_schedule": cron_schedule, - "name": name, - "agent_config": agent_config, - "agent_uid": agent_uid, - "enabled": enabled, - "mode": mode, - "prompt": prompt, - "team": team, - }, schedule_create_params.ScheduleCreateParams), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + body=maybe_transform( + { + "cron_schedule": cron_schedule, + "name": name, + "agent_config": agent_config, + "agent_uid": agent_uid, + "enabled": enabled, + "mode": mode, + "prompt": prompt, + "team": team, + }, + schedule_create_params.ScheduleCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduledAgentItem, ) - def retrieve(self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: + def retrieve( + self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduledAgentItem: """ Retrieve detailed information about a specific scheduled agent, including its configuration, history, and next scheduled run time. @@ -146,31 +147,33 @@ def retrieve(self, timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError( - f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") return self._get( path_template("/agent/schedules/{schedule_id}", schedule_id=schedule_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduledAgentItem, ) - def update(self, - schedule_id: str, - *, - cron_schedule: str, - enabled: bool, - name: str, - agent_config: AmbientAgentConfigParam | Omit = omit, - agent_uid: str | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - prompt: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: + def update( + self, + schedule_id: str, + *, + cron_schedule: str, + enabled: bool, + name: str, + agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + prompt: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduledAgentItem: """Update an existing scheduled agent's configuration. All fields except @@ -203,32 +206,37 @@ def update(self, timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError( - f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") return self._put( path_template("/agent/schedules/{schedule_id}", schedule_id=schedule_id), - body=maybe_transform({ - "cron_schedule": cron_schedule, - "enabled": enabled, - "name": name, - "agent_config": agent_config, - "agent_uid": agent_uid, - "mode": mode, - "prompt": prompt, - }, schedule_update_params.ScheduleUpdateParams), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + body=maybe_transform( + { + "cron_schedule": cron_schedule, + "enabled": enabled, + "name": name, + "agent_config": agent_config, + "agent_uid": agent_uid, + "mode": mode, + "prompt": prompt, + }, + schedule_update_params.ScheduleUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduledAgentItem, ) - def list(self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduleListResponse: + def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleListResponse: """Retrieve all scheduled agents accessible to the authenticated user. Results are @@ -236,19 +244,23 @@ def list(self, """ return self._get( "/agent/schedules", - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduleListResponse, ) - def delete(self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduleDeleteResponse: + def delete( + self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleDeleteResponse: """Delete a scheduled agent. This will stop all future scheduled runs. @@ -263,24 +275,26 @@ def delete(self, timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError( - f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") return self._delete( path_template("/agent/schedules/{schedule_id}", schedule_id=schedule_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduleDeleteResponse, ) - def pause(self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: + def pause( + self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduledAgentItem: """Pause a scheduled agent. The agent will not run until resumed. @@ -295,24 +309,26 @@ def pause(self, timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError( - f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") return self._post( path_template("/agent/schedules/{schedule_id}/pause", schedule_id=schedule_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduledAgentItem, ) - def resume(self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: + def resume( + self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduledAgentItem: """Resume a paused scheduled agent. The agent will start running according to its @@ -328,17 +344,19 @@ def resume(self, timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError( - f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") return self._post( path_template("/agent/schedules/{schedule_id}/resume", schedule_id=schedule_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduledAgentItem, ) + class AsyncSchedulesResource(AsyncAPIResource): """Operations for creating and managing scheduled agents""" + @cached_property def with_raw_response(self) -> AsyncSchedulesResourceWithRawResponse: """ @@ -358,22 +376,24 @@ def with_streaming_response(self) -> AsyncSchedulesResourceWithStreamingResponse """ return AsyncSchedulesResourceWithStreamingResponse(self) - async def create(self, - *, - cron_schedule: str, - name: str, - agent_config: AmbientAgentConfigParam | Omit = omit, - agent_uid: str | Omit = omit, - enabled: bool | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - prompt: str | Omit = omit, - team: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: + async def create( + self, + *, + cron_schedule: str, + name: str, + agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, + enabled: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + prompt: str | Omit = omit, + team: bool | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduledAgentItem: """Create a new scheduled agent that runs on a cron schedule. The agent will be @@ -411,29 +431,36 @@ async def create(self, """ return await self._post( "/agent/schedules", - body=await async_maybe_transform({ - "cron_schedule": cron_schedule, - "name": name, - "agent_config": agent_config, - "agent_uid": agent_uid, - "enabled": enabled, - "mode": mode, - "prompt": prompt, - "team": team, - }, schedule_create_params.ScheduleCreateParams), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + body=await async_maybe_transform( + { + "cron_schedule": cron_schedule, + "name": name, + "agent_config": agent_config, + "agent_uid": agent_uid, + "enabled": enabled, + "mode": mode, + "prompt": prompt, + "team": team, + }, + schedule_create_params.ScheduleCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduledAgentItem, ) - async def retrieve(self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: + async def retrieve( + self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduledAgentItem: """ Retrieve detailed information about a specific scheduled agent, including its configuration, history, and next scheduled run time. @@ -448,31 +475,33 @@ async def retrieve(self, timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError( - f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") return await self._get( path_template("/agent/schedules/{schedule_id}", schedule_id=schedule_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduledAgentItem, ) - async def update(self, - schedule_id: str, - *, - cron_schedule: str, - enabled: bool, - name: str, - agent_config: AmbientAgentConfigParam | Omit = omit, - agent_uid: str | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, - prompt: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: + async def update( + self, + schedule_id: str, + *, + cron_schedule: str, + enabled: bool, + name: str, + agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, + prompt: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduledAgentItem: """Update an existing scheduled agent's configuration. All fields except @@ -505,32 +534,37 @@ async def update(self, timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError( - f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") return await self._put( path_template("/agent/schedules/{schedule_id}", schedule_id=schedule_id), - body=await async_maybe_transform({ - "cron_schedule": cron_schedule, - "enabled": enabled, - "name": name, - "agent_config": agent_config, - "agent_uid": agent_uid, - "mode": mode, - "prompt": prompt, - }, schedule_update_params.ScheduleUpdateParams), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + body=await async_maybe_transform( + { + "cron_schedule": cron_schedule, + "enabled": enabled, + "name": name, + "agent_config": agent_config, + "agent_uid": agent_uid, + "mode": mode, + "prompt": prompt, + }, + schedule_update_params.ScheduleUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduledAgentItem, ) - async def list(self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduleListResponse: + async def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleListResponse: """Retrieve all scheduled agents accessible to the authenticated user. Results are @@ -538,19 +572,23 @@ async def list(self, """ return await self._get( "/agent/schedules", - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduleListResponse, ) - async def delete(self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduleDeleteResponse: + async def delete( + self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleDeleteResponse: """Delete a scheduled agent. This will stop all future scheduled runs. @@ -565,24 +603,26 @@ async def delete(self, timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError( - f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") return await self._delete( path_template("/agent/schedules/{schedule_id}", schedule_id=schedule_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduleDeleteResponse, ) - async def pause(self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: + async def pause( + self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduledAgentItem: """Pause a scheduled agent. The agent will not run until resumed. @@ -597,24 +637,26 @@ async def pause(self, timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError( - f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") return await self._post( path_template("/agent/schedules/{schedule_id}/pause", schedule_id=schedule_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduledAgentItem, ) - async def resume(self, - schedule_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> ScheduledAgentItem: + async def resume( + self, + schedule_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduledAgentItem: """Resume a paused scheduled agent. The agent will start running according to its @@ -630,15 +672,16 @@ async def resume(self, timeout: Override the client-level default timeout for this request, in seconds """ if not schedule_id: - raise ValueError( - f'Expected a non-empty value for `schedule_id` but received {schedule_id!r}' - ) + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") return await self._post( path_template("/agent/schedules/{schedule_id}/resume", schedule_id=schedule_id), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), cast_to=ScheduledAgentItem, ) + class SchedulesResourceWithRawResponse: def __init__(self, schedules: SchedulesResource) -> None: self._schedules = schedules @@ -665,6 +708,7 @@ def __init__(self, schedules: SchedulesResource) -> None: schedules.resume, ) + class AsyncSchedulesResourceWithRawResponse: def __init__(self, schedules: AsyncSchedulesResource) -> None: self._schedules = schedules @@ -691,6 +735,7 @@ def __init__(self, schedules: AsyncSchedulesResource) -> None: schedules.resume, ) + class SchedulesResourceWithStreamingResponse: def __init__(self, schedules: SchedulesResource) -> None: self._schedules = schedules @@ -717,6 +762,7 @@ def __init__(self, schedules: SchedulesResource) -> None: schedules.resume, ) + class AsyncSchedulesResourceWithStreamingResponse: def __init__(self, schedules: AsyncSchedulesResource) -> None: self._schedules = schedules @@ -741,4 +787,4 @@ def __init__(self, schedules: AsyncSchedulesResource) -> None: ) self.resume = async_to_streamed_response_wrapper( schedules.resume, - ) \ No newline at end of file + ) diff --git a/src/oz_agent_sdk/resources/agent/sessions.py b/src/oz_agent_sdk/resources/agent/sessions.py index fff5e27..d704bd6 100644 --- a/src/oz_agent_sdk/resources/agent/sessions.py +++ b/src/oz_agent_sdk/resources/agent/sessions.py @@ -4,27 +4,25 @@ import httpx -from ..._resource import SyncAPIResource, AsyncAPIResource - -from ..._compat import cached_property - +from ..._types import Body, Query, Headers, NotGiven, not_given from ..._utils import path_template - -from ...types.agent.session_check_redirect_response import SessionCheckRedirectResponse - +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) from ..._base_client import make_request_options - -from ..._types import NotGiven - -from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper, to_streamed_response_wrapper, async_to_streamed_response_wrapper - -from typing_extensions import Literal, overload -from ..._types import Timeout, Headers, NotGiven, not_given, Omit, omit, NoneType, Query, Body +from ...types.agent.session_check_redirect_response import SessionCheckRedirectResponse __all__ = ["SessionsResource", "AsyncSessionsResource"] + class SessionsResource(SyncAPIResource): """Operations for running and managing cloud agents""" + @cached_property def with_raw_response(self) -> SessionsResourceWithRawResponse: """ @@ -44,15 +42,17 @@ def with_streaming_response(self) -> SessionsResourceWithStreamingResponse: """ return SessionsResourceWithStreamingResponse(self) - def check_redirect(self, - session_uuid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> SessionCheckRedirectResponse: + def check_redirect( + self, + session_uuid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SessionCheckRedirectResponse: """ Check whether a shared session should redirect to a conversation transcript. Returns a conversation_id if the agent sandbox has finished and conversation @@ -72,17 +72,23 @@ def check_redirect(self, timeout: Override the client-level default timeout for this request, in seconds """ if not session_uuid: - raise ValueError( - f'Expected a non-empty value for `session_uuid` but received {session_uuid!r}' - ) + raise ValueError(f"Expected a non-empty value for `session_uuid` but received {session_uuid!r}") return self._get( path_template("/agent/sessions/{session_uuid}/redirect", session_uuid=session_uuid), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, security={}), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + security={}, + ), cast_to=SessionCheckRedirectResponse, ) + class AsyncSessionsResource(AsyncAPIResource): """Operations for running and managing cloud agents""" + @cached_property def with_raw_response(self) -> AsyncSessionsResourceWithRawResponse: """ @@ -102,15 +108,17 @@ def with_streaming_response(self) -> AsyncSessionsResourceWithStreamingResponse: """ return AsyncSessionsResourceWithStreamingResponse(self) - async def check_redirect(self, - session_uuid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given,) -> SessionCheckRedirectResponse: + async def check_redirect( + self, + session_uuid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SessionCheckRedirectResponse: """ Check whether a shared session should redirect to a conversation transcript. Returns a conversation_id if the agent sandbox has finished and conversation @@ -130,15 +138,20 @@ async def check_redirect(self, timeout: Override the client-level default timeout for this request, in seconds """ if not session_uuid: - raise ValueError( - f'Expected a non-empty value for `session_uuid` but received {session_uuid!r}' - ) + raise ValueError(f"Expected a non-empty value for `session_uuid` but received {session_uuid!r}") return await self._get( path_template("/agent/sessions/{session_uuid}/redirect", session_uuid=session_uuid), - options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, security={}), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + security={}, + ), cast_to=SessionCheckRedirectResponse, ) + class SessionsResourceWithRawResponse: def __init__(self, sessions: SessionsResource) -> None: self._sessions = sessions @@ -147,6 +160,7 @@ def __init__(self, sessions: SessionsResource) -> None: sessions.check_redirect, ) + class AsyncSessionsResourceWithRawResponse: def __init__(self, sessions: AsyncSessionsResource) -> None: self._sessions = sessions @@ -155,6 +169,7 @@ def __init__(self, sessions: AsyncSessionsResource) -> None: sessions.check_redirect, ) + class SessionsResourceWithStreamingResponse: def __init__(self, sessions: SessionsResource) -> None: self._sessions = sessions @@ -163,10 +178,11 @@ def __init__(self, sessions: SessionsResource) -> None: sessions.check_redirect, ) + class AsyncSessionsResourceWithStreamingResponse: def __init__(self, sessions: AsyncSessionsResource) -> None: self._sessions = sessions self.check_redirect = async_to_streamed_response_wrapper( sessions.check_redirect, - ) \ No newline at end of file + ) diff --git a/src/oz_agent_sdk/types/__init__.py b/src/oz_agent_sdk/types/__init__.py index e188048..e27ca02 100644 --- a/src/oz_agent_sdk/types/__init__.py +++ b/src/oz_agent_sdk/types/__init__.py @@ -2,22 +2,22 @@ from __future__ import annotations +from .scope import Scope as Scope +from .error_code import ErrorCode as ErrorCode from .agent_skill import AgentSkill as AgentSkill -from .ambient_agent_config import AmbientAgentConfig as AmbientAgentConfig -from .ambient_agent_config_param import AmbientAgentConfigParam as AmbientAgentConfigParam -from .aws_provider_config import AwsProviderConfig as AwsProviderConfig +from .user_profile import UserProfile as UserProfile +from .agent_run_params import AgentRunParams as AgentRunParams +from .agent_list_params import AgentListParams as AgentListParams from .cloud_environment import CloudEnvironment as CloudEnvironment -from .cloud_environment_config import CloudEnvironmentConfig as CloudEnvironmentConfig -from .error_code import ErrorCode as ErrorCode -from .gcp_provider_config import GcpProviderConfig as GcpProviderConfig from .mcp_server_config import McpServerConfig as McpServerConfig -from .mcp_server_config_param import McpServerConfigParam as McpServerConfigParam -from .scope import Scope as Scope -from .user_profile import UserProfile as UserProfile +from .agent_run_response import AgentRunResponse as AgentRunResponse from .agent_list_response import AgentListResponse as AgentListResponse +from .aws_provider_config import AwsProviderConfig as AwsProviderConfig +from .gcp_provider_config import GcpProviderConfig as GcpProviderConfig +from .ambient_agent_config import AmbientAgentConfig as AmbientAgentConfig +from .mcp_server_config_param import McpServerConfigParam as McpServerConfigParam +from .cloud_environment_config import CloudEnvironmentConfig as CloudEnvironmentConfig +from .ambient_agent_config_param import AmbientAgentConfigParam as AmbientAgentConfigParam from .agent_get_artifact_response import AgentGetArtifactResponse as AgentGetArtifactResponse -from .agent_list_environments_response import AgentListEnvironmentsResponse as AgentListEnvironmentsResponse -from .agent_run_response import AgentRunResponse as AgentRunResponse -from .agent_list_params import AgentListParams as AgentListParams from .agent_list_environments_params import AgentListEnvironmentsParams as AgentListEnvironmentsParams -from .agent_run_params import AgentRunParams as AgentRunParams \ No newline at end of file +from .agent_list_environments_response import AgentListEnvironmentsResponse as AgentListEnvironmentsResponse diff --git a/src/oz_agent_sdk/types/agent/__init__.py b/src/oz_agent_sdk/types/agent/__init__.py index 6658587..07bab46 100644 --- a/src/oz_agent_sdk/types/agent/__init__.py +++ b/src/oz_agent_sdk/types/agent/__init__.py @@ -2,23 +2,25 @@ from __future__ import annotations -from .artifact_item import ArtifactItem as ArtifactItem from .run_item import RunItem as RunItem -from .run_source_type import RunSourceType as RunSourceType from .run_state import RunState as RunState -from .run_cancel_response import RunCancelResponse as RunCancelResponse -from .run_list_handoff_attachments_response import RunListHandoffAttachmentsResponse as RunListHandoffAttachmentsResponse +from .artifact_item import ArtifactItem as ArtifactItem +from .agent_response import AgentResponse as AgentResponse from .run_list_params import RunListParams as RunListParams -from .run_submit_followup_params import RunSubmitFollowupParams as RunSubmitFollowupParams -from .scheduled_agent_history_item import ScheduledAgentHistoryItem as ScheduledAgentHistoryItem +from .run_source_type import RunSourceType as RunSourceType +from .agent_create_params import AgentCreateParams as AgentCreateParams +from .agent_update_params import AgentUpdateParams as AgentUpdateParams +from .run_cancel_response import RunCancelResponse as RunCancelResponse from .scheduled_agent_item import ScheduledAgentItem as ScheduledAgentItem -from .schedule_list_response import ScheduleListResponse as ScheduleListResponse -from .schedule_delete_response import ScheduleDeleteResponse as ScheduleDeleteResponse from .schedule_create_params import ScheduleCreateParams as ScheduleCreateParams +from .schedule_list_response import ScheduleListResponse as ScheduleListResponse from .schedule_update_params import ScheduleUpdateParams as ScheduleUpdateParams -from .agent_response import AgentResponse as AgentResponse +from .schedule_delete_response import ScheduleDeleteResponse as ScheduleDeleteResponse +from .run_submit_followup_params import RunSubmitFollowupParams as RunSubmitFollowupParams +from .scheduled_agent_history_item import ScheduledAgentHistoryItem as ScheduledAgentHistoryItem from .list_agent_identities_response import ListAgentIdentitiesResponse as ListAgentIdentitiesResponse -from .agent_create_params import AgentCreateParams as AgentCreateParams -from .agent_update_params import AgentUpdateParams as AgentUpdateParams from .session_check_redirect_response import SessionCheckRedirectResponse as SessionCheckRedirectResponse -from .conversation_check_redirect_response import ConversationCheckRedirectResponse as ConversationCheckRedirectResponse \ No newline at end of file +from .conversation_check_redirect_response import ConversationCheckRedirectResponse as ConversationCheckRedirectResponse +from .run_list_handoff_attachments_response import ( + RunListHandoffAttachmentsResponse as RunListHandoffAttachmentsResponse, +) diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py index 987d525..798e05d 100644 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -2,15 +2,21 @@ from __future__ import annotations -from typing_extensions import TypedDict, Required, Literal - -from typing import Optional, Dict, Iterable +from typing import Dict, Iterable, Optional +from typing_extensions import Literal, Required, TypedDict +from ..._types import SequenceNotStr from ..mcp_server_config_param import McpServerConfigParam -from ..._types import SequenceNotStr +__all__ = [ + "AgentCreateParams", + "HarnessAuthSecrets", + "InferenceProviders", + "InferenceProvidersAws", + "MemoryStore", + "Secret", +] -__all__ = ["AgentCreateParams", "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws", "MemoryStore", "Secret"] class AgentCreateParams(TypedDict, total=False): name: Required[str] @@ -72,11 +78,13 @@ class AgentCreateParams(TypedDict, total=False): or malformed specs are rejected. """ + class HarnessAuthSecrets(TypedDict, total=False): """ Authentication secrets for third-party harnesses. Only the secret for the harness specified gets injected into the environment. """ + claude_auth_secret_name: str """ Name of a managed secret for Claude Code harness authentication. The secret must @@ -91,11 +99,13 @@ class HarnessAuthSecrets(TypedDict, total=False): "codex". """ + class InferenceProvidersAws(TypedDict, total=False): """ Configures AWS Bedrock as the LLM inference provider for this agent or run. """ + disabled: bool """If true, opt out of Bedrock at this layer.""" @@ -105,13 +115,17 @@ class InferenceProvidersAws(TypedDict, total=False): role_arn: str """IAM role ARN to assume when calling Bedrock.""" + class InferenceProviders(TypedDict, total=False): """Inference provider settings used for LLM calls.""" + aws: InferenceProvidersAws """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" + class MemoryStore(TypedDict, total=False): """Reference to a memory store to attach to an agent.""" + access: Required[Literal["read_write", "read_only"]] """Access level for the store.""" @@ -121,7 +135,9 @@ class MemoryStore(TypedDict, total=False): uid: Required[str] """UID of the memory store.""" + class Secret(TypedDict, total=False): """Reference to a managed secret by name.""" + name: Required[str] - """Name of the managed secret.""" \ No newline at end of file + """Name of the managed secret.""" diff --git a/src/oz_agent_sdk/types/agent/agent_response.py b/src/oz_agent_sdk/types/agent/agent_response.py index 68792bf..37d13b9 100644 --- a/src/oz_agent_sdk/types/agent/agent_response.py +++ b/src/oz_agent_sdk/types/agent/agent_response.py @@ -1,19 +1,25 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from ..._models import BaseModel - -from typing_extensions import Literal - -from typing import Optional, List, Dict - +from typing import Dict, List, Optional from datetime import datetime +from typing_extensions import Literal +from ..._models import BaseModel from ..mcp_server_config import McpServerConfig -__all__ = ["AgentResponse", "MemoryStore", "Secret", "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws"] +__all__ = [ + "AgentResponse", + "MemoryStore", + "Secret", + "HarnessAuthSecrets", + "InferenceProviders", + "InferenceProvidersAws", +] + class MemoryStore(BaseModel): """Reference to a memory store to attach to an agent.""" + access: Literal["read_write", "read_only"] """Access level for the store.""" @@ -23,16 +29,20 @@ class MemoryStore(BaseModel): uid: str """UID of the memory store.""" + class Secret(BaseModel): """Reference to a managed secret by name.""" + name: str """Name of the managed secret.""" + class HarnessAuthSecrets(BaseModel): """ Authentication secrets for third-party harnesses. Only the secret for the harness specified gets injected into the environment. """ + claude_auth_secret_name: Optional[str] = None """ Name of a managed secret for Claude Code harness authentication. The secret must @@ -47,11 +57,13 @@ class HarnessAuthSecrets(BaseModel): "codex". """ + class InferenceProvidersAws(BaseModel): """ Configures AWS Bedrock as the LLM inference provider for this agent or run. """ + disabled: Optional[bool] = None """If true, opt out of Bedrock at this layer.""" @@ -61,11 +73,14 @@ class InferenceProvidersAws(BaseModel): role_arn: Optional[str] = None """IAM role ARN to assume when calling Bedrock.""" + class InferenceProviders(BaseModel): """Inference provider settings used for LLM calls.""" + aws: Optional[InferenceProvidersAws] = None """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" + class AgentResponse(BaseModel): available: bool """Whether this agent is within the team's plan limit and can be used for runs""" @@ -146,4 +161,4 @@ class AgentResponse(BaseModel): """ prompt: Optional[str] = None - """Optional base prompt for this agent""" \ No newline at end of file + """Optional base prompt for this agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_update_params.py b/src/oz_agent_sdk/types/agent/agent_update_params.py index d67e417..19082d4 100644 --- a/src/oz_agent_sdk/types/agent/agent_update_params.py +++ b/src/oz_agent_sdk/types/agent/agent_update_params.py @@ -2,15 +2,21 @@ from __future__ import annotations -from typing_extensions import TypedDict, Literal, Required - -from typing import Optional, Dict, Iterable +from typing import Dict, Iterable, Optional +from typing_extensions import Literal, Required, TypedDict +from ..._types import SequenceNotStr from ..mcp_server_config_param import McpServerConfigParam -from ..._types import SequenceNotStr +__all__ = [ + "AgentUpdateParams", + "HarnessAuthSecrets", + "InferenceProviders", + "InferenceProvidersAws", + "MemoryStore", + "Secret", +] -__all__ = ["AgentUpdateParams", "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws", "MemoryStore", "Secret"] class AgentUpdateParams(TypedDict, total=False): base_harness: Optional[str] @@ -84,11 +90,13 @@ class AgentUpdateParams(TypedDict, total=False): to replace. """ + class HarnessAuthSecrets(TypedDict, total=False): """ Authentication secrets for third-party harnesses. Only the secret for the harness specified gets injected into the environment. """ + claude_auth_secret_name: str """ Name of a managed secret for Claude Code harness authentication. The secret must @@ -103,11 +111,13 @@ class HarnessAuthSecrets(TypedDict, total=False): "codex". """ + class InferenceProvidersAws(TypedDict, total=False): """ Configures AWS Bedrock as the LLM inference provider for this agent or run. """ + disabled: bool """If true, opt out of Bedrock at this layer.""" @@ -117,13 +127,17 @@ class InferenceProvidersAws(TypedDict, total=False): role_arn: str """IAM role ARN to assume when calling Bedrock.""" + class InferenceProviders(TypedDict, total=False): """Inference provider settings used for LLM calls.""" + aws: InferenceProvidersAws """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" + class MemoryStore(TypedDict, total=False): """Reference to a memory store to attach to an agent.""" + access: Required[Literal["read_write", "read_only"]] """Access level for the store.""" @@ -133,7 +147,9 @@ class MemoryStore(TypedDict, total=False): uid: Required[str] """UID of the memory store.""" + class Secret(TypedDict, total=False): """Reference to a managed secret by name.""" + name: Required[str] - """Name of the managed secret.""" \ No newline at end of file + """Name of the managed secret.""" diff --git a/src/oz_agent_sdk/types/agent/artifact_item.py b/src/oz_agent_sdk/types/agent/artifact_item.py index 226a754..437b857 100644 --- a/src/oz_agent_sdk/types/agent/artifact_item.py +++ b/src/oz_agent_sdk/types/agent/artifact_item.py @@ -1,16 +1,24 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional - -from ..._models import BaseModel - -from typing_extensions import Literal, Annotated, TypeAliasType, TypeAlias - from datetime import datetime +from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo +from ..._models import BaseModel + +__all__ = [ + "ArtifactItem", + "PlanArtifact", + "PlanArtifactData", + "PullRequestArtifact", + "PullRequestArtifactData", + "ScreenshotArtifact", + "ScreenshotArtifactData", + "FileArtifact", + "FileArtifactData", +] -__all__ = ["ArtifactItem", "PlanArtifact", "PlanArtifactData", "PullRequestArtifact", "PullRequestArtifactData", "ScreenshotArtifact", "ScreenshotArtifactData", "FileArtifact", "FileArtifactData"] class PlanArtifactData(BaseModel): document_uid: str @@ -31,6 +39,7 @@ class PlanArtifactData(BaseModel): url: Optional[str] = None """URL to open the plan in Warp Drive""" + class PlanArtifact(BaseModel): artifact_type: Literal["PLAN"] """Type of the artifact""" @@ -40,6 +49,7 @@ class PlanArtifact(BaseModel): data: PlanArtifactData + class PullRequestArtifactData(BaseModel): branch: str """Branch name for the pull request""" @@ -47,6 +57,7 @@ class PullRequestArtifactData(BaseModel): url: str """URL of the pull request""" + class PullRequestArtifact(BaseModel): artifact_type: Literal["PULL_REQUEST"] """Type of the artifact""" @@ -56,6 +67,7 @@ class PullRequestArtifact(BaseModel): data: PullRequestArtifactData + class ScreenshotArtifactData(BaseModel): artifact_uid: str """Unique identifier for the screenshot artifact""" @@ -66,6 +78,7 @@ class ScreenshotArtifactData(BaseModel): description: Optional[str] = None """Optional description of the screenshot""" + class ScreenshotArtifact(BaseModel): artifact_type: Literal["SCREENSHOT"] """Type of the artifact""" @@ -75,6 +88,7 @@ class ScreenshotArtifact(BaseModel): data: ScreenshotArtifactData + class FileArtifactData(BaseModel): artifact_uid: str """Unique identifier for the file artifact""" @@ -94,6 +108,7 @@ class FileArtifactData(BaseModel): size_bytes: Optional[int] = None """Size of the uploaded file in bytes""" + class FileArtifact(BaseModel): artifact_type: Literal["FILE"] """Type of the artifact""" @@ -103,4 +118,8 @@ class FileArtifact(BaseModel): data: FileArtifactData -ArtifactItem: TypeAlias = Annotated[Union[PlanArtifact, PullRequestArtifact, ScreenshotArtifact, FileArtifact], PropertyInfo(discriminator="artifact_type")] \ No newline at end of file + +ArtifactItem: TypeAlias = Annotated[ + Union[PlanArtifact, PullRequestArtifact, ScreenshotArtifact, FileArtifact], + PropertyInfo(discriminator="artifact_type"), +] diff --git a/src/oz_agent_sdk/types/agent/conversation_check_redirect_response.py b/src/oz_agent_sdk/types/agent/conversation_check_redirect_response.py index 143aa8d..d18fa13 100644 --- a/src/oz_agent_sdk/types/agent/conversation_check_redirect_response.py +++ b/src/oz_agent_sdk/types/agent/conversation_check_redirect_response.py @@ -1,11 +1,12 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from ..._models import BaseModel - from typing import Optional +from ..._models import BaseModel + __all__ = ["ConversationCheckRedirectResponse"] + class ConversationCheckRedirectResponse(BaseModel): session_id: Optional[str] = None - """The shared session UUID to redirect to (only present when redirect is needed)""" \ No newline at end of file + """The shared session UUID to redirect to (only present when redirect is needed)""" diff --git a/src/oz_agent_sdk/types/agent/list_agent_identities_response.py b/src/oz_agent_sdk/types/agent/list_agent_identities_response.py index 53e0d5d..d796e6f 100644 --- a/src/oz_agent_sdk/types/agent/list_agent_identities_response.py +++ b/src/oz_agent_sdk/types/agent/list_agent_identities_response.py @@ -1,12 +1,12 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from ..._models import BaseModel - from typing import List +from ..._models import BaseModel from .agent_response import AgentResponse __all__ = ["ListAgentIdentitiesResponse"] + class ListAgentIdentitiesResponse(BaseModel): - agents: List[AgentResponse] \ No newline at end of file + agents: List[AgentResponse] diff --git a/src/oz_agent_sdk/types/agent/run_cancel_response.py b/src/oz_agent_sdk/types/agent/run_cancel_response.py index ecb9017..b002815 100644 --- a/src/oz_agent_sdk/types/agent/run_cancel_response.py +++ b/src/oz_agent_sdk/types/agent/run_cancel_response.py @@ -1,7 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing_extensions import TypeAliasType, TypeAlias +from typing_extensions import TypeAlias __all__ = ["RunCancelResponse"] -RunCancelResponse: TypeAlias = str \ No newline at end of file +RunCancelResponse: TypeAlias = str diff --git a/src/oz_agent_sdk/types/agent/run_item.py b/src/oz_agent_sdk/types/agent/run_item.py index e587baf..47231a1 100644 --- a/src/oz_agent_sdk/types/agent/run_item.py +++ b/src/oz_agent_sdk/types/agent/run_item.py @@ -1,34 +1,27 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from ..._models import BaseModel - -from typing import Optional, List - -from ..error_code import ErrorCode - +from typing import List, Optional from datetime import datetime - -from .run_state import RunState - -from ..ambient_agent_config import AmbientAgentConfig - -from .artifact_item import ArtifactItem - -from ..user_profile import UserProfile - from typing_extensions import Literal from ..scope import Scope - +from ..._models import BaseModel +from .run_state import RunState +from ..error_code import ErrorCode +from ..user_profile import UserProfile +from .artifact_item import ArtifactItem from .run_source_type import RunSourceType +from ..ambient_agent_config import AmbientAgentConfig __all__ = ["RunItem", "AgentSkill", "RequestUsage", "Schedule", "StatusMessage"] + class AgentSkill(BaseModel): """ Information about the agent skill used for the run. Either full_path or bundled_skill_id will be set, but not both. """ + bundled_skill_id: Optional[str] = None """Unique identifier for bundled skills""" @@ -41,8 +34,10 @@ class AgentSkill(BaseModel): name: Optional[str] = None """Human-readable name of the skill""" + class RequestUsage(BaseModel): """Resource usage information for the run""" + compute_cost: Optional[float] = None """Cost of compute resources for the run""" @@ -52,10 +47,12 @@ class RequestUsage(BaseModel): platform_cost: Optional[float] = None """Cost of platform usage for the run""" + class Schedule(BaseModel): """ Information about the schedule that triggered this run (only present for scheduled runs) """ + cron_schedule: str """Cron expression at the time the run was created""" @@ -65,12 +62,14 @@ class Schedule(BaseModel): schedule_name: str """Name of the schedule at the time the run was created""" + class StatusMessage(BaseModel): """Status message for a run. For terminal error states, includes structured error code and retryability info from the platform error catalog. """ + message: str """Human-readable status message""" @@ -111,6 +110,7 @@ class StatusMessage(BaseModel): the underlying cause will not succeed. """ + class RunItem(BaseModel): created_at: datetime """Timestamp when the run was created (RFC3339)""" @@ -236,4 +236,4 @@ class RunItem(BaseModel): """ trigger_url: Optional[str] = None - """URL to the run trigger (e.g. Slack thread, Linear issue, schedule)""" \ No newline at end of file + """URL to the run trigger (e.g. Slack thread, Linear issue, schedule)""" diff --git a/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py b/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py index f1a50dc..b3ac5b8 100644 --- a/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py +++ b/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py @@ -1,13 +1,15 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from ..._models import BaseModel +from typing import List, Optional -from typing import Optional, List +from ..._models import BaseModel __all__ = ["RunListHandoffAttachmentsResponse", "Attachment"] + class Attachment(BaseModel): """A handoff snapshot attachment exposed for download.""" + attachment_id: str """Identifier for the snapshot attachment within the run.""" @@ -20,10 +22,12 @@ class Attachment(BaseModel): mime_type: Optional[str] = None """MIME type of the snapshot attachment, if known.""" + class RunListHandoffAttachmentsResponse(BaseModel): """Response body for listing handoff snapshot attachments.""" + attachments: List[Attachment] """ Handoff snapshot attachments exposed by the latest ended execution. Empty when no ended execution exists or no files were uploaded. - """ \ No newline at end of file + """ diff --git a/src/oz_agent_sdk/types/agent/run_list_params.py b/src/oz_agent_sdk/types/agent/run_list_params.py index 5763223..2e2d36f 100644 --- a/src/oz_agent_sdk/types/agent/run_list_params.py +++ b/src/oz_agent_sdk/types/agent/run_list_params.py @@ -2,20 +2,17 @@ from __future__ import annotations -from typing_extensions import TypedDict, Literal, Annotated - -from typing import Union, List - +from typing import List, Union from datetime import datetime +from typing_extensions import Literal, Annotated, TypedDict from ..._utils import PropertyInfo - -from .run_source_type import RunSourceType - from .run_state import RunState +from .run_source_type import RunSourceType __all__ = ["RunListParams"] + class RunListParams(TypedDict, total=False): ancestor_run_id: str """Filter runs by ancestor run ID. @@ -26,10 +23,10 @@ class RunListParams(TypedDict, total=False): artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] """Filter runs by artifact type""" - created_after: Annotated[Union[str, datetime], PropertyInfo(format = "iso8601")] + created_after: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] """Filter runs created after this timestamp (RFC3339 format)""" - created_before: Annotated[Union[str, datetime], PropertyInfo(format = "iso8601")] + created_before: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] """Filter runs created before this timestamp (RFC3339 format)""" creator: str @@ -96,5 +93,5 @@ class RunListParams(TypedDict, total=False): Can be specified multiple times to match any of the given states. """ - updated_after: Annotated[Union[str, datetime], PropertyInfo(format = "iso8601")] - """Filter runs updated after this timestamp (RFC3339 format)""" \ No newline at end of file + updated_after: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """Filter runs updated after this timestamp (RFC3339 format)""" diff --git a/src/oz_agent_sdk/types/agent/run_source_type.py b/src/oz_agent_sdk/types/agent/run_source_type.py index 77d0cdb..344fa13 100644 --- a/src/oz_agent_sdk/types/agent/run_source_type.py +++ b/src/oz_agent_sdk/types/agent/run_source_type.py @@ -1,7 +1,9 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing_extensions import Literal, TypeAliasType, TypeAlias +from typing_extensions import Literal, TypeAlias __all__ = ["RunSourceType"] -RunSourceType: TypeAlias = Literal["LINEAR", "API", "SLACK", "LOCAL", "SCHEDULED_AGENT", "WEB_APP", "GITHUB_ACTION", "CLOUD_MODE", "CLI"] \ No newline at end of file +RunSourceType: TypeAlias = Literal[ + "LINEAR", "API", "SLACK", "LOCAL", "SCHEDULED_AGENT", "WEB_APP", "GITHUB_ACTION", "CLOUD_MODE", "CLI" +] diff --git a/src/oz_agent_sdk/types/agent/run_state.py b/src/oz_agent_sdk/types/agent/run_state.py index 9d07ca0..c3fbe73 100644 --- a/src/oz_agent_sdk/types/agent/run_state.py +++ b/src/oz_agent_sdk/types/agent/run_state.py @@ -1,7 +1,9 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing_extensions import Literal, TypeAliasType, TypeAlias +from typing_extensions import Literal, TypeAlias __all__ = ["RunState"] -RunState: TypeAlias = Literal["QUEUED", "PENDING", "CLAIMED", "INPROGRESS", "SUCCEEDED", "FAILED", "BLOCKED", "ERROR", "CANCELLED"] \ No newline at end of file +RunState: TypeAlias = Literal[ + "QUEUED", "PENDING", "CLAIMED", "INPROGRESS", "SUCCEEDED", "FAILED", "BLOCKED", "ERROR", "CANCELLED" +] diff --git a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py index 5b3ae2a..abc435b 100644 --- a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py +++ b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py @@ -2,10 +2,11 @@ from __future__ import annotations -from typing_extensions import TypedDict, Literal +from typing_extensions import Literal, TypedDict __all__ = ["RunSubmitFollowupParams"] + class RunSubmitFollowupParams(TypedDict, total=False): message: str """The follow-up message to send to the run.""" @@ -15,4 +16,4 @@ class RunSubmitFollowupParams(TypedDict, total=False): Defaults to `normal` when omitted. The server does not infer mode from prompt prefixes such as `/plan`. - """ \ No newline at end of file + """ diff --git a/src/oz_agent_sdk/types/agent/schedule_create_params.py b/src/oz_agent_sdk/types/agent/schedule_create_params.py index cca91bf..484b594 100644 --- a/src/oz_agent_sdk/types/agent/schedule_create_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_create_params.py @@ -2,12 +2,13 @@ from __future__ import annotations -from typing_extensions import TypedDict, Required, Literal +from typing_extensions import Literal, Required, TypedDict from ..ambient_agent_config_param import AmbientAgentConfigParam __all__ = ["ScheduleCreateParams"] + class ScheduleCreateParams(TypedDict, total=False): cron_schedule: Required[str] """ @@ -47,4 +48,4 @@ class ScheduleCreateParams(TypedDict, total=False): """ Whether to create a team-owned schedule. Defaults to true for users on a single team. - """ \ No newline at end of file + """ diff --git a/src/oz_agent_sdk/types/agent/schedule_delete_response.py b/src/oz_agent_sdk/types/agent/schedule_delete_response.py index ad1c739..af8e5fd 100644 --- a/src/oz_agent_sdk/types/agent/schedule_delete_response.py +++ b/src/oz_agent_sdk/types/agent/schedule_delete_response.py @@ -4,6 +4,7 @@ __all__ = ["ScheduleDeleteResponse"] + class ScheduleDeleteResponse(BaseModel): success: bool - """Whether the deletion was successful""" \ No newline at end of file + """Whether the deletion was successful""" diff --git a/src/oz_agent_sdk/types/agent/schedule_list_response.py b/src/oz_agent_sdk/types/agent/schedule_list_response.py index 13af968..e0983ef 100644 --- a/src/oz_agent_sdk/types/agent/schedule_list_response.py +++ b/src/oz_agent_sdk/types/agent/schedule_list_response.py @@ -1,13 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from ..._models import BaseModel - from typing import List +from ..._models import BaseModel from .scheduled_agent_item import ScheduledAgentItem __all__ = ["ScheduleListResponse"] + class ScheduleListResponse(BaseModel): schedules: List[ScheduledAgentItem] - """List of scheduled agents""" \ No newline at end of file + """List of scheduled agents""" diff --git a/src/oz_agent_sdk/types/agent/schedule_update_params.py b/src/oz_agent_sdk/types/agent/schedule_update_params.py index b2a35ee..1ca6805 100644 --- a/src/oz_agent_sdk/types/agent/schedule_update_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_update_params.py @@ -2,12 +2,13 @@ from __future__ import annotations -from typing_extensions import TypedDict, Required, Literal +from typing_extensions import Literal, Required, TypedDict from ..ambient_agent_config_param import AmbientAgentConfigParam __all__ = ["ScheduleUpdateParams"] + class ScheduleUpdateParams(TypedDict, total=False): cron_schedule: Required[str] """Cron expression defining when the agent runs""" @@ -38,4 +39,4 @@ class ScheduleUpdateParams(TypedDict, total=False): """ The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec or agent_config.skills is provided. - """ \ No newline at end of file + """ diff --git a/src/oz_agent_sdk/types/agent/scheduled_agent_history_item.py b/src/oz_agent_sdk/types/agent/scheduled_agent_history_item.py index 4a6994e..d8ad5f7 100644 --- a/src/oz_agent_sdk/types/agent/scheduled_agent_history_item.py +++ b/src/oz_agent_sdk/types/agent/scheduled_agent_history_item.py @@ -1,17 +1,18 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from ..._models import BaseModel - from typing import Optional - from datetime import datetime +from ..._models import BaseModel + __all__ = ["ScheduledAgentHistoryItem"] + class ScheduledAgentHistoryItem(BaseModel): """Scheduler-derived history metadata for a scheduled agent""" + last_ran: Optional[datetime] = None """Timestamp of the last successful run (RFC3339)""" next_run: Optional[datetime] = None - """Timestamp of the next scheduled run (RFC3339)""" \ No newline at end of file + """Timestamp of the next scheduled run (RFC3339)""" diff --git a/src/oz_agent_sdk/types/agent/scheduled_agent_item.py b/src/oz_agent_sdk/types/agent/scheduled_agent_item.py index 5c2c73f..d307d25 100644 --- a/src/oz_agent_sdk/types/agent/scheduled_agent_item.py +++ b/src/oz_agent_sdk/types/agent/scheduled_agent_item.py @@ -1,23 +1,18 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from ..._models import BaseModel - -from datetime import datetime - from typing import Optional +from datetime import datetime -from ..ambient_agent_config import AmbientAgentConfig - +from ..scope import Scope +from ..._models import BaseModel from ..user_profile import UserProfile - +from ..ambient_agent_config import AmbientAgentConfig from ..cloud_environment_config import CloudEnvironmentConfig - from .scheduled_agent_history_item import ScheduledAgentHistoryItem -from ..scope import Scope - __all__ = ["ScheduledAgentItem"] + class ScheduledAgentItem(BaseModel): id: str """Unique identifier for the scheduled agent""" @@ -63,4 +58,4 @@ class ScheduledAgentItem(BaseModel): scope: Optional[Scope] = None """Ownership scope for a resource (team or personal)""" - updated_by: Optional[UserProfile] = None \ No newline at end of file + updated_by: Optional[UserProfile] = None diff --git a/src/oz_agent_sdk/types/agent/session_check_redirect_response.py b/src/oz_agent_sdk/types/agent/session_check_redirect_response.py index 47d50d4..9a287fc 100644 --- a/src/oz_agent_sdk/types/agent/session_check_redirect_response.py +++ b/src/oz_agent_sdk/types/agent/session_check_redirect_response.py @@ -1,11 +1,12 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from ..._models import BaseModel - from typing import Optional +from ..._models import BaseModel + __all__ = ["SessionCheckRedirectResponse"] + class SessionCheckRedirectResponse(BaseModel): conversation_id: Optional[str] = None - """The conversation ID to redirect to (only present when redirect is needed)""" \ No newline at end of file + """The conversation ID to redirect to (only present when redirect is needed)""" diff --git a/src/oz_agent_sdk/types/agent_get_artifact_response.py b/src/oz_agent_sdk/types/agent_get_artifact_response.py index 4fef192..7e835c8 100644 --- a/src/oz_agent_sdk/types/agent_get_artifact_response.py +++ b/src/oz_agent_sdk/types/agent_get_artifact_response.py @@ -1,19 +1,26 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional - -from .._models import BaseModel - -from typing_extensions import Literal, Annotated, TypeAliasType, TypeAlias - from datetime import datetime +from typing_extensions import Literal, Annotated, TypeAlias from .._utils import PropertyInfo +from .._models import BaseModel + +__all__ = [ + "AgentGetArtifactResponse", + "PlanArtifactResponse", + "PlanArtifactResponseData", + "ScreenshotArtifactResponse", + "ScreenshotArtifactResponseData", + "FileArtifactResponse", + "FileArtifactResponseData", +] -__all__ = ["AgentGetArtifactResponse", "PlanArtifactResponse", "PlanArtifactResponseData", "ScreenshotArtifactResponse", "ScreenshotArtifactResponseData", "FileArtifactResponse", "FileArtifactResponseData"] class PlanArtifactResponseData(BaseModel): """Response data for a plan artifact, including current markdown content.""" + content: str """Current markdown content of the plan""" @@ -32,8 +39,10 @@ class PlanArtifactResponseData(BaseModel): url: Optional[str] = None """URL to open the plan in Warp Drive""" + class PlanArtifactResponse(BaseModel): """Response for retrieving a plan artifact.""" + artifact_type: Literal["PLAN"] """Type of the artifact""" @@ -46,8 +55,10 @@ class PlanArtifactResponse(BaseModel): data: PlanArtifactResponseData """Response data for a plan artifact, including current markdown content.""" + class ScreenshotArtifactResponseData(BaseModel): """Response data for a screenshot artifact, including a signed download URL.""" + content_type: str """MIME type of the screenshot (e.g., image/png)""" @@ -60,8 +71,10 @@ class ScreenshotArtifactResponseData(BaseModel): description: Optional[str] = None """Optional description of the screenshot""" + class ScreenshotArtifactResponse(BaseModel): """Response for retrieving a screenshot artifact.""" + artifact_type: Literal["SCREENSHOT"] """Type of the artifact""" @@ -74,8 +87,10 @@ class ScreenshotArtifactResponse(BaseModel): data: ScreenshotArtifactResponseData """Response data for a screenshot artifact, including a signed download URL.""" + class FileArtifactResponseData(BaseModel): """Response data for a file artifact, including a signed download URL.""" + content_type: str """MIME type of the uploaded file""" @@ -97,8 +112,10 @@ class FileArtifactResponseData(BaseModel): size_bytes: Optional[int] = None """Size of the uploaded file in bytes""" + class FileArtifactResponse(BaseModel): """Response for retrieving a file artifact.""" + artifact_type: Literal["FILE"] """Type of the artifact""" @@ -111,4 +128,8 @@ class FileArtifactResponse(BaseModel): data: FileArtifactResponseData """Response data for a file artifact, including a signed download URL.""" -AgentGetArtifactResponse: TypeAlias = Annotated[Union[PlanArtifactResponse, ScreenshotArtifactResponse, FileArtifactResponse], PropertyInfo(discriminator="artifact_type")] \ No newline at end of file + +AgentGetArtifactResponse: TypeAlias = Annotated[ + Union[PlanArtifactResponse, ScreenshotArtifactResponse, FileArtifactResponse], + PropertyInfo(discriminator="artifact_type"), +] diff --git a/src/oz_agent_sdk/types/agent_list_environments_params.py b/src/oz_agent_sdk/types/agent_list_environments_params.py index aa340a4..481c31d 100644 --- a/src/oz_agent_sdk/types/agent_list_environments_params.py +++ b/src/oz_agent_sdk/types/agent_list_environments_params.py @@ -2,14 +2,15 @@ from __future__ import annotations -from typing_extensions import TypedDict, Literal +from typing_extensions import Literal, TypedDict __all__ = ["AgentListEnvironmentsParams"] + class AgentListEnvironmentsParams(TypedDict, total=False): sort_by: Literal["name", "last_updated"] """Sort order for the returned environments. - `name`: alphabetical by environment name - `last_updated`: most recently updated first (default) - """ \ No newline at end of file + """ diff --git a/src/oz_agent_sdk/types/agent_list_environments_response.py b/src/oz_agent_sdk/types/agent_list_environments_response.py index 79fb430..103845a 100644 --- a/src/oz_agent_sdk/types/agent_list_environments_response.py +++ b/src/oz_agent_sdk/types/agent_list_environments_response.py @@ -1,13 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .._models import BaseModel - from typing import List +from .._models import BaseModel from .cloud_environment import CloudEnvironment __all__ = ["AgentListEnvironmentsResponse"] + class AgentListEnvironmentsResponse(BaseModel): environments: List[CloudEnvironment] - """List of accessible cloud environments""" \ No newline at end of file + """List of accessible cloud environments""" diff --git a/src/oz_agent_sdk/types/agent_list_params.py b/src/oz_agent_sdk/types/agent_list_params.py index 26e1300..d3157f4 100644 --- a/src/oz_agent_sdk/types/agent_list_params.py +++ b/src/oz_agent_sdk/types/agent_list_params.py @@ -2,10 +2,11 @@ from __future__ import annotations -from typing_extensions import TypedDict, Literal +from typing_extensions import Literal, TypedDict __all__ = ["AgentListParams"] + class AgentListParams(TypedDict, total=False): include_malformed_skills: bool """When true, includes skills whose SKILL.md file exists but is malformed. @@ -31,4 +32,4 @@ class AgentListParams(TypedDict, total=False): - "name": Sort alphabetically by name (default) - "last_run": Sort by most recently used - """ \ No newline at end of file + """ diff --git a/src/oz_agent_sdk/types/agent_list_response.py b/src/oz_agent_sdk/types/agent_list_response.py index 62bec00..b32e870 100644 --- a/src/oz_agent_sdk/types/agent_list_response.py +++ b/src/oz_agent_sdk/types/agent_list_response.py @@ -1,13 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .._models import BaseModel - from typing import List +from .._models import BaseModel from .agent_skill import AgentSkill __all__ = ["AgentListResponse"] + class AgentListResponse(BaseModel): agents: List[AgentSkill] - """List of available agents""" \ No newline at end of file + """List of available agents""" diff --git a/src/oz_agent_sdk/types/agent_run_params.py b/src/oz_agent_sdk/types/agent_run_params.py index 788b18f..870c2de 100644 --- a/src/oz_agent_sdk/types/agent_run_params.py +++ b/src/oz_agent_sdk/types/agent_run_params.py @@ -2,20 +2,17 @@ from __future__ import annotations -from typing_extensions import TypedDict, Literal, Annotated, Required - -from typing import Iterable, Union - -from .ambient_agent_config_param import AmbientAgentConfigParam - -from .._models import set_pydantic_config +from typing import Union, Iterable +from typing_extensions import Literal, Required, Annotated, TypedDict from .._types import Base64FileInput - from .._utils import PropertyInfo +from .._models import set_pydantic_config +from .ambient_agent_config_param import AmbientAgentConfigParam __all__ = ["AgentRunParams", "Attachment"] + class AgentRunParams(TypedDict, total=False): agent_identity_uid: str """ @@ -80,9 +77,11 @@ class AgentRunParams(TypedDict, total=False): title: str """Custom title for the run (auto-generated if not provided)""" + class Attachment(TypedDict, total=False): """A base64-encoded file attachment to include with the prompt""" - data: Required[Annotated[Union[str, Base64FileInput], PropertyInfo(format = "base64")]] + + data: Required[Annotated[Union[str, Base64FileInput], PropertyInfo(format="base64")]] """Base64-encoded attachment data""" file_name: Required[str] @@ -94,6 +93,5 @@ class Attachment(TypedDict, total=False): image/gif, image/webp """ -set_pydantic_config(Attachment, { - "arbitrary_types_allowed": True -}) \ No newline at end of file + +set_pydantic_config(Attachment, {"arbitrary_types_allowed": True}) diff --git a/src/oz_agent_sdk/types/agent_run_response.py b/src/oz_agent_sdk/types/agent_run_response.py index 812632b..fb2480e 100644 --- a/src/oz_agent_sdk/types/agent_run_response.py +++ b/src/oz_agent_sdk/types/agent_run_response.py @@ -1,13 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .._models import BaseModel +from typing import Optional +from .._models import BaseModel from .agent.run_state import RunState -from typing import Optional - __all__ = ["AgentRunResponse"] + class AgentRunResponse(BaseModel): run_id: str """Unique identifier for the created run""" @@ -33,4 +33,4 @@ class AgentRunResponse(BaseModel): """ at_capacity: Optional[bool] = None - """Whether the system is at capacity when the run was created""" \ No newline at end of file + """Whether the system is at capacity when the run was created""" diff --git a/src/oz_agent_sdk/types/agent_skill.py b/src/oz_agent_sdk/types/agent_skill.py index 5cf4468..b7b9ef4 100644 --- a/src/oz_agent_sdk/types/agent_skill.py +++ b/src/oz_agent_sdk/types/agent_skill.py @@ -1,13 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .._models import BaseModel - -from typing import Optional, List - +from typing import List, Optional from datetime import datetime +from .._models import BaseModel + __all__ = ["AgentSkill", "Variant", "VariantEnvironment", "VariantSource"] + class VariantEnvironment(BaseModel): name: str """Human-readable name of the environment""" @@ -15,6 +15,7 @@ class VariantEnvironment(BaseModel): uid: str """Unique identifier for the environment""" + class VariantSource(BaseModel): name: str """GitHub repository name""" @@ -32,6 +33,7 @@ class VariantSource(BaseModel): linked to environments). """ + class Variant(BaseModel): id: str """ @@ -60,9 +62,10 @@ class Variant(BaseModel): last_run_timestamp: Optional[datetime] = None """Timestamp of the last time this skill was run (RFC3339)""" + class AgentSkill(BaseModel): name: str """Human-readable name of the agent""" variants: List[Variant] - """Available variants of this agent""" \ No newline at end of file + """Available variants of this agent""" diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index 6cc94a6..a12a31a 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -1,22 +1,30 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .._models import BaseModel - -from typing import Optional, Dict, List - +from typing import Dict, List, Optional from typing_extensions import Literal +from pydantic import Field as FieldInfo + +from .._models import BaseModel from .mcp_server_config import McpServerConfig -from pydantic import Field as FieldInfo +__all__ = [ + "AmbientAgentConfig", + "Harness", + "HarnessAuthSecrets", + "InferenceProviders", + "InferenceProvidersAws", + "MemoryStore", + "SessionSharing", +] -__all__ = ["AmbientAgentConfig", "Harness", "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws", "MemoryStore", "SessionSharing"] class Harness(BaseModel): """ Specifies which execution harness to use for the agent run. Default (nil/empty) uses Warp's built-in harness. """ + type: Optional[Literal["oz", "claude", "gemini", "codex"]] = None """The harness type identifier. @@ -26,11 +34,13 @@ class Harness(BaseModel): - codex: Codex CLI harness """ + class HarnessAuthSecrets(BaseModel): """ Authentication secrets for third-party harnesses. Only the secret for the harness specified gets injected into the environment. """ + claude_auth_secret_name: Optional[str] = None """ Name of a managed secret for Claude Code harness authentication. The secret must @@ -45,11 +55,13 @@ class HarnessAuthSecrets(BaseModel): "codex". """ + class InferenceProvidersAws(BaseModel): """ Configures AWS Bedrock as the LLM inference provider for this agent or run. """ + disabled: Optional[bool] = None """If true, opt out of Bedrock at this layer.""" @@ -59,13 +71,17 @@ class InferenceProvidersAws(BaseModel): role_arn: Optional[str] = None """IAM role ARN to assume when calling Bedrock.""" + class InferenceProviders(BaseModel): """Inference provider settings used for LLM calls.""" + aws: Optional[InferenceProvidersAws] = None """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" + class MemoryStore(BaseModel): """Reference to a memory store to attach to an agent.""" + access: Literal["read_write", "read_only"] """Access level for the store.""" @@ -75,6 +91,7 @@ class MemoryStore(BaseModel): uid: str """UID of the memory store.""" + class SessionSharing(BaseModel): """ Configures sharing behavior for the run's shared session. @@ -84,6 +101,7 @@ class SessionSharing(BaseModel): link viewers can read the conversation without being on the run's team. Subject to the workspace-level anyone-with-link sharing setting. """ + public_access: Optional[Literal["VIEWER", "EDITOR"]] = None """ Grants anyone-with-link access at the specified level to the run's shared @@ -95,8 +113,10 @@ class SessionSharing(BaseModel): still be authenticated Warp users. """ + class AmbientAgentConfig(BaseModel): """Configuration for a cloud agent run""" + base_prompt: Optional[str] = None """Custom base prompt for the agent""" @@ -137,7 +157,7 @@ class AmbientAgentConfig(BaseModel): memory_stores: Optional[List[MemoryStore]] = None """Memory stores to attach to this run.""" - api_model_id: Optional[str] = FieldInfo(alias = "model_id", default = None) + api_model_id: Optional[str] = FieldInfo(alias="model_id", default=None) """LLM model to use (uses team default if not specified)""" name: Optional[str] = None @@ -180,4 +200,4 @@ class AmbientAgentConfig(BaseModel): """ Self-hosted worker ID that should execute this task. If not specified or set to "warp", the task runs on Warp-hosted workers. - """ \ No newline at end of file + """ diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index a22f34b..e1f241e 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -3,20 +3,28 @@ from __future__ import annotations from typing import Dict, Iterable - -from .mcp_server_config_param import McpServerConfigParam +from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr +from .mcp_server_config_param import McpServerConfigParam -from typing_extensions import Literal, TypedDict, Required +__all__ = [ + "AmbientAgentConfigParam", + "Harness", + "HarnessAuthSecrets", + "InferenceProviders", + "InferenceProvidersAws", + "MemoryStore", + "SessionSharing", +] -__all__ = ["AmbientAgentConfigParam", "Harness", "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws", "MemoryStore", "SessionSharing"] class Harness(TypedDict, total=False): """ Specifies which execution harness to use for the agent run. Default (nil/empty) uses Warp's built-in harness. """ + type: Literal["oz", "claude", "gemini", "codex"] """The harness type identifier. @@ -26,11 +34,13 @@ class Harness(TypedDict, total=False): - codex: Codex CLI harness """ + class HarnessAuthSecrets(TypedDict, total=False): """ Authentication secrets for third-party harnesses. Only the secret for the harness specified gets injected into the environment. """ + claude_auth_secret_name: str """ Name of a managed secret for Claude Code harness authentication. The secret must @@ -45,11 +55,13 @@ class HarnessAuthSecrets(TypedDict, total=False): "codex". """ + class InferenceProvidersAws(TypedDict, total=False): """ Configures AWS Bedrock as the LLM inference provider for this agent or run. """ + disabled: bool """If true, opt out of Bedrock at this layer.""" @@ -59,13 +71,17 @@ class InferenceProvidersAws(TypedDict, total=False): role_arn: str """IAM role ARN to assume when calling Bedrock.""" + class InferenceProviders(TypedDict, total=False): """Inference provider settings used for LLM calls.""" + aws: InferenceProvidersAws """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" + class MemoryStore(TypedDict, total=False): """Reference to a memory store to attach to an agent.""" + access: Required[Literal["read_write", "read_only"]] """Access level for the store.""" @@ -75,6 +91,7 @@ class MemoryStore(TypedDict, total=False): uid: Required[str] """UID of the memory store.""" + class SessionSharing(TypedDict, total=False): """ Configures sharing behavior for the run's shared session. @@ -84,6 +101,7 @@ class SessionSharing(TypedDict, total=False): link viewers can read the conversation without being on the run's team. Subject to the workspace-level anyone-with-link sharing setting. """ + public_access: Literal["VIEWER", "EDITOR"] """ Grants anyone-with-link access at the specified level to the run's shared @@ -95,8 +113,10 @@ class SessionSharing(TypedDict, total=False): still be authenticated Warp users. """ + class AmbientAgentConfigParam(TypedDict, total=False): """Configuration for a cloud agent run""" + base_prompt: str """Custom base prompt for the agent""" @@ -180,4 +200,4 @@ class AmbientAgentConfigParam(TypedDict, total=False): """ Self-hosted worker ID that should execute this task. If not specified or set to "warp", the task runs on Warp-hosted workers. - """ \ No newline at end of file + """ diff --git a/src/oz_agent_sdk/types/aws_provider_config.py b/src/oz_agent_sdk/types/aws_provider_config.py index c358b4e..61020d8 100644 --- a/src/oz_agent_sdk/types/aws_provider_config.py +++ b/src/oz_agent_sdk/types/aws_provider_config.py @@ -4,7 +4,9 @@ __all__ = ["AwsProviderConfig"] + class AwsProviderConfig(BaseModel): """AWS IAM role assumption settings""" + role_arn: str - """AWS IAM role ARN to assume""" \ No newline at end of file + """AWS IAM role ARN to assume""" diff --git a/src/oz_agent_sdk/types/cloud_environment.py b/src/oz_agent_sdk/types/cloud_environment.py index 537e08f..4bde98c 100644 --- a/src/oz_agent_sdk/types/cloud_environment.py +++ b/src/oz_agent_sdk/types/cloud_environment.py @@ -1,23 +1,20 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .._models import BaseModel - +from typing import Optional from datetime import datetime +from .scope import Scope +from .._models import BaseModel +from .user_profile import UserProfile from .agent.run_state import RunState - -from typing import Optional - from .cloud_environment_config import CloudEnvironmentConfig -from .user_profile import UserProfile - -from .scope import Scope - __all__ = ["CloudEnvironment", "LastTaskCreated"] + class LastTaskCreated(BaseModel): """Summary of the most recently created task for an environment""" + id: str """Unique identifier of the task""" @@ -47,8 +44,10 @@ class LastTaskCreated(BaseModel): started_at: Optional[datetime] = None """When the task started running (RFC3339), null if not yet started""" + class CloudEnvironment(BaseModel): """A cloud environment for running agents""" + config: CloudEnvironmentConfig """Configuration for a cloud environment used by scheduled agents""" @@ -72,4 +71,4 @@ class CloudEnvironment(BaseModel): """Timestamp of the most recent task run in this environment (RFC3339)""" scope: Optional[Scope] = None - """Ownership scope for a resource (team or personal)""" \ No newline at end of file + """Ownership scope for a resource (team or personal)""" diff --git a/src/oz_agent_sdk/types/cloud_environment_config.py b/src/oz_agent_sdk/types/cloud_environment_config.py index 61f034b..15ef158 100644 --- a/src/oz_agent_sdk/types/cloud_environment_config.py +++ b/src/oz_agent_sdk/types/cloud_environment_config.py @@ -1,15 +1,14 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .._models import BaseModel - -from typing import Optional, List +from typing import List, Optional +from .._models import BaseModel from .aws_provider_config import AwsProviderConfig - from .gcp_provider_config import GcpProviderConfig __all__ = ["CloudEnvironmentConfig", "GitHubRepo", "Providers"] + class GitHubRepo(BaseModel): owner: str """GitHub repository owner (user or organization)""" @@ -17,16 +16,20 @@ class GitHubRepo(BaseModel): repo: str """GitHub repository name""" + class Providers(BaseModel): """Optional cloud provider configurations for automatic auth""" + aws: Optional[AwsProviderConfig] = None """AWS IAM role assumption settings""" gcp: Optional[GcpProviderConfig] = None """GCP Workload Identity Federation settings""" + class CloudEnvironmentConfig(BaseModel): """Configuration for a cloud environment used by scheduled agents""" + description: Optional[str] = None """Optional description of the environment""" @@ -43,4 +46,4 @@ class CloudEnvironmentConfig(BaseModel): """Optional cloud provider configurations for automatic auth""" setup_commands: Optional[List[str]] = None - """Shell commands to run during environment setup""" \ No newline at end of file + """Shell commands to run during environment setup""" diff --git a/src/oz_agent_sdk/types/error_code.py b/src/oz_agent_sdk/types/error_code.py index b734fbf..5732142 100644 --- a/src/oz_agent_sdk/types/error_code.py +++ b/src/oz_agent_sdk/types/error_code.py @@ -1,7 +1,24 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing_extensions import Literal, TypeAliasType, TypeAlias +from typing_extensions import Literal, TypeAlias __all__ = ["ErrorCode"] -ErrorCode: TypeAlias = Literal["insufficient_credits", "feature_not_available", "external_authentication_required", "not_authorized", "invalid_request", "resource_not_found", "budget_exceeded", "integration_disabled", "integration_not_configured", "operation_not_supported", "environment_setup_failed", "content_policy_violation", "conflict", "authentication_required", "resource_unavailable", "internal_error"] \ No newline at end of file +ErrorCode: TypeAlias = Literal[ + "insufficient_credits", + "feature_not_available", + "external_authentication_required", + "not_authorized", + "invalid_request", + "resource_not_found", + "budget_exceeded", + "integration_disabled", + "integration_not_configured", + "operation_not_supported", + "environment_setup_failed", + "content_policy_violation", + "conflict", + "authentication_required", + "resource_unavailable", + "internal_error", +] diff --git a/src/oz_agent_sdk/types/gcp_provider_config.py b/src/oz_agent_sdk/types/gcp_provider_config.py index bf43a23..e849b7e 100644 --- a/src/oz_agent_sdk/types/gcp_provider_config.py +++ b/src/oz_agent_sdk/types/gcp_provider_config.py @@ -1,13 +1,15 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .._models import BaseModel - from typing import Optional +from .._models import BaseModel + __all__ = ["GcpProviderConfig"] + class GcpProviderConfig(BaseModel): """GCP Workload Identity Federation settings""" + project_number: str """GCP project number""" @@ -18,4 +20,4 @@ class GcpProviderConfig(BaseModel): """Workload Identity Federation provider ID""" service_account_email: Optional[str] = None - """Optional GCP service account email to impersonate""" \ No newline at end of file + """Optional GCP service account email to impersonate""" diff --git a/src/oz_agent_sdk/types/mcp_server_config.py b/src/oz_agent_sdk/types/mcp_server_config.py index 3f77e7b..c9b7134 100644 --- a/src/oz_agent_sdk/types/mcp_server_config.py +++ b/src/oz_agent_sdk/types/mcp_server_config.py @@ -1,16 +1,18 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .._models import BaseModel +from typing import Dict, List, Optional -from typing import Optional, List, Dict +from .._models import BaseModel __all__ = ["McpServerConfig"] + class McpServerConfig(BaseModel): """Configuration for an MCP server. Must have exactly one of: warp_id, command, or url. """ + args: Optional[List[str]] = None """Stdio transport - command arguments""" @@ -27,4 +29,4 @@ class McpServerConfig(BaseModel): """SSE/HTTP transport - server URL""" warp_id: Optional[str] = None - """Reference to a Warp shared MCP server by UUID""" \ No newline at end of file + """Reference to a Warp shared MCP server by UUID""" diff --git a/src/oz_agent_sdk/types/mcp_server_config_param.py b/src/oz_agent_sdk/types/mcp_server_config_param.py index 8124273..63a63aa 100644 --- a/src/oz_agent_sdk/types/mcp_server_config_param.py +++ b/src/oz_agent_sdk/types/mcp_server_config_param.py @@ -2,19 +2,20 @@ from __future__ import annotations -from .._types import SequenceNotStr - from typing import Dict - from typing_extensions import TypedDict +from .._types import SequenceNotStr + __all__ = ["McpServerConfigParam"] + class McpServerConfigParam(TypedDict, total=False): """Configuration for an MCP server. Must have exactly one of: warp_id, command, or url. """ + args: SequenceNotStr[str] """Stdio transport - command arguments""" @@ -31,4 +32,4 @@ class McpServerConfigParam(TypedDict, total=False): """SSE/HTTP transport - server URL""" warp_id: str - """Reference to a Warp shared MCP server by UUID""" \ No newline at end of file + """Reference to a Warp shared MCP server by UUID""" diff --git a/src/oz_agent_sdk/types/scope.py b/src/oz_agent_sdk/types/scope.py index c086d02..ac765e3 100644 --- a/src/oz_agent_sdk/types/scope.py +++ b/src/oz_agent_sdk/types/scope.py @@ -1,17 +1,18 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .._models import BaseModel - +from typing import Optional from typing_extensions import Literal -from typing import Optional +from .._models import BaseModel __all__ = ["Scope"] + class Scope(BaseModel): """Ownership scope for a resource (team or personal)""" + type: Literal["User", "Team"] """Type of ownership ("User" for personal, "Team" for team-owned)""" uid: Optional[str] = None - """UID of the owning user or team""" \ No newline at end of file + """UID of the owning user or team""" diff --git a/src/oz_agent_sdk/types/user_profile.py b/src/oz_agent_sdk/types/user_profile.py index c4ca035..5892be4 100644 --- a/src/oz_agent_sdk/types/user_profile.py +++ b/src/oz_agent_sdk/types/user_profile.py @@ -1,13 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .._models import BaseModel - from typing import Optional - from typing_extensions import Literal +from .._models import BaseModel + __all__ = ["UserProfile"] + class UserProfile(BaseModel): display_name: Optional[str] = None """Display name of the creator""" @@ -22,4 +22,4 @@ class UserProfile(BaseModel): """Type of the creator principal""" uid: Optional[str] = None - """Unique identifier of the creator""" \ No newline at end of file + """Unique identifier of the creator""" diff --git a/tests/__init__.py b/tests/__init__.py index bd67c17..fd8019a 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. \ No newline at end of file +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/__init__.py b/tests/api_resources/__init__.py index bd67c17..fd8019a 100644 --- a/tests/api_resources/__init__.py +++ b/tests/api_resources/__init__.py @@ -1 +1 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. \ No newline at end of file +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/agent/__init__.py b/tests/api_resources/agent/__init__.py index bd67c17..fd8019a 100644 --- a/tests/api_resources/agent/__init__.py +++ b/tests/api_resources/agent/__init__.py @@ -1 +1 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. \ No newline at end of file +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/agent/test_agent_.py b/tests/api_resources/agent/test_agent_.py index 04d9bfa..dbc1785 100644 --- a/tests/api_resources/agent/test_agent_.py +++ b/tests/api_resources/agent/test_agent_.py @@ -2,27 +2,23 @@ from __future__ import annotations -from oz_agent_sdk import OzAPI, AsyncOzAPI - -from oz_agent_sdk.types.agent import AgentResponse, ListAgentIdentitiesResponse - -from typing import cast, Any - import os +from typing import Any, cast + import pytest -import httpx -from typing_extensions import get_args -from respx import MockRouter -from oz_agent_sdk import OzAPI, AsyncOzAPI + from tests.utils import assert_matches_type -from oz_agent_sdk.types.agent import agent_create_params -from oz_agent_sdk.types.agent import agent_update_params +from oz_agent_sdk import OzAPI, AsyncOzAPI +from oz_agent_sdk.types.agent import ( + AgentResponse, + ListAgentIdentitiesResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -class TestAgent: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=['loose', 'strict']) +class TestAgent: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -30,7 +26,7 @@ def test_method_create(self, client: OzAPI) -> None: agent = client.agent.agent.create( name="name", ) - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -56,53 +52,48 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "foo": { "args": ["string"], "command": "command", - "env": { - "foo": "string" - }, - "headers": { - "foo": "string" - }, + "env": {"foo": "string"}, + "headers": {"foo": "string"}, "url": "https://example.com", "warp_id": "warp_id", } }, - memory_stores=[{ - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - }], + memory_stores=[ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], prompt="prompt", - secrets=[{ - "name": "name" - }], + secrets=[{"name": "name"}], skills=["string"], ) - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_create(self, client: OzAPI) -> None: - response = client.agent.agent.with_raw_response.create( name="name", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_create(self, client: OzAPI) -> None: with client.agent.agent.with_streaming_response.create( name="name", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -112,7 +103,7 @@ def test_method_update(self, client: OzAPI) -> None: agent = client.agent.agent.update( uid="uid", ) - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -138,54 +129,49 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "foo": { "args": ["string"], "command": "command", - "env": { - "foo": "string" - }, - "headers": { - "foo": "string" - }, + "env": {"foo": "string"}, + "headers": {"foo": "string"}, "url": "https://example.com", "warp_id": "warp_id", } }, - memory_stores=[{ - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - }], + memory_stores=[ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], name="name", prompt="prompt", - secrets=[{ - "name": "name" - }], + secrets=[{"name": "name"}], skills=["string"], ) - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_update(self, client: OzAPI) -> None: - response = client.agent.agent.with_raw_response.update( uid="uid", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_update(self, client: OzAPI) -> None: with client.agent.agent.with_streaming_response.update( uid="uid", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -193,36 +179,35 @@ def test_streaming_response_update(self, client: OzAPI) -> None: @parametrize def test_path_params_update(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - client.agent.agent.with_raw_response.update( - uid="", - ) + client.agent.agent.with_raw_response.update( + uid="", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list(self, client: OzAPI) -> None: agent = client.agent.agent.list() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=['response']) + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_list(self, client: OzAPI) -> None: - response = client.agent.agent.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=['response']) + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_list(self, client: OzAPI) -> None: - with client.agent.agent.with_streaming_response.list() as response : + with client.agent.agent.with_streaming_response.list() as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=['response']) + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -237,13 +222,12 @@ def test_method_delete(self, client: OzAPI) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_delete(self, client: OzAPI) -> None: - response = client.agent.agent.with_raw_response.delete( "uid", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() assert agent is None @@ -252,9 +236,9 @@ def test_raw_response_delete(self, client: OzAPI) -> None: def test_streaming_response_delete(self, client: OzAPI) -> None: with client.agent.agent.with_streaming_response.delete( "uid", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() assert agent is None @@ -265,9 +249,9 @@ def test_streaming_response_delete(self, client: OzAPI) -> None: @parametrize def test_path_params_delete(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - client.agent.agent.with_raw_response.delete( - "", - ) + client.agent.agent.with_raw_response.delete( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -275,32 +259,31 @@ def test_method_get(self, client: OzAPI) -> None: agent = client.agent.agent.get( "uid", ) - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_get(self, client: OzAPI) -> None: - response = client.agent.agent.with_raw_response.get( "uid", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_get(self, client: OzAPI) -> None: with client.agent.agent.with_streaming_response.get( "uid", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -308,20 +291,23 @@ def test_streaming_response_get(self, client: OzAPI) -> None: @parametrize def test_path_params_get(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - client.agent.agent.with_raw_response.get( - "", - ) -class TestAsyncAgent: - parametrize = pytest.mark.parametrize("async_client", [False, True, {'http_client': 'aiohttp'}], indirect=True, ids=['loose', 'strict', 'aiohttp']) + client.agent.agent.with_raw_response.get( + "", + ) +class TestAsyncAgent: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_create(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.agent.create( name="name", ) - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -347,53 +333,48 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "foo": { "args": ["string"], "command": "command", - "env": { - "foo": "string" - }, - "headers": { - "foo": "string" - }, + "env": {"foo": "string"}, + "headers": {"foo": "string"}, "url": "https://example.com", "warp_id": "warp_id", } }, - memory_stores=[{ - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - }], + memory_stores=[ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], prompt="prompt", - secrets=[{ - "name": "name" - }], + secrets=[{"name": "name"}], skills=["string"], ) - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_create(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.agent.with_raw_response.create( name="name", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_create(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.agent.with_streaming_response.create( name="name", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -403,7 +384,7 @@ async def test_method_update(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.agent.update( uid="uid", ) - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -429,54 +410,49 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "foo": { "args": ["string"], "command": "command", - "env": { - "foo": "string" - }, - "headers": { - "foo": "string" - }, + "env": {"foo": "string"}, + "headers": {"foo": "string"}, "url": "https://example.com", "warp_id": "warp_id", } }, - memory_stores=[{ - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - }], + memory_stores=[ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], name="name", prompt="prompt", - secrets=[{ - "name": "name" - }], + secrets=[{"name": "name"}], skills=["string"], ) - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_update(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.agent.with_raw_response.update( uid="uid", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_update(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.agent.with_streaming_response.update( uid="uid", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -484,36 +460,35 @@ async def test_streaming_response_update(self, async_client: AsyncOzAPI) -> None @parametrize async def test_path_params_update(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - await async_client.agent.agent.with_raw_response.update( - uid="", - ) + await async_client.agent.agent.with_raw_response.update( + uid="", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.agent.list() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=['response']) + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_list(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.agent.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=['response']) + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_list(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.agent.with_streaming_response.list() as response : + async with async_client.agent.agent.with_streaming_response.list() as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=['response']) + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -528,13 +503,12 @@ async def test_method_delete(self, async_client: AsyncOzAPI) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_delete(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.agent.with_raw_response.delete( "uid", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() assert agent is None @@ -543,9 +517,9 @@ async def test_raw_response_delete(self, async_client: AsyncOzAPI) -> None: async def test_streaming_response_delete(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.agent.with_streaming_response.delete( "uid", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() assert agent is None @@ -556,9 +530,9 @@ async def test_streaming_response_delete(self, async_client: AsyncOzAPI) -> None @parametrize async def test_path_params_delete(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - await async_client.agent.agent.with_raw_response.delete( - "", - ) + await async_client.agent.agent.with_raw_response.delete( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -566,32 +540,31 @@ async def test_method_get(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.agent.get( "uid", ) - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_get(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.agent.with_raw_response.get( "uid", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_get(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.agent.with_streaming_response.get( "uid", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=['response']) + assert_matches_type(AgentResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -599,6 +572,6 @@ async def test_streaming_response_get(self, async_client: AsyncOzAPI) -> None: @parametrize async def test_path_params_get(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - await async_client.agent.agent.with_raw_response.get( - "", - ) \ No newline at end of file + await async_client.agent.agent.with_raw_response.get( + "", + ) diff --git a/tests/api_resources/agent/test_conversations.py b/tests/api_resources/agent/test_conversations.py index e6200f0..e1a21d4 100644 --- a/tests/api_resources/agent/test_conversations.py +++ b/tests/api_resources/agent/test_conversations.py @@ -2,25 +2,20 @@ from __future__ import annotations -from oz_agent_sdk import OzAPI, AsyncOzAPI - -from oz_agent_sdk.types.agent import ConversationCheckRedirectResponse - -from typing import cast, Any - import os +from typing import Any, cast + import pytest -import httpx -from typing_extensions import get_args -from respx import MockRouter -from oz_agent_sdk import OzAPI, AsyncOzAPI + from tests.utils import assert_matches_type +from oz_agent_sdk import OzAPI, AsyncOzAPI +from oz_agent_sdk.types.agent import ConversationCheckRedirectResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -class TestConversations: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=['loose', 'strict']) +class TestConversations: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -28,32 +23,31 @@ def test_method_check_redirect(self, client: OzAPI) -> None: conversation = client.agent.conversations.check_redirect( "conversationId", ) - assert_matches_type(ConversationCheckRedirectResponse, conversation, path=['response']) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_check_redirect(self, client: OzAPI) -> None: - response = client.agent.conversations.with_raw_response.check_redirect( "conversationId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() - assert_matches_type(ConversationCheckRedirectResponse, conversation, path=['response']) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_check_redirect(self, client: OzAPI) -> None: with client.agent.conversations.with_streaming_response.check_redirect( "conversationId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() - assert_matches_type(ConversationCheckRedirectResponse, conversation, path=['response']) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) assert cast(Any, response.is_closed) is True @@ -61,12 +55,15 @@ def test_streaming_response_check_redirect(self, client: OzAPI) -> None: @parametrize def test_path_params_check_redirect(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): - client.agent.conversations.with_raw_response.check_redirect( - "", - ) -class TestAsyncConversations: - parametrize = pytest.mark.parametrize("async_client", [False, True, {'http_client': 'aiohttp'}], indirect=True, ids=['loose', 'strict', 'aiohttp']) + client.agent.conversations.with_raw_response.check_redirect( + "", + ) + +class TestAsyncConversations: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -74,32 +71,31 @@ async def test_method_check_redirect(self, async_client: AsyncOzAPI) -> None: conversation = await async_client.agent.conversations.check_redirect( "conversationId", ) - assert_matches_type(ConversationCheckRedirectResponse, conversation, path=['response']) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_check_redirect(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.conversations.with_raw_response.check_redirect( "conversationId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = await response.parse() - assert_matches_type(ConversationCheckRedirectResponse, conversation, path=['response']) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_check_redirect(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.conversations.with_streaming_response.check_redirect( "conversationId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = await response.parse() - assert_matches_type(ConversationCheckRedirectResponse, conversation, path=['response']) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) assert cast(Any, response.is_closed) is True @@ -107,6 +103,6 @@ async def test_streaming_response_check_redirect(self, async_client: AsyncOzAPI) @parametrize async def test_path_params_check_redirect(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): - await async_client.agent.conversations.with_raw_response.check_redirect( - "", - ) \ No newline at end of file + await async_client.agent.conversations.with_raw_response.check_redirect( + "", + ) diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index 5b92ce3..54bb08c 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -2,32 +2,25 @@ from __future__ import annotations -from oz_agent_sdk import OzAPI, AsyncOzAPI - -from oz_agent_sdk.types.agent import RunItem, RunCancelResponse, RunListHandoffAttachmentsResponse - -from typing import cast, Any - -from oz_agent_sdk.pagination import SyncRunsCursorPage, AsyncRunsCursorPage - -from oz_agent_sdk._utils import parse_datetime - import os +from typing import Any, cast + import pytest -import httpx -from typing_extensions import get_args -from respx import MockRouter -from oz_agent_sdk import OzAPI, AsyncOzAPI + from tests.utils import assert_matches_type -from oz_agent_sdk.types.agent import run_list_params -from oz_agent_sdk.types.agent import run_submit_followup_params -from oz_agent_sdk.types.agent import RunSourceType +from oz_agent_sdk import OzAPI, AsyncOzAPI +from oz_agent_sdk._utils import parse_datetime +from oz_agent_sdk.pagination import SyncRunsCursorPage, AsyncRunsCursorPage +from oz_agent_sdk.types.agent import ( + RunItem, + RunListHandoffAttachmentsResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -class TestRuns: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=['loose', 'strict']) +class TestRuns: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -35,32 +28,31 @@ def test_method_retrieve(self, client: OzAPI) -> None: run = client.agent.runs.retrieve( "runId", ) - assert_matches_type(RunItem, run, path=['response']) + assert_matches_type(RunItem, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_retrieve(self, client: OzAPI) -> None: - response = client.agent.runs.with_raw_response.retrieve( "runId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() - assert_matches_type(RunItem, run, path=['response']) + assert_matches_type(RunItem, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_retrieve(self, client: OzAPI) -> None: with client.agent.runs.with_streaming_response.retrieve( "runId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() - assert_matches_type(RunItem, run, path=['response']) + assert_matches_type(RunItem, run, path=["response"]) assert cast(Any, response.is_closed) is True @@ -68,15 +60,15 @@ def test_streaming_response_retrieve(self, client: OzAPI) -> None: @parametrize def test_path_params_retrieve(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - client.agent.runs.with_raw_response.retrieve( - "", - ) + client.agent.runs.with_raw_response.retrieve( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list(self, client: OzAPI) -> None: run = client.agent.runs.list() - assert_matches_type(SyncRunsCursorPage[RunItem], run, path=['response']) + assert_matches_type(SyncRunsCursorPage[RunItem], run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -104,28 +96,27 @@ def test_method_list_with_all_params(self, client: OzAPI) -> None: state=["QUEUED"], updated_after=parse_datetime("2019-12-27T18:11:19.117Z"), ) - assert_matches_type(SyncRunsCursorPage[RunItem], run, path=['response']) + assert_matches_type(SyncRunsCursorPage[RunItem], run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_list(self, client: OzAPI) -> None: - response = client.agent.runs.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() - assert_matches_type(SyncRunsCursorPage[RunItem], run, path=['response']) + assert_matches_type(SyncRunsCursorPage[RunItem], run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_list(self, client: OzAPI) -> None: - with client.agent.runs.with_streaming_response.list() as response : + with client.agent.runs.with_streaming_response.list() as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() - assert_matches_type(SyncRunsCursorPage[RunItem], run, path=['response']) + assert_matches_type(SyncRunsCursorPage[RunItem], run, path=["response"]) assert cast(Any, response.is_closed) is True @@ -135,32 +126,31 @@ def test_method_cancel(self, client: OzAPI) -> None: run = client.agent.runs.cancel( "runId", ) - assert_matches_type(str, run, path=['response']) + assert_matches_type(str, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_cancel(self, client: OzAPI) -> None: - response = client.agent.runs.with_raw_response.cancel( "runId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() - assert_matches_type(str, run, path=['response']) + assert_matches_type(str, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_cancel(self, client: OzAPI) -> None: with client.agent.runs.with_streaming_response.cancel( "runId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() - assert_matches_type(str, run, path=['response']) + assert_matches_type(str, run, path=["response"]) assert cast(Any, response.is_closed) is True @@ -168,9 +158,9 @@ def test_streaming_response_cancel(self, client: OzAPI) -> None: @parametrize def test_path_params_cancel(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - client.agent.runs.with_raw_response.cancel( - "", - ) + client.agent.runs.with_raw_response.cancel( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -178,32 +168,31 @@ def test_method_list_handoff_attachments(self, client: OzAPI) -> None: run = client.agent.runs.list_handoff_attachments( "runId", ) - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=['response']) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_list_handoff_attachments(self, client: OzAPI) -> None: - response = client.agent.runs.with_raw_response.list_handoff_attachments( "runId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=['response']) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_list_handoff_attachments(self, client: OzAPI) -> None: with client.agent.runs.with_streaming_response.list_handoff_attachments( "runId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=['response']) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) assert cast(Any, response.is_closed) is True @@ -211,9 +200,9 @@ def test_streaming_response_list_handoff_attachments(self, client: OzAPI) -> Non @parametrize def test_path_params_list_handoff_attachments(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - client.agent.runs.with_raw_response.list_handoff_attachments( - "", - ) + client.agent.runs.with_raw_response.list_handoff_attachments( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -221,7 +210,7 @@ def test_method_submit_followup(self, client: OzAPI) -> None: run = client.agent.runs.submit_followup( run_id="runId", ) - assert_matches_type(object, run, path=['response']) + assert_matches_type(object, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -231,32 +220,31 @@ def test_method_submit_followup_with_all_params(self, client: OzAPI) -> None: message="message", mode="normal", ) - assert_matches_type(object, run, path=['response']) + assert_matches_type(object, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_submit_followup(self, client: OzAPI) -> None: - response = client.agent.runs.with_raw_response.submit_followup( run_id="runId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() - assert_matches_type(object, run, path=['response']) + assert_matches_type(object, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_submit_followup(self, client: OzAPI) -> None: with client.agent.runs.with_streaming_response.submit_followup( run_id="runId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() - assert_matches_type(object, run, path=['response']) + assert_matches_type(object, run, path=["response"]) assert cast(Any, response.is_closed) is True @@ -264,45 +252,47 @@ def test_streaming_response_submit_followup(self, client: OzAPI) -> None: @parametrize def test_path_params_submit_followup(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - client.agent.runs.with_raw_response.submit_followup( - run_id="", - ) -class TestAsyncRuns: - parametrize = pytest.mark.parametrize("async_client", [False, True, {'http_client': 'aiohttp'}], indirect=True, ids=['loose', 'strict', 'aiohttp']) + client.agent.runs.with_raw_response.submit_followup( + run_id="", + ) +class TestAsyncRuns: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_retrieve(self, async_client: AsyncOzAPI) -> None: run = await async_client.agent.runs.retrieve( "runId", ) - assert_matches_type(RunItem, run, path=['response']) + assert_matches_type(RunItem, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.runs.with_raw_response.retrieve( "runId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() - assert_matches_type(RunItem, run, path=['response']) + assert_matches_type(RunItem, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.runs.with_streaming_response.retrieve( "runId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() - assert_matches_type(RunItem, run, path=['response']) + assert_matches_type(RunItem, run, path=["response"]) assert cast(Any, response.is_closed) is True @@ -310,15 +300,15 @@ async def test_streaming_response_retrieve(self, async_client: AsyncOzAPI) -> No @parametrize async def test_path_params_retrieve(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - await async_client.agent.runs.with_raw_response.retrieve( - "", - ) + await async_client.agent.runs.with_raw_response.retrieve( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncOzAPI) -> None: run = await async_client.agent.runs.list() - assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=['response']) + assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -346,28 +336,27 @@ async def test_method_list_with_all_params(self, async_client: AsyncOzAPI) -> No state=["QUEUED"], updated_after=parse_datetime("2019-12-27T18:11:19.117Z"), ) - assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=['response']) + assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_list(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.runs.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() - assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=['response']) + assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_list(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.runs.with_streaming_response.list() as response : + async with async_client.agent.runs.with_streaming_response.list() as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() - assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=['response']) + assert_matches_type(AsyncRunsCursorPage[RunItem], run, path=["response"]) assert cast(Any, response.is_closed) is True @@ -377,32 +366,31 @@ async def test_method_cancel(self, async_client: AsyncOzAPI) -> None: run = await async_client.agent.runs.cancel( "runId", ) - assert_matches_type(str, run, path=['response']) + assert_matches_type(str, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_cancel(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.runs.with_raw_response.cancel( "runId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() - assert_matches_type(str, run, path=['response']) + assert_matches_type(str, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_cancel(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.runs.with_streaming_response.cancel( "runId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() - assert_matches_type(str, run, path=['response']) + assert_matches_type(str, run, path=["response"]) assert cast(Any, response.is_closed) is True @@ -410,9 +398,9 @@ async def test_streaming_response_cancel(self, async_client: AsyncOzAPI) -> None @parametrize async def test_path_params_cancel(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - await async_client.agent.runs.with_raw_response.cancel( - "", - ) + await async_client.agent.runs.with_raw_response.cancel( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -420,32 +408,31 @@ async def test_method_list_handoff_attachments(self, async_client: AsyncOzAPI) - run = await async_client.agent.runs.list_handoff_attachments( "runId", ) - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=['response']) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.runs.with_raw_response.list_handoff_attachments( "runId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=['response']) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.runs.with_streaming_response.list_handoff_attachments( "runId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=['response']) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) assert cast(Any, response.is_closed) is True @@ -453,9 +440,9 @@ async def test_streaming_response_list_handoff_attachments(self, async_client: A @parametrize async def test_path_params_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - await async_client.agent.runs.with_raw_response.list_handoff_attachments( - "", - ) + await async_client.agent.runs.with_raw_response.list_handoff_attachments( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -463,7 +450,7 @@ async def test_method_submit_followup(self, async_client: AsyncOzAPI) -> None: run = await async_client.agent.runs.submit_followup( run_id="runId", ) - assert_matches_type(object, run, path=['response']) + assert_matches_type(object, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -473,32 +460,31 @@ async def test_method_submit_followup_with_all_params(self, async_client: AsyncO message="message", mode="normal", ) - assert_matches_type(object, run, path=['response']) + assert_matches_type(object, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_submit_followup(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.runs.with_raw_response.submit_followup( run_id="runId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() - assert_matches_type(object, run, path=['response']) + assert_matches_type(object, run, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_submit_followup(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.runs.with_streaming_response.submit_followup( run_id="runId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() - assert_matches_type(object, run, path=['response']) + assert_matches_type(object, run, path=["response"]) assert cast(Any, response.is_closed) is True @@ -506,6 +492,6 @@ async def test_streaming_response_submit_followup(self, async_client: AsyncOzAPI @parametrize async def test_path_params_submit_followup(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - await async_client.agent.runs.with_raw_response.submit_followup( - run_id="", - ) \ No newline at end of file + await async_client.agent.runs.with_raw_response.submit_followup( + run_id="", + ) diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index 00ce34d..272c7e3 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -2,29 +2,24 @@ from __future__ import annotations -from oz_agent_sdk import OzAPI, AsyncOzAPI - -from oz_agent_sdk.types.agent import ScheduledAgentItem, ScheduleListResponse, ScheduleDeleteResponse - -from typing import cast, Any - import os +from typing import Any, cast + import pytest -import httpx -from typing_extensions import get_args -from respx import MockRouter -from oz_agent_sdk import OzAPI, AsyncOzAPI + from tests.utils import assert_matches_type -from oz_agent_sdk.types.agent import schedule_create_params -from oz_agent_sdk.types.agent import schedule_update_params -from oz_agent_sdk.types import AmbientAgentConfig -from oz_agent_sdk.types import AmbientAgentConfig +from oz_agent_sdk import OzAPI, AsyncOzAPI +from oz_agent_sdk.types.agent import ( + ScheduledAgentItem, + ScheduleListResponse, + ScheduleDeleteResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -class TestSchedules: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=['loose', 'strict']) +class TestSchedules: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -33,7 +28,7 @@ def test_method_create(self, client: OzAPI) -> None: cron_schedule="0 9 * * *", name="Daily Code Review", ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -45,9 +40,7 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "type": "oz" - }, + "harness": {"type": "oz"}, "harness_auth_secrets": { "claude_auth_secret_name": "claude_auth_secret_name", "codex_auth_secret_name": "codex_auth_secret_name", @@ -64,26 +57,22 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "foo": { "args": ["string"], "command": "command", - "env": { - "foo": "string" - }, - "headers": { - "foo": "string" - }, + "env": {"foo": "string"}, + "headers": {"foo": "string"}, "url": "https://example.com", "warp_id": "warp_id", } }, - "memory_stores": [{ - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - }], + "memory_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], "model_id": "model_id", "name": "name", - "session_sharing": { - "public_access": "VIEWER" - }, + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "skills": ["string"], "worker_host": "worker_host", @@ -94,21 +83,20 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: prompt="Review open pull requests and provide feedback", team=True, ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_create(self, client: OzAPI) -> None: - response = client.agent.schedules.with_raw_response.create( cron_schedule="0 9 * * *", name="Daily Code Review", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -116,12 +104,12 @@ def test_streaming_response_create(self, client: OzAPI) -> None: with client.agent.schedules.with_streaming_response.create( cron_schedule="0 9 * * *", name="Daily Code Review", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -131,32 +119,31 @@ def test_method_retrieve(self, client: OzAPI) -> None: schedule = client.agent.schedules.retrieve( "scheduleId", ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_retrieve(self, client: OzAPI) -> None: - response = client.agent.schedules.with_raw_response.retrieve( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_retrieve(self, client: OzAPI) -> None: with client.agent.schedules.with_streaming_response.retrieve( "scheduleId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -164,9 +151,9 @@ def test_streaming_response_retrieve(self, client: OzAPI) -> None: @parametrize def test_path_params_retrieve(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - client.agent.schedules.with_raw_response.retrieve( - "", - ) + client.agent.schedules.with_raw_response.retrieve( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -177,7 +164,7 @@ def test_method_update(self, client: OzAPI) -> None: enabled=True, name="name", ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -191,9 +178,7 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "type": "oz" - }, + "harness": {"type": "oz"}, "harness_auth_secrets": { "claude_auth_secret_name": "claude_auth_secret_name", "codex_auth_secret_name": "codex_auth_secret_name", @@ -210,26 +195,22 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "foo": { "args": ["string"], "command": "command", - "env": { - "foo": "string" - }, - "headers": { - "foo": "string" - }, + "env": {"foo": "string"}, + "headers": {"foo": "string"}, "url": "https://example.com", "warp_id": "warp_id", } }, - "memory_stores": [{ - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - }], + "memory_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], "model_id": "model_id", "name": "name", - "session_sharing": { - "public_access": "VIEWER" - }, + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "skills": ["string"], "worker_host": "worker_host", @@ -238,12 +219,11 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: mode="normal", prompt="prompt", ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_update(self, client: OzAPI) -> None: - response = client.agent.schedules.with_raw_response.update( schedule_id="scheduleId", cron_schedule="cron_schedule", @@ -252,9 +232,9 @@ def test_raw_response_update(self, client: OzAPI) -> None: ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -264,12 +244,12 @@ def test_streaming_response_update(self, client: OzAPI) -> None: cron_schedule="cron_schedule", enabled=True, name="name", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -277,39 +257,38 @@ def test_streaming_response_update(self, client: OzAPI) -> None: @parametrize def test_path_params_update(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - client.agent.schedules.with_raw_response.update( - schedule_id="", - cron_schedule="cron_schedule", - enabled=True, - name="name", - ) + client.agent.schedules.with_raw_response.update( + schedule_id="", + cron_schedule="cron_schedule", + enabled=True, + name="name", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list(self, client: OzAPI) -> None: schedule = client.agent.schedules.list() - assert_matches_type(ScheduleListResponse, schedule, path=['response']) + assert_matches_type(ScheduleListResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_list(self, client: OzAPI) -> None: - response = client.agent.schedules.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduleListResponse, schedule, path=['response']) + assert_matches_type(ScheduleListResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_list(self, client: OzAPI) -> None: - with client.agent.schedules.with_streaming_response.list() as response : + with client.agent.schedules.with_streaming_response.list() as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduleListResponse, schedule, path=['response']) + assert_matches_type(ScheduleListResponse, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -319,32 +298,31 @@ def test_method_delete(self, client: OzAPI) -> None: schedule = client.agent.schedules.delete( "scheduleId", ) - assert_matches_type(ScheduleDeleteResponse, schedule, path=['response']) + assert_matches_type(ScheduleDeleteResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_delete(self, client: OzAPI) -> None: - response = client.agent.schedules.with_raw_response.delete( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduleDeleteResponse, schedule, path=['response']) + assert_matches_type(ScheduleDeleteResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_delete(self, client: OzAPI) -> None: with client.agent.schedules.with_streaming_response.delete( "scheduleId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduleDeleteResponse, schedule, path=['response']) + assert_matches_type(ScheduleDeleteResponse, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -352,9 +330,9 @@ def test_streaming_response_delete(self, client: OzAPI) -> None: @parametrize def test_path_params_delete(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - client.agent.schedules.with_raw_response.delete( - "", - ) + client.agent.schedules.with_raw_response.delete( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -362,32 +340,31 @@ def test_method_pause(self, client: OzAPI) -> None: schedule = client.agent.schedules.pause( "scheduleId", ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_pause(self, client: OzAPI) -> None: - response = client.agent.schedules.with_raw_response.pause( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_pause(self, client: OzAPI) -> None: with client.agent.schedules.with_streaming_response.pause( "scheduleId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -395,9 +372,9 @@ def test_streaming_response_pause(self, client: OzAPI) -> None: @parametrize def test_path_params_pause(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - client.agent.schedules.with_raw_response.pause( - "", - ) + client.agent.schedules.with_raw_response.pause( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -405,32 +382,31 @@ def test_method_resume(self, client: OzAPI) -> None: schedule = client.agent.schedules.resume( "scheduleId", ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_resume(self, client: OzAPI) -> None: - response = client.agent.schedules.with_raw_response.resume( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_resume(self, client: OzAPI) -> None: with client.agent.schedules.with_streaming_response.resume( "scheduleId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -438,12 +414,15 @@ def test_streaming_response_resume(self, client: OzAPI) -> None: @parametrize def test_path_params_resume(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - client.agent.schedules.with_raw_response.resume( - "", - ) -class TestAsyncSchedules: - parametrize = pytest.mark.parametrize("async_client", [False, True, {'http_client': 'aiohttp'}], indirect=True, ids=['loose', 'strict', 'aiohttp']) + client.agent.schedules.with_raw_response.resume( + "", + ) + +class TestAsyncSchedules: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -452,7 +431,7 @@ async def test_method_create(self, async_client: AsyncOzAPI) -> None: cron_schedule="0 9 * * *", name="Daily Code Review", ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -464,9 +443,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "type": "oz" - }, + "harness": {"type": "oz"}, "harness_auth_secrets": { "claude_auth_secret_name": "claude_auth_secret_name", "codex_auth_secret_name": "codex_auth_secret_name", @@ -483,26 +460,22 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "foo": { "args": ["string"], "command": "command", - "env": { - "foo": "string" - }, - "headers": { - "foo": "string" - }, + "env": {"foo": "string"}, + "headers": {"foo": "string"}, "url": "https://example.com", "warp_id": "warp_id", } }, - "memory_stores": [{ - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - }], + "memory_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], "model_id": "model_id", "name": "name", - "session_sharing": { - "public_access": "VIEWER" - }, + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "skills": ["string"], "worker_host": "worker_host", @@ -513,21 +486,20 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> prompt="Review open pull requests and provide feedback", team=True, ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_create(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.schedules.with_raw_response.create( cron_schedule="0 9 * * *", name="Daily Code Review", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -535,12 +507,12 @@ async def test_streaming_response_create(self, async_client: AsyncOzAPI) -> None async with async_client.agent.schedules.with_streaming_response.create( cron_schedule="0 9 * * *", name="Daily Code Review", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -550,32 +522,31 @@ async def test_method_retrieve(self, async_client: AsyncOzAPI) -> None: schedule = await async_client.agent.schedules.retrieve( "scheduleId", ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.schedules.with_raw_response.retrieve( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.schedules.with_streaming_response.retrieve( "scheduleId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -583,9 +554,9 @@ async def test_streaming_response_retrieve(self, async_client: AsyncOzAPI) -> No @parametrize async def test_path_params_retrieve(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - await async_client.agent.schedules.with_raw_response.retrieve( - "", - ) + await async_client.agent.schedules.with_raw_response.retrieve( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -596,7 +567,7 @@ async def test_method_update(self, async_client: AsyncOzAPI) -> None: enabled=True, name="name", ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -610,9 +581,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "type": "oz" - }, + "harness": {"type": "oz"}, "harness_auth_secrets": { "claude_auth_secret_name": "claude_auth_secret_name", "codex_auth_secret_name": "codex_auth_secret_name", @@ -629,26 +598,22 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "foo": { "args": ["string"], "command": "command", - "env": { - "foo": "string" - }, - "headers": { - "foo": "string" - }, + "env": {"foo": "string"}, + "headers": {"foo": "string"}, "url": "https://example.com", "warp_id": "warp_id", } }, - "memory_stores": [{ - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - }], + "memory_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], "model_id": "model_id", "name": "name", - "session_sharing": { - "public_access": "VIEWER" - }, + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "skills": ["string"], "worker_host": "worker_host", @@ -657,12 +622,11 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> mode="normal", prompt="prompt", ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_update(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.schedules.with_raw_response.update( schedule_id="scheduleId", cron_schedule="cron_schedule", @@ -671,9 +635,9 @@ async def test_raw_response_update(self, async_client: AsyncOzAPI) -> None: ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -683,12 +647,12 @@ async def test_streaming_response_update(self, async_client: AsyncOzAPI) -> None cron_schedule="cron_schedule", enabled=True, name="name", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -696,39 +660,38 @@ async def test_streaming_response_update(self, async_client: AsyncOzAPI) -> None @parametrize async def test_path_params_update(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - await async_client.agent.schedules.with_raw_response.update( - schedule_id="", - cron_schedule="cron_schedule", - enabled=True, - name="name", - ) + await async_client.agent.schedules.with_raw_response.update( + schedule_id="", + cron_schedule="cron_schedule", + enabled=True, + name="name", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncOzAPI) -> None: schedule = await async_client.agent.schedules.list() - assert_matches_type(ScheduleListResponse, schedule, path=['response']) + assert_matches_type(ScheduleListResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_list(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.schedules.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduleListResponse, schedule, path=['response']) + assert_matches_type(ScheduleListResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_list(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.schedules.with_streaming_response.list() as response : + async with async_client.agent.schedules.with_streaming_response.list() as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduleListResponse, schedule, path=['response']) + assert_matches_type(ScheduleListResponse, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -738,32 +701,31 @@ async def test_method_delete(self, async_client: AsyncOzAPI) -> None: schedule = await async_client.agent.schedules.delete( "scheduleId", ) - assert_matches_type(ScheduleDeleteResponse, schedule, path=['response']) + assert_matches_type(ScheduleDeleteResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_delete(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.schedules.with_raw_response.delete( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduleDeleteResponse, schedule, path=['response']) + assert_matches_type(ScheduleDeleteResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_delete(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.schedules.with_streaming_response.delete( "scheduleId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduleDeleteResponse, schedule, path=['response']) + assert_matches_type(ScheduleDeleteResponse, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -771,9 +733,9 @@ async def test_streaming_response_delete(self, async_client: AsyncOzAPI) -> None @parametrize async def test_path_params_delete(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - await async_client.agent.schedules.with_raw_response.delete( - "", - ) + await async_client.agent.schedules.with_raw_response.delete( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -781,32 +743,31 @@ async def test_method_pause(self, async_client: AsyncOzAPI) -> None: schedule = await async_client.agent.schedules.pause( "scheduleId", ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_pause(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.schedules.with_raw_response.pause( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_pause(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.schedules.with_streaming_response.pause( "scheduleId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -814,9 +775,9 @@ async def test_streaming_response_pause(self, async_client: AsyncOzAPI) -> None: @parametrize async def test_path_params_pause(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - await async_client.agent.schedules.with_raw_response.pause( - "", - ) + await async_client.agent.schedules.with_raw_response.pause( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -824,32 +785,31 @@ async def test_method_resume(self, async_client: AsyncOzAPI) -> None: schedule = await async_client.agent.schedules.resume( "scheduleId", ) - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_resume(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.schedules.with_raw_response.resume( "scheduleId", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_resume(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.schedules.with_streaming_response.resume( "scheduleId", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduledAgentItem, schedule, path=['response']) + assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @@ -857,6 +817,6 @@ async def test_streaming_response_resume(self, async_client: AsyncOzAPI) -> None @parametrize async def test_path_params_resume(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): - await async_client.agent.schedules.with_raw_response.resume( - "", - ) \ No newline at end of file + await async_client.agent.schedules.with_raw_response.resume( + "", + ) diff --git a/tests/api_resources/agent/test_sessions.py b/tests/api_resources/agent/test_sessions.py index 7519323..5b344ac 100644 --- a/tests/api_resources/agent/test_sessions.py +++ b/tests/api_resources/agent/test_sessions.py @@ -2,25 +2,20 @@ from __future__ import annotations -from oz_agent_sdk import OzAPI, AsyncOzAPI - -from oz_agent_sdk.types.agent import SessionCheckRedirectResponse - -from typing import cast, Any - import os +from typing import Any, cast + import pytest -import httpx -from typing_extensions import get_args -from respx import MockRouter -from oz_agent_sdk import OzAPI, AsyncOzAPI + from tests.utils import assert_matches_type +from oz_agent_sdk import OzAPI, AsyncOzAPI +from oz_agent_sdk.types.agent import SessionCheckRedirectResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -class TestSessions: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=['loose', 'strict']) +class TestSessions: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -28,32 +23,31 @@ def test_method_check_redirect(self, client: OzAPI) -> None: session = client.agent.sessions.check_redirect( "sessionUuid", ) - assert_matches_type(SessionCheckRedirectResponse, session, path=['response']) + assert_matches_type(SessionCheckRedirectResponse, session, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_check_redirect(self, client: OzAPI) -> None: - response = client.agent.sessions.with_raw_response.check_redirect( "sessionUuid", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" session = response.parse() - assert_matches_type(SessionCheckRedirectResponse, session, path=['response']) + assert_matches_type(SessionCheckRedirectResponse, session, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_check_redirect(self, client: OzAPI) -> None: with client.agent.sessions.with_streaming_response.check_redirect( "sessionUuid", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" session = response.parse() - assert_matches_type(SessionCheckRedirectResponse, session, path=['response']) + assert_matches_type(SessionCheckRedirectResponse, session, path=["response"]) assert cast(Any, response.is_closed) is True @@ -61,12 +55,15 @@ def test_streaming_response_check_redirect(self, client: OzAPI) -> None: @parametrize def test_path_params_check_redirect(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_uuid` but received ''"): - client.agent.sessions.with_raw_response.check_redirect( - "", - ) -class TestAsyncSessions: - parametrize = pytest.mark.parametrize("async_client", [False, True, {'http_client': 'aiohttp'}], indirect=True, ids=['loose', 'strict', 'aiohttp']) + client.agent.sessions.with_raw_response.check_redirect( + "", + ) + +class TestAsyncSessions: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -74,32 +71,31 @@ async def test_method_check_redirect(self, async_client: AsyncOzAPI) -> None: session = await async_client.agent.sessions.check_redirect( "sessionUuid", ) - assert_matches_type(SessionCheckRedirectResponse, session, path=['response']) + assert_matches_type(SessionCheckRedirectResponse, session, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_check_redirect(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.sessions.with_raw_response.check_redirect( "sessionUuid", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" session = await response.parse() - assert_matches_type(SessionCheckRedirectResponse, session, path=['response']) + assert_matches_type(SessionCheckRedirectResponse, session, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_check_redirect(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.sessions.with_streaming_response.check_redirect( "sessionUuid", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" session = await response.parse() - assert_matches_type(SessionCheckRedirectResponse, session, path=['response']) + assert_matches_type(SessionCheckRedirectResponse, session, path=["response"]) assert cast(Any, response.is_closed) is True @@ -107,6 +103,6 @@ async def test_streaming_response_check_redirect(self, async_client: AsyncOzAPI) @parametrize async def test_path_params_check_redirect(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_uuid` but received ''"): - await async_client.agent.sessions.with_raw_response.check_redirect( - "", - ) \ No newline at end of file + await async_client.agent.sessions.with_raw_response.check_redirect( + "", + ) diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index 5593546..d7d463e 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -2,35 +2,31 @@ from __future__ import annotations -from oz_agent_sdk import OzAPI, AsyncOzAPI - -from oz_agent_sdk.types import AgentListResponse, AgentGetArtifactResponse, AgentListEnvironmentsResponse, AgentRunResponse - -from typing import cast, Any - import os +from typing import Any, cast + import pytest -import httpx -from typing_extensions import get_args -from respx import MockRouter -from oz_agent_sdk import OzAPI, AsyncOzAPI + from tests.utils import assert_matches_type -from oz_agent_sdk.types import agent_list_params -from oz_agent_sdk.types import agent_list_environments_params -from oz_agent_sdk.types import agent_run_params -from oz_agent_sdk.types import AmbientAgentConfig +from oz_agent_sdk import OzAPI, AsyncOzAPI +from oz_agent_sdk.types import ( + AgentRunResponse, + AgentListResponse, + AgentGetArtifactResponse, + AgentListEnvironmentsResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -class TestAgent: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=['loose', 'strict']) +class TestAgent: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list(self, client: OzAPI) -> None: agent = client.agent.list() - assert_matches_type(AgentListResponse, agent, path=['response']) + assert_matches_type(AgentListResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -41,28 +37,27 @@ def test_method_list_with_all_params(self, client: OzAPI) -> None: repo="repo", sort_by="name", ) - assert_matches_type(AgentListResponse, agent, path=['response']) + assert_matches_type(AgentListResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_list(self, client: OzAPI) -> None: - response = client.agent.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentListResponse, agent, path=['response']) + assert_matches_type(AgentListResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_list(self, client: OzAPI) -> None: - with client.agent.with_streaming_response.list() as response : + with client.agent.with_streaming_response.list() as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentListResponse, agent, path=['response']) + assert_matches_type(AgentListResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -72,32 +67,31 @@ def test_method_get_artifact(self, client: OzAPI) -> None: agent = client.agent.get_artifact( "artifactUid", ) - assert_matches_type(AgentGetArtifactResponse, agent, path=['response']) + assert_matches_type(AgentGetArtifactResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_get_artifact(self, client: OzAPI) -> None: - response = client.agent.with_raw_response.get_artifact( "artifactUid", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentGetArtifactResponse, agent, path=['response']) + assert_matches_type(AgentGetArtifactResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_get_artifact(self, client: OzAPI) -> None: with client.agent.with_streaming_response.get_artifact( "artifactUid", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentGetArtifactResponse, agent, path=['response']) + assert_matches_type(AgentGetArtifactResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -105,15 +99,15 @@ def test_streaming_response_get_artifact(self, client: OzAPI) -> None: @parametrize def test_path_params_get_artifact(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `artifact_uid` but received ''"): - client.agent.with_raw_response.get_artifact( - "", - ) + client.agent.with_raw_response.get_artifact( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list_environments(self, client: OzAPI) -> None: agent = client.agent.list_environments() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -121,28 +115,27 @@ def test_method_list_environments_with_all_params(self, client: OzAPI) -> None: agent = client.agent.list_environments( sort_by="name", ) - assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_list_environments(self, client: OzAPI) -> None: - response = client.agent.with_raw_response.list_environments() assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_list_environments(self, client: OzAPI) -> None: - with client.agent.with_streaming_response.list_environments() as response : + with client.agent.with_streaming_response.list_environments() as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -150,25 +143,25 @@ def test_streaming_response_list_environments(self, client: OzAPI) -> None: @parametrize def test_method_run(self, client: OzAPI) -> None: agent = client.agent.run() - assert_matches_type(AgentRunResponse, agent, path=['response']) + assert_matches_type(AgentRunResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_run_with_all_params(self, client: OzAPI) -> None: agent = client.agent.run( agent_identity_uid="agent_identity_uid", - attachments=[{ - "data": "U3RhaW5sZXNzIHJvY2tz", - "file_name": "file_name", - "mime_type": "mime_type", - }], + attachments=[ + { + "data": "U3RhaW5sZXNzIHJvY2tz", + "file_name": "file_name", + "mime_type": "mime_type", + } + ], config={ "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "type": "oz" - }, + "harness": {"type": "oz"}, "harness_auth_secrets": { "claude_auth_secret_name": "claude_auth_secret_name", "codex_auth_secret_name": "codex_auth_secret_name", @@ -185,26 +178,22 @@ def test_method_run_with_all_params(self, client: OzAPI) -> None: "foo": { "args": ["string"], "command": "command", - "env": { - "foo": "string" - }, - "headers": { - "foo": "string" - }, + "env": {"foo": "string"}, + "headers": {"foo": "string"}, "url": "https://example.com", "warp_id": "warp_id", } }, - "memory_stores": [{ - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - }], + "memory_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], "model_id": "model_id", "name": "name", - "session_sharing": { - "public_access": "VIEWER" - }, + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "skills": ["string"], "worker_host": "worker_host", @@ -218,39 +207,41 @@ def test_method_run_with_all_params(self, client: OzAPI) -> None: team=True, title="title", ) - assert_matches_type(AgentRunResponse, agent, path=['response']) + assert_matches_type(AgentRunResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_run(self, client: OzAPI) -> None: - response = client.agent.with_raw_response.run() assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentRunResponse, agent, path=['response']) + assert_matches_type(AgentRunResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_run(self, client: OzAPI) -> None: - with client.agent.with_streaming_response.run() as response : + with client.agent.with_streaming_response.run() as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = response.parse() - assert_matches_type(AgentRunResponse, agent, path=['response']) + assert_matches_type(AgentRunResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True -class TestAsyncAgent: - parametrize = pytest.mark.parametrize("async_client", [False, True, {'http_client': 'aiohttp'}], indirect=True, ids=['loose', 'strict', 'aiohttp']) +class TestAsyncAgent: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.list() - assert_matches_type(AgentListResponse, agent, path=['response']) + assert_matches_type(AgentListResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -261,28 +252,27 @@ async def test_method_list_with_all_params(self, async_client: AsyncOzAPI) -> No repo="repo", sort_by="name", ) - assert_matches_type(AgentListResponse, agent, path=['response']) + assert_matches_type(AgentListResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_list(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.with_raw_response.list() assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentListResponse, agent, path=['response']) + assert_matches_type(AgentListResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_list(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.with_streaming_response.list() as response : + async with async_client.agent.with_streaming_response.list() as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentListResponse, agent, path=['response']) + assert_matches_type(AgentListResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -292,32 +282,31 @@ async def test_method_get_artifact(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.get_artifact( "artifactUid", ) - assert_matches_type(AgentGetArtifactResponse, agent, path=['response']) + assert_matches_type(AgentGetArtifactResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_get_artifact(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.with_raw_response.get_artifact( "artifactUid", ) assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentGetArtifactResponse, agent, path=['response']) + assert_matches_type(AgentGetArtifactResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_get_artifact(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.with_streaming_response.get_artifact( "artifactUid", - ) as response : + ) as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentGetArtifactResponse, agent, path=['response']) + assert_matches_type(AgentGetArtifactResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -325,15 +314,15 @@ async def test_streaming_response_get_artifact(self, async_client: AsyncOzAPI) - @parametrize async def test_path_params_get_artifact(self, async_client: AsyncOzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `artifact_uid` but received ''"): - await async_client.agent.with_raw_response.get_artifact( - "", - ) + await async_client.agent.with_raw_response.get_artifact( + "", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list_environments(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.list_environments() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -341,28 +330,27 @@ async def test_method_list_environments_with_all_params(self, async_client: Asyn agent = await async_client.agent.list_environments( sort_by="name", ) - assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_list_environments(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.with_raw_response.list_environments() assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_list_environments(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.with_streaming_response.list_environments() as response : + async with async_client.agent.with_streaming_response.list_environments() as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=['response']) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) assert cast(Any, response.is_closed) is True @@ -370,25 +358,25 @@ async def test_streaming_response_list_environments(self, async_client: AsyncOzA @parametrize async def test_method_run(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.run() - assert_matches_type(AgentRunResponse, agent, path=['response']) + assert_matches_type(AgentRunResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.run( agent_identity_uid="agent_identity_uid", - attachments=[{ - "data": "U3RhaW5sZXNzIHJvY2tz", - "file_name": "file_name", - "mime_type": "mime_type", - }], + attachments=[ + { + "data": "U3RhaW5sZXNzIHJvY2tz", + "file_name": "file_name", + "mime_type": "mime_type", + } + ], config={ "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "type": "oz" - }, + "harness": {"type": "oz"}, "harness_auth_secrets": { "claude_auth_secret_name": "claude_auth_secret_name", "codex_auth_secret_name": "codex_auth_secret_name", @@ -405,26 +393,22 @@ async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> Non "foo": { "args": ["string"], "command": "command", - "env": { - "foo": "string" - }, - "headers": { - "foo": "string" - }, + "env": {"foo": "string"}, + "headers": {"foo": "string"}, "url": "https://example.com", "warp_id": "warp_id", } }, - "memory_stores": [{ - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - }], + "memory_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], "model_id": "model_id", "name": "name", - "session_sharing": { - "public_access": "VIEWER" - }, + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "skills": ["string"], "worker_host": "worker_host", @@ -438,27 +422,26 @@ async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> Non team=True, title="title", ) - assert_matches_type(AgentRunResponse, agent, path=['response']) + assert_matches_type(AgentRunResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_run(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.with_raw_response.run() assert response.is_closed is True - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentRunResponse, agent, path=['response']) + assert_matches_type(AgentRunResponse, agent, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_run(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.with_streaming_response.run() as response : + async with async_client.agent.with_streaming_response.run() as response: assert not response.is_closed - assert response.http_request.headers.get('X-Stainless-Lang') == 'python' + assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent = await response.parse() - assert_matches_type(AgentRunResponse, agent, path=['response']) + assert_matches_type(AgentRunResponse, agent, path=["response"]) - assert cast(Any, response.is_closed) is True \ No newline at end of file + assert cast(Any, response.is_closed) is True diff --git a/tests/conftest.py b/tests/conftest.py index 1dc9683..5884465 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,31 +2,25 @@ from __future__ import annotations +import os import logging +from typing import TYPE_CHECKING, Iterator, AsyncIterator import httpx - -from oz_agent_sdk import OzAPI, DefaultAioHttpClient, AsyncOzAPI - -from oz_agent_sdk._utils import is_dict - -import logging -from typing import Iterator - import pytest from pytest_asyncio import is_async_test -import os -from typing import TYPE_CHECKING, AsyncIterator -from oz_agent_sdk import OzAPI, AsyncOzAPI +from oz_agent_sdk import OzAPI, AsyncOzAPI, DefaultAioHttpClient +from oz_agent_sdk._utils import is_dict if TYPE_CHECKING: - from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage] + from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage] pytest.register_assert_rewrite("tests.utils") logging.getLogger("oz_agent_sdk").setLevel(logging.DEBUG) + # automatically add `pytest.mark.asyncio()` to all of our async tests # so we don't have to add that boilerplate everywhere def pytest_collection_modifyitems(items: list[pytest.Function]) -> None: @@ -41,26 +35,29 @@ def pytest_collection_modifyitems(items: list[pytest.Function]) -> None: if "async_client" not in item.fixturenames or "respx_mock" not in item.fixturenames: continue - if not hasattr(item, 'callspec'): - continue + if not hasattr(item, "callspec"): + continue async_client_param = item.callspec.params.get("async_client") if is_dict(async_client_param) and async_client_param.get("http_client") == "aiohttp": item.add_marker(pytest.mark.skip(reason="aiohttp client is not compatible with respx_mock")) + base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My API Key" + @pytest.fixture(scope="session") def client(request: FixtureRequest) -> Iterator[OzAPI]: - strict = getattr(request, 'param', True) + strict = getattr(request, "param", True) if not isinstance(strict, bool): - raise TypeError(f'Unexpected fixture parameter type {type(strict)}, expected {bool}') + raise TypeError(f"Unexpected fixture parameter type {type(strict)}, expected {bool}") - with OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client : + with OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client: yield client + @pytest.fixture(scope="session") async def async_client(request: FixtureRequest) -> AsyncIterator[AsyncOzAPI]: param = getattr(request, "param", True) @@ -81,5 +78,7 @@ async def async_client(request: FixtureRequest) -> AsyncIterator[AsyncOzAPI]: else: raise TypeError(f"Unexpected fixture parameter type {type(param)}, expected bool or dict") - async with AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=strict, http_client=http_client) as client : - yield client \ No newline at end of file + async with AsyncOzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=strict, http_client=http_client + ) as client: + yield client diff --git a/tests/test_client.py b/tests/test_client.py index d3a0d01..988622f 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -2,109 +2,106 @@ from __future__ import annotations -import dataclasses - -import pytest - +import gc +import os import sys - -import httpx - -from oz_agent_sdk import OzAPI, AsyncOzAPI - -from oz_agent_sdk._exceptions import APITimeoutError, APIStatusError, OzAPIError, APIResponseValidationError - -from typing import TypeVar, Callable, Coroutine, Iterable, Optional, Iterator, cast, Any, Union - -from typing_extensions import override, AsyncIterator, Literal - -from oz_agent_sdk._types import Omit - -from pydantic import ValidationError - -from oz_agent_sdk._base_client import DefaultHttpxClient, get_platform, OtherPlatform, DefaultAsyncHttpxClient - -from oz_agent_sdk._utils import asyncify - +import json import asyncio -import gc import inspect -import json -import os +import dataclasses import tracemalloc +from typing import Any, Union, TypeVar, Callable, Iterable, Iterator, Optional, Coroutine, cast from unittest import mock +from typing_extensions import Literal, AsyncIterator, override import httpx import pytest from respx import MockRouter +from pydantic import ValidationError from oz_agent_sdk import OzAPI, AsyncOzAPI, APIResponseValidationError -from oz_agent_sdk._models import FinalRequestOptions, BaseModel -from oz_agent_sdk._types import Headers, Query, Body, Timeout, Omit -from oz_agent_sdk._base_client import DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, BaseClient, RequestOptions, make_request_options -from oz_agent_sdk._streaming import Stream, AsyncStream -from oz_agent_sdk._constants import RAW_RESPONSE_HEADER -from oz_agent_sdk._response import APIResponse, AsyncAPIResponse from oz_agent_sdk._types import Omit +from oz_agent_sdk._utils import asyncify +from oz_agent_sdk._models import BaseModel, FinalRequestOptions +from oz_agent_sdk._exceptions import OzAPIError, APIStatusError, APITimeoutError, APIResponseValidationError +from oz_agent_sdk._base_client import ( + DEFAULT_TIMEOUT, + HTTPX_DEFAULT_TIMEOUT, + BaseClient, + OtherPlatform, + DefaultHttpxClient, + DefaultAsyncHttpxClient, + get_platform, + make_request_options, +) + from .utils import update_env T = TypeVar("T") base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My API Key" + def _get_params(client: BaseClient[Any, Any]) -> dict[str, str]: - request = client._build_request(FinalRequestOptions(method="get", url='/foo')) - url = httpx.URL(request.url) - return dict(url.params) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + url = httpx.URL(request.url) + return dict(url.params) + def _low_retry_timeout(*_args: Any, **_kwargs: Any) -> float: return 0.1 + def mirror_request_content(request: httpx.Request) -> httpx.Response: - return httpx.Response(200, content=request.content) + return httpx.Response(200, content=request.content) + # note: we can't use the httpx.MockTransport class as it consumes the request # body itself, which means we can't test that the body is read lazily class MockTransport(httpx.BaseTransport, httpx.AsyncBaseTransport): - def __init__( - self, - handler: Callable[[httpx.Request], httpx.Response] - | Callable[[httpx.Request], Coroutine[Any, Any, httpx.Response]], - ) -> None: - self.handler = handler - - @override - def handle_request( - self, - request: httpx.Request, - ) -> httpx.Response: - assert not inspect.iscoroutinefunction(self.handler), "handler must not be a coroutine function" - assert inspect.isfunction(self.handler), "handler must be a function" - return self.handler(request) - - @override - async def handle_async_request( - self, - request: httpx.Request, - ) -> httpx.Response: - assert inspect.iscoroutinefunction(self.handler), "handler must be a coroutine function" - return await self.handler(request) + def __init__( + self, + handler: Callable[[httpx.Request], httpx.Response] + | Callable[[httpx.Request], Coroutine[Any, Any, httpx.Response]], + ) -> None: + self.handler = handler + + @override + def handle_request( + self, + request: httpx.Request, + ) -> httpx.Response: + assert not inspect.iscoroutinefunction(self.handler), "handler must not be a coroutine function" + assert inspect.isfunction(self.handler), "handler must be a function" + return self.handler(request) + + @override + async def handle_async_request( + self, + request: httpx.Request, + ) -> httpx.Response: + assert inspect.iscoroutinefunction(self.handler), "handler must be a coroutine function" + return await self.handler(request) + @dataclasses.dataclass class Counter: value: int = 0 + def _make_sync_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> Iterator[T]: - for item in iterable: - if counter: - counter.value += 1 - yield item + for item in iterable: + if counter: + counter.value += 1 + yield item + async def _make_async_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> AsyncIterator[T]: - for item in iterable: - if counter: - counter.value += 1 - yield item + for item in iterable: + if counter: + counter.value += 1 + yield item + def _get_open_connections(client: OzAPI | AsyncOzAPI) -> int: transport = client._client._transport @@ -113,6 +110,7 @@ def _get_open_connections(client: OzAPI | AsyncOzAPI) -> int: pool = transport._pool return len(pool._requests) + class TestOzAPI: @pytest.mark.respx(base_url=base_url) def test_raw_response(self, respx_mock: MockRouter, client: OzAPI) -> None: @@ -125,7 +123,9 @@ def test_raw_response(self, respx_mock: MockRouter, client: OzAPI) -> None: @pytest.mark.respx(base_url=base_url) def test_raw_response_for_binary(self, respx_mock: MockRouter, client: OzAPI) -> None: - respx_mock.post("/foo").mock(return_value=httpx.Response(200, headers={'Content-Type':'application/binary'}, content='{"foo": "bar"}')) + respx_mock.post("/foo").mock( + return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') + ) response = client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 @@ -157,59 +157,59 @@ def test_copy_default_options(self, client: OzAPI) -> None: assert isinstance(client.timeout, httpx.Timeout) def test_copy_default_headers(self) -> None: - client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ - "X-Foo": "bar" - }) - assert client.default_headers['X-Foo'] == 'bar' + client = OzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} + ) + assert client.default_headers["X-Foo"] == "bar" # does not override the already given value when not specified copied = client.copy() - assert copied.default_headers['X-Foo'] == 'bar' + assert copied.default_headers["X-Foo"] == "bar" # merges already given headers - copied = client.copy(default_headers={'X-Bar': 'stainless'}) - assert copied.default_headers['X-Foo'] == 'bar' - assert copied.default_headers['X-Bar'] == 'stainless' + copied = client.copy(default_headers={"X-Bar": "stainless"}) + assert copied.default_headers["X-Foo"] == "bar" + assert copied.default_headers["X-Bar"] == "stainless" # uses new values for any already given headers - copied = client.copy(default_headers={'X-Foo': 'stainless'}) - assert copied.default_headers['X-Foo'] == 'stainless' + copied = client.copy(default_headers={"X-Foo": "stainless"}) + assert copied.default_headers["X-Foo"] == "stainless" # set_default_headers # completely overrides already set values copied = client.copy(set_default_headers={}) - assert copied.default_headers.get('X-Foo') is None + assert copied.default_headers.get("X-Foo") is None - copied = client.copy(set_default_headers={'X-Bar': 'Robert'}) - assert copied.default_headers['X-Bar'] == 'Robert' + copied = client.copy(set_default_headers={"X-Bar": "Robert"}) + assert copied.default_headers["X-Bar"] == "Robert" with pytest.raises( - ValueError, - match='`default_headers` and `set_default_headers` arguments are mutually exclusive', + ValueError, + match="`default_headers` and `set_default_headers` arguments are mutually exclusive", ): - client.copy(set_default_headers={}, default_headers={'X-Foo': 'Bar'}) + client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) client.close() def test_copy_default_query(self) -> None: - client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={ - "foo": "bar" - }) - assert _get_params(client)['foo'] == 'bar' + client = OzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} + ) + assert _get_params(client)["foo"] == "bar" # does not override the already given value when not specified copied = client.copy() - assert _get_params(copied)['foo'] == 'bar' + assert _get_params(copied)["foo"] == "bar" # merges already given params - copied = client.copy(default_query={'bar': 'stainless'}) + copied = client.copy(default_query={"bar": "stainless"}) params = _get_params(copied) - assert params['foo'] == 'bar' - assert params['bar'] == 'stainless' + assert params["foo"] == "bar" + assert params["bar"] == "stainless" # uses new values for any already given headers - copied = client.copy(default_query={'foo': 'stainless'}) - assert _get_params(copied)['foo'] == 'stainless' + copied = client.copy(default_query={"foo": "stainless"}) + assert _get_params(copied)["foo"] == "stainless" # set_default_query @@ -217,23 +217,23 @@ def test_copy_default_query(self) -> None: copied = client.copy(set_default_query={}) assert _get_params(copied) == {} - copied = client.copy(set_default_query={'bar': 'Robert'}) - assert _get_params(copied)['bar'] == 'Robert' + copied = client.copy(set_default_query={"bar": "Robert"}) + assert _get_params(copied)["bar"] == "Robert" with pytest.raises( - ValueError, - # TODO: update - match='`default_query` and `set_default_query` arguments are mutually exclusive', + ValueError, + # TODO: update + match="`default_query` and `set_default_query` arguments are mutually exclusive", ): - client.copy(set_default_query={}, default_query={'foo': 'Bar'}) + client.copy(set_default_query={}, default_query={"foo": "Bar"}) client.close() def test_copy_signature(self, client: OzAPI) -> None: # ensure the same parameters that can be passed to the client are defined in the `.copy()` method init_signature = inspect.signature( - # mypy doesn't like that we access the `__init__` property. - client.__init__, # type: ignore[misc] + # mypy doesn't like that we access the `__init__` property. + client.__init__, # type: ignore[misc] ) copy_signature = inspect.signature(client.copy) exclude_params = {"transport", "proxies", "_strict_response_validation"} @@ -313,9 +313,7 @@ def test_request_timeout(self, client: OzAPI) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT - request = client._build_request( - FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0)) - ) + request = client._build_request(FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0))) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(100.0) @@ -331,75 +329,89 @@ def test_client_timeout_option(self) -> None: def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used with httpx.Client(timeout=None) as http_client: - client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client) + client = OzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client + ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == httpx.Timeout(None) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == httpx.Timeout(None) - client.close() + client.close() # no timeout given to the httpx client should not use the httpx default with httpx.Client() as http_client: - client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client) + client = OzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client + ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT - client.close() + client.close() # explicitly passing the default timeout currently results in it being ignored with httpx.Client(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: - client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client) + client = OzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client + ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT # our default + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT # our default - client.close() + client.close() async def test_invalid_http_client(self) -> None: - with pytest.raises(TypeError, match='Invalid `http_client` arg') : - async with httpx.AsyncClient() as http_client : - OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=cast(Any, http_client)) + with pytest.raises(TypeError, match="Invalid `http_client` arg"): + async with httpx.AsyncClient() as http_client: + OzAPI( + base_url=base_url, + api_key=api_key, + _strict_response_validation=True, + http_client=cast(Any, http_client), + ) def test_default_headers_option(self) -> None: - test_client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ - "X-Foo": "bar" - }) - request = test_client._build_request(FinalRequestOptions(method="get", url='/foo')) - assert request.headers.get('x-foo') == 'bar' - assert request.headers.get('x-stainless-lang') == 'python' - - test_client2 = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ - "X-Foo": "stainless", - "X-Stainless-Lang": "my-overriding-header", - }) - request = test_client2._build_request(FinalRequestOptions(method="get", url='/foo')) - assert request.headers.get('x-foo') == 'stainless' - assert request.headers.get('x-stainless-lang') == 'my-overriding-header' + test_client = OzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} + ) + request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) + assert request.headers.get("x-foo") == "bar" + assert request.headers.get("x-stainless-lang") == "python" + + test_client2 = OzAPI( + base_url=base_url, + api_key=api_key, + _strict_response_validation=True, + default_headers={ + "X-Foo": "stainless", + "X-Stainless-Lang": "my-overriding-header", + }, + ) + request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) + assert request.headers.get("x-foo") == "stainless" + assert request.headers.get("x-stainless-lang") == "my-overriding-header" test_client.close() test_client2.close() def test_validate_headers(self) -> None: client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True) - request = client._build_request(FinalRequestOptions(method="get", url='/foo')) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("Authorization") == f"Bearer {api_key}" with pytest.raises(OzAPIError): - with update_env(**{ - "WARP_API_KEY": Omit() - }) : + with update_env(**{"WARP_API_KEY": Omit()}): client2 = OzAPI(base_url=base_url, api_key=None, _strict_response_validation=True) _ = client2 def test_default_query_option(self) -> None: - client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={ - "query_param": "bar" - }) - request = client._build_request(FinalRequestOptions(method="get", url='/foo')) + client = OzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} + ) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) url = httpx.URL(request.url) assert dict(url.params) == {"query_param": "bar"} @@ -411,7 +423,7 @@ def test_default_query_option(self) -> None: ) ) url = httpx.URL(request.url) - assert dict(url.params) == {'foo': 'baz', "query_param": "overridden"} + assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} client.close() @@ -520,7 +532,7 @@ def test_request_extra_query(self, client: OzAPI) -> None: ), ) params = dict(request.url.params) - assert params == {'bar': '1', 'foo': '2'} + assert params == {"bar": "1", "foo": "2"} # `extra_query` takes priority over `query` when keys clash request = client._build_request( @@ -534,7 +546,7 @@ def test_request_extra_query(self, client: OzAPI) -> None: ), ) params = dict(request.url.params) - assert params == {'foo': '2'} + assert params == {"foo": "2"} def test_multipart_repeating_array(self, client: OzAPI) -> None: request = client._build_request( @@ -571,7 +583,12 @@ def test_binary_content_upload(self, respx_mock: MockRouter, client: OzAPI) -> N file_content = b"Hello, this is a test file." - response = client.post("/upload", content=file_content, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}) + response = client.post( + "/upload", + content=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" @@ -586,13 +603,23 @@ def mock_handler(request: httpx.Request) -> httpx.Response: assert counter.value == 0, "the request body should not have been read" return httpx.Response(200, content=request.read()) - with OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=httpx.Client(transport = MockTransport(handler=mock_handler))) as client: - response = client.post("/upload", content=iterator, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}) + with OzAPI( + base_url=base_url, + api_key=api_key, + _strict_response_validation=True, + http_client=httpx.Client(transport=MockTransport(handler=mock_handler)), + ) as client: + response = client.post( + "/upload", + content=iterator, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) - assert response.status_code == 200 - assert response.request.headers["Content-Type"] == "application/octet-stream" - assert response.content == file_content - assert counter.value == 1 + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + assert counter.value == 1 @pytest.mark.respx(base_url=base_url) def test_binary_content_upload_with_body_is_deprecated(self, respx_mock: MockRouter, client: OzAPI) -> None: @@ -603,7 +630,12 @@ def test_binary_content_upload_with_body_is_deprecated(self, respx_mock: MockRou with pytest.deprecated_call( match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." ): - response = client.post("/upload", body=file_content, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}) + response = client.post( + "/upload", + body=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" @@ -617,27 +649,29 @@ class Model1(BaseModel): class Model2(BaseModel): foo: str - respx_mock.get('/foo').mock(return_value=httpx.Response(200, json={'foo': 'bar'})) + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) - assert response.foo == 'bar' + assert response.foo == "bar" + @pytest.mark.respx(base_url=base_url) def test_union_response_different_types(self, respx_mock: MockRouter, client: OzAPI) -> None: """Union of objects with the same field name using a different type""" + class Model1(BaseModel): foo: int class Model2(BaseModel): foo: str - respx_mock.get('/foo').mock(return_value=httpx.Response(200, json={'foo': 'bar'})) + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) - assert response.foo == 'bar' + assert response.foo == "bar" - respx_mock.get('/foo').mock(return_value=httpx.Response(200, json={'foo': 1})) + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model1) @@ -648,6 +682,7 @@ def test_non_application_json_content_type_for_json_data(self, respx_mock: MockR """ Response that sets Content-Type to something other than application/json but returns json data """ + class Model(BaseModel): foo: int @@ -674,11 +709,23 @@ def test_base_url_setter(self) -> None: client.close() def test_base_url_env(self) -> None: - with update_env(OZ_API_BASE_URL='http://localhost:5000/from/env'): - client = OzAPI(api_key=api_key, _strict_response_validation=True) - assert client.base_url == 'http://localhost:5000/from/env/' + with update_env(OZ_API_BASE_URL="http://localhost:5000/from/env"): + client = OzAPI(api_key=api_key, _strict_response_validation=True) + assert client.base_url == "http://localhost:5000/from/env/" - @pytest.mark.parametrize("client", [OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.Client())], ids = ["standard", "custom http client"]) + @pytest.mark.parametrize( + "client", + [ + OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), + OzAPI( + base_url="http://localhost:5000/custom/path/", + api_key=api_key, + _strict_response_validation=True, + http_client=httpx.Client(), + ), + ], + ids=["standard", "custom http client"], + ) def test_base_url_trailing_slash(self, client: OzAPI) -> None: request = client._build_request( FinalRequestOptions( @@ -690,7 +737,19 @@ def test_base_url_trailing_slash(self, client: OzAPI) -> None: assert request.url == "http://localhost:5000/custom/path/foo" client.close() - @pytest.mark.parametrize("client", [OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.Client())], ids = ["standard", "custom http client"]) + @pytest.mark.parametrize( + "client", + [ + OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), + OzAPI( + base_url="http://localhost:5000/custom/path/", + api_key=api_key, + _strict_response_validation=True, + http_client=httpx.Client(), + ), + ], + ids=["standard", "custom http client"], + ) def test_base_url_no_trailing_slash(self, client: OzAPI) -> None: request = client._build_request( FinalRequestOptions( @@ -702,7 +761,19 @@ def test_base_url_no_trailing_slash(self, client: OzAPI) -> None: assert request.url == "http://localhost:5000/custom/path/foo" client.close() - @pytest.mark.parametrize("client", [OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.Client())], ids = ["standard", "custom http client"]) + @pytest.mark.parametrize( + "client", + [ + OzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), + OzAPI( + base_url="http://localhost:5000/custom/path/", + api_key=api_key, + _strict_response_validation=True, + http_client=httpx.Client(), + ), + ], + ids=["standard", "custom http client"], + ) def test_absolute_request_url(self, client: OzAPI) -> None: request = client._build_request( FinalRequestOptions( @@ -728,9 +799,9 @@ def test_copied_client_does_not_close_http(self) -> None: def test_client_context_manager(self) -> None: test_client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True) with test_client as c2: - assert c2 is test_client - assert not c2.is_closed() - assert not test_client.is_closed() + assert c2 is test_client + assert not c2.is_closed() + assert not test_client.is_closed() assert test_client.is_closed() @pytest.mark.respx(base_url=base_url) @@ -747,7 +818,7 @@ class Model(BaseModel): def test_client_max_retries_validation(self) -> None: with pytest.raises(TypeError, match=r"max_retries cannot be None"): - OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None)) + OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None)) @pytest.mark.respx(base_url=base_url) def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: @@ -759,7 +830,7 @@ class Model(BaseModel): strict_client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True) with pytest.raises(APIResponseValidationError): - strict_client.get("/foo", cast_to=Model) + strict_client.get("/foo", cast_to=Model) non_strict_client = OzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=False) @@ -770,32 +841,34 @@ class Model(BaseModel): non_strict_client.close() @pytest.mark.parametrize( - "remaining_retries,retry_after,timeout", - [ - [ 3, "20", 20 ], - [ 3, "0", 0.5 ], - [ 3, "-10", 0.5 ], - [ 3, "60", 60 ], - [ 3, "61", 0.5 ], - [ 3, "Fri, 29 Sep 2023 16:26:57 GMT", 20 ], - [ 3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5 ], - [ 3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5 ], - [ 3, "Fri, 29 Sep 2023 16:27:37 GMT", 60 ], - [ 3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5 ], - [ 3, "99999999999999999999999999999999999", 0.5 ], - [ 3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5 ], - [ 3, "", 0.5 ], - [ 2, "", 0.5 * 2.0 ], - [ 1, "", 0.5 * 4.0 ], - [-1100, "", 8], # test large number potentially overflowing - ], - ) + "remaining_retries,retry_after,timeout", + [ + [3, "20", 20], + [3, "0", 0.5], + [3, "-10", 0.5], + [3, "60", 60], + [3, "61", 0.5], + [3, "Fri, 29 Sep 2023 16:26:57 GMT", 20], + [3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5], + [3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5], + [3, "Fri, 29 Sep 2023 16:27:37 GMT", 60], + [3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5], + [3, "99999999999999999999999999999999999", 0.5], + [3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5], + [3, "", 0.5], + [2, "", 0.5 * 2.0], + [1, "", 0.5 * 4.0], + [-1100, "", 8], # test large number potentially overflowing + ], + ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) - def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float, client: OzAPI) -> None: + def test_parse_retry_after_header( + self, remaining_retries: int, retry_after: str, timeout: float, client: OzAPI + ) -> None: headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) calculated = client._calculate_retry_timeout(remaining_retries, options, headers) - assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] + assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] @mock.patch("oz_agent_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @@ -825,7 +898,7 @@ def test_retries_taken( client: OzAPI, failures_before_success: int, failure_mode: Literal["status", "exception"], - respx_mock: MockRouter + respx_mock: MockRouter, ) -> None: client = client.with_options(max_retries=4) @@ -836,7 +909,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: if nb_retries < failures_before_success: nb_retries += 1 if failure_mode == "exception": - raise RuntimeError("oops") + raise RuntimeError("oops") return httpx.Response(500) return httpx.Response(200) @@ -850,12 +923,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("oz_agent_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - def test_omit_retry_count_header( - self, - client: OzAPI, - failures_before_success: int, - respx_mock: MockRouter - ) -> None: + def test_omit_retry_count_header(self, client: OzAPI, failures_before_success: int, respx_mock: MockRouter) -> None: client = client.with_options(max_retries=4) nb_retries = 0 @@ -869,18 +937,15 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/agent/runs").mock(side_effect=retry_handler) - response = client.agent.with_raw_response.run(extra_headers={'x-stainless-retry-count': Omit()}) + response = client.agent.with_raw_response.run(extra_headers={"x-stainless-retry-count": Omit()}) - assert len(response.http_request.headers.get_list('x-stainless-retry-count')) == 0 + assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("oz_agent_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_overwrite_retry_count_header( - self, - client: OzAPI, - failures_before_success: int, - respx_mock: MockRouter + self, client: OzAPI, failures_before_success: int, respx_mock: MockRouter ) -> None: client = client.with_options(max_retries=4) @@ -895,9 +960,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/agent/runs").mock(side_effect=retry_handler) - response = client.agent.with_raw_response.run(extra_headers={'x-stainless-retry-count': '42'}) + response = client.agent.with_raw_response.run(extra_headers={"x-stainless-retry-count": "42"}) - assert response.http_request.headers.get('x-stainless-retry-count') == '42' + assert response.http_request.headers.get("x-stainless-retry-count") == "42" def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: # Test that the proxy environment variables are set correctly @@ -953,6 +1018,8 @@ def test_follow_redirects_disabled(self, respx_mock: MockRouter, client: OzAPI) assert exc_info.value.response.status_code == 302 assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" + + class TestAsyncOzAPI: @pytest.mark.respx(base_url=base_url) async def test_raw_response(self, respx_mock: MockRouter, async_client: AsyncOzAPI) -> None: @@ -965,7 +1032,9 @@ async def test_raw_response(self, respx_mock: MockRouter, async_client: AsyncOzA @pytest.mark.respx(base_url=base_url) async def test_raw_response_for_binary(self, respx_mock: MockRouter, async_client: AsyncOzAPI) -> None: - respx_mock.post("/foo").mock(return_value=httpx.Response(200, headers={'Content-Type':'application/binary'}, content='{"foo": "bar"}')) + respx_mock.post("/foo").mock( + return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') + ) response = await async_client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 @@ -997,59 +1066,59 @@ def test_copy_default_options(self, async_client: AsyncOzAPI) -> None: assert isinstance(async_client.timeout, httpx.Timeout) async def test_copy_default_headers(self) -> None: - client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ - "X-Foo": "bar" - }) - assert client.default_headers['X-Foo'] == 'bar' + client = AsyncOzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} + ) + assert client.default_headers["X-Foo"] == "bar" # does not override the already given value when not specified copied = client.copy() - assert copied.default_headers['X-Foo'] == 'bar' + assert copied.default_headers["X-Foo"] == "bar" # merges already given headers - copied = client.copy(default_headers={'X-Bar': 'stainless'}) - assert copied.default_headers['X-Foo'] == 'bar' - assert copied.default_headers['X-Bar'] == 'stainless' + copied = client.copy(default_headers={"X-Bar": "stainless"}) + assert copied.default_headers["X-Foo"] == "bar" + assert copied.default_headers["X-Bar"] == "stainless" # uses new values for any already given headers - copied = client.copy(default_headers={'X-Foo': 'stainless'}) - assert copied.default_headers['X-Foo'] == 'stainless' + copied = client.copy(default_headers={"X-Foo": "stainless"}) + assert copied.default_headers["X-Foo"] == "stainless" # set_default_headers # completely overrides already set values copied = client.copy(set_default_headers={}) - assert copied.default_headers.get('X-Foo') is None + assert copied.default_headers.get("X-Foo") is None - copied = client.copy(set_default_headers={'X-Bar': 'Robert'}) - assert copied.default_headers['X-Bar'] == 'Robert' + copied = client.copy(set_default_headers={"X-Bar": "Robert"}) + assert copied.default_headers["X-Bar"] == "Robert" with pytest.raises( - ValueError, - match='`default_headers` and `set_default_headers` arguments are mutually exclusive', + ValueError, + match="`default_headers` and `set_default_headers` arguments are mutually exclusive", ): - client.copy(set_default_headers={}, default_headers={'X-Foo': 'Bar'}) + client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) await client.close() async def test_copy_default_query(self) -> None: - client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={ - "foo": "bar" - }) - assert _get_params(client)['foo'] == 'bar' + client = AsyncOzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} + ) + assert _get_params(client)["foo"] == "bar" # does not override the already given value when not specified copied = client.copy() - assert _get_params(copied)['foo'] == 'bar' + assert _get_params(copied)["foo"] == "bar" # merges already given params - copied = client.copy(default_query={'bar': 'stainless'}) + copied = client.copy(default_query={"bar": "stainless"}) params = _get_params(copied) - assert params['foo'] == 'bar' - assert params['bar'] == 'stainless' + assert params["foo"] == "bar" + assert params["bar"] == "stainless" # uses new values for any already given headers - copied = client.copy(default_query={'foo': 'stainless'}) - assert _get_params(copied)['foo'] == 'stainless' + copied = client.copy(default_query={"foo": "stainless"}) + assert _get_params(copied)["foo"] == "stainless" # set_default_query @@ -1057,23 +1126,23 @@ async def test_copy_default_query(self) -> None: copied = client.copy(set_default_query={}) assert _get_params(copied) == {} - copied = client.copy(set_default_query={'bar': 'Robert'}) - assert _get_params(copied)['bar'] == 'Robert' + copied = client.copy(set_default_query={"bar": "Robert"}) + assert _get_params(copied)["bar"] == "Robert" with pytest.raises( - ValueError, - # TODO: update - match='`default_query` and `set_default_query` arguments are mutually exclusive', + ValueError, + # TODO: update + match="`default_query` and `set_default_query` arguments are mutually exclusive", ): - client.copy(set_default_query={}, default_query={'foo': 'Bar'}) + client.copy(set_default_query={}, default_query={"foo": "Bar"}) await client.close() def test_copy_signature(self, async_client: AsyncOzAPI) -> None: # ensure the same parameters that can be passed to the client are defined in the `.copy()` method init_signature = inspect.signature( - # mypy doesn't like that we access the `__init__` property. - async_client.__init__, # type: ignore[misc] + # mypy doesn't like that we access the `__init__` property. + async_client.__init__, # type: ignore[misc] ) copy_signature = inspect.signature(async_client.copy) exclude_params = {"transport", "proxies", "_strict_response_validation"} @@ -1160,7 +1229,9 @@ async def test_request_timeout(self, async_client: AsyncOzAPI) -> None: assert timeout == httpx.Timeout(100.0) async def test_client_timeout_option(self) -> None: - client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0)) + client = AsyncOzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0) + ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore @@ -1171,75 +1242,89 @@ async def test_client_timeout_option(self) -> None: async def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used async with httpx.AsyncClient(timeout=None) as http_client: - client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client) + client = AsyncOzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client + ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == httpx.Timeout(None) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == httpx.Timeout(None) - await client.close() + await client.close() # no timeout given to the httpx client should not use the httpx default async with httpx.AsyncClient() as http_client: - client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client) + client = AsyncOzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client + ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT - await client.close() + await client.close() # explicitly passing the default timeout currently results in it being ignored async with httpx.AsyncClient(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: - client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client) + client = AsyncOzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client + ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT # our default + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT # our default - await client.close() + await client.close() def test_invalid_http_client(self) -> None: - with pytest.raises(TypeError, match='Invalid `http_client` arg') : - with httpx.Client() as http_client : - AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=cast(Any, http_client)) + with pytest.raises(TypeError, match="Invalid `http_client` arg"): + with httpx.Client() as http_client: + AsyncOzAPI( + base_url=base_url, + api_key=api_key, + _strict_response_validation=True, + http_client=cast(Any, http_client), + ) async def test_default_headers_option(self) -> None: - test_client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ - "X-Foo": "bar" - }) - request = test_client._build_request(FinalRequestOptions(method="get", url='/foo')) - assert request.headers.get('x-foo') == 'bar' - assert request.headers.get('x-stainless-lang') == 'python' - - test_client2 = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ - "X-Foo": "stainless", - "X-Stainless-Lang": "my-overriding-header", - }) - request = test_client2._build_request(FinalRequestOptions(method="get", url='/foo')) - assert request.headers.get('x-foo') == 'stainless' - assert request.headers.get('x-stainless-lang') == 'my-overriding-header' + test_client = AsyncOzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} + ) + request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) + assert request.headers.get("x-foo") == "bar" + assert request.headers.get("x-stainless-lang") == "python" + + test_client2 = AsyncOzAPI( + base_url=base_url, + api_key=api_key, + _strict_response_validation=True, + default_headers={ + "X-Foo": "stainless", + "X-Stainless-Lang": "my-overriding-header", + }, + ) + request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) + assert request.headers.get("x-foo") == "stainless" + assert request.headers.get("x-stainless-lang") == "my-overriding-header" await test_client.close() await test_client2.close() def test_validate_headers(self) -> None: client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True) - request = client._build_request(FinalRequestOptions(method="get", url='/foo')) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("Authorization") == f"Bearer {api_key}" with pytest.raises(OzAPIError): - with update_env(**{ - "WARP_API_KEY": Omit() - }) : + with update_env(**{"WARP_API_KEY": Omit()}): client2 = AsyncOzAPI(base_url=base_url, api_key=None, _strict_response_validation=True) _ = client2 async def test_default_query_option(self) -> None: - client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={ - "query_param": "bar" - }) - request = client._build_request(FinalRequestOptions(method="get", url='/foo')) + client = AsyncOzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} + ) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) url = httpx.URL(request.url) assert dict(url.params) == {"query_param": "bar"} @@ -1251,7 +1336,7 @@ async def test_default_query_option(self) -> None: ) ) url = httpx.URL(request.url) - assert dict(url.params) == {'foo': 'baz', "query_param": "overridden"} + assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} await client.close() @@ -1360,7 +1445,7 @@ def test_request_extra_query(self, client: OzAPI) -> None: ), ) params = dict(request.url.params) - assert params == {'bar': '1', 'foo': '2'} + assert params == {"bar": "1", "foo": "2"} # `extra_query` takes priority over `query` when keys clash request = client._build_request( @@ -1374,7 +1459,7 @@ def test_request_extra_query(self, client: OzAPI) -> None: ), ) params = dict(request.url.params) - assert params == {'foo': '2'} + assert params == {"foo": "2"} def test_multipart_repeating_array(self, async_client: AsyncOzAPI) -> None: request = async_client._build_request( @@ -1411,7 +1496,12 @@ async def test_binary_content_upload(self, respx_mock: MockRouter, async_client: file_content = b"Hello, this is a test file." - response = await async_client.post("/upload", content=file_content, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}) + response = await async_client.post( + "/upload", + content=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" @@ -1426,16 +1516,28 @@ async def mock_handler(request: httpx.Request) -> httpx.Response: assert counter.value == 0, "the request body should not have been read" return httpx.Response(200, content=await request.aread()) - async with AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient(transport = MockTransport(handler=mock_handler))) as client: - response = await client.post("/upload", content=iterator, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}) + async with AsyncOzAPI( + base_url=base_url, + api_key=api_key, + _strict_response_validation=True, + http_client=httpx.AsyncClient(transport=MockTransport(handler=mock_handler)), + ) as client: + response = await client.post( + "/upload", + content=iterator, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) - assert response.status_code == 200 - assert response.request.headers["Content-Type"] == "application/octet-stream" - assert response.content == file_content - assert counter.value == 1 + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + assert counter.value == 1 @pytest.mark.respx(base_url=base_url) - async def test_binary_content_upload_with_body_is_deprecated(self, respx_mock: MockRouter, async_client: AsyncOzAPI) -> None: + async def test_binary_content_upload_with_body_is_deprecated( + self, respx_mock: MockRouter, async_client: AsyncOzAPI + ) -> None: respx_mock.post("/upload").mock(side_effect=mirror_request_content) file_content = b"Hello, this is a test file." @@ -1443,7 +1545,12 @@ async def test_binary_content_upload_with_body_is_deprecated(self, respx_mock: M with pytest.deprecated_call( match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." ): - response = await async_client.post("/upload", body=file_content, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}) + response = await async_client.post( + "/upload", + body=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" @@ -1457,37 +1564,42 @@ class Model1(BaseModel): class Model2(BaseModel): foo: str - respx_mock.get('/foo').mock(return_value=httpx.Response(200, json={'foo': 'bar'})) + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) - assert response.foo == 'bar' + assert response.foo == "bar" + @pytest.mark.respx(base_url=base_url) async def test_union_response_different_types(self, respx_mock: MockRouter, async_client: AsyncOzAPI) -> None: """Union of objects with the same field name using a different type""" + class Model1(BaseModel): foo: int class Model2(BaseModel): foo: str - respx_mock.get('/foo').mock(return_value=httpx.Response(200, json={'foo': 'bar'})) + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) - assert response.foo == 'bar' + assert response.foo == "bar" - respx_mock.get('/foo').mock(return_value=httpx.Response(200, json={'foo': 1})) + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model1) assert response.foo == 1 @pytest.mark.respx(base_url=base_url) - async def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter, async_client: AsyncOzAPI) -> None: + async def test_non_application_json_content_type_for_json_data( + self, respx_mock: MockRouter, async_client: AsyncOzAPI + ) -> None: """ Response that sets Content-Type to something other than application/json but returns json data """ + class Model(BaseModel): foo: int @@ -1514,11 +1626,25 @@ async def test_base_url_setter(self) -> None: await client.close() async def test_base_url_env(self) -> None: - with update_env(OZ_API_BASE_URL='http://localhost:5000/from/env'): - client = AsyncOzAPI(api_key=api_key, _strict_response_validation=True) - assert client.base_url == 'http://localhost:5000/from/env/' + with update_env(OZ_API_BASE_URL="http://localhost:5000/from/env"): + client = AsyncOzAPI(api_key=api_key, _strict_response_validation=True) + assert client.base_url == "http://localhost:5000/from/env/" - @pytest.mark.parametrize("client", [AsyncOzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), AsyncOzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient())], ids = ["standard", "custom http client"]) + @pytest.mark.parametrize( + "client", + [ + AsyncOzAPI( + base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True + ), + AsyncOzAPI( + base_url="http://localhost:5000/custom/path/", + api_key=api_key, + _strict_response_validation=True, + http_client=httpx.AsyncClient(), + ), + ], + ids=["standard", "custom http client"], + ) async def test_base_url_trailing_slash(self, client: AsyncOzAPI) -> None: request = client._build_request( FinalRequestOptions( @@ -1530,7 +1656,21 @@ async def test_base_url_trailing_slash(self, client: AsyncOzAPI) -> None: assert request.url == "http://localhost:5000/custom/path/foo" await client.close() - @pytest.mark.parametrize("client", [AsyncOzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), AsyncOzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient())], ids = ["standard", "custom http client"]) + @pytest.mark.parametrize( + "client", + [ + AsyncOzAPI( + base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True + ), + AsyncOzAPI( + base_url="http://localhost:5000/custom/path/", + api_key=api_key, + _strict_response_validation=True, + http_client=httpx.AsyncClient(), + ), + ], + ids=["standard", "custom http client"], + ) async def test_base_url_no_trailing_slash(self, client: AsyncOzAPI) -> None: request = client._build_request( FinalRequestOptions( @@ -1542,7 +1682,21 @@ async def test_base_url_no_trailing_slash(self, client: AsyncOzAPI) -> None: assert request.url == "http://localhost:5000/custom/path/foo" await client.close() - @pytest.mark.parametrize("client", [AsyncOzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), AsyncOzAPI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient())], ids = ["standard", "custom http client"]) + @pytest.mark.parametrize( + "client", + [ + AsyncOzAPI( + base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True + ), + AsyncOzAPI( + base_url="http://localhost:5000/custom/path/", + api_key=api_key, + _strict_response_validation=True, + http_client=httpx.AsyncClient(), + ), + ], + ids=["standard", "custom http client"], + ) async def test_absolute_request_url(self, client: AsyncOzAPI) -> None: request = client._build_request( FinalRequestOptions( @@ -1569,9 +1723,9 @@ async def test_copied_client_does_not_close_http(self) -> None: async def test_client_context_manager(self) -> None: test_client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True) async with test_client as c2: - assert c2 is test_client - assert not c2.is_closed() - assert not test_client.is_closed() + assert c2 is test_client + assert not c2.is_closed() + assert not test_client.is_closed() assert test_client.is_closed() @pytest.mark.respx(base_url=base_url) @@ -1588,7 +1742,9 @@ class Model(BaseModel): async def test_client_max_retries_validation(self) -> None: with pytest.raises(TypeError, match=r"max_retries cannot be None"): - AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None)) + AsyncOzAPI( + base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None) + ) @pytest.mark.respx(base_url=base_url) async def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: @@ -1600,7 +1756,7 @@ class Model(BaseModel): strict_client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=True) with pytest.raises(APIResponseValidationError): - await strict_client.get("/foo", cast_to=Model) + await strict_client.get("/foo", cast_to=Model) non_strict_client = AsyncOzAPI(base_url=base_url, api_key=api_key, _strict_response_validation=False) @@ -1611,32 +1767,34 @@ class Model(BaseModel): await non_strict_client.close() @pytest.mark.parametrize( - "remaining_retries,retry_after,timeout", - [ - [ 3, "20", 20 ], - [ 3, "0", 0.5 ], - [ 3, "-10", 0.5 ], - [ 3, "60", 60 ], - [ 3, "61", 0.5 ], - [ 3, "Fri, 29 Sep 2023 16:26:57 GMT", 20 ], - [ 3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5 ], - [ 3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5 ], - [ 3, "Fri, 29 Sep 2023 16:27:37 GMT", 60 ], - [ 3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5 ], - [ 3, "99999999999999999999999999999999999", 0.5 ], - [ 3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5 ], - [ 3, "", 0.5 ], - [ 2, "", 0.5 * 2.0 ], - [ 1, "", 0.5 * 4.0 ], - [-1100, "", 8], # test large number potentially overflowing - ], - ) + "remaining_retries,retry_after,timeout", + [ + [3, "20", 20], + [3, "0", 0.5], + [3, "-10", 0.5], + [3, "60", 60], + [3, "61", 0.5], + [3, "Fri, 29 Sep 2023 16:26:57 GMT", 20], + [3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5], + [3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5], + [3, "Fri, 29 Sep 2023 16:27:37 GMT", 60], + [3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5], + [3, "99999999999999999999999999999999999", 0.5], + [3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5], + [3, "", 0.5], + [2, "", 0.5 * 2.0], + [1, "", 0.5 * 4.0], + [-1100, "", 8], # test large number potentially overflowing + ], + ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) - async def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float, async_client: AsyncOzAPI) -> None: + async def test_parse_retry_after_header( + self, remaining_retries: int, retry_after: str, timeout: float, async_client: AsyncOzAPI + ) -> None: headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) calculated = async_client._calculate_retry_timeout(remaining_retries, options, headers) - assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] + assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] @mock.patch("oz_agent_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @@ -1666,7 +1824,7 @@ async def test_retries_taken( async_client: AsyncOzAPI, failures_before_success: int, failure_mode: Literal["status", "exception"], - respx_mock: MockRouter + respx_mock: MockRouter, ) -> None: client = async_client.with_options(max_retries=4) @@ -1677,7 +1835,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: if nb_retries < failures_before_success: nb_retries += 1 if failure_mode == "exception": - raise RuntimeError("oops") + raise RuntimeError("oops") return httpx.Response(500) return httpx.Response(200) @@ -1692,10 +1850,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @mock.patch("oz_agent_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_omit_retry_count_header( - self, - async_client: AsyncOzAPI, - failures_before_success: int, - respx_mock: MockRouter + self, async_client: AsyncOzAPI, failures_before_success: int, respx_mock: MockRouter ) -> None: client = async_client.with_options(max_retries=4) @@ -1710,18 +1865,15 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/agent/runs").mock(side_effect=retry_handler) - response = await client.agent.with_raw_response.run(extra_headers={'x-stainless-retry-count': Omit()}) + response = await client.agent.with_raw_response.run(extra_headers={"x-stainless-retry-count": Omit()}) - assert len(response.http_request.headers.get_list('x-stainless-retry-count')) == 0 + assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("oz_agent_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_overwrite_retry_count_header( - self, - async_client: AsyncOzAPI, - failures_before_success: int, - respx_mock: MockRouter + self, async_client: AsyncOzAPI, failures_before_success: int, respx_mock: MockRouter ) -> None: client = async_client.with_options(max_retries=4) @@ -1736,9 +1888,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/agent/runs").mock(side_effect=retry_handler) - response = await client.agent.with_raw_response.run(extra_headers={'x-stainless-retry-count': '42'}) + response = await client.agent.with_raw_response.run(extra_headers={"x-stainless-retry-count": "42"}) - assert response.http_request.headers.get('x-stainless-retry-count') == '42' + assert response.http_request.headers.get("x-stainless-retry-count") == "42" async def test_get_platform(self) -> None: platform = await asyncify(get_platform)() @@ -1794,7 +1946,9 @@ async def test_follow_redirects_disabled(self, respx_mock: MockRouter, async_cli ) with pytest.raises(APIStatusError) as exc_info: - await async_client.post("/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response) + await async_client.post( + "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response + ) assert exc_info.value.response.status_code == 302 - assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" \ No newline at end of file + assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index c378416..c7d7add 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -4,7 +4,7 @@ import pytest -from oz_agent_sdk._types import ArrayFormat, FileTypes +from oz_agent_sdk._types import FileTypes, ArrayFormat from oz_agent_sdk._utils import extract_files @@ -28,7 +28,10 @@ def test_removes_files_from_input() -> None: def test_multiple_files() -> None: query = {"documents": [{"file": b"My first file"}, {"file": b"My second file"}]} - assert extract_files(query, paths=[["documents", "", "file"]]) == [("documents[][file]", b"My first file"), ("documents[][file]", b"My second file")] + assert extract_files(query, paths=[["documents", "", "file"]]) == [ + ("documents[][file]", b"My first file"), + ("documents[][file]", b"My second file"), + ] assert query == {"documents": [{}, {}]} @@ -82,13 +85,7 @@ def test_array_format_controls_file_field_names( 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 - ) + 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 - ) + 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 3f0fe1c..393aa1a 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -4,7 +4,7 @@ import pytest from dirty_equals import IsDict, IsList, IsBytes, IsTuple -from oz_agent_sdk._files import async_to_httpx_files, deepcopy_with_paths, to_httpx_files +from oz_agent_sdk._files import to_httpx_files, deepcopy_with_paths, async_to_httpx_files from oz_agent_sdk._utils import extract_files readme_path = Path(__file__).parent.parent.joinpath("README.md") diff --git a/tests/test_models.py b/tests/test_models.py index 3c7f182..ae6ec09 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,7 +1,7 @@ import json -from collections import deque from typing import TYPE_CHECKING, Any, Dict, List, Union, Iterable, Optional, cast from datetime import datetime, timezone +from collections import deque from typing_extensions import Literal, Annotated, TypedDict, TypeAliasType import pytest diff --git a/tests/test_response.py b/tests/test_response.py index 407d828..b81481c 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -6,7 +6,7 @@ import pytest import pydantic -from oz_agent_sdk import BaseModel, OzAPI, AsyncOzAPI +from oz_agent_sdk import OzAPI, BaseModel, AsyncOzAPI from oz_agent_sdk._response import ( APIResponse, BaseAPIResponse, diff --git a/tests/test_streaming.py b/tests/test_streaming.py index ace9284..b9b682f 100644 --- a/tests/test_streaming.py +++ b/tests/test_streaming.py @@ -28,9 +28,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_data_missing_event( - sync: bool, client: OzAPI, async_client: AsyncOzAPI -) -> None: +async def test_data_missing_event(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: def body() -> Iterator[bytes]: yield b'data: {"foo":true}\n' yield b"\n" @@ -46,9 +44,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_event_missing_data( - sync: bool, client: OzAPI, async_client: AsyncOzAPI -) -> None: +async def test_event_missing_data(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"\n" @@ -64,9 +60,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_events( - sync: bool, client: OzAPI, async_client: AsyncOzAPI -) -> None: +async def test_multiple_events(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"\n" @@ -88,9 +82,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_events_with_data( - sync: bool, client: OzAPI, async_client: AsyncOzAPI -) -> None: +async def test_multiple_events_with_data(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b'data: {"foo":true}\n' @@ -114,9 +106,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_data_lines_with_empty_line( - sync: bool, client: OzAPI, async_client: AsyncOzAPI -) -> None: +async def test_multiple_data_lines_with_empty_line(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"data: {\n" @@ -138,9 +128,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_data_json_escaped_double_new_line( - sync: bool, client: OzAPI, async_client: AsyncOzAPI -) -> None: +async def test_data_json_escaped_double_new_line(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b'data: {"foo": "my long\\n\\ncontent"}' @@ -157,9 +145,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_data_lines( - sync: bool, client: OzAPI, async_client: AsyncOzAPI -) -> None: +async def test_multiple_data_lines(sync: bool, client: OzAPI, async_client: AsyncOzAPI) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"data: {\n" diff --git a/tests/test_transform.py b/tests/test_transform.py index a7385fa..6b1bb6b 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -8,7 +8,7 @@ import pytest -from oz_agent_sdk._types import not_given, omit, Base64FileInput +from oz_agent_sdk._types import Base64FileInput, omit, not_given from oz_agent_sdk._utils import ( PropertyInfo, transform as _transform, diff --git a/tests/test_utils/test_datetime_parse.py b/tests/test_utils/test_datetime_parse.py index 3b5c823..de12854 100644 --- a/tests/test_utils/test_datetime_parse.py +++ b/tests/test_utils/test_datetime_parse.py @@ -7,6 +7,7 @@ from datetime import date, datetime, timezone, timedelta import pytest + from oz_agent_sdk._utils import parse_date, parse_datetime diff --git a/tests/utils.py b/tests/utils.py index 526ea2e..3e9d221 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -4,7 +4,7 @@ import inspect import traceback import contextlib -from typing import Any, Sequence, TypeVar, Iterator, cast +from typing import Any, TypeVar, Iterator, Sequence, cast from datetime import date, datetime from typing_extensions import Literal, get_args, get_origin, assert_type @@ -13,9 +13,9 @@ is_dict, is_list, is_list_type, - is_sequence_type, is_union_type, extract_type_arg, + is_sequence_type, is_annotated_type, is_type_alias_type, ) From 80a6ba1ae7b72a47cb4b392c969894bc9c7760b1 Mon Sep 17 00:00:00 2001 From: Ian Hodge Date: Wed, 17 Jun 2026 15:10:32 -0400 Subject: [PATCH 08/14] ci: restore test job as sealed custom code Stainless-Generated-From: eee2b456017cc9a6c2d997b01b231302525d2ebb --- .github/workflows/ci.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2f2ce9..78b4056 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,3 +55,22 @@ jobs: - name: Run build run: uv build + + test: + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') + timeout-minutes: 10 + name: test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 + with: + version: '0.10.2' + + - name: Bootstrap + run: ./scripts/bootstrap + + - name: Run tests + run: ./scripts/test From ed25fd46853fe06a7b8ae1e89bb96cef77ea61b6 Mon Sep 17 00:00:00 2001 From: stlc-bot Date: Mon, 22 Jun 2026 17:56:25 +0000 Subject: [PATCH 09/14] chore: reseal python stlc tracking file to current staging main Stainless-Generated-From: 5141d1e8fe237b2a0f3c9a69dbdb4b24865a097e --- src/oz_agent_sdk/resources/agent/agent_.py | 30 ++++----- .../types/agent/agent_create_params.py | 37 ++++++++--- .../types/agent/agent_response.py | 56 ++++++++++++++-- .../types/agent/agent_update_params.py | 24 ++++--- tests/api_resources/agent/test_agent_.py | 66 +++++++++++-------- 5 files changed, 144 insertions(+), 69 deletions(-) diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py index 65eb4d5..7294d3b 100644 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -58,7 +58,7 @@ def create( harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, inference_providers: agent_create_params.InferenceProviders | Omit = omit, mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, - memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, + memory: agent_create_params.Memory | Omit = omit, prompt: Optional[str] | Omit = omit, secrets: Iterable[agent_create_params.Secret] | Omit = omit, skills: SequenceNotStr[str] | Omit = omit, @@ -94,9 +94,7 @@ def create( mcp_servers: Optional map of MCP server configurations by name to attach to runs executed by this agent. Run-level MCP config takes precedence over this agent-level default. - memory_stores: Optional list of memory stores to attach to the agent. Each store must be - team-owned by the same team as the agent. Duplicate UIDs within a single request - are rejected. + memory: Memory settings for creating an agent. prompt: Optional base prompt for this agent @@ -131,7 +129,7 @@ def create( "harness_auth_secrets": harness_auth_secrets, "inference_providers": inference_providers, "mcp_servers": mcp_servers, - "memory_stores": memory_stores, + "memory": memory, "prompt": prompt, "secrets": secrets, "skills": skills, @@ -155,7 +153,7 @@ def update( harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, - memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, + memory: Optional[agent_update_params.Memory] | Omit = omit, name: str | Omit = omit, prompt: Optional[str] | Omit = omit, secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, @@ -193,8 +191,7 @@ def update( pass an empty object to clear, or pass a non-empty object to replace. Run-level MCP config takes precedence over this agent-level default. - memory_stores: Replacement list of memory stores. Omit to leave unchanged, pass an empty array - to clear, or pass a non-empty array to replace. + memory: Memory settings for updating an agent. name: The new name for the agent @@ -228,7 +225,7 @@ def update( "harness_auth_secrets": harness_auth_secrets, "inference_providers": inference_providers, "mcp_servers": mcp_servers, - "memory_stores": memory_stores, + "memory": memory, "name": name, "prompt": prompt, "secrets": secrets, @@ -370,7 +367,7 @@ async def create( harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, inference_providers: agent_create_params.InferenceProviders | Omit = omit, mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, - memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, + memory: agent_create_params.Memory | Omit = omit, prompt: Optional[str] | Omit = omit, secrets: Iterable[agent_create_params.Secret] | Omit = omit, skills: SequenceNotStr[str] | Omit = omit, @@ -406,9 +403,7 @@ async def create( mcp_servers: Optional map of MCP server configurations by name to attach to runs executed by this agent. Run-level MCP config takes precedence over this agent-level default. - memory_stores: Optional list of memory stores to attach to the agent. Each store must be - team-owned by the same team as the agent. Duplicate UIDs within a single request - are rejected. + memory: Memory settings for creating an agent. prompt: Optional base prompt for this agent @@ -443,7 +438,7 @@ async def create( "harness_auth_secrets": harness_auth_secrets, "inference_providers": inference_providers, "mcp_servers": mcp_servers, - "memory_stores": memory_stores, + "memory": memory, "prompt": prompt, "secrets": secrets, "skills": skills, @@ -467,7 +462,7 @@ async def update( harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, - memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, + memory: Optional[agent_update_params.Memory] | Omit = omit, name: str | Omit = omit, prompt: Optional[str] | Omit = omit, secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, @@ -505,8 +500,7 @@ async def update( pass an empty object to clear, or pass a non-empty object to replace. Run-level MCP config takes precedence over this agent-level default. - memory_stores: Replacement list of memory stores. Omit to leave unchanged, pass an empty array - to clear, or pass a non-empty array to replace. + memory: Memory settings for updating an agent. name: The new name for the agent @@ -540,7 +534,7 @@ async def update( "harness_auth_secrets": harness_auth_secrets, "inference_providers": inference_providers, "mcp_servers": mcp_servers, - "memory_stores": memory_stores, + "memory": memory, "name": name, "prompt": prompt, "secrets": secrets, diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py index 798e05d..c69586c 100644 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -13,7 +13,9 @@ "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws", - "MemoryStore", + "Memory", + "MemoryAttachedStore", + "MemoryAutoMemory", "Secret", ] @@ -52,12 +54,8 @@ class AgentCreateParams(TypedDict, total=False): this agent. Run-level MCP config takes precedence over this agent-level default. """ - memory_stores: Iterable[MemoryStore] - """ - Optional list of memory stores to attach to the agent. Each store must be - team-owned by the same team as the agent. Duplicate UIDs within a single request - are rejected. - """ + memory: Memory + """Memory settings for creating an agent.""" prompt: Optional[str] """Optional base prompt for this agent""" @@ -123,7 +121,7 @@ class InferenceProviders(TypedDict, total=False): """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" -class MemoryStore(TypedDict, total=False): +class MemoryAttachedStore(TypedDict, total=False): """Reference to a memory store to attach to an agent.""" access: Required[Literal["read_write", "read_only"]] @@ -136,6 +134,29 @@ class MemoryStore(TypedDict, total=False): """UID of the memory store.""" +class MemoryAutoMemory(TypedDict, total=False): + """Auto-memory settings for creating an agent.""" + + enabled: bool + """ + Whether to create and attach a default service-account-owned memory store for + this agent. Defaults to true when omitted. + """ + + +class Memory(TypedDict, total=False): + """Memory settings for creating an agent.""" + + attached_stores: Iterable[MemoryAttachedStore] + """ + Existing team memory stores to attach to the agent. Duplicate UIDs within a + single request are rejected. + """ + + auto_memory: MemoryAutoMemory + """Auto-memory settings for creating an agent.""" + + class Secret(TypedDict, total=False): """Reference to a managed secret by name.""" diff --git a/src/oz_agent_sdk/types/agent/agent_response.py b/src/oz_agent_sdk/types/agent/agent_response.py index 37d13b9..1ad9a40 100644 --- a/src/oz_agent_sdk/types/agent/agent_response.py +++ b/src/oz_agent_sdk/types/agent/agent_response.py @@ -9,7 +9,10 @@ __all__ = [ "AgentResponse", - "MemoryStore", + "Memory", + "MemoryAttachedStore", + "MemoryAutoMemory", + "MemoryAutoMemoryStore", "Secret", "HarnessAuthSecrets", "InferenceProviders", @@ -17,7 +20,7 @@ ] -class MemoryStore(BaseModel): +class MemoryAttachedStore(BaseModel): """Reference to a memory store to attach to an agent.""" access: Literal["read_write", "read_only"] @@ -30,6 +33,48 @@ class MemoryStore(BaseModel): """UID of the memory store.""" +class MemoryAutoMemoryStore(BaseModel): + """Memory store attached to an agent.""" + + access: Literal["read_write", "read_only"] + """Access level for the store.""" + + instructions: str + """Instructions for how the agent should use this memory store.""" + + owner_type: Literal["user", "service_account", "team"] + """Public owner type.""" + + owner_uid: str + """Public UID of the user, service account, or team that owns the memory store.""" + + uid: str + """UID of the memory store.""" + + description: Optional[str] = None + """Optional description for the memory store.""" + + +class MemoryAutoMemory(BaseModel): + """Auto-memory state for an agent.""" + + enabled: bool + """Whether this agent has an agent-owned memory store.""" + + store: Optional[MemoryAutoMemoryStore] = None + """Memory store attached to an agent.""" + + +class Memory(BaseModel): + """Memory settings for an agent.""" + + attached_stores: List[MemoryAttachedStore] + """Team memory stores attached to the agent.""" + + auto_memory: MemoryAutoMemory + """Auto-memory state for an agent.""" + + class Secret(BaseModel): """Reference to a managed secret by name.""" @@ -88,11 +133,8 @@ class AgentResponse(BaseModel): created_at: datetime """When the agent was created (RFC3339)""" - memory_stores: List[MemoryStore] - """ - Memory stores attached to this agent. Always present; empty when no stores are - attached. - """ + memory: Memory + """Memory settings for an agent.""" name: str """Name of the agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_update_params.py b/src/oz_agent_sdk/types/agent/agent_update_params.py index 19082d4..0d4c4d7 100644 --- a/src/oz_agent_sdk/types/agent/agent_update_params.py +++ b/src/oz_agent_sdk/types/agent/agent_update_params.py @@ -13,7 +13,8 @@ "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws", - "MemoryStore", + "Memory", + "MemoryAttachedStore", "Secret", ] @@ -60,12 +61,8 @@ class AgentUpdateParams(TypedDict, total=False): default. """ - memory_stores: Optional[Iterable[MemoryStore]] - """Replacement list of memory stores. - - Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array - to replace. - """ + memory: Optional[Memory] + """Memory settings for updating an agent.""" name: str """The new name for the agent""" @@ -135,7 +132,7 @@ class InferenceProviders(TypedDict, total=False): """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" -class MemoryStore(TypedDict, total=False): +class MemoryAttachedStore(TypedDict, total=False): """Reference to a memory store to attach to an agent.""" access: Required[Literal["read_write", "read_only"]] @@ -148,6 +145,17 @@ class MemoryStore(TypedDict, total=False): """UID of the memory store.""" +class Memory(TypedDict, total=False): + """Memory settings for updating an agent.""" + + attached_stores: Optional[Iterable[MemoryAttachedStore]] + """Replacement list of attached team memory stores. + + Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array + to replace. + """ + + class Secret(TypedDict, total=False): """Reference to a managed secret by name.""" diff --git a/tests/api_resources/agent/test_agent_.py b/tests/api_resources/agent/test_agent_.py index dbc1785..cec38f5 100644 --- a/tests/api_resources/agent/test_agent_.py +++ b/tests/api_resources/agent/test_agent_.py @@ -58,13 +58,16 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "warp_id": "warp_id", } }, - memory_stores=[ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + memory={ + "attached_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], + "auto_memory": {"enabled": True}, + }, prompt="prompt", secrets=[{"name": "name"}], skills=["string"], @@ -135,13 +138,15 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "warp_id": "warp_id", } }, - memory_stores=[ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + memory={ + "attached_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ] + }, name="name", prompt="prompt", secrets=[{"name": "name"}], @@ -339,13 +344,16 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "warp_id": "warp_id", } }, - memory_stores=[ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + memory={ + "attached_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], + "auto_memory": {"enabled": True}, + }, prompt="prompt", secrets=[{"name": "name"}], skills=["string"], @@ -416,13 +424,15 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "warp_id": "warp_id", } }, - memory_stores=[ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", - } - ], + memory={ + "attached_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ] + }, name="name", prompt="prompt", secrets=[{"name": "name"}], From 5ad6a6e49f2eb5769f839db25267eb605d81c674 Mon Sep 17 00:00:00 2001 From: liliwilson Date: Wed, 24 Jun 2026 15:30:28 +0000 Subject: [PATCH 10/14] fix(deps): seal aiohttp>=3.14.1, pytest>=9.0.3, pygments>=2.20.0 CVE fixes - aiohttp restricted to python_version>='3.10' + >=3.14.1: resolves CVE-2026-34993, CVE-2026-47265, CVE-2026-54273 through CVE-2026-54280, CVE-2026-50269 - pytest>=9.0.3 (python_version>='3.10' constraint): resolves CVE-2025-71176 - pygments>=2.20.0: resolves CVE-2026-4539 (ReDoS) Stainless-Generated-From: ed25fd46853fe06a7b8ae1e89bb96cef77ea61b6 Co-Authored-By: Oz --- pyproject.toml | 14 ++- requirements-dev.lock | 8 +- uv.lock | 196 ++++++------------------------------------ 3 files changed, 42 insertions(+), 176 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2d37867..d6d05c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,10 @@ Homepage = "https://github.com/warpdotdev/oz-sdk-python" Repository = "https://github.com/warpdotdev/oz-sdk-python" [project.optional-dependencies] -aiohttp = ["aiohttp>=3.13.5", "httpx_aiohttp>=0.1.9"] +# Security pin: aiohttp<3.14.0 is vulnerable to multiple CVEs (CVE-2026-34993, +# CVE-2026-47265, CVE-2026-54273 through CVE-2026-54280, CVE-2026-50269). +# aiohttp 3.14.x dropped Python 3.9 support, so restrict to python_version >= '3.10'. +aiohttp = ["aiohttp>=3.14.1; python_version >= '3.10'", "httpx_aiohttp>=0.1.9; python_version >= '3.10'"] [tool.uv] managed = true @@ -50,7 +53,14 @@ required-version = ">=0.9" # declared above. Versions <3.15 are vulnerable to CVE-2026-45409 # (GHSA-65pc-fj4g-8rjx), so constrain it without adding it as a direct # dependency. Sealed as custom code so it survives SDK regeneration. -constraint-dependencies = ["idna>=3.15"] +constraint-dependencies = [ + "idna>=3.15", + # Security pin: pytest<9.0.3 is vulnerable to CVE-2025-71176 (tmpdir handling). + # pytest 9.0.3 requires Python>=3.10; pin only for compatible versions. + "pytest>=9.0.3; python_version >= '3.10'", + # Security pin: pygments<2.20.0 is vulnerable to CVE-2026-4539 (ReDoS). + "pygments>=2.20.0", +] conflicts = [ [ { group = "pydantic-v1" }, diff --git a/requirements-dev.lock b/requirements-dev.lock index f34eca7..5ff1150 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -1,5 +1,5 @@ # This file was autogenerated by uv via the following command: -# uv export -o requirements-dev.lock --no-hashes +# uv export --group dev --no-hashes -e . annotated-types==0.7.0 # via pydantic @@ -32,7 +32,7 @@ httpx==0.28.1 # via # oz-agent-sdk # respx -idna==3.11 +idna==3.18 # via # anyio # httpx @@ -62,7 +62,7 @@ pydantic==2.12.5 # via oz-agent-sdk pydantic-core==2.41.5 # via pydantic -pygments==2.19.2 +pygments==2.20.0 # via # pytest # rich @@ -71,7 +71,7 @@ pytest==8.4.2 ; python_full_version < '3.10' # via # pytest-asyncio # pytest-xdist -pytest==9.0.2 ; python_full_version >= '3.10' +pytest==9.1.1 ; python_full_version >= '3.10' # via # pytest-asyncio # pytest-xdist diff --git a/uv.lock b/uv.lock index 13132d8..ddf0935 100644 --- a/uv.lock +++ b/uv.lock @@ -16,7 +16,11 @@ conflicts = [[ ]] [manifest] -constraints = [{ name = "idna", specifier = ">=3.15" }] +constraints = [ + { name = "idna", specifier = ">=3.15" }, + { name = "pygments", specifier = ">=2.20.0" }, + { name = "pytest", marker = "python_full_version >= '3.10'", specifier = ">=9.0.3" }, +] [[package]] name = "aiohappyeyeballs" @@ -27,156 +31,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, ] -[[package]] -name = "aiohttp" -version = "3.13.5" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "aiohappyeyeballs", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "aiosignal", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "async-timeout", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "attrs", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "frozenlist", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "multidict", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "propcache", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "yarl", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/77/9a/152096d4808df8e4268befa55fba462f440f14beab85e8ad9bf990516918/aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1", size = 7858271, upload-time = "2026-03-31T22:01:03.343Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/85/cebc47ee74d8b408749073a1a46c6fcba13d170dc8af7e61996c6c9394ac/aiohttp-3.13.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b", size = 750547, upload-time = "2026-03-31T21:56:30.024Z" }, - { url = "https://files.pythonhosted.org/packages/05/98/afd308e35b9d3d8c9ec54c0918f1d722c86dc17ddfec272fcdbcce5a3124/aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5", size = 503535, upload-time = "2026-03-31T21:56:31.935Z" }, - { url = "https://files.pythonhosted.org/packages/6f/4d/926c183e06b09d5270a309eb50fbde7b09782bfd305dec1e800f329834fb/aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670", size = 497830, upload-time = "2026-03-31T21:56:33.654Z" }, - { url = "https://files.pythonhosted.org/packages/e4/d6/f47d1c690f115a5c2a5e8938cce4a232a5be9aac5c5fb2647efcbbbda333/aiohttp-3.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274", size = 1682474, upload-time = "2026-03-31T21:56:35.513Z" }, - { url = "https://files.pythonhosted.org/packages/01/44/056fd37b1bb52eac760303e5196acc74d9d546631b035704ae5927f7b4ac/aiohttp-3.13.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a", size = 1655259, upload-time = "2026-03-31T21:56:37.843Z" }, - { url = "https://files.pythonhosted.org/packages/91/9f/78eb1a20c1c28ae02f6a3c0f4d7b0dcc66abce5290cadd53d78ce3084175/aiohttp-3.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d", size = 1736204, upload-time = "2026-03-31T21:56:39.822Z" }, - { url = "https://files.pythonhosted.org/packages/de/6c/d20d7de23f0b52b8c1d9e2033b2db1ac4dacbb470bb74c56de0f5f86bb4f/aiohttp-3.13.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796", size = 1826198, upload-time = "2026-03-31T21:56:41.378Z" }, - { url = "https://files.pythonhosted.org/packages/2f/86/a6f3ff1fd795f49545a7c74b2c92f62729135d73e7e4055bf74da5a26c82/aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95", size = 1681329, upload-time = "2026-03-31T21:56:43.374Z" }, - { url = "https://files.pythonhosted.org/packages/fb/68/84cd3dab6b7b4f3e6fe9459a961acb142aaab846417f6e8905110d7027e5/aiohttp-3.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5", size = 1560023, upload-time = "2026-03-31T21:56:45.031Z" }, - { url = "https://files.pythonhosted.org/packages/41/2c/db61b64b0249e30f954a65ab4cb4970ced57544b1de2e3c98ee5dc24165f/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a", size = 1652372, upload-time = "2026-03-31T21:56:47.075Z" }, - { url = "https://files.pythonhosted.org/packages/25/6f/e96988a6c982d047810c772e28c43c64c300c943b0ed5c1c0c4ce1e1027c/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73", size = 1662031, upload-time = "2026-03-31T21:56:48.835Z" }, - { url = "https://files.pythonhosted.org/packages/b7/26/a56feace81f3d347b4052403a9d03754a0ab23f7940780dada0849a38c92/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297", size = 1708118, upload-time = "2026-03-31T21:56:50.833Z" }, - { url = "https://files.pythonhosted.org/packages/78/6e/b6173a8ff03d01d5e1a694bc06764b5dad1df2d4ed8f0ceec12bb3277936/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074", size = 1548667, upload-time = "2026-03-31T21:56:52.81Z" }, - { url = "https://files.pythonhosted.org/packages/16/13/13296ffe2c132d888b3fe2c195c8b9c0c24c89c3fa5cc2c44464dc23b22e/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e", size = 1724490, upload-time = "2026-03-31T21:56:54.541Z" }, - { url = "https://files.pythonhosted.org/packages/7a/b4/1f1c287f4a79782ef36e5a6e62954c85343bc30470d862d30bd5f26c9fa2/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7", size = 1667109, upload-time = "2026-03-31T21:56:56.21Z" }, - { url = "https://files.pythonhosted.org/packages/ef/42/8461a2aaf60a8f4ea4549a4056be36b904b0eb03d97ca9a8a2604681a500/aiohttp-3.13.5-cp310-cp310-win32.whl", hash = "sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9", size = 439478, upload-time = "2026-03-31T21:56:58.292Z" }, - { url = "https://files.pythonhosted.org/packages/e5/71/06956304cb5ee439dfe8d86e1b2e70088bd88ed1ced1f42fb29e5d855f0e/aiohttp-3.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76", size = 462047, upload-time = "2026-03-31T21:57:00.257Z" }, - { url = "https://files.pythonhosted.org/packages/d6/f5/a20c4ac64aeaef1679e25c9983573618ff765d7aa829fa2b84ae7573169e/aiohttp-3.13.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6", size = 757513, upload-time = "2026-03-31T21:57:02.146Z" }, - { url = "https://files.pythonhosted.org/packages/75/0a/39fa6c6b179b53fcb3e4b3d2b6d6cad0180854eda17060c7218540102bef/aiohttp-3.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d", size = 506748, upload-time = "2026-03-31T21:57:04.275Z" }, - { url = "https://files.pythonhosted.org/packages/87/ec/e38ce072e724fd7add6243613f8d1810da084f54175353d25ccf9f9c7e5a/aiohttp-3.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c", size = 501673, upload-time = "2026-03-31T21:57:06.208Z" }, - { url = "https://files.pythonhosted.org/packages/ba/ba/3bc7525d7e2beaa11b309a70d48b0d3cfc3c2089ec6a7d0820d59c657053/aiohttp-3.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb", size = 1763757, upload-time = "2026-03-31T21:57:07.882Z" }, - { url = "https://files.pythonhosted.org/packages/5e/ab/e87744cf18f1bd78263aba24924d4953b41086bd3a31d22452378e9028a0/aiohttp-3.13.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6", size = 1720152, upload-time = "2026-03-31T21:57:09.946Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f3/ed17a6f2d742af17b50bae2d152315ed1b164b07a5fd5cc1754d99e4dfa5/aiohttp-3.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13", size = 1818010, upload-time = "2026-03-31T21:57:12.157Z" }, - { url = "https://files.pythonhosted.org/packages/53/06/ecbc63dc937192e2a5cb46df4d3edb21deb8225535818802f210a6ea5816/aiohttp-3.13.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174", size = 1907251, upload-time = "2026-03-31T21:57:14.023Z" }, - { url = "https://files.pythonhosted.org/packages/7e/a5/0521aa32c1ddf3aa1e71dcc466be0b7db2771907a13f18cddaa45967d97b/aiohttp-3.13.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc", size = 1759969, upload-time = "2026-03-31T21:57:16.146Z" }, - { url = "https://files.pythonhosted.org/packages/f6/78/a38f8c9105199dd3b9706745865a8a59d0041b6be0ca0cc4b2ccf1bab374/aiohttp-3.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6", size = 1616871, upload-time = "2026-03-31T21:57:17.856Z" }, - { url = "https://files.pythonhosted.org/packages/6f/41/27392a61ead8ab38072105c71aa44ff891e71653fe53d576a7067da2b4e8/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49", size = 1739844, upload-time = "2026-03-31T21:57:19.679Z" }, - { url = "https://files.pythonhosted.org/packages/6e/55/5564e7ae26d94f3214250009a0b1c65a0c6af4bf88924ccb6fdab901de28/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8", size = 1731969, upload-time = "2026-03-31T21:57:22.006Z" }, - { url = "https://files.pythonhosted.org/packages/6d/c5/705a3929149865fc941bcbdd1047b238e4a72bcb215a9b16b9d7a2e8d992/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d", size = 1795193, upload-time = "2026-03-31T21:57:24.256Z" }, - { url = "https://files.pythonhosted.org/packages/a6/19/edabed62f718d02cff7231ca0db4ef1c72504235bc467f7b67adb1679f48/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c", size = 1606477, upload-time = "2026-03-31T21:57:26.364Z" }, - { url = "https://files.pythonhosted.org/packages/de/fc/76f80ef008675637d88d0b21584596dc27410a990b0918cb1e5776545b5b/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac", size = 1813198, upload-time = "2026-03-31T21:57:28.316Z" }, - { url = "https://files.pythonhosted.org/packages/e5/67/5b3ac26b80adb20ea541c487f73730dc8fa107d632c998f25bbbab98fcda/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3", size = 1752321, upload-time = "2026-03-31T21:57:30.549Z" }, - { url = "https://files.pythonhosted.org/packages/88/06/e4a2e49255ea23fa4feeb5ab092d90240d927c15e47b5b5c48dff5a9ce29/aiohttp-3.13.5-cp311-cp311-win32.whl", hash = "sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06", size = 439069, upload-time = "2026-03-31T21:57:32.388Z" }, - { url = "https://files.pythonhosted.org/packages/c0/43/8c7163a596dab4f8be12c190cf467a1e07e4734cf90eebb39f7f5d53fc6a/aiohttp-3.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8", size = 462859, upload-time = "2026-03-31T21:57:34.455Z" }, - { url = "https://files.pythonhosted.org/packages/be/6f/353954c29e7dcce7cf00280a02c75f30e133c00793c7a2ed3776d7b2f426/aiohttp-3.13.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9", size = 748876, upload-time = "2026-03-31T21:57:36.319Z" }, - { url = "https://files.pythonhosted.org/packages/f5/1b/428a7c64687b3b2e9cd293186695affc0e1e54a445d0361743b231f11066/aiohttp-3.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416", size = 499557, upload-time = "2026-03-31T21:57:38.236Z" }, - { url = "https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2", size = 500258, upload-time = "2026-03-31T21:57:39.923Z" }, - { url = "https://files.pythonhosted.org/packages/67/84/c9ecc5828cb0b3695856c07c0a6817a99d51e2473400f705275a2b3d9239/aiohttp-3.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4", size = 1749199, upload-time = "2026-03-31T21:57:41.938Z" }, - { url = "https://files.pythonhosted.org/packages/f0/d3/3c6d610e66b495657622edb6ae7c7fd31b2e9086b4ec50b47897ad6042a9/aiohttp-3.13.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9", size = 1721013, upload-time = "2026-03-31T21:57:43.904Z" }, - { url = "https://files.pythonhosted.org/packages/49/a0/24409c12217456df0bae7babe3b014e460b0b38a8e60753d6cb339f6556d/aiohttp-3.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5", size = 1781501, upload-time = "2026-03-31T21:57:46.285Z" }, - { url = "https://files.pythonhosted.org/packages/98/9d/b65ec649adc5bccc008b0957a9a9c691070aeac4e41cea18559fef49958b/aiohttp-3.13.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e", size = 1878981, upload-time = "2026-03-31T21:57:48.734Z" }, - { url = "https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1", size = 1767934, upload-time = "2026-03-31T21:57:51.171Z" }, - { url = "https://files.pythonhosted.org/packages/31/04/d3f8211f273356f158e3464e9e45484d3fb8c4ce5eb2f6fe9405c3273983/aiohttp-3.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286", size = 1566671, upload-time = "2026-03-31T21:57:53.326Z" }, - { url = "https://files.pythonhosted.org/packages/41/db/073e4ebe00b78e2dfcacff734291651729a62953b48933d765dc513bf798/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9", size = 1705219, upload-time = "2026-03-31T21:57:55.385Z" }, - { url = "https://files.pythonhosted.org/packages/48/45/7dfba71a2f9fd97b15c95c06819de7eb38113d2cdb6319669195a7d64270/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88", size = 1743049, upload-time = "2026-03-31T21:57:57.341Z" }, - { url = "https://files.pythonhosted.org/packages/18/71/901db0061e0f717d226386a7f471bb59b19566f2cae5f0d93874b017271f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3", size = 1749557, upload-time = "2026-03-31T21:57:59.626Z" }, - { url = "https://files.pythonhosted.org/packages/08/d5/41eebd16066e59cd43728fe74bce953d7402f2b4ddfdfef2c0e9f17ca274/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b", size = 1558931, upload-time = "2026-03-31T21:58:01.972Z" }, - { url = "https://files.pythonhosted.org/packages/30/e6/4a799798bf05740e66c3a1161079bda7a3dd8e22ca392481d7a7f9af82a6/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe", size = 1774125, upload-time = "2026-03-31T21:58:04.007Z" }, - { url = "https://files.pythonhosted.org/packages/84/63/7749337c90f92bc2cb18f9560d67aa6258c7060d1397d21529b8004fcf6f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14", size = 1732427, upload-time = "2026-03-31T21:58:06.337Z" }, - { url = "https://files.pythonhosted.org/packages/98/de/cf2f44ff98d307e72fb97d5f5bbae3bfcb442f0ea9790c0bf5c5c2331404/aiohttp-3.13.5-cp312-cp312-win32.whl", hash = "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3", size = 433534, upload-time = "2026-03-31T21:58:08.712Z" }, - { url = "https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1", size = 460446, upload-time = "2026-03-31T21:58:10.945Z" }, - { url = "https://files.pythonhosted.org/packages/78/e9/d76bf503005709e390122d34e15256b88f7008e246c4bdbe915cd4f1adce/aiohttp-3.13.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61", size = 742930, upload-time = "2026-03-31T21:58:13.155Z" }, - { url = "https://files.pythonhosted.org/packages/57/00/4b7b70223deaebd9bb85984d01a764b0d7bd6526fcdc73cca83bcbe7243e/aiohttp-3.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832", size = 496927, upload-time = "2026-03-31T21:58:15.073Z" }, - { url = "https://files.pythonhosted.org/packages/9c/f5/0fb20fb49f8efdcdce6cd8127604ad2c503e754a8f139f5e02b01626523f/aiohttp-3.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9", size = 497141, upload-time = "2026-03-31T21:58:17.009Z" }, - { url = "https://files.pythonhosted.org/packages/3b/86/b7c870053e36a94e8951b803cb5b909bfbc9b90ca941527f5fcafbf6b0fa/aiohttp-3.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090", size = 1732476, upload-time = "2026-03-31T21:58:18.925Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e5/4e161f84f98d80c03a238671b4136e6530453d65262867d989bbe78244d0/aiohttp-3.13.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b", size = 1706507, upload-time = "2026-03-31T21:58:21.094Z" }, - { url = "https://files.pythonhosted.org/packages/d4/56/ea11a9f01518bd5a2a2fcee869d248c4b8a0cfa0bb13401574fa31adf4d4/aiohttp-3.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a", size = 1773465, upload-time = "2026-03-31T21:58:23.159Z" }, - { url = "https://files.pythonhosted.org/packages/eb/40/333ca27fb74b0383f17c90570c748f7582501507307350a79d9f9f3c6eb1/aiohttp-3.13.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8", size = 1873523, upload-time = "2026-03-31T21:58:25.59Z" }, - { url = "https://files.pythonhosted.org/packages/f0/d2/e2f77eef1acb7111405433c707dc735e63f67a56e176e72e9e7a2cd3f493/aiohttp-3.13.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665", size = 1754113, upload-time = "2026-03-31T21:58:27.624Z" }, - { url = "https://files.pythonhosted.org/packages/fb/56/3f653d7f53c89669301ec9e42c95233e2a0c0a6dd051269e6e678db4fdb0/aiohttp-3.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540", size = 1562351, upload-time = "2026-03-31T21:58:29.918Z" }, - { url = "https://files.pythonhosted.org/packages/ec/a6/9b3e91eb8ae791cce4ee736da02211c85c6f835f1bdfac0594a8a3b7018c/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb", size = 1693205, upload-time = "2026-03-31T21:58:32.214Z" }, - { url = "https://files.pythonhosted.org/packages/98/fc/bfb437a99a2fcebd6b6eaec609571954de2ed424f01c352f4b5504371dd3/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46", size = 1730618, upload-time = "2026-03-31T21:58:34.728Z" }, - { url = "https://files.pythonhosted.org/packages/e4/b6/c8534862126191a034f68153194c389addc285a0f1347d85096d349bbc15/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8", size = 1745185, upload-time = "2026-03-31T21:58:36.909Z" }, - { url = "https://files.pythonhosted.org/packages/0b/93/4ca8ee2ef5236e2707e0fd5fecb10ce214aee1ff4ab307af9c558bda3b37/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d", size = 1557311, upload-time = "2026-03-31T21:58:39.38Z" }, - { url = "https://files.pythonhosted.org/packages/57/ae/76177b15f18c5f5d094f19901d284025db28eccc5ae374d1d254181d33f4/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6", size = 1773147, upload-time = "2026-03-31T21:58:41.476Z" }, - { url = "https://files.pythonhosted.org/packages/01/a4/62f05a0a98d88af59d93b7fcac564e5f18f513cb7471696ac286db970d6a/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c", size = 1730356, upload-time = "2026-03-31T21:58:44.049Z" }, - { url = "https://files.pythonhosted.org/packages/e4/85/fc8601f59dfa8c9523808281f2da571f8b4699685f9809a228adcc90838d/aiohttp-3.13.5-cp313-cp313-win32.whl", hash = "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc", size = 432637, upload-time = "2026-03-31T21:58:46.167Z" }, - { url = "https://files.pythonhosted.org/packages/c0/1b/ac685a8882896acf0f6b31d689e3792199cfe7aba37969fa91da63a7fa27/aiohttp-3.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83", size = 458896, upload-time = "2026-03-31T21:58:48.119Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ce/46572759afc859e867a5bc8ec3487315869013f59281ce61764f76d879de/aiohttp-3.13.5-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c", size = 745721, upload-time = "2026-03-31T21:58:50.229Z" }, - { url = "https://files.pythonhosted.org/packages/13/fe/8a2efd7626dbe6049b2ef8ace18ffda8a4dfcbe1bcff3ac30c0c7575c20b/aiohttp-3.13.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be", size = 497663, upload-time = "2026-03-31T21:58:52.232Z" }, - { url = "https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25", size = 499094, upload-time = "2026-03-31T21:58:54.566Z" }, - { url = "https://files.pythonhosted.org/packages/0a/33/a8362cb15cf16a3af7e86ed11962d5cd7d59b449202dc576cdc731310bde/aiohttp-3.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56", size = 1726701, upload-time = "2026-03-31T21:58:56.864Z" }, - { url = "https://files.pythonhosted.org/packages/45/0c/c091ac5c3a17114bd76cbf85d674650969ddf93387876cf67f754204bd77/aiohttp-3.13.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2", size = 1683360, upload-time = "2026-03-31T21:58:59.072Z" }, - { url = "https://files.pythonhosted.org/packages/23/73/bcee1c2b79bc275e964d1446c55c54441a461938e70267c86afaae6fba27/aiohttp-3.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a", size = 1773023, upload-time = "2026-03-31T21:59:01.776Z" }, - { url = "https://files.pythonhosted.org/packages/c7/ef/720e639df03004fee2d869f771799d8c23046dec47d5b81e396c7cda583a/aiohttp-3.13.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be", size = 1853795, upload-time = "2026-03-31T21:59:04.568Z" }, - { url = "https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b", size = 1730405, upload-time = "2026-03-31T21:59:07.221Z" }, - { url = "https://files.pythonhosted.org/packages/ce/75/ee1fd286ca7dc599d824b5651dad7b3be7ff8d9a7e7b3fe9820d9180f7db/aiohttp-3.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94", size = 1558082, upload-time = "2026-03-31T21:59:09.484Z" }, - { url = "https://files.pythonhosted.org/packages/c3/20/1e9e6650dfc436340116b7aa89ff8cb2bbdf0abc11dfaceaad8f74273a10/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d", size = 1692346, upload-time = "2026-03-31T21:59:12.068Z" }, - { url = "https://files.pythonhosted.org/packages/d8/40/8ebc6658d48ea630ac7903912fe0dd4e262f0e16825aa4c833c56c9f1f56/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7", size = 1698891, upload-time = "2026-03-31T21:59:14.552Z" }, - { url = "https://files.pythonhosted.org/packages/d8/78/ea0ae5ec8ba7a5c10bdd6e318f1ba5e76fcde17db8275188772afc7917a4/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772", size = 1742113, upload-time = "2026-03-31T21:59:17.068Z" }, - { url = "https://files.pythonhosted.org/packages/8a/66/9d308ed71e3f2491be1acb8769d96c6f0c47d92099f3bc9119cada27b357/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5", size = 1553088, upload-time = "2026-03-31T21:59:19.541Z" }, - { url = "https://files.pythonhosted.org/packages/da/a6/6cc25ed8dfc6e00c90f5c6d126a98e2cf28957ad06fa1036bd34b6f24a2c/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1", size = 1757976, upload-time = "2026-03-31T21:59:22.311Z" }, - { url = "https://files.pythonhosted.org/packages/c1/2b/cce5b0ffe0de99c83e5e36d8f828e4161e415660a9f3e58339d07cce3006/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b", size = 1712444, upload-time = "2026-03-31T21:59:24.635Z" }, - { url = "https://files.pythonhosted.org/packages/6c/cf/9e1795b4160c58d29421eafd1a69c6ce351e2f7c8d3c6b7e4ca44aea1a5b/aiohttp-3.13.5-cp314-cp314-win32.whl", hash = "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3", size = 438128, upload-time = "2026-03-31T21:59:27.291Z" }, - { url = "https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162", size = 464029, upload-time = "2026-03-31T21:59:29.429Z" }, - { url = "https://files.pythonhosted.org/packages/79/11/c27d9332ee20d68dd164dc12a6ecdef2e2e35ecc97ed6cf0d2442844624b/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a", size = 778758, upload-time = "2026-03-31T21:59:31.547Z" }, - { url = "https://files.pythonhosted.org/packages/04/fb/377aead2e0a3ba5f09b7624f702a964bdf4f08b5b6728a9799830c80041e/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254", size = 512883, upload-time = "2026-03-31T21:59:34.098Z" }, - { url = "https://files.pythonhosted.org/packages/bb/a6/aa109a33671f7a5d3bd78b46da9d852797c5e665bfda7d6b373f56bff2ec/aiohttp-3.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36", size = 516668, upload-time = "2026-03-31T21:59:36.497Z" }, - { url = "https://files.pythonhosted.org/packages/79/b3/ca078f9f2fa9563c36fb8ef89053ea2bb146d6f792c5104574d49d8acb63/aiohttp-3.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f", size = 1883461, upload-time = "2026-03-31T21:59:38.723Z" }, - { url = "https://files.pythonhosted.org/packages/b7/e3/a7ad633ca1ca497b852233a3cce6906a56c3225fb6d9217b5e5e60b7419d/aiohttp-3.13.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800", size = 1747661, upload-time = "2026-03-31T21:59:41.187Z" }, - { url = "https://files.pythonhosted.org/packages/33/b9/cd6fe579bed34a906d3d783fe60f2fa297ef55b27bb4538438ee49d4dc41/aiohttp-3.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf", size = 1863800, upload-time = "2026-03-31T21:59:43.84Z" }, - { url = "https://files.pythonhosted.org/packages/c0/3f/2c1e2f5144cefa889c8afd5cf431994c32f3b29da9961698ff4e3811b79a/aiohttp-3.13.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b", size = 1958382, upload-time = "2026-03-31T21:59:46.187Z" }, - { url = "https://files.pythonhosted.org/packages/66/1d/f31ec3f1013723b3babe3609e7f119c2c2fb6ef33da90061a705ef3e1bc8/aiohttp-3.13.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a", size = 1803724, upload-time = "2026-03-31T21:59:48.656Z" }, - { url = "https://files.pythonhosted.org/packages/0e/b4/57712dfc6f1542f067daa81eb61da282fab3e6f1966fca25db06c4fc62d5/aiohttp-3.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8", size = 1640027, upload-time = "2026-03-31T21:59:51.284Z" }, - { url = "https://files.pythonhosted.org/packages/25/3c/734c878fb43ec083d8e31bf029daae1beafeae582d1b35da234739e82ee7/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be", size = 1806644, upload-time = "2026-03-31T21:59:53.753Z" }, - { url = "https://files.pythonhosted.org/packages/20/a5/f671e5cbec1c21d044ff3078223f949748f3a7f86b14e34a365d74a5d21f/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b", size = 1791630, upload-time = "2026-03-31T21:59:56.239Z" }, - { url = "https://files.pythonhosted.org/packages/0b/63/fb8d0ad63a0b8a99be97deac8c04dacf0785721c158bdf23d679a87aa99e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6", size = 1809403, upload-time = "2026-03-31T21:59:59.103Z" }, - { url = "https://files.pythonhosted.org/packages/59/0c/bfed7f30662fcf12206481c2aac57dedee43fe1c49275e85b3a1e1742294/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037", size = 1634924, upload-time = "2026-03-31T22:00:02.116Z" }, - { url = "https://files.pythonhosted.org/packages/17/d6/fd518d668a09fd5a3319ae5e984d4d80b9a4b3df4e21c52f02251ef5a32e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500", size = 1836119, upload-time = "2026-03-31T22:00:04.756Z" }, - { url = "https://files.pythonhosted.org/packages/78/b7/15fb7a9d52e112a25b621c67b69c167805cb1f2ab8f1708a5c490d1b52fe/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9", size = 1772072, upload-time = "2026-03-31T22:00:07.494Z" }, - { url = "https://files.pythonhosted.org/packages/7e/df/57ba7f0c4a553fc2bd8b6321df236870ec6fd64a2a473a8a13d4f733214e/aiohttp-3.13.5-cp314-cp314t-win32.whl", hash = "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8", size = 471819, upload-time = "2026-03-31T22:00:10.277Z" }, - { url = "https://files.pythonhosted.org/packages/62/29/2f8418269e46454a26171bfdd6a055d74febf32234e474930f2f60a17145/aiohttp-3.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9", size = 505441, upload-time = "2026-03-31T22:00:12.791Z" }, - { url = "https://files.pythonhosted.org/packages/e2/a5/630bc484695d4a1342bbae85fb8689bf979106525684fc88f05b397324ad/aiohttp-3.13.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf", size = 752872, upload-time = "2026-03-31T22:00:15.553Z" }, - { url = "https://files.pythonhosted.org/packages/cd/b8/6a19dda37fda94a9ebefb3c1ae0ff419ac7fbf4fb40750e992829fc13614/aiohttp-3.13.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1", size = 504582, upload-time = "2026-03-31T22:00:18.191Z" }, - { url = "https://files.pythonhosted.org/packages/d5/34/8413eafee3421ade2d6ce9e7c0da1213e1d7f0049be09dcdc342b03a39ba/aiohttp-3.13.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10", size = 499094, upload-time = "2026-03-31T22:00:21.118Z" }, - { url = "https://files.pythonhosted.org/packages/da/cf/c6f97006093d1e8ca40fbab843ff49ec7725ab668f0714dd1cb702c62cbd/aiohttp-3.13.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f", size = 1669505, upload-time = "2026-03-31T22:00:24.01Z" }, - { url = "https://files.pythonhosted.org/packages/c2/27/3b2288e66dcec8b04771b2bee3909f70e4072bea995cde5ab7e775e73ddc/aiohttp-3.13.5-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b", size = 1648928, upload-time = "2026-03-31T22:00:27.001Z" }, - { url = "https://files.pythonhosted.org/packages/3a/7f/605d766887594a88dcc27a19663499c7c5e13e7aa87f129b763765a2ee63/aiohttp-3.13.5-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643", size = 1731800, upload-time = "2026-03-31T22:00:29.603Z" }, - { url = "https://files.pythonhosted.org/packages/71/94/5a878e728e30699d22b118f1a6ad576ab6fff9eb2c6fc8a7faa9376a1c3e/aiohttp-3.13.5-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031", size = 1824247, upload-time = "2026-03-31T22:00:32.139Z" }, - { url = "https://files.pythonhosted.org/packages/37/99/84b448291e9996bb83bf4fad3a71a9786d542f19c50a3ff0531bfaba6fac/aiohttp-3.13.5-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258", size = 1670742, upload-time = "2026-03-31T22:00:34.788Z" }, - { url = "https://files.pythonhosted.org/packages/14/a8/d8d5d1ab6d29a4a3bdb9db31f161e338bfdf6638f6574ea8380f1d4a243c/aiohttp-3.13.5-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a", size = 1562474, upload-time = "2026-03-31T22:00:37.623Z" }, - { url = "https://files.pythonhosted.org/packages/92/e8/bd889697916f10b65524422c61b4eeaf919eb35a170290cccb680cbe4eb4/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88", size = 1642235, upload-time = "2026-03-31T22:00:40.541Z" }, - { url = "https://files.pythonhosted.org/packages/60/42/3f1928107131f1413a5972ace14ddcd5364968e9bd7b3ad71272defafc9c/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0", size = 1655397, upload-time = "2026-03-31T22:00:43.167Z" }, - { url = "https://files.pythonhosted.org/packages/b2/79/c4bbcf4cac3a4715a326e49720ccdc3a4b5e14a367c5029eae7727d06029/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f", size = 1703509, upload-time = "2026-03-31T22:00:45.908Z" }, - { url = "https://files.pythonhosted.org/packages/d1/e6/32d245876f211a7308a7d5437707f9296b1f9837a2888a407ed04e61321c/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8", size = 1550098, upload-time = "2026-03-31T22:00:49.48Z" }, - { url = "https://files.pythonhosted.org/packages/db/62/ab0f1304def56ce2356e6fbb9f0b024d6544010351430070f48f53b89e0a/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f", size = 1724326, upload-time = "2026-03-31T22:00:52.165Z" }, - { url = "https://files.pythonhosted.org/packages/c4/9a/aab4469689024046220ea438aa020ea2ae04cd1dd71aea3057e094f8c357/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b", size = 1658824, upload-time = "2026-03-31T22:00:55.122Z" }, - { url = "https://files.pythonhosted.org/packages/b0/98/bcc35d4db687acabf06d41f561a99fa88bca145292513388c858d99b72c5/aiohttp-3.13.5-cp39-cp39-win32.whl", hash = "sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83", size = 440302, upload-time = "2026-03-31T22:00:57.673Z" }, - { url = "https://files.pythonhosted.org/packages/25/61/b0203c2ef6bd268fca0eda142f0efbba7cbebd7ad38f7bb01dd31c2ff68e/aiohttp-3.13.5-cp39-cp39-win_amd64.whl", hash = "sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67", size = 463076, upload-time = "2026-03-31T22:01:00.264Z" }, -] - [[package]] name = "aiohttp" version = "3.14.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2'", - "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra != 'group-12-oz-agent-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra != 'group-12-oz-agent-sdk-pydantic-v2'", -] dependencies = [ { name = "aiohappyeyeballs", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "aiosignal", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, @@ -315,8 +173,8 @@ name = "aiosignal" version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "frozenlist" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "frozenlist", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "typing-extensions", marker = "(python_full_version >= '3.10' and python_full_version < '3.13') or (python_full_version < '3.10' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2') or (python_full_version >= '3.13' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } wheels = [ @@ -609,9 +467,8 @@ name = "httpx-aiohttp" version = "0.1.12" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "aiohttp", version = "3.13.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "aiohttp", version = "3.14.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "httpx" }, + { name = "aiohttp", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "httpx", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/63/2c/b894861cecf030fb45675ea24aa55b5722e97c602a163d872fca66c5a6d8/httpx_aiohttp-0.1.12.tar.gz", hash = "sha256:81feec51fd82c0ecfa0e9aaf1b1a6c2591260d5e2bcbeb7eb0277a78e610df2c", size = 275945, upload-time = "2025-12-12T10:12:15.283Z" } wheels = [ @@ -713,7 +570,7 @@ name = "multidict" version = "6.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "typing-extensions", marker = "python_full_version == '3.10.*' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" } wheels = [ @@ -943,9 +800,8 @@ dependencies = [ [package.optional-dependencies] aiohttp = [ - { name = "aiohttp", version = "3.13.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "aiohttp", version = "3.14.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "httpx-aiohttp" }, + { name = "aiohttp", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "httpx-aiohttp", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] [package.dev-dependencies] @@ -955,7 +811,7 @@ dev = [ { name = "mypy" }, { name = "pyright" }, { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "pytest", version = "9.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "pytest-asyncio", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "pytest-asyncio", version = "1.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "pytest-xdist" }, @@ -974,11 +830,11 @@ pydantic-v2 = [ [package.metadata] requires-dist = [ - { name = "aiohttp", marker = "extra == 'aiohttp'", specifier = ">=3.13.5" }, + { name = "aiohttp", marker = "python_full_version >= '3.10' and extra == 'aiohttp'", specifier = ">=3.14.1" }, { name = "anyio", specifier = ">=3.5.0,<5" }, { name = "distro", specifier = ">=1.7.0,<2" }, { name = "httpx", specifier = ">=0.23.0,<1" }, - { name = "httpx-aiohttp", marker = "extra == 'aiohttp'", specifier = ">=0.1.9" }, + { name = "httpx-aiohttp", marker = "python_full_version >= '3.10' and extra == 'aiohttp'", specifier = ">=0.1.9" }, { name = "pydantic", specifier = ">=1.9.0,<3" }, { name = "sniffio" }, { name = "typing-extensions", specifier = ">=4.14,<5" }, @@ -1362,11 +1218,11 @@ wheels = [ [[package]] name = "pygments" -version = "2.19.2" +version = "2.20.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, ] [[package]] @@ -1405,7 +1261,7 @@ wheels = [ [[package]] name = "pytest" -version = "9.0.2" +version = "9.1.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2'", @@ -1422,9 +1278,9 @@ dependencies = [ { name = "pygments", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "tomli", marker = "python_full_version == '3.10.*' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, ] [[package]] @@ -1456,7 +1312,7 @@ resolution-markers = [ ] dependencies = [ { name = "backports-asyncio-runner", marker = "python_full_version == '3.10.*' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "pytest", version = "9.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "typing-extensions", marker = "(python_full_version >= '3.10' and python_full_version < '3.13') or (python_full_version < '3.10' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2') or (python_full_version >= '3.13' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/90/2c/8af215c0f776415f3590cac4f9086ccefd6fd463befeae41cd4d3f193e5a/pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5", size = 50087, upload-time = "2025-11-10T16:07:47.256Z" } @@ -1471,7 +1327,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "execnet" }, { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "pytest", version = "9.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } wheels = [ @@ -1833,9 +1689,9 @@ name = "yarl" version = "1.22.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "idna" }, - { name = "multidict" }, - { name = "propcache" }, + { name = "idna", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "multidict", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "propcache", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } wheels = [ From 46c142840b2637e734bdf272d66742a563282807 Mon Sep 17 00:00:00 2001 From: stlc-bot Date: Wed, 24 Jun 2026 17:20:33 +0000 Subject: [PATCH 11/14] fix(stlc): seal handlebars>=4.7.9 pin for CVE-2026-33937 and related (oz-sdk-typescript) Stainless-Generated-From: fd4deae13bfc3c0c5df989a0ec3f3c3782f4a170 --- pyproject.toml | 14 +-- requirements-dev.lock | 8 +- uv.lock | 196 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 176 insertions(+), 42 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d6d05c3..2d37867 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,10 +41,7 @@ Homepage = "https://github.com/warpdotdev/oz-sdk-python" Repository = "https://github.com/warpdotdev/oz-sdk-python" [project.optional-dependencies] -# Security pin: aiohttp<3.14.0 is vulnerable to multiple CVEs (CVE-2026-34993, -# CVE-2026-47265, CVE-2026-54273 through CVE-2026-54280, CVE-2026-50269). -# aiohttp 3.14.x dropped Python 3.9 support, so restrict to python_version >= '3.10'. -aiohttp = ["aiohttp>=3.14.1; python_version >= '3.10'", "httpx_aiohttp>=0.1.9; python_version >= '3.10'"] +aiohttp = ["aiohttp>=3.13.5", "httpx_aiohttp>=0.1.9"] [tool.uv] managed = true @@ -53,14 +50,7 @@ required-version = ">=0.9" # declared above. Versions <3.15 are vulnerable to CVE-2026-45409 # (GHSA-65pc-fj4g-8rjx), so constrain it without adding it as a direct # dependency. Sealed as custom code so it survives SDK regeneration. -constraint-dependencies = [ - "idna>=3.15", - # Security pin: pytest<9.0.3 is vulnerable to CVE-2025-71176 (tmpdir handling). - # pytest 9.0.3 requires Python>=3.10; pin only for compatible versions. - "pytest>=9.0.3; python_version >= '3.10'", - # Security pin: pygments<2.20.0 is vulnerable to CVE-2026-4539 (ReDoS). - "pygments>=2.20.0", -] +constraint-dependencies = ["idna>=3.15"] conflicts = [ [ { group = "pydantic-v1" }, diff --git a/requirements-dev.lock b/requirements-dev.lock index 5ff1150..f34eca7 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -1,5 +1,5 @@ # This file was autogenerated by uv via the following command: -# uv export --group dev --no-hashes +# uv export -o requirements-dev.lock --no-hashes -e . annotated-types==0.7.0 # via pydantic @@ -32,7 +32,7 @@ httpx==0.28.1 # via # oz-agent-sdk # respx -idna==3.18 +idna==3.11 # via # anyio # httpx @@ -62,7 +62,7 @@ pydantic==2.12.5 # via oz-agent-sdk pydantic-core==2.41.5 # via pydantic -pygments==2.20.0 +pygments==2.19.2 # via # pytest # rich @@ -71,7 +71,7 @@ pytest==8.4.2 ; python_full_version < '3.10' # via # pytest-asyncio # pytest-xdist -pytest==9.1.1 ; python_full_version >= '3.10' +pytest==9.0.2 ; python_full_version >= '3.10' # via # pytest-asyncio # pytest-xdist diff --git a/uv.lock b/uv.lock index ddf0935..13132d8 100644 --- a/uv.lock +++ b/uv.lock @@ -16,11 +16,7 @@ conflicts = [[ ]] [manifest] -constraints = [ - { name = "idna", specifier = ">=3.15" }, - { name = "pygments", specifier = ">=2.20.0" }, - { name = "pytest", marker = "python_full_version >= '3.10'", specifier = ">=9.0.3" }, -] +constraints = [{ name = "idna", specifier = ">=3.15" }] [[package]] name = "aiohappyeyeballs" @@ -31,10 +27,156 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, ] +[[package]] +name = "aiohttp" +version = "3.13.5" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "aiohappyeyeballs", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "aiosignal", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "async-timeout", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "attrs", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "frozenlist", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "multidict", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "propcache", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "yarl", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/77/9a/152096d4808df8e4268befa55fba462f440f14beab85e8ad9bf990516918/aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1", size = 7858271, upload-time = "2026-03-31T22:01:03.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/85/cebc47ee74d8b408749073a1a46c6fcba13d170dc8af7e61996c6c9394ac/aiohttp-3.13.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b", size = 750547, upload-time = "2026-03-31T21:56:30.024Z" }, + { url = "https://files.pythonhosted.org/packages/05/98/afd308e35b9d3d8c9ec54c0918f1d722c86dc17ddfec272fcdbcce5a3124/aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5", size = 503535, upload-time = "2026-03-31T21:56:31.935Z" }, + { url = "https://files.pythonhosted.org/packages/6f/4d/926c183e06b09d5270a309eb50fbde7b09782bfd305dec1e800f329834fb/aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670", size = 497830, upload-time = "2026-03-31T21:56:33.654Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d6/f47d1c690f115a5c2a5e8938cce4a232a5be9aac5c5fb2647efcbbbda333/aiohttp-3.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274", size = 1682474, upload-time = "2026-03-31T21:56:35.513Z" }, + { url = "https://files.pythonhosted.org/packages/01/44/056fd37b1bb52eac760303e5196acc74d9d546631b035704ae5927f7b4ac/aiohttp-3.13.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a", size = 1655259, upload-time = "2026-03-31T21:56:37.843Z" }, + { url = "https://files.pythonhosted.org/packages/91/9f/78eb1a20c1c28ae02f6a3c0f4d7b0dcc66abce5290cadd53d78ce3084175/aiohttp-3.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d", size = 1736204, upload-time = "2026-03-31T21:56:39.822Z" }, + { url = "https://files.pythonhosted.org/packages/de/6c/d20d7de23f0b52b8c1d9e2033b2db1ac4dacbb470bb74c56de0f5f86bb4f/aiohttp-3.13.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796", size = 1826198, upload-time = "2026-03-31T21:56:41.378Z" }, + { url = "https://files.pythonhosted.org/packages/2f/86/a6f3ff1fd795f49545a7c74b2c92f62729135d73e7e4055bf74da5a26c82/aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95", size = 1681329, upload-time = "2026-03-31T21:56:43.374Z" }, + { url = "https://files.pythonhosted.org/packages/fb/68/84cd3dab6b7b4f3e6fe9459a961acb142aaab846417f6e8905110d7027e5/aiohttp-3.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5", size = 1560023, upload-time = "2026-03-31T21:56:45.031Z" }, + { url = "https://files.pythonhosted.org/packages/41/2c/db61b64b0249e30f954a65ab4cb4970ced57544b1de2e3c98ee5dc24165f/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a", size = 1652372, upload-time = "2026-03-31T21:56:47.075Z" }, + { url = "https://files.pythonhosted.org/packages/25/6f/e96988a6c982d047810c772e28c43c64c300c943b0ed5c1c0c4ce1e1027c/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73", size = 1662031, upload-time = "2026-03-31T21:56:48.835Z" }, + { url = "https://files.pythonhosted.org/packages/b7/26/a56feace81f3d347b4052403a9d03754a0ab23f7940780dada0849a38c92/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297", size = 1708118, upload-time = "2026-03-31T21:56:50.833Z" }, + { url = "https://files.pythonhosted.org/packages/78/6e/b6173a8ff03d01d5e1a694bc06764b5dad1df2d4ed8f0ceec12bb3277936/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074", size = 1548667, upload-time = "2026-03-31T21:56:52.81Z" }, + { url = "https://files.pythonhosted.org/packages/16/13/13296ffe2c132d888b3fe2c195c8b9c0c24c89c3fa5cc2c44464dc23b22e/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e", size = 1724490, upload-time = "2026-03-31T21:56:54.541Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/1f1c287f4a79782ef36e5a6e62954c85343bc30470d862d30bd5f26c9fa2/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7", size = 1667109, upload-time = "2026-03-31T21:56:56.21Z" }, + { url = "https://files.pythonhosted.org/packages/ef/42/8461a2aaf60a8f4ea4549a4056be36b904b0eb03d97ca9a8a2604681a500/aiohttp-3.13.5-cp310-cp310-win32.whl", hash = "sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9", size = 439478, upload-time = "2026-03-31T21:56:58.292Z" }, + { url = "https://files.pythonhosted.org/packages/e5/71/06956304cb5ee439dfe8d86e1b2e70088bd88ed1ced1f42fb29e5d855f0e/aiohttp-3.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76", size = 462047, upload-time = "2026-03-31T21:57:00.257Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f5/a20c4ac64aeaef1679e25c9983573618ff765d7aa829fa2b84ae7573169e/aiohttp-3.13.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6", size = 757513, upload-time = "2026-03-31T21:57:02.146Z" }, + { url = "https://files.pythonhosted.org/packages/75/0a/39fa6c6b179b53fcb3e4b3d2b6d6cad0180854eda17060c7218540102bef/aiohttp-3.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d", size = 506748, upload-time = "2026-03-31T21:57:04.275Z" }, + { url = "https://files.pythonhosted.org/packages/87/ec/e38ce072e724fd7add6243613f8d1810da084f54175353d25ccf9f9c7e5a/aiohttp-3.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c", size = 501673, upload-time = "2026-03-31T21:57:06.208Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ba/3bc7525d7e2beaa11b309a70d48b0d3cfc3c2089ec6a7d0820d59c657053/aiohttp-3.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb", size = 1763757, upload-time = "2026-03-31T21:57:07.882Z" }, + { url = "https://files.pythonhosted.org/packages/5e/ab/e87744cf18f1bd78263aba24924d4953b41086bd3a31d22452378e9028a0/aiohttp-3.13.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6", size = 1720152, upload-time = "2026-03-31T21:57:09.946Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f3/ed17a6f2d742af17b50bae2d152315ed1b164b07a5fd5cc1754d99e4dfa5/aiohttp-3.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13", size = 1818010, upload-time = "2026-03-31T21:57:12.157Z" }, + { url = "https://files.pythonhosted.org/packages/53/06/ecbc63dc937192e2a5cb46df4d3edb21deb8225535818802f210a6ea5816/aiohttp-3.13.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174", size = 1907251, upload-time = "2026-03-31T21:57:14.023Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a5/0521aa32c1ddf3aa1e71dcc466be0b7db2771907a13f18cddaa45967d97b/aiohttp-3.13.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc", size = 1759969, upload-time = "2026-03-31T21:57:16.146Z" }, + { url = "https://files.pythonhosted.org/packages/f6/78/a38f8c9105199dd3b9706745865a8a59d0041b6be0ca0cc4b2ccf1bab374/aiohttp-3.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6", size = 1616871, upload-time = "2026-03-31T21:57:17.856Z" }, + { url = "https://files.pythonhosted.org/packages/6f/41/27392a61ead8ab38072105c71aa44ff891e71653fe53d576a7067da2b4e8/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49", size = 1739844, upload-time = "2026-03-31T21:57:19.679Z" }, + { url = "https://files.pythonhosted.org/packages/6e/55/5564e7ae26d94f3214250009a0b1c65a0c6af4bf88924ccb6fdab901de28/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8", size = 1731969, upload-time = "2026-03-31T21:57:22.006Z" }, + { url = "https://files.pythonhosted.org/packages/6d/c5/705a3929149865fc941bcbdd1047b238e4a72bcb215a9b16b9d7a2e8d992/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d", size = 1795193, upload-time = "2026-03-31T21:57:24.256Z" }, + { url = "https://files.pythonhosted.org/packages/a6/19/edabed62f718d02cff7231ca0db4ef1c72504235bc467f7b67adb1679f48/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c", size = 1606477, upload-time = "2026-03-31T21:57:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/de/fc/76f80ef008675637d88d0b21584596dc27410a990b0918cb1e5776545b5b/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac", size = 1813198, upload-time = "2026-03-31T21:57:28.316Z" }, + { url = "https://files.pythonhosted.org/packages/e5/67/5b3ac26b80adb20ea541c487f73730dc8fa107d632c998f25bbbab98fcda/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3", size = 1752321, upload-time = "2026-03-31T21:57:30.549Z" }, + { url = "https://files.pythonhosted.org/packages/88/06/e4a2e49255ea23fa4feeb5ab092d90240d927c15e47b5b5c48dff5a9ce29/aiohttp-3.13.5-cp311-cp311-win32.whl", hash = "sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06", size = 439069, upload-time = "2026-03-31T21:57:32.388Z" }, + { url = "https://files.pythonhosted.org/packages/c0/43/8c7163a596dab4f8be12c190cf467a1e07e4734cf90eebb39f7f5d53fc6a/aiohttp-3.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8", size = 462859, upload-time = "2026-03-31T21:57:34.455Z" }, + { url = "https://files.pythonhosted.org/packages/be/6f/353954c29e7dcce7cf00280a02c75f30e133c00793c7a2ed3776d7b2f426/aiohttp-3.13.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9", size = 748876, upload-time = "2026-03-31T21:57:36.319Z" }, + { url = "https://files.pythonhosted.org/packages/f5/1b/428a7c64687b3b2e9cd293186695affc0e1e54a445d0361743b231f11066/aiohttp-3.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416", size = 499557, upload-time = "2026-03-31T21:57:38.236Z" }, + { url = "https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2", size = 500258, upload-time = "2026-03-31T21:57:39.923Z" }, + { url = "https://files.pythonhosted.org/packages/67/84/c9ecc5828cb0b3695856c07c0a6817a99d51e2473400f705275a2b3d9239/aiohttp-3.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4", size = 1749199, upload-time = "2026-03-31T21:57:41.938Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d3/3c6d610e66b495657622edb6ae7c7fd31b2e9086b4ec50b47897ad6042a9/aiohttp-3.13.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9", size = 1721013, upload-time = "2026-03-31T21:57:43.904Z" }, + { url = "https://files.pythonhosted.org/packages/49/a0/24409c12217456df0bae7babe3b014e460b0b38a8e60753d6cb339f6556d/aiohttp-3.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5", size = 1781501, upload-time = "2026-03-31T21:57:46.285Z" }, + { url = "https://files.pythonhosted.org/packages/98/9d/b65ec649adc5bccc008b0957a9a9c691070aeac4e41cea18559fef49958b/aiohttp-3.13.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e", size = 1878981, upload-time = "2026-03-31T21:57:48.734Z" }, + { url = "https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1", size = 1767934, upload-time = "2026-03-31T21:57:51.171Z" }, + { url = "https://files.pythonhosted.org/packages/31/04/d3f8211f273356f158e3464e9e45484d3fb8c4ce5eb2f6fe9405c3273983/aiohttp-3.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286", size = 1566671, upload-time = "2026-03-31T21:57:53.326Z" }, + { url = "https://files.pythonhosted.org/packages/41/db/073e4ebe00b78e2dfcacff734291651729a62953b48933d765dc513bf798/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9", size = 1705219, upload-time = "2026-03-31T21:57:55.385Z" }, + { url = "https://files.pythonhosted.org/packages/48/45/7dfba71a2f9fd97b15c95c06819de7eb38113d2cdb6319669195a7d64270/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88", size = 1743049, upload-time = "2026-03-31T21:57:57.341Z" }, + { url = "https://files.pythonhosted.org/packages/18/71/901db0061e0f717d226386a7f471bb59b19566f2cae5f0d93874b017271f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3", size = 1749557, upload-time = "2026-03-31T21:57:59.626Z" }, + { url = "https://files.pythonhosted.org/packages/08/d5/41eebd16066e59cd43728fe74bce953d7402f2b4ddfdfef2c0e9f17ca274/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b", size = 1558931, upload-time = "2026-03-31T21:58:01.972Z" }, + { url = "https://files.pythonhosted.org/packages/30/e6/4a799798bf05740e66c3a1161079bda7a3dd8e22ca392481d7a7f9af82a6/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe", size = 1774125, upload-time = "2026-03-31T21:58:04.007Z" }, + { url = "https://files.pythonhosted.org/packages/84/63/7749337c90f92bc2cb18f9560d67aa6258c7060d1397d21529b8004fcf6f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14", size = 1732427, upload-time = "2026-03-31T21:58:06.337Z" }, + { url = "https://files.pythonhosted.org/packages/98/de/cf2f44ff98d307e72fb97d5f5bbae3bfcb442f0ea9790c0bf5c5c2331404/aiohttp-3.13.5-cp312-cp312-win32.whl", hash = "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3", size = 433534, upload-time = "2026-03-31T21:58:08.712Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1", size = 460446, upload-time = "2026-03-31T21:58:10.945Z" }, + { url = "https://files.pythonhosted.org/packages/78/e9/d76bf503005709e390122d34e15256b88f7008e246c4bdbe915cd4f1adce/aiohttp-3.13.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61", size = 742930, upload-time = "2026-03-31T21:58:13.155Z" }, + { url = "https://files.pythonhosted.org/packages/57/00/4b7b70223deaebd9bb85984d01a764b0d7bd6526fcdc73cca83bcbe7243e/aiohttp-3.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832", size = 496927, upload-time = "2026-03-31T21:58:15.073Z" }, + { url = "https://files.pythonhosted.org/packages/9c/f5/0fb20fb49f8efdcdce6cd8127604ad2c503e754a8f139f5e02b01626523f/aiohttp-3.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9", size = 497141, upload-time = "2026-03-31T21:58:17.009Z" }, + { url = "https://files.pythonhosted.org/packages/3b/86/b7c870053e36a94e8951b803cb5b909bfbc9b90ca941527f5fcafbf6b0fa/aiohttp-3.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090", size = 1732476, upload-time = "2026-03-31T21:58:18.925Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e5/4e161f84f98d80c03a238671b4136e6530453d65262867d989bbe78244d0/aiohttp-3.13.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b", size = 1706507, upload-time = "2026-03-31T21:58:21.094Z" }, + { url = "https://files.pythonhosted.org/packages/d4/56/ea11a9f01518bd5a2a2fcee869d248c4b8a0cfa0bb13401574fa31adf4d4/aiohttp-3.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a", size = 1773465, upload-time = "2026-03-31T21:58:23.159Z" }, + { url = "https://files.pythonhosted.org/packages/eb/40/333ca27fb74b0383f17c90570c748f7582501507307350a79d9f9f3c6eb1/aiohttp-3.13.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8", size = 1873523, upload-time = "2026-03-31T21:58:25.59Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d2/e2f77eef1acb7111405433c707dc735e63f67a56e176e72e9e7a2cd3f493/aiohttp-3.13.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665", size = 1754113, upload-time = "2026-03-31T21:58:27.624Z" }, + { url = "https://files.pythonhosted.org/packages/fb/56/3f653d7f53c89669301ec9e42c95233e2a0c0a6dd051269e6e678db4fdb0/aiohttp-3.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540", size = 1562351, upload-time = "2026-03-31T21:58:29.918Z" }, + { url = "https://files.pythonhosted.org/packages/ec/a6/9b3e91eb8ae791cce4ee736da02211c85c6f835f1bdfac0594a8a3b7018c/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb", size = 1693205, upload-time = "2026-03-31T21:58:32.214Z" }, + { url = "https://files.pythonhosted.org/packages/98/fc/bfb437a99a2fcebd6b6eaec609571954de2ed424f01c352f4b5504371dd3/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46", size = 1730618, upload-time = "2026-03-31T21:58:34.728Z" }, + { url = "https://files.pythonhosted.org/packages/e4/b6/c8534862126191a034f68153194c389addc285a0f1347d85096d349bbc15/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8", size = 1745185, upload-time = "2026-03-31T21:58:36.909Z" }, + { url = "https://files.pythonhosted.org/packages/0b/93/4ca8ee2ef5236e2707e0fd5fecb10ce214aee1ff4ab307af9c558bda3b37/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d", size = 1557311, upload-time = "2026-03-31T21:58:39.38Z" }, + { url = "https://files.pythonhosted.org/packages/57/ae/76177b15f18c5f5d094f19901d284025db28eccc5ae374d1d254181d33f4/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6", size = 1773147, upload-time = "2026-03-31T21:58:41.476Z" }, + { url = "https://files.pythonhosted.org/packages/01/a4/62f05a0a98d88af59d93b7fcac564e5f18f513cb7471696ac286db970d6a/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c", size = 1730356, upload-time = "2026-03-31T21:58:44.049Z" }, + { url = "https://files.pythonhosted.org/packages/e4/85/fc8601f59dfa8c9523808281f2da571f8b4699685f9809a228adcc90838d/aiohttp-3.13.5-cp313-cp313-win32.whl", hash = "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc", size = 432637, upload-time = "2026-03-31T21:58:46.167Z" }, + { url = "https://files.pythonhosted.org/packages/c0/1b/ac685a8882896acf0f6b31d689e3792199cfe7aba37969fa91da63a7fa27/aiohttp-3.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83", size = 458896, upload-time = "2026-03-31T21:58:48.119Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ce/46572759afc859e867a5bc8ec3487315869013f59281ce61764f76d879de/aiohttp-3.13.5-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c", size = 745721, upload-time = "2026-03-31T21:58:50.229Z" }, + { url = "https://files.pythonhosted.org/packages/13/fe/8a2efd7626dbe6049b2ef8ace18ffda8a4dfcbe1bcff3ac30c0c7575c20b/aiohttp-3.13.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be", size = 497663, upload-time = "2026-03-31T21:58:52.232Z" }, + { url = "https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25", size = 499094, upload-time = "2026-03-31T21:58:54.566Z" }, + { url = "https://files.pythonhosted.org/packages/0a/33/a8362cb15cf16a3af7e86ed11962d5cd7d59b449202dc576cdc731310bde/aiohttp-3.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56", size = 1726701, upload-time = "2026-03-31T21:58:56.864Z" }, + { url = "https://files.pythonhosted.org/packages/45/0c/c091ac5c3a17114bd76cbf85d674650969ddf93387876cf67f754204bd77/aiohttp-3.13.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2", size = 1683360, upload-time = "2026-03-31T21:58:59.072Z" }, + { url = "https://files.pythonhosted.org/packages/23/73/bcee1c2b79bc275e964d1446c55c54441a461938e70267c86afaae6fba27/aiohttp-3.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a", size = 1773023, upload-time = "2026-03-31T21:59:01.776Z" }, + { url = "https://files.pythonhosted.org/packages/c7/ef/720e639df03004fee2d869f771799d8c23046dec47d5b81e396c7cda583a/aiohttp-3.13.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be", size = 1853795, upload-time = "2026-03-31T21:59:04.568Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b", size = 1730405, upload-time = "2026-03-31T21:59:07.221Z" }, + { url = "https://files.pythonhosted.org/packages/ce/75/ee1fd286ca7dc599d824b5651dad7b3be7ff8d9a7e7b3fe9820d9180f7db/aiohttp-3.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94", size = 1558082, upload-time = "2026-03-31T21:59:09.484Z" }, + { url = "https://files.pythonhosted.org/packages/c3/20/1e9e6650dfc436340116b7aa89ff8cb2bbdf0abc11dfaceaad8f74273a10/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d", size = 1692346, upload-time = "2026-03-31T21:59:12.068Z" }, + { url = "https://files.pythonhosted.org/packages/d8/40/8ebc6658d48ea630ac7903912fe0dd4e262f0e16825aa4c833c56c9f1f56/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7", size = 1698891, upload-time = "2026-03-31T21:59:14.552Z" }, + { url = "https://files.pythonhosted.org/packages/d8/78/ea0ae5ec8ba7a5c10bdd6e318f1ba5e76fcde17db8275188772afc7917a4/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772", size = 1742113, upload-time = "2026-03-31T21:59:17.068Z" }, + { url = "https://files.pythonhosted.org/packages/8a/66/9d308ed71e3f2491be1acb8769d96c6f0c47d92099f3bc9119cada27b357/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5", size = 1553088, upload-time = "2026-03-31T21:59:19.541Z" }, + { url = "https://files.pythonhosted.org/packages/da/a6/6cc25ed8dfc6e00c90f5c6d126a98e2cf28957ad06fa1036bd34b6f24a2c/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1", size = 1757976, upload-time = "2026-03-31T21:59:22.311Z" }, + { url = "https://files.pythonhosted.org/packages/c1/2b/cce5b0ffe0de99c83e5e36d8f828e4161e415660a9f3e58339d07cce3006/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b", size = 1712444, upload-time = "2026-03-31T21:59:24.635Z" }, + { url = "https://files.pythonhosted.org/packages/6c/cf/9e1795b4160c58d29421eafd1a69c6ce351e2f7c8d3c6b7e4ca44aea1a5b/aiohttp-3.13.5-cp314-cp314-win32.whl", hash = "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3", size = 438128, upload-time = "2026-03-31T21:59:27.291Z" }, + { url = "https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162", size = 464029, upload-time = "2026-03-31T21:59:29.429Z" }, + { url = "https://files.pythonhosted.org/packages/79/11/c27d9332ee20d68dd164dc12a6ecdef2e2e35ecc97ed6cf0d2442844624b/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a", size = 778758, upload-time = "2026-03-31T21:59:31.547Z" }, + { url = "https://files.pythonhosted.org/packages/04/fb/377aead2e0a3ba5f09b7624f702a964bdf4f08b5b6728a9799830c80041e/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254", size = 512883, upload-time = "2026-03-31T21:59:34.098Z" }, + { url = "https://files.pythonhosted.org/packages/bb/a6/aa109a33671f7a5d3bd78b46da9d852797c5e665bfda7d6b373f56bff2ec/aiohttp-3.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36", size = 516668, upload-time = "2026-03-31T21:59:36.497Z" }, + { url = "https://files.pythonhosted.org/packages/79/b3/ca078f9f2fa9563c36fb8ef89053ea2bb146d6f792c5104574d49d8acb63/aiohttp-3.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f", size = 1883461, upload-time = "2026-03-31T21:59:38.723Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e3/a7ad633ca1ca497b852233a3cce6906a56c3225fb6d9217b5e5e60b7419d/aiohttp-3.13.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800", size = 1747661, upload-time = "2026-03-31T21:59:41.187Z" }, + { url = "https://files.pythonhosted.org/packages/33/b9/cd6fe579bed34a906d3d783fe60f2fa297ef55b27bb4538438ee49d4dc41/aiohttp-3.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf", size = 1863800, upload-time = "2026-03-31T21:59:43.84Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3f/2c1e2f5144cefa889c8afd5cf431994c32f3b29da9961698ff4e3811b79a/aiohttp-3.13.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b", size = 1958382, upload-time = "2026-03-31T21:59:46.187Z" }, + { url = "https://files.pythonhosted.org/packages/66/1d/f31ec3f1013723b3babe3609e7f119c2c2fb6ef33da90061a705ef3e1bc8/aiohttp-3.13.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a", size = 1803724, upload-time = "2026-03-31T21:59:48.656Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b4/57712dfc6f1542f067daa81eb61da282fab3e6f1966fca25db06c4fc62d5/aiohttp-3.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8", size = 1640027, upload-time = "2026-03-31T21:59:51.284Z" }, + { url = "https://files.pythonhosted.org/packages/25/3c/734c878fb43ec083d8e31bf029daae1beafeae582d1b35da234739e82ee7/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be", size = 1806644, upload-time = "2026-03-31T21:59:53.753Z" }, + { url = "https://files.pythonhosted.org/packages/20/a5/f671e5cbec1c21d044ff3078223f949748f3a7f86b14e34a365d74a5d21f/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b", size = 1791630, upload-time = "2026-03-31T21:59:56.239Z" }, + { url = "https://files.pythonhosted.org/packages/0b/63/fb8d0ad63a0b8a99be97deac8c04dacf0785721c158bdf23d679a87aa99e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6", size = 1809403, upload-time = "2026-03-31T21:59:59.103Z" }, + { url = "https://files.pythonhosted.org/packages/59/0c/bfed7f30662fcf12206481c2aac57dedee43fe1c49275e85b3a1e1742294/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037", size = 1634924, upload-time = "2026-03-31T22:00:02.116Z" }, + { url = "https://files.pythonhosted.org/packages/17/d6/fd518d668a09fd5a3319ae5e984d4d80b9a4b3df4e21c52f02251ef5a32e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500", size = 1836119, upload-time = "2026-03-31T22:00:04.756Z" }, + { url = "https://files.pythonhosted.org/packages/78/b7/15fb7a9d52e112a25b621c67b69c167805cb1f2ab8f1708a5c490d1b52fe/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9", size = 1772072, upload-time = "2026-03-31T22:00:07.494Z" }, + { url = "https://files.pythonhosted.org/packages/7e/df/57ba7f0c4a553fc2bd8b6321df236870ec6fd64a2a473a8a13d4f733214e/aiohttp-3.13.5-cp314-cp314t-win32.whl", hash = "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8", size = 471819, upload-time = "2026-03-31T22:00:10.277Z" }, + { url = "https://files.pythonhosted.org/packages/62/29/2f8418269e46454a26171bfdd6a055d74febf32234e474930f2f60a17145/aiohttp-3.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9", size = 505441, upload-time = "2026-03-31T22:00:12.791Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a5/630bc484695d4a1342bbae85fb8689bf979106525684fc88f05b397324ad/aiohttp-3.13.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf", size = 752872, upload-time = "2026-03-31T22:00:15.553Z" }, + { url = "https://files.pythonhosted.org/packages/cd/b8/6a19dda37fda94a9ebefb3c1ae0ff419ac7fbf4fb40750e992829fc13614/aiohttp-3.13.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1", size = 504582, upload-time = "2026-03-31T22:00:18.191Z" }, + { url = "https://files.pythonhosted.org/packages/d5/34/8413eafee3421ade2d6ce9e7c0da1213e1d7f0049be09dcdc342b03a39ba/aiohttp-3.13.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10", size = 499094, upload-time = "2026-03-31T22:00:21.118Z" }, + { url = "https://files.pythonhosted.org/packages/da/cf/c6f97006093d1e8ca40fbab843ff49ec7725ab668f0714dd1cb702c62cbd/aiohttp-3.13.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f", size = 1669505, upload-time = "2026-03-31T22:00:24.01Z" }, + { url = "https://files.pythonhosted.org/packages/c2/27/3b2288e66dcec8b04771b2bee3909f70e4072bea995cde5ab7e775e73ddc/aiohttp-3.13.5-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b", size = 1648928, upload-time = "2026-03-31T22:00:27.001Z" }, + { url = "https://files.pythonhosted.org/packages/3a/7f/605d766887594a88dcc27a19663499c7c5e13e7aa87f129b763765a2ee63/aiohttp-3.13.5-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643", size = 1731800, upload-time = "2026-03-31T22:00:29.603Z" }, + { url = "https://files.pythonhosted.org/packages/71/94/5a878e728e30699d22b118f1a6ad576ab6fff9eb2c6fc8a7faa9376a1c3e/aiohttp-3.13.5-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031", size = 1824247, upload-time = "2026-03-31T22:00:32.139Z" }, + { url = "https://files.pythonhosted.org/packages/37/99/84b448291e9996bb83bf4fad3a71a9786d542f19c50a3ff0531bfaba6fac/aiohttp-3.13.5-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258", size = 1670742, upload-time = "2026-03-31T22:00:34.788Z" }, + { url = "https://files.pythonhosted.org/packages/14/a8/d8d5d1ab6d29a4a3bdb9db31f161e338bfdf6638f6574ea8380f1d4a243c/aiohttp-3.13.5-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a", size = 1562474, upload-time = "2026-03-31T22:00:37.623Z" }, + { url = "https://files.pythonhosted.org/packages/92/e8/bd889697916f10b65524422c61b4eeaf919eb35a170290cccb680cbe4eb4/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88", size = 1642235, upload-time = "2026-03-31T22:00:40.541Z" }, + { url = "https://files.pythonhosted.org/packages/60/42/3f1928107131f1413a5972ace14ddcd5364968e9bd7b3ad71272defafc9c/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0", size = 1655397, upload-time = "2026-03-31T22:00:43.167Z" }, + { url = "https://files.pythonhosted.org/packages/b2/79/c4bbcf4cac3a4715a326e49720ccdc3a4b5e14a367c5029eae7727d06029/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f", size = 1703509, upload-time = "2026-03-31T22:00:45.908Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e6/32d245876f211a7308a7d5437707f9296b1f9837a2888a407ed04e61321c/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8", size = 1550098, upload-time = "2026-03-31T22:00:49.48Z" }, + { url = "https://files.pythonhosted.org/packages/db/62/ab0f1304def56ce2356e6fbb9f0b024d6544010351430070f48f53b89e0a/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f", size = 1724326, upload-time = "2026-03-31T22:00:52.165Z" }, + { url = "https://files.pythonhosted.org/packages/c4/9a/aab4469689024046220ea438aa020ea2ae04cd1dd71aea3057e094f8c357/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b", size = 1658824, upload-time = "2026-03-31T22:00:55.122Z" }, + { url = "https://files.pythonhosted.org/packages/b0/98/bcc35d4db687acabf06d41f561a99fa88bca145292513388c858d99b72c5/aiohttp-3.13.5-cp39-cp39-win32.whl", hash = "sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83", size = 440302, upload-time = "2026-03-31T22:00:57.673Z" }, + { url = "https://files.pythonhosted.org/packages/25/61/b0203c2ef6bd268fca0eda142f0efbba7cbebd7ad38f7bb01dd31c2ff68e/aiohttp-3.13.5-cp39-cp39-win_amd64.whl", hash = "sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67", size = 463076, upload-time = "2026-03-31T22:01:00.264Z" }, +] + [[package]] name = "aiohttp" version = "3.14.1" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2'", + "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2'", + "python_full_version >= '3.10' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra != 'group-12-oz-agent-sdk-pydantic-v2'", + "python_full_version >= '3.10' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra != 'group-12-oz-agent-sdk-pydantic-v2'", +] dependencies = [ { name = "aiohappyeyeballs", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "aiosignal", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, @@ -173,8 +315,8 @@ name = "aiosignal" version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "frozenlist", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "typing-extensions", marker = "(python_full_version >= '3.10' and python_full_version < '3.13') or (python_full_version < '3.10' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2') or (python_full_version >= '3.13' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "frozenlist" }, + { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } wheels = [ @@ -467,8 +609,9 @@ name = "httpx-aiohttp" version = "0.1.12" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "aiohttp", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "httpx", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "aiohttp", version = "3.13.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "aiohttp", version = "3.14.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "httpx" }, ] sdist = { url = "https://files.pythonhosted.org/packages/63/2c/b894861cecf030fb45675ea24aa55b5722e97c602a163d872fca66c5a6d8/httpx_aiohttp-0.1.12.tar.gz", hash = "sha256:81feec51fd82c0ecfa0e9aaf1b1a6c2591260d5e2bcbeb7eb0277a78e610df2c", size = 275945, upload-time = "2025-12-12T10:12:15.283Z" } wheels = [ @@ -570,7 +713,7 @@ name = "multidict" version = "6.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version == '3.10.*' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" } wheels = [ @@ -800,8 +943,9 @@ dependencies = [ [package.optional-dependencies] aiohttp = [ - { name = "aiohttp", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "httpx-aiohttp", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "aiohttp", version = "3.13.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "aiohttp", version = "3.14.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "httpx-aiohttp" }, ] [package.dev-dependencies] @@ -811,7 +955,7 @@ dev = [ { name = "mypy" }, { name = "pyright" }, { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "pytest", version = "9.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "pytest-asyncio", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "pytest-asyncio", version = "1.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "pytest-xdist" }, @@ -830,11 +974,11 @@ pydantic-v2 = [ [package.metadata] requires-dist = [ - { name = "aiohttp", marker = "python_full_version >= '3.10' and extra == 'aiohttp'", specifier = ">=3.14.1" }, + { name = "aiohttp", marker = "extra == 'aiohttp'", specifier = ">=3.13.5" }, { name = "anyio", specifier = ">=3.5.0,<5" }, { name = "distro", specifier = ">=1.7.0,<2" }, { name = "httpx", specifier = ">=0.23.0,<1" }, - { name = "httpx-aiohttp", marker = "python_full_version >= '3.10' and extra == 'aiohttp'", specifier = ">=0.1.9" }, + { name = "httpx-aiohttp", marker = "extra == 'aiohttp'", specifier = ">=0.1.9" }, { name = "pydantic", specifier = ">=1.9.0,<3" }, { name = "sniffio" }, { name = "typing-extensions", specifier = ">=4.14,<5" }, @@ -1218,11 +1362,11 @@ wheels = [ [[package]] name = "pygments" -version = "2.20.0" +version = "2.19.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, ] [[package]] @@ -1261,7 +1405,7 @@ wheels = [ [[package]] name = "pytest" -version = "9.1.1" +version = "9.0.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2'", @@ -1278,9 +1422,9 @@ dependencies = [ { name = "pygments", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "tomli", marker = "python_full_version == '3.10.*' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, + { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, ] [[package]] @@ -1312,7 +1456,7 @@ resolution-markers = [ ] dependencies = [ { name = "backports-asyncio-runner", marker = "python_full_version == '3.10.*' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "pytest", version = "9.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "typing-extensions", marker = "(python_full_version >= '3.10' and python_full_version < '3.13') or (python_full_version < '3.10' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2') or (python_full_version >= '3.13' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/90/2c/8af215c0f776415f3590cac4f9086ccefd6fd463befeae41cd4d3f193e5a/pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5", size = 50087, upload-time = "2025-11-10T16:07:47.256Z" } @@ -1327,7 +1471,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "execnet" }, { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "pytest", version = "9.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } wheels = [ @@ -1689,9 +1833,9 @@ name = "yarl" version = "1.22.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "idna", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "multidict", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "propcache", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, ] sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } wheels = [ From 9bcd811980eb957f94ce639c43d673b7413999cd Mon Sep 17 00:00:00 2001 From: liliwilson Date: Wed, 24 Jun 2026 18:41:10 +0000 Subject: [PATCH 12/14] fix(deps): pin aiohttp>=3.14.1, pytest>=9.0.3, pygments>=2.20.0 (CVE fixes) Stainless-Generated-From: 4ab431c104fb2e887cc8bea4abaa07cba4374349 Co-Authored-By: Oz --- pyproject.toml | 14 ++- requirements-dev.lock | 8 +- uv.lock | 196 ++++++------------------------------------ 3 files changed, 42 insertions(+), 176 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2d37867..d6d05c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,10 @@ Homepage = "https://github.com/warpdotdev/oz-sdk-python" Repository = "https://github.com/warpdotdev/oz-sdk-python" [project.optional-dependencies] -aiohttp = ["aiohttp>=3.13.5", "httpx_aiohttp>=0.1.9"] +# Security pin: aiohttp<3.14.0 is vulnerable to multiple CVEs (CVE-2026-34993, +# CVE-2026-47265, CVE-2026-54273 through CVE-2026-54280, CVE-2026-50269). +# aiohttp 3.14.x dropped Python 3.9 support, so restrict to python_version >= '3.10'. +aiohttp = ["aiohttp>=3.14.1; python_version >= '3.10'", "httpx_aiohttp>=0.1.9; python_version >= '3.10'"] [tool.uv] managed = true @@ -50,7 +53,14 @@ required-version = ">=0.9" # declared above. Versions <3.15 are vulnerable to CVE-2026-45409 # (GHSA-65pc-fj4g-8rjx), so constrain it without adding it as a direct # dependency. Sealed as custom code so it survives SDK regeneration. -constraint-dependencies = ["idna>=3.15"] +constraint-dependencies = [ + "idna>=3.15", + # Security pin: pytest<9.0.3 is vulnerable to CVE-2025-71176 (tmpdir handling). + # pytest 9.0.3 requires Python>=3.10; pin only for compatible versions. + "pytest>=9.0.3; python_version >= '3.10'", + # Security pin: pygments<2.20.0 is vulnerable to CVE-2026-4539 (ReDoS). + "pygments>=2.20.0", +] conflicts = [ [ { group = "pydantic-v1" }, diff --git a/requirements-dev.lock b/requirements-dev.lock index f34eca7..5ff1150 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -1,5 +1,5 @@ # This file was autogenerated by uv via the following command: -# uv export -o requirements-dev.lock --no-hashes +# uv export --group dev --no-hashes -e . annotated-types==0.7.0 # via pydantic @@ -32,7 +32,7 @@ httpx==0.28.1 # via # oz-agent-sdk # respx -idna==3.11 +idna==3.18 # via # anyio # httpx @@ -62,7 +62,7 @@ pydantic==2.12.5 # via oz-agent-sdk pydantic-core==2.41.5 # via pydantic -pygments==2.19.2 +pygments==2.20.0 # via # pytest # rich @@ -71,7 +71,7 @@ pytest==8.4.2 ; python_full_version < '3.10' # via # pytest-asyncio # pytest-xdist -pytest==9.0.2 ; python_full_version >= '3.10' +pytest==9.1.1 ; python_full_version >= '3.10' # via # pytest-asyncio # pytest-xdist diff --git a/uv.lock b/uv.lock index 13132d8..ddf0935 100644 --- a/uv.lock +++ b/uv.lock @@ -16,7 +16,11 @@ conflicts = [[ ]] [manifest] -constraints = [{ name = "idna", specifier = ">=3.15" }] +constraints = [ + { name = "idna", specifier = ">=3.15" }, + { name = "pygments", specifier = ">=2.20.0" }, + { name = "pytest", marker = "python_full_version >= '3.10'", specifier = ">=9.0.3" }, +] [[package]] name = "aiohappyeyeballs" @@ -27,156 +31,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, ] -[[package]] -name = "aiohttp" -version = "3.13.5" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "aiohappyeyeballs", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "aiosignal", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "async-timeout", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "attrs", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "frozenlist", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "multidict", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "propcache", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "yarl", marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/77/9a/152096d4808df8e4268befa55fba462f440f14beab85e8ad9bf990516918/aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1", size = 7858271, upload-time = "2026-03-31T22:01:03.343Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/85/cebc47ee74d8b408749073a1a46c6fcba13d170dc8af7e61996c6c9394ac/aiohttp-3.13.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b", size = 750547, upload-time = "2026-03-31T21:56:30.024Z" }, - { url = "https://files.pythonhosted.org/packages/05/98/afd308e35b9d3d8c9ec54c0918f1d722c86dc17ddfec272fcdbcce5a3124/aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5", size = 503535, upload-time = "2026-03-31T21:56:31.935Z" }, - { url = "https://files.pythonhosted.org/packages/6f/4d/926c183e06b09d5270a309eb50fbde7b09782bfd305dec1e800f329834fb/aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670", size = 497830, upload-time = "2026-03-31T21:56:33.654Z" }, - { url = "https://files.pythonhosted.org/packages/e4/d6/f47d1c690f115a5c2a5e8938cce4a232a5be9aac5c5fb2647efcbbbda333/aiohttp-3.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274", size = 1682474, upload-time = "2026-03-31T21:56:35.513Z" }, - { url = "https://files.pythonhosted.org/packages/01/44/056fd37b1bb52eac760303e5196acc74d9d546631b035704ae5927f7b4ac/aiohttp-3.13.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a", size = 1655259, upload-time = "2026-03-31T21:56:37.843Z" }, - { url = "https://files.pythonhosted.org/packages/91/9f/78eb1a20c1c28ae02f6a3c0f4d7b0dcc66abce5290cadd53d78ce3084175/aiohttp-3.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d", size = 1736204, upload-time = "2026-03-31T21:56:39.822Z" }, - { url = "https://files.pythonhosted.org/packages/de/6c/d20d7de23f0b52b8c1d9e2033b2db1ac4dacbb470bb74c56de0f5f86bb4f/aiohttp-3.13.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796", size = 1826198, upload-time = "2026-03-31T21:56:41.378Z" }, - { url = "https://files.pythonhosted.org/packages/2f/86/a6f3ff1fd795f49545a7c74b2c92f62729135d73e7e4055bf74da5a26c82/aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95", size = 1681329, upload-time = "2026-03-31T21:56:43.374Z" }, - { url = "https://files.pythonhosted.org/packages/fb/68/84cd3dab6b7b4f3e6fe9459a961acb142aaab846417f6e8905110d7027e5/aiohttp-3.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5", size = 1560023, upload-time = "2026-03-31T21:56:45.031Z" }, - { url = "https://files.pythonhosted.org/packages/41/2c/db61b64b0249e30f954a65ab4cb4970ced57544b1de2e3c98ee5dc24165f/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a", size = 1652372, upload-time = "2026-03-31T21:56:47.075Z" }, - { url = "https://files.pythonhosted.org/packages/25/6f/e96988a6c982d047810c772e28c43c64c300c943b0ed5c1c0c4ce1e1027c/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73", size = 1662031, upload-time = "2026-03-31T21:56:48.835Z" }, - { url = "https://files.pythonhosted.org/packages/b7/26/a56feace81f3d347b4052403a9d03754a0ab23f7940780dada0849a38c92/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297", size = 1708118, upload-time = "2026-03-31T21:56:50.833Z" }, - { url = "https://files.pythonhosted.org/packages/78/6e/b6173a8ff03d01d5e1a694bc06764b5dad1df2d4ed8f0ceec12bb3277936/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074", size = 1548667, upload-time = "2026-03-31T21:56:52.81Z" }, - { url = "https://files.pythonhosted.org/packages/16/13/13296ffe2c132d888b3fe2c195c8b9c0c24c89c3fa5cc2c44464dc23b22e/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e", size = 1724490, upload-time = "2026-03-31T21:56:54.541Z" }, - { url = "https://files.pythonhosted.org/packages/7a/b4/1f1c287f4a79782ef36e5a6e62954c85343bc30470d862d30bd5f26c9fa2/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7", size = 1667109, upload-time = "2026-03-31T21:56:56.21Z" }, - { url = "https://files.pythonhosted.org/packages/ef/42/8461a2aaf60a8f4ea4549a4056be36b904b0eb03d97ca9a8a2604681a500/aiohttp-3.13.5-cp310-cp310-win32.whl", hash = "sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9", size = 439478, upload-time = "2026-03-31T21:56:58.292Z" }, - { url = "https://files.pythonhosted.org/packages/e5/71/06956304cb5ee439dfe8d86e1b2e70088bd88ed1ced1f42fb29e5d855f0e/aiohttp-3.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76", size = 462047, upload-time = "2026-03-31T21:57:00.257Z" }, - { url = "https://files.pythonhosted.org/packages/d6/f5/a20c4ac64aeaef1679e25c9983573618ff765d7aa829fa2b84ae7573169e/aiohttp-3.13.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6", size = 757513, upload-time = "2026-03-31T21:57:02.146Z" }, - { url = "https://files.pythonhosted.org/packages/75/0a/39fa6c6b179b53fcb3e4b3d2b6d6cad0180854eda17060c7218540102bef/aiohttp-3.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d", size = 506748, upload-time = "2026-03-31T21:57:04.275Z" }, - { url = "https://files.pythonhosted.org/packages/87/ec/e38ce072e724fd7add6243613f8d1810da084f54175353d25ccf9f9c7e5a/aiohttp-3.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c", size = 501673, upload-time = "2026-03-31T21:57:06.208Z" }, - { url = "https://files.pythonhosted.org/packages/ba/ba/3bc7525d7e2beaa11b309a70d48b0d3cfc3c2089ec6a7d0820d59c657053/aiohttp-3.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb", size = 1763757, upload-time = "2026-03-31T21:57:07.882Z" }, - { url = "https://files.pythonhosted.org/packages/5e/ab/e87744cf18f1bd78263aba24924d4953b41086bd3a31d22452378e9028a0/aiohttp-3.13.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6", size = 1720152, upload-time = "2026-03-31T21:57:09.946Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f3/ed17a6f2d742af17b50bae2d152315ed1b164b07a5fd5cc1754d99e4dfa5/aiohttp-3.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13", size = 1818010, upload-time = "2026-03-31T21:57:12.157Z" }, - { url = "https://files.pythonhosted.org/packages/53/06/ecbc63dc937192e2a5cb46df4d3edb21deb8225535818802f210a6ea5816/aiohttp-3.13.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174", size = 1907251, upload-time = "2026-03-31T21:57:14.023Z" }, - { url = "https://files.pythonhosted.org/packages/7e/a5/0521aa32c1ddf3aa1e71dcc466be0b7db2771907a13f18cddaa45967d97b/aiohttp-3.13.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc", size = 1759969, upload-time = "2026-03-31T21:57:16.146Z" }, - { url = "https://files.pythonhosted.org/packages/f6/78/a38f8c9105199dd3b9706745865a8a59d0041b6be0ca0cc4b2ccf1bab374/aiohttp-3.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6", size = 1616871, upload-time = "2026-03-31T21:57:17.856Z" }, - { url = "https://files.pythonhosted.org/packages/6f/41/27392a61ead8ab38072105c71aa44ff891e71653fe53d576a7067da2b4e8/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49", size = 1739844, upload-time = "2026-03-31T21:57:19.679Z" }, - { url = "https://files.pythonhosted.org/packages/6e/55/5564e7ae26d94f3214250009a0b1c65a0c6af4bf88924ccb6fdab901de28/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8", size = 1731969, upload-time = "2026-03-31T21:57:22.006Z" }, - { url = "https://files.pythonhosted.org/packages/6d/c5/705a3929149865fc941bcbdd1047b238e4a72bcb215a9b16b9d7a2e8d992/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d", size = 1795193, upload-time = "2026-03-31T21:57:24.256Z" }, - { url = "https://files.pythonhosted.org/packages/a6/19/edabed62f718d02cff7231ca0db4ef1c72504235bc467f7b67adb1679f48/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c", size = 1606477, upload-time = "2026-03-31T21:57:26.364Z" }, - { url = "https://files.pythonhosted.org/packages/de/fc/76f80ef008675637d88d0b21584596dc27410a990b0918cb1e5776545b5b/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac", size = 1813198, upload-time = "2026-03-31T21:57:28.316Z" }, - { url = "https://files.pythonhosted.org/packages/e5/67/5b3ac26b80adb20ea541c487f73730dc8fa107d632c998f25bbbab98fcda/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3", size = 1752321, upload-time = "2026-03-31T21:57:30.549Z" }, - { url = "https://files.pythonhosted.org/packages/88/06/e4a2e49255ea23fa4feeb5ab092d90240d927c15e47b5b5c48dff5a9ce29/aiohttp-3.13.5-cp311-cp311-win32.whl", hash = "sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06", size = 439069, upload-time = "2026-03-31T21:57:32.388Z" }, - { url = "https://files.pythonhosted.org/packages/c0/43/8c7163a596dab4f8be12c190cf467a1e07e4734cf90eebb39f7f5d53fc6a/aiohttp-3.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8", size = 462859, upload-time = "2026-03-31T21:57:34.455Z" }, - { url = "https://files.pythonhosted.org/packages/be/6f/353954c29e7dcce7cf00280a02c75f30e133c00793c7a2ed3776d7b2f426/aiohttp-3.13.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9", size = 748876, upload-time = "2026-03-31T21:57:36.319Z" }, - { url = "https://files.pythonhosted.org/packages/f5/1b/428a7c64687b3b2e9cd293186695affc0e1e54a445d0361743b231f11066/aiohttp-3.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416", size = 499557, upload-time = "2026-03-31T21:57:38.236Z" }, - { url = "https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2", size = 500258, upload-time = "2026-03-31T21:57:39.923Z" }, - { url = "https://files.pythonhosted.org/packages/67/84/c9ecc5828cb0b3695856c07c0a6817a99d51e2473400f705275a2b3d9239/aiohttp-3.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4", size = 1749199, upload-time = "2026-03-31T21:57:41.938Z" }, - { url = "https://files.pythonhosted.org/packages/f0/d3/3c6d610e66b495657622edb6ae7c7fd31b2e9086b4ec50b47897ad6042a9/aiohttp-3.13.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9", size = 1721013, upload-time = "2026-03-31T21:57:43.904Z" }, - { url = "https://files.pythonhosted.org/packages/49/a0/24409c12217456df0bae7babe3b014e460b0b38a8e60753d6cb339f6556d/aiohttp-3.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5", size = 1781501, upload-time = "2026-03-31T21:57:46.285Z" }, - { url = "https://files.pythonhosted.org/packages/98/9d/b65ec649adc5bccc008b0957a9a9c691070aeac4e41cea18559fef49958b/aiohttp-3.13.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e", size = 1878981, upload-time = "2026-03-31T21:57:48.734Z" }, - { url = "https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1", size = 1767934, upload-time = "2026-03-31T21:57:51.171Z" }, - { url = "https://files.pythonhosted.org/packages/31/04/d3f8211f273356f158e3464e9e45484d3fb8c4ce5eb2f6fe9405c3273983/aiohttp-3.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286", size = 1566671, upload-time = "2026-03-31T21:57:53.326Z" }, - { url = "https://files.pythonhosted.org/packages/41/db/073e4ebe00b78e2dfcacff734291651729a62953b48933d765dc513bf798/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9", size = 1705219, upload-time = "2026-03-31T21:57:55.385Z" }, - { url = "https://files.pythonhosted.org/packages/48/45/7dfba71a2f9fd97b15c95c06819de7eb38113d2cdb6319669195a7d64270/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88", size = 1743049, upload-time = "2026-03-31T21:57:57.341Z" }, - { url = "https://files.pythonhosted.org/packages/18/71/901db0061e0f717d226386a7f471bb59b19566f2cae5f0d93874b017271f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3", size = 1749557, upload-time = "2026-03-31T21:57:59.626Z" }, - { url = "https://files.pythonhosted.org/packages/08/d5/41eebd16066e59cd43728fe74bce953d7402f2b4ddfdfef2c0e9f17ca274/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b", size = 1558931, upload-time = "2026-03-31T21:58:01.972Z" }, - { url = "https://files.pythonhosted.org/packages/30/e6/4a799798bf05740e66c3a1161079bda7a3dd8e22ca392481d7a7f9af82a6/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe", size = 1774125, upload-time = "2026-03-31T21:58:04.007Z" }, - { url = "https://files.pythonhosted.org/packages/84/63/7749337c90f92bc2cb18f9560d67aa6258c7060d1397d21529b8004fcf6f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14", size = 1732427, upload-time = "2026-03-31T21:58:06.337Z" }, - { url = "https://files.pythonhosted.org/packages/98/de/cf2f44ff98d307e72fb97d5f5bbae3bfcb442f0ea9790c0bf5c5c2331404/aiohttp-3.13.5-cp312-cp312-win32.whl", hash = "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3", size = 433534, upload-time = "2026-03-31T21:58:08.712Z" }, - { url = "https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1", size = 460446, upload-time = "2026-03-31T21:58:10.945Z" }, - { url = "https://files.pythonhosted.org/packages/78/e9/d76bf503005709e390122d34e15256b88f7008e246c4bdbe915cd4f1adce/aiohttp-3.13.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61", size = 742930, upload-time = "2026-03-31T21:58:13.155Z" }, - { url = "https://files.pythonhosted.org/packages/57/00/4b7b70223deaebd9bb85984d01a764b0d7bd6526fcdc73cca83bcbe7243e/aiohttp-3.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832", size = 496927, upload-time = "2026-03-31T21:58:15.073Z" }, - { url = "https://files.pythonhosted.org/packages/9c/f5/0fb20fb49f8efdcdce6cd8127604ad2c503e754a8f139f5e02b01626523f/aiohttp-3.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9", size = 497141, upload-time = "2026-03-31T21:58:17.009Z" }, - { url = "https://files.pythonhosted.org/packages/3b/86/b7c870053e36a94e8951b803cb5b909bfbc9b90ca941527f5fcafbf6b0fa/aiohttp-3.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090", size = 1732476, upload-time = "2026-03-31T21:58:18.925Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e5/4e161f84f98d80c03a238671b4136e6530453d65262867d989bbe78244d0/aiohttp-3.13.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b", size = 1706507, upload-time = "2026-03-31T21:58:21.094Z" }, - { url = "https://files.pythonhosted.org/packages/d4/56/ea11a9f01518bd5a2a2fcee869d248c4b8a0cfa0bb13401574fa31adf4d4/aiohttp-3.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a", size = 1773465, upload-time = "2026-03-31T21:58:23.159Z" }, - { url = "https://files.pythonhosted.org/packages/eb/40/333ca27fb74b0383f17c90570c748f7582501507307350a79d9f9f3c6eb1/aiohttp-3.13.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8", size = 1873523, upload-time = "2026-03-31T21:58:25.59Z" }, - { url = "https://files.pythonhosted.org/packages/f0/d2/e2f77eef1acb7111405433c707dc735e63f67a56e176e72e9e7a2cd3f493/aiohttp-3.13.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665", size = 1754113, upload-time = "2026-03-31T21:58:27.624Z" }, - { url = "https://files.pythonhosted.org/packages/fb/56/3f653d7f53c89669301ec9e42c95233e2a0c0a6dd051269e6e678db4fdb0/aiohttp-3.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540", size = 1562351, upload-time = "2026-03-31T21:58:29.918Z" }, - { url = "https://files.pythonhosted.org/packages/ec/a6/9b3e91eb8ae791cce4ee736da02211c85c6f835f1bdfac0594a8a3b7018c/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb", size = 1693205, upload-time = "2026-03-31T21:58:32.214Z" }, - { url = "https://files.pythonhosted.org/packages/98/fc/bfb437a99a2fcebd6b6eaec609571954de2ed424f01c352f4b5504371dd3/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46", size = 1730618, upload-time = "2026-03-31T21:58:34.728Z" }, - { url = "https://files.pythonhosted.org/packages/e4/b6/c8534862126191a034f68153194c389addc285a0f1347d85096d349bbc15/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8", size = 1745185, upload-time = "2026-03-31T21:58:36.909Z" }, - { url = "https://files.pythonhosted.org/packages/0b/93/4ca8ee2ef5236e2707e0fd5fecb10ce214aee1ff4ab307af9c558bda3b37/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d", size = 1557311, upload-time = "2026-03-31T21:58:39.38Z" }, - { url = "https://files.pythonhosted.org/packages/57/ae/76177b15f18c5f5d094f19901d284025db28eccc5ae374d1d254181d33f4/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6", size = 1773147, upload-time = "2026-03-31T21:58:41.476Z" }, - { url = "https://files.pythonhosted.org/packages/01/a4/62f05a0a98d88af59d93b7fcac564e5f18f513cb7471696ac286db970d6a/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c", size = 1730356, upload-time = "2026-03-31T21:58:44.049Z" }, - { url = "https://files.pythonhosted.org/packages/e4/85/fc8601f59dfa8c9523808281f2da571f8b4699685f9809a228adcc90838d/aiohttp-3.13.5-cp313-cp313-win32.whl", hash = "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc", size = 432637, upload-time = "2026-03-31T21:58:46.167Z" }, - { url = "https://files.pythonhosted.org/packages/c0/1b/ac685a8882896acf0f6b31d689e3792199cfe7aba37969fa91da63a7fa27/aiohttp-3.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83", size = 458896, upload-time = "2026-03-31T21:58:48.119Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ce/46572759afc859e867a5bc8ec3487315869013f59281ce61764f76d879de/aiohttp-3.13.5-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c", size = 745721, upload-time = "2026-03-31T21:58:50.229Z" }, - { url = "https://files.pythonhosted.org/packages/13/fe/8a2efd7626dbe6049b2ef8ace18ffda8a4dfcbe1bcff3ac30c0c7575c20b/aiohttp-3.13.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be", size = 497663, upload-time = "2026-03-31T21:58:52.232Z" }, - { url = "https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25", size = 499094, upload-time = "2026-03-31T21:58:54.566Z" }, - { url = "https://files.pythonhosted.org/packages/0a/33/a8362cb15cf16a3af7e86ed11962d5cd7d59b449202dc576cdc731310bde/aiohttp-3.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56", size = 1726701, upload-time = "2026-03-31T21:58:56.864Z" }, - { url = "https://files.pythonhosted.org/packages/45/0c/c091ac5c3a17114bd76cbf85d674650969ddf93387876cf67f754204bd77/aiohttp-3.13.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2", size = 1683360, upload-time = "2026-03-31T21:58:59.072Z" }, - { url = "https://files.pythonhosted.org/packages/23/73/bcee1c2b79bc275e964d1446c55c54441a461938e70267c86afaae6fba27/aiohttp-3.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a", size = 1773023, upload-time = "2026-03-31T21:59:01.776Z" }, - { url = "https://files.pythonhosted.org/packages/c7/ef/720e639df03004fee2d869f771799d8c23046dec47d5b81e396c7cda583a/aiohttp-3.13.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be", size = 1853795, upload-time = "2026-03-31T21:59:04.568Z" }, - { url = "https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b", size = 1730405, upload-time = "2026-03-31T21:59:07.221Z" }, - { url = "https://files.pythonhosted.org/packages/ce/75/ee1fd286ca7dc599d824b5651dad7b3be7ff8d9a7e7b3fe9820d9180f7db/aiohttp-3.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94", size = 1558082, upload-time = "2026-03-31T21:59:09.484Z" }, - { url = "https://files.pythonhosted.org/packages/c3/20/1e9e6650dfc436340116b7aa89ff8cb2bbdf0abc11dfaceaad8f74273a10/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d", size = 1692346, upload-time = "2026-03-31T21:59:12.068Z" }, - { url = "https://files.pythonhosted.org/packages/d8/40/8ebc6658d48ea630ac7903912fe0dd4e262f0e16825aa4c833c56c9f1f56/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7", size = 1698891, upload-time = "2026-03-31T21:59:14.552Z" }, - { url = "https://files.pythonhosted.org/packages/d8/78/ea0ae5ec8ba7a5c10bdd6e318f1ba5e76fcde17db8275188772afc7917a4/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772", size = 1742113, upload-time = "2026-03-31T21:59:17.068Z" }, - { url = "https://files.pythonhosted.org/packages/8a/66/9d308ed71e3f2491be1acb8769d96c6f0c47d92099f3bc9119cada27b357/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5", size = 1553088, upload-time = "2026-03-31T21:59:19.541Z" }, - { url = "https://files.pythonhosted.org/packages/da/a6/6cc25ed8dfc6e00c90f5c6d126a98e2cf28957ad06fa1036bd34b6f24a2c/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1", size = 1757976, upload-time = "2026-03-31T21:59:22.311Z" }, - { url = "https://files.pythonhosted.org/packages/c1/2b/cce5b0ffe0de99c83e5e36d8f828e4161e415660a9f3e58339d07cce3006/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b", size = 1712444, upload-time = "2026-03-31T21:59:24.635Z" }, - { url = "https://files.pythonhosted.org/packages/6c/cf/9e1795b4160c58d29421eafd1a69c6ce351e2f7c8d3c6b7e4ca44aea1a5b/aiohttp-3.13.5-cp314-cp314-win32.whl", hash = "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3", size = 438128, upload-time = "2026-03-31T21:59:27.291Z" }, - { url = "https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162", size = 464029, upload-time = "2026-03-31T21:59:29.429Z" }, - { url = "https://files.pythonhosted.org/packages/79/11/c27d9332ee20d68dd164dc12a6ecdef2e2e35ecc97ed6cf0d2442844624b/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a", size = 778758, upload-time = "2026-03-31T21:59:31.547Z" }, - { url = "https://files.pythonhosted.org/packages/04/fb/377aead2e0a3ba5f09b7624f702a964bdf4f08b5b6728a9799830c80041e/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254", size = 512883, upload-time = "2026-03-31T21:59:34.098Z" }, - { url = "https://files.pythonhosted.org/packages/bb/a6/aa109a33671f7a5d3bd78b46da9d852797c5e665bfda7d6b373f56bff2ec/aiohttp-3.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36", size = 516668, upload-time = "2026-03-31T21:59:36.497Z" }, - { url = "https://files.pythonhosted.org/packages/79/b3/ca078f9f2fa9563c36fb8ef89053ea2bb146d6f792c5104574d49d8acb63/aiohttp-3.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f", size = 1883461, upload-time = "2026-03-31T21:59:38.723Z" }, - { url = "https://files.pythonhosted.org/packages/b7/e3/a7ad633ca1ca497b852233a3cce6906a56c3225fb6d9217b5e5e60b7419d/aiohttp-3.13.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800", size = 1747661, upload-time = "2026-03-31T21:59:41.187Z" }, - { url = "https://files.pythonhosted.org/packages/33/b9/cd6fe579bed34a906d3d783fe60f2fa297ef55b27bb4538438ee49d4dc41/aiohttp-3.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf", size = 1863800, upload-time = "2026-03-31T21:59:43.84Z" }, - { url = "https://files.pythonhosted.org/packages/c0/3f/2c1e2f5144cefa889c8afd5cf431994c32f3b29da9961698ff4e3811b79a/aiohttp-3.13.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b", size = 1958382, upload-time = "2026-03-31T21:59:46.187Z" }, - { url = "https://files.pythonhosted.org/packages/66/1d/f31ec3f1013723b3babe3609e7f119c2c2fb6ef33da90061a705ef3e1bc8/aiohttp-3.13.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a", size = 1803724, upload-time = "2026-03-31T21:59:48.656Z" }, - { url = "https://files.pythonhosted.org/packages/0e/b4/57712dfc6f1542f067daa81eb61da282fab3e6f1966fca25db06c4fc62d5/aiohttp-3.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8", size = 1640027, upload-time = "2026-03-31T21:59:51.284Z" }, - { url = "https://files.pythonhosted.org/packages/25/3c/734c878fb43ec083d8e31bf029daae1beafeae582d1b35da234739e82ee7/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be", size = 1806644, upload-time = "2026-03-31T21:59:53.753Z" }, - { url = "https://files.pythonhosted.org/packages/20/a5/f671e5cbec1c21d044ff3078223f949748f3a7f86b14e34a365d74a5d21f/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b", size = 1791630, upload-time = "2026-03-31T21:59:56.239Z" }, - { url = "https://files.pythonhosted.org/packages/0b/63/fb8d0ad63a0b8a99be97deac8c04dacf0785721c158bdf23d679a87aa99e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6", size = 1809403, upload-time = "2026-03-31T21:59:59.103Z" }, - { url = "https://files.pythonhosted.org/packages/59/0c/bfed7f30662fcf12206481c2aac57dedee43fe1c49275e85b3a1e1742294/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037", size = 1634924, upload-time = "2026-03-31T22:00:02.116Z" }, - { url = "https://files.pythonhosted.org/packages/17/d6/fd518d668a09fd5a3319ae5e984d4d80b9a4b3df4e21c52f02251ef5a32e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500", size = 1836119, upload-time = "2026-03-31T22:00:04.756Z" }, - { url = "https://files.pythonhosted.org/packages/78/b7/15fb7a9d52e112a25b621c67b69c167805cb1f2ab8f1708a5c490d1b52fe/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9", size = 1772072, upload-time = "2026-03-31T22:00:07.494Z" }, - { url = "https://files.pythonhosted.org/packages/7e/df/57ba7f0c4a553fc2bd8b6321df236870ec6fd64a2a473a8a13d4f733214e/aiohttp-3.13.5-cp314-cp314t-win32.whl", hash = "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8", size = 471819, upload-time = "2026-03-31T22:00:10.277Z" }, - { url = "https://files.pythonhosted.org/packages/62/29/2f8418269e46454a26171bfdd6a055d74febf32234e474930f2f60a17145/aiohttp-3.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9", size = 505441, upload-time = "2026-03-31T22:00:12.791Z" }, - { url = "https://files.pythonhosted.org/packages/e2/a5/630bc484695d4a1342bbae85fb8689bf979106525684fc88f05b397324ad/aiohttp-3.13.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf", size = 752872, upload-time = "2026-03-31T22:00:15.553Z" }, - { url = "https://files.pythonhosted.org/packages/cd/b8/6a19dda37fda94a9ebefb3c1ae0ff419ac7fbf4fb40750e992829fc13614/aiohttp-3.13.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1", size = 504582, upload-time = "2026-03-31T22:00:18.191Z" }, - { url = "https://files.pythonhosted.org/packages/d5/34/8413eafee3421ade2d6ce9e7c0da1213e1d7f0049be09dcdc342b03a39ba/aiohttp-3.13.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10", size = 499094, upload-time = "2026-03-31T22:00:21.118Z" }, - { url = "https://files.pythonhosted.org/packages/da/cf/c6f97006093d1e8ca40fbab843ff49ec7725ab668f0714dd1cb702c62cbd/aiohttp-3.13.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f", size = 1669505, upload-time = "2026-03-31T22:00:24.01Z" }, - { url = "https://files.pythonhosted.org/packages/c2/27/3b2288e66dcec8b04771b2bee3909f70e4072bea995cde5ab7e775e73ddc/aiohttp-3.13.5-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b", size = 1648928, upload-time = "2026-03-31T22:00:27.001Z" }, - { url = "https://files.pythonhosted.org/packages/3a/7f/605d766887594a88dcc27a19663499c7c5e13e7aa87f129b763765a2ee63/aiohttp-3.13.5-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643", size = 1731800, upload-time = "2026-03-31T22:00:29.603Z" }, - { url = "https://files.pythonhosted.org/packages/71/94/5a878e728e30699d22b118f1a6ad576ab6fff9eb2c6fc8a7faa9376a1c3e/aiohttp-3.13.5-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031", size = 1824247, upload-time = "2026-03-31T22:00:32.139Z" }, - { url = "https://files.pythonhosted.org/packages/37/99/84b448291e9996bb83bf4fad3a71a9786d542f19c50a3ff0531bfaba6fac/aiohttp-3.13.5-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258", size = 1670742, upload-time = "2026-03-31T22:00:34.788Z" }, - { url = "https://files.pythonhosted.org/packages/14/a8/d8d5d1ab6d29a4a3bdb9db31f161e338bfdf6638f6574ea8380f1d4a243c/aiohttp-3.13.5-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a", size = 1562474, upload-time = "2026-03-31T22:00:37.623Z" }, - { url = "https://files.pythonhosted.org/packages/92/e8/bd889697916f10b65524422c61b4eeaf919eb35a170290cccb680cbe4eb4/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88", size = 1642235, upload-time = "2026-03-31T22:00:40.541Z" }, - { url = "https://files.pythonhosted.org/packages/60/42/3f1928107131f1413a5972ace14ddcd5364968e9bd7b3ad71272defafc9c/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0", size = 1655397, upload-time = "2026-03-31T22:00:43.167Z" }, - { url = "https://files.pythonhosted.org/packages/b2/79/c4bbcf4cac3a4715a326e49720ccdc3a4b5e14a367c5029eae7727d06029/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f", size = 1703509, upload-time = "2026-03-31T22:00:45.908Z" }, - { url = "https://files.pythonhosted.org/packages/d1/e6/32d245876f211a7308a7d5437707f9296b1f9837a2888a407ed04e61321c/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8", size = 1550098, upload-time = "2026-03-31T22:00:49.48Z" }, - { url = "https://files.pythonhosted.org/packages/db/62/ab0f1304def56ce2356e6fbb9f0b024d6544010351430070f48f53b89e0a/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f", size = 1724326, upload-time = "2026-03-31T22:00:52.165Z" }, - { url = "https://files.pythonhosted.org/packages/c4/9a/aab4469689024046220ea438aa020ea2ae04cd1dd71aea3057e094f8c357/aiohttp-3.13.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b", size = 1658824, upload-time = "2026-03-31T22:00:55.122Z" }, - { url = "https://files.pythonhosted.org/packages/b0/98/bcc35d4db687acabf06d41f561a99fa88bca145292513388c858d99b72c5/aiohttp-3.13.5-cp39-cp39-win32.whl", hash = "sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83", size = 440302, upload-time = "2026-03-31T22:00:57.673Z" }, - { url = "https://files.pythonhosted.org/packages/25/61/b0203c2ef6bd268fca0eda142f0efbba7cbebd7ad38f7bb01dd31c2ff68e/aiohttp-3.13.5-cp39-cp39-win_amd64.whl", hash = "sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67", size = 463076, upload-time = "2026-03-31T22:01:00.264Z" }, -] - [[package]] name = "aiohttp" version = "3.14.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2'", - "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra != 'group-12-oz-agent-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra != 'group-12-oz-agent-sdk-pydantic-v2'", -] dependencies = [ { name = "aiohappyeyeballs", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "aiosignal", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, @@ -315,8 +173,8 @@ name = "aiosignal" version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "frozenlist" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "frozenlist", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "typing-extensions", marker = "(python_full_version >= '3.10' and python_full_version < '3.13') or (python_full_version < '3.10' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2') or (python_full_version >= '3.13' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } wheels = [ @@ -609,9 +467,8 @@ name = "httpx-aiohttp" version = "0.1.12" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "aiohttp", version = "3.13.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "aiohttp", version = "3.14.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "httpx" }, + { name = "aiohttp", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "httpx", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/63/2c/b894861cecf030fb45675ea24aa55b5722e97c602a163d872fca66c5a6d8/httpx_aiohttp-0.1.12.tar.gz", hash = "sha256:81feec51fd82c0ecfa0e9aaf1b1a6c2591260d5e2bcbeb7eb0277a78e610df2c", size = 275945, upload-time = "2025-12-12T10:12:15.283Z" } wheels = [ @@ -713,7 +570,7 @@ name = "multidict" version = "6.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "typing-extensions", marker = "python_full_version == '3.10.*' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" } wheels = [ @@ -943,9 +800,8 @@ dependencies = [ [package.optional-dependencies] aiohttp = [ - { name = "aiohttp", version = "3.13.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "aiohttp", version = "3.14.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "httpx-aiohttp" }, + { name = "aiohttp", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "httpx-aiohttp", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] [package.dev-dependencies] @@ -955,7 +811,7 @@ dev = [ { name = "mypy" }, { name = "pyright" }, { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "pytest", version = "9.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "pytest-asyncio", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "pytest-asyncio", version = "1.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "pytest-xdist" }, @@ -974,11 +830,11 @@ pydantic-v2 = [ [package.metadata] requires-dist = [ - { name = "aiohttp", marker = "extra == 'aiohttp'", specifier = ">=3.13.5" }, + { name = "aiohttp", marker = "python_full_version >= '3.10' and extra == 'aiohttp'", specifier = ">=3.14.1" }, { name = "anyio", specifier = ">=3.5.0,<5" }, { name = "distro", specifier = ">=1.7.0,<2" }, { name = "httpx", specifier = ">=0.23.0,<1" }, - { name = "httpx-aiohttp", marker = "extra == 'aiohttp'", specifier = ">=0.1.9" }, + { name = "httpx-aiohttp", marker = "python_full_version >= '3.10' and extra == 'aiohttp'", specifier = ">=0.1.9" }, { name = "pydantic", specifier = ">=1.9.0,<3" }, { name = "sniffio" }, { name = "typing-extensions", specifier = ">=4.14,<5" }, @@ -1362,11 +1218,11 @@ wheels = [ [[package]] name = "pygments" -version = "2.19.2" +version = "2.20.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, ] [[package]] @@ -1405,7 +1261,7 @@ wheels = [ [[package]] name = "pytest" -version = "9.0.2" +version = "9.1.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and extra != 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2'", @@ -1422,9 +1278,9 @@ dependencies = [ { name = "pygments", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "tomli", marker = "python_full_version == '3.10.*' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, ] [[package]] @@ -1456,7 +1312,7 @@ resolution-markers = [ ] dependencies = [ { name = "backports-asyncio-runner", marker = "python_full_version == '3.10.*' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "pytest", version = "9.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, { name = "typing-extensions", marker = "(python_full_version >= '3.10' and python_full_version < '3.13') or (python_full_version < '3.10' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2') or (python_full_version >= '3.13' and extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/90/2c/8af215c0f776415f3590cac4f9086ccefd6fd463befeae41cd4d3f193e5a/pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5", size = 50087, upload-time = "2025-11-10T16:07:47.256Z" } @@ -1471,7 +1327,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "execnet" }, { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, - { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "pytest", version = "9.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } wheels = [ @@ -1833,9 +1689,9 @@ name = "yarl" version = "1.22.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "idna" }, - { name = "multidict" }, - { name = "propcache" }, + { name = "idna", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "multidict", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, + { name = "propcache", marker = "python_full_version >= '3.10' or (extra == 'group-12-oz-agent-sdk-pydantic-v1' and extra == 'group-12-oz-agent-sdk-pydantic-v2')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } wheels = [ From 779259fa90af41a7666ebdf14f4026453a648f1f Mon Sep 17 00:00:00 2001 From: liliwilson Date: Wed, 24 Jun 2026 18:51:18 +0000 Subject: [PATCH 13/14] fix(lint): suppress pyright errors for optional httpx_aiohttp import on Python 3.9 aiohttp>=3.14.1 dropped Python 3.9 support, so the aiohttp extra is restricted to python_version>='3.10'. On Python 3.9, httpx_aiohttp is not installed, causing pyright to emit reportMissingImports and reportUnknownMemberType errors in _base_client.py. Suppress them with targeted type: ignore comments (consistent with existing # type: ignore on the class definition line). Stainless-Generated-From: 4ab431c104fb2e887cc8bea4abaa07cba4374349 Co-Authored-By: Oz --- src/oz_agent_sdk/_base_client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/oz_agent_sdk/_base_client.py b/src/oz_agent_sdk/_base_client.py index 047d5bb..2122696 100644 --- a/src/oz_agent_sdk/_base_client.py +++ b/src/oz_agent_sdk/_base_client.py @@ -1397,7 +1397,7 @@ def __init__(self, **kwargs: Any) -> None: try: - import httpx_aiohttp + import httpx_aiohttp # type: ignore[import] except ImportError: class _DefaultAioHttpClient(httpx.AsyncClient): @@ -1411,7 +1411,7 @@ def __init__(self, **kwargs: Any) -> None: kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS) kwargs.setdefault("follow_redirects", True) - super().__init__(**kwargs) + super().__init__(**kwargs) # type: ignore[no-untyped-call] if TYPE_CHECKING: From bc21ec14851c71bb7fc6d4fe7ebc58ccc0e10865 Mon Sep 17 00:00:00 2001 From: stlc-bot Date: Wed, 24 Jun 2026 21:22:23 +0000 Subject: [PATCH 14/14] Add Jira to public API run source enum Stainless-Generated-From: 562b7b5ad7e0f38d3643d69a8ab22b72dc4f934c --- src/oz_agent_sdk/types/agent/run_item.py | 1 + src/oz_agent_sdk/types/agent/run_source_type.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/oz_agent_sdk/types/agent/run_item.py b/src/oz_agent_sdk/types/agent/run_item.py index 47231a1..66692ec 100644 --- a/src/oz_agent_sdk/types/agent/run_item.py +++ b/src/oz_agent_sdk/types/agent/run_item.py @@ -223,6 +223,7 @@ class RunItem(BaseModel): - GITHUB_ACTION: Created from a GitHub action - CLOUD_MODE: Created from a Cloud Mode - CLI: Created from the CLI + - JIRA: Created from Jira integration """ started_at: Optional[datetime] = None diff --git a/src/oz_agent_sdk/types/agent/run_source_type.py b/src/oz_agent_sdk/types/agent/run_source_type.py index 344fa13..ec0d1e4 100644 --- a/src/oz_agent_sdk/types/agent/run_source_type.py +++ b/src/oz_agent_sdk/types/agent/run_source_type.py @@ -5,5 +5,5 @@ __all__ = ["RunSourceType"] RunSourceType: TypeAlias = Literal[ - "LINEAR", "API", "SLACK", "LOCAL", "SCHEDULED_AGENT", "WEB_APP", "GITHUB_ACTION", "CLOUD_MODE", "CLI" + "LINEAR", "API", "SLACK", "LOCAL", "SCHEDULED_AGENT", "WEB_APP", "GITHUB_ACTION", "CLOUD_MODE", "CLI", "JIRA" ]