Skip to content

chore: 🐝 Update SDK - Generate 0.10.1#357

Closed
github-actions[bot] wants to merge 2 commits into
mainfrom
speakeasy-sdk-regen-1782262991
Closed

chore: 🐝 Update SDK - Generate 0.10.1#357
github-actions[bot] wants to merge 2 commits into
mainfrom
speakeasy-sdk-regen-1782262991

Conversation

@github-actions

@github-actions github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

SDK update

Versioning

Version Bump Type: [patch] - 🤖 (automated)

Tip

If updates to your OpenAPI document introduce breaking changes, be sure to update the info.version field to trigger the correct version bump.
Speakeasy supports manual control of SDK versioning through multiple methods.

Python SDK Changes:

  • open_router.beta.responses.send():
    • request Changed
    • response Changed Breaking ⚠️
  • open_router.tts.create_speech():
    • request.provider.options Changed
  • open_router.chat.send(): response Changed
  • open_router.images.list_models(): Added
  • open_router.images.list_model_endpoints(): Added
  • open_router.datasets.get_benchmarks_artificial_analysis(): Deleted Breaking ⚠️
  • open_router.datasets.get_benchmarks_design_arena(): Deleted Breaking ⚠️
  • open_router.classifications.get_task_classifications(): Added
  • open_router.benchmarks.get_benchmarks(): Added
  • open_router.images.generate(): Added
  • open_router.stt.create_transcription():
    • request.provider.options Changed
  • open_router.byok.list(): request.provider Changed
  • open_router.embeddings.generate(): response.usage Changed
  • open_router.embeddings.list_models(): response.data.[].reasoning Added
  • open_router.models.get(): response.data.reasoning Added
  • open_router.models.list():
    • request.sort Changed
    • response.data.[].reasoning Added
  • open_router.models.list_for_user(): response.data.[].reasoning Added
  • open_router.presets.create_presets_responses(): request Changed
  • open_router.video_generation.generate():
    • request.provider.options Changed
OpenAPI Change Summary
├─┬Paths
│ ├──[-] path (24140:5)❌ 
│ ├──[-] path (24052:5)❌ 
│ ├──[+] path (24908:3)
│ ├──[+] path (27984:3)
│ ├──[+] path (28034:3)
│ ├──[+] path (27838:3)
│ ├──[+] path (24021:3)
│ ├─┬/models
│ │ └─┬GET
│ │   ├─┬Parameters
│ │   │ ├──[🔀] description (29961:24)
│ │   │ └─┬Schema
│ │   │   ├──[+] enum (29979:17)
│ │   │   ├──[+] enum (29978:17)
│ │   │   └──[🔀] description (29967:26)
│ │   └─┬Responses
│ │     └─┬200
│ │       └─┬application/json
│ │         └──[🔀] example (30090:17)
│ ├─┬/embeddings
│ │ └─┬POST
│ │   └─┬Responses
│ │     └─┬200
│ │       └─┬application/json
│ │         └─┬Schema
│ │           └─┬usage
│ │             ├──[+] properties (25653:23)
│ │             ├──[+] properties (25675:23)
│ │             ├─┬prompt_tokens
│ │             │ ├──[+] required (25672:29)❌ 
│ │             │ ├──[+] required (25673:29)❌ 
│ │             │ ├──[🔀] type (25674:31)❌ 
│ │             │ ├──[🔀] description (25654:38)
│ │             │ ├──[+] nullable (25659:35)❌ 
│ │             │ ├──[🔀] example (25656:27)
│ │             │ ├──[+] properties (25661:27)
│ │             │ ├──[+] properties (25664:27)
│ │             │ └──[+] properties (25668:27)
│ │             ├─┬total_tokens
│ │             │ └──[🔀] description (25679:38)
│ │             └─┬prompt_tokens_details
│ │               ├──[🔀] type (25677:31)❌ 
│ │               ├──[🔀] description (25676:38)
│ │               ├──[-] properties (24580:53)❌ 
│ │               ├──[-] properties (24583:53)❌ 
│ │               ├──[-] properties (24586:53)❌ 
│ │               ├──[-] properties (24590:53)❌ 
│ │               └──[-] properties (24594:53)❌ 
│ └─┬/byok
│   └─┬GET
│     └─┬Parameters
│       └─┬Schema
│         ├──[+] enum (24242:17)
│         ├──[+] enum (24273:17)
│         ├──[+] enum (24239:17)
│         └──[+] enum (24281:17)
├─┬Tags
│ └──[+] Benchmarks (34064:5)
├─┬Tags
│ └──[+] Classifications (34068:5)
├─┬Tags
│ └──[+] Images (34084:5)
└─┬Components
  ├──[-] schemas (3712:13)❌ 
  ├──[-] schemas (3646:13)❌ 
  ├──[-] schemas (3784:13)❌ 
  ├──[-] schemas (3665:13)❌ 
  ├──[-] schemas (3874:13)❌ 
  ├──[+] schemas (9560:7)
  ├──[-] schemas (3947:13)❌ 
  ├──[-] schemas (3755:13)❌ 
  ├──[+] schemas (9748:7)
  ├──[+] schemas (9888:7)
  ├──[+] schemas (9663:7)
  ├──[+] schemas (21400:7)
  ├──[+] schemas (12869:7)
  ├──[+] schemas (6971:7)
  ├──[+] schemas (9875:7)
  ├──[+] schemas (21194:7)
  ├──[+] schemas (2207:7)
  ├──[+] schemas (20849:7)
  ├──[+] schemas (20730:7)
  ├──[+] schemas (21175:7)
  ├──[+] schemas (20749:7)
  ├──[+] schemas (21248:7)
  ├──[+] schemas (3684:7)
  ├──[+] schemas (9405:7)
  ├──[+] schemas (20876:7)
  ├──[+] schemas (9845:7)
  ├──[+] schemas (20818:7)
  ├──[+] schemas (9726:7)
  ├──[+] schemas (7272:7)
  ├──[+] schemas (9139:7)
  ├──[+] schemas (18967:7)
  ├──[+] schemas (21344:7)
  ├──[+] schemas (4070:7)
  ├──[+] schemas (9252:7)
  ├──[+] schemas (9282:7)
  ├──[+] schemas (9782:7)
  ├──[+] schemas (9921:7)
  ├──[+] schemas (9686:7)
  ├─┬FusionServerToolConfig
  │ ├──[+] properties (8291:9)
  │ ├─┬tools
  │ │ ├──[-] items (8511:25)❌ 
  │ │ ├──[🔀] type (8336:17)❌ 
  │ │ ├──[+] format (8335:19)❌ 
  │ │ ├──[-] maxItems (8523:31)❌ 
  │ │ ├──[🔀] description (8332:24)
  │ │ └──[🔀] example (8334:20)
  │ ├─┬max_completion_tokens
  │ │ └──[🔀] $ref (509:20)❌ 
  │ ├─┬temperature
  │ │ └──[🔀] description (8332:24)
  │ ├─┬max_tool_calls
  │ │ ├──[-] maximum (8467:30)❌ 
  │ │ ├──[-] minimum (8468:30)❌ 
  │ │ ├──[🔀] description (8294:24)
  │ │ └──[🔀] example (8296:20)
  │ ├─┬model
  │ │ ├──[🔀] type (8304:17)❌ 
  │ │ ├──[+] maximum (8302:20)❌ 
  │ │ ├──[+] minimum (8303:20)❌ 
  │ │ ├──[🔀] description (8299:24)
  │ │ └──[🔀] example (8301:20)
  │ └─┬reasoning
  │   └─┬effort
  │     └──[+] enum (8317:19)
  ├─┬ChatRequest
  │ ├─┬reasoning_effort
  │ │ └──[+] enum (4833:15)
  │ └─┬reasoning
  │   └─┬effort
  │     └──[+] enum (4814:19)
  ├─┬ProviderName
  │ ├──[+] enum (17801:11)
  │ ├──[+] enum (17835:11)
  │ ├──[+] enum (17808:11)
  │ └──[+] enum (17844:11)
  ├─┬MessagesErrorEvent
  │ ├──[🔀] example (11496:9)
  │ ├──[+] properties (11514:9)
  │ ├─┬type
  │ │ └──[🔀] $ref (15638:9)❌ 
  │ └─┬error
  │   ├──[+] properties (11504:13)
  │   └─┬message
  │     └──[🔀] $ref (2207:20)❌ 
  ├─┬FusionPlugin
  │ └─┬preset
  │   └──[+] enum (8197:15)
  ├─┬ChatUsage
  │ ├──[🔀] example (5467:9)
  │ ├──[+] properties (5538:9)
  │ └─┬total_tokens
  │   ├──[🔀] type (5556:17)❌ 
  │   ├──[🔀] description (5539:24)
  │   ├──[+] nullable (5540:21)❌ 
  │   ├──[+] properties (5542:13)
  │   ├──[+] properties (5546:13)
  │   └──[+] properties (5551:13)
  ├─┬ProviderResponse
  │ └─┬provider_name
  │   ├──[+] enum (18643:15)
  │   ├──[+] enum (18609:15)
  │   ├──[+] enum (18616:15)
  │   └──[+] enum (18652:15)
  ├─┬ResponsesRequest
  │ ├──[+] properties (19567:9)
  │ ├─┬plugins
  │ │ ├──[-] items (19038:25)❌ 
  │ │ ├──[🔀] type (19609:17)❌ 
  │ │ ├──[-] description (19036:34)
  │ │ └──[+] nullable (19608:21)❌ 
  │ ├─┬provider
  │ │ └──[🔀] $ref (19646:11)❌ 
  │ ├─┬modalities
  │ │ └──[🔀] $ref (19372:9)❌ 
  │ ├─┬safety_identifier
  │ │ └──[🔀] $ref (7114:19)❌ 
  │ ├─┬top_logprobs
  │ │ └──[-] nullable (19170:31)❌ 
  │ ├─┬reasoning
  │ │ └──[🔀] $ref (18381:29)❌ 
  │ ├─┬parallel_tool_calls
  │ │ ├──[+] items (19605:13)❌ 
  │ │ ├──[🔀] type (19606:17)❌ 
  │ │ └──[-] nullable (19033:31)❌ 
  │ ├─┬store
  │ │ └──[🔀] $ref (20123:20)❌ 
  │ ├─┬tools
  │ │ └──[🔀] $ref (15342:9)❌ 
  │ ├─┬include
  │ │ └──[🔀] $ref (9125:9)❌ 
  │ ├─┬trace
  │ │ └──[🔀] $ref (19748:11)❌ 
  │ ├─┬previous_response_id
  │ │ ├──[🔀] type (19639:17)❌ 
  │ │ └──[+] format (19637:19)❌ 
  │ ├─┬models
  │ │ ├──[-] items (19030:25)❌ 
  │ │ └──[🔀] type (19602:17)❌ 
  │ ├─┬text
  │ │ └──[🔀] $ref (19684:11)❌ 
  │ ├─┬stop_server_tools_when
  │ │ └──[🔀] $ref (19670:11)❌ 
  │ ├─┬frequency_penalty
  │ │ └──[🔀] $ref (4362:20)❌ 
  │ ├─┬session_id
  │ │ ├──[+] enum (19661:15)
  │ │ ├──[+] enum (19662:15)
  │ │ ├──[+] enum (19663:15)
  │ │ ├──[+] enum (19664:15)
  │ │ ├──[+] enum (19665:15)
  │ │ ├──[+] enum (19660:15)
  │ │ ├──[-] maxLength (19097:32)❌ 
  │ │ ├──[-] description (19095:34)
  │ │ ├──[+] default (19658:20)❌ 
  │ │ ├──[+] nullable (19666:21)❌ 
  │ │ └─┬Extensions
  │ │   └──[+] x-speakeasy-unknown-values (19668:39)
  │ ├─┬service_tier
  │ │ ├──[-] enum (19085:27)❌ 
  │ │ ├──[-] enum (19086:27)❌ 
  │ │ ├──[-] enum (19087:27)❌ 
  │ │ ├──[-] enum (19088:27)❌ 
  │ │ ├──[-] enum (19089:27)❌ 
  │ │ ├──[-] enum (19090:27)❌ 
  │ │ ├──[-] default (19083:30)❌ 
  │ │ └─┬Extensions
  │ │   └──[-] x-speakeasy-unknown-values (19093:49)❌ 
  │ ├─┬image_config
  │ │ └──[🔀] $ref (19570:11)❌ 
  │ ├─┬metadata
  │ │ └──[🔀] $ref (19589:11)❌ 
  │ ├─┬stream
  │ │ └──[+] const (19677:18)❌ 
  │ ├─┬top_k
  │ │ ├──[+] items (19693:13)❌ 
  │ │ └──[🔀] type (19741:17)❌ 
  │ ├─┬max_output_tokens
  │ │ └──[🔀] type (19584:17)❌ 
  │ ├─┬tool_choice
  │ │ └──[🔀] $ref (20985:9)❌ 
  │ ├─┬instructions
  │ │ └──[🔀] $ref (10174:9)❌ 
  │ ├─┬user
  │ │ └──[🔀] $ref (15394:9)❌ 
  │ ├─┬presence_penalty
  │ │ ├──[+] items (19613:13)❌ 
  │ │ ├──[🔀] type (19635:17)❌ 
  │ │ ├──[-] format (19062:29)❌ 
  │ │ ├──[+] description (19611:24)
  │ │ └──[-] nullable (19063:31)❌ 
  │ ├─┬route
  │ │ └──[🔀] $ref (19071:9)❌ 
  │ ├─┬temperature
  │ │ ├──[🔀] type (19682:17)❌ 
  │ │ ├──[-] format (19109:29)❌ 
  │ │ ├──[+] default (19681:20)❌ 
  │ │ └──[-] nullable (19110:31)❌ 
  │ ├─┬prompt_cache_key
  │ │ └──[🔀] $ref (20238:9)❌ 
  │ ├─┬prompt
  │ │ └──[🔀] $ref (19641:11)❌ 
  │ ├─┬model
  │ │ ├──[+] items (19599:13)❌ 
  │ │ ├──[🔀] type (19600:17)❌ 
  │ │ ├──[+] description (19594:24)
  │ │ └──[+] example (19596:13)
  │ ├─┬input
  │ │ └──[🔀] $ref (19576:11)❌ 
  │ ├─┬truncation
  │ │ └──[🔀] $ref (21108:9)❌ 
  │ └─┬top_p
  │   ├──[🔀] type (19746:17)❌ 
  │   └──[-] format (19173:29)❌ 
  ├─┬ObservabilityArizeDestination
  │ └─┬config
  │   └─┬modelId
  │     └──[+] description (13152:28)
  ├─┬MessagesErrorDetail
  │ ├──[🔀] example (11479:9)
  │ ├──[+] properties (11483:9)
  │ └─┬message
  │   └──[🔀] $ref (2207:20)❌ 
  ├─┬Model
  │ ├──[🔀] example (12606:9)
  │ ├──[+] properties (12702:9)
  │ ├─┬supported_voices
  │ │ ├──[🔀] description (12705:24)
  │ │ ├──[-] nullable (12226:31)❌ 
  │ │ ├──[-] example (12223:30)
  │ │ └─┬Schema
  │ │   └──[🔀] $ref (17207:9)❌ 
  │ ├─┬supported_parameters
  │ │ └──[🔀] $ref (12869:20)❌ 
  │ └─┬top_provider
  │   └──[🔀] $ref (12710:11)❌ 
  ├─┬StreamEvents
  │ ├──[+] oneOf (6971:7)
  │ └──Discriminator
  ├─┬MessagesStartEvent
  │ └─┬message
  │   └─┬provider
  │     ├──[+] enum (12469:19)
  │     ├──[+] enum (12426:19)
  │     ├──[+] enum (12433:19)
  │     └──[+] enum (12460:19)
  ├─┬ChatStreamChunk
  │ └─┬error
  │   ├──[🔀] example (5106:13)
  │   └──[+] properties (5120:13)
  ├─┬AdvisorReasoning
  │ └─┬effort
  │   └──[+] enum (178:15)
  ├─┬ProviderOptions
  │ ├──[+] properties (18044:9)
  │ ├──[+] properties (18068:9)
  │ ├──[+] properties (18248:9)
  │ └──[+] properties (18296:9)
  ├─┬ReasoningEffort
  │ └──[+] enum (19201:11)
  ├─┬OpenResponsesResult
  │ └─┬ALLOF
  │   ├──[+] properties (15570:13)
  │   ├─┬text
  │   │ └──[🔀] $ref (15579:15)❌ 
  │   ├─┬service_tier
  │   │ ├──[+] items (15576:17)❌ 
  │   │ ├──[🔀] type (15577:21)❌ 
  │   │ └──[-] nullable (15051:35)❌ 
  │   ├─┬openrouter_metadata
  │   │ └──[🔀] $ref (2207:20)❌ 
  │   ├─┬output
  │   │ └──[🔀] $ref (15638:9)❌ 
  │   └─┬usage
  │     └──[🔀] $ref (20985:9)❌ 
  ├─┬SubagentReasoning
  │ └─┬effort
  │   └──[+] enum (20658:15)
  └─┬BYOKProviderSlug
    ├──[+] enum (4015:11)
    ├──[+] enum (4049:11)
    ├──[+] enum (4057:11)
    └──[+] enum (4018:11)
Document Element Total Changes Breaking Changes
paths 35 12
tags 3 0
components 192 98

PYTHON CHANGELOG

No relevant generator changes

Based on Speakeasy CLI 1.680.0

Last updated by Speakeasy workflow

@github-actions github-actions Bot added the patch Patch version bump label Jun 24, 2026

@perry-the-pr-reviewer perry-the-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perry's Review

Speakeasy SDK regeneration (0.10.0 → 0.10.1) consolidating the two legacy benchmark endpoints into a single unified benchmarks.get_benchmarks(), adding images and classifications sub-SDKs, and renaming a large swath of public component types.

Verdict: 🔁 Needs changes

Details

Risk: 🟡 Medium — generated client SDK; failure is reversible (re-generate / re-publish), but one confirmed silent response-parsing bug + a public-API break shipped under a patch bump.

CI: ⏳ no checks reported yet on bb204dc (head is the empty commit to trigger [run-tests] workflow; combined status pending). Not a verdict gate.

Findings (see inline comments):

  • 🔴 src/openrouter/components/anthropicusageiteration.py:39 — net-new AnthropicUsageIteration is a plain (undiscriminated) Union; a normal {"type":"message", …} payload without the optional model field deserializes as AnthropicUnknownUsageIteration, not AnthropicMessageUsageIteration (empirically confirmed with pydantic 2.13). Root cause is upstream: the spec's AnthropicUsageIteration anyOf has no discriminator.
  • 🟡 pyproject.toml:3 — breaking public-API removals/renames shipped under a patch bump (0.10.0 → 0.10.1): the get_benchmarks_artificial_analysis() / get_benchmarks_design_arena() methods on the datasets SDK are removed; ~38 public exports removed/renamed (BenchmarksAA*/BenchmarksDA*Unified*, top-level Error, CompletionTokensDetails, PromptTokensDetails, Quality, Resolution, …). Carry-forward of the same concern raised on #352.
  • 🟡 src/openrouter/components/capabilitydescriptor.py:22 — discriminated unions (CapabilityDescriptor, also UnifiedBenchmarksResponseData) have no catch-all variant; an unknown type/source raises ValidationError. The spec's x-speakeasy-unknown-values: allow is misplaced inside the discriminator mapping block (.speakeasy/out.openapi.yaml:4073), so the intended fallback never generates.

Codex (openai/gpt-5.5): 2 findings surfaced — the AnthropicUsageIteration union-resolution blocker (independently confirmed by me) and the misplaced x-speakeasy-unknown-values discriminator-mapping suggestion. Both folded into the inline findings above.

Research: Speakeasy SDK versioning — Speakeasy bumps off info.version + document checksum, NOT schema-content diffing, so removed/renamed types register only as a checksum→patch bump unless info.version is bumped or a major/minor label is applied; pre-1.0.0 SDKs additionally auto-downgrade major→minor. Pydantic v2 unions — smart-mode union resolution scores by field-count then exactness and is explicitly not order-guaranteed; for reliable variant + fallback selection a Discriminator (or left_to_right with the catch-all last) is required. That is exactly what the anyOf is missing.

Security: no concerns — secret scan clean; no auth/key-handling/streaming-validation changes in the diff. The new image and classification endpoints are additive request/response models only.

Test coverage: none added — this repo ships generated code with no SDK-level unit tests; the union-resolution bug in particular would be caught by a single round-trip test over a type:"message" usage iteration without model.

Unresolved threads: none (first review).

Review metadata

Scope: first review (full)
Review: tier=large · model=claude-opus-latest · score=109.9

"AnthropicUsageIteration",
Union[
AnthropicCompactionUsageIteration,
AnthropicUnknownUsageIteration,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocker][codex] AnthropicUsageIteration is an undiscriminated Union — a normal type:"message" usage iteration without the optional model field deserializes as AnthropicUnknownUsageIteration, silently losing the typed variant.

Details

Why: This is a plain Union[Compaction, Unknown, Message, AdvisorMessage] with no Discriminator. AnthropicUnknownUsageIteration.type is str (accepts anything) while AnthropicMessageUsageIteration.type is Literal["message"]. Under pydantic v2 smart-mode, when a minimal {"type":"message","input_tokens":10,"output_tokens":5} payload is validated, the Unknown and Message variants set the same number of fields (the model field is optional), so the field-count metric ties and the broad str-typed Unknown variant wins. Confirmed empirically against the worktree with pydantic 2.13.4:

message payload (no model) -> AnthropicUnknownUsageIteration   # ❌ wrong
message payload (with model) -> AnthropicMessageUsageIteration # ✅
compaction payload -> AnthropicCompactionUsageIteration        # ✅

This type is reachable: AnthropicUsageIteration is embedded in ImageGenerationUsage.iterations and the anthropic usage block, so any image-gen / anthropic usage response carrying a model-less message iteration parses into the wrong type.

Fix (at the source — these files are DO NOT EDIT generated output): add a discriminator to the AnthropicUsageIteration schema in the source OpenAPI doc (rendered to .speakeasy/out.openapi.yaml:1948). Either give it a real discriminator: { propertyName: type } with a mapping, or — since Unknown is meant as the catch-all — make the generated union order Unknown LAST and use a discriminated-union-with-fallback shape. The generated anyOf currently has no discriminator at all.

Ref: Pydantic v2 — Unions (smart mode is not order-guaranteed; use a Discriminator)

Prompt for agents
The source OpenAPI schema `AnthropicUsageIteration` (rendered to .speakeasy/out.openapi.yaml:1948) is an anyOf with no discriminator, so Speakeasy generates src/openrouter/components/anthropicusageiteration.py as a plain pydantic Union. A {"type":"message"} payload without the optional `model` field mis-resolves to AnthropicUnknownUsageIteration instead of AnthropicMessageUsageIteration. Fix in the source spec (not the generated Python): add a discriminator with propertyName `type` mapping message->AnthropicMessageUsageIteration, compaction->AnthropicCompactionUsageIteration, etc., and keep AnthropicUnknownUsageIteration as the unknown-values fallback. Regenerate the SDK and add a round-trip test asserting a model-less message iteration parses as AnthropicMessageUsageIteration.

Reviewed at bb204dc

Comment thread pyproject.toml
[project]
name = "openrouter"
version = "0.10.0"
version = "0.10.1"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[suggestion] Breaking public-API removals/renames are shipping under a patch bump (0.10.0 → 0.10.1) — downstream installs that pin ~=0.10.0 will silently pull a breaking release.

Details

Why: This regen removes and renames a large public surface, not just additive changes:

  • datasets.get_benchmarks_artificial_analysis() and datasets.get_benchmarks_design_arena() (+ their _async variants) are removed, replaced by benchmarks.get_benchmarks(). Endpoint paths moved from /datasets/benchmarks/* to /benchmarks.
  • ~38 public exports removed/renamed in components/__init__.py: BenchmarksAA*/BenchmarksDA*Unified*, plus top-level Error, CompletionTokensDetails, PromptTokensDetails, Metadata, Options, Quality, Resolution, etc.

Any consumer importing those names or calling the old methods breaks on upgrade. Per SemVer this warrants a minor bump (the SDK is pre-1.0.0, where Speakeasy auto-downgrades a major to minor — so the correct floor here is 0.11.0, not 0.10.1). This is the same concern raised on #352.

Root cause: Speakeasy derives the bump from info.version + a document checksum, not by diffing schema content — so a breaking spec change with an unchanged info.version only triggers a checksum→patch bump. The fix is to bump info.version in the source spec (or apply a minor label / SPEAKEASY_BUMP_OVERRIDE=minor) so the SDK lands as 0.11.0.

Ref: Speakeasy — SDK versioning · Handling breaking changes

Prompt for agents
This Speakeasy regen removes public methods (datasets.get_benchmarks_artificial_analysis/design_arena) and renames ~38 public component exports, but bumps only the patch version (0.10.0 -> 0.10.1). Bump to a minor instead (0.11.0): set info.version in the source OpenAPI spec to a new minor, or apply the `minor` PR label / SPEAKEASY_BUMP_OVERRIDE=minor before regeneration, so downstream `~=0.10.0` pins are not silently broken. This is the second regen (after #352) to ship breaking public-API changes under a patch.

Reviewed at bb204dc

r"""A typed descriptor for one supported request parameter."""


CapabilityDescriptor = Annotated[

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[suggestion][codex] Discriminated unions have no catch-all variant — an unknown type (here) or source (UnifiedBenchmarksResponseData) raises ValidationError instead of degrading gracefully.

Details

Why: CapabilityDescriptor is a Discriminator-tagged union over exactly enum/range/boolean. get_discriminator() (src/openrouter/utils/annotations.py:79) raises ValueError when the discriminator value isn't one of the tags, so a future capability type the server adds will hard-fail client-side parsing. Confirmed against the worktree:

CapabilityDescriptor unknown type        -> ValidationError
UnifiedBenchmarksResponseData unknown src -> ValidationError

The spec intended a fallback — .speakeasy/out.openapi.yaml:4073 has x-speakeasy-unknown-values: allow, but it is nested inside the discriminator.mapping block, so Speakeasy reads it as a bogus discriminator entry ("x-speakeasy-unknown-values" -> "allow") rather than an unknown-values directive on the schema. The fallback therefore never generates.

Fix (source spec): move x-speakeasy-unknown-values: allow out of discriminator.mapping and onto the CapabilityDescriptor schema itself (sibling of oneOf/discriminator), then regenerate. Apply the same check to UnifiedBenchmarksResponseData / the benchmark item unions.

Ref: Speakeasy — unknown union members / x-speakeasy-unknown-values

Prompt for agents
In the source OpenAPI spec, CapabilityDescriptor (rendered .speakeasy/out.openapi.yaml:4067) places `x-speakeasy-unknown-values: allow` inside discriminator.mapping, which makes it a bogus discriminator key instead of an unknown-values fallback directive. Move that extension to be a sibling of `oneOf`/`discriminator` on the CapabilityDescriptor schema. Audit UnifiedBenchmarksResponseData and the benchmark item unions for the same misplacement. Regenerate the SDK; verify an unknown capability `type` / benchmark `source` no longer raises pydantic ValidationError.

Reviewed at bb204dc

@github-actions github-actions Bot force-pushed the speakeasy-sdk-regen-1782262991 branch from bb204dc to ae0a378 Compare June 24, 2026 02:56
@perry-the-pr-reviewer perry-the-pr-reviewer Bot dismissed their stale review June 24, 2026 03:07

Superseded by updated Perry review

@perry-the-pr-reviewer perry-the-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perry's Review

Speakeasy SDK regen 0.10.1 — adds the new image-generation/benchmarks/classifications surface, removes the old datasets benchmark methods, and (since my last pass) adds the Sakana AI provider to the provider enums and per-provider option maps.

Verdict: 🔁 Needs changes

Details

Scope: incremental re-review. The only net-new change since my prior review (at bb204dc) is the addition of one provider (Sakana AI) across the provider-slug enum, display-name enums, and the image/video/byok option maps, plus the regenerated lockfiles and spec. I verified that addition is internally consistent at all seven sites (slug, two display-name enums, three option dicts with the sakana-ai alias, and the byok provider list) — no findings on the new code.

Why this is still "Needs changes": all three findings from my previous review remain open and unaddressed on this head, and the headline one is a correctness blocker I re-confirmed empirically at this SHA (pydantic 2.13.4):

  • 🔴 blocker (carry-forward): the AnthropicUsageIteration union is an undiscriminated pydantic Union, so a model-less message usage iteration silently deserializes into the unknown/catch-all variant instead of the message variant. Re-reproduced against the worktree at this head — a minimal message payload without the optional model field resolves to the wrong type. See the existing open thread on the generated component for the full repro + the source-spec fix (add a discriminator on the anyOf rendered in the spec).
  • 🟡 suggestion (carry-forward): breaking public-API removals/renames are shipping under a patch bump (0.10.0 → 0.10.1). Confirmed against Speakeasy's versioning docs: for a pre-1.0.0 SDK a breaking change should be a minor (0.11.0), and the patch bump happens only because the source spec's info.version is unchanged. Downstream pins of the compatible form will silently pull a breaking release. See the existing open thread.
  • 🟡 suggestion (carry-forward): the CapabilityDescriptor discriminated union has no catch-all variant — an unknown discriminator value raises ValidationError client-side. The source spec intended a fallback but the x-speakeasy-unknown-values directive is misplaced inside the discriminator mapping. See the existing open thread.

These three threads are still unresolved, so I'm holding the prior Needs changes verdict rather than re-posting duplicate review threads on code I already flagged.

CI: pending — the head commit is an empty "trigger run-tests" commit and no checks have reported yet. Not a verdict gate (branch protection handles required checks).

Codex (second opinion): corroborated the version-bump finding and independently flagged the dropped legacy exports (Options/Resolution/AspectRatio) — both already covered by the open breaking-change thread. No net-new findings.

Analysis lanes: 75 candidate findings, all referencing nonexistent paths (hallucinated module layout) — 0 survived source verification.

Research: Speakeasy SDK versioning docs (pre-1.0.0 breaking → minor, not patch; bump derived from info.version + checksum) and pydantic v2 union resolution (smart-mode is not order-guaranteed; a Discriminator is required) — both reconfirm the carry-forward findings.

Security: no concerns. The only new surface is an additive provider enum value + optional option dict; no credential handling, auth, or streaming-path change.

Test coverage: generated SDK — no hand-written tests in scope.

Unresolved threads: 3 — all mine, all carry-forward (see above), none re-posted this pass.

Scope: incremental — net-new since prior review is the Sakana AI provider addition only
Review: tier=large · model=claude-opus-latest · score=110.2

@github-actions github-actions Bot force-pushed the speakeasy-sdk-regen-1782262991 branch from e9155a4 to a6a9d48 Compare June 24, 2026 17:17
@perry-the-pr-reviewer perry-the-pr-reviewer Bot dismissed their stale review June 24, 2026 17:26

Superseded by updated Perry review

perry-the-pr-reviewer[bot]

This comment was marked as outdated.

@github-actions github-actions Bot force-pushed the speakeasy-sdk-regen-1782262991 branch from 3863960 to 60cbeab Compare June 24, 2026 21:01
perry-the-pr-reviewer[bot]

This comment was marked as outdated.

@github-actions github-actions Bot force-pushed the speakeasy-sdk-regen-1782262991 branch from 2e52e15 to 049b807 Compare June 24, 2026 22:36
perry-the-pr-reviewer[bot]

This comment was marked as outdated.

* `open_router.beta.responses.send()`: 
  *  `request` **Changed**
  *  `response` **Changed** **Breaking** ⚠️
* `open_router.tts.create_speech()`: 
  *  `request.provider.options` **Changed**
* `open_router.chat.send()`:  `response` **Changed**
* `open_router.images.list_models()`: **Added**
* `open_router.images.list_model_endpoints()`: **Added**
* `open_router.datasets.get_benchmarks_artificial_analysis()`: **Deleted** **Breaking** ⚠️
* `open_router.datasets.get_benchmarks_design_arena()`: **Deleted** **Breaking** ⚠️
* `open_router.classifications.get_task_classifications()`: **Added**
* `open_router.benchmarks.get_benchmarks()`: **Added**
* `open_router.images.generate()`: **Added**
* `open_router.stt.create_transcription()`: 
  *  `request.provider.options` **Changed**
* `open_router.byok.list()`:  `request.provider` **Changed**
* `open_router.embeddings.generate()`:  `response.usage` **Changed**
* `open_router.embeddings.list_models()`:  `response.data.[].reasoning` **Added**
* `open_router.models.get()`:  `response.data.reasoning` **Added**
* `open_router.models.list()`: 
  *  `request.sort` **Changed**
  *  `response.data.[].reasoning` **Added**
* `open_router.models.list_for_user()`:  `response.data.[].reasoning` **Added**
* `open_router.presets.create_presets_responses()`:  `request` **Changed**
* `open_router.video_generation.generate()`: 
  *  `request.provider.options` **Changed**
@github-actions github-actions Bot force-pushed the speakeasy-sdk-regen-1782262991 branch from d45da4e to d7628fa Compare June 25, 2026 00:54
@github-actions github-actions Bot changed the title chore: 🐝 Update SDK - Generate (spec change merged) 0.10.1 chore: 🐝 Update SDK - Generate 0.10.1 Jun 25, 2026

@perry-the-pr-reviewer perry-the-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perry's Review

Speakeasy SDK regen to 0.10.1 — adds image-generation, benchmarks, and task-classification surfaces; renames the benchmark components/operations; and introduces the Anthropic usage-iteration union.

Verdict: 💬 Comments / questions

Details

Re-review scope: the only change since my last review (d45da4e9af8656) is generator-metadata churn — a regenerated gen-lock generation id and a RELEASES.md timestamp. The substantive SDK output is byte-identical to what I already reviewed, so I have not regenerated nits on unchanged code.

Risk: 🟡 Medium

CI: all passing ✅

Findings: no net-new findings on this push. My three prior findings remain open and unresolved as existing review threads (not re-posted here to avoid duplication):

  • 🔴 blocker — the Anthropic usage-iteration union is undiscriminated; a model-less message iteration mis-deserializes into the unknown variant. Re-confirmed empirically against the worktree on pydantic 2.13.4 (a minimal message payload resolves to the unknown variant, not the message variant).
  • 🟡 suggestion — breaking public-API removals and renames are shipping under a patch bump (0.10.0 to 0.10.1); per SemVer this warrants a minor (0.11.0). Speakeasy derives the bump from info.version plus a document checksum rather than a content diff, so the breaking surface is invisible to its versioner.
  • 🟡 suggestion — the discriminated unions (capability descriptor, unified benchmarks response) have no catch-all variant, so an unknown discriminator value raises a validation error instead of degrading gracefully; the intended unknown-values directive is misplaced inside the discriminator mapping in the source spec.

Codex (heavy second opinion): independently re-surfaced the union-ordering blocker (same root cause as my prior blocker) — no additional net-new findings.

Research: Pydantic v2 union docs confirm smart-mode resolves by field-set count then exactness (not declaration order, and explicitly subject to change) — a discriminated union keyed on the type field is the recommended fix. Speakeasy versioning docs confirm the bump is info.version plus checksum derived and that pre-1.0.0 majors auto-downgrade to minor, so the bump-override env var (or a minor label) is the correct remedy.

Security: no concerns — generated client models only; no secrets in the diff, no auth, streaming, or logging logic touched.

Test coverage: the regen adds no round-trip tests for the new union; a test asserting a model-less message iteration parses as the message variant would catch the blocker.

Unresolved threads: 3 open (the blocker plus 2 suggestions above), all carried forward from prior pushes.

Scope: incremental — only generator-metadata lines changed since prior review
Review: tier=large · model=claude-opus-latest · score=112.0

@christineschen

Copy link
Copy Markdown
Collaborator

Closing stale Speakeasy regen PR. The auto-merge + PR-validation workflows (#364, #365) have landed on main; re-running Generate to produce a fresh, validated 0.10.1 PR that will auto-merge.

@christineschen christineschen deleted the speakeasy-sdk-regen-1782262991 branch June 25, 2026 21:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

patch Patch version bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants