From 4f2dacff75f19c2e167b52d340c57650364c66e1 Mon Sep 17 00:00:00 2001 From: speakeasybot Date: Fri, 25 Sep 2026 19:41:53 +0000 Subject: [PATCH 1/2] ## Python SDK Changes: * `open_router.tts.create_speech()`: * `request.input_references[]` **Changed** * `open_router.endpoints.list_zdr_endpoints()`: `response.data[]` **Changed** * `open_router.endpoints.list()`: `response.data.endpoints[]` **Changed** --- .speakeasy/gen.lock | 108 ++++++++++-------- .speakeasy/gen.yaml | 2 +- .speakeasy/out.openapi.yaml | 63 ++++++++-- .speakeasy/workflow.lock | 10 +- RELEASES.md | 12 +- docs/components/publicendpoint.mdx | 2 + docs/components/speechinputreference.mdx | 8 +- docs/components/speechinputreferenceaudio.mdx | 2 +- .../speechinputreferenceaudioinput.mdx | 9 +- docs/components/speechinputreferenceimage.mdx | 13 +++ .../speechinputreferenceimageinput.mdx | 12 ++ .../speechinputreferenceimagetype.mdx | 15 +++ docs/components/speechinputreferencetext.mdx | 10 +- docs/components/speechrequest.mdx | 24 ++-- docs/sdks/tts/README.mdx | 32 +++--- pyproject.toml | 2 +- src/openrouter/_version.py | 4 +- src/openrouter/components/__init__.py | 19 +++ src/openrouter/components/publicendpoint.py | 18 ++- .../components/speechinputreference.py | 15 ++- .../components/speechinputreferenceaudio.py | 4 +- .../speechinputreferenceaudioinput.py | 15 ++- .../components/speechinputreferenceimage.py | 30 +++++ .../speechinputreferenceimageinput.py | 19 +++ .../components/speechinputreferencetext.py | 8 +- src/openrouter/components/speechrequest.py | 4 +- src/openrouter/tts.py | 4 +- uv.lock | 2 +- 28 files changed, 345 insertions(+), 121 deletions(-) create mode 100644 docs/components/speechinputreferenceimage.mdx create mode 100644 docs/components/speechinputreferenceimageinput.mdx create mode 100644 docs/components/speechinputreferenceimagetype.mdx create mode 100644 src/openrouter/components/speechinputreferenceimage.py create mode 100644 src/openrouter/components/speechinputreferenceimageinput.py diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 8319c3bf..e6a97b36 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: 7dee79d06858c3877d9e3d05e5614cde + docChecksum: aaa7d4a75666f6d910431ccff64692b5 docVersion: 1.0.0 speakeasyVersion: 1.787.0 generationVersion: 2.914.0 - releaseVersion: 1.2.27 - configChecksum: 4a0681d5fa9d5dff4c80dfd7c16e3caf + releaseVersion: 1.2.28 + configChecksum: 79af06c5b64804f84ca14bbeb1a2b789 repoURL: https://github.com/OpenRouterTeam/python-sdk.git installationURL: https://github.com/OpenRouterTeam/python-sdk.git published: true persistentEdits: - generation_id: 7787c28d-aa9e-440e-948a-98b6c018b499 - pristine_commit_hash: 0bcff2f200e5921ae70581dd4cbd597c609b8c97 - pristine_tree_hash: f255f10672de49b394769fcd4e0b3a01ba82c6d5 + generation_id: c2e564a7-f9f9-4620-b18c-32f209645c9b + pristine_commit_hash: 4994453781c2d4211c9d4aa1c668ff05ae6fda99 + pristine_tree_hash: ab24309cad6866631f246b0bd6ee01d6c62020e8 features: python: acceptHeaders: 3.0.0 @@ -4919,8 +4919,8 @@ trackedFiles: pristine_git_object: be1e5af9301ba917704f25fdafed31c152485abf docs/components/publicendpoint.mdx: id: ec4843ef5d86 - last_write_checksum: sha1:23aab4f17e54311ce27a585548fef94c997def7c - pristine_git_object: 78fc661608b214ddacd52d640660ea7e27cf3c73 + last_write_checksum: sha1:54822f1b82fe3c0d91cf214773a1b52a6e7cf3a3 + pristine_git_object: fc7a3507a210a8409cfe9d528972e8d4b68b67a1 docs/components/publicpricing.mdx: id: 61fb18b7ff94 last_write_checksum: sha1:e241420249fcbd1bf515b0f5e84934de0b207948 @@ -5407,32 +5407,44 @@ trackedFiles: pristine_git_object: 5d617cac37f7b364f4dd0640246e97c34351d824 docs/components/speechinputreference.mdx: id: eb5af16936c7 - last_write_checksum: sha1:7c6f3859c9f24efd0787a34f951d85fbe71eac29 - pristine_git_object: 79204829325eb4f74a711c7edc1c782b8df12aaa + last_write_checksum: sha1:ab545b03da2161ae1ad449714b6861cd55ae66df + pristine_git_object: 7303b4f78166679c086effde5fd5b6ab875d580d docs/components/speechinputreferenceaudio.mdx: id: be120390be39 - last_write_checksum: sha1:2bade388b0b8cb5458c4f1bf0f790fdca724c0ec - pristine_git_object: c69013daa1490e363dbbd66ee5a849eb946e7325 + last_write_checksum: sha1:4abc3f8a18880605e3802670e48d114cde250070 + pristine_git_object: f00281d13b6d61ad5496ebdcb3ec34dcc834a9d0 docs/components/speechinputreferenceaudioinput.mdx: id: 5fc8d05d280c - last_write_checksum: sha1:c28160bb5c9a47d9b95fccf3e834e5705b863a14 - pristine_git_object: fa10a1fbb2b79c1f46da48595119d9a5ed8f9e1e + last_write_checksum: sha1:046a2f438968786be605f7b37dd85d3e6d069a6f + pristine_git_object: c16ea82c8c24655bba86bd9c8de13f91e79a9c3e docs/components/speechinputreferenceaudiotype.mdx: id: 058d6a67e101 last_write_checksum: sha1:4af157ebbeebbfa18cc110c3ac32f8ff78a69ce2 pristine_git_object: 99478c90d4d43c6e23cbe275f97998502c2378ae + docs/components/speechinputreferenceimage.mdx: + id: 8e77f64c57a8 + last_write_checksum: sha1:586ef478d847509339873a7e5bbc7134d38f1b36 + pristine_git_object: 068290f70f3496c0a6a3b030ce6f5cb384550fb9 + docs/components/speechinputreferenceimageinput.mdx: + id: 04884f13e007 + last_write_checksum: sha1:fb6443433e5735e00e7264c3dfee8389af295339 + pristine_git_object: 127f005a602cda6872f4ce9aed15e1d032024e6b + docs/components/speechinputreferenceimagetype.mdx: + id: b9da823bf7a8 + last_write_checksum: sha1:500c0d9827d91ed7591910328db819e3549ee970 + pristine_git_object: b40df3d3d04538e5328895c3d02481db6b273261 docs/components/speechinputreferencetext.mdx: id: c16449cda36e - last_write_checksum: sha1:b5099e4b7f20460e2dd9609e998491841305a9fb - pristine_git_object: ff25c4928b7e6ecaeaee0a23255f3b001219de85 + last_write_checksum: sha1:ed437a992026eb4169008b59ade634dcc41e765d + pristine_git_object: af437e9f376058bc571531b1d3019d06d2d62863 docs/components/speechinputreferencetexttype.mdx: id: 469b6fa8fe52 last_write_checksum: sha1:47783070359618513e2d6c3b963e507cf1320b70 pristine_git_object: 34f4f07fb3008df83646fa3d88ce04009274246a docs/components/speechrequest.mdx: id: 06e81b0433f6 - last_write_checksum: sha1:5076534e37775a644db8326988169e8315cd4298 - pristine_git_object: a9c5cb0175063b4abd1ca036420a20c527f7ae22 + last_write_checksum: sha1:9750d04360830c6aa909c67c8278a2d76e5c78cc + pristine_git_object: 2c86114409b77d9cd1f7d32ca8bfe505da0a0226 docs/components/speechrequestprovider.mdx: id: 4f78ed0394c4 last_write_checksum: sha1:99d94c6b01dbd3e875c213584f97c7dca545a6a9 @@ -8235,8 +8247,8 @@ trackedFiles: pristine_git_object: fc7688ebea8e973bebc0525a820ba246b6491f81 docs/sdks/tts/README.mdx: id: cd1132543884 - last_write_checksum: sha1:37918eb124f9ae0234e8047be7ec07a955458cbc - pristine_git_object: bc53071afea2d5c822b7d8bea60e486d72447e1c + last_write_checksum: sha1:5a8e24e62e0b41a781f38f22eed4369e4feaa960 + pristine_git_object: 2d7b6d76d80b07c4720ff5984742b9ca5b097f1c docs/sdks/vault/README.mdx: id: 3738c6722acd last_write_checksum: sha1:2b26b8c7e7c88dc4aee023f518b7d8e94f1649f9 @@ -8255,8 +8267,8 @@ trackedFiles: pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544 pyproject.toml: id: 5d07e7d72637 - last_write_checksum: sha1:2182755c8b37ffe89d33640d78d15eded50c963f - pristine_git_object: 3cfb53504b33635caaaa5e59ba31aced74918a2b + last_write_checksum: sha1:a1f5febefe9ab41f16f33ee654083f9643575ebf + pristine_git_object: 08d4dd47159e38b401c96d12fcbb9ab119899f26 scripts/prepare_readme.py: id: e0c5957a6035 last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54 @@ -8283,8 +8295,8 @@ trackedFiles: pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137 src/openrouter/_version.py: id: d8d15ad6c586 - last_write_checksum: sha1:a5e896d58791d6d48c64dfaf9fc3d68c9b887ae4 - pristine_git_object: e3bd110d9f3eebe44728fd0f917865ae6bc7c26b + last_write_checksum: sha1:a6f6ff6b2bae032b308a2440d0e07aa418db58f4 + pristine_git_object: 39525f896b5f75a8287a9069e88b5d3a5712b81d src/openrouter/alpha.py: id: 306c4d93308d last_write_checksum: sha1:30f55a360f41376ab194b9ea725fe4e001a5ae1a @@ -8327,8 +8339,8 @@ trackedFiles: pristine_git_object: ad3d247954547814054c01989a2dff3d12b3e4e1 src/openrouter/components/__init__.py: id: 81754e97b3f4 - last_write_checksum: sha1:286c1a4c6b8272e410a0da94c48d29719f989186 - pristine_git_object: 7300d1852826e3c47d7a155151cc5a473e14f56e + last_write_checksum: sha1:0fe14e50afa7072a2c6c47dbfdbfad4967d06f62 + pristine_git_object: 471fad91d8163a89e5a53d074eff798df191ef83 src/openrouter/components/aabenchmarkentry.py: id: e2e0f0b48c82 last_write_checksum: sha1:fab4d9a24d2cea937bb749d46c5f83941e99d65c @@ -10419,8 +10431,8 @@ trackedFiles: pristine_git_object: 5f4a4186a9c98767217546b6b87d238fbc0155f3 src/openrouter/components/publicendpoint.py: id: 848aa2ef9129 - last_write_checksum: sha1:42707d2210be0e29267c85b4454676dfd56164b9 - pristine_git_object: 7830ec36d3bd2bcd575007c61910165ebe0f2952 + last_write_checksum: sha1:9df37e60706796b35acd7fd36a2ac1aa082c2904 + pristine_git_object: cfa5b51c2a31c34b96413bc44e70f629796f3ad2 src/openrouter/components/publicpricing.py: id: 96d115d83cc5 last_write_checksum: sha1:fd8c320ac83b282eaf2405045329b55076d4311a @@ -10659,24 +10671,32 @@ trackedFiles: pristine_git_object: 418953ba7366a6015934bf8795178d79adb03b89 src/openrouter/components/speechinputreference.py: id: 8e2b63f83354 - last_write_checksum: sha1:9692e7a4c71a1afec612ee7303b4b8202e313b39 - pristine_git_object: 9f490fecdd4b480cbe4b7f2ab6c5fe15aa207f12 + last_write_checksum: sha1:b2ebc68fae64644f8bfca9b555ca7d2a7b46c9e1 + pristine_git_object: 0881593ad73af3e97f5d3a6a2aeb6cfe5ffe687e src/openrouter/components/speechinputreferenceaudio.py: id: 72d940d3f6a2 - last_write_checksum: sha1:f5c3ecd689121fb02903cd869323fbebee033ad3 - pristine_git_object: 7341493f9a8745299e004ccf4e2b672f624fad4f + last_write_checksum: sha1:efd262edae0cb4b4b5052680ffc798f6fd5833d8 + pristine_git_object: 3f346893a5b7da55fa1d1eb437d989d0ec74545f src/openrouter/components/speechinputreferenceaudioinput.py: id: 2e2aeb5ee50f - last_write_checksum: sha1:9712952578b85c2049549cb3c36fd11630405ef3 - pristine_git_object: c6e21210786537b19ca5ba99b48d7a8b61dfcdb1 + last_write_checksum: sha1:7b390e8f08f740cfad113a2f64b0a0b24b940944 + pristine_git_object: 33d35ab0c8d110d9253331c790c4b78b920660f3 + src/openrouter/components/speechinputreferenceimage.py: + id: 644d542991a7 + last_write_checksum: sha1:1e9923984145ab1fa0ced2ccccdba8997e2bba11 + pristine_git_object: 6129f2f1ecb2c8883a1d998e2ac976d54c90ee94 + src/openrouter/components/speechinputreferenceimageinput.py: + id: 91a49498faa8 + last_write_checksum: sha1:b8f5ae40360a7d96de4128d730b042bcd0d2d8e8 + pristine_git_object: f962606705fc3ba8799a2f39b97c1ea5916d8196 src/openrouter/components/speechinputreferencetext.py: id: d9cd9e42ac40 - last_write_checksum: sha1:1bad63b5cff8b3b522dbebdaafb9495d3ddfab61 - pristine_git_object: e1703efe8ac18c7aea925375ddfa6ef74c31193b + last_write_checksum: sha1:3acdadbccb53ffe81cf7221c5f13ef031436adb7 + pristine_git_object: 4633e5d7658c500aa903ce8caa8ef86cc97b78eb src/openrouter/components/speechrequest.py: id: 2a9400167112 - last_write_checksum: sha1:3dbce6755f21e37ab2949daef2c02c530396ddb1 - pristine_git_object: e38473a545f990c87e71007577cf9b6a691fd99a + last_write_checksum: sha1:ac6c30caa9222c55133d8fe5a206c6429010e1af + pristine_git_object: 877daa6a52ae8c1ae4105d860b03fce8e5474c06 src/openrouter/components/stopservertoolswhencondition.py: id: 2deeda4209ac last_write_checksum: sha1:581e0ee62776d42bf598b9f68b998faabfecd3ce @@ -11823,8 +11843,8 @@ trackedFiles: pristine_git_object: aac5cbef3468a6b9c9fe04c3bd6c86e23de4b4e9 src/openrouter/tts.py: id: 5055d4b95f1d - last_write_checksum: sha1:cdeb84948a22d150b582c65b63a53bfab5c13109 - pristine_git_object: 7903797cbdcfced8f4a868feaa0b15b9b44512bb + last_write_checksum: sha1:505003b62781347ac707761c8d082f3b2738025d + pristine_git_object: 7fd842bd10805bae6281913c77e4826a188cd01e src/openrouter/types/__init__.py: id: 5eab536205b7 last_write_checksum: sha1:f9ad14217f832e74f594285960125add50324be9 @@ -12173,7 +12193,7 @@ examples: slug: "gpt-4" responses: "200": - application/json: {"data": {"architecture": {"input_modalities": ["text"], "instruct_type": "chatml", "modality": "text->text", "output_modalities": ["text"], "tokenizer": "GPT"}, "created": 1692901234, "description": "GPT-4 is a large multimodal model that can solve difficult problems with greater accuracy.", "endpoints": [{"context_length": 8192, "latency_last_30m": {"p50": 0.25, "p75": 0.35, "p90": 0.48, "p99": 0.85}, "max_completion_tokens": 4096, "max_prompt_tokens": 8192, "model_id": "openai/gpt-4", "model_name": "GPT-4", "name": "OpenAI: GPT-4", "pricing": {"completion": "0.00006", "prompt": "0.00003"}, "provider_name": "OpenAI", "quantization": "fp16", "supported_parameters": ["temperature", "top_p", "max_tokens"], "supports_implicit_caching": true, "supports_tool_choice": {"auto": true, "function": true, "none": true, "required": true}, "supports_voice_cloning": false, "tag": "openai", "throughput_last_30m": {"p50": 45.2, "p75": 38.5, "p90": 28.3, "p99": 15.1}, "uptime_last_1d": 99.8, "uptime_last_30m": 99.5, "uptime_last_5m": 100}], "id": "openai/gpt-4", "name": "GPT-4"}} + application/json: {"data": {"architecture": {"input_modalities": ["text"], "instruct_type": "chatml", "modality": "text->text", "output_modalities": ["text"], "tokenizer": "GPT"}, "created": 1692901234, "description": "GPT-4 is a large multimodal model that can solve difficult problems with greater accuracy.", "endpoints": [{"context_length": 8192, "latency_last_30m": {"p50": 0.25, "p75": 0.35, "p90": 0.48, "p99": 0.85}, "max_completion_tokens": 4096, "max_prompt_tokens": 8192, "model_id": "openai/gpt-4", "model_name": "GPT-4", "name": "OpenAI: GPT-4", "pricing": {"completion": "0.00006", "prompt": "0.00003"}, "provider_name": "OpenAI", "quantization": "fp16", "supported_parameters": ["temperature", "top_p", "max_tokens"], "supports_image_reference": false, "supports_implicit_caching": true, "supports_multiple_audio_references": false, "supports_tool_choice": {"auto": true, "function": true, "none": true, "required": true}, "supports_voice_cloning": false, "tag": "openai", "throughput_last_30m": {"p50": 45.2, "p75": 38.5, "p90": 28.3, "p99": 15.1}, "uptime_last_1d": 99.8, "uptime_last_30m": 99.5, "uptime_last_5m": 100}], "id": "openai/gpt-4", "name": "GPT-4"}} "404": application/json: {"error": {"code": 404, "message": "Resource not found"}} "500": @@ -12184,7 +12204,7 @@ examples: speakeasy-default-list-endpoints-zdr: responses: "200": - application/json: {"data": [{"context_length": 8192, "latency_last_30m": {"p50": 0.25, "p75": 0.35, "p90": 0.48, "p99": 0.85}, "max_completion_tokens": 4096, "max_prompt_tokens": 8192, "model_id": "openai/gpt-4", "model_name": "GPT-4", "name": "OpenAI: GPT-4", "pricing": {"completion": "0.00006", "prompt": "0.00003"}, "provider_name": "OpenAI", "quantization": "fp16", "supported_parameters": ["temperature", "top_p", "max_tokens"], "supports_implicit_caching": true, "supports_tool_choice": {"auto": true, "function": true, "none": true, "required": true}, "supports_voice_cloning": false, "tag": "openai", "throughput_last_30m": {"p50": 45.2, "p75": 38.5, "p90": 28.3, "p99": 15.1}, "uptime_last_1d": 99.8, "uptime_last_30m": 99.5, "uptime_last_5m": 100}]} + application/json: {"data": [{"context_length": 8192, "latency_last_30m": {"p50": 0.25, "p75": 0.35, "p90": 0.48, "p99": 0.85}, "max_completion_tokens": 4096, "max_prompt_tokens": 8192, "model_id": "openai/gpt-4", "model_name": "GPT-4", "name": "OpenAI: GPT-4", "pricing": {"completion": "0.00006", "prompt": "0.00003"}, "provider_name": "OpenAI", "quantization": "fp16", "supported_parameters": ["temperature", "top_p", "max_tokens"], "supports_image_reference": false, "supports_implicit_caching": true, "supports_multiple_audio_references": false, "supports_tool_choice": {"auto": true, "function": true, "none": true, "required": true}, "supports_voice_cloning": false, "tag": "openai", "throughput_last_30m": {"p50": 45.2, "p75": 38.5, "p90": 28.3, "p99": 15.1}, "uptime_last_1d": 99.8, "uptime_last_30m": 99.5, "uptime_last_5m": 100}]} "500": application/json: {"error": {"code": 500, "message": "Internal Server Error"}} "403": @@ -15162,6 +15182,4 @@ examples: "500": application/json: {"error": {"code": 404, "message": "Intern not found"}} examplesVersion: 1.0.2 -releaseNotes: | - ## Python SDK Changes: - * `open_router.interns.get_intern_daemon_access()`: `error.status[429]` **Removed** (Breaking ⚠️) +releaseNotes: "## Python SDK Changes:\n* `open_router.tts.create_speech()`: \n * `request.input_references[]` **Changed**\n* `open_router.endpoints.list_zdr_endpoints()`: `response.data[]` **Changed**\n* `open_router.endpoints.list()`: `response.data.endpoints[]` **Changed**\n" diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index 24840779..57690f43 100644 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -36,7 +36,7 @@ generation: documentation: mintlify preApplyUnionDiscriminators: true python: - version: 1.2.27 + version: 1.2.28 additionalDependencies: dev: {} main: {} diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml index 3381824e..f66acf24 100644 --- a/.speakeasy/out.openapi.yaml +++ b/.speakeasy/out.openapi.yaml @@ -23967,7 +23967,9 @@ components: - 'temperature' - 'top_p' - 'max_tokens' + supports_image_reference: false supports_implicit_caching: true + supports_multiple_audio_references: false supports_tool_choice: auto: true function: true @@ -24259,8 +24261,16 @@ components: items: $ref: '#/components/schemas/Parameter' type: 'array' + supports_image_reference: + default: false + description: 'Whether this TTS endpoint accepts an `image_url` reference describing the desired voice. Requests carrying an image reference are only routed to endpoints where this is true.' + type: 'boolean' supports_implicit_caching: type: 'boolean' + supports_multiple_audio_references: + default: false + description: 'Whether this TTS endpoint accepts more than one `input_audio` reference clip per request. Requests carrying several clips are only routed to endpoints where this is true.' + type: 'boolean' supports_tool_choice: $ref: '#/components/schemas/ToolChoiceSupport' supports_voice_cloning: @@ -25925,17 +25935,19 @@ components: - $ref: '#/components/schemas/ContainerAutoEnvironment' - $ref: '#/components/schemas/ContainerReferenceEnvironment' SpeechInputReference: - description: 'Reference content part for stateless voice cloning' + description: 'Reference content part for stateless voice cloning or voice design' discriminator: mapping: + image_url: '#/components/schemas/SpeechInputReferenceImage' input_audio: '#/components/schemas/SpeechInputReferenceAudio' text: '#/components/schemas/SpeechInputReferenceText' propertyName: 'type' oneOf: - $ref: '#/components/schemas/SpeechInputReferenceAudio' - $ref: '#/components/schemas/SpeechInputReferenceText' + - $ref: '#/components/schemas/SpeechInputReferenceImage' SpeechInputReferenceAudio: - description: 'Reference audio input for stateless voice cloning' + description: 'Reference audio input for stateless voice cloning. Up to three parts per request; the Nth audio part is addressable from `input` as `@AudioN` on providers that support multiple references.' example: input_audio: data: 'data:audio/wav;base64,UklGRuQXDABXQVZF...' @@ -25955,7 +25967,7 @@ components: description: 'Reference audio input object' properties: data: - description: 'Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio).' + description: 'Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio). Exactly one of `data` or `url` is required.' example: 'data:audio/wav;base64,UklGRuQXDABXQVZF...' maxLength: 20971520 minLength: 1 @@ -25964,17 +25976,50 @@ components: description: 'Audio format of the reference audio (e.g., wav, mp3). Optional; most providers detect the format from the audio bytes.' example: 'wav' type: 'string' + url: + description: 'Public http(s) URL of the reference audio. OpenRouter downloads it (15 MiB max) and forwards the bytes, never the URL. Exactly one of `data` or `url` is required.' + example: 'https://example.com/reference.wav' + format: 'uri' + maxLength: 2048 + type: 'string' + type: 'object' + SpeechInputReferenceImage: + description: 'Reference image describing the desired voice. Cannot be combined with `input_audio` parts. Only routed to endpoints that support image references.' + example: + image_url: + url: 'data:image/png;base64,iVBORw0KGgo...' + type: 'image_url' + properties: + image_url: + $ref: '#/components/schemas/SpeechInputReferenceImageInput' + type: + enum: + - 'image_url' + type: 'string' required: - - 'data' + - 'type' + - 'image_url' + type: 'object' + SpeechInputReferenceImageInput: + description: 'Reference image input object' + properties: + url: + description: 'JPEG, PNG, or WebP reference image as a base64 data URI or a public http(s) URL. Remote images are downloaded (15 MiB max) and forwarded as bytes, never as the URL.' + example: 'data:image/png;base64,iVBORw0KGgo...' + maxLength: 20971520 + minLength: 1 + type: 'string' + required: + - 'url' type: 'object' SpeechInputReferenceText: - description: 'Transcript of the accompanying reference audio' + description: 'Transcript of an `input_audio` part' example: text: 'I used to rule the world.' type: 'text' properties: text: - description: 'Transcript of the accompanying reference audio.' + description: 'Transcript of an `input_audio` part. With a single clip it may appear before or after the clip; with multiple clips it must immediately follow the clip it transcribes.' example: 'I used to rule the world.' maxLength: 10000 type: 'string' @@ -26000,7 +26045,7 @@ components: example: 'Hello world' type: 'string' input_references: - description: 'Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning.' + description: 'Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference.' example: - input_audio: data: 'data:audio/wav;base64,UklGRuQXDABXQVZF...' @@ -34214,7 +34259,9 @@ paths: - 'temperature' - 'top_p' - 'max_tokens' + supports_image_reference: false supports_implicit_caching: true + supports_multiple_audio_references: false supports_voice_cloning: false tag: 'openai' throughput_last_30m: @@ -34251,7 +34298,9 @@ paths: - 'temperature' - 'top_p' - 'max_tokens' + supports_image_reference: false supports_implicit_caching: true + supports_multiple_audio_references: false supports_voice_cloning: false tag: 'openai' throughput_last_30m: diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 19e5c899..16752744 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -2,8 +2,8 @@ speakeasyVersion: 1.787.0 sources: OpenRouter API: sourceNamespace: open-router-chat-completions-api - sourceRevisionDigest: sha256:ebf6e311e185cd80a5e5643606d4def285c2e8f30aa4cbd1f3622e7a9366036b - sourceBlobDigest: sha256:aa51ea5e2f170565c5063fbc4d3b316de3928f9953bbb2683fe6275df1ef56e2 + sourceRevisionDigest: sha256:3300acddd2fd2bf4dd86533707050dd422c7297bccfa3b38546c88df69667864 + sourceBlobDigest: sha256:3a6c855be1c0b1e5ed3c4d831d2b5da76fe0d92432a3fbf6d2edfec6aab84c40 tags: - latest - 1.0.0 @@ -11,10 +11,10 @@ targets: open-router: source: OpenRouter API sourceNamespace: open-router-chat-completions-api - sourceRevisionDigest: sha256:ebf6e311e185cd80a5e5643606d4def285c2e8f30aa4cbd1f3622e7a9366036b - sourceBlobDigest: sha256:aa51ea5e2f170565c5063fbc4d3b316de3928f9953bbb2683fe6275df1ef56e2 + sourceRevisionDigest: sha256:3300acddd2fd2bf4dd86533707050dd422c7297bccfa3b38546c88df69667864 + sourceBlobDigest: sha256:3a6c855be1c0b1e5ed3c4d831d2b5da76fe0d92432a3fbf6d2edfec6aab84c40 codeSamplesNamespace: open-router-python-code-samples - codeSamplesRevisionDigest: sha256:f88e970e6e4f54ca7fe848f85ee986e35301d2119907e87407aafe55a531f301 + codeSamplesRevisionDigest: sha256:d618ed63247c77943456f9506235eca0ac64da62ade8439196342cfac374e221 workflow: workflowVersion: 1.0.0 speakeasyVersion: 1.787.0 diff --git a/RELEASES.md b/RELEASES.md index da874028..df50d511 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -2679,4 +2679,14 @@ Based on: ### Generated - [python v1.2.27] . ### Releases -- [PyPI v1.2.27] https://pypi.org/project/openrouter/1.2.27 - . \ No newline at end of file +- [PyPI v1.2.27] https://pypi.org/project/openrouter/1.2.27 - . + +## 2026-09-25 19:39:53 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.787.0 (2.914.0) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v1.2.28] . +### Releases +- [PyPI v1.2.28] https://pypi.org/project/openrouter/1.2.28 - . \ No newline at end of file diff --git a/docs/components/publicendpoint.mdx b/docs/components/publicendpoint.mdx index 78fc6616..fc7a3507 100644 --- a/docs/components/publicendpoint.mdx +++ b/docs/components/publicendpoint.mdx @@ -22,7 +22,9 @@ Information about a specific model endpoint | `quantization` | [Nullable[components.Quantization]](../components/quantization.mdx) | :heavy_check_mark: | N/A | fp16 | | `status` | [Optional[components.EndpointStatus]](../components/endpointstatus.mdx) | :heavy_minus_sign: | N/A | 0 | | `supported_parameters` | List[[components.Parameter](../components/parameter.mdx)] | :heavy_check_mark: | N/A | | +| `supports_image_reference` | *Optional[bool]* | :heavy_minus_sign: | Whether this TTS endpoint accepts an `image_url` reference describing the desired voice. Requests carrying an image reference are only routed to endpoints where this is true. | | | `supports_implicit_caching` | *bool* | :heavy_check_mark: | N/A | | +| `supports_multiple_audio_references` | *Optional[bool]* | :heavy_minus_sign: | Whether this TTS endpoint accepts more than one `input_audio` reference clip per request. Requests carrying several clips are only routed to endpoints where this is true. | | | `supports_tool_choice` | [components.ToolChoiceSupport](../components/toolchoicesupport.mdx) | :heavy_check_mark: | Per-variant `tool_choice` support. `tool_choice` in `supported_parameters` only says the parameter is accepted; these flags say which of its values passed testing. | \{
"auto": true,
"function": true,
"none": true,
"required": true
} | | `supports_voice_cloning` | *Optional[bool]* | :heavy_minus_sign: | Whether this TTS endpoint accepts inline reference audio (`input_references`) for stateless voice cloning. Requests carrying reference audio are only routed to endpoints where this is true. | | | `tag` | *str* | :heavy_check_mark: | N/A | | diff --git a/docs/components/speechinputreference.mdx b/docs/components/speechinputreference.mdx index 79204829..7303b4f7 100644 --- a/docs/components/speechinputreference.mdx +++ b/docs/components/speechinputreference.mdx @@ -2,11 +2,17 @@ title: "SpeechInputReference" --- -Reference content part for stateless voice cloning +Reference content part for stateless voice cloning or voice design ## Supported Types +### `components.SpeechInputReferenceImage` + +```python +value: components.SpeechInputReferenceImage = /* values here */ +``` + ### `components.SpeechInputReferenceAudio` ```python diff --git a/docs/components/speechinputreferenceaudio.mdx b/docs/components/speechinputreferenceaudio.mdx index c69013da..f00281d1 100644 --- a/docs/components/speechinputreferenceaudio.mdx +++ b/docs/components/speechinputreferenceaudio.mdx @@ -2,7 +2,7 @@ title: "SpeechInputReferenceAudio" --- -Reference audio input for stateless voice cloning +Reference audio input for stateless voice cloning. Up to three parts per request; the Nth audio part is addressable from `input` as `@AudioN` on providers that support multiple references. ## Fields diff --git a/docs/components/speechinputreferenceaudioinput.mdx b/docs/components/speechinputreferenceaudioinput.mdx index fa10a1fb..c16ea82c 100644 --- a/docs/components/speechinputreferenceaudioinput.mdx +++ b/docs/components/speechinputreferenceaudioinput.mdx @@ -7,7 +7,8 @@ Reference audio input object ## Fields -| Field | Type | Required | Description | Example | -| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `data` | *str* | :heavy_check_mark: | Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio). | data:audio/wav;base64,UklGRuQXDABXQVZF... | -| `format_` | *Optional[str]* | :heavy_minus_sign: | Audio format of the reference audio (e.g., wav, mp3). Optional; most providers detect the format from the audio bytes. | wav | \ No newline at end of file +| Field | Type | Required | Description | Example | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `data` | *Optional[str]* | :heavy_minus_sign: | Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio). Exactly one of `data` or `url` is required. | data:audio/wav;base64,UklGRuQXDABXQVZF... | +| `format_` | *Optional[str]* | :heavy_minus_sign: | Audio format of the reference audio (e.g., wav, mp3). Optional; most providers detect the format from the audio bytes. | wav | +| `url` | *Optional[str]* | :heavy_minus_sign: | Public http(s) URL of the reference audio. OpenRouter downloads it (15 MiB max) and forwards the bytes, never the URL. Exactly one of `data` or `url` is required. | https://example.com/reference.wav | \ No newline at end of file diff --git a/docs/components/speechinputreferenceimage.mdx b/docs/components/speechinputreferenceimage.mdx new file mode 100644 index 00000000..068290f7 --- /dev/null +++ b/docs/components/speechinputreferenceimage.mdx @@ -0,0 +1,13 @@ +--- +title: "SpeechInputReferenceImage" +--- + +Reference image describing the desired voice. Cannot be combined with `input_audio` parts. Only routed to endpoints that support image references. + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | +| `image_url` | [components.SpeechInputReferenceImageInput](../components/speechinputreferenceimageinput.mdx) | :heavy_check_mark: | Reference image input object | +| `type` | [components.SpeechInputReferenceImageType](../components/speechinputreferenceimagetype.mdx) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/docs/components/speechinputreferenceimageinput.mdx b/docs/components/speechinputreferenceimageinput.mdx new file mode 100644 index 00000000..127f005a --- /dev/null +++ b/docs/components/speechinputreferenceimageinput.mdx @@ -0,0 +1,12 @@ +--- +title: "SpeechInputReferenceImageInput" +--- + +Reference image input object + + +## Fields + +| Field | Type | Required | Description | Example | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `url` | *str* | :heavy_check_mark: | JPEG, PNG, or WebP reference image as a base64 data URI or a public http(s) URL. Remote images are downloaded (15 MiB max) and forwarded as bytes, never as the URL. | data:image/png;base64,iVBORw0KGgo... | \ No newline at end of file diff --git a/docs/components/speechinputreferenceimagetype.mdx b/docs/components/speechinputreferenceimagetype.mdx new file mode 100644 index 00000000..b40df3d3 --- /dev/null +++ b/docs/components/speechinputreferenceimagetype.mdx @@ -0,0 +1,15 @@ +--- +title: "SpeechInputReferenceImageType" +--- + +## Example Usage + +```python +from openrouter.components import SpeechInputReferenceImageType +value: SpeechInputReferenceImageType = "image_url" +``` + + +## Values + +- `"image_url"` diff --git a/docs/components/speechinputreferencetext.mdx b/docs/components/speechinputreferencetext.mdx index ff25c492..af437e9f 100644 --- a/docs/components/speechinputreferencetext.mdx +++ b/docs/components/speechinputreferencetext.mdx @@ -2,12 +2,12 @@ title: "SpeechInputReferenceText" --- -Transcript of the accompanying reference audio +Transcript of an `input_audio` part ## Fields -| Field | Type | Required | Description | Example | -| ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | -| `text` | *str* | :heavy_check_mark: | Transcript of the accompanying reference audio. | I used to rule the world. | -| `type` | [components.SpeechInputReferenceTextType](../components/speechinputreferencetexttype.mdx) | :heavy_check_mark: | N/A | | \ No newline at end of file +| Field | Type | Required | Description | Example | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `text` | *str* | :heavy_check_mark: | Transcript of an `input_audio` part. With a single clip it may appear before or after the clip; with multiple clips it must immediately follow the clip it transcribes. | I used to rule the world. | +| `type` | [components.SpeechInputReferenceTextType](../components/speechinputreferencetexttype.mdx) | :heavy_check_mark: | N/A | | \ No newline at end of file diff --git a/docs/components/speechrequest.mdx b/docs/components/speechrequest.mdx index a9c5cb01..2c861144 100644 --- a/docs/components/speechrequest.mdx +++ b/docs/components/speechrequest.mdx @@ -7,15 +7,15 @@ Text-to-speech request input ## Fields -| Field | Type | Required | Description | Example | -| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `input` | *str* | :heavy_check_mark: | Text to synthesize | Hello world | -| `input_references` | List[[components.SpeechInputReference](../components/speechinputreference.mdx)] | :heavy_minus_sign: | Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning. | [
\{
"input_audio": \{
"data": "data:audio/wav;base64,UklGRuQXDABXQVZF..."
},
"type": "input_audio"
},
\{
"text": "I used to rule the world.",
"type": "text"
}
] | -| `model` | *str* | :heavy_check_mark: | TTS model identifier | mistralai/voxtral-mini-tts-2603 | -| `provider` | [Optional[components.SpeechRequestProvider]](../components/speechrequestprovider.mdx) | :heavy_minus_sign: | Provider-specific passthrough configuration | | -| `response_format` | [Optional[components.SpeechRequestResponseFormat]](../components/speechrequestresponseformat.mdx) | :heavy_minus_sign: | Audio output format | pcm | -| `session_id` | *Optional[str]* | :heavy_minus_sign: | A unique identifier for grouping related requests (e.g., a conversation or agent workflow). Used for observability grouping in Broadcast and private logging; never sent to the provider. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters. | session-1234 | -| `speed` | *Optional[float]* | :heavy_minus_sign: | Playback speed multiplier. Only used by models that support it (e.g. OpenAI TTS). Ignored by other providers. | 1 | -| `trace` | [Optional[components.TraceConfig]](../components/traceconfig.mdx) | :heavy_minus_sign: | Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations. | \{
"trace_id": "trace-abc123",
"trace_name": "my-app-trace"
} | -| `user` | *Optional[str]* | :heavy_minus_sign: | A unique identifier representing your end-user. Forwarded to Broadcast and private logging as the end-user id; never sent to the provider. | user-1234 | -| `voice` | *Optional[str]* | :heavy_minus_sign: | Voice identifier (provider-specific). | en_paul_neutral | \ No newline at end of file +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `input` | *str* | :heavy_check_mark: | Text to synthesize | Hello world | +| `input_references` | List[[components.SpeechInputReference](../components/speechinputreference.mdx)] | :heavy_minus_sign: | Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference. | [
\{
"input_audio": \{
"data": "data:audio/wav;base64,UklGRuQXDABXQVZF..."
},
"type": "input_audio"
},
\{
"text": "I used to rule the world.",
"type": "text"
}
] | +| `model` | *str* | :heavy_check_mark: | TTS model identifier | mistralai/voxtral-mini-tts-2603 | +| `provider` | [Optional[components.SpeechRequestProvider]](../components/speechrequestprovider.mdx) | :heavy_minus_sign: | Provider-specific passthrough configuration | | +| `response_format` | [Optional[components.SpeechRequestResponseFormat]](../components/speechrequestresponseformat.mdx) | :heavy_minus_sign: | Audio output format | pcm | +| `session_id` | *Optional[str]* | :heavy_minus_sign: | A unique identifier for grouping related requests (e.g., a conversation or agent workflow). Used for observability grouping in Broadcast and private logging; never sent to the provider. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters. | session-1234 | +| `speed` | *Optional[float]* | :heavy_minus_sign: | Playback speed multiplier. Only used by models that support it (e.g. OpenAI TTS). Ignored by other providers. | 1 | +| `trace` | [Optional[components.TraceConfig]](../components/traceconfig.mdx) | :heavy_minus_sign: | Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations. | \{
"trace_id": "trace-abc123",
"trace_name": "my-app-trace"
} | +| `user` | *Optional[str]* | :heavy_minus_sign: | A unique identifier representing your end-user. Forwarded to Broadcast and private logging as the end-user id; never sent to the provider. | user-1234 | +| `voice` | *Optional[str]* | :heavy_minus_sign: | Voice identifier (provider-specific). | en_paul_neutral | \ No newline at end of file diff --git a/docs/sdks/tts/README.mdx b/docs/sdks/tts/README.mdx index bc53071a..2d7b6d76 100644 --- a/docs/sdks/tts/README.mdx +++ b/docs/sdks/tts/README.mdx @@ -38,22 +38,22 @@ with OpenRouter( ### Parameters -| Parameter | Type | Required | Description | Example | -| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `input` | *str* | :heavy_check_mark: | Text to synthesize | Hello world | -| `model` | *str* | :heavy_check_mark: | TTS model identifier | mistralai/voxtral-mini-tts-2603 | -| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| | -| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| | -| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| | -| `input_references` | List[[components.SpeechInputReference](../../components/speechinputreference.mdx)] | :heavy_minus_sign: | Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning. | [
\{
"input_audio": \{
"data": "data:audio/wav;base64,UklGRuQXDABXQVZF..."
},
"type": "input_audio"
},
\{
"text": "I used to rule the world.",
"type": "text"
}
] | -| `provider` | [Optional[components.SpeechRequestProvider]](../../components/speechrequestprovider.mdx) | :heavy_minus_sign: | Provider-specific passthrough configuration | | -| `response_format` | [Optional[components.SpeechRequestResponseFormat]](../../components/speechrequestresponseformat.mdx) | :heavy_minus_sign: | Audio output format | pcm | -| `session_id` | *Optional[str]* | :heavy_minus_sign: | A unique identifier for grouping related requests (e.g., a conversation or agent workflow). Used for observability grouping in Broadcast and private logging; never sent to the provider. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters. | session-1234 | -| `speed` | *Optional[float]* | :heavy_minus_sign: | Playback speed multiplier. Only used by models that support it (e.g. OpenAI TTS). Ignored by other providers. | 1 | -| `trace` | [Optional[components.TraceConfig]](../../components/traceconfig.mdx) | :heavy_minus_sign: | Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations. | \{
"trace_id": "trace-abc123",
"trace_name": "my-app-trace"
} | -| `user` | *Optional[str]* | :heavy_minus_sign: | A unique identifier representing your end-user. Forwarded to Broadcast and private logging as the end-user id; never sent to the provider. | user-1234 | -| `voice` | *Optional[str]* | :heavy_minus_sign: | Voice identifier (provider-specific). | en_paul_neutral | -| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.mdx) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | | +| Parameter | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `input` | *str* | :heavy_check_mark: | Text to synthesize | Hello world | +| `model` | *str* | :heavy_check_mark: | TTS model identifier | mistralai/voxtral-mini-tts-2603 | +| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| | +| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| | +| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| | +| `input_references` | List[[components.SpeechInputReference](../../components/speechinputreference.mdx)] | :heavy_minus_sign: | Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference. | [
\{
"input_audio": \{
"data": "data:audio/wav;base64,UklGRuQXDABXQVZF..."
},
"type": "input_audio"
},
\{
"text": "I used to rule the world.",
"type": "text"
}
] | +| `provider` | [Optional[components.SpeechRequestProvider]](../../components/speechrequestprovider.mdx) | :heavy_minus_sign: | Provider-specific passthrough configuration | | +| `response_format` | [Optional[components.SpeechRequestResponseFormat]](../../components/speechrequestresponseformat.mdx) | :heavy_minus_sign: | Audio output format | pcm | +| `session_id` | *Optional[str]* | :heavy_minus_sign: | A unique identifier for grouping related requests (e.g., a conversation or agent workflow). Used for observability grouping in Broadcast and private logging; never sent to the provider. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters. | session-1234 | +| `speed` | *Optional[float]* | :heavy_minus_sign: | Playback speed multiplier. Only used by models that support it (e.g. OpenAI TTS). Ignored by other providers. | 1 | +| `trace` | [Optional[components.TraceConfig]](../../components/traceconfig.mdx) | :heavy_minus_sign: | Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations. | \{
"trace_id": "trace-abc123",
"trace_name": "my-app-trace"
} | +| `user` | *Optional[str]* | :heavy_minus_sign: | A unique identifier representing your end-user. Forwarded to Broadcast and private logging as the end-user id; never sent to the provider. | user-1234 | +| `voice` | *Optional[str]* | :heavy_minus_sign: | Voice identifier (provider-specific). | en_paul_neutral | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.mdx) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | | ### Response diff --git a/pyproject.toml b/pyproject.toml index 3cfb5350..08d4dd47 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openrouter" -version = "1.2.27" +version = "1.2.28" 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 e3bd110d..39525f89 100644 --- a/src/openrouter/_version.py +++ b/src/openrouter/_version.py @@ -3,10 +3,10 @@ import importlib.metadata __title__: str = "openrouter" -__version__: str = "1.2.27" +__version__: str = "1.2.28" __openapi_doc_version__: str = "1.0.0" __gen_version__: str = "2.914.0" -__user_agent__: str = "speakeasy-sdk/python 1.2.27 2.914.0 1.0.0 openrouter" +__user_agent__: str = "speakeasy-sdk/python 1.2.28 2.914.0 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 7300d185..471fad91 100644 --- a/src/openrouter/components/__init__.py +++ b/src/openrouter/components/__init__.py @@ -3069,6 +3069,15 @@ SpeechInputReferenceAudioInput, SpeechInputReferenceAudioInputTypedDict, ) + from .speechinputreferenceimage import ( + SpeechInputReferenceImage, + SpeechInputReferenceImageType, + SpeechInputReferenceImageTypedDict, + ) + from .speechinputreferenceimageinput import ( + SpeechInputReferenceImageInput, + SpeechInputReferenceImageInputTypedDict, + ) from .speechinputreferencetext import ( SpeechInputReferenceText, SpeechInputReferenceTextType, @@ -5656,6 +5665,11 @@ "SpeechInputReferenceAudioInputTypedDict", "SpeechInputReferenceAudioType", "SpeechInputReferenceAudioTypedDict", + "SpeechInputReferenceImage", + "SpeechInputReferenceImageInput", + "SpeechInputReferenceImageInputTypedDict", + "SpeechInputReferenceImageType", + "SpeechInputReferenceImageTypedDict", "SpeechInputReferenceText", "SpeechInputReferenceTextType", "SpeechInputReferenceTextTypedDict", @@ -8328,6 +8342,11 @@ "SpeechInputReferenceAudioTypedDict": ".speechinputreferenceaudio", "SpeechInputReferenceAudioInput": ".speechinputreferenceaudioinput", "SpeechInputReferenceAudioInputTypedDict": ".speechinputreferenceaudioinput", + "SpeechInputReferenceImage": ".speechinputreferenceimage", + "SpeechInputReferenceImageType": ".speechinputreferenceimage", + "SpeechInputReferenceImageTypedDict": ".speechinputreferenceimage", + "SpeechInputReferenceImageInput": ".speechinputreferenceimageinput", + "SpeechInputReferenceImageInputTypedDict": ".speechinputreferenceimageinput", "SpeechInputReferenceText": ".speechinputreferencetext", "SpeechInputReferenceTextType": ".speechinputreferencetext", "SpeechInputReferenceTextTypedDict": ".speechinputreferencetext", diff --git a/src/openrouter/components/publicendpoint.py b/src/openrouter/components/publicendpoint.py index 7830ec36..cfa5b51c 100644 --- a/src/openrouter/components/publicendpoint.py +++ b/src/openrouter/components/publicendpoint.py @@ -496,6 +496,10 @@ class PublicEndpointTypedDict(TypedDict): perf_last_30m_by_workload: NotRequired[PerfLast30mByWorkloadTypedDict] r"""Endpoint performance over the last 30 minutes, keyed by the kind of request served (e.g. `text_generation`, `image_generation`). Additive to the legacy singular latency and throughput fields; image and video generation report end-to-end latency. Only visible when authenticated with an API key or cookie.""" status: NotRequired[EndpointStatus] + supports_image_reference: NotRequired[bool] + r"""Whether this TTS endpoint accepts an `image_url` reference describing the desired voice. Requests carrying an image reference are only routed to endpoints where this is true.""" + supports_multiple_audio_references: NotRequired[bool] + r"""Whether this TTS endpoint accepts more than one `input_audio` reference clip per request. Requests carrying several clips are only routed to endpoints where this is true.""" supports_voice_cloning: NotRequired[bool] r"""Whether this TTS endpoint accepts inline reference audio (`input_references`) for stateless voice cloning. Requests carrying reference audio are only routed to endpoints where this is true.""" @@ -550,13 +554,25 @@ class PublicEndpoint(BaseModel): status: Optional[EndpointStatus] = None + supports_image_reference: Optional[bool] = False + r"""Whether this TTS endpoint accepts an `image_url` reference describing the desired voice. Requests carrying an image reference are only routed to endpoints where this is true.""" + + supports_multiple_audio_references: Optional[bool] = False + r"""Whether this TTS endpoint accepts more than one `input_audio` reference clip per request. Requests carrying several clips are only routed to endpoints where this is true.""" + supports_voice_cloning: Optional[bool] = False r"""Whether this TTS endpoint accepts inline reference audio (`input_references`) for stateless voice cloning. Requests carrying reference audio are only routed to endpoints where this is true.""" @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = set( - ["perf_last_30m_by_workload", "status", "supports_voice_cloning"] + [ + "perf_last_30m_by_workload", + "status", + "supports_image_reference", + "supports_multiple_audio_references", + "supports_voice_cloning", + ] ) nullable_fields = set( [ diff --git a/src/openrouter/components/speechinputreference.py b/src/openrouter/components/speechinputreference.py index 9f490fec..0881593a 100644 --- a/src/openrouter/components/speechinputreference.py +++ b/src/openrouter/components/speechinputreference.py @@ -5,6 +5,10 @@ SpeechInputReferenceAudio, SpeechInputReferenceAudioTypedDict, ) +from .speechinputreferenceimage import ( + SpeechInputReferenceImage, + SpeechInputReferenceImageTypedDict, +) from .speechinputreferencetext import ( SpeechInputReferenceText, SpeechInputReferenceTextTypedDict, @@ -17,16 +21,21 @@ SpeechInputReferenceTypedDict = TypeAliasType( "SpeechInputReferenceTypedDict", - Union[SpeechInputReferenceAudioTypedDict, SpeechInputReferenceTextTypedDict], + Union[ + SpeechInputReferenceAudioTypedDict, + SpeechInputReferenceTextTypedDict, + SpeechInputReferenceImageTypedDict, + ], ) -r"""Reference content part for stateless voice cloning""" +r"""Reference content part for stateless voice cloning or voice design""" SpeechInputReference = Annotated[ Union[ + Annotated[SpeechInputReferenceImage, Tag("image_url")], Annotated[SpeechInputReferenceAudio, Tag("input_audio")], Annotated[SpeechInputReferenceText, Tag("text")], ], Discriminator(lambda m: get_discriminator(m, "type", "type")), ] -r"""Reference content part for stateless voice cloning""" +r"""Reference content part for stateless voice cloning or voice design""" diff --git a/src/openrouter/components/speechinputreferenceaudio.py b/src/openrouter/components/speechinputreferenceaudio.py index 7341493f..3f346893 100644 --- a/src/openrouter/components/speechinputreferenceaudio.py +++ b/src/openrouter/components/speechinputreferenceaudio.py @@ -14,7 +14,7 @@ class SpeechInputReferenceAudioTypedDict(TypedDict): - r"""Reference audio input for stateless voice cloning""" + r"""Reference audio input for stateless voice cloning. Up to three parts per request; the Nth audio part is addressable from `input` as `@AudioN` on providers that support multiple references.""" input_audio: SpeechInputReferenceAudioInputTypedDict r"""Reference audio input object""" @@ -22,7 +22,7 @@ class SpeechInputReferenceAudioTypedDict(TypedDict): class SpeechInputReferenceAudio(BaseModel): - r"""Reference audio input for stateless voice cloning""" + r"""Reference audio input for stateless voice cloning. Up to three parts per request; the Nth audio part is addressable from `input` as `@AudioN` on providers that support multiple references.""" input_audio: SpeechInputReferenceAudioInput r"""Reference audio input object""" diff --git a/src/openrouter/components/speechinputreferenceaudioinput.py b/src/openrouter/components/speechinputreferenceaudioinput.py index c6e21210..33d35ab0 100644 --- a/src/openrouter/components/speechinputreferenceaudioinput.py +++ b/src/openrouter/components/speechinputreferenceaudioinput.py @@ -11,24 +11,29 @@ class SpeechInputReferenceAudioInputTypedDict(TypedDict): r"""Reference audio input object""" - data: str - r"""Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio).""" + data: NotRequired[str] + r"""Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio). Exactly one of `data` or `url` is required.""" format_: NotRequired[str] r"""Audio format of the reference audio (e.g., wav, mp3). Optional; most providers detect the format from the audio bytes.""" + url: NotRequired[str] + r"""Public http(s) URL of the reference audio. OpenRouter downloads it (15 MiB max) and forwards the bytes, never the URL. Exactly one of `data` or `url` is required.""" class SpeechInputReferenceAudioInput(BaseModel): r"""Reference audio input object""" - data: str - r"""Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio).""" + data: Optional[str] = None + r"""Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio). Exactly one of `data` or `url` is required.""" format_: Annotated[Optional[str], pydantic.Field(alias="format")] = None r"""Audio format of the reference audio (e.g., wav, mp3). Optional; most providers detect the format from the audio bytes.""" + url: Optional[str] = None + r"""Public http(s) URL of the reference audio. OpenRouter downloads it (15 MiB max) and forwards the bytes, never the URL. Exactly one of `data` or `url` is required.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["format"]) + optional_fields = set(["data", "format", "url"]) serialized = handler(self) m = {} diff --git a/src/openrouter/components/speechinputreferenceimage.py b/src/openrouter/components/speechinputreferenceimage.py new file mode 100644 index 00000000..6129f2f1 --- /dev/null +++ b/src/openrouter/components/speechinputreferenceimage.py @@ -0,0 +1,30 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .speechinputreferenceimageinput import ( + SpeechInputReferenceImageInput, + SpeechInputReferenceImageInputTypedDict, +) +from openrouter.types import BaseModel +from typing import Literal +from typing_extensions import TypedDict + + +SpeechInputReferenceImageType = Literal["image_url",] + + +class SpeechInputReferenceImageTypedDict(TypedDict): + r"""Reference image describing the desired voice. Cannot be combined with `input_audio` parts. Only routed to endpoints that support image references.""" + + image_url: SpeechInputReferenceImageInputTypedDict + r"""Reference image input object""" + type: SpeechInputReferenceImageType + + +class SpeechInputReferenceImage(BaseModel): + r"""Reference image describing the desired voice. Cannot be combined with `input_audio` parts. Only routed to endpoints that support image references.""" + + image_url: SpeechInputReferenceImageInput + r"""Reference image input object""" + + type: SpeechInputReferenceImageType diff --git a/src/openrouter/components/speechinputreferenceimageinput.py b/src/openrouter/components/speechinputreferenceimageinput.py new file mode 100644 index 00000000..f9626067 --- /dev/null +++ b/src/openrouter/components/speechinputreferenceimageinput.py @@ -0,0 +1,19 @@ +"""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 SpeechInputReferenceImageInputTypedDict(TypedDict): + r"""Reference image input object""" + + url: str + r"""JPEG, PNG, or WebP reference image as a base64 data URI or a public http(s) URL. Remote images are downloaded (15 MiB max) and forwarded as bytes, never as the URL.""" + + +class SpeechInputReferenceImageInput(BaseModel): + r"""Reference image input object""" + + url: str + r"""JPEG, PNG, or WebP reference image as a base64 data URI or a public http(s) URL. Remote images are downloaded (15 MiB max) and forwarded as bytes, never as the URL.""" diff --git a/src/openrouter/components/speechinputreferencetext.py b/src/openrouter/components/speechinputreferencetext.py index e1703efe..4633e5d7 100644 --- a/src/openrouter/components/speechinputreferencetext.py +++ b/src/openrouter/components/speechinputreferencetext.py @@ -10,17 +10,17 @@ class SpeechInputReferenceTextTypedDict(TypedDict): - r"""Transcript of the accompanying reference audio""" + r"""Transcript of an `input_audio` part""" text: str - r"""Transcript of the accompanying reference audio.""" + r"""Transcript of an `input_audio` part. With a single clip it may appear before or after the clip; with multiple clips it must immediately follow the clip it transcribes.""" type: SpeechInputReferenceTextType class SpeechInputReferenceText(BaseModel): - r"""Transcript of the accompanying reference audio""" + r"""Transcript of an `input_audio` part""" text: str - r"""Transcript of the accompanying reference audio.""" + r"""Transcript of an `input_audio` part. With a single clip it may appear before or after the clip; with multiple clips it must immediately follow the clip it transcribes.""" type: SpeechInputReferenceTextType diff --git a/src/openrouter/components/speechrequest.py b/src/openrouter/components/speechrequest.py index e38473a5..877daa6a 100644 --- a/src/openrouter/components/speechrequest.py +++ b/src/openrouter/components/speechrequest.py @@ -58,7 +58,7 @@ class SpeechRequestTypedDict(TypedDict): model: str r"""TTS model identifier""" input_references: NotRequired[List[SpeechInputReferenceTypedDict]] - r"""Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning.""" + r"""Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference.""" provider: NotRequired[SpeechRequestProviderTypedDict] r"""Provider-specific passthrough configuration""" response_format: NotRequired[SpeechRequestResponseFormat] @@ -85,7 +85,7 @@ class SpeechRequest(BaseModel): r"""TTS model identifier""" input_references: Optional[List[SpeechInputReference]] = None - r"""Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning.""" + r"""Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference.""" provider: Optional[SpeechRequestProvider] = None r"""Provider-specific passthrough configuration""" diff --git a/src/openrouter/tts.py b/src/openrouter/tts.py index 7903797c..7fd842bd 100644 --- a/src/openrouter/tts.py +++ b/src/openrouter/tts.py @@ -59,7 +59,7 @@ def create_speech( :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. - :param input_references: Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning. + :param input_references: Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference. :param provider: Provider-specific passthrough configuration :param response_format: Audio output format :param session_id: A unique identifier for grouping related requests (e.g., a conversation or agent workflow). Used for observability grouping in Broadcast and private logging; never sent to the provider. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters. @@ -312,7 +312,7 @@ async def create_speech_async( :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. - :param input_references: Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning. + :param input_references: Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference. :param provider: Provider-specific passthrough configuration :param response_format: Audio output format :param session_id: A unique identifier for grouping related requests (e.g., a conversation or agent workflow). Used for observability grouping in Broadcast and private logging; never sent to the provider. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters. diff --git a/uv.lock b/uv.lock index 9059cede..0f644753 100644 --- a/uv.lock +++ b/uv.lock @@ -213,7 +213,7 @@ wheels = [ [[package]] name = "openrouter" -version = "1.2.27" +version = "1.2.28" source = { editable = "." } dependencies = [ { name = "httpcore" }, From 0b4639f53da1ba02495b5cf446ab16ca147801a2 Mon Sep 17 00:00:00 2001 From: "speakeasy-github[bot]" <128539517+speakeasy-github[bot]@users.noreply.github.com> Date: Fri, 25 Sep 2026 19:42:02 +0000 Subject: [PATCH 2/2] empty commit to trigger [run-tests] workflow