From 9de69b0889dc22985572c024c921970b6bb49d4f Mon Sep 17 00:00:00 2001 From: speakeasybot Date: Thu, 5 Nov 2026 01:52:48 +0000 Subject: [PATCH 1/2] ## Python SDK Changes: * `open_router.batch.create_batches()`: `response.results[].response.body.union(OpenResponsesResult)` **Changed** * `open_router.batch.get_batches()`: `response.results[].response.body.union(OpenResponsesResult)` **Changed** * `open_router.organization.list_members()`: `response.data[].role.enum(org:viewer)` **Added** * `open_router.presets.create_presets_chat_completions()`: * `request.deferred_tools.profile.enum(universal)` **Added** * `open_router.presets.create_presets_messages()`: * `request.deferred_tools.profile.enum(universal)` **Added** * `open_router.presets.create_presets_responses()`: `request` **Changed** --- .speakeasy/gen.lock | 94 +++++++++++-------- .speakeasy/gen.yaml | 2 +- .speakeasy/out.openapi.yaml | 91 +++++++++++++++++- .speakeasy/workflow.lock | 10 +- RELEASES.md | 12 ++- docs/components/chatusage.mdx | 23 ++--- docs/components/deferredtoolscontrol.mdx | 12 +-- docs/components/deferredtoolsdetails.mdx | 15 +++ .../outputtoolsearchservertoolitem.mdx | 22 +++-- .../outputtoolsearchservertoolitemformat.mdx | 17 ++++ docs/components/profile.mdx | 7 +- docs/components/usage.mdx | 23 ++--- .../listorganizationmembersdata.mdx | 14 +-- docs/operations/role.mdx | 3 +- pyproject.toml | 2 +- src/openrouter/_version.py | 4 +- src/openrouter/components/__init__.py | 11 +++ src/openrouter/components/chatusage.py | 7 ++ .../components/deferredtoolscontrol.py | 18 ++-- .../components/deferredtoolsdetails.py | 34 +++++++ src/openrouter/components/inputs_union.py | 24 ++--- .../components/openresponsesresult.py | 14 ++- src/openrouter/components/outputitems.py | 10 +- .../outputtoolsearchservertoolitem.py | 60 +++++++++++- .../operations/listorganizationmembers.py | 7 +- uv.lock | 2 +- 26 files changed, 410 insertions(+), 128 deletions(-) create mode 100644 docs/components/deferredtoolsdetails.mdx create mode 100644 docs/components/outputtoolsearchservertoolitemformat.mdx create mode 100644 src/openrouter/components/deferredtoolsdetails.py diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 6236c3fc9..3eeac571d 100644 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,19 +1,19 @@ lockVersion: 2.0.0 id: c48cf606-fb42-4a45-9c23-8f0555307828 management: - docChecksum: dfe297f1e160a1084303efb6211f4058 + docChecksum: 2fe567942733dd3f020b7f1ff0fd02d8 docVersion: 1.0.0 speakeasyVersion: 1.803.2 generationVersion: 2.950.13 - releaseVersion: 1.3.123 - configChecksum: c674eddd41c9bef60461d13a78688109 + releaseVersion: 1.3.124 + configChecksum: 4c8fc1e57b2cdff5192d1b5b7e2fb166 repoURL: https://github.com/OpenRouterTeam/python-sdk.git installationURL: https://github.com/OpenRouterTeam/python-sdk.git published: true persistentEdits: - generation_id: e42d1548-440e-42f8-9b16-95e929203bf8 - pristine_commit_hash: e4c78f0be023cd6a88bf208f4bdc975ec659747d - pristine_tree_hash: be0568a86fcd500bef84b71d88d6a2d1c4086eec + generation_id: 14a992de-7a74-4727-80d9-47c17f828af9 + pristine_commit_hash: d5164283e00654cebdf94937e24b9726333a4e28 + pristine_tree_hash: 1685aba1ff2cab7e07a13a12174161c55a6008db features: python: acceptHeaders: 3.0.0 @@ -2180,8 +2180,8 @@ trackedFiles: pristine_git_object: 48386287b072381a9b59de6ae804b0ffbbab221a docs/components/chatusage.mdx: id: d7c2bc8b3eb2 - last_write_checksum: sha1:d6d9961d68cec736cd081c151b299b4748e5b87f - pristine_git_object: 2bb1e32441b71d5616dda7134fa115f0a02d423e + last_write_checksum: sha1:7e88196fd7a48982974db6f0fa3d6f6da816fe47 + pristine_git_object: 2f9b81331967705b2abc349c838c760c273ee8be docs/components/chatusagecompletiontokensdetails.mdx: id: 0274e721a9d9 last_write_checksum: sha1:c6111d83cf3b08f228fc92197ce89aba5cba6faf @@ -3052,8 +3052,12 @@ trackedFiles: pristine_git_object: a226240fb3b94358d33acc91761a8bba03309b63 docs/components/deferredtoolscontrol.mdx: id: 13db9fb1f102 - last_write_checksum: sha1:fd854b3d96e1fd9f3223b3603f4c3b80f2612290 - pristine_git_object: ebb8bfa594095e21b1c84eab5a0e3ad3ed16720c + last_write_checksum: sha1:92e20daf24c49c040d40dcba0d6b5f4ec46900f6 + pristine_git_object: c226e1a86b4a6b12668e11e4033c0568a8d4c52d + docs/components/deferredtoolsdetails.mdx: + id: 18832b6c60aa + last_write_checksum: sha1:15b5cc53097084283f00f04ce8b0f4016a0abb5c + pristine_git_object: 2a290bbd3177b4e748807e26d6ac921ff5c091ee docs/components/deferredtoolssearchstrategy.mdx: id: 6152b1ee19ef last_write_checksum: sha1:bbd8c8508c11d8b065cc8a0caed09ef92b820738 @@ -6428,8 +6432,12 @@ trackedFiles: pristine_git_object: d68bd61421859df1e00c0ec15f5a6946ed52dfd1 docs/components/outputtoolsearchservertoolitem.mdx: id: 7106fbb89729 - last_write_checksum: sha1:6158bcc60cd42ce08009cb486e930404245cb21a - pristine_git_object: 29b9d6202d9f4f82768ee0f501f0896752e5c5ac + last_write_checksum: sha1:624ad5b5ea8b46034cde801d3322141411bbda4c + pristine_git_object: c49ae6e87990a02aa270c6d26b98669fd6af4760 + docs/components/outputtoolsearchservertoolitemformat.mdx: + id: 717072e9e3e8 + last_write_checksum: sha1:04cf65dbe63614cfee6df054640472e679b4faac + pristine_git_object: 7d64dcb2814cc71db092a40b0dc45305680f924a docs/components/outputtoolsearchservertoolitemtype.mdx: id: 2b67e805a2ae last_write_checksum: sha1:7d4b330d471721610a9ac7d9f44684fd1a099f7b @@ -6780,8 +6788,8 @@ trackedFiles: pristine_git_object: 6c3e7e5d4da71c9aa3052bf628a98a37de57a648 docs/components/profile.mdx: id: cb682ce5da89 - last_write_checksum: sha1:4cf126470a616a8097d53d721fbc5b50ca2a5495 - pristine_git_object: b59688b7be0ae1054801e22f84a62252d5692821 + last_write_checksum: sha1:85fc558652373eaf48459a2c14c15da8cd7c990e + pristine_git_object: f9eb1da620f71c083b8db1563c4b424f3ece8bcf docs/components/promptcachebreakpoint.mdx: id: c135956dc623 last_write_checksum: sha1:581974fd4042ee26dd8a88d28a084c28b3ccdef9 @@ -8476,8 +8484,8 @@ trackedFiles: pristine_git_object: c5fe94ebc3791026c16a9636c7d6077773297e19 docs/components/usage.mdx: id: d84b29a6ea8c - last_write_checksum: sha1:6fa13809fd51308a2fc96110ff42fe7dc306f867 - pristine_git_object: 10680b424111c6f82d49dc9b2bbe15a6449c802f + last_write_checksum: sha1:a893189873208f1eccc91563aa4e24f2dcc8dc2e + pristine_git_object: f70fe4842e667898a9fbd16eebcbd55c80694f59 docs/components/usagecostdetails.mdx: id: 95d8a52fead9 last_write_checksum: sha1:d3cb96ee83e39f1c736a63f6577d0c0e509a058a @@ -10168,8 +10176,8 @@ trackedFiles: pristine_git_object: f7ab206b5ca32f5af427138d0a9156f66e92211c docs/operations/listorganizationmembersdata.mdx: id: d96ba08cbfe4 - last_write_checksum: sha1:f7e3ae704edba14da53afbc3cde58ceeec1b54e0 - pristine_git_object: fc485e857933e51b9d190534b5f262d2799e315d + last_write_checksum: sha1:e8d8484bd155fd79905699db6ae993d76c1cf74a + pristine_git_object: f65b92ed5b0400090645b019e89358a83484617e docs/operations/listorganizationmembersglobals.mdx: id: 421fd4978d8f last_write_checksum: sha1:b4aec9055bf7a1f276ebdc4b270e09aee733e3fd @@ -10440,8 +10448,8 @@ trackedFiles: pristine_git_object: 24b7423443ac3523f8625a5e517bfc7028bb9481 docs/operations/role.mdx: id: ee0d3c3547d7 - last_write_checksum: sha1:11ebdfcfbf9a1197a42516d3daa0eaa3e2955f81 - pristine_git_object: 9e1219b8c4da58c9ee1d0707aa809d3d3b54f372 + last_write_checksum: sha1:c2c27a0591e9de3995858a6e91f0e6358036f0ed + pristine_git_object: 533bb7464eb384876aba0a0f3c19bcd5382e1cb9 docs/operations/searchsurface.mdx: id: 2d463024ea29 last_write_checksum: sha1:f612f65bd78b46bd424a0bbbbfb6260331738acc @@ -10820,8 +10828,8 @@ trackedFiles: pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544 pyproject.toml: id: 5d07e7d72637 - last_write_checksum: sha1:5329d9a8a9a1686c5eb37209f0582690781c0c22 - pristine_git_object: a66006a71e2412308f21e53e34b58acafd109be6 + last_write_checksum: sha1:c5e1924981838851b3d839d32f63ec62d8996265 + pristine_git_object: a33e8a445cb823382ff26f6e7ab63382970abdf6 scripts/prepare_readme.py: id: e0c5957a6035 last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54 @@ -10848,8 +10856,8 @@ trackedFiles: pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137 src/openrouter/_version.py: id: d8d15ad6c586 - last_write_checksum: sha1:eff4f3a9bc877a572a413e3fa0384027fe0a034a - pristine_git_object: 7250656ffea1731e53d7a49f5f153b4728c199ca + last_write_checksum: sha1:83dce9640df4a5aa9d044290ff5f65c7a0ff1e50 + pristine_git_object: b01419c49ec9beca4349bc329325b37cd378374c src/openrouter/alpha.py: id: 306c4d93308d last_write_checksum: sha1:80cc0f39649445431cc2247ed0e0765438467766 @@ -10896,8 +10904,8 @@ trackedFiles: pristine_git_object: ad3d247954547814054c01989a2dff3d12b3e4e1 src/openrouter/components/__init__.py: id: 81754e97b3f4 - last_write_checksum: sha1:4515fb513d201ae92f0e96aad89bef200973aa80 - pristine_git_object: 212a3d7b1f97f526a713bb58742ac339e0eca83d + last_write_checksum: sha1:77d26d645188b87e6bca9deb1e375de58c598160 + pristine_git_object: 94487b2834d8a4eb212455fec5b618042e9a1677 src/openrouter/components/aabenchmarkentry.py: id: e2e0f0b48c82 last_write_checksum: sha1:fab4d9a24d2cea937bb749d46c5f83941e99d65c @@ -11804,8 +11812,8 @@ trackedFiles: pristine_git_object: 2ccba8386486b7a730816a9829b01754935a2e96 src/openrouter/components/chatusage.py: id: f224a054bf45 - last_write_checksum: sha1:ea708aa417bad1c480ef113ec9c4491f1cdfcf44 - pristine_git_object: 4fd2be35dd11a5c81fcc575f766ae23cbdc4e78e + last_write_checksum: sha1:a16d2ff72e087e940ca5eeef75844baa7e9ca1a1 + pristine_git_object: 9df54c7862f45164e9093affcd8af5a2850cf7aa src/openrouter/components/chatusermessage.py: id: 7777191e729a last_write_checksum: sha1:6e9d3d1a827832b947bbb688a8f78f43aaaa9f81 @@ -12180,8 +12188,12 @@ trackedFiles: pristine_git_object: 8a4e94425724c374a040ea028d0933db39ec1451 src/openrouter/components/deferredtoolscontrol.py: id: b8b6ceef6f86 - last_write_checksum: sha1:a0037788a6737210bec53e6f67046d5eb8ce72f2 - pristine_git_object: 53c2c277462ed9b10ff68432790f1e654b47599b + last_write_checksum: sha1:5e39422e677b596848df4fadf4b32f80d554cab7 + pristine_git_object: cef37bad7a45c3731eeca91832fa4f867c885825 + src/openrouter/components/deferredtoolsdetails.py: + id: 044f0e33803d + last_write_checksum: sha1:2f8fcc43fc779a0cb9621149875a5e7bbfa5e6dc + pristine_git_object: 1cc2be0d154e3487e2f7b33b6cf3baa652f21e5b src/openrouter/components/deferredtoolssearchstrategy.py: id: 6bd66af4513f last_write_checksum: sha1:fa3e06da0ca4390085a58f5ded26a64ebe157fff @@ -12724,8 +12736,8 @@ trackedFiles: pristine_git_object: f499cbbb546232f5cfbfe2c44fb41aefb306c87f src/openrouter/components/inputs_union.py: id: 17d6239cb6a7 - last_write_checksum: sha1:a5065a0dbdecb23a269ca4e60ca0ce0b0a210b18 - pristine_git_object: a2efac9eee07c47fd1d7db56dd24b27c62b816d4 + last_write_checksum: sha1:dfe49f1e6c19162682f6fa841ff6d26081a13a21 + pristine_git_object: bea147ee65f20c44bae5de0c758e7f2959ac8b49 src/openrouter/components/inputtext.py: id: a995ae96be99 last_write_checksum: sha1:94c720a449e0d5a3f23ee7195f648422f61ac114 @@ -13168,8 +13180,8 @@ trackedFiles: pristine_git_object: 08d990d8cc07b7928158fc55784cd9d613f4c58b src/openrouter/components/openresponsesresult.py: id: 78f7e33b19e6 - last_write_checksum: sha1:efefeab1914ae1f1d978084bbd1f01f6844dc463 - pristine_git_object: 703b72543c0783ae1d97a7fab4a7fc45474509ce + last_write_checksum: sha1:4b96f26ba96c33ae35aaa48a0c74616d93dd8d1f + pristine_git_object: d5ffb60091faae032e6d20c5696c4f57314590e0 src/openrouter/components/openrouterfile.py: id: df1961bcb130 last_write_checksum: sha1:1a9a1b1e640f4d0ef78ce0caa160b5ab342f02cc @@ -13340,8 +13352,8 @@ trackedFiles: pristine_git_object: 616b0f5112e106777b4c096aeea6fef58ff32020 src/openrouter/components/outputitems.py: id: 90f107de3116 - last_write_checksum: sha1:b5b931651d18454e9eddc807f9226debf70befdb - pristine_git_object: 53f3d7f01df67fe89520ccae6e5e232a35ff338c + last_write_checksum: sha1:8e0e487161f75e4d205f490f28520fa2f9a16867 + pristine_git_object: c4933ca3bf16935f1defe8ab2ac29cd5e4448310 src/openrouter/components/outputitemwebsearchcall.py: id: bac8732aecb9 last_write_checksum: sha1:00d5b67226d6ff2c6a5497e6e01c764aeede496e @@ -13404,8 +13416,8 @@ trackedFiles: pristine_git_object: d5a5c820aff0971a68a725af296d68d8d3891992 src/openrouter/components/outputtoolsearchservertoolitem.py: id: fb4ec737039d - last_write_checksum: sha1:18ad18555adb74558726426d34dfa28f3c01769a - pristine_git_object: 69f1f522ddee5316f9540e77ec36a1cd7340ab54 + last_write_checksum: sha1:26f3a6e53d940ea78b3317e86a1e4da6eb1a63e0 + pristine_git_object: b1cd35a559ceebe4b5b6d9f85915bb311fca343c src/openrouter/components/outputwebfetchservertoolitem.py: id: 2b12eb287cdf last_write_checksum: sha1:60ec6ef59d691699c092120ea7dffed824197872 @@ -15100,8 +15112,8 @@ trackedFiles: pristine_git_object: 6912194b6639fd1fbcd56b359c52f78857955954 src/openrouter/operations/listorganizationmembers.py: id: d40a3e0e2b38 - last_write_checksum: sha1:95091a5194c0df932a15898831dea3738973ab2b - pristine_git_object: f8ab3cfb4b38110dd4c64da3595e9e1f8d367f2f + last_write_checksum: sha1:f00056f68a32cdd602e362e4180c8344daa4bb41 + pristine_git_object: bab4420d737b66ae01eb72c70892ec4b2b4cfea8 src/openrouter/operations/listpresets.py: id: ecdc7097aab7 last_write_checksum: sha1:4b209724a3bf1627ca12250d165806bed44fb8ac @@ -19960,4 +19972,4 @@ examples: "500": application/json: {"error": {"code": 500, "message": "Internal Server Error"}} examplesVersion: 1.0.2 -releaseNotes: "## Python SDK Changes:\n* `open_router.batch.create_batches()`: `response.results[].response.body.union(OpenResponsesResult)` **Changed**\n* `open_router.batch.get_batches()`: `response.results[].response.body.union(OpenResponsesResult)` **Changed**\n* `open_router.presets.create_presets_responses()`: \n * `request.input.union(Array<>)[].union(CompactionTriggerItem)` **Added**\n" +releaseNotes: "## Python SDK Changes:\n* `open_router.batch.create_batches()`: `response.results[].response.body.union(OpenResponsesResult)` **Changed**\n* `open_router.batch.get_batches()`: `response.results[].response.body.union(OpenResponsesResult)` **Changed**\n* `open_router.organization.list_members()`: `response.data[].role.enum(org:viewer)` **Added**\n* `open_router.presets.create_presets_chat_completions()`: \n * `request.deferred_tools.profile.enum(universal)` **Added**\n* `open_router.presets.create_presets_messages()`: \n * `request.deferred_tools.profile.enum(universal)` **Added**\n* `open_router.presets.create_presets_responses()`: `request` **Changed**\n" diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index 3dbe76e18..fc03d1109 100644 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -37,7 +37,7 @@ generation: documentation: mintlify preApplyUnionDiscriminators: true python: - version: 1.3.123 + version: 1.3.124 additionalDependencies: dev: pytest: '>=8.3' diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml index 7a15488cf..700ccf02d 100644 --- a/.speakeasy/out.openapi.yaml +++ b/.speakeasy/out.openapi.yaml @@ -8743,6 +8743,8 @@ components: - 'null' cost_details: $ref: '#/components/schemas/CostDetails' + deferred_tools_details: + $ref: '#/components/schemas/DeferredToolsDetails' is_byok: description: 'Whether a request was made using a Bring Your Own Key configuration' type: 'boolean' @@ -11530,10 +11532,12 @@ components: validation: 'runtime' properties: profile: - description: 'Loading profile. Only `portable` is available in this release: OpenRouter serves deferral with router-built search and call wrappers on any model.' + description: 'Loading profile. `portable` serves the `defer_loading` tools with router-built search and call wrappers on any model and keeps the catalog fixed. `universal` defers every wrappable tool behind the same wrappers so the provider-facing tool list never changes, and rebuilds the catalog from each request so tools can be added or removed mid-conversation.' enum: - 'portable' + - 'universal' type: 'string' + x-speakeasy-unknown-values: allow protocol: enum: - 'v1' @@ -11551,6 +11555,34 @@ components: - 'validation' - 'search' type: 'object' + DeferredToolsDetails: + description: 'Totals across every upstream model call of a deferred-tools run. The native usage fields report only the final call; cost covers every call.' + example: + completion_tokens: 180 + prompt_tokens: 2400 + total_tokens: 2580 + turns: 2 + properties: + completion_tokens: + description: 'Completion tokens summed over every upstream call' + type: 'integer' + prompt_tokens: + description: 'Prompt tokens summed over every upstream call' + type: 'integer' + total_tokens: + description: 'Sum of the above two fields' + type: 'integer' + turns: + description: 'Upstream model calls the run made' + exclusiveMinimum: true + minimum: 0 + type: 'integer' + required: + - 'turns' + - 'prompt_tokens' + - 'completion_tokens' + - 'total_tokens' + type: 'object' DeferredToolsSearchStrategy: description: 'Router-local regex/BM25 or caller-owned custom search.' discriminator: @@ -18994,6 +19026,28 @@ components: - 'null' cost_details: $ref: '#/components/schemas/CostDetails' + deferred_tools_details: + properties: + completion_tokens: + description: 'Completion tokens summed over every upstream call' + type: 'integer' + prompt_tokens: + description: 'Prompt tokens summed over every upstream call' + type: 'integer' + total_tokens: + description: 'Sum of the above two fields' + type: 'integer' + turns: + description: 'Upstream model calls the run made' + exclusiveMinimum: true + minimum: 0 + type: 'integer' + required: + - 'turns' + - 'prompt_tokens' + - 'completion_tokens' + - 'total_tokens' + type: 'object' is_byok: type: 'boolean' iterations: @@ -26178,10 +26232,32 @@ components: status: 'completed' type: 'openrouter:tool_search' properties: + arguments: + description: 'The JSON arguments of the model call, verbatim. Replaying the item reuses them.' + example: '{"query":"weather tools"}' + type: 'string' + call_id: + description: 'The ID of the model call that ran the search. Replaying the item reuses it.' + example: 'call_search_1' + type: 'string' + catalog_index: + description: 'The deferred-tool index the router showed the model with a pre-search, listing tool sources and names. Replaying the item shows the same index.' + example: "Deferred tools, found with tool_search and called with tool_exec:\nSources: mcp__sentry (12)." + type: 'string' error: description: 'The error message when the tool call failed before producing a result. Set together with `status: ''failed''`; absent on a successful call.' example: 'Tool execution failed' type: 'string' + format: + description: 'How the model saw the matches. `compact` means each tool by name, description, and input shape, plus a call example. Replaying the item renders the same result.' + enum: + - 'compact' + example: 'compact' + type: 'string' + hint: + description: 'The guidance the model got when the search matched no tools.' + example: 'No tools matched. Search again with other keywords, or load tools by exact name with "select:Name1,Name2".' + type: 'string' id: type: 'string' matches: @@ -26204,6 +26280,14 @@ components: type: 'string' status: $ref: '#/components/schemas/FailableToolCallStatus' + turn_call_ids: + description: 'The IDs of every tool call in the model response that ran the search, in order. Replaying the item keeps those calls in one turn.' + example: + - 'call_search_1' + - 'call_exec_1' + items: + type: 'string' + type: 'array' type: enum: - 'openrouter:tool_search' @@ -34603,6 +34687,8 @@ components: - 'upstream_inference_input_cost' - 'upstream_inference_output_cost' type: 'object' + deferred_tools_details: + $ref: '#/components/schemas/DeferredToolsDetails' is_byok: description: 'Whether a request was made using a Bring Your Own Key configuration' type: 'boolean' @@ -48349,10 +48435,11 @@ paths: - 'string' - 'null' role: - description: 'Role of the member in the organization' + description: 'Role of the member in the organization. `org:viewer` is coming soon and not yet available. Once launched, it has read-only organization access: it can view organization settings, billing and workspaces but not change them. Workspace roles can still grant write access in specific workspaces.' enum: - 'org:admin' - 'org:member' + - 'org:viewer' example: 'org:member' type: 'string' x-speakeasy-unknown-values: allow diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 048c64809..90f9915e2 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -2,8 +2,8 @@ speakeasyVersion: 1.803.2 sources: OpenRouter API: sourceNamespace: open-router-chat-completions-api - sourceRevisionDigest: sha256:48d683ebca808ecf2a33d82e720da6a0e4c4c8bd9f403e4ae7218eb52a5cc4a5 - sourceBlobDigest: sha256:52a6bbab3c7b34eed54c1028f4467443bc9f24b24181ee7d0ac542caca5ca126 + sourceRevisionDigest: sha256:b0702bea14c14c62d23f2a99482e4f39b9934e5091fe1ad463128671abfb08e1 + sourceBlobDigest: sha256:1497f72360880691a966e318272e68b27d573cc4ed89f0a4a2b1ed692dcf6e25 tags: - latest - 1.0.0 @@ -11,10 +11,10 @@ targets: open-router: source: OpenRouter API sourceNamespace: open-router-chat-completions-api - sourceRevisionDigest: sha256:48d683ebca808ecf2a33d82e720da6a0e4c4c8bd9f403e4ae7218eb52a5cc4a5 - sourceBlobDigest: sha256:52a6bbab3c7b34eed54c1028f4467443bc9f24b24181ee7d0ac542caca5ca126 + sourceRevisionDigest: sha256:b0702bea14c14c62d23f2a99482e4f39b9934e5091fe1ad463128671abfb08e1 + sourceBlobDigest: sha256:1497f72360880691a966e318272e68b27d573cc4ed89f0a4a2b1ed692dcf6e25 codeSamplesNamespace: open-router-python-code-samples - codeSamplesRevisionDigest: sha256:cd248b5bf76d621f943dd3de7dbd3cefab3ad776e174585b02b40bcb222cd89d + codeSamplesRevisionDigest: sha256:1b2625a1c2ec06a271fa89696cd45cbd537cddb04f2d5ccce4a6ab3ac6d24418 workflow: workflowVersion: 1.0.0 speakeasyVersion: 1.803.2 diff --git a/RELEASES.md b/RELEASES.md index 0d41b58c8..0baae3602 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -3999,4 +3999,14 @@ Based on: ### Generated - [python v1.3.123] . ### Releases -- [PyPI v1.3.123] https://pypi.org/project/openrouter/1.3.123 - . \ No newline at end of file +- [PyPI v1.3.123] https://pypi.org/project/openrouter/1.3.123 - . + +## 2026-11-05 01:49:48 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.803.2 (2.950.13) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v1.3.124] . +### Releases +- [PyPI v1.3.124] https://pypi.org/project/openrouter/1.3.124 - . \ No newline at end of file diff --git a/docs/components/chatusage.mdx b/docs/components/chatusage.mdx index 2bb1e3244..2f9b81331 100644 --- a/docs/components/chatusage.mdx +++ b/docs/components/chatusage.mdx @@ -7,14 +7,15 @@ Token usage statistics ## Fields -| Field | Type | Required | Description | Example | -| ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -| `completion_tokens` | *int* | ✔️ | Number of tokens in the completion | | -| `completion_tokens_details` | [OptionalNullable[components.ChatUsageCompletionTokensDetails]](../components/chatusagecompletiontokensdetails.mdx) | ➖ | Detailed completion token usage | | -| `cost` | *OptionalNullable[float]* | ➖ | Cost of the completion | | -| `cost_details` | [OptionalNullable[components.CostDetails]](../components/costdetails.mdx) | ➖ | Breakdown of upstream inference costs | \{
"upstream_inference_completions_cost": 0.0004,
"upstream_inference_cost": null,
"upstream_inference_prompt_cost": 0.0008
} | -| `is_byok` | *Optional[bool]* | ➖ | Whether a request was made using a Bring Your Own Key configuration | | -| `prompt_tokens` | *int* | ✔️ | Number of tokens in the prompt | | -| `prompt_tokens_details` | [OptionalNullable[components.ChatUsagePromptTokensDetails]](../components/chatusageprompttokensdetails.mdx) | ➖ | Detailed prompt token usage | | -| `server_tool_use_details` | [OptionalNullable[components.ServerToolUseDetails]](../components/servertoolusedetails.mdx) | ➖ | Usage for server-side tool execution (e.g., web search) | \{
"tool_calls_executed": 2,
"tool_calls_requested": 2,
"web_search_requests": 2
} | -| `total_tokens` | *int* | ✔️ | Total number of tokens | | \ No newline at end of file +| Field | Type | Required | Description | Example | +| -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| `completion_tokens` | *int* | ✔️ | Number of tokens in the completion | | +| `completion_tokens_details` | [OptionalNullable[components.ChatUsageCompletionTokensDetails]](../components/chatusagecompletiontokensdetails.mdx) | ➖ | Detailed completion token usage | | +| `cost` | *OptionalNullable[float]* | ➖ | Cost of the completion | | +| `cost_details` | [OptionalNullable[components.CostDetails]](../components/costdetails.mdx) | ➖ | Breakdown of upstream inference costs | \{
"upstream_inference_completions_cost": 0.0004,
"upstream_inference_cost": null,
"upstream_inference_prompt_cost": 0.0008
} | +| `deferred_tools_details` | [Optional[components.DeferredToolsDetails]](../components/deferredtoolsdetails.mdx) | ➖ | Totals across every upstream model call of a deferred-tools run. The native usage fields report only the final call; cost covers every call. | \{
"completion_tokens": 180,
"prompt_tokens": 2400,
"total_tokens": 2580,
"turns": 2
} | +| `is_byok` | *Optional[bool]* | ➖ | Whether a request was made using a Bring Your Own Key configuration | | +| `prompt_tokens` | *int* | ✔️ | Number of tokens in the prompt | | +| `prompt_tokens_details` | [OptionalNullable[components.ChatUsagePromptTokensDetails]](../components/chatusageprompttokensdetails.mdx) | ➖ | Detailed prompt token usage | | +| `server_tool_use_details` | [OptionalNullable[components.ServerToolUseDetails]](../components/servertoolusedetails.mdx) | ➖ | Usage for server-side tool execution (e.g., web search) | \{
"tool_calls_executed": 2,
"tool_calls_requested": 2,
"web_search_requests": 2
} | +| `total_tokens` | *int* | ✔️ | Total number of tokens | | \ No newline at end of file diff --git a/docs/components/deferredtoolscontrol.mdx b/docs/components/deferredtoolscontrol.mdx index ebb8bfa59..c226e1a86 100644 --- a/docs/components/deferredtoolscontrol.mdx +++ b/docs/components/deferredtoolscontrol.mdx @@ -7,9 +7,9 @@ Opt-in versioned router-level deferred-tool protocol. Replay assistant reasoning ## Fields -| Field | Type | Required | Description | Example | -| -------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -| `profile` | [components.Profile](../components/profile.mdx) | ✔️ | Loading profile. Only `portable` is available in this release: OpenRouter serves deferral with router-built search and call wrappers on any model. | | -| `protocol` | [components.Protocol](../components/protocol.mdx) | ✔️ | N/A | | -| `search` | [components.DeferredToolsSearchStrategy](../components/deferredtoolssearchstrategy.mdx) | ✔️ | Router-local regex/BM25 or caller-owned custom search. | \{
"max_results": 5,
"type": "bm25"
} | -| `validation` | [components.Validation](../components/validation.mdx) | ✔️ | Where tool-call arguments are checked against the original schema. Only `runtime` (in OpenRouter) is available in this release. | | \ No newline at end of file +| Field | Type | Required | Description | Example | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `profile` | [components.Profile](../components/profile.mdx) | ✔️ | Loading profile. `portable` serves the `defer_loading` tools with router-built search and call wrappers on any model and keeps the catalog fixed. `universal` defers every wrappable tool behind the same wrappers so the provider-facing tool list never changes, and rebuilds the catalog from each request so tools can be added or removed mid-conversation. | | +| `protocol` | [components.Protocol](../components/protocol.mdx) | ✔️ | N/A | | +| `search` | [components.DeferredToolsSearchStrategy](../components/deferredtoolssearchstrategy.mdx) | ✔️ | Router-local regex/BM25 or caller-owned custom search. | \{
"max_results": 5,
"type": "bm25"
} | +| `validation` | [components.Validation](../components/validation.mdx) | ✔️ | Where tool-call arguments are checked against the original schema. Only `runtime` (in OpenRouter) is available in this release. | | \ No newline at end of file diff --git a/docs/components/deferredtoolsdetails.mdx b/docs/components/deferredtoolsdetails.mdx new file mode 100644 index 000000000..2a290bbd3 --- /dev/null +++ b/docs/components/deferredtoolsdetails.mdx @@ -0,0 +1,15 @@ +--- +title: "DeferredToolsDetails" +--- + +Totals across every upstream model call of a deferred-tools run. The native usage fields report only the final call; cost covers every call. + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- | +| `completion_tokens` | *int* | ✔️ | Completion tokens summed over every upstream call | +| `prompt_tokens` | *int* | ✔️ | Prompt tokens summed over every upstream call | +| `total_tokens` | *int* | ✔️ | Sum of the above two fields | +| `turns` | *int* | ✔️ | Upstream model calls the run made | \ No newline at end of file diff --git a/docs/components/outputtoolsearchservertoolitem.mdx b/docs/components/outputtoolsearchservertoolitem.mdx index 29b9d6202..c49ae6e87 100644 --- a/docs/components/outputtoolsearchservertoolitem.mdx +++ b/docs/components/outputtoolsearchservertoolitem.mdx @@ -7,11 +7,17 @@ An openrouter:tool_search server tool output item ## Fields -| Field | Type | Required | Description | Example | -| ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -| `error` | *Optional[str]* | ➖ | The error message when the tool call failed before producing a result. Set together with `status: 'failed'`; absent on a successful call. | Tool execution failed | -| `id` | *Optional[str]* | ➖ | N/A | | -| `matches` | List[[components.Match](../components/match.mdx)] | ➖ | N/A | | -| `query` | *Optional[str]* | ➖ | N/A | | -| `status` | [components.FailableToolCallStatus](../components/failabletoolcallstatus.mdx) | ✔️ | N/A | completed | -| `type` | [components.OutputToolSearchServerToolItemType](../components/outputtoolsearchservertoolitemtype.mdx) | ✔️ | N/A | | \ No newline at end of file +| Field | Type | Required | Description | Example | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `arguments` | *Optional[str]* | ➖ | The JSON arguments of the model call, verbatim. Replaying the item reuses them. | \{"query":"weather tools"} | +| `call_id` | *Optional[str]* | ➖ | The ID of the model call that ran the search. Replaying the item reuses it. | call_search_1 | +| `catalog_index` | *Optional[str]* | ➖ | The deferred-tool index the router showed the model with a pre-search, listing tool sources and names. Replaying the item shows the same index. | Deferred tools, found with tool_search and called with tool_exec:
Sources: mcp__sentry (12). | +| `error` | *Optional[str]* | ➖ | The error message when the tool call failed before producing a result. Set together with `status: 'failed'`; absent on a successful call. | Tool execution failed | +| `format_` | [Optional[components.OutputToolSearchServerToolItemFormat]](../components/outputtoolsearchservertoolitemformat.mdx) | ➖ | How the model saw the matches. `compact` means each tool by name, description, and input shape, plus a call example. Replaying the item renders the same result. | compact | +| `hint` | *Optional[str]* | ➖ | The guidance the model got when the search matched no tools. | No tools matched. Search again with other keywords, or load tools by exact name with "select:Name1,Name2". | +| `id` | *Optional[str]* | ➖ | N/A | | +| `matches` | List[[components.Match](../components/match.mdx)] | ➖ | N/A | | +| `query` | *Optional[str]* | ➖ | N/A | | +| `status` | [components.FailableToolCallStatus](../components/failabletoolcallstatus.mdx) | ✔️ | N/A | completed | +| `turn_call_ids` | List[*str*] | ➖ | The IDs of every tool call in the model response that ran the search, in order. Replaying the item keeps those calls in one turn. | [
"call_search_1",
"call_exec_1"
] | +| `type` | [components.OutputToolSearchServerToolItemType](../components/outputtoolsearchservertoolitemtype.mdx) | ✔️ | N/A | | \ No newline at end of file diff --git a/docs/components/outputtoolsearchservertoolitemformat.mdx b/docs/components/outputtoolsearchservertoolitemformat.mdx new file mode 100644 index 000000000..7d64dcb28 --- /dev/null +++ b/docs/components/outputtoolsearchservertoolitemformat.mdx @@ -0,0 +1,17 @@ +--- +title: "OutputToolSearchServerToolItemFormat" +--- + +How the model saw the matches. `compact` means each tool by name, description, and input shape, plus a call example. Replaying the item renders the same result. + +## Example Usage + +```python +from openrouter.components import OutputToolSearchServerToolItemFormat +value: OutputToolSearchServerToolItemFormat = "compact" +``` + + +## Values + +- `"compact"` diff --git a/docs/components/profile.mdx b/docs/components/profile.mdx index b59688b7b..f9eb1da62 100644 --- a/docs/components/profile.mdx +++ b/docs/components/profile.mdx @@ -2,16 +2,21 @@ title: "Profile" --- -Loading profile. Only `portable` is available in this release: OpenRouter serves deferral with router-built search and call wrappers on any model. +Loading profile. `portable` serves the `defer_loading` tools with router-built search and call wrappers on any model and keeps the catalog fixed. `universal` defers every wrappable tool behind the same wrappers so the provider-facing tool list never changes, and rebuilds the catalog from each request so tools can be added or removed mid-conversation. ## Example Usage ```python from openrouter.components import Profile + +# Open enum: unrecognized values are captured as UnrecognizedStr value: Profile = "portable" ``` ## Values +This is an open enum. Unrecognized values will not fail type checks. + - `"portable"` +- `"universal"` diff --git a/docs/components/usage.mdx b/docs/components/usage.mdx index 10680b424..f70fe4842 100644 --- a/docs/components/usage.mdx +++ b/docs/components/usage.mdx @@ -4,14 +4,15 @@ title: "Usage" ## Fields -| Field | Type | Required | Description | Example | -| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | -| `input_tokens` | *int* | ✔️ | N/A | | -| `input_tokens_details` | [components.InputTokensDetails](../components/inputtokensdetails.mdx) | ✔️ | N/A | | -| `output_tokens` | *int* | ✔️ | N/A | | -| `output_tokens_details` | [components.OutputTokensDetails](../components/outputtokensdetails.mdx) | ✔️ | N/A | | -| `total_tokens` | *int* | ✔️ | N/A | | -| `cost` | *OptionalNullable[float]* | ➖ | Cost of the completion | | -| `cost_details` | [Optional[components.UsageCostDetails]](../components/usagecostdetails.mdx) | ➖ | N/A | | -| `is_byok` | *Optional[bool]* | ➖ | Whether a request was made using a Bring Your Own Key configuration | | -| `server_tool_use_details` | [OptionalNullable[components.ServerToolUseDetails]](../components/servertoolusedetails.mdx) | ➖ | Usage for server-side tool execution (e.g., web search) | \{
"tool_calls_executed": 2,
"tool_calls_requested": 2,
"web_search_requests": 2
} | \ No newline at end of file +| Field | Type | Required | Description | Example | +| -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| `input_tokens` | *int* | ✔️ | N/A | | +| `input_tokens_details` | [components.InputTokensDetails](../components/inputtokensdetails.mdx) | ✔️ | N/A | | +| `output_tokens` | *int* | ✔️ | N/A | | +| `output_tokens_details` | [components.OutputTokensDetails](../components/outputtokensdetails.mdx) | ✔️ | N/A | | +| `total_tokens` | *int* | ✔️ | N/A | | +| `cost` | *OptionalNullable[float]* | ➖ | Cost of the completion | | +| `cost_details` | [Optional[components.UsageCostDetails]](../components/usagecostdetails.mdx) | ➖ | N/A | | +| `deferred_tools_details` | [Optional[components.DeferredToolsDetails]](../components/deferredtoolsdetails.mdx) | ➖ | Totals across every upstream model call of a deferred-tools run. The native usage fields report only the final call; cost covers every call. | \{
"completion_tokens": 180,
"prompt_tokens": 2400,
"total_tokens": 2580,
"turns": 2
} | +| `is_byok` | *Optional[bool]* | ➖ | Whether a request was made using a Bring Your Own Key configuration | | +| `server_tool_use_details` | [OptionalNullable[components.ServerToolUseDetails]](../components/servertoolusedetails.mdx) | ➖ | Usage for server-side tool execution (e.g., web search) | \{
"tool_calls_executed": 2,
"tool_calls_requested": 2,
"web_search_requests": 2
} | \ No newline at end of file diff --git a/docs/operations/listorganizationmembersdata.mdx b/docs/operations/listorganizationmembersdata.mdx index fc485e857..f65b92ed5 100644 --- a/docs/operations/listorganizationmembersdata.mdx +++ b/docs/operations/listorganizationmembersdata.mdx @@ -4,10 +4,10 @@ title: "ListOrganizationMembersData" ## Fields -| Field | Type | Required | Description | Example | -| ---------------------------------------- | ---------------------------------------- | ---------------------------------------- | ---------------------------------------- | ---------------------------------------- | -| `email` | *str* | ✔️ | Email address of the member | jane.doe@example.com | -| `first_name` | *Nullable[str]* | ✔️ | First name of the member | Jane | -| `id` | *str* | ✔️ | User ID of the organization member | user_2dHFtVWx2n56w6HkM0000000000 | -| `last_name` | *Nullable[str]* | ✔️ | Last name of the member | Doe | -| `role` | [operations.Role](../operations/role.mdx) | ✔️ | Role of the member in the organization | org:member | \ No newline at end of file +| Field | Type | Required | Description | Example | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `email` | *str* | ✔️ | Email address of the member | jane.doe@example.com | +| `first_name` | *Nullable[str]* | ✔️ | First name of the member | Jane | +| `id` | *str* | ✔️ | User ID of the organization member | user_2dHFtVWx2n56w6HkM0000000000 | +| `last_name` | *Nullable[str]* | ✔️ | Last name of the member | Doe | +| `role` | [operations.Role](../operations/role.mdx) | ✔️ | Role of the member in the organization. `org:viewer` is coming soon and not yet available. Once launched, it has read-only organization access: it can view organization settings, billing and workspaces but not change them. Workspace roles can still grant write access in specific workspaces. | org:member | \ No newline at end of file diff --git a/docs/operations/role.mdx b/docs/operations/role.mdx index 9e1219b8c..533bb7464 100644 --- a/docs/operations/role.mdx +++ b/docs/operations/role.mdx @@ -2,7 +2,7 @@ title: "Role" --- -Role of the member in the organization +Role of the member in the organization. `org:viewer` is coming soon and not yet available. Once launched, it has read-only organization access: it can view organization settings, billing and workspaces but not change them. Workspace roles can still grant write access in specific workspaces. ## Example Usage @@ -20,3 +20,4 @@ This is an open enum. Unrecognized values will not fail type checks. - `"org:admin"` - `"org:member"` +- `"org:viewer"` diff --git a/pyproject.toml b/pyproject.toml index a66006a71..a33e8a445 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openrouter" -version = "1.3.123" +version = "1.3.124" description = "Official Python Client SDK for OpenRouter." authors = [{ name = "OpenRouter" },] readme = "README-PYPI.md" diff --git a/src/openrouter/_version.py b/src/openrouter/_version.py index 7250656ff..b01419c49 100644 --- a/src/openrouter/_version.py +++ b/src/openrouter/_version.py @@ -3,10 +3,10 @@ import importlib.metadata __title__: str = "openrouter" -__version__: str = "1.3.123" +__version__: str = "1.3.124" __openapi_doc_version__: str = "1.0.0" __gen_version__: str = "2.950.13" -__user_agent__: str = "speakeasy-sdk/python 1.3.123 2.950.13 1.0.0 openrouter" +__user_agent__: str = "speakeasy-sdk/python 1.3.124 2.950.13 1.0.0 openrouter" try: if __package__ is not None: diff --git a/src/openrouter/components/__init__.py b/src/openrouter/components/__init__.py index 212a3d7b1..94487b283 100644 --- a/src/openrouter/components/__init__.py +++ b/src/openrouter/components/__init__.py @@ -1755,6 +1755,10 @@ Protocol, Validation, ) + from .deferredtoolsdetails import ( + DeferredToolsDetails, + DeferredToolsDetailsTypedDict, + ) from .deferredtoolssearchstrategy import ( DeferredToolsSearchStrategy, DeferredToolsSearchStrategyTypedDict, @@ -3613,6 +3617,7 @@ Match, MatchTypedDict, OutputToolSearchServerToolItem, + OutputToolSearchServerToolItemFormat, OutputToolSearchServerToolItemType, OutputToolSearchServerToolItemTypedDict, ) @@ -5927,6 +5932,8 @@ "DeferredRegexSearchTypedDict", "DeferredToolsControl", "DeferredToolsControlTypedDict", + "DeferredToolsDetails", + "DeferredToolsDetailsTypedDict", "DeferredToolsSearchStrategy", "DeferredToolsSearchStrategyTypedDict", "DeleteBYOKKeyResponse", @@ -7254,6 +7261,7 @@ "OutputToolSearchCallItemType", "OutputToolSearchCallItemTypedDict", "OutputToolSearchServerToolItem", + "OutputToolSearchServerToolItemFormat", "OutputToolSearchServerToolItemType", "OutputToolSearchServerToolItemTypedDict", "OutputWebFetchServerToolItem", @@ -9486,6 +9494,8 @@ "Profile": ".deferredtoolscontrol", "Protocol": ".deferredtoolscontrol", "Validation": ".deferredtoolscontrol", + "DeferredToolsDetails": ".deferredtoolsdetails", + "DeferredToolsDetailsTypedDict": ".deferredtoolsdetails", "DeferredToolsSearchStrategy": ".deferredtoolssearchstrategy", "DeferredToolsSearchStrategyTypedDict": ".deferredtoolssearchstrategy", "DeleteBYOKKeyResponse": ".deletebyokkeyresponse", @@ -10914,6 +10924,7 @@ "Match": ".outputtoolsearchservertoolitem", "MatchTypedDict": ".outputtoolsearchservertoolitem", "OutputToolSearchServerToolItem": ".outputtoolsearchservertoolitem", + "OutputToolSearchServerToolItemFormat": ".outputtoolsearchservertoolitem", "OutputToolSearchServerToolItemType": ".outputtoolsearchservertoolitem", "OutputToolSearchServerToolItemTypedDict": ".outputtoolsearchservertoolitem", "OutputWebFetchServerToolItem": ".outputwebfetchservertoolitem", diff --git a/src/openrouter/components/chatusage.py b/src/openrouter/components/chatusage.py index 4fd2be35d..9df54c786 100644 --- a/src/openrouter/components/chatusage.py +++ b/src/openrouter/components/chatusage.py @@ -2,6 +2,7 @@ from __future__ import annotations from .costdetails import CostDetails, CostDetailsTypedDict +from .deferredtoolsdetails import DeferredToolsDetails, DeferredToolsDetailsTypedDict from .servertoolusedetails import ServerToolUseDetails, ServerToolUseDetailsTypedDict from openrouter.types import ( BaseModel, @@ -147,6 +148,8 @@ class ChatUsageTypedDict(TypedDict): r"""Cost of the completion""" cost_details: NotRequired[Nullable[CostDetailsTypedDict]] r"""Breakdown of upstream inference costs""" + deferred_tools_details: NotRequired[DeferredToolsDetailsTypedDict] + r"""Totals across every upstream model call of a deferred-tools run. The native usage fields report only the final call; cost covers every call.""" is_byok: NotRequired[bool] r"""Whether a request was made using a Bring Your Own Key configuration""" prompt_tokens_details: NotRequired[Nullable[ChatUsagePromptTokensDetailsTypedDict]] @@ -178,6 +181,9 @@ class ChatUsage(BaseModel): cost_details: OptionalNullable[CostDetails] = UNSET r"""Breakdown of upstream inference costs""" + deferred_tools_details: Optional[DeferredToolsDetails] = None + r"""Totals across every upstream model call of a deferred-tools run. The native usage fields report only the final call; cost covers every call.""" + is_byok: Optional[bool] = None r"""Whether a request was made using a Bring Your Own Key configuration""" @@ -194,6 +200,7 @@ def serialize_model(self, handler): "completion_tokens_details", "cost", "cost_details", + "deferred_tools_details", "is_byok", "prompt_tokens_details", "server_tool_use_details", diff --git a/src/openrouter/components/deferredtoolscontrol.py b/src/openrouter/components/deferredtoolscontrol.py index 53c2c2774..cef37bad7 100644 --- a/src/openrouter/components/deferredtoolscontrol.py +++ b/src/openrouter/components/deferredtoolscontrol.py @@ -5,13 +5,19 @@ DeferredToolsSearchStrategy, DeferredToolsSearchStrategyTypedDict, ) -from openrouter.types import BaseModel -from typing import Literal +from openrouter.types import BaseModel, UnrecognizedStr +from typing import Literal, Union from typing_extensions import TypedDict -Profile = Literal["portable",] -r"""Loading profile. Only `portable` is available in this release: OpenRouter serves deferral with router-built search and call wrappers on any model.""" +Profile = Union[ + Literal[ + "portable", + "universal", + ], + UnrecognizedStr, +] +r"""Loading profile. `portable` serves the `defer_loading` tools with router-built search and call wrappers on any model and keeps the catalog fixed. `universal` defers every wrappable tool behind the same wrappers so the provider-facing tool list never changes, and rebuilds the catalog from each request so tools can be added or removed mid-conversation.""" Protocol = Literal["v1",] @@ -25,7 +31,7 @@ class DeferredToolsControlTypedDict(TypedDict): r"""Opt-in versioned router-level deferred-tool protocol. Replay assistant reasoning unchanged on continuation; keep the catalog unchanged.""" profile: Profile - r"""Loading profile. Only `portable` is available in this release: OpenRouter serves deferral with router-built search and call wrappers on any model.""" + r"""Loading profile. `portable` serves the `defer_loading` tools with router-built search and call wrappers on any model and keeps the catalog fixed. `universal` defers every wrappable tool behind the same wrappers so the provider-facing tool list never changes, and rebuilds the catalog from each request so tools can be added or removed mid-conversation.""" protocol: Protocol search: DeferredToolsSearchStrategyTypedDict r"""Router-local regex/BM25 or caller-owned custom search.""" @@ -37,7 +43,7 @@ class DeferredToolsControl(BaseModel): r"""Opt-in versioned router-level deferred-tool protocol. Replay assistant reasoning unchanged on continuation; keep the catalog unchanged.""" profile: Profile - r"""Loading profile. Only `portable` is available in this release: OpenRouter serves deferral with router-built search and call wrappers on any model.""" + r"""Loading profile. `portable` serves the `defer_loading` tools with router-built search and call wrappers on any model and keeps the catalog fixed. `universal` defers every wrappable tool behind the same wrappers so the provider-facing tool list never changes, and rebuilds the catalog from each request so tools can be added or removed mid-conversation.""" protocol: Protocol diff --git a/src/openrouter/components/deferredtoolsdetails.py b/src/openrouter/components/deferredtoolsdetails.py new file mode 100644 index 000000000..1cc2be0d1 --- /dev/null +++ b/src/openrouter/components/deferredtoolsdetails.py @@ -0,0 +1,34 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from openrouter.types import BaseModel +from typing_extensions import TypedDict + + +class DeferredToolsDetailsTypedDict(TypedDict): + r"""Totals across every upstream model call of a deferred-tools run. The native usage fields report only the final call; cost covers every call.""" + + completion_tokens: int + r"""Completion tokens summed over every upstream call""" + prompt_tokens: int + r"""Prompt tokens summed over every upstream call""" + total_tokens: int + r"""Sum of the above two fields""" + turns: int + r"""Upstream model calls the run made""" + + +class DeferredToolsDetails(BaseModel): + r"""Totals across every upstream model call of a deferred-tools run. The native usage fields report only the final call; cost covers every call.""" + + completion_tokens: int + r"""Completion tokens summed over every upstream call""" + + prompt_tokens: int + r"""Prompt tokens summed over every upstream call""" + + total_tokens: int + r"""Sum of the above two fields""" + + turns: int + r"""Upstream model calls the run made""" diff --git a/src/openrouter/components/inputs_union.py b/src/openrouter/components/inputs_union.py index a2efac9ee..bea147ee6 100644 --- a/src/openrouter/components/inputs_union.py +++ b/src/openrouter/components/inputs_union.py @@ -414,26 +414,26 @@ def serialize_model(self, handler): ToolSearchOutputItemTypedDict, ToolSearchCallItemTypedDict, InputsMessageTypedDict, - OutputToolSearchServerToolItemTypedDict, OutputComputerCallItemTypedDict, AgentMessageItemTypedDict, OutputCodeInterpreterCallItemTypedDict, - ShellCallItemTypedDict, McpCallItemTypedDict, + ShellCallItemTypedDict, ReasoningItemTypedDict, - OutputWebFetchServerToolItemTypedDict, - OutputAdvisorServerToolItemTypedDict, InputsReasoningTypedDict, - CustomToolCallItemTypedDict, + OutputAdvisorServerToolItemTypedDict, OutputCodeInterpreterServerToolItemTypedDict, + OutputWebFetchServerToolItemTypedDict, + CustomToolCallItemTypedDict, + OutputImageGenerationServerToolItemTypedDict, OutputArmorBlockedItemTypedDict, ShellCallOutputItemTypedDict, - OutputImageGenerationServerToolItemTypedDict, OutputFusionServerToolItemTypedDict, OutputShellServerToolItemTypedDict, OutputFilesServerToolItemTypedDict, FunctionCallItemTypedDict, OutputSubagentServerToolItemTypedDict, + OutputToolSearchServerToolItemTypedDict, OutputBashServerToolItemTypedDict, ], ) @@ -474,26 +474,26 @@ def serialize_model(self, handler): ToolSearchOutputItem, ToolSearchCallItem, InputsMessage, - OutputToolSearchServerToolItem, OutputComputerCallItem, AgentMessageItem, OutputCodeInterpreterCallItem, - ShellCallItem, McpCallItem, + ShellCallItem, ReasoningItem, - OutputWebFetchServerToolItem, - OutputAdvisorServerToolItem, InputsReasoning, - CustomToolCallItem, + OutputAdvisorServerToolItem, OutputCodeInterpreterServerToolItem, + OutputWebFetchServerToolItem, + CustomToolCallItem, + OutputImageGenerationServerToolItem, OutputArmorBlockedItem, ShellCallOutputItem, - OutputImageGenerationServerToolItem, OutputFusionServerToolItem, OutputShellServerToolItem, OutputFilesServerToolItem, FunctionCallItem, OutputSubagentServerToolItem, + OutputToolSearchServerToolItem, OutputBashServerToolItem, ], ) diff --git a/src/openrouter/components/openresponsesresult.py b/src/openrouter/components/openresponsesresult.py index 703b72543..d5ffb6009 100644 --- a/src/openrouter/components/openresponsesresult.py +++ b/src/openrouter/components/openresponsesresult.py @@ -14,6 +14,7 @@ from .codexlocalshelltool import CodexLocalShellTool, CodexLocalShellToolTypedDict from .computeruseservertool import ComputerUseServerTool, ComputerUseServerToolTypedDict from .customtool import CustomTool, CustomToolTypedDict +from .deferredtoolsdetails import DeferredToolsDetails, DeferredToolsDetailsTypedDict from .filesearchservertool import FileSearchServerTool, FileSearchServerToolTypedDict from .imagegenerationservertool import ( ImageGenerationServerTool, @@ -339,6 +340,8 @@ class UsageTypedDict(TypedDict): cost: NotRequired[Nullable[float]] r"""Cost of the completion""" cost_details: NotRequired[UsageCostDetailsTypedDict] + deferred_tools_details: NotRequired[DeferredToolsDetailsTypedDict] + r"""Totals across every upstream model call of a deferred-tools run. The native usage fields report only the final call; cost covers every call.""" is_byok: NotRequired[bool] r"""Whether a request was made using a Bring Your Own Key configuration""" server_tool_use_details: NotRequired[Nullable[ServerToolUseDetailsTypedDict]] @@ -361,6 +364,9 @@ class Usage(BaseModel): cost_details: Optional[UsageCostDetails] = None + deferred_tools_details: Optional[DeferredToolsDetails] = None + r"""Totals across every upstream model call of a deferred-tools run. The native usage fields report only the final call; cost covers every call.""" + is_byok: Optional[bool] = None r"""Whether a request was made using a Bring Your Own Key configuration""" @@ -370,7 +376,13 @@ class Usage(BaseModel): @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = set( - ["cost", "cost_details", "is_byok", "server_tool_use_details"] + [ + "cost", + "cost_details", + "deferred_tools_details", + "is_byok", + "server_tool_use_details", + ] ) nullable_fields = set(["cost", "server_tool_use_details"]) serialized = handler(self) diff --git a/src/openrouter/components/outputitems.py b/src/openrouter/components/outputitems.py index 53f3d7f01..c4933ca3b 100644 --- a/src/openrouter/components/outputitems.py +++ b/src/openrouter/components/outputitems.py @@ -151,23 +151,23 @@ OutputMemoryServerToolItemTypedDict, OutputComputerCallItemTypedDict, OutputMessageItemTypedDict, - OutputToolSearchServerToolItemTypedDict, OutputShellCallItemTypedDict, OutputCodeInterpreterCallItemTypedDict, - OutputReasoningItemTypedDict, + OutputCodeInterpreterServerToolItemTypedDict, OutputCustomToolCallItemTypedDict, OutputWebFetchServerToolItemTypedDict, - OutputCodeInterpreterServerToolItemTypedDict, + OutputReasoningItemTypedDict, OutputAdvisorServerToolItemTypedDict, - OutputShellCallOutputItemTypedDict, OutputArmorBlockedItemTypedDict, OutputImageGenerationServerToolItemTypedDict, + OutputShellCallOutputItemTypedDict, OutputFusionServerToolItemTypedDict, - OutputFilesServerToolItemTypedDict, OutputShellServerToolItemTypedDict, OutputFunctionCallItemTypedDict, + OutputFilesServerToolItemTypedDict, OutputSubagentServerToolItemTypedDict, OutputBashServerToolItemTypedDict, + OutputToolSearchServerToolItemTypedDict, ], ) r"""An output item from the response""" diff --git a/src/openrouter/components/outputtoolsearchservertoolitem.py b/src/openrouter/components/outputtoolsearchservertoolitem.py index 69f1f522d..b1cd35a55 100644 --- a/src/openrouter/components/outputtoolsearchservertoolitem.py +++ b/src/openrouter/components/outputtoolsearchservertoolitem.py @@ -3,9 +3,14 @@ from __future__ import annotations from .failabletoolcallstatus import FailableToolCallStatus from openrouter.types import BaseModel, UNSET_SENTINEL +import pydantic from pydantic import model_serializer from typing import Any, Dict, List, Literal, Optional -from typing_extensions import NotRequired, TypedDict +from typing_extensions import Annotated, NotRequired, TypedDict + + +OutputToolSearchServerToolItemFormat = Literal["compact",] +r"""How the model saw the matches. `compact` means each tool by name, description, and input shape, plus a call example. Replaying the item renders the same result.""" class MatchTypedDict(TypedDict): @@ -30,11 +35,23 @@ class OutputToolSearchServerToolItemTypedDict(TypedDict): status: FailableToolCallStatus type: OutputToolSearchServerToolItemType + arguments: NotRequired[str] + r"""The JSON arguments of the model call, verbatim. Replaying the item reuses them.""" + call_id: NotRequired[str] + r"""The ID of the model call that ran the search. Replaying the item reuses it.""" + catalog_index: NotRequired[str] + r"""The deferred-tool index the router showed the model with a pre-search, listing tool sources and names. Replaying the item shows the same index.""" error: NotRequired[str] r"""The error message when the tool call failed before producing a result. Set together with `status: 'failed'`; absent on a successful call.""" + format_: NotRequired[OutputToolSearchServerToolItemFormat] + r"""How the model saw the matches. `compact` means each tool by name, description, and input shape, plus a call example. Replaying the item renders the same result.""" + hint: NotRequired[str] + r"""The guidance the model got when the search matched no tools.""" id: NotRequired[str] matches: NotRequired[List[MatchTypedDict]] query: NotRequired[str] + turn_call_ids: NotRequired[List[str]] + r"""The IDs of every tool call in the model response that ran the search, in order. Replaying the item keeps those calls in one turn.""" class OutputToolSearchServerToolItem(BaseModel): @@ -44,18 +61,51 @@ class OutputToolSearchServerToolItem(BaseModel): type: OutputToolSearchServerToolItemType + arguments: Optional[str] = None + r"""The JSON arguments of the model call, verbatim. Replaying the item reuses them.""" + + call_id: Optional[str] = None + r"""The ID of the model call that ran the search. Replaying the item reuses it.""" + + catalog_index: Optional[str] = None + r"""The deferred-tool index the router showed the model with a pre-search, listing tool sources and names. Replaying the item shows the same index.""" + error: Optional[str] = None r"""The error message when the tool call failed before producing a result. Set together with `status: 'failed'`; absent on a successful call.""" + format_: Annotated[ + Optional[OutputToolSearchServerToolItemFormat], pydantic.Field(alias="format") + ] = None + r"""How the model saw the matches. `compact` means each tool by name, description, and input shape, plus a call example. Replaying the item renders the same result.""" + + hint: Optional[str] = None + r"""The guidance the model got when the search matched no tools.""" + id: Optional[str] = None matches: Optional[List[Match]] = None query: Optional[str] = None + turn_call_ids: Optional[List[str]] = None + r"""The IDs of every tool call in the model response that ran the search, in order. Replaying the item keeps those calls in one turn.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["error", "id", "matches", "query"]) + optional_fields = set( + [ + "arguments", + "call_id", + "catalog_index", + "error", + "format", + "hint", + "id", + "matches", + "query", + "turn_call_ids", + ] + ) serialized = handler(self) m = {} @@ -68,3 +118,9 @@ def serialize_model(self, handler): m[k] = val return m + + +try: + OutputToolSearchServerToolItem.model_rebuild() +except NameError: + pass diff --git a/src/openrouter/operations/listorganizationmembers.py b/src/openrouter/operations/listorganizationmembers.py index f8ab3cfb4..bab4420d7 100644 --- a/src/openrouter/operations/listorganizationmembers.py +++ b/src/openrouter/operations/listorganizationmembers.py @@ -178,10 +178,11 @@ def serialize_model(self, handler): Literal[ "org:admin", "org:member", + "org:viewer", ], UnrecognizedStr, ] -r"""Role of the member in the organization""" +r"""Role of the member in the organization. `org:viewer` is coming soon and not yet available. Once launched, it has read-only organization access: it can view organization settings, billing and workspaces but not change them. Workspace roles can still grant write access in specific workspaces.""" class ListOrganizationMembersDataTypedDict(TypedDict): @@ -194,7 +195,7 @@ class ListOrganizationMembersDataTypedDict(TypedDict): last_name: Nullable[str] r"""Last name of the member""" role: Role - r"""Role of the member in the organization""" + r"""Role of the member in the organization. `org:viewer` is coming soon and not yet available. Once launched, it has read-only organization access: it can view organization settings, billing and workspaces but not change them. Workspace roles can still grant write access in specific workspaces.""" class ListOrganizationMembersData(BaseModel): @@ -211,7 +212,7 @@ class ListOrganizationMembersData(BaseModel): r"""Last name of the member""" role: Role - r"""Role of the member in the organization""" + r"""Role of the member in the organization. `org:viewer` is coming soon and not yet available. Once launched, it has read-only organization access: it can view organization settings, billing and workspaces but not change them. Workspace roles can still grant write access in specific workspaces.""" @model_serializer(mode="wrap") def serialize_model(self, handler): diff --git a/uv.lock b/uv.lock index 1d11bc98e..7c1423543 100644 --- a/uv.lock +++ b/uv.lock @@ -231,7 +231,7 @@ wheels = [ [[package]] name = "openrouter" -version = "1.3.123" +version = "1.3.124" source = { editable = "." } dependencies = [ { name = "httpcore" }, From b021d785d43c87d010b862f49e3f7bfc6d780097 Mon Sep 17 00:00:00 2001 From: "speakeasy-github[bot]" <128539517+speakeasy-github[bot]@users.noreply.github.com> Date: Thu, 5 Nov 2026 01:52:56 +0000 Subject: [PATCH 2/2] empty commit to trigger [run-tests] workflow