diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 4fb69ee4..eda56587 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: 30567c425d240802631762506228f8ef + docChecksum: 0b6a4f9f718f46a6b9f1c42f66c7c30d docVersion: 1.0.0 speakeasyVersion: 1.803.2 generationVersion: 2.950.13 - releaseVersion: 1.3.171 - configChecksum: ddb32bd4e2b8a710a5724c95f74c9178 + releaseVersion: 1.3.172 + configChecksum: 96e13e4cf0f1fa887bacdd39a5d0d076 repoURL: https://github.com/OpenRouterTeam/python-sdk.git installationURL: https://github.com/OpenRouterTeam/python-sdk.git published: true persistentEdits: - generation_id: 8f603718-2d74-46a4-8de3-253f2cbea57d - pristine_commit_hash: eb79adce5125c82f470d162346517bb4969878a2 - pristine_tree_hash: 414af1b5eb147165659d5fe3d63d08256f91be78 + generation_id: 44a2bbd7-6f29-454d-bccc-fedc6448e62e + pristine_commit_hash: 630e03187bf7df7f5e8d5d6160ec96523df8ccf0 + pristine_tree_hash: b0db7e32f346d6660cf37c9ce78472d7711f6af8 features: python: acceptHeaders: 3.0.0 @@ -2618,6 +2618,10 @@ trackedFiles: id: e5d65035c6cb last_write_checksum: sha1:ea5a9c809cbb6200745c7cfb66c90cfbb08cece1 pristine_git_object: 3c403ebfaf37d008ac6ea149c251b7290ff42301 + docs/components/contentfilterreadentry.mdx: + id: 5a8e6c4e402e + last_write_checksum: sha1:cb4e732270307966fc119d309372c04c85d16453 + pristine_git_object: e76e781ebe9c10107d7981baa5ba49cbdc815421 docs/components/contentimageurl.mdx: id: 4092a59d86b4 last_write_checksum: sha1:41a45a0483695585f05fbe1a4c7819ae8eba928f @@ -4212,8 +4216,8 @@ trackedFiles: pristine_git_object: 6e17644dffb3aef799758f46d5ac781114b58c1f docs/components/guardrail.mdx: id: 91791d4c83b6 - last_write_checksum: sha1:d1adf8ad6b61dbed5a1114202791c934a3db6632 - pristine_git_object: 9095f97d749034bcce9ba14d22122a727e7db21b + last_write_checksum: sha1:0d3052ca5606284b1b009b793e0c6c29caa0725b + pristine_git_object: 16a5de46fe7d071a2cd7ee2914a6e6a9ee9967ae docs/components/guardrailbudgetpolicyauthoringconfig.mdx: id: 9e5753c7f2e8 last_write_checksum: sha1:c1527680bab858136a3ceb69966af7aab285636b @@ -11632,8 +11636,8 @@ trackedFiles: pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544 pyproject.toml: id: 5d07e7d72637 - last_write_checksum: sha1:1fedb72c7a7746bc6820bfc15d27da4668a25d38 - pristine_git_object: d5e097456fcbe579ec290d83033603e77b733dd9 + last_write_checksum: sha1:bae5be3f485ba7126e93649fc8ca83d9c76b96a8 + pristine_git_object: 10294129d7ad0e29ff4ec5c11700dd0b91104ece scripts/prepare_readme.py: id: e0c5957a6035 last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54 @@ -11660,8 +11664,8 @@ trackedFiles: pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137 src/openrouter/_version.py: id: d8d15ad6c586 - last_write_checksum: sha1:54a93a3b40a308a571cbb926dd7a4340c573ded4 - pristine_git_object: 015b9fc84d77cd77a66356cfe7b8fb05de0931a3 + last_write_checksum: sha1:cc55eb6ad7c80e6c3d3a905686f96ad39415d077 + pristine_git_object: 3a4ea3ee2c7b9e6290ea23ddfd3a3e51dfcc3d24 src/openrouter/alpha.py: id: 306c4d93308d last_write_checksum: sha1:80cc0f39649445431cc2247ed0e0765438467766 @@ -11708,8 +11712,8 @@ trackedFiles: pristine_git_object: ad3d247954547814054c01989a2dff3d12b3e4e1 src/openrouter/components/__init__.py: id: 81754e97b3f4 - last_write_checksum: sha1:1e5e989da812bce6bb2832f209b3dd4072ca253b - pristine_git_object: 0f5c732d00c70b143a6ddf64bd045eceb9546cff + last_write_checksum: sha1:43b8464cd93aff7843b793ccdc334cdeda04755a + pristine_git_object: cfdfb3cf4efc0e170e3a60b747656228ea906135 src/openrouter/components/aabenchmarkentry.py: id: e2e0f0b48c82 last_write_checksum: sha1:fab4d9a24d2cea937bb749d46c5f83941e99d65c @@ -12814,6 +12818,10 @@ trackedFiles: id: 149ebe184f88 last_write_checksum: sha1:63dcb28479bc328253a4d102a6c191fa0e515394 pristine_git_object: 882178bfe6217c6cf9947ca1ce9fe67d07830262 + src/openrouter/components/contentfilterreadentry.py: + id: 9fb39b4a7350 + last_write_checksum: sha1:9e169db041e977fe6b42c313991d3fecfd488fac + pristine_git_object: 3a227dba2a7c5c7fd802bf354977f8c9aeb7b544 src/openrouter/components/contentpartaddedevent.py: id: a074d4f3e193 last_write_checksum: sha1:ce0fc4800d5dae3328f0185add65758d149c5d4a @@ -13452,8 +13460,8 @@ trackedFiles: pristine_git_object: 1268e32c9058ed4feb7482458a64366c56201676 src/openrouter/components/guardrail.py: id: 67ee78dd06e6 - last_write_checksum: sha1:246d44cd9b211dcd23614df71505b79b2677125a - pristine_git_object: 252b329019216d0cc8d4c7568edfc0d9c91968fe + last_write_checksum: sha1:71dd7b2bc5afd3708209661a3dbd936db4840251 + pristine_git_object: 1d5e7be619427a95bc598364fed9810cf8e17596 src/openrouter/components/guardrailbudgetpolicyauthoringconfig.py: id: 3011896fdeb5 last_write_checksum: sha1:604d6ec6906a391e0ce81e315ec077ab17e081a9 @@ -21641,3 +21649,9 @@ examples: "500": application/json: {"error": {"code": 500, "message": "Internal Server Error"}} examplesVersion: 1.0.2 +releaseNotes: | + ## Python SDK Changes: + * `open_router.guardrails.list()`: `response.data[].content_filters[].is_enforced` **Added** + * `open_router.guardrails.create()`: `response.data.content_filters[].is_enforced` **Added** + * `open_router.guardrails.get()`: `response.data.content_filters[].is_enforced` **Added** + * `open_router.guardrails.update()`: `response.data.content_filters[].is_enforced` **Added** diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index 682f7c89..bc373b83 100644 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -37,7 +37,7 @@ generation: documentation: mintlify preApplyUnionDiscriminators: true python: - version: 1.3.171 + version: 1.3.172 additionalDependencies: dev: pytest: '>=8.3' diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml index 3e8387c4..2160b4f7 100644 --- a/.speakeasy/out.openapi.yaml +++ b/.speakeasy/out.openapi.yaml @@ -10200,6 +10200,23 @@ components: - 'pattern' - 'action' type: 'object' + ContentFilterReadEntry: + allOf: + - $ref: '#/components/schemas/ContentFilterEntry' + - properties: + is_enforced: + description: 'Whether inference applies this pattern. False for a pattern saved before pattern validation that is too complex to run safely; it is kept but skipped until replaced.' + example: true + type: 'boolean' + required: + - 'is_enforced' + type: 'object' + description: 'A custom regex content filter, with whether inference enforces it.' + example: + action: 'redact' + is_enforced: true + label: '[API_KEY]' + pattern: '\b(sk-[a-zA-Z0-9]{48})\b' ContentPartAddedEvent: allOf: - $ref: '#/components/schemas/BaseContentPartAddedEvent' @@ -15962,10 +15979,11 @@ components: description: 'Custom regex content filters applied to request messages' example: - action: 'redact' + is_enforced: true label: '[API_KEY]' pattern: '\b(sk-[a-zA-Z0-9]{48})\b' items: - $ref: '#/components/schemas/ContentFilterEntry' + $ref: '#/components/schemas/ContentFilterReadEntry' type: - 'array' - 'null' diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 4027b906..4741b64d 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -2,8 +2,8 @@ speakeasyVersion: 1.803.2 sources: OpenRouter API: sourceNamespace: open-router-chat-completions-api - sourceRevisionDigest: sha256:2da9790d04eb9873088b59c89e7456494fc51041d339e057428ccf326dabe8e5 - sourceBlobDigest: sha256:fe041198672377cdbae02cfb2a1342e1d96dc5de89fb2338946809ade321fea6 + sourceRevisionDigest: sha256:aaea7962bb250e48c30aef0665e01972f79cf4b7b5f808aafca88ea64dae0b64 + sourceBlobDigest: sha256:22a0a735520200446a3deb7951eedee023d6bf24365011fd80670fa3b6cad6bb tags: - latest - 1.0.0 @@ -11,10 +11,10 @@ targets: open-router: source: OpenRouter API sourceNamespace: open-router-chat-completions-api - sourceRevisionDigest: sha256:2da9790d04eb9873088b59c89e7456494fc51041d339e057428ccf326dabe8e5 - sourceBlobDigest: sha256:fe041198672377cdbae02cfb2a1342e1d96dc5de89fb2338946809ade321fea6 + sourceRevisionDigest: sha256:aaea7962bb250e48c30aef0665e01972f79cf4b7b5f808aafca88ea64dae0b64 + sourceBlobDigest: sha256:22a0a735520200446a3deb7951eedee023d6bf24365011fd80670fa3b6cad6bb codeSamplesNamespace: open-router-python-code-samples - codeSamplesRevisionDigest: sha256:b23baa9166ec8ee272754fd101966676f619c29ab42423aafeae165f44f8f35e + codeSamplesRevisionDigest: sha256:302a2a067b3442735f68158a236dc28ac6b70785bb6560e902e620641c91eeb1 workflow: workflowVersion: 1.0.0 speakeasyVersion: 1.803.2 diff --git a/RELEASES.md b/RELEASES.md index c0a08182..5074b4c3 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -4479,4 +4479,14 @@ Based on: ### Generated - [python v1.3.171] . ### Releases -- [PyPI v1.3.171] https://pypi.org/project/openrouter/1.3.171 - . \ No newline at end of file +- [PyPI v1.3.171] https://pypi.org/project/openrouter/1.3.171 - . + +## 2026-11-12 19:40:35 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.803.2 (2.950.13) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v1.3.172] . +### Releases +- [PyPI v1.3.172] https://pypi.org/project/openrouter/1.3.172 - . \ No newline at end of file diff --git a/docs/components/contentfilterreadentry.mdx b/docs/components/contentfilterreadentry.mdx new file mode 100644 index 00000000..e76e781e --- /dev/null +++ b/docs/components/contentfilterreadentry.mdx @@ -0,0 +1,15 @@ +--- +title: "ContentFilterReadEntry" +--- + +A custom regex content filter, with whether inference enforces it. + + +## Fields + +| Field | Type | Required | Description | Example | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `action` | [components.ContentFilterAction](../components/contentfilteraction.mdx) | ✔️ | Action taken when the pattern matches | block | +| `label` | *OptionalNullable[str]* | ➖ | Optional label used in redaction placeholders or error messages | [API_KEY] | +| `pattern` | *str* | ✔️ | A regex pattern to match against request content | \b(sk-[a-zA-Z0-9]\{48})\b | +| `is_enforced` | *bool* | ✔️ | Whether inference applies this pattern. False for a pattern saved before pattern validation that is too complex to run safely; it is kept but skipped until replaced. | true | \ No newline at end of file diff --git a/docs/components/guardrail.mdx b/docs/components/guardrail.mdx index 9095f97d..16a5de46 100644 --- a/docs/components/guardrail.mdx +++ b/docs/components/guardrail.mdx @@ -12,7 +12,7 @@ title: "Guardrail" | `allowed_models` | List[*str*] | ➖ | Array of model canonical_slugs (immutable identifiers) | [
"openai/gpt-5.2-20251211",
"anthropic/claude-4.5-opus-20251124",
"deepseek/deepseek-r1-0528:free"
] | | `allowed_providers` | List[*str*] | ➖ | List of allowed provider IDs | [
"openai",
"anthropic",
"google"
] | | `content_filter_builtins` | List[[components.ContentFilterBuiltinEntry](../components/contentfilterbuiltinentry.mdx)] | ➖ | Builtin content filters applied to requests. Includes PII detectors and the regex-based prompt injection detector. | [
\{
"action": "redact",
"label": "[EMAIL]",
"slug": "email"
}
] | -| `content_filters` | List[[components.ContentFilterEntry](../components/contentfilterentry.mdx)] | ➖ | Custom regex content filters applied to request messages | [
\{
"action": "redact",
"label": "[API_KEY]",
"pattern": "\\b(sk-[a-zA-Z0-9]\{48})\\b"
}
] | +| `content_filters` | List[[components.ContentFilterReadEntry](../components/contentfilterreadentry.mdx)] | ➖ | Custom regex content filters applied to request messages | [
\{
"action": "redact",
"is_enforced": true,
"label": "[API_KEY]",
"pattern": "\\b(sk-[a-zA-Z0-9]\{48})\\b"
}
] | | `created_at` | *str* | ✔️ | ISO 8601 timestamp of when the guardrail was created | 2025-08-24T10:30:00Z | | `description` | *OptionalNullable[str]* | ➖ | Description of the guardrail | Guardrail for production environment | | `enable_free_model_publication` | *OptionalNullable[bool]* | ➖ | Whether this guardrail allows free endpoints that publish prompts. | false | diff --git a/pyproject.toml b/pyproject.toml index d5e09745..10294129 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openrouter" -version = "1.3.171" +version = "1.3.172" 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 015b9fc8..3a4ea3ee 100644 --- a/src/openrouter/_version.py +++ b/src/openrouter/_version.py @@ -3,10 +3,10 @@ import importlib.metadata __title__: str = "openrouter" -__version__: str = "1.3.171" +__version__: str = "1.3.172" __openapi_doc_version__: str = "1.0.0" __gen_version__: str = "2.950.13" -__user_agent__: str = "speakeasy-sdk/python 1.3.171 2.950.13 1.0.0 openrouter" +__user_agent__: str = "speakeasy-sdk/python 1.3.172 2.950.13 1.0.0 openrouter" try: if __package__ is not None: diff --git a/src/openrouter/components/__init__.py b/src/openrouter/components/__init__.py index 0f5c732d..cfdfb3cf 100644 --- a/src/openrouter/components/__init__.py +++ b/src/openrouter/components/__init__.py @@ -1503,6 +1503,10 @@ ) from .contentfilterbuiltinslug import ContentFilterBuiltinSlug from .contentfilterentry import ContentFilterEntry, ContentFilterEntryTypedDict + from .contentfilterreadentry import ( + ContentFilterReadEntry, + ContentFilterReadEntryTypedDict, + ) from .contentpartaddedevent import ( ContentPartAddedEvent, ContentPartAddedEventPart, @@ -6092,6 +6096,8 @@ "ContentFilterBuiltinTypedDict", "ContentFilterEntry", "ContentFilterEntryTypedDict", + "ContentFilterReadEntry", + "ContentFilterReadEntryTypedDict", "ContentFilterTypedDict", "ContentImageURL", "ContentImageURLImageURL", @@ -9888,6 +9894,8 @@ "ContentFilterBuiltinSlug": ".contentfilterbuiltinslug", "ContentFilterEntry": ".contentfilterentry", "ContentFilterEntryTypedDict": ".contentfilterentry", + "ContentFilterReadEntry": ".contentfilterreadentry", + "ContentFilterReadEntryTypedDict": ".contentfilterreadentry", "ContentPartAddedEvent": ".contentpartaddedevent", "ContentPartAddedEventPart": ".contentpartaddedevent", "ContentPartAddedEventPartTypedDict": ".contentpartaddedevent", diff --git a/src/openrouter/components/contentfilterreadentry.py b/src/openrouter/components/contentfilterreadentry.py new file mode 100644 index 00000000..3a227dba --- /dev/null +++ b/src/openrouter/components/contentfilterreadentry.py @@ -0,0 +1,67 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .contentfilteraction import ContentFilterAction +from openrouter.types import ( + BaseModel, + Nullable, + OptionalNullable, + UNSET, + UNSET_SENTINEL, +) +from pydantic import model_serializer +from typing_extensions import NotRequired, TypedDict + + +class ContentFilterReadEntryTypedDict(TypedDict): + r"""A custom regex content filter, with whether inference enforces it.""" + + action: ContentFilterAction + r"""Action taken when the pattern matches""" + pattern: str + r"""A regex pattern to match against request content""" + is_enforced: bool + r"""Whether inference applies this pattern. False for a pattern saved before pattern validation that is too complex to run safely; it is kept but skipped until replaced.""" + label: NotRequired[Nullable[str]] + r"""Optional label used in redaction placeholders or error messages""" + + +class ContentFilterReadEntry(BaseModel): + r"""A custom regex content filter, with whether inference enforces it.""" + + action: ContentFilterAction + r"""Action taken when the pattern matches""" + + pattern: str + r"""A regex pattern to match against request content""" + + is_enforced: bool + r"""Whether inference applies this pattern. False for a pattern saved before pattern validation that is too complex to run safely; it is kept but skipped until replaced.""" + + label: OptionalNullable[str] = UNSET + r"""Optional label used in redaction placeholders or error messages""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["label"]) + nullable_fields = set(["label"]) + 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)) + is_nullable_and_explicitly_set = ( + k in nullable_fields + and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member + ) + + if val != UNSET_SENTINEL: + if ( + val is not None + or k not in optional_fields + or is_nullable_and_explicitly_set + ): + m[k] = val + + return m diff --git a/src/openrouter/components/guardrail.py b/src/openrouter/components/guardrail.py index 252b3290..1d5e7be6 100644 --- a/src/openrouter/components/guardrail.py +++ b/src/openrouter/components/guardrail.py @@ -5,7 +5,10 @@ ContentFilterBuiltinEntry, ContentFilterBuiltinEntryTypedDict, ) -from .contentfilterentry import ContentFilterEntry, ContentFilterEntryTypedDict +from .contentfilterreadentry import ( + ContentFilterReadEntry, + ContentFilterReadEntryTypedDict, +) from .guardraildataregion import GuardrailDataRegion from .guardrailinterval import GuardrailInterval from openrouter.types import ( @@ -46,7 +49,7 @@ class GuardrailTypedDict(TypedDict): Nullable[List[ContentFilterBuiltinEntryTypedDict]] ] r"""Builtin content filters applied to requests. Includes PII detectors and the regex-based prompt injection detector.""" - content_filters: NotRequired[Nullable[List[ContentFilterEntryTypedDict]]] + content_filters: NotRequired[Nullable[List[ContentFilterReadEntryTypedDict]]] r"""Custom regex content filters applied to request messages""" description: NotRequired[Nullable[str]] r"""Description of the guardrail""" @@ -116,7 +119,7 @@ class Guardrail(BaseModel): content_filter_builtins: OptionalNullable[List[ContentFilterBuiltinEntry]] = UNSET r"""Builtin content filters applied to requests. Includes PII detectors and the regex-based prompt injection detector.""" - content_filters: OptionalNullable[List[ContentFilterEntry]] = UNSET + content_filters: OptionalNullable[List[ContentFilterReadEntry]] = UNSET r"""Custom regex content filters applied to request messages""" description: OptionalNullable[str] = UNSET diff --git a/uv.lock b/uv.lock index 72c34a41..ffd45e16 100644 --- a/uv.lock +++ b/uv.lock @@ -231,7 +231,7 @@ wheels = [ [[package]] name = "openrouter" -version = "1.3.171" +version = "1.3.172" source = { editable = "." } dependencies = [ { name = "httpcore" },