From 8048089cf3a118ff7b18ce6814462363af183262 Mon Sep 17 00:00:00 2001 From: speakeasybot Date: Sun, 20 Sep 2026 04:45:26 +0000 Subject: [PATCH 1/3] ## Python SDK Changes: * `open_router.system_one.create()`: **Added** --- .speakeasy/gen.lock | 82 +++- .speakeasy/gen.yaml | 2 +- .speakeasy/out.openapi.yaml | 11 +- .speakeasy/workflow.lock | 10 +- RELEASES.md | 12 +- docs/operations/createsystemoneglobals.mdx | 11 + docs/operations/createsystemonerequest.mdx | 12 + docs/sdks/systemone/README.mdx | 105 +++++ pyproject.toml | 2 +- src/openrouter/_version.py | 4 +- src/openrouter/operations/__init__.py | 14 + src/openrouter/operations/createsystemone.py | 144 ++++++ src/openrouter/sdk.py | 4 + src/openrouter/systemone.py | 439 +++++++++++++++++++ uv.lock | 2 +- 15 files changed, 825 insertions(+), 29 deletions(-) create mode 100644 docs/operations/createsystemoneglobals.mdx create mode 100644 docs/operations/createsystemonerequest.mdx create mode 100644 docs/sdks/systemone/README.mdx create mode 100644 src/openrouter/operations/createsystemone.py create mode 100644 src/openrouter/systemone.py diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 37c9a799..9f63688e 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: b8ef8e6acc081583a4b4b5280d5bc66a + docChecksum: 10cc3bd835df5bf3fce4fe2563a34256 docVersion: 1.0.0 speakeasyVersion: 1.787.0 generationVersion: 2.914.0 - releaseVersion: 1.2.7 - configChecksum: aa1b9118eec5df8f4c5665a1e53972cd + releaseVersion: 1.2.8 + configChecksum: 5aa38056cf49b40445697d3786c6310a repoURL: https://github.com/OpenRouterTeam/python-sdk.git installationURL: https://github.com/OpenRouterTeam/python-sdk.git published: true persistentEdits: - generation_id: bca11b04-b80d-49be-a6bd-00fc34f50538 - pristine_commit_hash: c713a8d5543ed7cc25eb572945a4a4c5ea574510 - pristine_tree_hash: ec331e7667fa75e32ef857f3c3ad74172c54ce23 + generation_id: dce5049f-6fa8-49be-a5f5-bc657ee76aa9 + pristine_commit_hash: 7f8731cb0345e17e75f6ee2102f01698513004ce + pristine_tree_hash: b9165056d686a979117bcf0e228ee3567ce2ffc4 features: python: acceptHeaders: 3.0.0 @@ -6841,6 +6841,14 @@ trackedFiles: id: 56c7ec9966fa last_write_checksum: sha1:b98cbf395a3bc9b53b859f3b1e8efe9ee35366bb pristine_git_object: 1832b155e778ebd9eb28ebc4a4af459b95a1a506 + docs/operations/createsystemoneglobals.mdx: + id: 41c14f5ceed1 + last_write_checksum: sha1:96f8ca57c9f21bbfcd86edb240c79e6ca45a492c + pristine_git_object: 6fde4d64361c306141ada1382a473c123cf01b26 + docs/operations/createsystemonerequest.mdx: + id: 482fbce116a8 + last_write_checksum: sha1:b2631e99056ea9f80865ee9a40ffcbe5c198a432 + pristine_git_object: 434fb7f89f9489c58dcfbf5dd065c5605206c118 docs/operations/createvideosglobals.mdx: id: 84de29ff23d6 last_write_checksum: sha1:b0e6bc84afd5b4bcdb3f491c64b3f5c15e74d187 @@ -8141,6 +8149,10 @@ trackedFiles: id: 190b0dc9a5d1 last_write_checksum: sha1:9a13f8f1e26550bccf3935a36e9c3426febc6fcb pristine_git_object: 1a12d8375fe6ddf9ef6ee1911ce0ed6831a16942 + docs/sdks/systemone/README.mdx: + id: 55c317c71f3d + last_write_checksum: sha1:b1ad82361fe1dbef6bedeead3783c75ec36283b6 + pristine_git_object: fc7688ebea8e973bebc0525a820ba246b6491f81 docs/sdks/tts/README.mdx: id: cd1132543884 last_write_checksum: sha1:37918eb124f9ae0234e8047be7ec07a955458cbc @@ -8163,8 +8175,8 @@ trackedFiles: pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544 pyproject.toml: id: 5d07e7d72637 - last_write_checksum: sha1:b9b202e55e8f133fe617f5a90f83911d10664e1e - pristine_git_object: 11ae0f2796eb8bb374a0e12ab2cbcb284f6a1c34 + last_write_checksum: sha1:9c9aac4feea5df58390f40a1d212f251d3b80123 + pristine_git_object: 2fa4c827c0a455783b23e7183a3076a34e06723b scripts/prepare_readme.py: id: e0c5957a6035 last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54 @@ -8191,8 +8203,8 @@ trackedFiles: pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137 src/openrouter/_version.py: id: d8d15ad6c586 - last_write_checksum: sha1:f80f256266c26716757ffd8846abb566c67c9557 - pristine_git_object: 9e7f35935b8f44c86d1f2c350d6179a3b5bdfe58 + last_write_checksum: sha1:bf31610e41c64a659df291327e64114d28656f4f + pristine_git_object: 2a441139a5a23bb3841818e1e027427935a32494 src/openrouter/alpha.py: id: 306c4d93308d last_write_checksum: sha1:0c25a52ed5fb688ec1e923e4e82bcfc9cae49465 @@ -11163,8 +11175,8 @@ trackedFiles: pristine_git_object: 8680343bbc90107ae6413bd5686012b1fd75d665 src/openrouter/operations/__init__.py: id: 9afcea1e7161 - last_write_checksum: sha1:75bfcaac588b4da23900adbd7960f9a633955cf8 - pristine_git_object: 297025948ee72fba5ef27e0efb31207d6caf55d8 + last_write_checksum: sha1:0c2f16d015e25e4cb302ba60d5aa8cf0e4d29f9f + pristine_git_object: f11532262b28c15b5a367afdeff9dd415e78f53e src/openrouter/operations/bulkaddworkspacemembers.py: id: e0ed56117619 last_write_checksum: sha1:5c44eb0d40fdece3ac084615f6c6082be4cf1d5a @@ -11277,6 +11289,10 @@ trackedFiles: id: 6e34c289d71d last_write_checksum: sha1:3395583f3df63ed55df668d1172a9fbe507a47f0 pristine_git_object: bafc88732217831ec34ae960b8711e2587640ba9 + src/openrouter/operations/createsystemone.py: + id: 3f135b32567e + last_write_checksum: sha1:7afb0a0fdf95fb8c6987c3e43fd6796e63e749ec + pristine_git_object: 356ee5d165f57ad1dea59e7064fbaff5a5807ce6 src/openrouter/operations/createvideos.py: id: d52f6a4a3fe4 last_write_checksum: sha1:dbcf7068a23f48a5d4cfd9c8150206731a40cc9b @@ -11675,8 +11691,8 @@ trackedFiles: pristine_git_object: 1bea5be2496b283307c037f131a45a25bcca3c6c src/openrouter/sdk.py: id: ee9846c4c9c5 - last_write_checksum: sha1:242d0703dc95b748be45817ef9c7ad376e074b76 - pristine_git_object: 0fb8d63a93c0adc8462682be6e5a0207edebe593 + last_write_checksum: sha1:524fce02fc013302916d4e533dc358c739f0cbb4 + pristine_git_object: 28ea1b39c429276d1e06268ac0f60652ff15a989 src/openrouter/sdkconfiguration.py: id: 55773bb98d7c last_write_checksum: sha1:c01826125c31a8b8bc99d9d679782c8758fae001 @@ -11685,6 +11701,10 @@ trackedFiles: id: fc0c2f669423 last_write_checksum: sha1:294961a1d783e04ac54c3733e4563494e241fcd7 pristine_git_object: 7502cb976473e1324ca78330ed0f22505d01c925 + src/openrouter/systemone.py: + id: 7e0a0e237bb1 + last_write_checksum: sha1:fffd7413e70f4840b793888763631b51929eb766 + pristine_git_object: aac5cbef3468a6b9c9fe04c3bd6c86e23de4b4e9 src/openrouter/tts.py: id: 5055d4b95f1d last_write_checksum: sha1:cdeb84948a22d150b582c65b63a53bfab5c13109 @@ -14954,4 +14974,38 @@ examples: application/json: {"error": {"code": 409, "message": "That question is no longer waiting for an answer."}} "502": application/json: {"error": {"code": 409, "message": "That question is no longer waiting for an answer."}} + createSystemone: + speakeasy-default-create-systemone: + requestBody: + application/json: {"model": "Taurus", "questions": {}, "state": {"key": "Utah", "key1": "Alaska", "key2": "Ohio"}} + responses: + "200": + application/json: {"answers": {"key": {"score": 9690, "type": "score"}}, "model": "Model Y", "usage": {"input_tokens": 514823, "output_tokens": 883118}} + "400": + application/json: {"error": {"code": 400, "message": "Invalid request parameters"}} + "401": + application/json: {"error": {"code": 401, "message": "Missing Authentication header"}} + "402": + application/json: {"error": {"code": 402, "message": "Insufficient credits. Add more using https://openrouter.ai/credits"}} + "403": + application/json: {"error": {"code": 403, "message": "Only management keys can perform this operation"}} + "404": + application/json: {"error": {"code": 404, "message": "Resource not found"}} + "413": + application/json: {"error": {"code": 413, "message": "Request payload too large"}} + "429": + application/json: {"error": {"code": 429, "message": "Rate limit exceeded"}} + "500": + application/json: {"error": {"code": 500, "message": "Internal Server Error"}} + "502": + application/json: {"error": {"code": 502, "message": "Provider returned error"}} + "503": + application/json: {"error": {"code": 503, "message": "Service temporarily unavailable"}} + "524": + application/json: {"error": {"code": 524, "message": "Request timed out. Please try again later."}} + "529": + application/json: {"error": {"code": 529, "message": "Provider returned error"}} examplesVersion: 1.0.2 +releaseNotes: | + ## Python SDK Changes: + * `open_router.system_one.create()`: **Added** diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index 11d453a8..4aa000a9 100644 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -36,7 +36,7 @@ generation: documentation: mintlify preApplyUnionDiscriminators: true python: - version: 1.2.7 + version: 1.2.8 additionalDependencies: dev: {} main: {} diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml index b0202321..c2508a42 100644 --- a/.speakeasy/out.openapi.yaml +++ b/.speakeasy/out.openapi.yaml @@ -43316,7 +43316,7 @@ paths: - $ref: "#/components/parameters/AppCategories" /systemone: post: - description: 'TypeSafe SDK compatible alias for `POST /api/alpha/decisions`. Accepts the same request body and returns the same response. Bare TypeSafe model IDs such as `jev-1.13` and `jev-latest` are mapped onto the `typesafe/` namespace.' + description: 'Sends state and typed questions to a System One model such as Jev and returns its answers. Compatible with the TypeSafe SDKs. Bare System One model IDs such as `jev-1.13` and `jev-latest` are mapped onto the `typesafe/` namespace.' operationId: 'createSystemone' requestBody: content: @@ -43509,10 +43509,10 @@ paths: schema: $ref: '#/components/schemas/ProviderOverloadedResponse' description: 'Provider Overloaded - Provider is temporarily overloaded' - summary: 'Submit a System One request (TypeSafe SDK compatible alias)' + summary: 'Submit a System One request' tags: - - 'alpha.decisions' - x-speakeasy-ignore: true + - 'SystemOne' + x-speakeasy-name-override: 'create' parameters: - $ref: "#/components/parameters/AppIdentifier" - $ref: "#/components/parameters/AppDisplayName" @@ -46488,6 +46488,9 @@ tags: - description: 'Speech-to-text endpoints' name: 'STT' x-displayName: 'Transcriptions' + - description: 'System One endpoints for models such as Jev, compatible with the TypeSafe SDKs. See https://openrouter.ai/docs/guides/community/typesafe-sdk.' + name: 'SystemOne' + x-displayName: 'System One' - description: 'Text-to-speech endpoints' name: 'TTS' x-displayName: 'Speech' diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 9dccc52a..3932be46 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:a6fb2582d267b7a3ea83cae1439a32e175a0f65079851685be4ad94d684f4689 - sourceBlobDigest: sha256:b48edb241b574a295970dc9757ce399f317bdb84a4932b017a60cbe5969a6801 + sourceRevisionDigest: sha256:afa706f4e8224e896a845cf5ab0b73d8e7f98460c6cd9644071c183083268eda + sourceBlobDigest: sha256:52077f88403046264219927d45e06d3e45a47bcfcc5aceaeb5c494ec1144ae9a tags: - latest - 1.0.0 @@ -11,10 +11,10 @@ targets: open-router: source: OpenRouter API sourceNamespace: open-router-chat-completions-api - sourceRevisionDigest: sha256:a6fb2582d267b7a3ea83cae1439a32e175a0f65079851685be4ad94d684f4689 - sourceBlobDigest: sha256:b48edb241b574a295970dc9757ce399f317bdb84a4932b017a60cbe5969a6801 + sourceRevisionDigest: sha256:afa706f4e8224e896a845cf5ab0b73d8e7f98460c6cd9644071c183083268eda + sourceBlobDigest: sha256:52077f88403046264219927d45e06d3e45a47bcfcc5aceaeb5c494ec1144ae9a codeSamplesNamespace: open-router-python-code-samples - codeSamplesRevisionDigest: sha256:5ec445fcf3f7f6272d47694eeb88a4f2b90932843ec515d063c28b56df1c5ef9 + codeSamplesRevisionDigest: sha256:b2cd8196b0557606a3c03dd8dfed3be0e421e0c278c63058cb0f8b947b49f6f6 workflow: workflowVersion: 1.0.0 speakeasyVersion: 1.787.0 diff --git a/RELEASES.md b/RELEASES.md index 087109bb..982cd92e 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -2479,4 +2479,14 @@ Based on: ### Generated - [python v1.2.7] . ### Releases -- [PyPI v1.2.7] https://pypi.org/project/openrouter/1.2.7 - . \ No newline at end of file +- [PyPI v1.2.7] https://pypi.org/project/openrouter/1.2.7 - . + +## 2026-09-20 04:43:59 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.787.0 (2.914.0) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v1.2.8] . +### Releases +- [PyPI v1.2.8] https://pypi.org/project/openrouter/1.2.8 - . \ No newline at end of file diff --git a/docs/operations/createsystemoneglobals.mdx b/docs/operations/createsystemoneglobals.mdx new file mode 100644 index 00000000..6fde4d64 --- /dev/null +++ b/docs/operations/createsystemoneglobals.mdx @@ -0,0 +1,11 @@ +--- +title: "CreateSystemoneGlobals" +--- + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| `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.
| \ No newline at end of file diff --git a/docs/operations/createsystemonerequest.mdx b/docs/operations/createsystemonerequest.mdx new file mode 100644 index 00000000..434fb7f8 --- /dev/null +++ b/docs/operations/createsystemonerequest.mdx @@ -0,0 +1,12 @@ +--- +title: "CreateSystemoneRequest" +--- + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| `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.
| +| `decisions_request` | [components.DecisionsRequest](../components/decisionsrequest.mdx) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/docs/sdks/systemone/README.mdx b/docs/sdks/systemone/README.mdx new file mode 100644 index 00000000..fc7688eb --- /dev/null +++ b/docs/sdks/systemone/README.mdx @@ -0,0 +1,105 @@ +--- +title: "SystemOne" +description: "System One endpoints for models such as Jev, compatible with the TypeSafe SDKs. See https://openrouter.ai/docs/guides/community/typesafe-sdk." +--- + +## Overview + +System One endpoints for models such as Jev, compatible with the TypeSafe SDKs. See https://openrouter.ai/docs/guides/community/typesafe-sdk. + +### Available Operations + +* [create](#create) - Submit a System One request + +## create + +Sends state and typed questions to a System One model such as Jev and returns its answers. Compatible with the TypeSafe SDKs. Bare System One model IDs such as `jev-1.13` and `jev-latest` are mapped onto the `typesafe/` namespace. + +### Example Usage + +```python +from openrouter import OpenRouter +import os + + +with OpenRouter( + http_referer="", + x_open_router_title="", + x_open_router_categories="", + api_key=os.getenv("OPENROUTER_API_KEY", ""), +) as open_router: + + res = open_router.system_one.create(model="typesafe/jev-1.13", questions={ + "is_bug": { + "criteria": { + "false": "The customer is asking a question or requesting a feature.", + "true": "The customer describes broken or unexpected product behavior.", + }, + "instructions": "Is the customer reporting a software defect?", + "type": "noul", + }, + "team": { + "criteria": { + "account": "Login, permissions, or profile issues.", + "frontend": "Rendering, layout, or browser compatibility issues.", + "payments": "Checkout, billing, or payment processing issues.", + }, + "instructions": "Which team should own this ticket?", + "type": "choice", + }, + "urgency": { + "criteria": [ + "Can wait for the next release", + "Should be fixed this week", + "Blocking revenue right now", + ], + "instructions": "How urgent is this ticket?", + "type": "score", + }, + }, state={ + "customer_tier": "enterprise", + "ticket": "My checkout page shows a blank screen after I click Pay. I have tried two browsers.", + }) + + # Handle response + print(res) + +``` + +### Parameters + +| Parameter | Type | Required | Description | Example | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `model` | *str* | :heavy_check_mark: | N/A | | +| `questions` | Dict[str, [components.Questions](../../components/questions.mdx)] | :heavy_check_mark: | N/A | | +| `state` | [components.State](../../components/state.mdx) | :heavy_check_mark: | The content to evaluate: a plain string, or a JSON object or array of related context. | | +| `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.
| | +| `provider` | [OptionalNullable[components.ProviderPreferences]](../../components/providerpreferences.mdx) | :heavy_minus_sign: | N/A | \{
"allow_fallbacks": true
} | +| `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 | +| `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: | N/A | | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.mdx) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | | + +### Response + +**[components.DecisionsResponse](../../components/decisionsresponse.mdx)** + +### Errors + +| Error Type | Status Code | Content Type | +| -------------------------------------- | -------------------------------------- | -------------------------------------- | +| errors.BadRequestResponseError | 400 | application/json | +| errors.UnauthorizedResponseError | 401 | application/json | +| errors.PaymentRequiredResponseError | 402 | application/json | +| errors.ForbiddenResponseError | 403 | application/json | +| errors.NotFoundResponseError | 404 | application/json | +| errors.PayloadTooLargeResponseError | 413 | application/json | +| errors.TooManyRequestsResponseError | 429 | application/json | +| errors.InternalServerResponseError | 500 | application/json | +| errors.BadGatewayResponseError | 502 | application/json | +| errors.ServiceUnavailableResponseError | 503 | application/json | +| errors.EdgeNetworkTimeoutResponseError | 524 | application/json | +| errors.ProviderOverloadedResponseError | 529 | application/json | +| errors.OpenRouterDefaultError | 4XX, 5XX | \*/\* | \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 11ae0f27..2fa4c827 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openrouter" -version = "1.2.7" +version = "1.2.8" 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 9e7f3593..2a441139 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.7" +__version__: str = "1.2.8" __openapi_doc_version__: str = "1.0.0" __gen_version__: str = "2.914.0" -__user_agent__: str = "speakeasy-sdk/python 1.2.7 2.914.0 1.0.0 openrouter" +__user_agent__: str = "speakeasy-sdk/python 1.2.8 2.914.0 1.0.0 openrouter" try: if __package__ is not None: diff --git a/src/openrouter/operations/__init__.py b/src/openrouter/operations/__init__.py index 29702594..f1153226 100644 --- a/src/openrouter/operations/__init__.py +++ b/src/openrouter/operations/__init__.py @@ -252,6 +252,12 @@ CreateScimSyncJobResponse, CreateScimSyncJobResponseTypedDict, ) + from .createsystemone import ( + CreateSystemoneGlobals, + CreateSystemoneGlobalsTypedDict, + CreateSystemoneRequest, + CreateSystemoneRequestTypedDict, + ) from .createvideos import ( CreateVideosGlobals, CreateVideosGlobalsTypedDict, @@ -1151,6 +1157,10 @@ "CreateScimSyncJobRequestTypedDict", "CreateScimSyncJobResponse", "CreateScimSyncJobResponseTypedDict", + "CreateSystemoneGlobals", + "CreateSystemoneGlobalsTypedDict", + "CreateSystemoneRequest", + "CreateSystemoneRequestTypedDict", "CreateVideosGlobals", "CreateVideosGlobalsTypedDict", "CreateVideosRequest", @@ -1899,6 +1909,10 @@ "CreateScimSyncJobRequestTypedDict": ".createscimsyncjob", "CreateScimSyncJobResponse": ".createscimsyncjob", "CreateScimSyncJobResponseTypedDict": ".createscimsyncjob", + "CreateSystemoneGlobals": ".createsystemone", + "CreateSystemoneGlobalsTypedDict": ".createsystemone", + "CreateSystemoneRequest": ".createsystemone", + "CreateSystemoneRequestTypedDict": ".createsystemone", "CreateVideosGlobals": ".createvideos", "CreateVideosGlobalsTypedDict": ".createvideos", "CreateVideosRequest": ".createvideos", diff --git a/src/openrouter/operations/createsystemone.py b/src/openrouter/operations/createsystemone.py new file mode 100644 index 00000000..356ee5d1 --- /dev/null +++ b/src/openrouter/operations/createsystemone.py @@ -0,0 +1,144 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from openrouter.components import decisionsrequest as components_decisionsrequest +from openrouter.types import BaseModel, UNSET_SENTINEL +from openrouter.utils import FieldMetadata, HeaderMetadata, RequestMetadata +import pydantic +from pydantic import model_serializer +from typing import Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class CreateSystemoneGlobalsTypedDict(TypedDict): + http_referer: NotRequired[str] + r"""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: NotRequired[str] + r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard. + + """ + x_open_router_categories: NotRequired[str] + r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. + + """ + + +class CreateSystemoneGlobals(BaseModel): + http_referer: Annotated[ + Optional[str], + pydantic.Field(alias="HTTP-Referer"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""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: Annotated[ + Optional[str], + pydantic.Field(alias="X-OpenRouter-Title"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard. + + """ + + x_open_router_categories: Annotated[ + Optional[str], + pydantic.Field(alias="X-OpenRouter-Categories"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. + + """ + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set( + ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"] + ) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class CreateSystemoneRequestTypedDict(TypedDict): + decisions_request: components_decisionsrequest.DecisionsRequestTypedDict + http_referer: NotRequired[str] + r"""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: NotRequired[str] + r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard. + + """ + x_open_router_categories: NotRequired[str] + r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. + + """ + + +class CreateSystemoneRequest(BaseModel): + decisions_request: Annotated[ + components_decisionsrequest.DecisionsRequest, + FieldMetadata(request=RequestMetadata(media_type="application/json")), + ] + + http_referer: Annotated[ + Optional[str], + pydantic.Field(alias="HTTP-Referer"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""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: Annotated[ + Optional[str], + pydantic.Field(alias="X-OpenRouter-Title"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard. + + """ + + x_open_router_categories: Annotated[ + Optional[str], + pydantic.Field(alias="X-OpenRouter-Categories"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. + + """ + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set( + ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"] + ) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m diff --git a/src/openrouter/sdk.py b/src/openrouter/sdk.py index 0fb8d63a..28ea1b39 100644 --- a/src/openrouter/sdk.py +++ b/src/openrouter/sdk.py @@ -44,6 +44,7 @@ from openrouter.responses import Responses from openrouter.scim import Scim from openrouter.stt import STT + from openrouter.systemone import SystemOne from openrouter.tts import TTS from openrouter.vault import Vault from openrouter.video_generation import VideoGeneration @@ -110,6 +111,8 @@ class OpenRouter(BaseSDK): beta: "Beta" scim: "Scim" r"""Management endpoints for SCIM group-to-workspace mappings, authenticated with a management key. These are not the SCIM 2.0 connector endpoints for your identity provider. In your identity provider, enter the SCIM endpoint URL shown when you enable provisioning under Settings > Members > SCIM Mappings. See https://openrouter.ai/docs/guides/features/scim-mappings#set-up-provisioning.""" + system_one: "SystemOne" + r"""System One endpoints for models such as Jev, compatible with the TypeSafe SDKs. See https://openrouter.ai/docs/guides/community/typesafe-sdk.""" vault: "Vault" r"""Store host-bound secrets for a workspace or for one intern. Scope is selected by the API key. Responses return metadata only, never secret values. See https://openrouter.ai/docs/guides/ori/vault.""" video_generation: "VideoGeneration" @@ -146,6 +149,7 @@ class OpenRouter(BaseSDK): "responses": ("openrouter.responses", "Responses"), "beta": ("openrouter.beta", "Beta"), "scim": ("openrouter.scim", "Scim"), + "system_one": ("openrouter.systemone", "SystemOne"), "vault": ("openrouter.vault", "Vault"), "video_generation": ("openrouter.video_generation", "VideoGeneration"), "workspaces": ("openrouter.workspaces", "Workspaces"), diff --git a/src/openrouter/systemone.py b/src/openrouter/systemone.py new file mode 100644 index 00000000..aac5cbef --- /dev/null +++ b/src/openrouter/systemone.py @@ -0,0 +1,439 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .basesdk import BaseSDK +from openrouter import components, errors, operations, utils +from openrouter._hooks import HookContext +from openrouter.types import OptionalNullable, UNSET +from openrouter.utils import get_security_from_env +from openrouter.utils.unmarshal_json_response import unmarshal_json_response +from typing import Any, Dict, Mapping, Optional, Union + + +class SystemOne(BaseSDK): + r"""System One endpoints for models such as Jev, compatible with the TypeSafe SDKs. See https://openrouter.ai/docs/guides/community/typesafe-sdk.""" + + def create( + self, + *, + model: str, + questions: Union[ + Mapping[str, components.Questions], + Mapping[str, components.QuestionsTypedDict], + ], + state: Union[components.State, components.StateTypedDict], + http_referer: Optional[str] = None, + x_open_router_title: Optional[str] = None, + x_open_router_categories: Optional[str] = None, + provider: OptionalNullable[ + Union[ + components.ProviderPreferences, components.ProviderPreferencesTypedDict + ] + ] = UNSET, + session_id: Optional[str] = None, + trace: Optional[ + Union[components.TraceConfig, components.TraceConfigTypedDict] + ] = None, + user: Optional[str] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> components.DecisionsResponse: + r"""Submit a System One request + + Sends state and typed questions to a System One model such as Jev and returns its answers. Compatible with the TypeSafe SDKs. Bare System One model IDs such as `jev-1.13` and `jev-latest` are mapped onto the `typesafe/` namespace. + + :param model: + :param questions: + :param state: The content to evaluate: a plain string, or a JSON object or array of related context. + :param http_referer: 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. + + :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard. + + :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. + + :param provider: + :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. + :param trace: 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. + :param user: + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = operations.CreateSystemoneRequest( + http_referer=http_referer, + x_open_router_title=x_open_router_title, + x_open_router_categories=x_open_router_categories, + decisions_request=components.DecisionsRequest( + model=model, + provider=utils.get_pydantic_model( + provider, OptionalNullable[components.ProviderPreferences] + ), + questions=utils.get_pydantic_model( + questions, Dict[str, components.Questions] + ), + session_id=session_id, + state=utils.unmarshal(state, components.State), + trace=utils.get_pydantic_model(trace, Optional[components.TraceConfig]), + user=user, + ), + ) + + req = self._build_request( + method="POST", + path="/systemone", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + _globals=operations.CreateSystemoneGlobals( + http_referer=self.sdk_configuration.globals.http_referer, + x_open_router_title=self.sdk_configuration.globals.x_open_router_title, + x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories, + ), + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.decisions_request, + False, + False, + "json", + components.DecisionsRequest, + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + else: + retries = utils.RetryConfig( + "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True + ) + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["5XX"]) + + http_res = self.do_request( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="createSystemone", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, components.Security + ), + tags=["SystemOne"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(components.DecisionsResponse, http_res) + if utils.match_response(http_res, "400", "application/json"): + response_data = unmarshal_json_response( + errors.BadRequestResponseErrorData, http_res + ) + raise errors.BadRequestResponseError(response_data, http_res) + if utils.match_response(http_res, "401", "application/json"): + response_data = unmarshal_json_response( + errors.UnauthorizedResponseErrorData, http_res + ) + raise errors.UnauthorizedResponseError(response_data, http_res) + if utils.match_response(http_res, "402", "application/json"): + response_data = unmarshal_json_response( + errors.PaymentRequiredResponseErrorData, http_res + ) + raise errors.PaymentRequiredResponseError(response_data, http_res) + if utils.match_response(http_res, "403", "application/json"): + response_data = unmarshal_json_response( + errors.ForbiddenResponseErrorData, http_res + ) + raise errors.ForbiddenResponseError(response_data, http_res) + if utils.match_response(http_res, "404", "application/json"): + response_data = unmarshal_json_response( + errors.NotFoundResponseErrorData, http_res + ) + raise errors.NotFoundResponseError(response_data, http_res) + if utils.match_response(http_res, "413", "application/json"): + response_data = unmarshal_json_response( + errors.PayloadTooLargeResponseErrorData, http_res + ) + raise errors.PayloadTooLargeResponseError(response_data, http_res) + if utils.match_response(http_res, "429", "application/json"): + response_data = unmarshal_json_response( + errors.TooManyRequestsResponseErrorData, http_res + ) + raise errors.TooManyRequestsResponseError(response_data, http_res) + if utils.match_response(http_res, "500", "application/json"): + response_data = unmarshal_json_response( + errors.InternalServerResponseErrorData, http_res + ) + raise errors.InternalServerResponseError(response_data, http_res) + if utils.match_response(http_res, "502", "application/json"): + response_data = unmarshal_json_response( + errors.BadGatewayResponseErrorData, http_res + ) + raise errors.BadGatewayResponseError(response_data, http_res) + if utils.match_response(http_res, "503", "application/json"): + response_data = unmarshal_json_response( + errors.ServiceUnavailableResponseErrorData, http_res + ) + raise errors.ServiceUnavailableResponseError(response_data, http_res) + if utils.match_response(http_res, "524", "application/json"): + response_data = unmarshal_json_response( + errors.EdgeNetworkTimeoutResponseErrorData, http_res + ) + raise errors.EdgeNetworkTimeoutResponseError(response_data, http_res) + if utils.match_response(http_res, "529", "application/json"): + response_data = unmarshal_json_response( + errors.ProviderOverloadedResponseErrorData, http_res + ) + raise errors.ProviderOverloadedResponseError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.OpenRouterDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.OpenRouterDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.OpenRouterDefaultError("Unexpected response received", http_res) + + async def create_async( + self, + *, + model: str, + questions: Union[ + Mapping[str, components.Questions], + Mapping[str, components.QuestionsTypedDict], + ], + state: Union[components.State, components.StateTypedDict], + http_referer: Optional[str] = None, + x_open_router_title: Optional[str] = None, + x_open_router_categories: Optional[str] = None, + provider: OptionalNullable[ + Union[ + components.ProviderPreferences, components.ProviderPreferencesTypedDict + ] + ] = UNSET, + session_id: Optional[str] = None, + trace: Optional[ + Union[components.TraceConfig, components.TraceConfigTypedDict] + ] = None, + user: Optional[str] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> components.DecisionsResponse: + r"""Submit a System One request + + Sends state and typed questions to a System One model such as Jev and returns its answers. Compatible with the TypeSafe SDKs. Bare System One model IDs such as `jev-1.13` and `jev-latest` are mapped onto the `typesafe/` namespace. + + :param model: + :param questions: + :param state: The content to evaluate: a plain string, or a JSON object or array of related context. + :param http_referer: 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. + + :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard. + + :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. + + :param provider: + :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. + :param trace: 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. + :param user: + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = operations.CreateSystemoneRequest( + http_referer=http_referer, + x_open_router_title=x_open_router_title, + x_open_router_categories=x_open_router_categories, + decisions_request=components.DecisionsRequest( + model=model, + provider=utils.get_pydantic_model( + provider, OptionalNullable[components.ProviderPreferences] + ), + questions=utils.get_pydantic_model( + questions, Dict[str, components.Questions] + ), + session_id=session_id, + state=utils.unmarshal(state, components.State), + trace=utils.get_pydantic_model(trace, Optional[components.TraceConfig]), + user=user, + ), + ) + + req = self._build_request_async( + method="POST", + path="/systemone", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + _globals=operations.CreateSystemoneGlobals( + http_referer=self.sdk_configuration.globals.http_referer, + x_open_router_title=self.sdk_configuration.globals.x_open_router_title, + x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories, + ), + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.decisions_request, + False, + False, + "json", + components.DecisionsRequest, + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + else: + retries = utils.RetryConfig( + "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True + ) + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["5XX"]) + + http_res = await self.do_request_async( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="createSystemone", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, components.Security + ), + tags=["SystemOne"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(components.DecisionsResponse, http_res) + if utils.match_response(http_res, "400", "application/json"): + response_data = unmarshal_json_response( + errors.BadRequestResponseErrorData, http_res + ) + raise errors.BadRequestResponseError(response_data, http_res) + if utils.match_response(http_res, "401", "application/json"): + response_data = unmarshal_json_response( + errors.UnauthorizedResponseErrorData, http_res + ) + raise errors.UnauthorizedResponseError(response_data, http_res) + if utils.match_response(http_res, "402", "application/json"): + response_data = unmarshal_json_response( + errors.PaymentRequiredResponseErrorData, http_res + ) + raise errors.PaymentRequiredResponseError(response_data, http_res) + if utils.match_response(http_res, "403", "application/json"): + response_data = unmarshal_json_response( + errors.ForbiddenResponseErrorData, http_res + ) + raise errors.ForbiddenResponseError(response_data, http_res) + if utils.match_response(http_res, "404", "application/json"): + response_data = unmarshal_json_response( + errors.NotFoundResponseErrorData, http_res + ) + raise errors.NotFoundResponseError(response_data, http_res) + if utils.match_response(http_res, "413", "application/json"): + response_data = unmarshal_json_response( + errors.PayloadTooLargeResponseErrorData, http_res + ) + raise errors.PayloadTooLargeResponseError(response_data, http_res) + if utils.match_response(http_res, "429", "application/json"): + response_data = unmarshal_json_response( + errors.TooManyRequestsResponseErrorData, http_res + ) + raise errors.TooManyRequestsResponseError(response_data, http_res) + if utils.match_response(http_res, "500", "application/json"): + response_data = unmarshal_json_response( + errors.InternalServerResponseErrorData, http_res + ) + raise errors.InternalServerResponseError(response_data, http_res) + if utils.match_response(http_res, "502", "application/json"): + response_data = unmarshal_json_response( + errors.BadGatewayResponseErrorData, http_res + ) + raise errors.BadGatewayResponseError(response_data, http_res) + if utils.match_response(http_res, "503", "application/json"): + response_data = unmarshal_json_response( + errors.ServiceUnavailableResponseErrorData, http_res + ) + raise errors.ServiceUnavailableResponseError(response_data, http_res) + if utils.match_response(http_res, "524", "application/json"): + response_data = unmarshal_json_response( + errors.EdgeNetworkTimeoutResponseErrorData, http_res + ) + raise errors.EdgeNetworkTimeoutResponseError(response_data, http_res) + if utils.match_response(http_res, "529", "application/json"): + response_data = unmarshal_json_response( + errors.ProviderOverloadedResponseErrorData, http_res + ) + raise errors.ProviderOverloadedResponseError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.OpenRouterDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.OpenRouterDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.OpenRouterDefaultError("Unexpected response received", http_res) diff --git a/uv.lock b/uv.lock index aeb95892..46c838ee 100644 --- a/uv.lock +++ b/uv.lock @@ -213,7 +213,7 @@ wheels = [ [[package]] name = "openrouter" -version = "1.2.7" +version = "1.2.8" source = { editable = "." } dependencies = [ { name = "httpcore" }, From fe653febf5c9df34de25eeb781fea72b3c615480 Mon Sep 17 00:00:00 2001 From: "speakeasy-github[bot]" <128539517+speakeasy-github[bot]@users.noreply.github.com> Date: Sun, 20 Sep 2026 04:45:32 +0000 Subject: [PATCH 2/3] empty commit to trigger [run-tests] workflow From 620cf88eeccf2e07ca61735c078abc32803a6104 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 20 Sep 2026 04:45:43 +0000 Subject: [PATCH 3/3] Chore: regenerate docs navigation Auto-generated-by: update-generated-files-action; https://github.com/OpenRouterTeam/python-sdk/actions/runs/35489946996 --- docs/docs.json | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs.json b/docs/docs.json index 3d453249..d7a03593 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -38,6 +38,7 @@ "sdks/responses/README", "sdks/scim/README", "sdks/stt/README", + "sdks/systemone/README", "sdks/tts/README", "sdks/vault/README", "sdks/videogeneration/README",